summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-06-25 13:49:53 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-06-25 13:49:53 (GMT)
commitdb8f05e257019694f5e8076845626008f2adc3dd (patch)
tree05d3959403cf15ac5f702091439e028af01f343b /src
parent8aafaa65a1d16f8b982279f5aceedf1e281ddb5a (diff)
parent796a5a2c7d8c91a46ac761dde18b7da2ec6c177b (diff)
downloadQt-db8f05e257019694f5e8076845626008f2adc3dd.zip
Qt-db8f05e257019694f5e8076845626008f2adc3dd.tar.gz
Qt-db8f05e257019694f5e8076845626008f2adc3dd.tar.bz2
Merge commit 'qt/master-stable' into 4.6-stable
Bring Qt 4.6 into the Qt-S60 repo. Conflicts: configure.exe mkspecs/features/qttest_p4.prf qmake/generators/makefile.cpp src/corelib/io/qdir.cpp src/corelib/io/qprocess.h src/corelib/kernel/qcoreevent.h src/corelib/kernel/qobject.cpp src/corelib/kernel/qsharedmemory_unix.cpp src/corelib/thread/qthread_p.h src/corelib/tools/qvector.h src/gui/dialogs/qdialog.cpp src/gui/dialogs/qfiledialog.cpp src/gui/dialogs/qfiledialog_p.h src/gui/dialogs/qmessagebox.cpp src/gui/graphicsview/qgraphicsitem.cpp src/gui/graphicsview/qgraphicsview.cpp src/gui/image/qpixmapcache.cpp src/gui/kernel/qapplication.cpp src/gui/kernel/qapplication_p.h src/gui/kernel/qwidget.cpp src/gui/kernel/qwidget_p.h src/gui/painting/qdrawhelper.cpp src/gui/painting/qpaintengine_raster.cpp src/gui/text/qfontengine_qpf.cpp src/gui/widgets/qmenubar.cpp src/network/socket/qlocalserver.cpp src/testlib/qtestcase.cpp src/testlib/testlib.pro tests/auto/qimagereader/tst_qimagereader.cpp tests/auto/qitemdelegate/tst_qitemdelegate.cpp tests/auto/qnetworkreply/tst_qnetworkreply.cpp tests/auto/qpixmap/qpixmap.pro
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp2
-rw-r--r--src/3rdparty/clucene/src/CLucene/util/Misc.cpp9
-rw-r--r--src/3rdparty/easing/easing.cpp670
-rw-r--r--src/3rdparty/easing/legal.qdoc35
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.h40
-rw-r--r--src/3rdparty/phonon/qt7/mediaobject.mm306
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.h8
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.mm41
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.h27
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.mm265
-rw-r--r--src/3rdparty/phonon/qt7/videoframe.mm24
-rw-r--r--src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h2
-rw-r--r--src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp6
-rw-r--r--src/3rdparty/webkit/WebCore/dom/XMLTokenizerQt.cpp4
-rw-r--r--src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp6
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp8
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp22
-rw-r--r--src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc3
-rw-r--r--src/activeqt/container/qaxbase.cpp86
-rw-r--r--src/activeqt/container/qaxdump.cpp38
-rw-r--r--src/activeqt/container/qaxscript.cpp4
-rw-r--r--src/activeqt/container/qaxwidget.cpp12
-rw-r--r--src/activeqt/control/qaxserver.cpp183
-rw-r--r--src/activeqt/control/qaxserverbase.cpp10
-rw-r--r--src/activeqt/control/qaxservermain.cpp2
-rw-r--r--src/activeqt/shared/qaxtypes.cpp2
-rw-r--r--src/corelib/animation/animation.pri25
-rw-r--r--src/corelib/animation/qabstractanimation.cpp733
-rw-r--r--src/corelib/animation/qabstractanimation.h137
-rw-r--r--src/corelib/animation/qabstractanimation_p.h150
-rw-r--r--src/corelib/animation/qanimationgroup.cpp309
-rw-r--r--src/corelib/animation/qanimationgroup.h88
-rw-r--r--src/corelib/animation/qanimationgroup_p.h79
-rw-r--r--src/corelib/animation/qparallelanimationgroup.cpp323
-rw-r--r--src/corelib/animation/qparallelanimationgroup.h86
-rw-r--r--src/corelib/animation/qparallelanimationgroup_p.h85
-rw-r--r--src/corelib/animation/qpauseanimation.cpp154
-rw-r--r--src/corelib/animation/qpauseanimation.h84
-rw-r--r--src/corelib/animation/qpropertyanimation.cpp318
-rw-r--r--src/corelib/animation/qpropertyanimation.h90
-rw-r--r--src/corelib/animation/qpropertyanimation_p.h89
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.cpp592
-rw-r--r--src/corelib/animation/qsequentialanimationgroup.h96
-rw-r--r--src/corelib/animation/qsequentialanimationgroup_p.h111
-rw-r--r--src/corelib/animation/qvariantanimation.cpp673
-rw-r--r--src/corelib/animation/qvariantanimation.h130
-rw-r--r--src/corelib/animation/qvariantanimation_p.h (renamed from src/gui/painting/qpaintengine_d3d_p.h)97
-rw-r--r--src/corelib/codecs/qisciicodec.cpp2
-rw-r--r--src/corelib/codecs/qtextcodec.cpp134
-rw-r--r--src/corelib/codecs/qtextcodec.h3
-rw-r--r--src/corelib/codecs/qtsciicodec_p.h2
-rw-r--r--src/corelib/codecs/qutfcodec.cpp15
-rw-r--r--src/corelib/concurrent/qfuturewatcher_p.h4
-rw-r--r--src/corelib/corelib.pro2
-rw-r--r--src/corelib/global/qfeatures.h10
-rw-r--r--src/corelib/global/qfeatures.txt22
-rw-r--r--src/corelib/global/qglobal.cpp11
-rw-r--r--src/corelib/global/qglobal.h47
-rw-r--r--src/corelib/global/qlibraryinfo.cpp16
-rw-r--r--src/corelib/global/qnamespace.h11
-rw-r--r--src/corelib/global/qt_windows.h3
-rw-r--r--src/corelib/io/io.pri2
-rw-r--r--src/corelib/io/qdatastream.h10
-rw-r--r--src/corelib/io/qdebug.h45
-rw-r--r--src/corelib/io/qdir.cpp95
-rw-r--r--src/corelib/io/qfile.cpp8
-rw-r--r--src/corelib/io/qfileinfo.cpp76
-rw-r--r--src/corelib/io/qfileinfo_p.h55
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp2
-rw-r--r--src/corelib/io/qfilesystemwatcher_dnotify.cpp2
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp8
-rw-r--r--src/corelib/io/qfsfileengine_win.cpp22
-rw-r--r--src/corelib/io/qiodevice.cpp6
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice.cpp544
-rw-r--r--src/corelib/io/qnoncontiguousbytedevice_p.h184
-rw-r--r--src/corelib/io/qprocess.cpp109
-rw-r--r--src/corelib/io/qprocess.h5
-rw-r--r--src/corelib/io/qprocess_p.h2
-rw-r--r--src/corelib/io/qprocess_unix.cpp73
-rw-r--r--src/corelib/io/qprocess_win.cpp95
-rw-r--r--src/corelib/io/qresource.cpp86
-rw-r--r--src/corelib/io/qsettings_p.h2
-rw-r--r--src/corelib/io/qsettings_win.cpp2
-rw-r--r--src/corelib/io/qtemporaryfile.cpp2
-rw-r--r--src/corelib/io/qtextstream.cpp22
-rw-r--r--src/corelib/io/qurl.cpp8
-rw-r--r--src/corelib/io/qurl.h2
-rw-r--r--src/corelib/kernel/kernel.pri11
-rw-r--r--src/corelib/kernel/qabstractitemmodel.cpp43
-rw-r--r--src/corelib/kernel/qabstractitemmodel_p.h3
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp33
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp41
-rw-r--r--src/corelib/kernel/qcoreevent.cpp2
-rw-r--r--src/corelib/kernel/qcoreevent.h11
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_unix_p.h4
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp10
-rw-r--r--src/corelib/kernel/qfunctions_wince.cpp5
-rw-r--r--src/corelib/kernel/qfunctions_wince.h5
-rw-r--r--src/corelib/kernel/qmetaobject.cpp5
-rw-r--r--src/corelib/kernel/qmetatype.cpp5
-rw-r--r--src/corelib/kernel/qmetatype.h11
-rw-r--r--src/corelib/kernel/qobject.cpp384
-rw-r--r--src/corelib/kernel/qobject.h3
-rw-r--r--src/corelib/kernel/qobject_p.h15
-rw-r--r--src/corelib/kernel/qobjectdefs.h2
-rw-r--r--src/corelib/kernel/qtimer.cpp6
-rw-r--r--src/corelib/kernel/qtranslator.cpp4
-rw-r--r--src/corelib/kernel/qvariant.cpp181
-rw-r--r--src/corelib/kernel/qvariant.h15
-rw-r--r--src/corelib/kernel/qvariant_p.h34
-rw-r--r--src/corelib/plugin/qfactoryloader.cpp2
-rw-r--r--src/corelib/plugin/qlibrary_unix.cpp2
-rw-r--r--src/corelib/plugin/qplugin.h21
-rw-r--r--src/corelib/plugin/quuid.cpp2
-rw-r--r--src/corelib/statemachine/qabstractstate.cpp206
-rw-r--r--src/corelib/statemachine/qabstractstate.h (renamed from src/gui/embedded/qkbdpc101_qws.h)67
-rw-r--r--src/corelib/statemachine/qabstractstate_p.h83
-rw-r--r--src/corelib/statemachine/qabstracttransition.cpp345
-rw-r--r--src/corelib/statemachine/qabstracttransition.h115
-rw-r--r--src/corelib/statemachine/qabstracttransition_p.h91
-rw-r--r--src/corelib/statemachine/qeventtransition.cpp290
-rw-r--r--src/corelib/statemachine/qeventtransition.h100
-rw-r--r--src/corelib/statemachine/qeventtransition_p.h79
-rw-r--r--src/corelib/statemachine/qfinalstate.cpp139
-rw-r--r--src/corelib/statemachine/qfinalstate.h (renamed from src/plugins/kbddrivers/linuxis/linuxiskbdhandler.h)56
-rw-r--r--src/corelib/statemachine/qhistorystate.cpp228
-rw-r--r--src/corelib/statemachine/qhistorystate.h95
-rw-r--r--src/corelib/statemachine/qhistorystate_p.h79
-rw-r--r--src/corelib/statemachine/qsignalevent.h81
-rw-r--r--src/corelib/statemachine/qsignaleventgenerator_p.h78
-rw-r--r--src/corelib/statemachine/qsignaltransition.cpp265
-rw-r--r--src/corelib/statemachine/qsignaltransition.h93
-rw-r--r--src/corelib/statemachine/qsignaltransition_p.h79
-rw-r--r--src/corelib/statemachine/qstate.cpp489
-rw-r--r--src/corelib/statemachine/qstate.h117
-rw-r--r--src/corelib/statemachine/qstate_p.h108
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp2214
-rw-r--r--src/corelib/statemachine/qstatemachine.h170
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h216
-rw-r--r--src/corelib/statemachine/qwrappedevent.h80
-rw-r--r--src/corelib/statemachine/statemachine.pri30
-rw-r--r--src/corelib/thread/qmutexpool.cpp20
-rw-r--r--src/corelib/thread/qmutexpool_p.h7
-rw-r--r--src/corelib/thread/qthread.cpp6
-rw-r--r--src/corelib/thread/qthread_p.h77
-rw-r--r--src/corelib/tools/qbitarray.cpp5
-rw-r--r--src/corelib/tools/qbytearray.cpp7
-rw-r--r--src/corelib/tools/qchar.cpp2
-rw-r--r--src/corelib/tools/qcontiguouscache.cpp432
-rw-r--r--src/corelib/tools/qcontiguouscache.h430
-rw-r--r--src/corelib/tools/qdatetime.cpp8
-rw-r--r--src/corelib/tools/qdumper.cpp1157
-rw-r--r--src/corelib/tools/qeasingcurve.cpp846
-rw-r--r--src/corelib/tools/qeasingcurve.h114
-rw-r--r--src/corelib/tools/qline.cpp4
-rw-r--r--src/corelib/tools/qlocale.cpp30
-rw-r--r--src/corelib/tools/qlocale.h2
-rw-r--r--src/corelib/tools/qlocale_data_p.h10
-rw-r--r--src/corelib/tools/qlocale_p.h40
-rw-r--r--src/corelib/tools/qmap.h2
-rw-r--r--src/corelib/tools/qpoint.cpp15
-rw-r--r--src/corelib/tools/qpoint.h2
-rw-r--r--src/corelib/tools/qregexp.cpp2
-rw-r--r--src/corelib/tools/qringbuffer_p.h48
-rw-r--r--src/corelib/tools/qset.h14
-rw-r--r--src/corelib/tools/qsize.h12
-rw-r--r--src/corelib/tools/qstring.cpp95
-rw-r--r--src/corelib/tools/qstring.h15
-rw-r--r--src/corelib/tools/qstringbuilder.cpp135
-rw-r--r--src/corelib/tools/qstringbuilder.h241
-rw-r--r--src/corelib/tools/qtimeline.cpp114
-rw-r--r--src/corelib/tools/qtimeline.h5
-rw-r--r--src/corelib/tools/qunicodetables_p.h2
-rw-r--r--src/corelib/tools/qvector.h147
-rw-r--r--src/corelib/tools/tools.pri7
-rwxr-xr-xsrc/corelib/xml/make-parser.sh4
-rw-r--r--src/corelib/xml/qxmlstream.cpp9
-rw-r--r--src/corelib/xml/qxmlstream.g4
-rw-r--r--src/corelib/xml/qxmlstream_p.h42
-rw-r--r--src/dbus/qdbus_symbols_p.h2
-rw-r--r--src/dbus/qdbuserror.cpp2
-rw-r--r--src/dbus/qdbusintegrator.cpp6
-rw-r--r--src/dbus/qdbusmetaobject.cpp2
-rw-r--r--src/dbus/qdbusthreaddebug_p.h2
-rw-r--r--src/dbus/qdbusutil.cpp16
-rw-r--r--src/gui/accessible/qaccessible.cpp2
-rw-r--r--src/gui/accessible/qaccessible_win.cpp12
-rw-r--r--src/gui/accessible/qaccessibleobject.cpp14
-rw-r--r--src/gui/accessible/qaccessiblewidget.cpp19
-rw-r--r--src/gui/animation/animation.pri3
-rw-r--r--src/gui/animation/qguivariantanimation.cpp77
-rw-r--r--src/gui/dialogs/qcolordialog.cpp11
-rw-r--r--src/gui/dialogs/qcolordialog_mac.mm38
-rw-r--r--src/gui/dialogs/qdialog.cpp18
-rw-r--r--src/gui/dialogs/qdialog.h4
-rw-r--r--src/gui/dialogs/qdialog_p.h2
-rw-r--r--src/gui/dialogs/qerrormessage.cpp10
-rw-r--r--src/gui/dialogs/qfiledialog.cpp14
-rw-r--r--src/gui/dialogs/qfiledialog_mac.mm19
-rw-r--r--src/gui/dialogs/qfiledialog_p.h5
-rw-r--r--src/gui/dialogs/qfiledialog_win.cpp34
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp4
-rw-r--r--src/gui/dialogs/qfontdialog.cpp4
-rw-r--r--src/gui/dialogs/qinputdialog.cpp5
-rw-r--r--src/gui/dialogs/qmessagebox.cpp64
-rw-r--r--src/gui/dialogs/qmessagebox.h4
-rw-r--r--src/gui/dialogs/qpagesetupdialog_win.cpp2
-rw-r--r--src/gui/dialogs/qprintdialog_unix.cpp8
-rw-r--r--src/gui/dialogs/qprintdialog_win.cpp2
-rw-r--r--src/gui/dialogs/qprintpreviewdialog.cpp148
-rw-r--r--src/gui/dialogs/qprogressdialog.cpp2
-rw-r--r--src/gui/dialogs/qwizard.cpp16
-rw-r--r--src/gui/dialogs/qwizard_win.cpp4
-rw-r--r--src/gui/embedded/embedded.pri19
-rw-r--r--src/gui/embedded/qkbd_defaultmap_qws_p.h796
-rw-r--r--src/gui/embedded/qkbd_qws.cpp481
-rw-r--r--src/gui/embedded/qkbd_qws.h22
-rw-r--r--src/gui/embedded/qkbd_qws_p.h130
-rw-r--r--src/gui/embedded/qkbddriverfactory_qws.cpp14
-rw-r--r--src/gui/embedded/qkbdlinuxinput_qws.cpp241
-rw-r--r--src/gui/embedded/qkbdlinuxinput_qws.h (renamed from src/gui/embedded/qkbdusb_qws.h)24
-rw-r--r--src/gui/embedded/qkbdpc101_qws.cpp485
-rw-r--r--src/gui/embedded/qkbdsl5000_qws.cpp25
-rw-r--r--src/gui/embedded/qkbdsl5000_qws.h19
-rw-r--r--src/gui/embedded/qkbdtty_qws.cpp306
-rw-r--r--src/gui/embedded/qkbdtty_qws.h8
-rw-r--r--src/gui/embedded/qkbdum_qws.cpp9
-rw-r--r--src/gui/embedded/qkbdusb_qws.cpp401
-rw-r--r--src/gui/embedded/qmouse_qws.cpp4
-rw-r--r--src/gui/embedded/qscreen_qws.cpp13
-rw-r--r--src/gui/embedded/qscreenmulti_qws.cpp4
-rw-r--r--src/gui/embedded/qscreenproxy_qws.cpp1
-rw-r--r--src/gui/embedded/qscreentransformed_qws.cpp6
-rw-r--r--src/gui/embedded/qscreenvfb_qws.cpp4
-rw-r--r--src/gui/embedded/qtransportauth_qws.cpp4
-rw-r--r--src/gui/embedded/qunixsocket.cpp32
-rw-r--r--src/gui/embedded/qunixsocketserver.cpp8
-rw-r--r--src/gui/embedded/qwindowsystem_qws.cpp4
-rw-r--r--src/gui/embedded/qwscommand_qws.cpp9
-rw-r--r--src/gui/embedded/qwssignalhandler.cpp6
-rw-r--r--src/gui/graphicsview/graphicsview.pri77
-rw-r--r--src/gui/graphicsview/qgraphicsgridlayout.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp2036
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h89
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h202
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem.cpp134
-rw-r--r--src/gui/graphicsview/qgraphicslayoutitem_p.h8
-rw-r--r--src/gui/graphicsview/qgraphicslinearlayout.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.cpp11
-rw-r--r--src/gui/graphicsview/qgraphicsproxywidget.h2
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp1133
-rw-r--r--src/gui/graphicsview/qgraphicsscene.h5
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h49
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp579
-rw-r--r--src/gui/graphicsview/qgraphicsview.h7
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h28
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp185
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h15
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp260
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h70
-rw-r--r--src/gui/graphicsview/qgridlayoutengine.cpp24
-rw-r--r--src/gui/gui.pro3
-rw-r--r--src/gui/image/image.pri1
-rw-r--r--src/gui/image/qicon.cpp2
-rw-r--r--src/gui/image/qimage.cpp25
-rw-r--r--src/gui/image/qnativeimage.cpp6
-rw-r--r--src/gui/image/qnativeimage_p.h2
-rw-r--r--src/gui/image/qpicture.cpp2
-rw-r--r--src/gui/image/qpicture.h2
-rw-r--r--src/gui/image/qpicture_p.h2
-rw-r--r--src/gui/image/qpixmap.cpp68
-rw-r--r--src/gui/image/qpixmap.h10
-rw-r--r--src/gui/image/qpixmap_mac.cpp8
-rw-r--r--src/gui/image/qpixmap_mac_p.h1
-rw-r--r--src/gui/image/qpixmap_raster.cpp52
-rw-r--r--src/gui/image/qpixmap_raster_p.h8
-rw-r--r--src/gui/image/qpixmap_win.cpp12
-rw-r--r--src/gui/image/qpixmap_x11.cpp10
-rw-r--r--src/gui/image/qpixmap_x11_p.h1
-rw-r--r--src/gui/image/qpixmapcache.cpp392
-rw-r--r--src/gui/image/qpixmapcache.h27
-rw-r--r--src/gui/image/qpixmapcache_p.h98
-rw-r--r--src/gui/image/qpixmapdata.cpp8
-rw-r--r--src/gui/image/qpixmapdata_p.h3
-rw-r--r--src/gui/image/qpixmapdatafactory.cpp2
-rw-r--r--src/gui/image/qpixmapdatafactory_p.h2
-rw-r--r--src/gui/image/qpixmapfilter.cpp1
-rw-r--r--src/gui/image/qxpmhandler.cpp6
-rw-r--r--src/gui/inputmethod/qinputcontext.cpp4
-rw-r--r--src/gui/inputmethod/qinputcontext_p.h4
-rw-r--r--src/gui/inputmethod/qmacinputcontext_mac.cpp20
-rw-r--r--src/gui/inputmethod/qmacinputcontext_p.h5
-rw-r--r--src/gui/inputmethod/qwininputcontext_p.h1
-rw-r--r--src/gui/inputmethod/qwininputcontext_win.cpp25
-rw-r--r--src/gui/inputmethod/qwsinputcontext_p.h1
-rw-r--r--src/gui/inputmethod/qwsinputcontext_qws.cpp11
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp3
-rw-r--r--src/gui/itemviews/qabstractitemview.cpp50
-rw-r--r--src/gui/itemviews/qabstractitemview_p.h2
-rw-r--r--src/gui/itemviews/qcolumnview.cpp40
-rw-r--r--src/gui/itemviews/qdirmodel.cpp11
-rw-r--r--src/gui/itemviews/qfileiconprovider.cpp17
-rw-r--r--src/gui/itemviews/qheaderview.cpp59
-rw-r--r--src/gui/itemviews/qheaderview_p.h9
-rw-r--r--src/gui/itemviews/qitemselectionmodel.cpp2
-rw-r--r--src/gui/itemviews/qlistview.cpp56
-rw-r--r--src/gui/itemviews/qlistview_p.h2
-rw-r--r--src/gui/itemviews/qlistwidget.cpp100
-rw-r--r--src/gui/itemviews/qlistwidget_p.h2
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp58
-rw-r--r--src/gui/itemviews/qstandarditemmodel.cpp42
-rw-r--r--src/gui/itemviews/qtableview.cpp339
-rw-r--r--src/gui/itemviews/qtableview_p.h98
-rw-r--r--src/gui/itemviews/qtablewidget.cpp148
-rw-r--r--src/gui/itemviews/qtablewidget_p.h3
-rw-r--r--src/gui/itemviews/qtreeview.cpp110
-rw-r--r--src/gui/itemviews/qtreewidget.cpp110
-rw-r--r--src/gui/itemviews/qtreewidget_p.h7
-rw-r--r--src/gui/kernel/kernel.pri2
-rw-r--r--src/gui/kernel/qaction.cpp31
-rw-r--r--src/gui/kernel/qapplication.cpp171
-rw-r--r--src/gui/kernel/qapplication.h4
-rw-r--r--src/gui/kernel/qapplication_mac.mm41
-rw-r--r--src/gui/kernel/qapplication_p.h8
-rw-r--r--src/gui/kernel/qapplication_qws.cpp19
-rw-r--r--src/gui/kernel/qapplication_win.cpp264
-rw-r--r--src/gui/kernel/qapplication_x11.cpp225
-rw-r--r--src/gui/kernel/qclipboard.cpp24
-rw-r--r--src/gui/kernel/qclipboard_x11.cpp16
-rw-r--r--src/gui/kernel/qcocoaview_mac.mm14
-rw-r--r--src/gui/kernel/qcocoaview_mac_p.h1
-rw-r--r--src/gui/kernel/qcursor.cpp2
-rw-r--r--src/gui/kernel/qcursor_win.cpp8
-rw-r--r--src/gui/kernel/qdesktopwidget_win.cpp12
-rw-r--r--src/gui/kernel/qdnd.cpp2
-rw-r--r--src/gui/kernel/qdnd_p.h2
-rw-r--r--src/gui/kernel/qdnd_win.cpp2
-rw-r--r--src/gui/kernel/qdnd_x11.cpp24
-rw-r--r--src/gui/kernel/qevent.cpp17
-rw-r--r--src/gui/kernel/qevent_p.h4
-rw-r--r--src/gui/kernel/qformlayout.cpp6
-rw-r--r--src/gui/kernel/qkeymapper.cpp2
-rw-r--r--src/gui/kernel/qkeymapper_mac.cpp32
-rw-r--r--src/gui/kernel/qkeysequence.cpp114
-rw-r--r--src/gui/kernel/qkeysequence.h4
-rw-r--r--src/gui/kernel/qlayout.cpp4
-rw-r--r--src/gui/kernel/qlayoutengine.cpp2
-rw-r--r--src/gui/kernel/qlayoutitem.cpp6
-rw-r--r--src/gui/kernel/qmime_mac.cpp123
-rw-r--r--src/gui/kernel/qmime_win.cpp10
-rw-r--r--src/gui/kernel/qpalette.cpp4
-rw-r--r--src/gui/kernel/qshortcut.cpp1
-rw-r--r--src/gui/kernel/qshortcutmap.cpp16
-rw-r--r--src/gui/kernel/qsizepolicy.h2
-rw-r--r--src/gui/kernel/qsound_qws.cpp2
-rw-r--r--src/gui/kernel/qt_cocoa_helpers_mac.mm79
-rw-r--r--src/gui/kernel/qt_mac_p.h15
-rw-r--r--src/gui/kernel/qt_x11_p.h11
-rw-r--r--src/gui/kernel/qtooltip.cpp21
-rw-r--r--src/gui/kernel/qwidget.cpp325
-rw-r--r--src/gui/kernel/qwidget.h5
-rw-r--r--src/gui/kernel/qwidget_mac.mm67
-rw-r--r--src/gui/kernel/qwidget_p.h542
-rw-r--r--src/gui/kernel/qwidget_qws.cpp17
-rw-r--r--src/gui/kernel/qwidget_win.cpp109
-rw-r--r--src/gui/kernel/qwidget_wince.cpp21
-rw-r--r--src/gui/kernel/qwidget_x11.cpp157
-rw-r--r--src/gui/kernel/qwidgetaction.cpp4
-rw-r--r--src/gui/kernel/qwindowdefs_win.h2
-rw-r--r--src/gui/kernel/qx11embed_x11.cpp19
-rw-r--r--src/gui/mac/images/leopard-unified-toolbar-on.pngbin0 -> 356 bytes
-rw-r--r--src/gui/mac/macresources.qrc (renamed from src/gui/mac/maccursors.qrc)3
-rw-r--r--src/gui/math3d/math3d.pri15
-rw-r--r--src/gui/math3d/qgenericmatrix.cpp251
-rw-r--r--src/gui/math3d/qgenericmatrix.h371
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp1808
-rw-r--r--src/gui/math3d/qmatrix4x4.h998
-rw-r--r--src/gui/math3d/qquaternion.cpp584
-rw-r--r--src/gui/math3d/qquaternion.h337
-rw-r--r--src/gui/math3d/qvector2d.cpp417
-rw-r--r--src/gui/math3d/qvector2d.h256
-rw-r--r--src/gui/math3d/qvector3d.cpp565
-rw-r--r--src/gui/math3d/qvector3d.h284
-rw-r--r--src/gui/math3d/qvector4d.cpp518
-rw-r--r--src/gui/math3d/qvector4d.h289
-rw-r--r--src/gui/painting/painting.pri10
-rw-r--r--src/gui/painting/qbackingstore.cpp4
-rw-r--r--src/gui/painting/qbezier.cpp32
-rw-r--r--src/gui/painting/qblendfunctions.cpp64
-rw-r--r--src/gui/painting/qbrush.cpp6
-rw-r--r--src/gui/painting/qbrush.h2
-rw-r--r--src/gui/painting/qcolor.cpp14
-rw-r--r--src/gui/painting/qcolor_p.cpp2
-rw-r--r--src/gui/painting/qcolormap_win.cpp2
-rw-r--r--src/gui/painting/qdrawhelper.cpp1022
-rw-r--r--src/gui/painting/qdrawhelper_p.h13
-rw-r--r--src/gui/painting/qdrawutil.cpp324
-rw-r--r--src/gui/painting/qdrawutil.h46
-rw-r--r--src/gui/painting/qemulationpaintengine.cpp12
-rw-r--r--src/gui/painting/qfixed_p.h2
-rw-r--r--src/gui/painting/qgraphicssystemfactory_p.h2
-rw-r--r--src/gui/painting/qgraphicssystemplugin_p.h2
-rw-r--r--src/gui/painting/qmatrix.cpp65
-rw-r--r--src/gui/painting/qmatrix.h22
-rw-r--r--src/gui/painting/qpaintengine.cpp4
-rw-r--r--src/gui/painting/qpaintengine_d3d.cpp4576
-rw-r--r--src/gui/painting/qpaintengine_d3d.fx608
-rw-r--r--src/gui/painting/qpaintengine_d3d.qrc5
-rw-r--r--src/gui/painting/qpaintengine_mac.cpp24
-rw-r--r--src/gui/painting/qpaintengine_mac_p.h2
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp285
-rw-r--r--src/gui/painting/qpaintengine_raster_p.h1
-rw-r--r--src/gui/painting/qpaintengine_x11_p.h1
-rw-r--r--src/gui/painting/qpaintengineex.cpp91
-rw-r--r--src/gui/painting/qpaintengineex_p.h34
-rw-r--r--src/gui/painting/qpainter.cpp98
-rw-r--r--src/gui/painting/qpainter.h1
-rw-r--r--src/gui/painting/qpainter_p.h6
-rw-r--r--src/gui/painting/qpainterpath.cpp70
-rw-r--r--src/gui/painting/qpainterpath.h12
-rw-r--r--src/gui/painting/qpainterpath_p.h2
-rw-r--r--src/gui/painting/qpathclipper.cpp36
-rw-r--r--src/gui/painting/qpdf.cpp26
-rw-r--r--src/gui/painting/qpdf_p.h2
-rw-r--r--src/gui/painting/qpen.cpp2
-rw-r--r--src/gui/painting/qpolygon.cpp61
-rw-r--r--src/gui/painting/qpolygon.h13
-rw-r--r--src/gui/painting/qprintengine_pdf.cpp4
-rw-r--r--src/gui/painting/qprintengine_ps.cpp24
-rw-r--r--src/gui/painting/qprinter.cpp17
-rw-r--r--src/gui/painting/qprinterinfo_unix.cpp4
-rw-r--r--src/gui/painting/qregion.cpp6
-rw-r--r--src/gui/painting/qstroker.cpp12
-rw-r--r--src/gui/painting/qstroker_p.h2
-rw-r--r--src/gui/painting/qtessellator.cpp14
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp69
-rw-r--r--src/gui/painting/qtextureglyphcache_p.h5
-rw-r--r--src/gui/painting/qtransform.cpp238
-rw-r--r--src/gui/painting/qtransform.h32
-rw-r--r--src/gui/painting/qvectorpath_p.h4
-rw-r--r--src/gui/painting/qwindowsurface_d3d.cpp169
-rw-r--r--src/gui/painting/qwindowsurface_raster.cpp12
-rw-r--r--src/gui/painting/qwindowsurface_x11.cpp2
-rw-r--r--src/gui/statemachine/qbasickeyeventtransition.cpp208
-rw-r--r--src/gui/statemachine/qbasickeyeventtransition_p.h98
-rw-r--r--src/gui/statemachine/qbasicmouseeventtransition.cpp213
-rw-r--r--src/gui/statemachine/qbasicmouseeventtransition_p.h101
-rw-r--r--src/gui/statemachine/qguistatemachine.cpp564
-rw-r--r--src/gui/statemachine/qkeyeventtransition.cpp191
-rw-r--r--src/gui/statemachine/qkeyeventtransition.h91
-rw-r--r--src/gui/statemachine/qmouseeventtransition.cpp221
-rw-r--r--src/gui/statemachine/qmouseeventtransition.h96
-rw-r--r--src/gui/statemachine/statemachine.pri13
-rw-r--r--src/gui/styles/gtksymbols.cpp230
-rw-r--r--src/gui/styles/qcleanlooksstyle.cpp242
-rw-r--r--src/gui/styles/qcommonstyle.cpp659
-rw-r--r--src/gui/styles/qgtkstyle.cpp124
-rw-r--r--src/gui/styles/qmacstyle_mac.mm235
-rw-r--r--src/gui/styles/qmotifstyle.cpp160
-rw-r--r--src/gui/styles/qplastiquestyle.cpp178
-rw-r--r--src/gui/styles/qproxystyle.cpp366
-rw-r--r--src/gui/styles/qproxystyle.h114
-rw-r--r--src/gui/styles/qproxystyle_p.h (renamed from src/gui/painting/qwindowsurface_d3d_p.h)41
-rw-r--r--src/gui/styles/qstyle.cpp40
-rw-r--r--src/gui/styles/qstyle.h8
-rw-r--r--src/gui/styles/qstyle_p.h16
-rw-r--r--src/gui/styles/qstylefactory.cpp2
-rw-r--r--src/gui/styles/qstylehelper.cpp352
-rw-r--r--src/gui/styles/qstylehelper_p.h83
-rw-r--r--src/gui/styles/qstyleoption.cpp52
-rw-r--r--src/gui/styles/qstyleoption.h1
-rw-r--r--src/gui/styles/qstylesheetstyle.cpp282
-rw-r--r--src/gui/styles/qstylesheetstyle_p.h2
-rw-r--r--src/gui/styles/qwindowsmobilestyle.cpp8
-rw-r--r--src/gui/styles/qwindowsstyle.cpp98
-rw-r--r--src/gui/styles/qwindowsvistastyle.cpp80
-rw-r--r--src/gui/styles/qwindowsxpstyle.cpp164
-rw-r--r--src/gui/styles/styles.pri6
-rw-r--r--src/gui/text/qcssparser.cpp46
-rw-r--r--src/gui/text/qcssparser_p.h23
-rw-r--r--src/gui/text/qfontdatabase.cpp40
-rw-r--r--src/gui/text/qfontdatabase_qws.cpp9
-rw-r--r--src/gui/text/qfontdatabase_win.cpp10
-rw-r--r--src/gui/text/qfontdatabase_x11.cpp30
-rw-r--r--src/gui/text/qfontengine.cpp14
-rw-r--r--src/gui/text/qfontengine_ft.cpp2
-rw-r--r--src/gui/text/qfontengine_mac.mm110
-rw-r--r--src/gui/text/qfontengine_p.h10
-rw-r--r--src/gui/text/qfontengine_qpf.cpp20
-rw-r--r--src/gui/text/qfontengine_qws.cpp2
-rw-r--r--src/gui/text/qfontengine_win.cpp46
-rw-r--r--src/gui/text/qfontengine_x11.cpp5
-rw-r--r--src/gui/text/qfontengineglyphcache_p.h4
-rw-r--r--src/gui/text/qfontsubset.cpp30
-rw-r--r--src/gui/text/qtextcontrol.cpp6
-rw-r--r--src/gui/text/qtextcontrol_p.h2
-rw-r--r--src/gui/text/qtextcursor.cpp82
-rw-r--r--src/gui/text/qtextdocument.cpp2
-rw-r--r--src/gui/text/qtextdocument_p.cpp47
-rw-r--r--src/gui/text/qtextdocument_p.h9
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp48
-rw-r--r--src/gui/text/qtextengine.cpp6
-rw-r--r--src/gui/text/qtextengine_p.h2
-rw-r--r--src/gui/text/qtextformat.cpp4
-rw-r--r--src/gui/text/qtextformat.h4
-rw-r--r--src/gui/text/qtexthtmlparser.cpp4
-rw-r--r--src/gui/text/qtextimagehandler_p.h4
-rw-r--r--src/gui/text/qtextodfwriter.cpp53
-rw-r--r--src/gui/util/qcompleter.cpp2
-rw-r--r--src/gui/util/qdesktopservices_mac.cpp15
-rw-r--r--src/gui/util/qdesktopservices_win.cpp67
-rw-r--r--src/gui/util/qdesktopservices_x11.cpp4
-rw-r--r--src/gui/util/qsystemtrayicon.cpp10
-rw-r--r--src/gui/util/qsystemtrayicon_win.cpp14
-rw-r--r--src/gui/widgets/qabstractbutton.cpp43
-rw-r--r--src/gui/widgets/qabstractscrollarea.cpp13
-rw-r--r--src/gui/widgets/qabstractscrollarea_p.h2
-rw-r--r--src/gui/widgets/qabstractspinbox.cpp5
-rw-r--r--src/gui/widgets/qbuttongroup.cpp17
-rw-r--r--src/gui/widgets/qcalendarwidget.cpp14
-rw-r--r--src/gui/widgets/qcombobox.cpp37
-rw-r--r--src/gui/widgets/qcombobox_p.h3
-rw-r--r--src/gui/widgets/qcommandlinkbutton.cpp9
-rw-r--r--src/gui/widgets/qdatetimeedit.cpp8
-rw-r--r--src/gui/widgets/qdockarealayout.cpp8
-rw-r--r--src/gui/widgets/qdockwidget.cpp86
-rw-r--r--src/gui/widgets/qeffects.cpp8
-rw-r--r--src/gui/widgets/qframe.cpp4
-rw-r--r--src/gui/widgets/qframe_p.h3
-rw-r--r--src/gui/widgets/qgroupbox.cpp12
-rw-r--r--src/gui/widgets/qlabel.cpp24
-rw-r--r--src/gui/widgets/qlcdnumber.cpp12
-rw-r--r--src/gui/widgets/qlineedit.cpp6
-rw-r--r--src/gui/widgets/qmainwindowlayout_mac.mm4
-rw-r--r--src/gui/widgets/qmainwindowlayout_p.h30
-rw-r--r--src/gui/widgets/qmdiarea.cpp34
-rw-r--r--src/gui/widgets/qmdisubwindow.cpp38
-rw-r--r--src/gui/widgets/qmdisubwindow_p.h4
-rw-r--r--src/gui/widgets/qmenu.cpp70
-rw-r--r--src/gui/widgets/qmenu.h4
-rw-r--r--src/gui/widgets/qmenu_mac.mm184
-rw-r--r--src/gui/widgets/qmenu_p.h12
-rw-r--r--src/gui/widgets/qmenu_wince.cpp4
-rw-r--r--src/gui/widgets/qmenubar.cpp157
-rw-r--r--src/gui/widgets/qmenubar.h8
-rw-r--r--src/gui/widgets/qmenubar_p.h15
-rw-r--r--src/gui/widgets/qplaintextedit.cpp25
-rw-r--r--src/gui/widgets/qprintpreviewwidget.cpp44
-rw-r--r--src/gui/widgets/qprogressbar.cpp8
-rw-r--r--src/gui/widgets/qpushbutton.cpp9
-rw-r--r--src/gui/widgets/qsizegrip.cpp2
-rw-r--r--src/gui/widgets/qslider.cpp10
-rw-r--r--src/gui/widgets/qspinbox.cpp23
-rw-r--r--src/gui/widgets/qsplitter.cpp14
-rw-r--r--src/gui/widgets/qsplitter_p.h9
-rw-r--r--src/gui/widgets/qstatusbar.cpp4
-rw-r--r--src/gui/widgets/qtabbar.cpp7
-rw-r--r--src/gui/widgets/qtabwidget.cpp2
-rw-r--r--src/gui/widgets/qtextbrowser.cpp8
-rw-r--r--src/gui/widgets/qtoolbar.cpp26
-rw-r--r--src/gui/widgets/qtoolbararealayout.cpp91
-rw-r--r--src/gui/widgets/qtoolbararealayout_p.h57
-rw-r--r--src/gui/widgets/qtoolbarlayout.cpp21
-rw-r--r--src/gui/widgets/qtoolbarlayout_p.h6
-rw-r--r--src/gui/widgets/qtoolbutton.cpp13
-rw-r--r--src/gui/widgets/qvalidator.cpp2
-rw-r--r--src/gui/widgets/qwidgetresizehandler.cpp2
-rw-r--r--src/network/access/qhttp.cpp10
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp296
-rw-r--r--src/network/access/qhttpnetworkconnection_p.h21
-rw-r--r--src/network/access/qhttpnetworkreply.cpp12
-rw-r--r--src/network/access/qhttpnetworkreply_p.h8
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp23
-rw-r--r--src/network/access/qhttpnetworkrequest_p.h9
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp57
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h38
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend.cpp283
-rw-r--r--src/network/access/qnetworkaccessdebugpipebackend_p.h23
-rw-r--r--src/network/access/qnetworkaccessfilebackend.cpp87
-rw-r--r--src/network/access/qnetworkaccessfilebackend_p.h9
-rw-r--r--src/network/access/qnetworkaccessftpbackend.cpp64
-rw-r--r--src/network/access/qnetworkaccessftpbackend_p.h5
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp99
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h11
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp29
-rw-r--r--src/network/access/qnetworkaccessmanager.h2
-rw-r--r--src/network/access/qnetworkcookie.cpp2
-rw-r--r--src/network/access/qnetworkdiskcache.cpp4
-rw-r--r--src/network/access/qnetworkdiskcache.h5
-rw-r--r--src/network/access/qnetworkreply.cpp4
-rw-r--r--src/network/access/qnetworkreply.h1
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp202
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h17
-rw-r--r--src/network/access/qnetworkrequest.cpp7
-rw-r--r--src/network/access/qnetworkrequest.h1
-rw-r--r--src/network/kernel/qauthenticator.cpp5
-rw-r--r--src/network/kernel/qhostaddress.cpp2
-rw-r--r--src/network/kernel/qnetworkinterface.cpp2
-rw-r--r--src/network/kernel/qnetworkproxy.cpp2
-rw-r--r--src/network/socket/qabstractsocket.cpp6
-rw-r--r--src/network/socket/qlocalserver.cpp8
-rw-r--r--src/network/socket/qlocalserver.h8
-rw-r--r--src/network/socket/qlocalserver_p.h61
-rw-r--r--src/network/socket/qlocalserver_unix.cpp6
-rw-r--r--src/network/socket/qlocalserver_win.cpp221
-rw-r--r--src/network/socket/qlocalsocket.cpp4
-rw-r--r--src/network/socket/qsocks5socketengine.cpp14
-rw-r--r--src/network/ssl/qsslcertificate.cpp20
-rw-r--r--src/network/ssl/qsslcipher.cpp2
-rw-r--r--src/network/ssl/qsslkey.cpp2
-rw-r--r--src/network/ssl/qsslsocket.cpp54
-rw-r--r--src/network/ssl/qsslsocket.h1
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp23
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h6
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp23
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h23
-rw-r--r--src/network/ssl/qsslsocket_p.h4
-rw-r--r--src/opengl/gl2paintengineex/glgc_shader_source.h289
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp10
-rw-r--r--src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h14
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager.cpp507
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadermanager_p.h395
-rw-r--r--src/opengl/gl2paintengineex/qglengineshadersource_p.h417
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache.cpp31
-rw-r--r--src/opengl/gl2paintengineex/qglgradientcache_p.h10
-rw-r--r--src/opengl/gl2paintengineex/qglpexshadermanager.cpp450
-rw-r--r--src/opengl/gl2paintengineex/qglpexshadermanager_p.h156
-rw-r--r--src/opengl/gl2paintengineex/qglshader.cpp605
-rw-r--r--src/opengl/gl2paintengineex/qglshader_p.h260
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp1237
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h130
-rw-r--r--src/opengl/opengl.pro40
-rw-r--r--src/opengl/qegl.cpp89
-rw-r--r--src/opengl/qegl_x11egl.cpp5
-rw-r--r--src/opengl/qgl.cpp526
-rw-r--r--src/opengl/qgl.h3
-rw-r--r--src/opengl/qgl_egl.cpp8
-rw-r--r--src/opengl/qgl_p.h80
-rw-r--r--src/opengl/qgl_x11.cpp124
-rw-r--r--src/opengl/qgl_x11egl.cpp158
-rw-r--r--src/opengl/qglextensions.cpp300
-rw-r--r--src/opengl/qglextensions_p.h454
-rw-r--r--src/opengl/qglframebufferobject.cpp587
-rw-r--r--src/opengl/qglframebufferobject.h49
-rw-r--r--src/opengl/qglpixelbuffer.cpp41
-rw-r--r--src/opengl/qglpixmapfilter.cpp211
-rw-r--r--src/opengl/qglpixmapfilter_p.h29
-rw-r--r--src/opengl/qglshaderprogram.cpp2986
-rw-r--r--src/opengl/qglshaderprogram.h293
-rw-r--r--src/opengl/qpaintengine_opengl.cpp259
-rw-r--r--src/opengl/qpixmapdata_gl.cpp379
-rw-r--r--src/opengl/qpixmapdata_gl_p.h43
-rw-r--r--src/opengl/qwindowsurface_gl.cpp289
-rw-r--r--src/opengl/qwindowsurface_gl_p.h7
-rw-r--r--src/opengl/util/fragmentprograms_p.h8
-rw-r--r--src/opengl/util/generator.cpp3
-rw-r--r--src/phonon/phonon.pro2
-rw-r--r--src/plugins/accessible/widgets/rangecontrols.cpp2
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp4
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp7
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp23
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.h4
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp17
-rw-r--r--src/plugins/gfxdrivers/hybrid/hybridscreen.cpp4
-rw-r--r--src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp2
-rw-r--r--src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp4
-rw-r--r--src/plugins/imageformats/ico/qicohandler.cpp331
-rw-r--r--src/plugins/imageformats/jpeg/qjpeghandler.cpp3
-rw-r--r--src/plugins/imageformats/svg/qsvgiohandler.cpp35
-rw-r--r--src/plugins/imageformats/tiff/qtiffhandler.cpp332
-rw-r--r--src/plugins/kbddrivers/kbddrivers.pro3
-rw-r--r--src/plugins/kbddrivers/linuxinput/linuxinput.pro14
-rw-r--r--src/plugins/kbddrivers/linuxinput/main.cpp (renamed from src/plugins/kbddrivers/usb/main.cpp)22
-rw-r--r--src/plugins/kbddrivers/linuxis/README1
-rw-r--r--src/plugins/kbddrivers/linuxis/linuxis.pro11
-rw-r--r--src/plugins/kbddrivers/linuxis/linuxiskbdhandler.cpp171
-rw-r--r--src/plugins/kbddrivers/usb/usb.pro14
-rw-r--r--src/plugins/sqldrivers/odbc/odbc.pro8
-rw-r--r--src/qbase.pri7
-rw-r--r--src/qt3support/dialogs/q3filedialog.cpp14
-rw-r--r--src/qt3support/dialogs/q3filedialog_mac.cpp2
-rw-r--r--src/qt3support/dialogs/q3filedialog_win.cpp2
-rw-r--r--src/qt3support/dialogs/q3tabdialog.cpp11
-rw-r--r--src/qt3support/dialogs/q3tabdialog.h1
-rw-r--r--src/qt3support/itemviews/q3iconview.cpp6
-rw-r--r--src/qt3support/network/q3dns.cpp16
-rw-r--r--src/qt3support/network/q3ftp.cpp22
-rw-r--r--src/qt3support/network/q3http.cpp8
-rw-r--r--src/qt3support/network/q3url.cpp61
-rw-r--r--src/qt3support/network/q3urloperator.cpp2
-rw-r--r--src/qt3support/other/q3dragobject.cpp11
-rw-r--r--src/qt3support/other/q3process.cpp2
-rw-r--r--src/qt3support/other/q3process_unix.cpp2
-rw-r--r--src/qt3support/other/q3process_win.cpp10
-rw-r--r--src/qt3support/painting/q3paintengine_svg.cpp48
-rw-r--r--src/qt3support/text/q3richtext.cpp28
-rw-r--r--src/qt3support/text/q3textedit.cpp4
-rw-r--r--src/qt3support/widgets/q3action.cpp2
-rw-r--r--src/qt3support/widgets/q3mainwindow.cpp18
-rw-r--r--src/script/qscriptcontext.cpp2
-rw-r--r--src/script/qscriptcontext_p.cpp6
-rw-r--r--src/script/qscriptecmaerror.cpp6
-rw-r--r--src/script/qscriptecmafunction.cpp2
-rw-r--r--src/script/qscriptecmaglobal.cpp2
-rw-r--r--src/script/qscriptecmaobject.cpp2
-rw-r--r--src/script/qscriptengine.cpp2
-rw-r--r--src/script/qscriptengine_p.cpp5
-rw-r--r--src/script/qscriptenginefwd_p.h1
-rw-r--r--src/script/qscriptextqobject.cpp56
-rw-r--r--src/script/qscriptparser.cpp4
-rw-r--r--src/script/qscriptprettypretty.cpp108
-rw-r--r--src/script/qscriptsyntaxchecker.cpp4
-rw-r--r--src/script/qscriptsyntaxchecker_p.h2
-rw-r--r--src/script/qscriptvalue.cpp1
-rw-r--r--src/script/qscriptvalueimpl.cpp12
-rw-r--r--src/script/qscriptxmlgenerator.cpp10
-rw-r--r--src/scripttools/debugging/debugging.pri6
-rw-r--r--src/scripttools/debugging/qscriptcompletiontask.cpp214
-rw-r--r--src/scripttools/debugging/qscriptcompletiontask_p.h9
-rw-r--r--src/scripttools/debugging/qscriptdebugger.cpp204
-rw-r--r--src/scripttools/debugging/qscriptdebugger_p.h34
-rw-r--r--src/scripttools/debugging/qscriptdebuggerbackend.cpp2
-rw-r--r--src/scripttools/debugging/qscriptdebuggercodeview.cpp3
-rw-r--r--src/scripttools/debugging/qscriptdebuggercodewidget.cpp13
-rw-r--r--src/scripttools/debugging/qscriptdebuggercommand.cpp20
-rw-r--r--src/scripttools/debugging/qscriptdebuggercommand_p.h5
-rw-r--r--src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp108
-rw-r--r--src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend.cpp11
-rw-r--r--src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend_p.h3
-rw-r--r--src/scripttools/debugging/qscriptdebuggerconsole.cpp4
-rw-r--r--src/scripttools/debugging/qscriptdebuggerlocalsmodel.cpp2
-rw-r--r--src/scripttools/debugging/qscriptdebuggerobjectsnapshotdelta_p.h5
-rw-r--r--src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory.cpp109
-rw-r--r--src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory_p.h85
-rw-r--r--src/scripttools/debugging/qscriptdebuggervalueproperty.cpp17
-rw-r--r--src/scripttools/debugging/qscriptdebuggerwidgetfactoryinterface_p.h10
-rw-r--r--src/scripttools/debugging/qscriptenginedebugger.cpp151
-rw-r--r--src/scripttools/debugging/qscripttooltipproviderinterface_p.h5
-rw-r--r--src/sql/drivers/db2/qsql_db2.cpp2
-rw-r--r--src/sql/drivers/ibase/qsql_ibase.cpp6
-rw-r--r--src/sql/drivers/mysql/qsql_mysql.cpp11
-rw-r--r--src/sql/drivers/oci/qsql_oci.cpp16
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp21
-rw-r--r--src/sql/drivers/psql/qsql_psql.cpp22
-rw-r--r--src/sql/drivers/sqlite/qsql_sqlite.cpp4
-rw-r--r--src/sql/drivers/sqlite2/qsql_sqlite2.cpp6
-rw-r--r--src/sql/drivers/tds/qsql_tds.cpp6
-rw-r--r--src/sql/kernel/qsqldriver.cpp18
-rw-r--r--src/sql/kernel/qsqlerror.cpp2
-rw-r--r--src/sql/kernel/qsqlfield.cpp4
-rw-r--r--src/sql/kernel/qsqlrecord.cpp2
-rw-r--r--src/sql/models/qsqlrelationaltablemodel.cpp2
-rw-r--r--src/svg/qgraphicssvgitem.cpp2
-rw-r--r--src/svg/qsvggenerator.cpp79
-rw-r--r--src/svg/qsvggraphics.cpp16
-rw-r--r--src/svg/qsvghandler.cpp3
-rw-r--r--src/testlib/qabstracttestlogger.cpp1
-rw-r--r--src/testlib/qbenchmark.cpp1
-rw-r--r--src/testlib/qbenchmark_p.h4
-rw-r--r--src/testlib/qbenchmarkvalgrind.cpp15
-rw-r--r--src/testlib/qplaintestlogger.cpp4
-rw-r--r--src/testlib/qsignaldumper.cpp10
-rw-r--r--src/testlib/qtestbasicstreamer.cpp219
-rw-r--r--src/testlib/qtestbasicstreamer.h90
-rw-r--r--src/testlib/qtestcase.cpp147
-rw-r--r--src/testlib/qtestcoreelement.h172
-rw-r--r--src/testlib/qtestcorelist.h (renamed from src/plugins/kbddrivers/linuxis/linuxiskbddriverplugin.cpp)105
-rw-r--r--src/testlib/qtestelement.cpp88
-rw-r--r--src/testlib/qtestelement.h75
-rw-r--r--src/testlib/qtestelementattribute.cpp177
-rw-r--r--src/testlib/qtestelementattribute.h111
-rw-r--r--src/testlib/qtestfilelogger.cpp95
-rw-r--r--src/testlib/qtestfilelogger.h (renamed from src/plugins/kbddrivers/linuxis/linuxiskbddriverplugin.h)35
-rw-r--r--src/testlib/qtestlightxmlstreamer.cpp185
-rw-r--r--src/testlib/qtestlightxmlstreamer.h72
-rw-r--r--src/testlib/qtestlog.cpp37
-rw-r--r--src/testlib/qtestlog_p.h5
-rw-r--r--src/testlib/qtestlogger.cpp403
-rw-r--r--src/testlib/qtestlogger_p.h127
-rw-r--r--src/testlib/qtestresult.cpp2
-rw-r--r--src/testlib/qtestxmlstreamer.cpp219
-rw-r--r--src/testlib/qtestxmlstreamer.h72
-rw-r--r--src/testlib/qtestxunitstreamer.cpp214
-rw-r--r--src/testlib/qtestxunitstreamer.h77
-rw-r--r--src/testlib/qxmltestlogger.cpp205
-rw-r--r--src/testlib/qxmltestlogger_p.h3
-rw-r--r--src/testlib/testlib.pro83
-rw-r--r--src/tools/idc/main.cpp6
-rw-r--r--src/tools/moc/generator.cpp24
-rw-r--r--src/tools/moc/moc.cpp14
-rw-r--r--src/tools/moc/moc.h3
-rw-r--r--src/tools/moc/outputrevision.h2
-rw-r--r--src/tools/moc/preprocessor.cpp2
-rw-r--r--src/tools/uic/cpp/cppwriteicondata.cpp4
-rw-r--r--src/tools/uic/cpp/cppwriteinitialization.cpp6
-rw-r--r--src/tools/uic/ui4.cpp245
-rw-r--r--src/tools/uic/ui4.h97
-rw-r--r--src/tools/uic3/embed.cpp2
-rw-r--r--src/tools/uic3/form.cpp84
-rw-r--r--src/tools/uic3/main.cpp2
-rw-r--r--src/tools/uic3/parser.cpp12
-rw-r--r--src/tools/uic3/qt3to4.cpp2
-rw-r--r--src/tools/uic3/subclassing.cpp36
-rw-r--r--src/tools/uic3/ui3reader.cpp24
-rw-r--r--src/winmain/qtmain_win.cpp4
-rw-r--r--src/xml/dom/qdom.cpp7
-rw-r--r--src/xml/sax/qxml.cpp12
-rw-r--r--src/xmlpatterns/acceltree/qacceltree.cpp14
-rw-r--r--src/xmlpatterns/api/qsourcelocation.cpp2
-rw-r--r--src/xmlpatterns/data/qabstractfloat.cpp2
-rw-r--r--src/xmlpatterns/data/qcommonvalues.cpp2
-rw-r--r--src/xmlpatterns/expr/qexpression_p.h2
814 files changed, 51944 insertions, 22347 deletions
diff --git a/src/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp b/src/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp
index 36c170a..e9659cf 100644
--- a/src/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp
+++ b/src/3rdparty/clucene/src/CLucene/store/FSDirectory.cpp
@@ -624,7 +624,7 @@ LuceneLock* FSDirectory::makeLock(const QString& name)
QString lockFile(getLockPrefix());
- lockFile.append(QLatin1String("-")).append(name);
+ lockFile.append(QLatin1Char('-')).append(name);
return _CLNEW FSLock(lockDir, lockFile);
}
diff --git a/src/3rdparty/clucene/src/CLucene/util/Misc.cpp b/src/3rdparty/clucene/src/CLucene/util/Misc.cpp
index 069b487..cb2efe2 100644
--- a/src/3rdparty/clucene/src/CLucene/util/Misc.cpp
+++ b/src/3rdparty/clucene/src/CLucene/util/Misc.cpp
@@ -181,12 +181,9 @@ void Misc::segmentname(QString& buffer, int32_t bufferLen,
CND_PRECONDITION(!segment.isEmpty(), "segment is NULL");
CND_PRECONDITION(!ext.isEmpty(), "extention is NULL");
- buffer.clear();
- if (x == -1) {
- buffer = QString(segment + ext);
- } else {
- buffer = QString(QLatin1String("%1%2%3")).arg(segment).arg(ext).arg(x);
- }
+ buffer = segment + ext;
+ if (x != -1)
+ buffer += QString::number(x);
}
// #pragma mark -- TCHAR related utils
diff --git a/src/3rdparty/easing/easing.cpp b/src/3rdparty/easing/easing.cpp
new file mode 100644
index 0000000..81af40f
--- /dev/null
+++ b/src/3rdparty/easing/easing.cpp
@@ -0,0 +1,670 @@
+/*
+Disclaimer for Robert Penner's Easing Equations license:
+
+TERMS OF USE - EASING EQUATIONS
+
+Open source under the BSD License.
+
+Copyright © 2001 Robert Penner
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <QtCore/qmath.h>
+#include <math.h>
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 (M_PI / 2)
+#endif
+
+QT_USE_NAMESPACE
+
+/**
+ * Easing equation function for a simple linear tweening, with no easing.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeNone(qreal progress)
+{
+ return progress;
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInQuad(qreal t)
+{
+ return t*t;
+}
+
+/**
+* Easing equation function for a quadratic (t^2) easing out: decelerating to zero velocity.
+*
+* @param t Current time (in frames or seconds).
+* @return The correct value.
+*/
+static qreal easeOutQuad(qreal t)
+{
+ return -t*(t-2);
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutQuad(qreal t)
+{
+ t*=2.0;
+ if (t < 1) {
+ return t*t/qreal(2);
+ } else {
+ --t;
+ return -0.5 * (t*(t-2) - 1);
+ }
+}
+
+/**
+ * Easing equation function for a quadratic (t^2) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInQuad(qreal t)
+{
+ if (t < 0.5) return easeOutQuad (t*2)/2;
+ return easeInQuad((2*t)-1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInCubic(qreal t)
+{
+ return t*t*t;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutCubic(qreal t)
+{
+ t-=1.0;
+ return t*t*t + 1;
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutCubic(qreal t)
+{
+ t*=2.0;
+ if(t < 1) {
+ return 0.5*t*t*t;
+ } else {
+ t -= qreal(2.0);
+ return 0.5*(t*t*t + 2);
+ }
+}
+
+/**
+ * Easing equation function for a cubic (t^3) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInCubic(qreal t)
+{
+ if (t < 0.5) return easeOutCubic (2*t)/2;
+ return easeInCubic(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInQuart(qreal t)
+{
+ return t*t*t*t;
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutQuart(qreal t)
+{
+ t-= qreal(1.0);
+ return - (t*t*t*t- 1);
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutQuart(qreal t)
+{
+ t*=2;
+ if (t < 1) return 0.5*t*t*t*t;
+ else {
+ t -= 2.0f;
+ return -0.5 * (t*t*t*t- 2);
+ }
+}
+
+/**
+ * Easing equation function for a quartic (t^4) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInQuart(qreal t)
+{
+ if (t < 0.5) return easeOutQuart (2*t)/2;
+ return easeInQuart(2*t-1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInQuint(qreal t)
+{
+ return t*t*t*t*t;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutQuint(qreal t)
+{
+ t-=1.0;
+ return t*t*t*t*t + 1;
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutQuint(qreal t)
+{
+ t*=2.0;
+ if (t < 1) return 0.5*t*t*t*t*t;
+ else {
+ t -= 2.0;
+ return 0.5*(t*t*t*t*t + 2);
+ }
+}
+
+/**
+ * Easing equation function for a quintic (t^5) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInQuint(qreal t)
+{
+ if (t < 0.5) return easeOutQuint (2*t)/2;
+ return easeInQuint(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInSine(qreal t)
+{
+ return (t == 1.0) ? 1.0 : -::cos(t * M_PI_2) + 1.0;
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutSine(qreal t)
+{
+ return ::sin(t* M_PI_2);
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutSine(qreal t)
+{
+ return -0.5 * (::cos(M_PI*t) - 1);
+}
+
+/**
+ * Easing equation function for a sinusoidal (sin(t)) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInSine(qreal t)
+{
+ if (t < 0.5) return easeOutSine (2*t)/2;
+ return easeInSine(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInExpo(qreal t)
+{
+ return (t==0 || t == 1.0) ? t : ::qPow(2.0, 10 * (t - 1)) - qreal(0.001);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutExpo(qreal t)
+{
+ return (t==1.0) ? 1.0 : 1.001 * (-::qPow(2.0f, -10 * t) + 1);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutExpo(qreal t)
+{
+ if (t==0.0) return qreal(0.0);
+ if (t==1.0) return qreal(1.0);
+ t*=2.0;
+ if (t < 1) return 0.5 * ::qPow(qreal(2.0), 10 * (t - 1)) - 0.0005;
+ return 0.5 * 1.0005 * (-::qPow(qreal(2.0), -10 * (t - 1)) + 2);
+}
+
+/**
+ * Easing equation function for an exponential (2^t) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInExpo(qreal t)
+{
+ if (t < 0.5) return easeOutExpo (2*t)/2;
+ return easeInExpo(2*t - 1)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInCirc(qreal t)
+{
+ return -(::sqrt(1 - t*t) - 1);
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutCirc(qreal t)
+{
+ t-= qreal(1.0);
+ return ::sqrt(1 - t* t);
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeInOutCirc(qreal t)
+{
+ t*=qreal(2.0);
+ if (t < 1) {
+ return -0.5 * (::sqrt(1 - t*t) - 1);
+ } else {
+ t -= qreal(2.0);
+ return 0.5 * (::sqrt(1 - t*t) + 1);
+ }
+}
+
+/**
+ * Easing equation function for a circular (sqrt(1-t^2)) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @return The correct value.
+ */
+static qreal easeOutInCirc(qreal t)
+{
+ if (t < 0.5) return easeOutCirc (2*t)/2;
+ return easeInCirc(2*t - 1)/2 + 0.5;
+}
+
+static qreal easeInElastic_helper(qreal t, qreal b, qreal c, qreal d, qreal a, qreal p)
+{
+ if (t==0) return b;
+ qreal t_adj = (qreal)t / (qreal)d;
+ if (t_adj==1) return b+c;
+
+ qreal s;
+ if(a < ::fabs(c)) {
+ a = c;
+ s = p / 4.0f;
+ } else {
+ s = p / (2 * M_PI) * ::asin(c / a);
+ }
+
+ t_adj -= 1.0f;
+ return -(a*::qPow(2.0f,10*t_adj) * ::sin( (t_adj*d-s)*(2*M_PI)/p )) + b;
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeInElastic(qreal t, qreal a, qreal p)
+{
+ return easeInElastic_helper(t, 0, 1, 1, a, p);
+}
+
+static qreal easeOutElastic_helper(qreal t, qreal /*b*/, qreal c, qreal /*d*/, qreal a, qreal p)
+{
+ if (t==0) return 0;
+ if (t==1) return c;
+
+ qreal s;
+ if(a < c) {
+ a = c;
+ s = p / 4.0f;
+ } else {
+ s = p / (2 * M_PI) * ::asin(c / a);
+ }
+
+ return (a*::qPow(2.0f,-10*t) * ::sin( (t-s)*(2*M_PI)/p ) + c);
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeOutElastic(qreal t, qreal a, qreal p)
+{
+ return easeOutElastic_helper(t, 0, 1, 1, a, p);
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeInOutElastic(qreal t, qreal a, qreal p)
+{
+ if (t==0) return 0.0;
+ t*=2.0;
+ if (t==2) return 1.0;
+
+ qreal s;
+ if(a < 1.0) {
+ a = 1.0;
+ s = p / 4.0f;
+ } else {
+ s = p / (2 * M_PI) * ::asin(1.0 / a);
+ }
+
+ if (t < 1) return -.5*(a*::qPow(2.0f,10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p ));
+ return a*::qPow(2.0f,-10*(t-1)) * ::sin( (t-1-s)*(2*M_PI)/p )*.5 + 1.0;
+}
+
+/**
+ * Easing equation function for an elastic (exponentially decaying sine wave) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @param p Period.
+ * @return The correct value.
+ */
+static qreal easeOutInElastic(qreal t, qreal a, qreal p)
+{
+ if (t < 0.5) return easeOutElastic_helper(t*2, 0, 0.5, 1.0, a, p);
+ return easeInElastic_helper(2*t - 1.0, 0.5, 0.5, 1.0, a, p);
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeInBack(qreal t, qreal s)
+{
+ return t*t*((s+1)*t - s);
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeOutBack(qreal t, qreal s)
+{
+ t-= qreal(1.0);
+ return t*t*((s+1)*t+ s) + 1;
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeInOutBack(qreal t, qreal s)
+{
+ t *= 2.0;
+ if (t < 1) {
+ s *= 1.525f;
+ return 0.5*(t*t*((s+1)*t - s));
+ } else {
+ t -= 2;
+ s *= 1.525f;
+ return 0.5*(t*t*((s+1)*t+ s) + 2);
+ }
+}
+
+/**
+ * Easing equation function for a back (overshooting cubic easing: (s+1)*t^3 - s*t^2) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param s Overshoot ammount: higher s means greater overshoot (0 produces cubic easing with no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent).
+ * @return The correct value.
+ */
+static qreal easeOutInBack(qreal t, qreal s)
+{
+ if (t < 0.5) return easeOutBack (2*t, s)/2;
+ return easeInBack(2*t - 1, s)/2 + 0.5;
+}
+
+static qreal easeOutBounce_helper(qreal t, qreal c, qreal a)
+{
+ if (t == 1.0) return c;
+ if (t < (4/11.0)) {
+ return c*(7.5625*t*t);
+ } else if (t < (8/11.0)) {
+ t -= (6/11.0);
+ return -a * (1. - (7.5625*t*t + .75)) + c;
+ } else if (t < (10/11.0)) {
+ t -= (9/11.0);
+ return -a * (1. - (7.5625*t*t + .9375)) + c;
+ } else {
+ t -= (21/22.0);
+ return -a * (1. - (7.5625*t*t + .984375)) + c;
+ }
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out: decelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeOutBounce(qreal t, qreal a)
+{
+ return easeOutBounce_helper(t, 1, a);
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in: accelerating from zero velocity.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeInBounce(qreal t, qreal a)
+{
+ return 1.0 - easeOutBounce_helper(1.0-t, 1.0, a);
+}
+
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing in/out: acceleration until halfway, then deceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeInOutBounce(qreal t, qreal a)
+{
+ if (t < 0.5) return easeInBounce (2*t, a)/2;
+ else return (t == 1.0) ? 1.0 : easeOutBounce (2*t - 1, a)/2 + 0.5;
+}
+
+/**
+ * Easing equation function for a bounce (exponentially decaying parabolic bounce) easing out/in: deceleration until halfway, then acceleration.
+ *
+ * @param t Current time (in frames or seconds).
+ * @param a Amplitude.
+ * @return The correct value.
+ */
+static qreal easeOutInBounce(qreal t, qreal a)
+{
+ if (t < 0.5) return easeOutBounce_helper(t*2, 0.5, a);
+ return 1.0 - easeOutBounce_helper (2.0-2*t, 0.5, a);
+}
+
+static inline qreal qt_sinProgress(qreal value)
+{
+ return qSin((value * M_PI) - M_PI_2) / 2 + qreal(0.5);
+}
+
+static inline qreal qt_smoothBeginEndMixFactor(qreal value)
+{
+ return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0));
+}
+
+// SmoothBegin blends Smooth and Linear Interpolation.
+// Progress 0 - 0.3 : Smooth only
+// Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear
+// Progress ~ 0.5 - 1 : Linear only
+
+/**
+ * Easing function that starts growing slowly, then increases in speed. At the end of the curve the speed will be constant.
+ */
+static qreal easeInCurve(qreal t)
+{
+ const qreal sinProgress = qt_sinProgress(t);
+ const qreal mix = qt_smoothBeginEndMixFactor(t);
+ return sinProgress * mix + t * (1 - mix);
+}
+
+/**
+ * Easing function that starts growing steadily, then ends slowly. The speed will be constant at the beginning of the curve.
+ */
+static qreal easeOutCurve(qreal t)
+{
+ const qreal sinProgress = qt_sinProgress(t);
+ const qreal mix = qt_smoothBeginEndMixFactor(1 - t);
+ return sinProgress * mix + t * (1 - mix);
+}
+
+/**
+ * Easing function where the value grows sinusoidally. Note that the calculated end value will be 0 rather than 1.
+ */
+static qreal easeSineCurve(qreal t)
+{
+ return (qSin(((t * M_PI * 2)) - M_PI_2) + 1) / 2;
+}
+
+/**
+ * Easing function where the value grows cosinusoidally. Note that the calculated start value will be 0.5 and the end value will be 0.5
+ * contrary to the usual 0 to 1 easing curve.
+ */
+static qreal easeCosineCurve(qreal t)
+{
+ return (qCos(((t * M_PI * 2)) - M_PI_2) + 1) / 2;
+}
+
diff --git a/src/3rdparty/easing/legal.qdoc b/src/3rdparty/easing/legal.qdoc
new file mode 100644
index 0000000..25f67e1
--- /dev/null
+++ b/src/3rdparty/easing/legal.qdoc
@@ -0,0 +1,35 @@
+/*!
+\page legal-easing.html
+\title Easing Equations by Robert Penner
+\ingroup animation
+
+\legalese
+\code
+Copyright (c) 2001 Robert Penner
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+ * Neither the name of the author nor the names of contributors may be used
+ to endorse or promote products derived from this software without specific
+ prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+\endcode
+\endlegalese
+*/
diff --git a/src/3rdparty/phonon/qt7/mediaobject.h b/src/3rdparty/phonon/qt7/mediaobject.h
index 27949ec..c93eddc 100644
--- a/src/3rdparty/phonon/qt7/mediaobject.h
+++ b/src/3rdparty/phonon/qt7/mediaobject.h
@@ -25,6 +25,10 @@
#include "medianode.h"
+#if QT_ALLOW_QUICKTIME
+ #include <QuickTime/QuickTime.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace Phonon
@@ -38,7 +42,10 @@ namespace QT7
class MediaObjectAudioNode;
class MediaObject : public MediaNode,
- public Phonon::MediaObjectInterface, public Phonon::AddonInterface
+ public Phonon::MediaObjectInterface
+#ifndef QT_NO_PHONON_MEDIACONTROLLER
+ , public Phonon::AddonInterface
+#endif
{
Q_OBJECT
Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface)
@@ -92,6 +99,10 @@ namespace QT7
int videoOutputCount();
+#if QT_ALLOW_QUICKTIME
+ void displayLinkEvent();
+#endif
+
signals:
void stateChanged(Phonon::State,Phonon::State);
void tick(qint64);
@@ -105,6 +116,16 @@ namespace QT7
void metaDataChanged(QMultiMap<QString,QString>);
void currentSourceChanged(const MediaSource &newSource);
+ // Add-on interface:
+ void availableSubtitlesChanged();
+ void availableAudioChannelsChanged();
+ void titleChanged(int);
+ void availableTitlesChanged(int);
+ void chapterChanged(int);
+ void availableChaptersChanged(int);
+ void angleChanged(int);
+ void availableAnglesChanged(int);
+
protected:
void mediaNodeEvent(const MediaNodeEvent *event);
bool event(QEvent *event);
@@ -118,7 +139,14 @@ namespace QT7
QuickTimeVideoPlayer *m_nextVideoPlayer;
QuickTimeAudioPlayer *m_nextAudioPlayer;
MediaObjectAudioNode *m_mediaObjectAudioNode;
- QuickTimeMetaData *m_metaData;
+
+#if QT_ALLOW_QUICKTIME
+ CVDisplayLinkRef m_displayLink;
+ QMutex m_displayLinkMutex;
+ bool m_pendingDisplayLinkEvent;
+ void startDisplayLink();
+ void stopDisplayLink();
+#endif
qint32 m_tickInterval;
qint32 m_transitionTime;
@@ -127,12 +155,14 @@ namespace QT7
float m_percentageLoaded;
int m_tickTimer;
- int m_bufferTimer;
+ int m_videoTimer;
+ int m_audioTimer;
int m_rapidTimer;
bool m_waitNextSwap;
int m_swapTimeLeft;
QTime m_swapTime;
+ bool m_autoplayTitles;
void synchAudioVideo();
void updateCurrentTime();
@@ -141,8 +171,7 @@ namespace QT7
void pause_internal();
void play_internal();
void setupAudioSystem();
- void updateTimer(int &timer, int interval);
- void bufferAudioVideo();
+ void restartAudioVideoTimers();
void updateRapidly();
void updateCrossFade();
void updateAudioBuffers();
@@ -154,6 +183,7 @@ namespace QT7
void inspectVideoGraphRecursive(MediaNode *node, int &effectCount, int &outputCount);
void inspectGraph();
bool isCrossFading();
+ void setCurrentTrack(int track);
QString m_errorString;
Phonon::ErrorType m_errorType;
diff --git a/src/3rdparty/phonon/qt7/mediaobject.mm b/src/3rdparty/phonon/qt7/mediaobject.mm
index 002c337..677640c 100644
--- a/src/3rdparty/phonon/qt7/mediaobject.mm
+++ b/src/3rdparty/phonon/qt7/mediaobject.mm
@@ -46,7 +46,6 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_mediaObjectAudioNode = new MediaObjectAudioNode(m_audioPlayer, m_nextAudioPlayer);
setAudioNode(m_mediaObjectAudioNode);
- m_metaData = new QuickTimeMetaData();
m_audioGraph = new AudioGraph(this);
m_tickInterval = 0;
@@ -55,6 +54,7 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_transitionTime = 0;
m_percentageLoaded = 0;
m_waitNextSwap = false;
+ m_autoplayTitles = true;
m_audioEffectCount = 0;
m_audioOutputCount = 0;
m_videoEffectCount = 0;
@@ -63,20 +63,28 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_errorType = Phonon::NoError;
m_tickTimer = 0;
- m_bufferTimer = 0;
+ m_videoTimer = 0;
+ m_audioTimer = 0;
m_rapidTimer = 0;
+#if QT_ALLOW_QUICKTIME
+ m_displayLink = 0;
+ m_pendingDisplayLinkEvent = false;
+#endif
+
checkForError();
}
MediaObject::~MediaObject()
-{
- // m_mediaObjectAudioNode is owned by super class.
+{
+ // m_mediaObjectAudioNode is owned by super class.
+#if QT_ALLOW_QUICKTIME
+ stopDisplayLink();
+#endif
m_audioPlayer->unsetVideoPlayer();
m_nextAudioPlayer->unsetVideoPlayer();
delete m_videoPlayer;
delete m_nextVideoPlayer;
- delete m_metaData;
checkForError();
}
@@ -88,7 +96,7 @@ bool MediaObject::setState(Phonon::State state)
emit stateChanged(m_state, prevState);
if (m_state != state){
// End-application did something
- // upon receiving the signal.
+ // upon receiving the signal.
return false;
}
}
@@ -122,7 +130,7 @@ void MediaObject::inspectGraph()
// Inspect the graph to check wether there are any
// effects or outputs connected. This will have
// influence on the audio system and video system that ends up beeing used:
- int prevVideoOutputCount = m_videoOutputCount;
+ int prevVideoOutputCount = m_videoOutputCount;
m_audioEffectCount = 0;
m_audioOutputCount = 0;
m_videoEffectCount = 0;
@@ -134,7 +142,7 @@ void MediaObject::inspectGraph()
if (m_videoOutputCount != prevVideoOutputCount){
MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
notify(&e1);
- }
+ }
}
void MediaObject::setupAudioSystem()
@@ -167,14 +175,14 @@ void MediaObject::setupAudioSystem()
if (newAudioSystem == m_audioSystem)
return;
-
+
// Enable selected audio system:
- m_audioSystem = newAudioSystem;
+ m_audioSystem = newAudioSystem;
switch (newAudioSystem){
case AS_Silent:
m_audioGraph->stop();
m_videoPlayer->enableAudio(false);
- m_nextVideoPlayer->enableAudio(false);
+ m_nextVideoPlayer->enableAudio(false);
m_audioPlayer->enableAudio(false);
m_nextAudioPlayer->enableAudio(false);
break;
@@ -214,28 +222,28 @@ void MediaObject::setSource(const MediaSource &source)
IMPLEMENTED;
PhononAutoReleasePool pool;
setState(Phonon::LoadingState);
-
+
// Save current state for event/signal handling below:
bool prevHasVideo = m_videoPlayer->hasVideo();
qint64 prevTotalTime = totalTime();
+ int prevTrackCount = m_videoPlayer->trackCount();
m_waitNextSwap = false;
-
+
// Cancel cross-fade if any:
m_nextVideoPlayer->pause();
m_nextAudioPlayer->pause();
m_mediaObjectAudioNode->cancelCrossFade();
-
+
// Set new source:
m_audioPlayer->unsetVideoPlayer();
m_videoPlayer->setMediaSource(source);
m_audioPlayer->setVideoPlayer(m_videoPlayer);
- m_metaData->setVideo(m_videoPlayer);
- m_audioGraph->updateStreamSpecifications();
+ m_audioGraph->updateStreamSpecifications();
m_nextAudioPlayer->unsetVideoPlayer();
- m_nextVideoPlayer->unsetVideo();
+ m_nextVideoPlayer->unsetCurrentMediaSource();
m_currentTime = 0;
-
+
// Emit/notify information about the new source:
QRect videoRect = m_videoPlayer->videoRect();
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
@@ -246,12 +254,14 @@ void MediaObject::setSource(const MediaSource &source)
updateVideo(emptyFrame);
emit currentSourceChanged(source);
- emit metaDataChanged(m_metaData->metaData());
+ emit metaDataChanged(m_videoPlayer->metaData());
if (prevHasVideo != m_videoPlayer->hasVideo())
- emit hasVideoChanged(m_videoPlayer->hasVideo());
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
if (prevTotalTime != totalTime())
- emit totalTimeChanged(totalTime());
+ emit totalTimeChanged(totalTime());
+ if (prevTrackCount != m_videoPlayer->trackCount())
+ emit availableTitlesChanged(m_videoPlayer->trackCount());
if (checkForError())
return;
if (!m_videoPlayer->isDrmAuthorized())
@@ -260,7 +270,7 @@ void MediaObject::setSource(const MediaSource &source)
return;
if (!m_videoPlayer->canPlayMedia())
SET_ERROR("Cannot play media.", FATAL_ERROR)
-
+
// The state might have changed from LoadingState
// as a response to an error state change. So we
// need to check it before stopping:
@@ -287,28 +297,30 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime)
// Save current state for event/signal handling below:
bool prevHasVideo = m_videoPlayer->hasVideo();
qint64 prevTotalTime = totalTime();
+ int prevTrackCount = m_videoPlayer->trackCount();
qSwap(m_audioPlayer, m_nextAudioPlayer);
qSwap(m_videoPlayer, m_nextVideoPlayer);
m_mediaObjectAudioNode->startCrossFade(transitionTime);
m_audioGraph->updateStreamSpecifications();
- m_metaData->setVideo(m_videoPlayer);
m_waitNextSwap = false;
m_currentTime = 0;
-
+
// Emit/notify information about the new source:
QRect videoRect = m_videoPlayer->videoRect();
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
notify(&e1);
emit currentSourceChanged(m_videoPlayer->mediaSource());
- emit metaDataChanged(m_metaData->metaData());
+ emit metaDataChanged(m_videoPlayer->metaData());
if (prevHasVideo != m_videoPlayer->hasVideo())
- emit hasVideoChanged(m_videoPlayer->hasVideo());
+ emit hasVideoChanged(m_videoPlayer->hasVideo());
if (prevTotalTime != totalTime())
emit totalTimeChanged(totalTime());
+ if (prevTrackCount != m_videoPlayer->trackCount())
+ emit availableTitlesChanged(m_videoPlayer->trackCount());
if (checkForError())
return;
if (!m_videoPlayer->isDrmAuthorized())
@@ -327,28 +339,107 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime)
}
}
-void MediaObject::updateTimer(int &timer, int interval)
+#if QT_ALLOW_QUICKTIME
+static CVReturn displayLinkCallback(CVDisplayLinkRef /*displayLink*/,
+ const CVTimeStamp */*inNow*/,
+ const CVTimeStamp */*inOutputTime*/,
+ CVOptionFlags /*flagsIn*/,
+ CVOptionFlags */*flagsOut*/,
+ void *userData)
+{
+ MediaObject *mediaObject = static_cast<MediaObject *>(userData);
+ mediaObject->displayLinkEvent();
+ return kCVReturnSuccess;
+}
+
+void MediaObject::displayLinkEvent()
+{
+ // This function is called from a
+ // thread != gui thread. So we post the event.
+ // But we need to make sure that we don't post faster
+ // than the event loop can eat:
+ m_displayLinkMutex.lock();
+ bool pending = m_pendingDisplayLinkEvent;
+ m_pendingDisplayLinkEvent = true;
+ m_displayLinkMutex.unlock();
+
+ if (!pending)
+ qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+}
+
+void MediaObject::startDisplayLink()
{
- if (timer)
- killTimer(timer);
- timer = 0;
- if (interval >= 0)
- timer = startTimer(interval);
+ if (m_displayLink)
+ return;
+ OSStatus err = CVDisplayLinkCreateWithCGDisplay(kCGDirectMainDisplay, &m_displayLink);
+ if (err != noErr)
+ goto fail;
+ err = CVDisplayLinkSetCurrentCGDisplay(m_displayLink, kCGDirectMainDisplay);
+ if (err != noErr)
+ goto fail;
+ err = CVDisplayLinkSetOutputCallback(m_displayLink, displayLinkCallback, this);
+ if (err != noErr)
+ goto fail;
+ err = CVDisplayLinkStart(m_displayLink);
+ if (err != noErr)
+ goto fail;
+ return;
+fail:
+ stopDisplayLink();
+}
+
+void MediaObject::stopDisplayLink()
+{
+ if (!m_displayLink)
+ return;
+ CVDisplayLinkStop(m_displayLink);
+ CFRelease(m_displayLink);
+ m_displayLink = 0;
+}
+#endif
+
+void MediaObject::restartAudioVideoTimers()
+{
+ if (m_videoTimer)
+ killTimer(m_videoTimer);
+ if (m_audioTimer)
+ killTimer(m_audioTimer);
+
+#if QT_ALLOW_QUICKTIME
+ // We prefer to use a display link as timer if available, since
+ // it is more steady, and results in better and smoother frame drawing:
+ startDisplayLink();
+ if (!m_displayLink){
+ float fps = m_videoPlayer->staticFps();
+ long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001;
+ m_videoTimer = startTimer(videoUpdateFrequency);
+ }
+#else
+ float fps = m_videoPlayer->staticFps();
+ long videoUpdateFrequency = fps ? long(1000.0f / fps) : 0.001;
+ m_videoTimer = startTimer(videoUpdateFrequency);
+#endif
+
+ long audioUpdateFrequency = m_audioPlayer->regularTaskFrequency();
+ m_audioTimer = startTimer(audioUpdateFrequency);
+ updateVideoFrames();
+ updateAudioBuffers();
}
void MediaObject::play_internal()
{
// Play main audio/video:
m_videoPlayer->play();
- m_audioPlayer->play();
+ m_audioPlayer->play();
updateLipSynch(0);
// Play old audio/video to finish cross-fade:
if (m_nextVideoPlayer->currentTime() > 0){
m_nextVideoPlayer->play();
m_nextAudioPlayer->play();
}
- bufferAudioVideo();
- updateTimer(m_rapidTimer, 100);
+ restartAudioVideoTimers();
+ if (!m_rapidTimer)
+ m_rapidTimer = startTimer(100);
}
void MediaObject::pause_internal()
@@ -358,9 +449,15 @@ void MediaObject::pause_internal()
m_nextAudioPlayer->pause();
m_videoPlayer->pause();
m_nextVideoPlayer->pause();
- updateTimer(m_rapidTimer, -1);
- updateTimer(m_bufferTimer, -1);
-
+ killTimer(m_rapidTimer);
+ killTimer(m_videoTimer);
+ killTimer(m_audioTimer);
+ m_rapidTimer = 0;
+ m_videoTimer = 0;
+ m_audioTimer = 0;
+#if QT_ALLOW_QUICKTIME
+ stopDisplayLink();
+#endif
if (m_waitNextSwap)
m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
}
@@ -382,7 +479,7 @@ void MediaObject::play()
if (!m_videoPlayer->canPlayMedia())
return;
if (!setState(Phonon::PlayingState))
- return;
+ return;
if (m_audioSystem == AS_Graph){
m_audioGraph->start();
m_mediaObjectAudioNode->setMute(true);
@@ -423,7 +520,7 @@ void MediaObject::stop()
if (!setState(Phonon::StoppedState))
return;
m_waitNextSwap = false;
- m_nextVideoPlayer->unsetVideo();
+ m_nextVideoPlayer->unsetCurrentMediaSource();
m_nextAudioPlayer->unsetVideoPlayer();
pause_internal();
seek(0);
@@ -435,9 +532,9 @@ void MediaObject::seek(qint64 milliseconds)
IMPLEMENTED;
if (m_state == Phonon::ErrorState)
return;
-
+
// Stop cross-fade if any:
- m_nextVideoPlayer->unsetVideo();
+ m_nextVideoPlayer->unsetCurrentMediaSource();
m_nextAudioPlayer->unsetVideoPlayer();
m_mediaObjectAudioNode->cancelCrossFade();
@@ -446,7 +543,7 @@ void MediaObject::seek(qint64 milliseconds)
m_videoPlayer->seek(milliseconds);
m_audioPlayer->seek(m_videoPlayer->currentTime());
m_mediaObjectAudioNode->setMute(false);
-
+
// Update time and cancel pending swap:
if (m_currentTime < m_videoPlayer->duration())
m_waitNextSwap = false;
@@ -557,7 +654,7 @@ bool MediaObject::isSeekable() const
qint64 MediaObject::currentTime() const
{
IMPLEMENTED_SILENT;
- const_cast<MediaObject *>(this)->updateCurrentTime();
+ const_cast<MediaObject *>(this)->updateCurrentTime();
return m_currentTime;
}
@@ -567,19 +664,24 @@ void MediaObject::updateCurrentTime()
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
quint64 total = m_videoPlayer->duration();
- // Check if it's time to emit aboutToFinish:
- quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
- if (lastUpdateTime < mark && mark <= m_currentTime)
- emit aboutToFinish();
-
- // Check if it's time to emit prefinishMarkReached:
- mark = qMax(quint64(0), total - m_prefinishMark);
- if (lastUpdateTime < mark && mark <= m_currentTime)
- emit prefinishMarkReached(total - m_currentTime);
+ if (m_videoPlayer->currentTrack() < m_videoPlayer->trackCount() - 1){
+ // There are still more tracks to play after the current track.
+ if (m_autoplayTitles) {
+ if (lastUpdateTime < m_currentTime && m_currentTime == total)
+ setCurrentTrack(m_videoPlayer->currentTrack() + 1);
+ }
+ } else if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
+ // There is no more sources or tracks to play after the current source.
+ // Check if it's time to emit aboutToFinish:
+ quint32 mark = qMax(quint64(0), qMin(total, total + m_transitionTime - 2000));
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit aboutToFinish();
+
+ // Check if it's time to emit prefinishMarkReached:
+ mark = qMax(quint64(0), total - m_prefinishMark);
+ if (lastUpdateTime < mark && mark <= m_currentTime)
+ emit prefinishMarkReached(total - m_currentTime);
- if (m_nextVideoPlayer->state() == QuickTimeVideoPlayer::NoMedia){
- // There is no next source in que.
- // Check if it's time to emit finished:
if (lastUpdateTime < m_currentTime && m_currentTime == total){
emit finished();
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
@@ -589,7 +691,7 @@ void MediaObject::updateCurrentTime()
} else {
// We have a next source.
// Check if it's time to swap to next source:
- mark = qMax(quint64(0), total + m_transitionTime);
+ quint32 mark = qMax(quint64(0), total + m_transitionTime);
if (m_waitNextSwap && m_state == Phonon::PlayingState &&
m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
swapCurrentWithNext(0);
@@ -692,14 +794,14 @@ bool MediaObject::setAudioDeviceOnMovie(int id)
void MediaObject::updateCrossFade()
{
- m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
+ m_mediaObjectAudioNode->updateCrossFade(m_currentTime);
// Clean-up previous movie if done fading:
if (m_mediaObjectAudioNode->m_fadeDuration == 0){
if (m_nextVideoPlayer->isPlaying() || m_nextAudioPlayer->isPlaying()){
- m_nextVideoPlayer->unsetVideo();
+ m_nextVideoPlayer->unsetCurrentMediaSource();
m_nextAudioPlayer->unsetVideoPlayer();
}
- }
+ }
}
void MediaObject::updateBufferStatus()
@@ -728,7 +830,7 @@ void MediaObject::updateVideoFrames()
// Draw next frame if awailable:
if (m_videoPlayer->videoFrameChanged()){
updateLipSynch(50);
- VideoFrame frame(m_videoPlayer);
+ VideoFrame frame(m_videoPlayer);
if (m_nextVideoPlayer->isPlaying()
&& m_nextVideoPlayer->hasVideo()
&& isCrossFading()){
@@ -736,9 +838,9 @@ void MediaObject::updateVideoFrames()
frame.setBackgroundFrame(bgFrame);
frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
}
-
+
// Send the frame through the graph:
- updateVideo(frame);
+ updateVideo(frame);
checkForError();
}
}
@@ -749,7 +851,7 @@ void MediaObject::updateLipSynch(int allowedOffset)
return;
if (m_videoSinkList.isEmpty() || m_audioSinkList.isEmpty())
return;
-
+
if (m_videoPlayer->hasVideo()){
qint64 diff = m_audioPlayer->currentTime() - m_videoPlayer->currentTime();
if (-allowedOffset > diff || diff > allowedOffset)
@@ -763,16 +865,6 @@ void MediaObject::updateLipSynch(int allowedOffset)
}
}
-void MediaObject::bufferAudioVideo()
-{
- long nextVideoUpdate = m_videoPlayer->hasVideo() ? 30 : INT_MAX;
- long nextAudioUpdate = m_audioPlayer->regularTaskFrequency();
- updateAudioBuffers();
- updateVideoFrames();
- if (m_state == Phonon::PlayingState)
- updateTimer(m_bufferTimer, qMin(nextVideoUpdate, nextAudioUpdate));
-}
-
void MediaObject::updateRapidly()
{
updateCurrentTime();
@@ -797,8 +889,8 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
synchAudioVideo();
checkForError();
m_mediaObjectAudioNode->setMute(false);
- if (m_state == Phonon::PlayingState)
- bufferAudioVideo();
+ if (m_state == Phonon::PlayingState)
+ restartAudioVideoTimers();
break;
case MediaNodeEvent::AudioGraphCannotPlay:
case MediaNodeEvent::AudioGraphInitialized:
@@ -809,7 +901,7 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
checkForError();
m_mediaObjectAudioNode->setMute(false);
}
- break;
+ break;
default:
break;
}
@@ -818,29 +910,67 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
bool MediaObject::event(QEvent *event)
{
switch (event->type()){
- case QEvent::Timer: {
- QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
- if (timerEvent->timerId() == m_rapidTimer)
+#if QT_ALLOW_QUICKTIME
+ case QEvent::User:{
+ m_displayLinkMutex.lock();
+ m_pendingDisplayLinkEvent = false;
+ m_displayLinkMutex.unlock();
+ updateVideoFrames();
+ break; }
+#endif
+ case QEvent::Timer:{
+ int timerId = static_cast<QTimerEvent *>(event)->timerId();
+ if (timerId == m_rapidTimer)
updateRapidly();
- else if (timerEvent->timerId() == m_tickTimer)
+ else if (timerId == m_tickTimer)
emit tick(currentTime());
- else if (timerEvent->timerId() == m_bufferTimer)
- bufferAudioVideo();
- }
- break;
+ else if (timerId == m_videoTimer)
+ updateVideoFrames();
+ else if (timerId == m_audioTimer)
+ updateAudioBuffers();
+ break; }
default:
break;
}
return QObject::event(event);
}
-bool MediaObject::hasInterface(Interface /*interface*/) const
+void MediaObject::setCurrentTrack(int track)
{
- return false;
+ if (track == m_videoPlayer->currentTrack() || track < 0 || track >= m_videoPlayer->trackCount())
+ return;
+
+ m_videoPlayer->setCurrentTrack(track);
+ emit titleChanged(track);
+ emit metaDataChanged(m_videoPlayer->metaData());
}
-QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
+bool MediaObject::hasInterface(Interface iface) const
{
+ return iface == AddonInterface::TitleInterface;
+}
+
+QVariant MediaObject::interfaceCall(Interface iface, int command, const QList<QVariant> &params)
+{
+ switch (iface) {
+ case TitleInterface:
+ switch (command) {
+ case availableTitles:
+ return m_videoPlayer->trackCount();
+ case title:
+ return m_videoPlayer->currentTrack();
+ case setTitle:
+ setCurrentTrack(params.first().toInt());
+ break;
+ case autoplayTitles:
+ return m_autoplayTitles;
+ case setAutoplayTitles:
+ m_autoplayTitles = params.first().toBool();
+ break;
+ }
+ default:
+ break;
+ }
return QVariant();
}
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.h b/src/3rdparty/phonon/qt7/quicktimemetadata.h
index d524183..c589535 100644
--- a/src/3rdparty/phonon/qt7/quicktimemetadata.h
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.h
@@ -38,10 +38,8 @@ namespace QT7
class QuickTimeMetaData
{
public:
- QuickTimeMetaData();
- virtual ~QuickTimeMetaData();
-
- void setVideo(QuickTimeVideoPlayer *videoPlayer);
+ QuickTimeMetaData(QuickTimeVideoPlayer *videoPlayer);
+ void update();
QMultiMap<QString, QString> metaData();
private:
@@ -49,6 +47,8 @@ namespace QT7
bool m_movieChanged;
QuickTimeVideoPlayer *m_videoPlayer;
void readMetaData();
+ void guessMetaDataForCD();
+ void readMetaDataFromMovie();
#ifdef QUICKTIME_C_API_AVAILABLE
QString stripCopyRightSymbol(const QString &key);
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.mm b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
index 851e707..2dcc152 100644
--- a/src/3rdparty/phonon/qt7/quicktimemetadata.mm
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
@@ -15,6 +15,7 @@
along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <QtCore/QFileInfo>
#include "quicktimemetadata.h"
#include "quicktimevideoplayer.h"
@@ -25,19 +26,14 @@ namespace Phonon
namespace QT7
{
-QuickTimeMetaData::QuickTimeMetaData()
+QuickTimeMetaData::QuickTimeMetaData(QuickTimeVideoPlayer *videoPlayer)
{
- m_videoPlayer = 0;
+ m_videoPlayer = videoPlayer;
m_movieChanged = false;
}
-QuickTimeMetaData::~QuickTimeMetaData()
+void QuickTimeMetaData::update()
{
-}
-
-void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer)
-{
- m_videoPlayer = videoPlayer;
m_movieChanged = true;
m_metaData.clear();
}
@@ -145,14 +141,22 @@ void QuickTimeMetaData::readFormattedData(QTMetaDataRef metaDataRef, OSType form
#endif // QUICKTIME_C_API_AVAILABLE
-void QuickTimeMetaData::readMetaData()
+void QuickTimeMetaData::guessMetaDataForCD()
+{
+ QString album = QFileInfo(m_videoPlayer->movieCompactDiscPath()).fileName();
+ QString title = QFileInfo(m_videoPlayer->currentTrackPath()).fileName();
+ title = title.left(title.lastIndexOf('.'));
+ m_metaData.insert(QLatin1String("ALBUM"), album);
+ m_metaData.insert(QLatin1String("TITLE"), title);
+ m_metaData.insert(QLatin1String("TRACKNUMBER"), QString::number(m_videoPlayer->currentTrack()));
+}
+
+void QuickTimeMetaData::readMetaDataFromMovie()
{
- if (!m_videoPlayer)
- return;
QMultiMap<QString, QString> metaMap;
-
+
#ifdef QUICKTIME_C_API_AVAILABLE
- QTMetaDataRef metaDataRef;
+ QTMetaDataRef metaDataRef;
OSStatus err = QTCopyMovieMetaData([m_videoPlayer->qtMovie() quickTimeMovie], &metaDataRef);
BACKEND_ASSERT2(err == noErr, "Could not read QuickTime meta data", NORMAL_ERROR)
@@ -173,6 +177,17 @@ void QuickTimeMetaData::readMetaData()
m_metaData.insert(QLatin1String("DESCRIPTION"), metaMap.value(QLatin1String("des")));
}
+void QuickTimeMetaData::readMetaData()
+{
+ if (!m_videoPlayer)
+ return;
+
+ if (m_videoPlayer->mediaSource().type() == Phonon::MediaSource::Disc)
+ guessMetaDataForCD();
+ else
+ readMetaDataFromMovie();
+}
+
QMultiMap<QString, QString> QuickTimeMetaData::metaData()
{
if (m_videoPlayer && m_videoPlayer->hasMovie() && m_movieChanged)
diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
index b80570a..98eacb5 100644
--- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
@@ -39,6 +39,7 @@ namespace Phonon
namespace QT7
{
class QuickTimeStreamReader;
+ class QuickTimeMetaData;
class VideoRenderWidgetQTMovieView;
class QuickTimeVideoPlayer : QObject
@@ -56,7 +57,7 @@ namespace QT7
void setMediaSource(const MediaSource &source);
MediaSource mediaSource() const;
- void unsetVideo();
+ void unsetCurrentMediaSource();
void play();
void pause();
@@ -67,11 +68,13 @@ namespace QT7
GLuint currentFrameAsGLTexture();
void *currentFrameAsCIImage();
QImage currentFrameAsQImage();
+ void releaseImageCache();
QRect videoRect() const;
quint64 duration() const;
quint64 currentTime() const;
long timeScale() const;
+ float staticFps();
QString currentTimeString();
void setColors(qreal brightness = 0, qreal contrast = 1, qreal hue = 0, qreal saturation = 1);
@@ -84,6 +87,7 @@ namespace QT7
bool setAudioDevice(int id);
void setPlaybackRate(float rate);
QTMovie *qtMovie() const;
+ QMultiMap<QString, QString> metaData();
float playbackRate() const;
float prefferedPlaybackRate() const;
@@ -103,6 +107,12 @@ namespace QT7
float percentageLoaded();
quint64 timeLoaded();
+ int trackCount() const;
+ int currentTrack() const;
+ void setCurrentTrack(int track);
+ QString movieCompactDiscPath() const;
+ QString currentTrackPath() const;
+
static QString timeToString(quint64 ms);
// Help functions when drawing to more that one widget in cocoa 64:
@@ -116,6 +126,10 @@ namespace QT7
QTMovie *m_QTMovie;
State m_state;
QGLPixelBuffer *m_QImagePixelBuffer;
+ QuickTimeMetaData *m_metaData;
+
+ CVOpenGLTextureRef m_cachedCVTextureRef;
+ QImage m_cachedQImage;
bool m_playbackRateSat;
bool m_isDrmProtected;
@@ -126,13 +140,18 @@ namespace QT7
float m_masterVolume;
float m_relativeVolume;
float m_playbackRate;
+ float m_staticFps;
quint64 m_currentTime;
MediaSource m_mediaSource;
+
void *m_primaryRenderingCIImage;
qreal m_brightness;
qreal m_contrast;
qreal m_hue;
qreal m_saturation;
+ NSArray *m_folderTracks;
+ int m_currentTrack;
+ QString m_movieCompactDiscPath;
#ifdef QUICKTIME_C_API_AVAILABLE
QTVisualContextRef m_visualContext;
@@ -140,20 +159,26 @@ namespace QT7
VideoFrame m_currentFrame;
QuickTimeStreamReader *m_streamReader;
+ void prepareCurrentMovieForPlayback();
void createVisualContext();
void openMovieFromCurrentMediaSource();
void openMovieFromDataRef(QTDataReference *dataRef);
void openMovieFromFile();
void openMovieFromUrl();
void openMovieFromStream();
+ void openMovieFromCompactDisc();
void openMovieFromData(QByteArray *data, char *fileType);
void openMovieFromDataGuessType(QByteArray *data);
QString mediaSourcePath();
bool codecExistsAccordingToSuffix(const QString &fileName);
+ NSString* pathToCompactDisc();
+ bool isCompactDisc(NSString *path);
+ NSArray* scanFolder(NSString *path);
void setError(NSError *error);
bool errorOccured();
void readProtection();
+ void calculateStaticFps();
void checkIfVideoAwailable();
bool movieNotLoaded();
void waitStatePlayable();
diff --git a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
index 3f76132..23c76e3 100644
--- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
@@ -20,6 +20,7 @@
#include "videowidget.h"
#include "audiodevice.h"
#include "quicktimestreamreader.h"
+#include "quicktimemetadata.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QEventLoop>
@@ -52,6 +53,7 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
{
m_state = NoMedia;
m_mediaSource = MediaSource();
+ m_metaData = new QuickTimeMetaData(this);
m_QTMovie = 0;
m_streamReader = 0;
m_playbackRate = 1.0f;
@@ -61,12 +63,16 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
m_mute = false;
m_audioEnabled = false;
m_hasVideo = false;
+ m_staticFps = 0;
m_playbackRateSat = false;
m_isDrmProtected = false;
m_isDrmAuthorized = true;
m_primaryRenderingTarget = 0;
m_primaryRenderingCIImage = 0;
m_QImagePixelBuffer = 0;
+ m_cachedCVTextureRef = 0;
+ m_folderTracks = 0;
+ m_currentTrack = 0;
#ifdef QUICKTIME_C_API_AVAILABLE
OSStatus err = EnterMovies();
@@ -77,7 +83,9 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
QuickTimeVideoPlayer::~QuickTimeVideoPlayer()
{
- unsetVideo();
+ PhononAutoReleasePool pool;
+ unsetCurrentMediaSource();
+ delete m_metaData;
[(NSObject*)m_primaryRenderingTarget release];
m_primaryRenderingTarget = 0;
#ifdef QUICKTIME_C_API_AVAILABLE
@@ -86,6 +94,15 @@ QuickTimeVideoPlayer::~QuickTimeVideoPlayer()
#endif
}
+void QuickTimeVideoPlayer::releaseImageCache()
+{
+ if (m_cachedCVTextureRef){
+ CVOpenGLTextureRelease(m_cachedCVTextureRef);
+ m_cachedCVTextureRef = 0;
+ }
+ m_cachedQImage = QImage();
+}
+
void QuickTimeVideoPlayer::createVisualContext()
{
#ifdef QUICKTIME_C_API_AVAILABLE
@@ -125,7 +142,10 @@ bool QuickTimeVideoPlayer::videoFrameChanged()
return false;
QTVisualContextTask(m_visualContext);
- return QTVisualContextIsNewImageAvailable(m_visualContext, 0);
+ bool changed = QTVisualContextIsNewImageAvailable(m_visualContext, 0);
+ if (changed)
+ releaseImageCache();
+ return changed;
#elif defined(QT_MAC_USE_COCOA)
return true;
@@ -140,10 +160,11 @@ CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture()
#ifdef QUICKTIME_C_API_AVAILABLE
if (!m_visualContext)
return 0;
- CVOpenGLTextureRef texture = 0;
- OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &texture);
- BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0)
- return texture;
+ if (!m_cachedCVTextureRef){
+ OSStatus err = QTVisualContextCopyImageForTime(m_visualContext, 0, 0, &m_cachedCVTextureRef);
+ BACKEND_ASSERT3(err == noErr, "Could not copy image for time in QuickTime player", FATAL_ERROR, 0)
+ }
+ return m_cachedCVTextureRef;
#else
return 0;
@@ -152,6 +173,9 @@ CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture()
QImage QuickTimeVideoPlayer::currentFrameAsQImage()
{
+ if (!m_cachedQImage.isNull())
+ return m_cachedQImage;
+
#ifdef QUICKTIME_C_API_AVAILABLE
QGLContext *prevContext = const_cast<QGLContext *>(QGLContext::currentContext());
CVOpenGLTextureRef texture = currentFrameAsCVTexture();
@@ -181,12 +205,11 @@ QImage QuickTimeVideoPlayer::currentFrameAsQImage()
glVertex2i(-1, -1);
glEnd();
- QImage image = m_QImagePixelBuffer->toImage();
- CVOpenGLTextureRelease(texture);
+ m_cachedQImage = m_QImagePixelBuffer->toImage();
// Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail.
// So we store, and restore, the context our selves:
prevContext->makeCurrent();
- return image;
+ return m_cachedQImage;
#else
CIImage *img = (CIImage *)currentFrameAsCIImage();
if (!img)
@@ -195,10 +218,10 @@ QImage QuickTimeVideoPlayer::currentFrameAsQImage()
NSBitmapImageRep* bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
CGRect bounds = [img extent];
QImage qImg([bitmap bitmapData], bounds.size.width, bounds.size.height, QImage::Format_ARGB32);
- QImage swapped = qImg.rgbSwapped();
+ m_cachedQImage = qImg.rgbSwapped();
[bitmap release];
[img release];
- return swapped;
+ return m_cachedQImage;
#endif
}
@@ -250,8 +273,7 @@ void *QuickTimeVideoPlayer::currentFrameAsCIImage()
#ifdef QUICKTIME_C_API_AVAILABLE
CVOpenGLTextureRef cvImg = currentFrameAsCVTexture();
CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg];
- CVOpenGLTextureRelease(cvImg);
- return img;
+ return img;
#else
return 0;
#endif
@@ -273,7 +295,7 @@ GLuint QuickTimeVideoPlayer::currentFrameAsGLTexture()
int samplesPerPixel = [bitmap samplesPerPixel];
if (![bitmap isPlanar] && (samplesPerPixel == 3 || samplesPerPixel == 4)){
- glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
+ glTexImage2D(GL_TEXTURE_RECTANGLE_EXT, 0,
samplesPerPixel == 4 ? GL_RGBA8 : GL_RGB8,
[bitmap pixelsWide], [bitmap pixelsHigh],
0, samplesPerPixel == 4 ? GL_RGBA : GL_RGB,
@@ -302,7 +324,7 @@ void QuickTimeVideoPlayer::setVolume(float masterVolume, float relativeVolume)
m_masterVolume = masterVolume;
m_relativeVolume = relativeVolume;
if (!m_QTMovie || !m_audioEnabled || m_mute)
- return;
+ return;
[m_QTMovie setVolume:(m_masterVolume * m_relativeVolume)];
}
@@ -313,7 +335,7 @@ void QuickTimeVideoPlayer::setMute(bool mute)
return;
// Work-around bug that happends if you set/unset mute
- // before movie is playing, and audio is not played
+ // before movie is playing, and audio is not played
// through graph. Then audio is delayed.
[m_QTMovie setMuted:mute];
[m_QTMovie setVolume:(mute ? 0 : m_masterVolume * m_relativeVolume)];
@@ -326,7 +348,7 @@ void QuickTimeVideoPlayer::enableAudio(bool enable)
return;
// Work-around bug that happends if you set/unset mute
- // before movie is playing, and audio is not played
+ // before movie is playing, and audio is not played
// through graph. Then audio is delayed.
[m_QTMovie setMuted:(!enable || m_mute)];
[m_QTMovie setVolume:((!enable || m_mute) ? 0 : m_masterVolume * m_relativeVolume)];
@@ -345,7 +367,7 @@ bool QuickTimeVideoPlayer::setAudioDevice(int id)
#ifdef QUICKTIME_C_API_AVAILABLE
// The following code will not work for some media codecs that
// typically mingle audio/video frames (e.g mpeg).
- CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id));
+ CFStringRef idString = PhononCFString::toCFStringRef(AudioDevice::deviceUID(id));
QTAudioContextRef context;
QTAudioContextCreateForAudioDevice(kCFAllocatorDefault, idString, 0, &context);
OSStatus err = SetMovieAudioContext([m_QTMovie quickTimeMovie], context);
@@ -369,11 +391,16 @@ void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue
contrast += 1;
saturation += 1;
+ if (m_brightness == brightness
+ && m_contrast == contrast
+ && m_hue == hue
+ && m_saturation == saturation)
+ return;
+
m_brightness = brightness;
m_contrast = contrast;
m_hue = hue;
m_saturation = saturation;
-
#ifdef QUICKTIME_C_API_AVAILABLE
Float32 value;
value = brightness;
@@ -385,6 +412,7 @@ void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue
value = saturation;
SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0);
#endif
+ releaseImageCache();
}
QRect QuickTimeVideoPlayer::videoRect() const
@@ -397,7 +425,7 @@ QRect QuickTimeVideoPlayer::videoRect() const
return QRect(0, 0, size.width, size.height);
}
-void QuickTimeVideoPlayer::unsetVideo()
+void QuickTimeVideoPlayer::unsetCurrentMediaSource()
{
if (!m_QTMovie)
return;
@@ -410,11 +438,17 @@ void QuickTimeVideoPlayer::unsetVideo()
m_state = NoMedia;
m_isDrmProtected = false;
m_isDrmAuthorized = true;
+ m_hasVideo = false;
+ m_staticFps = 0;
m_mediaSource = MediaSource();
+ m_movieCompactDiscPath.clear();
[(CIImage *)m_primaryRenderingCIImage release];
m_primaryRenderingCIImage = 0;
delete m_QImagePixelBuffer;
m_QImagePixelBuffer = 0;
+ releaseImageCache();
+ [m_folderTracks release];
+ m_folderTracks = 0;
}
QuickTimeVideoPlayer::State QuickTimeVideoPlayer::state() const
@@ -524,18 +558,25 @@ bool QuickTimeVideoPlayer::codecExistsAccordingToSuffix(const QString &fileName)
void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource)
{
PhononAutoReleasePool pool;
- unsetVideo();
+ unsetCurrentMediaSource();
+
m_mediaSource = mediaSource;
if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){
m_state = NoMedia;
return;
}
+
openMovieFromCurrentMediaSource();
if (errorOccured()){
- unsetVideo();
+ unsetCurrentMediaSource();
return;
}
+ prepareCurrentMovieForPlayback();
+}
+
+void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback()
+{
#ifdef QUICKTIME_C_API_AVAILABLE
if (m_visualContext)
SetMovieVisualContext([m_QTMovie quickTimeMovie], m_visualContext);
@@ -543,23 +584,25 @@ void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource)
waitStatePlayable();
if (errorOccured()){
- unsetVideo();
+ unsetCurrentMediaSource();
return;
}
readProtection();
preRollMovie();
if (errorOccured()){
- unsetVideo();
+ unsetCurrentMediaSource();
return;
}
if (!m_playbackRateSat)
m_playbackRate = prefferedPlaybackRate();
checkIfVideoAwailable();
+ calculateStaticFps();
enableAudio(m_audioEnabled);
setMute(m_mute);
setVolume(m_masterVolume, m_relativeVolume);
+ m_metaData->update();
pause();
}
@@ -573,7 +616,7 @@ void QuickTimeVideoPlayer::openMovieFromCurrentMediaSource()
openMovieFromUrl();
break;
case MediaSource::Disc:
- CASE_UNSUPPORTED("Could not open media source.", FATAL_ERROR)
+ openMovieFromCompactDisc();
break;
case MediaSource::Stream:
openMovieFromStream();
@@ -635,7 +678,7 @@ void QuickTimeVideoPlayer::openMovieFromDataGuessType(QByteArray *data)
// than using e.g [QTMovie movieFileTypes:QTIncludeCommonTypes]. Some
// codecs *think* they can decode the stream, and crash...
#define TryOpenMovieWithCodec(type) gClearError(); \
- openMovieFromData(data, "."type); \
+ openMovieFromData(data, (char *)"."type); \
if (m_QTMovie) return;
TryOpenMovieWithCodec("avi");
@@ -675,6 +718,50 @@ void QuickTimeVideoPlayer::openMovieFromStream()
openMovieFromDataGuessType(m_streamReader->pointerToData());
}
+typedef void (*qt_sighandler_t)(int);
+static void sigtest(int) {
+ qApp->exit(0);
+}
+
+void QuickTimeVideoPlayer::openMovieFromCompactDisc()
+{
+ // Interrupting the application while the device is open
+ // causes the application to hang. So we need to handle
+ // this in a more graceful way:
+ qt_sighandler_t hndl = signal(SIGINT, sigtest);
+ if (hndl)
+ signal(SIGINT, hndl);
+
+ PhononAutoReleasePool pool;
+ NSString *cd = 0;
+ QString devName = m_mediaSource.deviceName();
+ if (devName.isEmpty()) {
+ cd = pathToCompactDisc();
+ if (!cd) {
+ SET_ERROR("Could not open media source.", NORMAL_ERROR)
+ return;
+ }
+ m_movieCompactDiscPath = PhononCFString::toQString(reinterpret_cast<CFStringRef>(cd));
+ } else {
+ if (!QFileInfo(devName).isAbsolute())
+ devName = QLatin1String("/Volumes/") + devName;
+ cd = [reinterpret_cast<const NSString *>(PhononCFString::toCFStringRef(devName)) autorelease];
+ if (!isCompactDisc(cd)) {
+ SET_ERROR("Could not open media source.", NORMAL_ERROR)
+ return;
+ }
+ m_movieCompactDiscPath = devName;
+ }
+
+ m_folderTracks = [scanFolder(cd) retain];
+ setCurrentTrack(0);
+}
+
+QString QuickTimeVideoPlayer::movieCompactDiscPath() const
+{
+ return m_movieCompactDiscPath;
+}
+
MediaSource QuickTimeVideoPlayer::mediaSource() const
{
return m_mediaSource;
@@ -720,6 +807,44 @@ long QuickTimeVideoPlayer::timeScale() const
return [[m_QTMovie attributeForKey:@"QTMovieTimeScaleAttribute"] longValue];
}
+float QuickTimeVideoPlayer::staticFps()
+{
+ return m_staticFps;
+}
+
+void QuickTimeVideoPlayer::calculateStaticFps()
+{
+ if (!m_hasVideo){
+ m_staticFps = 0;
+ return;
+ }
+
+#ifdef QT_ALLOW_QUICKTIME
+ Boolean isMpeg = false;
+ Track videoTrack = GetMovieIndTrackType([m_QTMovie quickTimeMovie], 1,
+ FOUR_CHAR_CODE('vfrr'), // 'vfrr' means: has frame rate
+ movieTrackCharacteristic | movieTrackEnabledOnly);
+ Media media = GetTrackMedia(videoTrack);
+ MediaHandler mediaH = GetMediaHandler(media);
+ MediaHasCharacteristic(mediaH, FOUR_CHAR_CODE('mpeg'), &isMpeg);
+
+ if (isMpeg){
+ MHInfoEncodedFrameRateRecord frameRate;
+ Size frameRateSize = sizeof(frameRate);
+ MediaGetPublicInfo(mediaH, kMHInfoEncodedFrameRate, &frameRate, &frameRateSize);
+ m_staticFps = float(Fix2X(frameRate.encodedFrameRate));
+ } else {
+ Media media = GetTrackMedia(videoTrack);
+ long sampleCount = GetMediaSampleCount(media);
+ TimeValue64 duration = GetMediaDisplayDuration(media);
+ TimeValue64 timeScale = GetMediaTimeScale(media);
+ m_staticFps = float((double)sampleCount * (double)timeScale / (double)duration);
+ }
+#else
+ m_staticFps = 30.0f;
+#endif
+}
+
QString QuickTimeVideoPlayer::timeToString(quint64 ms)
{
int sec = ms/1000;
@@ -950,6 +1075,94 @@ void QuickTimeVideoPlayer::readProtection()
}
}
+QMultiMap<QString, QString> QuickTimeVideoPlayer::metaData()
+{
+ return m_metaData->metaData();
+}
+
+int QuickTimeVideoPlayer::trackCount() const
+{
+ if (!m_folderTracks)
+ return 0;
+ return [m_folderTracks count];
+}
+
+int QuickTimeVideoPlayer::currentTrack() const
+{
+ return m_currentTrack;
+}
+
+QString QuickTimeVideoPlayer::currentTrackPath() const
+{
+ if (!m_folderTracks)
+ return QString();
+
+ PhononAutoReleasePool pool;
+ NSString *trackPath = [m_folderTracks objectAtIndex:m_currentTrack];
+ return PhononCFString::toQString(reinterpret_cast<CFStringRef>(trackPath));
+}
+
+NSString* QuickTimeVideoPlayer::pathToCompactDisc()
+{
+ PhononAutoReleasePool pool;
+ NSArray *devices = [[NSWorkspace sharedWorkspace] mountedRemovableMedia];
+ for (unsigned int i=0; i<[devices count]; ++i) {
+ NSString *dev = [devices objectAtIndex:i];
+ if (isCompactDisc(dev))
+ return [dev retain];
+ }
+ return 0;
+}
+
+bool QuickTimeVideoPlayer::isCompactDisc(NSString *path)
+{
+ PhononAutoReleasePool pool;
+ NSString *type = [NSString string];
+ [[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:path
+ isRemovable:0
+ isWritable:0
+ isUnmountable:0
+ description:0
+ type:&type];
+ return [type hasPrefix:@"cdd"];
+}
+
+NSArray* QuickTimeVideoPlayer::scanFolder(NSString *path)
+{
+ NSMutableArray *tracks = [NSMutableArray arrayWithCapacity:20];
+ if (!path)
+ return tracks;
+
+ NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtPath:path];
+ while (NSString *track = [enumerator nextObject]) {
+ if (![track hasPrefix:@"."])
+ [tracks addObject:[path stringByAppendingPathComponent:track]];
+ }
+ return tracks;
+}
+
+void QuickTimeVideoPlayer::setCurrentTrack(int track)
+{
+ PhononAutoReleasePool pool;
+ [m_QTMovie release];
+ m_QTMovie = 0;
+ m_currentTime = 0;
+ m_currentTrack = track;
+
+ if (!m_folderTracks)
+ return;
+ if (track < 0 || track >= (int)[m_folderTracks count])
+ return;
+
+ NSString *trackPath = [m_folderTracks objectAtIndex:track];
+ QTDataReference *dataRef = [QTDataReference dataReferenceWithReferenceToFile:trackPath];
+ State currentState = m_state;
+ openMovieFromDataRef(dataRef);
+ prepareCurrentMovieForPlayback();
+ if (currentState == Playing)
+ play();
+}
+
}}
QT_END_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/videoframe.mm b/src/3rdparty/phonon/qt7/videoframe.mm
index 92a3cd5..7b67b5e 100644
--- a/src/3rdparty/phonon/qt7/videoframe.mm
+++ b/src/3rdparty/phonon/qt7/videoframe.mm
@@ -20,6 +20,8 @@
#import <QuartzCore/CIFilter.h>
#import <QuartzCore/CIContext.h>
+//#define CACHE_CV_TEXTURE
+
QT_BEGIN_NAMESPACE
namespace Phonon
@@ -70,7 +72,9 @@ namespace QT7
void VideoFrame::copyMembers(const VideoFrame& frame)
{
+#ifdef CACHE_CV_TEXTURE
m_cachedCVTextureRef = frame.m_cachedCVTextureRef;
+#endif
m_cachedCIImage = frame.m_cachedCIImage;
m_cachedQImage = frame.m_cachedQImage;
m_cachedNSBitmap = frame.m_cachedNSBitmap;
@@ -105,11 +109,20 @@ namespace QT7
CVOpenGLTextureRef VideoFrame::cachedCVTexture() const
{
+#ifdef CACHE_CV_TEXTURE
if (!m_cachedCVTextureRef && m_videoPlayer){
m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
(const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = m_videoPlayer->currentFrameAsCVTexture();
+ CVOpenGLTextureRetain((const_cast<VideoFrame *>(this))->m_cachedCVTextureRef);
}
return m_cachedCVTextureRef;
+#else
+ if (m_videoPlayer){
+ m_videoPlayer->setColors(m_brightness, m_contrast, m_hue, m_saturation);
+ return m_videoPlayer->currentFrameAsCVTexture();
+ }
+ return 0;
+#endif
}
void *VideoFrame::cachedCIImage() const
@@ -329,10 +342,12 @@ namespace QT7
void VideoFrame::invalidateImage() const
{
+#ifdef CACHE_CV_TEXTURE
if (m_cachedCVTextureRef){
CVOpenGLTextureRelease(m_cachedCVTextureRef);
(const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
}
+#endif
if (m_cachedCIImage){
[(CIImage *) m_cachedCIImage release];
(const_cast<VideoFrame *>(this))->m_cachedCIImage = 0;
@@ -346,8 +361,10 @@ namespace QT7
void VideoFrame::retain() const
{
+#ifdef CACHE_CV_TEXTURE
if (m_cachedCVTextureRef)
CVOpenGLTextureRetain(m_cachedCVTextureRef);
+#endif
if (m_cachedCIImage)
[(CIImage *) m_cachedCIImage retain];
if (m_backgroundFrame)
@@ -358,8 +375,12 @@ namespace QT7
void VideoFrame::release() const
{
- if (m_cachedCVTextureRef)
+#ifdef CACHE_CV_TEXTURE
+ if (m_cachedCVTextureRef){
CVOpenGLTextureRelease(m_cachedCVTextureRef);
+ (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
+ }
+#endif
if (m_cachedCIImage)
[(CIImage *) m_cachedCIImage release];
if (m_backgroundFrame)
@@ -368,7 +389,6 @@ namespace QT7
[m_cachedNSBitmap release];
(const_cast<VideoFrame *>(this))->m_backgroundFrame = 0;
- (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
(const_cast<VideoFrame *>(this))->m_cachedCIImage = 0;
(const_cast<VideoFrame *>(this))->m_cachedNSBitmap = 0;
}
diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h
index e6e8f23..5b849e4 100644
--- a/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h
+++ b/src/3rdparty/webkit/JavaScriptCore/wtf/unicode/Unicode.h
@@ -32,6 +32,6 @@
#error "Unknown Unicode implementation"
#endif
-COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes);
+COMPILE_ASSERT(sizeof(UChar) == 2, UCharIsTwoBytes)
#endif // WTF_UNICODE_H
diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp b/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp
index 4b94a94..26323e8 100644
--- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp
+++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_instance.cpp
@@ -337,7 +337,7 @@ JSValuePtr QtField::valueFromInstance(ExecState* exec, const Instance* inst) con
return ret;
} else {
- QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
+ QString msg = QString::fromLatin1("cannot access member `%1' of deleted QObject").arg(QLatin1String(name()));
return throwError(exec, GeneralError, msg.toLatin1().constData());
}
}
@@ -362,7 +362,7 @@ void QtField::setValueToInstance(ExecState* exec, const Instance* inst, JSValueP
} else if (m_type == DynamicProperty)
obj->setProperty(m_dynamicProperty.constData(), val);
} else {
- QString msg = QString(QLatin1String("cannot access member `%1' of deleted QObject")).arg(QLatin1String(name()));
+ QString msg = QString::fromLatin1("cannot access member `%1' of deleted QObject").arg(QLatin1String(name()));
throwError(exec, GeneralError, msg.toLatin1().constData());
}
}
diff --git a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp
index c7ba6c2..5a73dc7 100644
--- a/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp
+++ b/src/3rdparty/webkit/WebCore/bridge/qt/qt_runtime.cpp
@@ -1515,7 +1515,7 @@ JSValuePtr QtRuntimeConnectionMethod::call(ExecState* exec, JSObject* functionOb
bool ok = QMetaObject::connect(sender, signalIndex, conn, conn->metaObject()->methodOffset());
if (!ok) {
delete conn;
- QString msg = QString(QLatin1String("QtMetaMethod.connect: failed to connect to %1::%2()"))
+ QString msg = QString::fromLatin1("QtMetaMethod.connect: failed to connect to %1::%2()")
.arg(QLatin1String(sender->metaObject()->className()))
.arg(QLatin1String(d->m_signature));
return throwError(exec, GeneralError, msg.toLatin1().constData());
@@ -1541,14 +1541,14 @@ JSValuePtr QtRuntimeConnectionMethod::call(ExecState* exec, JSObject* functionOb
}
if (!ret) {
- QString msg = QString(QLatin1String("QtMetaMethod.disconnect: failed to disconnect from %1::%2()"))
+ QString msg = QString::fromLatin1("QtMetaMethod.disconnect: failed to disconnect from %1::%2()")
.arg(QLatin1String(sender->metaObject()->className()))
.arg(QLatin1String(d->m_signature));
return throwError(exec, GeneralError, msg.toLatin1().constData());
}
}
} else {
- QString msg = QString(QLatin1String("QtMetaMethod.%1: %2::%3() is not a signal"))
+ QString msg = QString::fromLatin1("QtMetaMethod.%1: %2::%3() is not a signal")
.arg(QLatin1String(d->m_isConnect ? "connect": "disconnect"))
.arg(QLatin1String(sender->metaObject()->className()))
.arg(QLatin1String(d->m_signature));
diff --git a/src/3rdparty/webkit/WebCore/dom/XMLTokenizerQt.cpp b/src/3rdparty/webkit/WebCore/dom/XMLTokenizerQt.cpp
index 30926e1..39ccefe 100644
--- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizerQt.cpp
+++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizerQt.cpp
@@ -357,7 +357,7 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
state.gotAttributes = false;
QXmlStreamReader stream;
- QString dummy = QString(QLatin1String("<?xml version=\"1.0\"?><attrs %1 />")).arg(string);
+ QString dummy = QString::fromLatin1("<?xml version=\"1.0\"?><attrs %1 />").arg(string);
stream.addData(dummy);
while (!stream.atEnd()) {
stream.readNext();
@@ -622,7 +622,7 @@ void XMLTokenizer::parseProcessingInstruction()
#if ENABLE(XSLT)
m_sawXSLTransform = !m_sawFirstElement && pi->isXSL();
- if (m_sawXSLTransform && !m_doc->transformSourceDocument()))
+ if (m_sawXSLTransform && !m_doc->transformSourceDocument())
stopParsing();
#endif
}
diff --git a/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp b/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp
index e68be2b..bff9edb 100644
--- a/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/graphics/qt/PathQt.cpp
@@ -286,10 +286,10 @@ String Path::debugString() const
switch (cur.type) {
case QPainterPath::MoveToElement:
- ret += QString(QLatin1String("M %1 %2")).arg(cur.x).arg(cur.y);
+ ret += QString::fromLatin1("M %1 %2").arg(cur.x).arg(cur.y);
break;
case QPainterPath::LineToElement:
- ret += QString(QLatin1String("L %1 %2")).arg(cur.x).arg(cur.y);
+ ret += QString::fromLatin1("L %1 %2").arg(cur.x).arg(cur.y);
break;
case QPainterPath::CurveToElement:
{
@@ -299,7 +299,7 @@ String Path::debugString() const
Q_ASSERT(c1.type == QPainterPath::CurveToDataElement);
Q_ASSERT(c2.type == QPainterPath::CurveToDataElement);
- ret += QString(QLatin1String("C %1 %2 %3 %4 %5 %6")).arg(cur.x).arg(cur.y).arg(c1.x).arg(c1.y).arg(c2.x).arg(c2.y);
+ ret += QString::fromLatin1("C %1 %2 %3 %4 %5 %6").arg(cur.x).arg(cur.y).arg(c1.x).arg(c1.y).arg(c2.x).arg(c2.y);
i += 2;
break;
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
index 01b68eb..77add54 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
@@ -1986,10 +1986,12 @@ bool QWebPage::isContentEditable() const
/*!
\property QWebPage::forwardUnsupportedContent
- \brief whether QWebPage should forward unsupported content through the
- unsupportedContent signal
+ \brief whether QWebPage should forward unsupported content
- If disabled the download of such content is aborted immediately.
+ If enabled, the unsupportedContent() signal is emitted with a network reply that
+ can be used to read the content.
+
+ If disabled, the download of such content is aborted immediately.
By default unsupported content is not forwarded.
*/
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp
index 1ad23f6..b516263 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebsettings.cpp
@@ -213,17 +213,25 @@ QWebSettings *QWebSettings::globalSettings()
Each QWebPage object has its own QWebSettings object, which configures the
settings for that page. If a setting is not configured, then it is looked
up in the global settings object, which can be accessed using
- QWebSettings::globalSettings().
+ globalSettings().
- QWebSettings allows configuring font properties such as font size and font
- family, the location of a custom stylesheet, and generic attributes like java
- script, plugins, etc. The \l{QWebSettings::WebAttribute}{WebAttribute}
- enum further describes this.
+ QWebSettings allows configuration of browser properties, such as font sizes and
+ families, the location of a custom style sheet, and generic attributes like
+ JavaScript and plugins. Individual attributes are set using the setAttribute()
+ function. The \l{QWebSettings::WebAttribute}{WebAttribute} enum further describes
+ each attribute.
- QWebSettings also configures global properties such as the web page memory
- cache and the web page icon database, local database storage and offline
+ QWebSettings also configures global properties such as the Web page memory
+ cache and the Web page icon database, local database storage and offline
applications storage.
+ \section1 Enabling Plugins
+
+ Support for browser plugins can enabled by setting the
+ \l{QWebSettings::PluginsEnabled}{PluginsEnabled} attribute. For many applications,
+ this attribute is enabled for all pages by setting it on the
+ \l{globalSettings()}{global settings object}.
+
\section1 Web Application Support
WebKit provides support for features specified in \l{HTML 5} that improve the
diff --git a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc
index 06305e0..119c126 100644
--- a/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc
+++ b/src/3rdparty/webkit/WebKit/qt/docs/qtwebkit.qdoc
@@ -96,7 +96,8 @@
Since WebKit supports the Netscape Plugin API, Qt applications can display
Web pages that embed common plugins, as long as the user has the appropriate
- binary files for those plugins installed.
+ binary files for those plugins installed and the \l{QWebSettings::PluginsEnabled}
+ attribute is set for the application.
The following locations are searched for plugins:
diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp
index 1ec704a..e1ffb81 100644
--- a/src/activeqt/container/qaxbase.cpp
+++ b/src/activeqt/container/qaxbase.cpp
@@ -421,7 +421,7 @@ public:
argv[p + 1] = varp + p + 1;
} else {
argv[p + 1] = const_cast<void*>(varp[p + 1].constData());
- if (ptype.endsWith("*")) {
+ if (ptype.endsWith('*')) {
argv_pointer[p + 1] = argv[p + 1];
argv[p + 1] = argv_pointer + p + 1;
}
@@ -648,7 +648,7 @@ QByteArray QAxEventSink::findProperty(DISPID dispID)
int index = mo->indexOfProperty(propname);
const QMetaProperty prop = mo->property(index);
propsignal += prop.typeName();
- propsignal += ")";
+ propsignal += ')';
addProperty(dispID, propname, propsignal);
return propname;
@@ -1660,11 +1660,15 @@ private:
QMap<QByteArray, Property> property_list;
void addProperty(const QByteArray &type, const QByteArray &name, uint flags)
{
+ QByteArray propertyType(type);
+ if (propertyType.endsWith('&'))
+ propertyType.chop(1);
+
Property &prop = property_list[name];
- if (!type.isEmpty() && type != "HRESULT") {
- prop.type = replaceType(type);
- if (prop.type != type)
- prop.realType = type;
+ if (!propertyType.isEmpty() && propertyType != "HRESULT") {
+ prop.type = replaceType(propertyType);
+ if (prop.type != propertyType)
+ prop.realType = propertyType;
}
if (flags & Writable)
flags |= Stored;
@@ -2042,11 +2046,11 @@ QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *inf
case VT_INT:
case VT_UINT:
case VT_CY:
- str += "&";
+ str += '&';
break;
case VT_PTR:
if (str == "QFont" || str == "QPixmap") {
- str += "&";
+ str += '&';
break;
} else if (str == "void*") {
str = "void **";
@@ -2055,19 +2059,19 @@ QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *inf
// FALLTHROUGH
default:
if (str == "QColor")
- str += "&";
+ str += '&';
else if (str == "QDateTime")
- str += "&";
+ str += '&';
else if (str == "QVariantList")
- str += "&";
+ str += '&';
else if (str == "QByteArray")
- str += "&";
+ str += '&';
else if (str == "QStringList")
- str += "&";
+ str += '&';
else if (!str.isEmpty() && hasEnum(str))
- str += "&";
+ str += '&';
else if (!str.isEmpty() && str != "QFont" && str != "QPixmap" && str != "QVariant")
- str += "*";
+ str += '*';
}
break;
case VT_SAFEARRAY:
@@ -2085,7 +2089,7 @@ QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *inf
default:
str = guessTypes(tdesc.lpadesc->tdescElem, info, function);
if (!str.isEmpty())
- str = "QList<" + str + ">";
+ str = "QList<" + str + '>';
break;
}
break;
@@ -2093,7 +2097,7 @@ QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *inf
str = guessTypes(tdesc.lpadesc->tdescElem, info, function);
if (!str.isEmpty()) {
for (int index = 0; index < tdesc.lpadesc->cDims; ++index)
- str += "[" + QByteArray::number((int)tdesc.lpadesc->rgbounds[index].cElements) + "]";
+ str += '[' + QByteArray::number((int)tdesc.lpadesc->rgbounds[index].cElements) + ']';
}
break;
case VT_USERDEFINED:
@@ -2110,7 +2114,7 @@ QByteArray MetaObjectGenerator::guessTypes(const TYPEDESC &tdesc, ITypeInfo *inf
}
if (tdesc.vt & VT_BYREF)
- str += "&";
+ str += '&';
str.replace("&*", "**");
return str;
@@ -2137,7 +2141,7 @@ void MetaObjectGenerator::readClassInfo()
if (d->useClassInfo && !hasClassInfo("CoClass")) {
QString coClassIDstr = iidnames.value(QLatin1String("/CLSID/") + coClassID + QLatin1String("/Default"), coClassID).toString();
addClassInfo("CoClass", coClassIDstr.isEmpty() ? coClassID.toLatin1() : coClassIDstr.toLatin1());
- QByteArray version = QByteArray::number(typeattr->wMajorVerNum) + "." + QByteArray::number(typeattr->wMinorVerNum);
+ QByteArray version = QByteArray::number(typeattr->wMajorVerNum) + '.' + QByteArray::number(typeattr->wMinorVerNum);
if (version != "0.0")
addClassInfo("Version", version);
}
@@ -2170,7 +2174,7 @@ void MetaObjectGenerator::readClassInfo()
while (tlfile.isEmpty() && vit != versions.end()) {
QString version = *vit;
++vit;
- tlfile = controls.value(QLatin1String("/") + version + QLatin1String("/0/win32/.")).toString();
+ tlfile = controls.value(QLatin1Char('/') + version + QLatin1String("/0/win32/.")).toString();
}
controls.endGroup();
} else {
@@ -2343,7 +2347,7 @@ void MetaObjectGenerator::addChangedSignal(const QByteArray &function, const QBy
// generate changed signal
QByteArray signalName(function);
signalName += "Changed";
- QByteArray signalProto = signalName + "(" + replaceType(type) + ")";
+ QByteArray signalProto = signalName + '(' + replaceType(type) + ')';
if (!hasSignal(signalProto))
addSignal(signalProto, function);
if (eventSink)
@@ -2360,7 +2364,7 @@ void MetaObjectGenerator::addSetterSlot(const QByteArray &property)
set = "set";
prototype[0] = toupper(prototype[0]);
}
- prototype = set + prototype + "(" + propertyType(property) + ")";
+ prototype = set + prototype + '(' + propertyType(property) + ')';
if (!hasSlot(prototype))
addSlot(0, prototype, property);
}
@@ -2377,7 +2381,7 @@ QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *t
type = guessTypes(funcdesc->lprgelemdescParam->tdesc, typeinfo, function);
}
- prototype = function + "(";
+ prototype = function + '(';
if (funcdesc->invkind == INVOKE_FUNC && type == hresult)
type = 0;
@@ -2391,7 +2395,7 @@ QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *t
QByteArray ptype = guessTypes(tdesc, typeinfo, function);
if (pdesc.wParamFlags & PARAMFLAG_FRETVAL) {
- if (ptype.endsWith("&")) {
+ if (ptype.endsWith('&')) {
ptype.truncate(ptype.length() - 1);
} else if (ptype.endsWith("**")) {
ptype.truncate(ptype.length() - 1);
@@ -2399,8 +2403,8 @@ QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *t
type = ptype;
} else {
prototype += ptype;
- if (pdesc.wParamFlags & PARAMFLAG_FOUT && !ptype.endsWith("&") && !ptype.endsWith("**"))
- prototype += "&";
+ if (pdesc.wParamFlags & PARAMFLAG_FOUT && !ptype.endsWith('&') && !ptype.endsWith("**"))
+ prototype += '&';
if (optional || pdesc.wParamFlags & PARAMFLAG_FOPT)
paramName += "=0";
else if (pdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) {
@@ -2410,22 +2414,22 @@ QByteArray MetaObjectGenerator::createPrototype(FUNCDESC *funcdesc, ITypeInfo *t
parameters << paramName;
}
if (p < funcdesc->cParams && !(pdesc.wParamFlags & PARAMFLAG_FRETVAL))
- prototype += ",";
+ prototype += ',';
}
if (!prototype.isEmpty()) {
- if (prototype.right(1) == ",") {
+ if (prototype.endsWith(',')) {
if (funcdesc->invkind == INVOKE_PROPERTYPUT && p == funcdesc->cParams) {
TYPEDESC tdesc = funcdesc->lprgelemdescParam[p-1].tdesc;
QByteArray ptype = guessTypes(tdesc, typeinfo, function);
prototype += ptype;
- prototype += ")";
+ prototype += ')';
parameters << "rhs";
} else {
prototype[prototype.length()-1] = ')';
}
} else {
- prototype += ")";
+ prototype += ')';
}
}
@@ -2573,11 +2577,11 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
if (defargs) {
parameters.takeLast();
- int lastParam = prototype.lastIndexOf(",");
+ int lastParam = prototype.lastIndexOf(',');
if (lastParam == -1)
- lastParam = prototype.indexOf("(") + 1;
+ lastParam = prototype.indexOf('(') + 1;
prototype.truncate(lastParam);
- prototype += ")";
+ prototype += ')';
}
} while (defargs);
}
@@ -2593,8 +2597,8 @@ void MetaObjectGenerator::readFuncsInfo(ITypeInfo *typeinfo, ushort nFuncs)
QString strDocu = QString::fromUtf16((const ushort*)bstrDocu);
SysFreeString(bstrDocu);
if (!!strDocu)
- desc += "[" + strDocu + "]";
- desc += "\n";
+ desc += '[' + strDocu + ']';
+ desc += '\n';
#endif
typeinfo->ReleaseFuncDesc(funcdesc);
}
@@ -2676,8 +2680,8 @@ void MetaObjectGenerator::readVarsInfo(ITypeInfo *typeinfo, ushort nVars)
QString strDocu = QString::fromUtf16((const ushort*)bstrDocu);
SysFreeString(bstrDocu);
if (!!strDocu)
- desc += "[" + strDocu + "]";
- desc += "\n";
+ desc += '[' + strDocu + ']';
+ desc += '\n';
#endif
typeinfo->ReleaseVarDesc(vardesc);
}
@@ -2823,8 +2827,8 @@ void MetaObjectGenerator::readEventInterface(ITypeInfo *eventinfo, IConnectionPo
QString strDocu = QString::fromUtf16((const ushort*)bstrDocu);
SysFreeString(bstrDocu);
if (!!strDocu)
- desc += "[" + strDocu + "]";
- desc += "\n";
+ desc += '[' + strDocu + ']';
+ desc += '\n';
#endif
eventinfo->ReleaseFuncDesc(funcdesc);
}
@@ -4394,8 +4398,8 @@ QVariant QAxBase::asVariant() const
cn = cn.mid(cn.lastIndexOf(':') + 1);
QObject *object = qObject();
if (QMetaType::type(cn))
- qvar = QVariant(qRegisterMetaType<QObject*>(cn + "*"), &object);
-// qVariantSetValue(qvar, qObject(), cn + "*");
+ qvar = QVariant(qRegisterMetaType<QObject*>(cn + '*'), &object);
+// qVariantSetValue(qvar, qObject(), cn + '*');
}
return qvar;
diff --git a/src/activeqt/container/qaxdump.cpp b/src/activeqt/container/qaxdump.cpp
index 62ef0a4..c3218a9 100644
--- a/src/activeqt/container/qaxdump.cpp
+++ b/src/activeqt/container/qaxdump.cpp
@@ -94,14 +94,14 @@ static QByteArray namedPrototype(const QList<QByteArray> &parameterTypes, const
prototype += type;
if (p < parameterNames.count())
- prototype += " " + parameterNames.at(p);
+ prototype += ' ' + parameterNames.at(p);
if (numDefArgs >= parameterTypes.count() - p)
prototype += " = 0";
if (p < parameterTypes.count() - 1)
prototype += ", ";
}
- prototype += ")";
+ prototype += ')';
return prototype;
}
@@ -196,8 +196,8 @@ QString qax_generateDocumentation(QAxBase *that)
prototype = namedPrototype(slot.parameterTypes(), slot.parameterNames());
QString detail = QString::fromLatin1("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
- QString::fromLatin1(returntype.constData()) + QLatin1String(" ") +
- QString::fromLatin1(name.constData()) + QLatin1String(" ") +
+ QLatin1String(returntype.constData()) + QLatin1Char(' ') +
+ QLatin1String(name.constData()) + QLatin1Char(' ') +
QString::fromLatin1(prototype.constData()) + QLatin1String("<tt> [slot]</tt></h3>\n");
prototype = namedPrototype(slot.parameterTypes(), QList<QByteArray>());
detail += docuFromName(typeInfo, QString::fromLatin1(name.constData()));
@@ -220,14 +220,14 @@ QString qax_generateDocumentation(QAxBase *that)
returntype = "QAxObject *";
}
if (returntype != "void")
- detail += QString::fromLatin1(returntype.constData()) + QLatin1String(" result = ");
- detail += QLatin1String("object->") + QString::fromLatin1(functionToCall.constData()) +
- QLatin1String("(\"" + name + prototype + "\"");
+ detail += QLatin1String(returntype.constData()) + QLatin1String(" result = ");
+ detail += QLatin1String("object->") + QLatin1String(functionToCall.constData()) +
+ QLatin1String("(\"" + name + prototype + '\"');
if (hasParams)
detail += QLatin1String(", params");
- detail += QLatin1String(")");
+ detail += QLatin1Char(')');
if (returntype != "void" && returntype != "QAxObject *" && returntype != "QVariant")
- detail += QLatin1String(".") + QString::fromLatin1(toType(returntype));
+ detail += QLatin1Char('.') + QLatin1String(toType(returntype));
detail += QLatin1String(";</pre>\n");
} else {
detail += QLatin1String("<p>This function has parameters of unsupported types and cannot be called directly.");
@@ -262,9 +262,9 @@ QString qax_generateDocumentation(QAxBase *that)
QByteArray name = signature.left(signature.indexOf('('));
stream << "<li>void <a href=\"#" << name << "\"><b>" << name << "</b></a>" << prototype << ";</li>" << endl;
- QString detail = QLatin1String("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>void ") +
- QString::fromLatin1(name.constData()) + QLatin1String(" ") +
- QString::fromLatin1(prototype.constData()) + QLatin1String("<tt> [signal]</tt></h3>\n");
+ QString detail = QLatin1String("<h3><a name=") + QLatin1String(name.constData()) + QLatin1String("></a>void ") +
+ QLatin1String(name.constData()) + QLatin1Char(' ') +
+ QLatin1String(prototype.constData()) + QLatin1String("<tt> [signal]</tt></h3>\n");
if (typeLib) {
interCount = 0;
do {
@@ -311,8 +311,8 @@ QString qax_generateDocumentation(QAxBase *that)
stream << "<li>" << type << " <a href=\"#" << name << "\"><b>" << name << "</b></a>;</li>" << endl;
QString detail = QLatin1String("<h3><a name=") + QString::fromLatin1(name.constData()) + QLatin1String("></a>") +
- QString::fromLatin1(type.constData()) +
- QLatin1String(" ") + QString::fromLatin1(name.constData()) + QLatin1String("</h3>\n");
+ QLatin1String(type.constData()) +
+ QLatin1Char(' ') + QLatin1String(name.constData()) + QLatin1String("</h3>\n");
detail += docuFromName(typeInfo, QString::fromLatin1(name));
QVariant::Type vartype = QVariant::nameToType(type);
if (!prop.isReadable())
@@ -326,14 +326,14 @@ QString qax_generateDocumentation(QAxBase *that)
if (prop.isEnumType())
detail += QLatin1String("\tint val = ");
else
- detail += QLatin1String("\t") + QString::fromLatin1(type.constData()) + QLatin1String(" val = ");
- detail += QLatin1String("object->property(\"") + QString::fromLatin1(name.constData()) +
- QLatin1String("\").") + QString::fromLatin1(toType(type).constData()) + QLatin1String(";\n");
+ detail += QLatin1Char('\t') + QLatin1String(type.constData()) + QLatin1String(" val = ");
+ detail += QLatin1String("object->property(\"") + QLatin1String(name.constData()) +
+ QLatin1String("\").") + QLatin1String(toType(type).constData()) + QLatin1String(";\n");
detail += QLatin1String("</pre>\n");
} else if (type == "IDispatch*" || type == "IUnknown*") {
detail += QLatin1String("<p>Get the subobject using querySubObject:<pre>\n");
- detail += QLatin1String("\tQAxObject *") + QString::fromLatin1(name.constData()) +
- QLatin1String(" = object->querySubObject(\"") + QString::fromLatin1(name.constData()) + QLatin1String("\");\n");
+ detail += QLatin1String("\tQAxObject *") + QLatin1String(name.constData()) +
+ QLatin1String(" = object->querySubObject(\"") + QLatin1String(name.constData()) + QLatin1String("\");\n");
detail += QLatin1String("</pre>\n");
} else {
detail += QLatin1String("<p>This property is of an unsupported type.\n");
diff --git a/src/activeqt/container/qaxscript.cpp b/src/activeqt/container/qaxscript.cpp
index c69fea0..8f8186a 100644
--- a/src/activeqt/container/qaxscript.cpp
+++ b/src/activeqt/container/qaxscript.cpp
@@ -1203,9 +1203,9 @@ QString QAxScriptManager::scriptFileFilter()
continue;
allFiles += QLatin1String(" *") + engine.extension;
- specialFiles += QLatin1String(";;") + engine.name + QLatin1String(" Files (*") + engine.extension + QLatin1String(")");
+ specialFiles += QLatin1String(";;") + engine.name + QLatin1String(" Files (*") + engine.extension + QLatin1Char(')');
}
- allFiles += QLatin1String(")");
+ allFiles += QLatin1Char(')');
return allFiles + specialFiles + QLatin1String(";;All Files (*.*)");
}
diff --git a/src/activeqt/container/qaxwidget.cpp b/src/activeqt/container/qaxwidget.cpp
index 4e8473f..7f20a5c 100644
--- a/src/activeqt/container/qaxwidget.cpp
+++ b/src/activeqt/container/qaxwidget.cpp
@@ -383,7 +383,7 @@ public:
bool eventTranslated : 1;
private:
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
struct OleMenuItem {
OleMenuItem(HMENU hm = 0, int ID = 0, QMenu *menu = 0)
: hMenu(hm), id(ID), subMenu(menu)
@@ -408,7 +408,7 @@ private:
bool canHostDocument : 1;
DWORD m_dwOleObject;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
HWND m_menuOwner;
#endif
CONTROLINFO control_info;
@@ -417,7 +417,7 @@ private:
unsigned long ref;
QAxWidget *widget;
QAxHostWidget *host;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QPointer<QMenuBar> menuBar;
QMap<QAction*,OleMenuItem> menuItemMap;
#endif
@@ -467,7 +467,7 @@ static QAbstractEventDispatcher::EventFilter previous_filter = 0;
#if QT_VERSION >= 0x050000
#error "Fix QAbstractEventDispatcher::setEventFilter"
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
static int filter_ref = 0;
#else
static const char *qaxatom = "QAxContainer4_Atom";
@@ -551,7 +551,7 @@ QAxClientSite::QAxClientSite(QAxWidget *c)
canHostDocument = false;
m_dwOleObject = 0;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
m_menuOwner = 0;
menuBar = 0;
#endif
@@ -1132,7 +1132,7 @@ HRESULT WINAPI QAxClientSite::OnPosRectChange(LPCRECT /*lprcPosRect*/)
}
//**** IOleInPlaceFrame
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
HRESULT WINAPI QAxClientSite::InsertMenus(HMENU /*hmenuShared*/, LPOLEMENUGROUPWIDTHS /*lpMenuWidths*/)
{
return E_NOTIMPL;
diff --git a/src/activeqt/control/qaxserver.cpp b/src/activeqt/control/qaxserver.cpp
index d919382..1771293 100644
--- a/src/activeqt/control/qaxserver.cpp
+++ b/src/activeqt/control/qaxserver.cpp
@@ -90,7 +90,7 @@ QAxFactory *qAxFactory()
QStringList keys(qax_factory->featureList());
for (int i = 0; i < keys.count(); ++i) {
QString key(keys.at(i));
- qRegisterMetaType((key + QLatin1String("*")).toLatin1(), (void**)0);
+ qRegisterMetaType((key + QLatin1Char('*')).toLatin1(), (void**)0);
}
}
return qax_factory;
@@ -208,9 +208,9 @@ HRESULT UpdateRegistry(BOOL bRegister)
{
qAxIsServer = false;
QString file = QString::fromLocal8Bit(qAxModuleFilename);
- QString path = file.left(file.lastIndexOf(QLatin1String("\\"))+1);
+ QString path = file.left(file.lastIndexOf(QLatin1Char('\\'))+1);
QString module = file.right(file.length() - path.length());
- module = module.left(module.lastIndexOf(QLatin1String(".")));
+ module = module.left(module.lastIndexOf(QLatin1Char('.')));
const QString appId = qAxFactory()->appID().toString().toUpper();
const QString libId = qAxFactory()->typeLibID().toString().toUpper();
@@ -226,7 +226,7 @@ HRESULT UpdateRegistry(BOOL bRegister)
DWORD major = libAttr->wMajorVerNum;
DWORD minor = libAttr->wMinorVerNum;
- typeLibVersion = QString::number((uint)major) + QLatin1String(".") + QString::number((uint)minor);
+ typeLibVersion = QString::number((uint)major) + QLatin1Char('.') + QString::number((uint)minor);
if (bRegister)
RegisterTypeLib(qAxTypeLibrary, (TCHAR*)libFile.utf16(), 0);
@@ -271,12 +271,12 @@ HRESULT UpdateRegistry(BOOL bRegister)
className = qax_clean_type(className, mo);
if (object) { // don't register subobject classes
- QString classVersion = mo ? QString(QLatin1String(mo->classInfo(mo->indexOfClassInfo("Version")).value())) : QString();
+ QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
if (classVersion.isNull())
classVersion = QLatin1String("1.0");
bool insertable = mo && !qstricmp(mo->classInfo(mo->indexOfClassInfo("Insertable")).value(), "yes");
bool control = object->isWidgetType();
- const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1String(".")));
+ const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
uint olemisc = OLEMISC_SETCLIENTSITEFIRST
|OLEMISC_ACTIVATEWHENVISIBLE
|OLEMISC_INSIDEOUT
@@ -287,17 +287,17 @@ HRESULT UpdateRegistry(BOOL bRegister)
else if (qFindChild<QMenuBar*>(object) && !qax_disable_inplaceframe)
olemisc |= OLEMISC_WANTSTOMENUMERGE;
- settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
- settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/CLSID/."), classId);
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."), className + QLatin1String(" Class"));
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."), classId);
if (insertable)
- settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."), QVariant(QLatin1String("")));
- settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/."), className + QLatin1String(" Class"));
- settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CLSID/."), classId);
- settings.setValue(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CurVer/."), module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion);
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."), className + QLatin1String(" Class"));
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."), classId);
+ settings.setValue(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/."), className + QLatin1String(" Class"));
- if (file.right(3).toLower() == QLatin1String("exe"))
+ if (file.endsWith(QLatin1String("exe"), Qt::CaseInsensitive))
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"), appId);
if (control)
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."), QVariant(QLatin1String("")));
@@ -307,15 +307,15 @@ HRESULT UpdateRegistry(BOOL bRegister)
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/InProcServer32/."), file);
else
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/LocalServer32/."),
- QLatin1String("\"") + file + QLatin1String("\" -activex"));
+ QLatin1Char('\"') + file + QLatin1String("\" -activex"));
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/."), control ? QLatin1String("1") : QLatin1String("0"));
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/MiscStatus/1/."), QString::number(olemisc));
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Programmable/."), QVariant(QLatin1String("")));
- settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."), QLatin1String("\"") +
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ToolboxBitmap32/."), QLatin1Char('\"') +
file + QLatin1String("\", 101"));
settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/TypeLib/."), libId); settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/Version/."), classVersion);
- settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."), module + QLatin1String(".") + className);
- settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."), module + QLatin1String(".") + className + QLatin1String(".") + classVersion.left(classVersion.indexOf(QLatin1Char('.'))));
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/VersionIndependentProgID/."), module + QLatin1Char('.') + className);
+ settings.setValue(QLatin1String("/CLSID/") + classId + QLatin1String("/ProgID/."), module + QLatin1Char('.') + className + QLatin1Char('.') + classVersion.left(classVersion.indexOf(QLatin1Char('.'))));
QString mime = QLatin1String(mo->classInfo(mo->indexOfClassInfo("MIME")).value());
if (!mime.isEmpty()) {
@@ -330,15 +330,15 @@ HRESULT UpdateRegistry(BOOL bRegister)
mime = mime.left(mime.length() - extension.length() - 1);
// Prepend '.' before extension, if required.
extension = extension.trimmed();
- if (extension[0] != QChar(QLatin1Char('.')))
- extension = QLatin1String(".") + extension;
+ if (extension[0] != QLatin1Char('.'))
+ extension = QLatin1Char('.') + extension;
}
if (!extension.isEmpty()) {
- settings.setValue(QLatin1String("/") + extension + QLatin1String("/."), module + QLatin1String(".") + className);
- settings.setValue(QLatin1String("/") + extension + QLatin1String("/Content Type"), mime);
+ settings.setValue(QLatin1Char('/') + extension + QLatin1String("/."), module + QLatin1Char('.') + className);
+ settings.setValue(QLatin1Char('/') + extension + QLatin1String("/Content Type"), mime);
- mime = mime.replace(QLatin1String("/"), QLatin1String("\\"));
+ mime = mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"), classId);
settings.setValue(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"), extension);
}
@@ -358,22 +358,22 @@ HRESULT UpdateRegistry(BOOL bRegister)
const QString classId = qAxFactory()->classID(className).toString().toUpper();
className = qax_clean_type(className, mo);
- QString classVersion = mo ? QString(QLatin1String(mo->classInfo(mo->indexOfClassInfo("Version")).value())) : QString();
+ QString classVersion = mo ? QString::fromLatin1(mo->classInfo(mo->indexOfClassInfo("Version")).value()) : QString();
if (classVersion.isNull())
classVersion = QLatin1String("1.0");
- const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1String(".")));
+ const QString classMajorVersion = classVersion.left(classVersion.indexOf(QLatin1Char('.')));
qAxFactory()->unregisterClass(*key, &settings);
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/CLSID/."));
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/Insertable/."));
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion + QLatin1String("/."));
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String(".") + classMajorVersion);
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/CLSID/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/Insertable/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion + QLatin1String("/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1Char('.') + classMajorVersion);
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CLSID/."));
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/CurVer/."));
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className + QLatin1String("/."));
- settings.remove(QLatin1String("/") + module + QLatin1String(".") + className);
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CLSID/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/CurVer/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className + QLatin1String("/."));
+ settings.remove(QLatin1Char('/') + module + QLatin1Char('.') + className);
settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/AppID"));
settings.remove(QLatin1String("/CLSID/") + classId + QLatin1String("/Control/."));
@@ -404,14 +404,14 @@ HRESULT UpdateRegistry(BOOL bRegister)
mime = mime.left(mime.length() - extension.length() - 1);
// Prepend '.' before extension, if required.
extension = extension.trimmed();
- if (extension[0] != QChar(QLatin1Char('.')))
- extension = QLatin1String(".") + extension;
+ if (extension[0] != QLatin1Char('.'))
+ extension.prepend(QLatin1Char('.'));
}
if (!extension.isEmpty()) {
- settings.remove(QLatin1String("/") + extension + QLatin1String("/Content Type"));
- settings.remove(QLatin1String("/") + extension + QLatin1String("/."));
- settings.remove(QLatin1String("/") + extension);
- mime = mime.replace(QLatin1String("/"), QLatin1String("\\"));
+ settings.remove(QLatin1Char('/') + extension + QLatin1String("/Content Type"));
+ settings.remove(QLatin1Char('/') + extension + QLatin1String("/."));
+ settings.remove(QLatin1Char('/') + extension);
+ mime.replace(QLatin1Char('/'), QLatin1Char('\\'));
settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/Extension"));
settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/CLSID"));
settings.remove(QLatin1String("/MIME/Database/Content Type/") + mime + QLatin1String("/."));
@@ -455,8 +455,8 @@ static const char* const type_map[][2] =
{ "QFont", "IFontDisp*" },
{ "QPixmap", "IPictureDisp*" },
{ "QVariant", "VARIANT" },
- { "QVariantList", "SAFEARRAY(VARIANT)" },
- { "QList<QVariant>","SAFEARRAY(VARIANT)" },
+ { "QVariantList", "SAFEARRAY(VARIANT)" },
+ { "QList<QVariant>", "SAFEARRAY(VARIANT)" },
{ "quint64", "CY" },
{ "qint64", "CY" },
{ "qulonglong", "CY" },
@@ -464,8 +464,8 @@ static const char* const type_map[][2] =
{ "QByteArray", "SAFEARRAY(BYTE)" },
{ "QStringList", "SAFEARRAY(BSTR)" },
// Userdefined Qt datatypes - some not on Borland though
- { "QCursor", "enum MousePointer" },
- { "Qt::FocusPolicy","enum FocusPolicy" },
+ { "QCursor", "enum MousePointer" },
+ { "Qt::FocusPolicy", "enum FocusPolicy" },
#ifndef Q_CC_BOR
# if __REQUIRED_RPCNDR_H_VERSION__ >= Q_REQUIRED_RPCNDR_H_VERSION
{ "QRect", "struct QRect" },
@@ -578,7 +578,7 @@ static QByteArray renameOverloads(const QByteArray &name)
int n = mapping.value(name);
if (mapping.contains(name)) {
int n = mapping.value(name);
- newName = name + "_" + QByteArray::number(n);
+ newName = name + '_' + QByteArray::number(n);
mapping.insert(name, n+1);
} else {
mapping.insert(name, 1);
@@ -686,13 +686,13 @@ static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList
QByteArray type(parameterTypes.at(p));
QByteArray name(parameterNames.at(p));
- if (type.endsWith("&")) {
+ if (type.endsWith('&')) {
out = true;
type.truncate(type.length() - 1);
} else if (type.endsWith("**")) {
out = true;
type.truncate(type.length() - 1);
- } else if (type.endsWith("*") && !subtypes.contains(type)) {
+ } else if (type.endsWith('*') && !subtypes.contains(type)) {
type.truncate(type.length() - 1);
}
if (type.isEmpty()) {
@@ -701,14 +701,14 @@ static QByteArray prototype(const QList<QByteArray> &parameterTypes, const QList
}
type = convertTypes(type, ok);
if (!out)
- prototype += "[in] " + type + " ";
+ prototype += "[in] " + type + ' ';
else
- prototype += "[in,out] " + type + " ";
+ prototype += "[in,out] " + type + ' ';
if (out)
- prototype += "*";
+ prototype += '*';
if (name.isEmpty())
- prototype += "p" + QByteArray::number(p);
+ prototype += 'p' + QByteArray::number(p);
else
prototype += "p_" + replaceKeyword(name);
@@ -728,12 +728,12 @@ static QByteArray addDefaultArguments(const QByteArray &prototype, int numDefArg
QByteArray ptype(prototype);
int in = -1;
while (numDefArgs) {
- in = ptype.lastIndexOf("]", in);
+ in = ptype.lastIndexOf(']', in);
ptype.replace(in, 1, ",optional]");
in = ptype.indexOf(' ', in) + 1;
QByteArray type = ptype.mid(in, ptype.indexOf(' ', in) - in);
if (type == "enum")
- type += " " + ptype.mid(in + 5, ptype.indexOf(' ', in + 5) - in - 5);
+ type += ' ' + ptype.mid(in + 5, ptype.indexOf(' ', in + 5) - in - 5);
ptype.replace(in, type.length(), QByteArray("VARIANT /*was: ") + type + "*/");
--numDefArgs;
}
@@ -801,7 +801,7 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
for (int j = 0; j < enumerator.keyCount(); ++j) {
QByteArray key(enumerator.key(j));
while (enumValues.contains(key)) {
- key += "_";
+ key += '_';
}
enumValues.append(key);
uint value = (uint)enumerator.value(j);
@@ -822,32 +822,32 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
if (!enums.contains("MousePointer")) {
enums.append("MousePointer");
out << "\tenum MousePointer {" << endl;
- out << "\t\tArrowCursor = " << Qt::ArrowCursor << "," << endl;
- out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << "," << endl;
- out << "\t\tCrossCursor = " << Qt::CrossCursor << "," << endl;
- out << "\t\tWaitCursor = " << Qt::WaitCursor << "," << endl;
- out << "\t\tIBeamCursor = " << Qt::IBeamCursor << "," << endl;
- out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << "," << endl;
- out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << "," << endl;
- out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << "," << endl;
- out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << "," << endl;
- out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << "," << endl;
- out << "\t\tBlankCursor = " << Qt::BlankCursor << "," << endl;
- out << "\t\tSplitVCursor = " << Qt::SplitVCursor << "," << endl;
- out << "\t\tSplitHCursor = " << Qt::SplitHCursor << "," << endl;
- out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << "," << endl;
- out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << "," << endl;
- out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << "," << endl;
+ out << "\t\tArrowCursor = " << Qt::ArrowCursor << ',' << endl;
+ out << "\t\tUpArrowCursor = " << Qt::UpArrowCursor << ',' << endl;
+ out << "\t\tCrossCursor = " << Qt::CrossCursor << ',' << endl;
+ out << "\t\tWaitCursor = " << Qt::WaitCursor << ',' << endl;
+ out << "\t\tIBeamCursor = " << Qt::IBeamCursor << ',' << endl;
+ out << "\t\tSizeVerCursor = " << Qt::SizeVerCursor << ',' << endl;
+ out << "\t\tSizeHorCursor = " << Qt::SizeHorCursor << ',' << endl;
+ out << "\t\tSizeBDiagCursor = " << Qt::SizeBDiagCursor << ',' << endl;
+ out << "\t\tSizeFDiagCursor = " << Qt::SizeFDiagCursor << ',' << endl;
+ out << "\t\tSizeAllCursor = " << Qt::SizeAllCursor << ',' << endl;
+ out << "\t\tBlankCursor = " << Qt::BlankCursor << ',' << endl;
+ out << "\t\tSplitVCursor = " << Qt::SplitVCursor << ',' << endl;
+ out << "\t\tSplitHCursor = " << Qt::SplitHCursor << ',' << endl;
+ out << "\t\tPointingHandCursor = " << Qt::PointingHandCursor << ',' << endl;
+ out << "\t\tForbiddenCursor = " << Qt::ForbiddenCursor << ',' << endl;
+ out << "\t\tWhatsThisCursor = " << Qt::WhatsThisCursor << ',' << endl;
out << "\t\tBusyCursor\t= " << Qt::BusyCursor << endl;
out << "\t};" << endl << endl;
}
if (!enums.contains("FocusPolicy")) {
enums.append("FocusPolicy");
out << "\tenum FocusPolicy {" << endl;
- out << "\t\tNoFocus = " << Qt::NoFocus << "," << endl;
- out << "\t\tTabFocus = " << Qt::TabFocus << "," << endl;
- out << "\t\tClickFocus = " << Qt::ClickFocus << "," << endl;
- out << "\t\tStrongFocus = " << Qt::StrongFocus << "," << endl;
+ out << "\t\tNoFocus = " << Qt::NoFocus << ',' << endl;
+ out << "\t\tTabFocus = " << Qt::TabFocus << ',' << endl;
+ out << "\t\tClickFocus = " << Qt::ClickFocus << ',' << endl;
+ out << "\t\tStrongFocus = " << Qt::StrongFocus << ',' << endl;
out << "\t\tWheelFocus = " << Qt::WheelFocus << endl;
out << "\t};" << endl << endl;
}
@@ -877,7 +877,7 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
if (!ok)
out << "\t/****** Property is of unsupported datatype" << endl;
- out << "\t\t[id(" << id << ")";
+ out << "\t\t[id(" << id << ')';
if (!property.isWritable())
out << ", readonly";
if (isBindable && property.isScriptable(o))
@@ -886,9 +886,9 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
out << ", nonbrowsable";
if (isBindable)
out << ", requestedit";
- if (defProp == QString::fromLatin1(name.constData()))
+ if (defProp == QLatin1String(name))
out << ", uidefault";
- out << "] " << type << " " << name << ";" << endl;
+ out << "] " << type << ' ' << name << ';' << endl;
if (!ok)
out << "\t******/" << endl;
@@ -939,7 +939,7 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
if (!ok)
outBuffer += "\t/****** Slot parameter uses unsupported datatype\n";
- outBuffer += "\t\t[id(" + QString::number(id).toLatin1() + ")] " + type + " " + name + "(" + ptype + ");\n";
+ outBuffer += "\t\t[id(" + QString::number(id).toLatin1() + ")] " + type + ' ' + name + '(' + ptype + ");\n";
if (!ok)
outBuffer += "\t******/\n";
@@ -991,7 +991,7 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
QList<QByteArray> parameterTypes(signal.parameterTypes());
QList<QByteArray> parameterNames(signal.parameterNames());
- bool isDefault = defSignal == QString::fromLatin1(name.constData());
+ bool isDefault = defSignal == QLatin1String(name);
name = renameOverloads(replaceKeyword(name));
bool ok = true;
@@ -1003,10 +1003,10 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
if (!ok)
out << "\t/****** Signal parameter uses unsupported datatype" << endl;
- out << "\t\t[id(" << id << ")";
+ out << "\t\t[id(" << id << ')';
if (isDefault)
out << ", uidefault";
- out << "] void " << name << "(" << ptype << ");" << endl;
+ out << "] void " << name << '(' << ptype << ");" << endl;
if (!ok)
out << "\t******/" << endl;
@@ -1031,7 +1031,7 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
const char *classVersion = mo->classInfo(mo->indexOfClassInfo("Version")).value();
if (classVersion)
out << "\t\tversion(" << classVersion << ")," << endl;
- out << "\t\tuuid(" << classID << ")";
+ out << "\t\tuuid(" << classID << ')';
if (control) {
out << ", " << endl;
out << "\t\tcontrol";
@@ -1043,7 +1043,7 @@ static HRESULT classIDL(QObject *o, const QMetaObject *mo, const QString &classN
out << "\t]" << endl;
out << "\tcoclass " << cleanClassName << endl;
out << "\t{" << endl;
- out << "\t\t[default] dispinterface I" << cleanClassName << ";" << endl;
+ out << "\t\t[default] dispinterface I" << cleanClassName << ';' << endl;
if (hasEvents)
out << "\t\t[default, source] dispinterface I" << cleanClassName << "Events;" << endl;
out << "\t};" << endl;
@@ -1068,7 +1068,7 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
file.remove();
QString filebase = QString::fromLocal8Bit(qAxModuleFilename);
- filebase = filebase.left(filebase.lastIndexOf(QLatin1String(".")));
+ filebase = filebase.left(filebase.lastIndexOf(QLatin1Char('.')));
QString appID = qAxFactory()->appID().toString().toUpper();
if (QUuid(appID).isNull())
@@ -1103,7 +1103,7 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
out << "/****************************************************************************" << endl;
out << "** Interface definition generated for ActiveQt project" << endl;
out << "**" << endl;
- out << "** '" << qAxModuleFilename << "'" << endl;
+ out << "** '" << qAxModuleFilename << '\'' << endl;
out << "**" << endl;
out << "** Created: " << QDateTime::currentDateTime().toString() << endl;
out << "**" << endl;
@@ -1121,13 +1121,13 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
delete_qApp = true;
}
- out << "[" << endl;
+ out << '[' << endl;
out << "\tuuid(" << typeLibID << ")," << endl;
out << "\tversion(" << version << ")," << endl;
- out << "\thelpstring(\"" << typelib << " " << version << " Type Library\")" << endl;
- out << "]" << endl;
+ out << "\thelpstring(\"" << typelib << ' ' << version << " Type Library\")" << endl;
+ out << ']' << endl;
out << "library " << typelib << "Lib" << endl;
- out << "{" << endl;
+ out << '{' << endl;
out << "\timportlib(\"stdole32.tlb\");" << endl;
out << "\timportlib(\"stdole2.tlb\");" << endl << endl;
@@ -1188,11 +1188,12 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
// We have meta object information for this type. Forward declare it.
if (mo) {
QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
- out << "\tcoclass " << cleanType << ";" << endl;
+ out << "\tcoclass " << cleanType << ';' << endl;
+ subtypes.append(cleanType);
+ qRegisterMetaType(cleanType, (void**)0);
+ cleanType += '*';
subtypes.append(cleanType);
- subtypes.append(cleanType + "*");
qRegisterMetaType(cleanType, (void**)0);
- qRegisterMetaType(cleanType + "*", (void**)0);
}
}
out << endl;
@@ -1225,7 +1226,7 @@ extern "C" HRESULT __stdcall DumpIDL(const QString &outfile, const QString &ver)
QByteArray cleanType = qax_clean_type(*key, mo).toLatin1();
subtypes.append(cleanType);
- subtypes.append(cleanType + "*");
+ subtypes.append(cleanType + '*');
res = classIDL(o, mo, QString::fromLatin1(className.constData()), isBindable, out);
delete o;
if (res != S_OK)
diff --git a/src/activeqt/control/qaxserverbase.cpp b/src/activeqt/control/qaxserverbase.cpp
index f3e1dff..19c2404 100644
--- a/src/activeqt/control/qaxserverbase.cpp
+++ b/src/activeqt/control/qaxserverbase.cpp
@@ -2446,10 +2446,10 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid,
int nameLength = 0;
if (index == -1) {
nameLength = name.length();
- name += "(";
+ name += '(';
// no parameter - shortcut
if (!pDispParams->cArgs)
- index = mo->indexOfSlot((name + ")"));
+ index = mo->indexOfSlot((name + ')'));
// search
if (index == -1) {
for (int i = 0; i < mo->methodCount(); ++i) {
@@ -2463,7 +2463,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid,
if (index == -1) {
QRegExp regexp(QLatin1String("_([0-9])\\("));
if (regexp.lastIndexIn(QString::fromLatin1(name.constData())) != -1) {
- name = name.left(name.length() - regexp.cap(0).length()) + "(";
+ name = name.left(name.length() - regexp.cap(0).length()) + '(';
int overload = regexp.cap(1).toInt() + 1;
for (int s = 0; s < qt.object->metaObject()->methodCount(); ++s) {
@@ -2559,7 +2559,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid,
argv[p + 1] = varp + p + 1;
} else {
argv[p + 1] = const_cast<void*>(varp[p + 1].constData());
- if (ptype.endsWith("*")) {
+ if (ptype.endsWith('*')) {
argv_pointer[p + 1] = argv[p + 1];
argv[p + 1] = argv_pointer + p + 1;
}
@@ -2590,7 +2590,7 @@ HRESULT WINAPI QAxServerBase::Invoke(DISPID dispidMember, REFIID riid,
} else {
argv[0] = const_cast<void*>(varp[0].constData());
}
- if (type.endsWith("*")) {
+ if (type.endsWith('*')) {
argv_pointer[0] = argv[0];
argv[0] = argv_pointer;
}
diff --git a/src/activeqt/control/qaxservermain.cpp b/src/activeqt/control/qaxservermain.cpp
index a50fef0..e3e1e5d 100644
--- a/src/activeqt/control/qaxservermain.cpp
+++ b/src/activeqt/control/qaxservermain.cpp
@@ -253,7 +253,7 @@ EXTERN_C int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR,
run = false;
break;
} else {
- unprocessed += cmds.at(i) + " ";
+ unprocessed += cmds.at(i) + ' ';
}
}
diff --git a/src/activeqt/shared/qaxtypes.cpp b/src/activeqt/shared/qaxtypes.cpp
index ace81e7..12307f3 100644
--- a/src/activeqt/shared/qaxtypes.cpp
+++ b/src/activeqt/shared/qaxtypes.cpp
@@ -1111,7 +1111,7 @@ QVariant VARIANTToQVariant(const VARIANT &arg, const QByteArray &typeName, uint
if (iface) {
QObject *qObj = iface->qObject();
iface->Release();
- var = QVariant(qRegisterMetaType<QObject*>(qObj ? QByteArray(qObj->metaObject()->className()) + "*" : typeName), &qObj);
+ var = QVariant(qRegisterMetaType<QObject*>(qObj ? QByteArray(qObj->metaObject()->className()) + '*' : typeName), &qObj);
} else
#endif
{
diff --git a/src/corelib/animation/animation.pri b/src/corelib/animation/animation.pri
new file mode 100644
index 0000000..cb7850c
--- /dev/null
+++ b/src/corelib/animation/animation.pri
@@ -0,0 +1,25 @@
+# Qt core animation module
+
+HEADERS += \
+ animation/qabstractanimation.h \
+ animation/qabstractanimation_p.h \
+ animation/qvariantanimation.h \
+ animation/qvariantanimation_p.h \
+ animation/qpropertyanimation.h \
+ animation/qpropertyanimation_p.h \
+ animation/qanimationgroup.h \
+ animation/qanimationgroup_p.h \
+ animation/qsequentialanimationgroup.h \
+ animation/qsequentialanimationgroup_p.h \
+ animation/qparallelanimationgroup.h \
+ animation/qparallelanimationgroup_p.h \
+ animation/qpauseanimation.h
+
+SOURCES += \
+ animation/qabstractanimation.cpp \
+ animation/qvariantanimation.cpp \
+ animation/qpropertyanimation.cpp \
+ animation/qanimationgroup.cpp \
+ animation/qsequentialanimationgroup.cpp \
+ animation/qparallelanimationgroup.cpp \
+ animation/qpauseanimation.cpp
diff --git a/src/corelib/animation/qabstractanimation.cpp b/src/corelib/animation/qabstractanimation.cpp
new file mode 100644
index 0000000..fcc63a4
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.cpp
@@ -0,0 +1,733 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAbstractAnimation
+ \ingroup animation
+ \brief The QAbstractAnimation class is the base of all animations.
+ \since 4.6
+
+ The class defines the functions for the functionality shared by
+ all animations. By inheriting this class, you can create custom
+ animations that plug into the rest of the animation framework.
+
+ The progress of an animation is given by its current time
+ (currentTime()), which is measured in milliseconds from the start
+ of the animation (0) to its end (duration()). The value is updated
+ automatically while the animation is running. It can also be set
+ directly with setCurrentTime().
+
+ At any point an animation is in one of three states:
+ \l{QAbstractAnimation::}{Running},
+ \l{QAbstractAnimation::}{Stopped}, or
+ \l{QAbstractAnimation::}{Paused}--as defined by the
+ \l{QAbstractAnimation::}{State} enum. The current state can be
+ changed by calling start(), stop(), pause(), or resume(). An
+ animation will always reset its \l{currentTime()}{current time}
+ when it is started. If paused, it will continue with the same
+ current time when resumed. When an animation is stopped, it cannot
+ be resumed, but will keep its current time (until started again).
+ QAbstractAnimation will emit stateChanged() whenever its state
+ changes.
+
+ An animation can loop any number of times by setting the loopCount
+ property. When an animation's current time reaches its duration(),
+ it will reset the current time and keep running. A loop count of 1
+ (the default value) means that the animation will run one time.
+ Note that a duration of -1 means that the animation will run until
+ stopped; the current time will increase indefinitely. When the
+ current time equals duration() and the animation is in its
+ final loop, the \l{QAbstractAnimation::}{Stopped} state is
+ entered, and the finished() signal is emitted.
+
+ QAbstractAnimation provides pure virtual functions used by
+ subclasses to track the progress of the animation: duration() and
+ updateCurrentTime(). The duration() function lets you report a
+ duration for the animation (as discussed above). The current time
+ is delivered by the animation framework through calls to
+ updateCurrentTime(). By reimplementing this function, you can
+ track the animation progress. Note that neither the interval
+ between calls nor the number of calls to this function are
+ defined; though, it will normally be 60 updates per second.
+
+ By reimplementing updateState(), you can track the animation's
+ state changes, which is particularly useful for animations that
+ are not driven by time.
+
+ \sa QVariantAnimation, QPropertyAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+/*!
+ \enum QAbstractAnimation::DeletionPolicy
+
+ \value KeepWhenStopped The animation will not be deleted when stopped.
+ \value DeleteWhenStopped The animation will be automatically deleted when
+ stopped.
+*/
+
+/*!
+ \fn QAbstractAnimation::finished()
+
+ QAbstractAnimation emits this signal after the animation has stopped and
+ has reached the end.
+
+ This signal is emitted after stateChanged().
+
+ \sa stateChanged()
+*/
+
+/*!
+ \fn QAbstractAnimation::stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState)
+
+ QAbstractAnimation emits this signal whenever the state of the animation has
+ changed from \a oldState to \a newState. This signal is emitted after the virtual
+ updateState() function is called.
+
+ \sa updateState()
+*/
+
+/*!
+ \fn QAbstractAnimation::currentLoopChanged(int currentLoop)
+
+ QAbstractAnimation emits this signal whenever the current loop
+ changes. \a currentLoop is the current loop.
+
+ \sa currentLoop(), loopCount()
+*/
+
+/*!
+ \fn QAbstractAnimation::directionChanged(QAbstractAnimation::Direction newDirection);
+
+ QAbstractAnimation emits this signal whenever the direction has been
+ changed. \a newDirection is the new direction.
+
+ \sa direction
+*/
+
+#include "qabstractanimation.h"
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+
+#include "qabstractanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qthreadstorage.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qpointer.h>
+
+#ifndef QT_NO_ANIMATION
+
+#define DEFAULT_TIMER_INTERVAL 16
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QThreadStorage<QUnifiedTimer *>, unifiedTimer)
+
+QUnifiedTimer::QUnifiedTimer() : QObject(), lastTick(0), timingInterval(DEFAULT_TIMER_INTERVAL), consistentTiming(false)
+{
+}
+
+QUnifiedTimer *QUnifiedTimer::instance()
+{
+ QUnifiedTimer *inst;
+ if (!unifiedTimer()->hasLocalData()) {
+ inst = new QUnifiedTimer;
+ unifiedTimer()->setLocalData(inst);
+ } else {
+ inst = unifiedTimer()->localData();
+ }
+ return inst;
+}
+
+void QUnifiedTimer::updateRecentlyStartedAnimations()
+{
+ if (animationsToStart.isEmpty())
+ return;
+
+ animations += animationsToStart;
+ updateTimer(); //we make sure we start the timer there
+
+ animationsToStart.clear();
+}
+
+void QUnifiedTimer::timerEvent(QTimerEvent *event)
+{
+ //this is simply the time we last received a tick
+ const int oldLastTick = lastTick;
+ if (time.isValid())
+ lastTick = consistentTiming ? oldLastTick + timingInterval : time.elapsed();
+
+ //we transfer the waiting animations into the "really running" state
+ updateRecentlyStartedAnimations();
+
+ if (event->timerId() == startStopAnimationTimer.timerId()) {
+ startStopAnimationTimer.stop();
+ if (animations.isEmpty()) {
+ animationTimer.stop();
+ time = QTime();
+ } else {
+ animationTimer.start(timingInterval, this);
+ lastTick = 0;
+ time.start();
+ }
+ } else if (event->timerId() == animationTimer.timerId()) {
+ const int delta = lastTick - oldLastTick;
+ for (int i = 0; i < animations.count(); ++i) {
+ QAbstractAnimation *animation = animations.at(i);
+ int elapsed = QAbstractAnimationPrivate::get(animation)->totalCurrentTime
+ + (animation->direction() == QAbstractAnimation::Forward ? delta : -delta);
+ animation->setCurrentTime(elapsed);
+ }
+ }
+}
+
+void QUnifiedTimer::updateTimer()
+{
+ //we delay the call to start and stop for the animation timer so that if you
+ //stop and start animations in batch you don't stop/start the timer too often.
+ if (!startStopAnimationTimer.isActive())
+ startStopAnimationTimer.start(0, this); // we delay the actual start of the animation
+}
+
+void QUnifiedTimer::registerAnimation(QAbstractAnimation *animation)
+{
+ if (animations.contains(animation) ||animationsToStart.contains(animation))
+ return;
+ animationsToStart << animation;
+ updateTimer();
+}
+
+void QUnifiedTimer::unregisterAnimation(QAbstractAnimation *animation)
+{
+ animations.removeAll(animation);
+ animationsToStart.removeAll(animation);
+ updateTimer();
+}
+
+
+void QAbstractAnimationPrivate::setState(QAbstractAnimation::State newState)
+{
+ Q_Q(QAbstractAnimation);
+ if (state == newState)
+ return;
+
+ QAbstractAnimation::State oldState = state;
+ int oldCurrentTime = currentTime;
+ int oldCurrentLoop = currentLoop;
+ QAbstractAnimation::Direction oldDirection = direction;
+
+ state = newState;
+
+ QPointer<QAbstractAnimation> guard(q);
+
+ guard->updateState(oldState, newState);
+
+ //this is to be safe if updateState changes the state
+ if (state == oldState)
+ return;
+
+ // Notify state change
+ if (guard)
+ emit guard->stateChanged(oldState, newState);
+
+ // Enter running state.
+ switch (state)
+ {
+ case QAbstractAnimation::Paused:
+ case QAbstractAnimation::Running:
+ {
+ // Rewind
+ if (oldState == QAbstractAnimation::Stopped) {
+ if (guard) {
+ if (direction == QAbstractAnimation::Forward)
+ q->setCurrentTime(0);
+ else
+ q->setCurrentTime(loopCount == -1 ? q->duration() : q->totalDuration());
+ }
+
+ // Check if the setCurrentTime() function called stop().
+ // This can happen for a 0-duration animation
+ if (state == QAbstractAnimation::Stopped)
+ return;
+ }
+
+ // Register timer if our parent is not running.
+ if (state == QAbstractAnimation::Running && guard) {
+ if (!group || group->state() == QAbstractAnimation::Stopped) {
+ QUnifiedTimer::instance()->registerAnimation(q);
+ }
+ } else {
+ //new state is paused
+ QUnifiedTimer::instance()->unregisterAnimation(q);
+ }
+ }
+ break;
+ case QAbstractAnimation::Stopped:
+ // Leave running state.
+ int dura = q->duration();
+ if (deleteWhenStopped && guard)
+ q->deleteLater();
+
+ QUnifiedTimer::instance()->unregisterAnimation(q);
+
+ if (dura == -1 || loopCount < 0
+ || (oldDirection == QAbstractAnimation::Forward && (oldCurrentTime * (oldCurrentLoop + 1)) == (dura * loopCount))
+ || (oldDirection == QAbstractAnimation::Backward && oldCurrentTime == 0)) {
+ if (guard)
+ emit q->finished();
+ }
+ break;
+ }
+
+}
+
+/*!
+ Constructs the QAbstractAnimation base class, and passes \a parent to
+ QObject's constructor.
+
+ \sa QVariantAnimation, QAnimationGroup
+*/
+QAbstractAnimation::QAbstractAnimation(QObject *parent)
+ : QObject(*new QAbstractAnimationPrivate, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+
+/*!
+ \internal
+*/
+QAbstractAnimation::QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent)
+ : QObject(dd, 0)
+{
+ // Allow auto-add on reparent
+ setParent(parent);
+}
+
+/*!
+ Stops the animation if it's running, then destroys the
+ QAbstractAnimation. If the animation is part of a QAnimationGroup, it is
+ automatically removed before it's destroyed.
+*/
+QAbstractAnimation::~QAbstractAnimation()
+{
+ Q_D(QAbstractAnimation);
+ //we can't call stop here. Otherwise we get pure virtual calls
+ if (d->state != Stopped) {
+ QAbstractAnimation::State oldState = d->state;
+ d->state = Stopped;
+ emit stateChanged(oldState, d->state);
+ QUnifiedTimer::instance()->unregisterAnimation(this);
+ }
+}
+
+/*!
+ \property QAbstractAnimation::state
+ \brief state of the animation.
+
+ This property describes the current state of the animation. When the
+ animation state changes, QAbstractAnimation emits the stateChanged()
+ signal.
+*/
+QAbstractAnimation::State QAbstractAnimation::state() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->state;
+}
+
+/*!
+ If this animation is part of a QAnimationGroup, this function returns a
+ pointer to the group; otherwise, it returns 0.
+
+ \sa QAnimationGroup::addAnimation()
+*/
+QAnimationGroup *QAbstractAnimation::group() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->group;
+}
+
+/*!
+ \enum QAbstractAnimation::State
+
+ This enum describes the state of the animation.
+
+ \value Stopped The animation is not running. This is the initial state
+ of QAbstractAnimation, and the state QAbstractAnimation reenters when finished. The current
+ time remain unchanged until either setCurrentTime() is
+ called, or the animation is started by calling start().
+
+ \value Paused The animation is paused (i.e., temporarily
+ suspended). Calling resume() will resume animation activity.
+
+ \value Running The animation is running. While control is in the event
+ loop, QAbstractAnimation will update its current time at regular intervals,
+ calling updateCurrentTime() when appropriate.
+
+ \sa state(), stateChanged()
+*/
+
+/*!
+ \enum QAbstractAnimation::Direction
+
+ This enum describes the direction of the animation when in \l Running state.
+
+ \value Forward The current time of the animation increases with time (i.e.,
+ moves from 0 and towards the end / duration).
+
+ \value Backward The current time of the animation decreases with time (i.e.,
+ moves from the end / duration and towards 0).
+
+ \sa direction
+*/
+
+/*!
+ \property QAbstractAnimation::direction
+ \brief the direction of the animation when it is in \l Running
+ state.
+
+ This direction indicates whether the time moves from 0 towards the
+ animation duration, or from the value of the duration and towards 0 after
+ start() has been called.
+
+ By default, this property is set to \l Forward.
+*/
+QAbstractAnimation::Direction QAbstractAnimation::direction() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->direction;
+}
+void QAbstractAnimation::setDirection(Direction direction)
+{
+ Q_D(QAbstractAnimation);
+ if (d->direction == direction)
+ return;
+
+ d->direction = direction;
+ if (state() == Stopped) {
+ if (direction == Backward) {
+ d->currentTime = duration();
+ d->currentLoop = d->loopCount - 1;
+ } else {
+ d->currentTime = 0;
+ d->currentLoop = 0;
+ }
+ }
+ updateDirection(direction);
+ emit directionChanged(direction);
+}
+
+/*!
+ \property QAbstractAnimation::duration
+ \brief the duration of the animation.
+
+ If the duration is -1, it means that the duration is undefined.
+ In this case, loopCount is ignored.
+*/
+
+/*!
+ \property QAbstractAnimation::loopCount
+ \brief the loop count of the animation
+
+ This property describes the loop count of the animation as an integer.
+ By default this value is 1, indicating that the animation
+ should run once only, and then stop. By changing it you can let the
+ animation loop several times. With a value of 0, the animation will not
+ run at all, and with a value of -1, the animation will loop forever
+ until stopped.
+ It is not supported to have loop on an animation that has an undefined
+ duration. It will only run once.
+*/
+int QAbstractAnimation::loopCount() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->loopCount;
+}
+void QAbstractAnimation::setLoopCount(int loopCount)
+{
+ Q_D(QAbstractAnimation);
+ d->loopCount = loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentLoop
+ \brief the current loop of the animation
+
+ This property describes the current loop of the animation. By default,
+ the animation's loop count is 1, and so the current loop will
+ always be 0. If the loop count is 2 and the animation runs past its
+ duration, it will automatically rewind and restart at current time 0, and
+ current loop 1, and so on.
+
+ When the current loop changes, QAbstractAnimation emits the
+ currentLoopChanged() signal.
+*/
+int QAbstractAnimation::currentLoop() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentLoop;
+}
+
+/*!
+ \fn virtual int QAbstractAnimation::duration() const = 0
+
+ This pure virtual function returns the duration of the animation, and
+ defines for how long QAbstractAnimation should update the current
+ time. This duration is local, and does not include the loop count.
+
+ A return value of -1 indicates that the animation has no defined duration;
+ the animation should run forever until stopped. This is useful for
+ animations that are not time driven, or where you cannot easily predict
+ its duration (e.g., event driven audio playback in a game).
+
+ If the animation is a parallel QAnimationGroup, the duration will be the longest
+ duration of all its animations. If the animation is a sequential QAnimationGroup,
+ the duration will be the sum of the duration of all its animations.
+ \sa loopCount
+*/
+
+/*!
+ Returns the total and effective duration of the animation, including the
+ loop count.
+
+ \sa duration(), currentTime
+*/
+int QAbstractAnimation::totalDuration() const
+{
+ Q_D(const QAbstractAnimation);
+ if (d->loopCount < 0)
+ return -1;
+ int dura = duration();
+ if (dura == -1)
+ return -1;
+ return dura * d->loopCount;
+}
+
+/*!
+ \property QAbstractAnimation::currentTime
+ \brief the current time and progress of the animation
+
+ This property describes the animation's current time. You can change the
+ current time by calling setCurrentTime, or you can call start() and let
+ the animation run, setting the current time automatically as the animation
+ progresses.
+
+ The animation's current time starts at 0, and ends at duration(). If the
+ animation's loopCount is larger than 1, the current time will rewind and
+ start at 0 again for the consecutive loops. If the animation has a pause.
+ currentTime will also include the duration of the pause.
+
+ \sa loopCount
+ */
+int QAbstractAnimation::currentTime() const
+{
+ Q_D(const QAbstractAnimation);
+ return d->currentTime;
+}
+void QAbstractAnimation::setCurrentTime(int msecs)
+{
+ Q_D(QAbstractAnimation);
+ msecs = qMax(msecs, 0);
+
+ // Calculate new time and loop.
+ int dura = duration();
+ int totalDura = (d->loopCount < 0 || dura == -1) ? -1 : dura * d->loopCount;
+ if (totalDura != -1)
+ msecs = qMin(totalDura, msecs);
+ d->totalCurrentTime = msecs;
+
+ // Update new values.
+ int oldLoop = d->currentLoop;
+ d->currentLoop = ((dura <= 0) ? 0 : (msecs / dura));
+ if (d->currentLoop == d->loopCount) {
+ //we're at the end
+ d->currentTime = qMax(0, dura);
+ d->currentLoop = qMax(0, d->loopCount - 1);
+ } else {
+ if (d->direction == Forward) {
+ d->currentTime = (dura <= 0) ? msecs : (msecs % dura);
+ } else {
+ d->currentTime = (dura <= 0) ? msecs : ((msecs - 1) % dura) + 1;
+ if (d->currentTime == dura)
+ --d->currentLoop;
+ }
+ }
+
+ updateCurrentTime(msecs);
+ if (d->currentLoop != oldLoop)
+ emit currentLoopChanged(d->currentLoop);
+
+ // All animations are responsible for stopping the animation when their
+ // own end state is reached; in this case the animation is time driven,
+ // and has reached the end.
+ if ((d->direction == Forward && d->totalCurrentTime == totalDura)
+ || (d->direction == Backward && d->totalCurrentTime == 0)) {
+ stop();
+ }
+}
+
+/*!
+ Starts the animation. The \a policy argument says whether or not the
+ animation should be deleted when it's done. When the animation starts, the
+ stateChanged() signal is emitted, and state() returns Running. When control
+ reaches the event loop, the animation will run by itself, periodically
+ calling updateCurrentTime() as the animation progresses.
+
+ If the animation is currently stopped or has already reached the end,
+ calling start() will rewind the animation and start again from the beginning.
+ When the animation reaches the end, the animation will either stop, or
+ if the loop level is more than 1, it will rewind and continue from the beginning.
+
+ If the animation is already running, this function does nothing.
+
+ \sa stop(), state()
+*/
+void QAbstractAnimation::start(DeletionPolicy policy)
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Running)
+ return;
+ d->setState(Running);
+ d->deleteWhenStopped = policy;
+}
+
+/*!
+ Stops the animation. When the animation is stopped, it emits the stateChanged()
+ signal, and state() returns Stopped. The current time is not changed.
+
+ If the animation stops by itself after reaching the end (i.e.,
+ currentTime() == duration() and currentLoop() > loopCount() - 1), the
+ finished() signal is emitted.
+
+ \sa start(), state()
+ */
+void QAbstractAnimation::stop()
+{
+ Q_D(QAbstractAnimation);
+
+ d->setState(Stopped);
+}
+
+/*!
+ Pauses the animation. When the animation is paused, state() returns Paused.
+ The currenttime will remain unchanged until resume() or start() is called.
+ If you want to continue from the current time, call resume().
+
+
+ \sa start(), state(), resume()
+ */
+void QAbstractAnimation::pause()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state == Stopped) {
+ qWarning("QAbstractAnimation::pause: Cannot pause a stopped animation");
+ return;
+ }
+
+ d->setState(Paused);
+}
+
+/*!
+ Resumes the animation after it was paused. When the animation is resumed,
+ it emits the resumed() and stateChanged() signals. The currenttime is not
+ changed.
+
+ \sa start(), pause(), state()
+ */
+void QAbstractAnimation::resume()
+{
+ Q_D(QAbstractAnimation);
+ if (d->state != Paused) {
+ qWarning("QAbstractAnimation::resume: "
+ "Cannot resume an animation that is not paused");
+ return;
+ }
+
+ d->setState(Running);
+}
+
+/*!
+ \reimp
+*/
+bool QAbstractAnimation::event(QEvent *event)
+{
+ return QObject::event(event);
+}
+
+/*!
+ \fn virtual void QAbstractAnimation::updateCurrentTime(int msecs) = 0;
+
+ This pure virtual function is called every time the animation's current
+ time changes. The \a msecs argument is the current time.
+
+ \sa updateState()
+*/
+
+/*!
+ This virtual function is called by QAbstractAnimation when the state
+ of the animation is changed from \a oldState to \a newState.
+
+ \sa start(), stop(), pause(), resume()
+*/
+void QAbstractAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+ This virtual function is called by QAbstractAnimation when the direction
+ of the animation is changed. The \a direction argument is the new direction.
+
+ \sa setDirection(), direction()
+*/
+void QAbstractAnimation::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_UNUSED(direction);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qabstractanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qabstractanimation.h b/src/corelib/animation/qabstractanimation.h
new file mode 100644
index 0000000..d6d50dc
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation.h
@@ -0,0 +1,137 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_H
+#define QABSTRACTANIMATION_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroup;
+class QSequentialAnimationGroup;
+
+class QAbstractAnimationPrivate;
+class Q_CORE_EXPORT QAbstractAnimation : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(State state READ state NOTIFY stateChanged)
+ Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
+ Q_PROPERTY(int currentTime READ currentTime WRITE setCurrentTime)
+ Q_PROPERTY(int currentLoop READ currentLoop NOTIFY currentLoopChanged)
+ Q_PROPERTY(Direction direction READ direction WRITE setDirection NOTIFY directionChanged)
+ Q_PROPERTY(int duration READ duration)
+
+public:
+ enum Direction {
+ Forward,
+ Backward
+ };
+
+ enum State {
+ Stopped,
+ Paused,
+ Running
+ };
+
+ enum DeletionPolicy {
+ KeepWhenStopped = 0,
+ DeleteWhenStopped
+ };
+
+ QAbstractAnimation(QObject *parent = 0);
+ virtual ~QAbstractAnimation();
+
+ State state() const;
+
+ QAnimationGroup *group() const;
+
+ Direction direction() const;
+ void setDirection(Direction direction);
+
+ int loopCount() const;
+ void setLoopCount(int loopCount);
+ int currentLoop() const;
+
+ virtual int duration() const = 0;
+ int totalDuration() const;
+
+ int currentTime() const;
+
+Q_SIGNALS:
+ void finished();
+ void stateChanged(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void currentLoopChanged(int currentLoop);
+ void directionChanged(QAbstractAnimation::Direction);
+
+public Q_SLOTS:
+ void start(QAbstractAnimation::DeletionPolicy policy = KeepWhenStopped);
+ void pause();
+ void resume();
+ void stop();
+ void setCurrentTime(int msecs);
+
+protected:
+ QAbstractAnimation(QAbstractAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ virtual void updateCurrentTime(int msecs) = 0;
+ virtual void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ virtual void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QAbstractAnimation)
+ Q_DECLARE_PRIVATE(QAbstractAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QABSTRACTANIMATION_H
diff --git a/src/corelib/animation/qabstractanimation_p.h b/src/corelib/animation/qabstractanimation_p.h
new file mode 100644
index 0000000..7a4bfcf
--- /dev/null
+++ b/src/corelib/animation/qabstractanimation_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTANIMATION_P_H
+#define QABSTRACTANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qbasictimer.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qtimer.h>
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroup;
+class QAbstractAnimation;
+class QAbstractAnimationPrivate : public QObjectPrivate
+{
+public:
+ QAbstractAnimationPrivate()
+ : state(QAbstractAnimation::Stopped),
+ direction(QAbstractAnimation::Forward),
+ deleteWhenStopped(false),
+ totalCurrentTime(0),
+ currentTime(0),
+ loopCount(1),
+ currentLoop(0),
+ group(0)
+ {
+ }
+
+ virtual ~QAbstractAnimationPrivate() {}
+
+ static QAbstractAnimationPrivate *get(QAbstractAnimation *q)
+ {
+ return q->d_func();
+ }
+
+ QAbstractAnimation::State state;
+ QAbstractAnimation::Direction direction;
+ bool deleteWhenStopped;
+ void setState(QAbstractAnimation::State state);
+
+ int totalCurrentTime;
+ int currentTime;
+ int loopCount;
+ int currentLoop;
+
+ QAnimationGroup *group;
+
+private:
+ Q_DECLARE_PUBLIC(QAbstractAnimation)
+};
+
+
+class QUnifiedTimer : public QObject
+{
+private:
+ QUnifiedTimer();
+
+public:
+ //XXX this is needed by dui
+ static Q_CORE_EXPORT QUnifiedTimer *instance();
+
+ void registerAnimation(QAbstractAnimation *animation);
+ void unregisterAnimation(QAbstractAnimation *animation);
+
+ //defines the timing interval. Default is DEFAULT_TIMER_INTERVAL
+ void setTimingInterval(int interval)
+ {
+ timingInterval = interval;
+ if (animationTimer.isActive()) {
+ //we changed the timing interval
+ animationTimer.start(timingInterval, this);
+ }
+ }
+
+ /*
+ this allows to have a consistent timer interval at each tick from the timer
+ not taking the real time that passed into account.
+ */
+ void setConsistentTiming(bool consistent) { consistentTiming = consistent; }
+
+ int elapsedTime() const { return lastTick; }
+
+protected:
+ void timerEvent(QTimerEvent *);
+ void updateTimer();
+
+private:
+ void updateRecentlyStartedAnimations();
+
+ QBasicTimer animationTimer, startStopAnimationTimer;
+ QTime time;
+ int lastTick;
+ int timingInterval;
+ bool consistentTiming;
+ QList<QAbstractAnimation*> animations, animationsToStart;
+};
+
+QT_END_NAMESPACE
+#endif
diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp
new file mode 100644
index 0000000..e192a6c
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.cpp
@@ -0,0 +1,309 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QAnimationGroup
+ \brief The QAnimationGroup class is an abstract base class for groups of animations.
+ \since 4.6
+ \ingroup animation
+
+ An animation group is a container for animations (subclasses of
+ QAbstractAnimation). A group is usually responsible for managing
+ the \l{QAbstractAnimation::State}{state} of its animations, i.e.,
+ it decides when to start, stop, resume, and pause them. Currently,
+ Qt provides two such groups: QParallelAnimationGroup and
+ QSequentialAnimationGroup. Look up their class descriptions for
+ details.
+
+ Since QAnimationGroup inherits from QAbstractAnimation, you can
+ combine groups, and easily construct complex animation graphs.
+ You can query QAbstractAnimation for the group it belongs to
+ (using the \l{QAbstractAnimation::}{group()} function).
+
+ To start a top-level animation group, you simply use the
+ \l{QAbstractAnimation::}{start()} function from
+ QAbstractAnimation. By a top-level animation group, we think of a
+ group that itself is not contained within another group. Starting
+ sub groups directly is not supported, and may lead to unexpected
+ behavior.
+
+ \omit OK, we'll put in a snippet on this here \endomit
+
+ QAnimationGroup provides methods for adding and retrieving
+ animations. Besides that, you can remove animations by calling
+ remove(), and clear the animation group by calling
+ clearAnimations(). You may keep track of changes in the group's
+ animations by listening to QEvent::ChildAdded and
+ QEvent::ChildRemoved events.
+
+ \omit OK, let's find a snippet here as well. \endomit
+
+ QAnimationGroup takes ownership of the animations it manages, and
+ ensures that they are deleted when the animation group is deleted.
+
+ You can also use a \l{The State Machine Framework}{state machine}
+ to create complex animations. The framework provides a special
+ state, QAnimationState, that plays an animation upon entry and
+ transitions to a new state when the animation has finished
+ playing. This technique can also be combined with using animation
+ groups.
+
+ \sa QAbstractAnimation, QVariantAnimation, {The Animation Framework}
+*/
+
+#include "qanimationgroup.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qcoreevent.h>
+#include "qanimationgroup_p.h"
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+
+/*!
+ Constructs a QAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QAnimationGroup::QAnimationGroup(QObject *parent)
+ : QAbstractAnimation(*new QAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
+ : QAbstractAnimation(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QAnimationGroup::~QAnimationGroup()
+{
+}
+
+/*!
+ Returns a pointer to the animation at \a index in this group. This
+ function is useful when you need access to a particular animation. \a
+ index is between 0 and animationCount() - 1.
+
+ \sa animationCount(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::animationAt(int index) const
+{
+ Q_D(const QAnimationGroup);
+
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::animationAt: index is out of bounds");
+ return 0;
+ }
+
+ return d->animations.at(index);
+}
+
+
+/*!
+ Returns the number of animations managed by this group.
+
+ \sa indexOfAnimation(), addAnimation(), animationAt()
+*/
+int QAnimationGroup::animationCount() const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.size();
+}
+
+/*!
+ Returns the index of \a animation. The returned index can be passed
+ to the other functions that take an index as an argument.
+
+ \sa insertAnimationAt(), animationAt(), takeAnimationAt()
+*/
+int QAnimationGroup::indexOfAnimation(QAbstractAnimation *animation) const
+{
+ Q_D(const QAnimationGroup);
+ return d->animations.indexOf(animation);
+}
+
+/*!
+ Adds \a animation to this group. This will call insertAnimationAt with
+ index equals to animationCount().
+
+ \note The group takes ownership of the animation.
+
+ \sa removeAnimation()
+*/
+void QAnimationGroup::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+ insertAnimationAt(d->animations.count(), animation);
+}
+
+/*!
+ Inserts \a animation into this animation group at \a index.
+ If \a index is 0 the animation is inserted at the beginning.
+ If \a index is animationCount(), the animation is inserted at the end.
+
+ \note The group takes ownership of the animation.
+
+ \sa takeAnimationAt(), addAnimation(), indexOfAnimation(), removeAnimation()
+*/
+void QAnimationGroup::insertAnimationAt(int index, QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QAnimationGroup::insertAnimationAt: index is out of bounds");
+ return;
+ }
+
+ if (QAnimationGroup *oldGroup = animation->group())
+ oldGroup->removeAnimation(animation);
+
+ d->animations.insert(index, animation);
+ QAbstractAnimationPrivate::get(animation)->group = this;
+ // this will make sure that ChildAdded event is sent to 'this'
+ animation->setParent(this);
+ d->animationInsertedAt(index);
+}
+
+/*!
+ Removes \a animation from this group. The ownership of \a animation is
+ transferred to the caller.
+
+ \sa takeAnimationAt(), insertAnimationAt(), addAnimation()
+*/
+void QAnimationGroup::removeAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAnimationGroup);
+
+ if (!animation) {
+ qWarning("QAnimationGroup::remove: cannot remove null animation");
+ return;
+ }
+ int index = d->animations.indexOf(animation);
+ if (index == -1) {
+ qWarning("QAnimationGroup::remove: animation is not part of this group");
+ return;
+ }
+
+ takeAnimationAt(index);
+}
+
+/*!
+ Returns the animation at \a index and removes it from the animation group.
+
+ \note The ownership of the animation is transferred to the caller.
+
+ \sa removeAnimation(), addAnimation(), insertAnimationAt(), indexOfAnimation()
+*/
+QAbstractAnimation *QAnimationGroup::takeAnimationAt(int index)
+{
+ Q_D(QAnimationGroup);
+ if (index < 0 || index >= d->animations.size()) {
+ qWarning("QAnimationGroup::takeAnimationAt: no animation at index %d", index);
+ return 0;
+ }
+ QAbstractAnimation *animation = d->animations.at(index);
+ QAbstractAnimationPrivate::get(animation)->group = 0;
+ // ### removing from list before doing setParent to avoid inifinite recursion
+ // in ChildRemoved event
+ d->animations.removeAt(index);
+ animation->setParent(0);
+ d->animationRemovedAt(index);
+ return animation;
+}
+
+/*!
+ Removes and deletes all animations in this animation group, and resets the current
+ time to 0.
+
+ \sa addAnimation(), removeAnimation()
+*/
+void QAnimationGroup::clearAnimations()
+{
+ Q_D(QAnimationGroup);
+ qDeleteAll(d->animations);
+}
+
+/*!
+ \reimp
+*/
+bool QAnimationGroup::event(QEvent *event)
+{
+ Q_D(QAnimationGroup);
+ if (event->type() == QEvent::ChildAdded) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ if (QAbstractAnimation *a = qobject_cast<QAbstractAnimation *>(childEvent->child())) {
+ if (a->group() != this)
+ addAnimation(a);
+ }
+ } else if (event->type() == QEvent::ChildRemoved) {
+ QChildEvent *childEvent = static_cast<QChildEvent *>(event);
+ QAbstractAnimation *a = static_cast<QAbstractAnimation *>(childEvent->child());
+ // You can only rely on the child being a QObject because in the QEvent::ChildRemoved
+ // case it might be called from the destructor.
+ int index = d->animations.indexOf(a);
+ if (index != -1)
+ takeAnimationAt(index);
+ }
+ return QAbstractAnimation::event(event);
+}
+
+
+void QAnimationGroupPrivate::animationRemovedAt(int index)
+{
+ Q_Q(QAnimationGroup);
+ Q_UNUSED(index);
+ if (animations.isEmpty()) {
+ currentTime = 0;
+ q->stop();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qanimationgroup.h b/src/corelib/animation/qanimationgroup.h
new file mode 100644
index 0000000..263bc38
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_H
+#define QANIMATIONGROUP_H
+
+#include <QtCore/qabstractanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QAnimationGroupPrivate;
+class Q_CORE_EXPORT QAnimationGroup : public QAbstractAnimation
+{
+ Q_OBJECT
+
+public:
+ QAnimationGroup(QObject *parent = 0);
+ ~QAnimationGroup();
+
+ QAbstractAnimation *animationAt(int index) const;
+ int animationCount() const;
+ int indexOfAnimation(QAbstractAnimation *animation) const;
+ void addAnimation(QAbstractAnimation *animation);
+ void insertAnimationAt(int index, QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QAbstractAnimation *takeAnimationAt(int index);
+ void clearAnimations();
+
+protected:
+ QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QAnimationGroup)
+ Q_DECLARE_PRIVATE(QAnimationGroup)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATIONGROUP_H
diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h
new file mode 100644
index 0000000..0f07138
--- /dev/null
+++ b/src/corelib/animation/qanimationgroup_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATIONGROUP_P_H
+#define QANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qanimationgroup.h"
+
+#include <QtCore/qlist.h>
+
+#include "private/qabstractanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QAnimationGroupPrivate : public QAbstractAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QAnimationGroup)
+public:
+ QAnimationGroupPrivate()
+ { }
+
+ virtual void animationInsertedAt(int index) { Q_UNUSED(index) };
+ virtual void animationRemovedAt(int index);
+
+ QList<QAbstractAnimation *> animations;
+};
+
+QT_END_NAMESPACE
+
+#endif //QANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp
new file mode 100644
index 0000000..6ec4679
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QParallelAnimationGroup
+ \brief The QParallelAnimationGroup class provides a parallel group of animations.
+ \since 4.6
+ \ingroup animation
+
+ QParallelAnimationGroup--a \l{QAnimationGroup}{container for
+ animations}--starts all its animations when it is
+ \l{QAbstractAnimation::start()}{started} itself, i.e., runs all
+ animations in parallel. The animation group finishes when the
+ longest lasting animation has finished.
+
+ You can treat QParallelAnimation as any other QAbstractAnimation,
+ e.g., pause, resume, or add it to other animation groups.
+
+ \code
+ QParallelAnimationGroup *group = new QParallelAnimationGroup;
+ group->addAnimation(anim1);
+ group->addAnimation(anim2);
+
+ group->start();
+ \endcode
+
+ In this example, \c anim1 and \c anim2 are two
+ \l{QPropertyAnimation}s that have already been set up.
+
+ \sa QAnimationGroup, QPropertyAnimation, {The Animation Framework}
+*/
+
+
+#include "qparallelanimationgroup.h"
+#include "qparallelanimationgroup_p.h"
+//#define QANIMATION_DEBUG
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ Constructs a QParallelAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QParallelAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QParallelAnimationGroup::QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QParallelAnimationGroup::~QParallelAnimationGroup()
+{
+}
+
+/*!
+ \reimp
+*/
+int QParallelAnimationGroup::duration() const
+{
+ Q_D(const QParallelAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret = qMax(ret, currentDuration);
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateCurrentTime(int)
+{
+ Q_D(QParallelAnimationGroup);
+ if (d->animations.isEmpty())
+ return;
+
+ if (d->currentLoop > d->lastLoop) {
+ // simulate completion of the loop
+ int dura = duration();
+ if (dura > 0) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ d->animations.at(i)->setCurrentTime(dura); // will stop
+ }
+ }
+ } else if (d->currentLoop < d->lastLoop) {
+ // simulate completion of the loop seeking backwards
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ animation->setCurrentTime(0);
+ animation->stop();
+ }
+ }
+
+ bool timeFwd = ((d->currentLoop == d->lastLoop && d->currentTime >= d->lastCurrentTime)
+ || d->currentLoop > d->lastLoop);
+#ifdef QANIMATION_DEBUG
+ qDebug("QParallellAnimationGroup %5d: setCurrentTime(%d), loop:%d, last:%d, timeFwd:%d, lastcurrent:%d, %d",
+ __LINE__, d->currentTime, d->currentLoop, d->lastLoop, timeFwd, d->lastCurrentTime, state());
+#endif
+ // finally move into the actual time of the current loop
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int dura = animation->totalDuration();
+ if (dura == -1 && d->isUncontrolledAnimationFinished(animation))
+ continue;
+ if (dura == -1 || (d->currentTime <= dura && dura != 0)
+ || (dura == 0 && d->currentLoop != d->lastLoop)) {
+ switch (state()) {
+ case Running:
+ animation->start();
+ break;
+ case Paused:
+ animation->pause();
+ break;
+ case Stopped:
+ default:
+ break;
+ }
+ }
+
+ if (dura <= 0) {
+ if (dura == -1)
+ animation->setCurrentTime(d->currentTime);
+ continue;
+ }
+
+ if ((timeFwd && d->lastCurrentTime <= dura)
+ || (!timeFwd && d->currentTime <= dura))
+ animation->setCurrentTime(d->currentTime);
+ if (d->currentTime > dura)
+ animation->stop();
+ }
+ d->lastLoop = d->currentLoop;
+ d->lastCurrentTime = d->currentTime;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QParallelAnimationGroup);
+ QAnimationGroup::updateState(oldState, newState);
+
+ switch (newState) {
+ case Stopped:
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->stop();
+ d->disconnectUncontrolledAnimations();
+ break;
+ case Paused:
+ for (int i = 0; i < d->animations.size(); ++i)
+ d->animations.at(i)->pause();
+ break;
+ case Running:
+ d->connectUncontrolledAnimations();
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ animation->stop();
+ animation->setDirection(d->direction);
+ animation->start();
+ }
+ break;
+ }
+}
+
+void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QAbstractAnimation *animation = qobject_cast<QAbstractAnimation *>(q->sender());
+ Q_ASSERT(animation);
+
+ int uncontrolledRunningCount = 0;
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ if (it.key() == animation) {
+ *it = animation->currentTime();
+ }
+ if (it.value() == -1)
+ ++uncontrolledRunningCount;
+ ++it;
+ }
+ }
+
+ if (uncontrolledRunningCount > 0)
+ return;
+
+ int maxDuration = 0;
+ for (int i = 0; i < animations.size(); ++i)
+ maxDuration = qMax(maxDuration, animations.at(i)->totalDuration());
+
+ if (currentTime >= maxDuration)
+ q->stop();
+}
+
+void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin();
+ while (it != uncontrolledFinishTime.end()) {
+ QObject::disconnect(it.key(), SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+ ++it;
+ }
+
+ uncontrolledFinishTime.clear();
+}
+
+void QParallelAnimationGroupPrivate::connectUncontrolledAnimations()
+{
+ Q_Q(QParallelAnimationGroup);
+
+ for (int i = 0; i < animations.size(); ++i) {
+ QAbstractAnimation *animation = animations.at(i);
+ if (animation->duration() == -1 || animation->loopCount() < 0) {
+ uncontrolledFinishTime[animation] = -1;
+ QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+ }
+ }
+}
+
+bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAnimation *anim) const
+{
+ return uncontrolledFinishTime.value(anim, -1) >= 0;
+}
+
+/*!
+ \reimp
+*/
+void QParallelAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QParallelAnimationGroup);
+ //we need to update the direction of the current animation
+ if (state() != Stopped) {
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ animation->setDirection(direction);
+ }
+ } else {
+ if (direction == Forward) {
+ d->lastLoop = 0;
+ d->lastCurrentTime = 0;
+ } else {
+ // Looping backwards with loopCount == -1 does not really work well...
+ d->lastLoop = (d->loopCount == -1 ? 0 : d->loopCount - 1);
+ d->lastCurrentTime = duration();
+ }
+ }
+}
+
+/*!
+ \reimp
+*/
+bool QParallelAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qparallelanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qparallelanimationgroup.h b/src/corelib/animation/qparallelanimationgroup.h
new file mode 100644
index 0000000..57a8146
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_H
+#define QPARALLELANIMATIONGROUP_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QParallelAnimationGroupPrivate;
+class Q_CORE_EXPORT QParallelAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+
+public:
+ QParallelAnimationGroup(QObject *parent = 0);
+ ~QParallelAnimationGroup();
+
+ int duration() const;
+
+protected:
+ QParallelAnimationGroup(QParallelAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QParallelAnimationGroup)
+ Q_DECLARE_PRIVATE(QParallelAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPARALLELANIMATIONGROUP
diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h
new file mode 100644
index 0000000..ecd6791
--- /dev/null
+++ b/src/corelib/animation/qparallelanimationgroup_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPARALLELANIMATIONGROUP_P_H
+#define QPARALLELANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qparallelanimationgroup.h"
+#include "private/qanimationgroup_p.h"
+#include <QtCore/QHash>
+
+QT_BEGIN_NAMESPACE
+
+class QParallelAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QParallelAnimationGroup)
+public:
+ QParallelAnimationGroupPrivate()
+ : lastLoop(0), lastCurrentTime(0)
+ {
+ }
+
+ QHash<QAbstractAnimation*, int> uncontrolledFinishTime;
+ int lastLoop;
+ int lastCurrentTime;
+
+ bool isUncontrolledAnimationFinished(QAbstractAnimation *anim) const;
+ void connectUncontrolledAnimations();
+ void disconnectUncontrolledAnimations();
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QPARALLELANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qpauseanimation.cpp b/src/corelib/animation/qpauseanimation.cpp
new file mode 100644
index 0000000..93043c2
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.cpp
@@ -0,0 +1,154 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPauseAnimation
+ \brief The QPauseAnimation class provides a pause for QSequentialAnimationGroup.
+ \since 4.6
+ \ingroup animation
+
+ If you wish to introduce a delay between animations in a
+ QSequentialAnimationGroup, you can insert a QPauseAnimation. This
+ class does not animate anything, but does not
+ \l{QAbstractAnimation::finished()}{finish} before a specified
+ number of milliseconds have elapsed from when it was started. You
+ specify the duration of the pause in the constructor. It can also
+ be set directly with setDuration().
+
+ It is not necessary to construct a QPauseAnimation yourself.
+ QSequentialAnimationGroup provides the convenience functions
+ \l{QSequentialAnimationGroup::}{addPause()} and
+ \l{QSequentialAnimationGroup::}{insertPauseAt()}. These functions
+ simply take the number of milliseconds the pause should last.
+
+ \sa QSequentialAnimationGroup
+*/
+
+#include "qpauseanimation.h"
+#include "qabstractanimation_p.h"
+
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+class QPauseAnimationPrivate : public QAbstractAnimationPrivate
+{
+public:
+ QPauseAnimationPrivate() : QAbstractAnimationPrivate(), duration(0)
+ {
+ }
+
+ int duration;
+};
+
+/*!
+ Constructs a QPauseAnimation.
+ \a parent is passed to QObject's constructor.
+ The default duration is 0.
+*/
+
+QPauseAnimation::QPauseAnimation(QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+}
+
+/*!
+ Constructs a QPauseAnimation.
+ \a msecs is the duration of the pause.
+ \a parent is passed to QObject's constructor.
+*/
+
+QPauseAnimation::QPauseAnimation(int msecs, QObject *parent) : QAbstractAnimation(*new QPauseAnimationPrivate, parent)
+{
+ setDuration(msecs);
+}
+
+/*!
+ Destroys the pause animation.
+*/
+QPauseAnimation::~QPauseAnimation()
+{
+}
+
+/*!
+ \property QPauseAnimation::duration
+ \brief the duration of the pause.
+
+ The duration of the pause. The duration should not be negative.
+*/
+int QPauseAnimation::duration() const
+{
+ Q_D(const QPauseAnimation);
+ return d->duration;
+}
+
+void QPauseAnimation::setDuration(int msecs)
+{
+ if (msecs < 0) {
+ qWarning("QPauseAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ Q_D(QPauseAnimation);
+ d->duration = msecs;
+}
+
+/*!
+ \reimp
+ */
+bool QPauseAnimation::event(QEvent *e)
+{
+ return QAbstractAnimation::event(e);
+}
+
+/*!
+ \reimp
+ */
+void QPauseAnimation::updateCurrentTime(int msecs)
+{
+ Q_UNUSED(msecs);
+}
+
+
+QT_END_NAMESPACE
+
+#include "moc_qpauseanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpauseanimation.h b/src/corelib/animation/qpauseanimation.h
new file mode 100644
index 0000000..cb6e041
--- /dev/null
+++ b/src/corelib/animation/qpauseanimation.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAUSEANIMATION_P_H
+#define QPAUSEANIMATION_P_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimationPrivate;
+
+class Q_CORE_EXPORT QPauseAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+public:
+ QPauseAnimation(QObject *parent = 0);
+ QPauseAnimation(int msecs, QObject *parent = 0);
+ ~QPauseAnimation();
+
+ int duration() const;
+ void setDuration(int msecs);
+
+protected:
+ bool event(QEvent *e);
+ void updateCurrentTime(int msecs);
+
+private:
+ Q_DISABLE_COPY(QPauseAnimation)
+ Q_DECLARE_PRIVATE(QPauseAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPAUSEANIMATION_P_H
diff --git a/src/corelib/animation/qpropertyanimation.cpp b/src/corelib/animation/qpropertyanimation.cpp
new file mode 100644
index 0000000..65f1361
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QPropertyAnimation
+ \brief The QPropertyAnimation class animates Qt properties
+ \since 4.6
+ \ingroup animation
+
+ QPropertyAnimation interpolates over \l{Qt's Property System}{Qt
+ properties}. As property values are stored in \l{QVariant}s, the
+ class inherits QVariantAnimation, and supports animation of the
+ same \l{QVariant::Type}{variant types} as its super class.
+
+ A class declaring properties must be a QObject. To make it
+ possible to animate a property, it must provide a setter (so that
+ QPropertyAnimation can set the property's value). Note that this
+ makes it possible to animate many of Qt's widgets. Let's look at
+ an example:
+
+ \code
+ QPropertyAnimation animation(myWidget, "geometry");
+ animation.setDuration(10000);
+ animation.setStartValue(QRect(0, 0, 100, 30));
+ animation.setEndValue(QRect(250, 250, 100, 30));
+
+ animation.start();
+ \endcode
+
+ The property name and the QObject instance of which property
+ should be animated are passed to the constructor. You can then
+ specify the start and end value of the property. The procedure is
+ equal for properties in classes you have implemented
+ yourself--just check with QVariantAnimation that your QVariant
+ type is supported.
+
+ The QVariantAnimation class description explains how to set up the
+ animation in detail. Note, however, that if a start value is not
+ set, the property will start at the value it had when the
+ QPropertyAnimation instance was created.
+
+ QPropertyAnimation works like a charm on its own. For complex
+ animations that, for instance, contain several objects,
+ QAnimationGroup is provided. An animation group is an animation
+ that can contain other animations, and that can manage when its
+ animations are played. Look at QParallelAnimationGroup for an
+ example.
+
+ \sa QVariantAnimation, QAnimationGroup, {The Animation Framework}
+*/
+
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+#include "qpropertyanimation_p.h"
+
+#include <QtCore/qmath.h>
+#include <QtCore/qmutex.h>
+#include <private/qmutexpool_p.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+typedef QPair<QObject *, QByteArray> QPropertyAnimationPair;
+typedef QHash<QPropertyAnimationPair, QPropertyAnimation*> QPropertyAnimationHash;
+Q_GLOBAL_STATIC(QPropertyAnimationHash, _q_runningAnimations)
+
+void QPropertyAnimationPrivate::updateMetaProperty()
+{
+ if (!target || propertyName.isEmpty())
+ return;
+
+ if (!hasMetaProperty && !property.isValid()) {
+ const QMetaObject *mo = target->metaObject();
+ propertyIndex = mo->indexOfProperty(propertyName);
+ if (propertyIndex != -1) {
+ hasMetaProperty = true;
+ property = mo->property(propertyIndex);
+ propertyType = property.userType();
+ } else {
+ if (!target->dynamicPropertyNames().contains(propertyName))
+ qWarning("QPropertyAnimation: you're trying to animate a non-existing property %s of your QObject", propertyName.constData());
+ }
+ }
+
+ if (property.isValid())
+ convertValues(propertyType);
+}
+
+void QPropertyAnimationPrivate::updateProperty(const QVariant &newValue)
+{
+ if (!target || state == QAbstractAnimation::Stopped)
+ return;
+
+ if (hasMetaProperty) {
+ if (newValue.userType() == propertyType) {
+ //no conversion is needed, we directly call the QObject::qt_metacall
+ void *data = const_cast<void*>(newValue.constData());
+ target->qt_metacall(QMetaObject::WriteProperty, propertyIndex, &data);
+ } else {
+ property.write(target, newValue);
+ }
+ } else {
+ target->setProperty(propertyName.constData(), newValue);
+ }
+}
+
+void QPropertyAnimationPrivate::_q_targetDestroyed()
+{
+ Q_Q(QPropertyAnimation);
+ //we stop here so that this animation is removed from the global hash
+ q->stop();
+ target = 0;
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor.
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+}
+
+/*!
+ Construct a QPropertyAnimation object. \a parent is passed to QObject's
+ constructor. The animation changes the property \a propertyName on \a
+ target. The default duration is 250ms.
+
+ \sa targetObject, propertyName
+*/
+QPropertyAnimation::QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent)
+ : QVariantAnimation(*new QPropertyAnimationPrivate, parent)
+{
+ setTargetObject(target);
+ setPropertyName(propertyName);
+}
+
+/*!
+ Destroys the QPropertyAnimation instance.
+ */
+QPropertyAnimation::~QPropertyAnimation()
+{
+ stop();
+}
+
+/*!
+ \property QPropertyAnimation::targetObject
+ \brief the target QObject for this animation.
+
+ This property defines the target QObject for this animation.
+ */
+QObject *QPropertyAnimation::targetObject() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->target;
+}
+
+void QPropertyAnimation::setTargetObject(QObject *target)
+{
+ Q_D(QPropertyAnimation);
+ if (d->target == target)
+ return;
+
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setTargetObject: you can't change the target of a running animation");
+ return;
+ }
+
+ //we need to get notified when the target is destroyed
+ if (d->target)
+ disconnect(d->target, SIGNAL(destroyed()), this, SLOT(_q_targetDestroyed()));
+
+ if (target)
+ connect(target, SIGNAL(destroyed()), SLOT(_q_targetDestroyed()));
+
+ d->target = target;
+ d->hasMetaProperty = false;
+ d->updateMetaProperty();
+}
+
+/*!
+ \property QPropertyAnimation::propertyName
+ \brief the target property name for this animation
+
+ This property defines the target property name for this animation. The
+ property name is required for the animation to operate.
+ */
+QByteArray QPropertyAnimation::propertyName() const
+{
+ Q_D(const QPropertyAnimation);
+ return d->propertyName;
+}
+
+void QPropertyAnimation::setPropertyName(const QByteArray &propertyName)
+{
+ Q_D(QPropertyAnimation);
+ if (d->state != QAbstractAnimation::Stopped) {
+ qWarning("QPropertyAnimation::setPropertyName: you can't change the property name of a running animation");
+ return;
+ }
+
+ d->propertyName = propertyName;
+ d->hasMetaProperty = false;
+ d->updateMetaProperty();
+}
+
+
+/*!
+ \reimp
+ */
+bool QPropertyAnimation::event(QEvent *event)
+{
+ return QVariantAnimation::event(event);
+}
+
+/*!
+ This virtual function is called by QVariantAnimation whenever the current value
+ changes. \a value is the new, updated value. It updates the current value
+ of the property on the target object.
+
+ \sa currentValue, currentTime
+ */
+void QPropertyAnimation::updateCurrentValue(const QVariant &value)
+{
+ Q_D(QPropertyAnimation);
+ d->updateProperty(value);
+}
+
+/*!
+ \reimp
+
+ If the startValue is not defined when the state of the animation changes from Stopped to Running,
+ the current property value is used as the initial value for the animation.
+*/
+void QPropertyAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QPropertyAnimation);
+
+ if (!d->target) {
+ qWarning("QPropertyAnimation::updateState: Changing state of an animation without target");
+ return;
+ }
+
+ QVariantAnimation::updateState(oldState, newState);
+
+ QPropertyAnimation *animToStop = 0;
+ {
+ QPropertyAnimationHash * hash = _q_runningAnimations();
+ QMutexLocker locker(QMutexPool::globalInstanceGet(hash));
+ QPropertyAnimationPair key(d->target, d->propertyName);
+ if (newState == Running) {
+ d->updateMetaProperty();
+ animToStop = hash->value(key, 0);
+ hash->insert(key, this);
+ // update the default start value
+ if (oldState == Stopped) {
+ d->setDefaultStartValue(d->target->property(d->propertyName.constData()));
+ }
+ } else if (hash->value(key) == this) {
+ hash->remove(key);
+ }
+ }
+
+ //we need to do that after the mutex was unlocked
+ if (animToStop) {
+ // try to stop the top level group
+ QAbstractAnimation *current = animToStop;
+ while (current->group() && current->state() != Stopped)
+ current = current->group();
+ current->stop();
+ }
+}
+
+#include "moc_qpropertyanimation.cpp"
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qpropertyanimation.h b/src/corelib/animation/qpropertyanimation.h
new file mode 100644
index 0000000..2fdd50c
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_H
+#define QPROPERTYANIMATION_H
+
+#include <QtCore/qvariantanimation.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPropertyAnimationPrivate;
+class Q_CORE_EXPORT QPropertyAnimation : public QVariantAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QByteArray propertyName READ propertyName WRITE setPropertyName)
+ Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
+
+public:
+ QPropertyAnimation(QObject *parent = 0);
+ QPropertyAnimation(QObject *target, const QByteArray &propertyName, QObject *parent = 0);
+ ~QPropertyAnimation();
+
+ QObject *targetObject() const;
+ void setTargetObject(QObject *target);
+
+ QByteArray propertyName() const;
+ void setPropertyName(const QByteArray &propertyName);
+
+protected:
+ bool event(QEvent *event);
+ void updateCurrentValue(const QVariant &value);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+
+private:
+ Q_PRIVATE_SLOT(d_func(), void _q_targetDestroyed())
+ Q_DISABLE_COPY(QPropertyAnimation)
+ Q_DECLARE_PRIVATE(QPropertyAnimation)
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROPERTYANIMATION_H
diff --git a/src/corelib/animation/qpropertyanimation_p.h b/src/corelib/animation/qpropertyanimation_p.h
new file mode 100644
index 0000000..16c63ab
--- /dev/null
+++ b/src/corelib/animation/qpropertyanimation_p.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROPERTYANIMATION_P_H
+#define QPROPERTYANIMATION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpropertyanimation.h"
+#include <QtCore/qmetaobject.h>
+
+#include "private/qvariantanimation_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QPropertyAnimationPrivate : public QVariantAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QPropertyAnimation)
+public:
+ QPropertyAnimationPrivate()
+ : target(0), propertyType(0), propertyIndex(0), hasMetaProperty(false)
+ {
+ }
+
+ void _q_targetDestroyed();
+
+ QObject *target;
+
+ //for the QProperty
+ QMetaProperty property;
+ int propertyType;
+ int propertyIndex;
+
+ bool hasMetaProperty;
+ QByteArray propertyName;
+ void updateProperty(const QVariant &);
+ void updateMetaProperty();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp
new file mode 100644
index 0000000..25db52f
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.cpp
@@ -0,0 +1,592 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*!
+ \class QSequentialAnimationGroup
+ \brief The QSequentialAnimationGroup class provides a sequential group of animations.
+ \since 4.6
+ \ingroup animation
+
+ QSequentialAnimationGroup is a QAnimationGroup that runs its
+ animations in sequence, i.e., it starts one animation after
+ another has finished playing. The animations are played in the
+ order they are added to the group (using
+ \l{QAnimationGroup::}{addAnimation()} or
+ \l{QAnimationGroup::}{insertAnimationAt()}). The animation group
+ finishes when its last animation has finished.
+
+ At each moment there is at most one animation that is active in
+ the group; it is returned by currentAnimation(). An empty group
+ has no current animation.
+
+ A sequential animation group can be treated as any other
+ animation, i.e., it can be started, stopped, and added to other
+ groups. You can also call addPause() or insertPauseAt() to add a
+ pause to a sequential animation group.
+
+ \code
+ QSequentialAnimationGroup group;
+
+ group.addAnimation(anim1);
+ group.addAnimation(anim2);
+
+ group.start();
+ \endcode
+
+ In this example, \c anim1 and \c anim2 are two already set up
+ \l{QPropertyAnimation}s.
+
+ \sa QAnimationGroup, QAbstractAnimation, {The Animation Framework}
+*/
+
+#include "qsequentialanimationgroup.h"
+#include "qsequentialanimationgroup_p.h"
+
+#include "qpauseanimation.h"
+
+#include <QtCore/qdebug.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+bool QSequentialAnimationGroupPrivate::atEnd() const
+{
+ // we try to detect if we're at the end of the group
+ //this is true if the following conditions are true:
+ // 1. we're in the last loop
+ // 2. the direction is forward
+ // 3. the current animation is the last one
+ // 4. the current animation has reached its end
+ const int animTotalCurrentTime = QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ return (currentLoop == loopCount - 1
+ && direction == QAbstractAnimation::Forward
+ && currentAnimation == animations.last()
+ && animTotalCurrentTime == animationActualTotalDuration(currentAnimationIndex));
+}
+
+int QSequentialAnimationGroupPrivate::animationActualTotalDuration(int index) const
+{
+ QAbstractAnimation *anim = animations.at(index);
+ int ret = anim->totalDuration();
+ if (ret == -1 && actualDuration.size() > index)
+ ret = actualDuration.at(index); //we can try the actual duration there
+ return ret;
+}
+
+QSequentialAnimationGroupPrivate::AnimationIndex QSequentialAnimationGroupPrivate::indexForTime(int msecs) const
+{
+ Q_Q(const QSequentialAnimationGroup);
+ Q_ASSERT(!animations.isEmpty());
+
+ AnimationIndex ret;
+ int duration = 0;
+
+ // in case duration is -1, currentLoop will always be 0
+ ret.timeOffset = currentLoop * q->duration();
+
+ for (int i = 0; i < animations.size(); ++i) {
+ duration = animationActualTotalDuration(i);
+
+ // 'animation' is the current animation if one of these reasons is true:
+ // 1. it's duration is undefined
+ // 2. it ends after msecs
+ // 3. it is the last animation (this can happen in case there is at least 1 uncontrolled animation)
+ // 4. it ends exactly in msecs and the direction is backwards
+ if (duration == -1 || msecs < (ret.timeOffset + duration)
+ || (msecs == (ret.timeOffset + duration) && direction == QAbstractAnimation::Backward)) {
+ ret.index = i;
+ return ret;
+ }
+
+ // 'animation' has a non-null defined duration and is not the one at time 'msecs'.
+ ret.timeOffset += duration;
+ }
+
+ // this can only happen when one of those conditions is true:
+ // 1. the duration of the group is undefined and we passed its actual duration
+ // 2. there are only 0-duration animations in the group
+ ret.timeOffset -= duration;
+ ret.index = animations.size() - 1;
+ return ret;
+}
+
+void QSequentialAnimationGroupPrivate::restart()
+{
+ // restarting the group by making the first/last animation the current one
+ if (direction == QAbstractAnimation::Forward) {
+ lastLoop = 0;
+ if (currentAnimationIndex == 0)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0);
+ } else { // direction == QAbstractAnimation::Backward
+ lastLoop = loopCount - 1;
+ int index = animations.size() - 1;
+ if (currentAnimationIndex == index)
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(index);
+ }
+}
+
+/*!
+ \internal
+ This manages advancing the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for rewinding the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::advanceForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop < currentLoop) {
+ // we need to fast forward to the end
+ for (int i = currentAnimationIndex; i < animations.size(); ++i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // this will make sure the current animation is reset to the beginning
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(0, true);
+ }
+
+ // and now we need to fast forward from the current position to
+ for (int i = currentAnimationIndex; i < newAnimationIndex.index; ++i) { //### WRONG,
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(animationActualTotalDuration(i));
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \internal
+ This manages rewinding the execution of a group running forwards (time has gone forward),
+ which is the same behaviour for advancing the execution of a group running backwards
+ (time has gone backward).
+*/
+void QSequentialAnimationGroupPrivate::rewindForwards(const AnimationIndex &newAnimationIndex)
+{
+ if (lastLoop > currentLoop) {
+ // we need to fast rewind to the beginning
+ for (int i = currentAnimationIndex; i >= 0 ; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // this will make sure the current animation is reset to the end
+ if (animations.size() == 1)
+ // we need to force activation because setCurrentAnimation will have no effect
+ activateCurrentAnimation();
+ else
+ setCurrentAnimation(animations.count() - 1, true);
+ }
+
+ // and now we need to fast rewind from the current position to
+ for (int i = currentAnimationIndex; i > newAnimationIndex.index; --i) {
+ QAbstractAnimation *anim = animations.at(i);
+ setCurrentAnimation(i, true);
+ anim->setCurrentTime(0);
+ }
+ // setting the new current animation will happen later
+}
+
+/*!
+ \fn QSequentialAnimationGroup::currentAnimationChanged(QAbstractAnimation *current)
+
+ QSequentialAnimationGroup emits this signal when currentAnimation
+ has been changed. \a current is the current animation.
+
+ \sa currentAnimation()
+*/
+
+
+/*!
+ Constructs a QSequentialAnimationGroup.
+ \a parent is passed to QObject's constructor.
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QObject *parent)
+ : QAnimationGroup(*new QSequentialAnimationGroupPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QSequentialAnimationGroup::QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd,
+ QObject *parent)
+ : QAnimationGroup(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation group. It will also destroy all its animations.
+*/
+QSequentialAnimationGroup::~QSequentialAnimationGroup()
+{
+}
+
+/*!
+ Adds a pause of \a msecs to this animation group.
+ The pause is considered as a special type of animation, thus count() will be
+ increased by one.
+ \sa insertPauseAt(), QAnimationGroup::addAnimation()
+*/
+QPauseAnimation *QSequentialAnimationGroup::addPause(int msecs)
+{
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ addAnimation(pause);
+ return pause;
+}
+
+/*!
+ Inserts a pause of \a msecs milliseconds at \a index in this animation
+ group.
+
+ \sa addPause(), QAnimationGroup::insertAnimationAt()
+*/
+QPauseAnimation *QSequentialAnimationGroup::insertPauseAt(int index, int msecs)
+{
+ Q_D(const QSequentialAnimationGroup);
+
+ if (index < 0 || index > d->animations.size()) {
+ qWarning("QSequentialAnimationGroup::insertPauseAt: index is out of bounds");
+ return 0;
+ }
+
+ QPauseAnimation *pause = new QPauseAnimation(msecs);
+ insertAnimationAt(index, pause);
+ return pause;
+}
+
+
+/*!
+ \property QSequentialAnimationGroup::currentAnimation
+ Returns the animation in the current time.
+
+ \sa currentAnimationChanged()
+*/
+QAbstractAnimation *QSequentialAnimationGroup::currentAnimation() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ return d->currentAnimation;
+}
+
+/*!
+ \reimp
+*/
+int QSequentialAnimationGroup::duration() const
+{
+ Q_D(const QSequentialAnimationGroup);
+ int ret = 0;
+
+ for (int i = 0; i < d->animations.size(); ++i) {
+ QAbstractAnimation *animation = d->animations.at(i);
+ const int currentDuration = animation->totalDuration();
+ if (currentDuration == -1)
+ return -1; // Undetermined length
+
+ ret += currentDuration;
+ }
+
+ return ret;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateCurrentTime(int msecs)
+{
+ Q_D(QSequentialAnimationGroup);
+ if (!d->currentAnimation)
+ return;
+
+ const QSequentialAnimationGroupPrivate::AnimationIndex newAnimationIndex = d->indexForTime(msecs);
+
+ // remove unneeded animations from actualDuration list
+ while (newAnimationIndex.index < d->actualDuration.size())
+ d->actualDuration.removeLast();
+
+ // newAnimationIndex.index is the new current animation
+ if (d->lastLoop < d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex < newAnimationIndex.index)) {
+ // advancing with forward direction is the same as rewinding with backwards direction
+ d->advanceForwards(newAnimationIndex);
+ } else if (d->lastLoop > d->currentLoop
+ || (d->lastLoop == d->currentLoop && d->currentAnimationIndex > newAnimationIndex.index)) {
+ // rewinding with forward direction is the same as advancing with backwards direction
+ d->rewindForwards(newAnimationIndex);
+ }
+
+ d->setCurrentAnimation(newAnimationIndex.index);
+
+ const int newCurrentTime = msecs - newAnimationIndex.timeOffset;
+
+ if (d->currentAnimation) {
+ d->currentAnimation->setCurrentTime(newCurrentTime);
+ if (d->atEnd()) {
+ //we make sure that we don't exceed the duration here
+ d->currentTime += QAbstractAnimationPrivate::get(d->currentAnimation)->totalCurrentTime - newCurrentTime;
+ stop();
+ }
+ } else {
+ //the only case where currentAnimation could be null
+ //is when all animations have been removed
+ Q_ASSERT(d->animations.isEmpty());
+ d->currentTime = 0;
+ stop();
+ }
+
+ d->lastLoop = d->currentLoop;
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_D(QSequentialAnimationGroup);
+ QAnimationGroup::updateState(oldState, newState);
+
+ if (!d->currentAnimation)
+ return;
+
+ switch (newState) {
+ case Stopped:
+ d->currentAnimation->stop();
+ break;
+ case Paused:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Running) {
+ d->currentAnimation->pause();
+ }
+ else
+ d->restart();
+ break;
+ case Running:
+ if (oldState == d->currentAnimation->state()
+ && oldState == QSequentialAnimationGroup::Paused)
+ d->currentAnimation->start();
+ else
+ d->restart();
+ break;
+ }
+}
+
+/*!
+ \reimp
+*/
+void QSequentialAnimationGroup::updateDirection(QAbstractAnimation::Direction direction)
+{
+ Q_D(QSequentialAnimationGroup);
+ // we need to update the direction of the current animation
+ if (state() != Stopped && d->currentAnimation)
+ d->currentAnimation->setDirection(direction);
+}
+
+/*!
+ \reimp
+*/
+bool QSequentialAnimationGroup::event(QEvent *event)
+{
+ return QAnimationGroup::event(event);
+}
+
+void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ index = qMin(index, animations.count() - 1);
+
+ if (index == -1) {
+ Q_ASSERT(animations.isEmpty());
+ currentAnimationIndex = -1;
+ currentAnimation = 0;
+ return;
+ }
+
+ // need these two checks below because this func can be called after the current animation
+ // has been removed
+ if (index == currentAnimationIndex && animations.at(index) == currentAnimation)
+ return;
+
+ // stop the old current animation
+ if (currentAnimation)
+ currentAnimation->stop();
+
+ currentAnimation = animations.at(index);
+ currentAnimationIndex = index;
+
+ emit q->currentAnimationChanged(currentAnimation);
+
+ activateCurrentAnimation(intermediate);
+}
+
+void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediate)
+{
+ Q_Q(QSequentialAnimationGroup);
+
+ if (!currentAnimation)
+ return;
+
+ if (state == QSequentialAnimationGroup::Stopped)
+ return;
+
+ currentAnimation->stop();
+
+ // we ensure the direction is consistent with the group's direction
+ currentAnimation->setDirection(direction);
+
+ // connects to the finish signal of uncontrolled animations
+ if (currentAnimation->totalDuration() == -1)
+ QObject::connect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+
+ currentAnimation->start();
+ if (!intermediate && state == QSequentialAnimationGroup::Paused)
+ currentAnimation->pause();
+}
+
+void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished()
+{
+ Q_Q(QSequentialAnimationGroup);
+ Q_ASSERT(qobject_cast<QAbstractAnimation *>(q->sender()) == currentAnimation);
+
+ // we trust the duration returned by the animation
+ while (actualDuration.size() < (currentAnimationIndex + 1))
+ actualDuration.append(-1);
+ actualDuration[currentAnimationIndex] = currentAnimation->currentTime();
+
+ QObject::disconnect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished()));
+
+ if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last())
+ || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) {
+ // we don't handle looping of a group with undefined duration
+ q->stop();
+ } else if (direction == QAbstractAnimation::Forward) {
+ // set the current animation to be the next one
+ setCurrentAnimation(currentAnimationIndex + 1);
+ } else {
+ // set the current animation to be the previous one
+ setCurrentAnimation(currentAnimationIndex - 1);
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is added to
+ the group at index \a index.
+ Note: We only support insertion after the current animation
+*/
+void QSequentialAnimationGroupPrivate::animationInsertedAt(int index)
+{
+ if (currentAnimation == 0)
+ setCurrentAnimation(0); // initialize the current animation
+
+ if (currentAnimationIndex == index
+ && currentAnimation->currentTime() == 0 && currentAnimation->currentLoop() == 0) {
+ //in this case we simply insert an animation before the current one has actually started
+ setCurrentAnimation(index);
+ }
+
+ //we update currentAnimationIndex in case it has changed (the animation pointer is still valid)
+ currentAnimationIndex = animations.indexOf(currentAnimation);
+
+ if (index < currentAnimationIndex || currentLoop != 0) {
+ qWarning("QSequentialGroup::insertAnimationAt only supports to add animations after the current one.");
+ return; //we're not affected because it is added after the current one
+ }
+}
+
+/*!
+ \internal
+ This method is called whenever an animation is removed from
+ the group at index \a index. The animation is no more listed when this
+ method is called.
+*/
+void QSequentialAnimationGroupPrivate::animationRemovedAt(int index)
+{
+ Q_Q(QSequentialAnimationGroup);
+ QAnimationGroupPrivate::animationRemovedAt(index);
+
+ Q_ASSERT(currentAnimation); // currentAnimation should always be set
+
+ if (actualDuration.size() > index)
+ actualDuration.removeAt(index);
+
+ const int currentIndex = animations.indexOf(currentAnimation);
+ if (currentIndex == -1) {
+ //we're removing the current animation, let's update it to another one
+ if (index < animations.count())
+ setCurrentAnimation(index); //let's try to take the next one
+ else if (index > 0)
+ setCurrentAnimation(index - 1);
+ else// case all animations were removed
+ setCurrentAnimation(-1);
+ } else if (currentAnimationIndex > index) {
+ currentAnimationIndex--;
+ }
+
+ // duration of the previous animations up to the current animation
+ currentTime = 0;
+ for (int i = 0; i < currentAnimationIndex; ++i) {
+ const int current = animationActualTotalDuration(i);
+ currentTime += current;
+ }
+
+ if (currentIndex != -1) {
+ //the current animation is not the one being removed
+ //so we add its current time to the current time of this group
+ currentTime += QAbstractAnimationPrivate::get(currentAnimation)->totalCurrentTime;
+ }
+
+ //let's also update the total current time
+ totalCurrentTime = currentTime + loopCount * q->duration();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qsequentialanimationgroup.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qsequentialanimationgroup.h b/src/corelib/animation/qsequentialanimationgroup.h
new file mode 100644
index 0000000..4701a76
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_H
+#define QSEQUENTIALANIMATIONGROUP_H
+
+#include <QtCore/qanimationgroup.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QPauseAnimation;
+class QSequentialAnimationGroupPrivate;
+
+class Q_CORE_EXPORT QSequentialAnimationGroup : public QAnimationGroup
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractAnimation* currentAnimation READ currentAnimation NOTIFY currentAnimationChanged)
+
+public:
+ QSequentialAnimationGroup(QObject *parent = 0);
+ ~QSequentialAnimationGroup();
+
+ QPauseAnimation *addPause(int msecs);
+ QPauseAnimation *insertPauseAt(int index, int msecs);
+
+ QAbstractAnimation *currentAnimation() const;
+ int duration() const;
+
+Q_SIGNALS:
+ void currentAnimationChanged(QAbstractAnimation *current);
+
+protected:
+ QSequentialAnimationGroup(QSequentialAnimationGroupPrivate &dd, QObject *parent);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+ void updateDirection(QAbstractAnimation::Direction direction);
+
+private:
+ Q_DISABLE_COPY(QSequentialAnimationGroup)
+ Q_DECLARE_PRIVATE(QSequentialAnimationGroup)
+ Q_PRIVATE_SLOT(d_func(), void _q_uncontrolledAnimationFinished())
+};
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QSEQUENTIALANIMATIONGROUP_H
diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h
new file mode 100644
index 0000000..c01aaf0
--- /dev/null
+++ b/src/corelib/animation/qsequentialanimationgroup_p.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSEQUENTIALANIMATIONGROUP_P_H
+#define QSEQUENTIALANIMATIONGROUP_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of QIODevice. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qsequentialanimationgroup.h"
+#include "private/qanimationgroup_p.h"
+
+
+QT_BEGIN_NAMESPACE
+
+class QSequentialAnimationGroupPrivate : public QAnimationGroupPrivate
+{
+ Q_DECLARE_PUBLIC(QSequentialAnimationGroup)
+public:
+ QSequentialAnimationGroupPrivate()
+ : currentAnimation(0), currentAnimationIndex(-1), lastLoop(0)
+ { }
+
+
+ struct AnimationIndex
+ {
+ AnimationIndex() : index(0), timeOffset(0) {}
+ // index points to the animation at timeOffset, skipping 0 duration animations.
+ // Note that the index semantic is slightly different depending on the direction.
+ int index; // the index of the animation in timeOffset
+ int timeOffset; // time offset when the animation at index starts.
+ };
+
+ int animationActualTotalDuration(int index) const;
+ AnimationIndex indexForTime(int msecs) const;
+
+ void setCurrentAnimation(int index, bool intermediate = false);
+ void activateCurrentAnimation(bool intermediate = false);
+
+ void animationInsertedAt(int index);
+ void animationRemovedAt(int index);
+
+ bool atEnd() const;
+
+ QAbstractAnimation *currentAnimation;
+ int currentAnimationIndex;
+
+ // this is the actual duration of uncontrolled animations
+ // it helps seeking and even going forward
+ QList<int> actualDuration;
+
+ void restart();
+ int lastLoop;
+
+ // handle time changes
+ void rewindForwards(const AnimationIndex &newAnimationIndex);
+ void advanceForwards(const AnimationIndex &newAnimationIndex);
+
+ // private slot
+ void _q_uncontrolledAnimationFinished();
+};
+
+QT_END_NAMESPACE
+
+#endif //QSEQUENTIALANIMATIONGROUP_P_H
diff --git a/src/corelib/animation/qvariantanimation.cpp b/src/corelib/animation/qvariantanimation.cpp
new file mode 100644
index 0000000..ab73373
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.cpp
@@ -0,0 +1,673 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvariantanimation.h"
+#include "qvariantanimation_p.h"
+
+#include <QtCore/qrect.h>
+#include <QtCore/qline.h>
+#include <QtCore/qmutex.h>
+#include <private/qmutexpool_p.h>
+
+#ifndef QT_NO_ANIMATION
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QVariantAnimation
+ \ingroup animation
+ \brief The QVariantAnimation class provides an abstract base class for animations.
+ \since 4.6
+
+ This class is part of \l{The Animation Framework}. It serves as a
+ base class for property and item animations, with functions for
+ shared functionality.
+
+ QVariantAnimation cannot be used directly as it is an abstract
+ class; it has a pure virtual method called updateCurrentValue().
+ The class performs interpolation over
+ \l{QVariant}s, but leaves using the interpolated values to its
+ subclasses. Currently, Qt provides QPropertyAnimation, which
+ animates Qt \l{Qt's Property System}{properties}. See the
+ QPropertyAnimation class description if you wish to animate such
+ properties.
+
+ You can then set start and end values for the property by calling
+ setStartValue() and setEndValue(), and finally call start() to
+ start the animation. QVariantAnimation will interpolate the
+ property of the target object and emit valueChanged(). To react to
+ a change in the current value you have to reimplement the
+ updateCurrentValue() virtual function.
+
+ It is also possible to set values at specified steps situated
+ between the start and end value. The interpolation will then
+ touch these points at the specified steps. Note that the start and
+ end values are defined as the key values at 0.0 and 1.0.
+
+ There are two ways to affect how QVariantAnimation interpolates
+ the values. You can set an easing curve by calling
+ setEasingCurve(), and configure the duration by calling
+ setDuration(). You can change how the QVariants are interpolated
+ by creating a subclass of QVariantAnimation, and reimplementing
+ the virtual interpolated() function.
+
+ Subclassing QVariantAnimation can be an alternative if you have
+ \l{QVariant}s that you do not wish to declare as Qt properties.
+ Note, however, that you in most cases will be better off declaring
+ your QVariant as a property.
+
+ Not all QVariant types are supported. Below is a list of currently
+ supported QVariant types:
+
+ \list
+ \o \l{QMetaType::}{Int}
+ \o \l{QMetaType::}{Double}
+ \o \l{QMetaType::}{Float}
+ \o \l{QMetaType::}{QLine}
+ \o \l{QMetaType::}{QLineF}
+ \o \l{QMetaType::}{QPoint}
+ \o \l{QMetaType::}{QSize}
+ \o \l{QMetaType::}{QSizeF}
+ \o \l{QMetaType::}{QRect}
+ \o \l{QMetaType::}{QRectF}
+ \endlist
+
+ If you need to interpolate other variant types, including custom
+ types, you have to implement interpolation for these yourself.
+ You do this by reimplementing interpolated(), which returns
+ interpolation values for the value being interpolated.
+
+ \omit We need some snippets around here. \endomit
+
+ \sa QPropertyAnimation, QAbstractAnimation, {The Animation Framework}
+*/
+
+/*!
+ \fn void QVariantAnimation::valueChanged(const QVariant &value)
+
+ QVariantAnimation emits this signal whenever the current \a value changes.
+
+ \sa currentValue, startValue, endValue
+*/
+
+/*!
+ \fn void QVariantAnimation::updateCurrentValue(const QVariant &value) = 0;
+
+ This pure virtual function is called every time the animation's current
+ value changes. The \a value argument is the new current value.
+
+ \sa currentValue
+*/
+
+
+static bool animationValueLessThan(const QVariantAnimation::KeyValue &p1, const QVariantAnimation::KeyValue &p2)
+{
+ return p1.first < p2.first;
+}
+
+static QVariant defaultInterpolator(const void *, const void *, qreal)
+{
+ return QVariant();
+}
+
+template<> Q_INLINE_TEMPLATE QRect _q_interpolate(const QRect &f, const QRect &t, qreal progress)
+{
+ QRect ret;
+ ret.setCoords(_q_interpolate(f.left(), t.left(), progress),
+ _q_interpolate(f.top(), t.top(), progress),
+ _q_interpolate(f.right(), t.right(), progress),
+ _q_interpolate(f.bottom(), t.bottom(), progress));
+ return ret;
+}
+
+template<> Q_INLINE_TEMPLATE QRectF _q_interpolate(const QRectF &f, const QRectF &t, qreal progress)
+{
+ qreal x1, y1, w1, h1;
+ f.getRect(&x1, &y1, &w1, &h1);
+ qreal x2, y2, w2, h2;
+ t.getRect(&x2, &y2, &w2, &h2);
+ return QRectF(_q_interpolate(x1, x2, progress), _q_interpolate(y1, y2, progress),
+ _q_interpolate(w1, w2, progress), _q_interpolate(h1, h2, progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLine _q_interpolate(const QLine &f, const QLine &t, qreal progress)
+{
+ return QLine( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+template<> Q_INLINE_TEMPLATE QLineF _q_interpolate(const QLineF &f, const QLineF &t, qreal progress)
+{
+ return QLineF( _q_interpolate(f.p1(), t.p1(), progress), _q_interpolate(f.p2(), t.p2(), progress));
+}
+
+QVariantAnimationPrivate::QVariantAnimationPrivate() : duration(250), hasStartValue(false),
+ interpolator(&defaultInterpolator),
+ changedSignalMask(1 << QVariantAnimation::staticMetaObject.indexOfSignal("valueChanged(QVariant)"))
+{
+ //we keep the mask so that we emit valueChanged only when needed (for performance reasons)
+}
+
+void QVariantAnimationPrivate::convertValues(int t)
+{
+ //this ensures that all the keyValues are of type t
+ for (int i = 0; i < keyValues.count(); ++i) {
+ QVariantAnimation::KeyValue &pair = keyValues[i];
+ pair.second.convert(static_cast<QVariant::Type>(t));
+ }
+ //we also need update to the current interval if needed
+ currentInterval.start.second.convert(static_cast<QVariant::Type>(t));
+ currentInterval.end.second.convert(static_cast<QVariant::Type>(t));
+
+ //... and the interpolator
+ updateInterpolator();
+}
+
+void QVariantAnimationPrivate::updateInterpolator()
+{
+ int type = currentInterval.start.second.userType();
+ if (type == currentInterval.end.second.userType())
+ interpolator = getInterpolator(type);
+ else
+ interpolator = 0;
+
+ //we make sure that the interpolator is always set to something
+ if (!interpolator)
+ interpolator = &defaultInterpolator;
+}
+
+/*!
+ \internal
+ The goal of this function is to update the currentInterval member. As a consequence, we also
+ need to update the currentValue.
+ Set \a force to true to always recalculate the interval.
+*/
+void QVariantAnimationPrivate::recalculateCurrentInterval(bool force/*=false*/)
+{
+ // can't interpolate if we have only 1 key value
+ if (keyValues.count() <= 1)
+ return;
+
+ const qreal progress = easing.valueForProgress(((duration == 0) ? qreal(1) : qreal(currentTime) / qreal(duration)));
+
+ if (force || progress < currentInterval.start.first || progress > currentInterval.end.first) {
+ //let's update currentInterval
+ QVariantAnimation::KeyValues::const_iterator itStart = qLowerBound(keyValues.constBegin(),
+ keyValues.constEnd(),
+ qMakePair(progress, QVariant()),
+ animationValueLessThan);
+ QVariantAnimation::KeyValues::const_iterator itEnd = itStart;
+
+ // If we are at the end we should continue to use the last keyValues in case of extrapolation (progress > 1.0).
+ // This is because the easing function can return a value slightly outside the range [0, 1]
+ if (itStart != keyValues.constEnd()) {
+ // this can't happen because we always prepend the default start value there
+ if (itStart == keyValues.constBegin()) {
+ ++itEnd;
+ } else {
+ --itStart;
+ }
+
+ // update all the values of the currentInterval
+ currentInterval.start = *itStart;
+ currentInterval.end = *itEnd;
+ updateInterpolator();
+ }
+ }
+ setCurrentValueForProgress(progress);
+}
+
+void QVariantAnimationPrivate::setCurrentValueForProgress(const qreal progress)
+{
+ Q_Q(QVariantAnimation);
+
+ const qreal startProgress = currentInterval.start.first;
+ const qreal endProgress = currentInterval.end.first;
+ const qreal localProgress = (progress - startProgress) / (endProgress - startProgress);
+
+ QVariant ret = q->interpolated(currentInterval.start.second,
+ currentInterval.end.second,
+ localProgress);
+ qSwap(currentValue, ret);
+ q->updateCurrentValue(currentValue);
+ if ((connectedSignals & changedSignalMask) && currentValue != ret) {
+ //the value has changed
+ emit q->valueChanged(currentValue);
+ }
+}
+
+QVariant QVariantAnimationPrivate::valueAt(qreal step) const
+{
+ QVariantAnimation::KeyValues::const_iterator result =
+ qBinaryFind(keyValues.begin(), keyValues.end(), qMakePair(step, QVariant()), animationValueLessThan);
+ if (result != keyValues.constEnd())
+ return result->second;
+
+ return QVariant();
+}
+
+void QVariantAnimationPrivate::setValueAt(qreal step, const QVariant &value)
+{
+ if (step < qreal(0.0) || step > qreal(1.0)) {
+ qWarning("QVariantAnimation::setValueAt: invalid step = %f", step);
+ return;
+ }
+
+ QVariantAnimation::KeyValue pair(step, value);
+
+ QVariantAnimation::KeyValues::iterator result = qLowerBound(keyValues.begin(), keyValues.end(), pair, animationValueLessThan);
+ if (result == keyValues.end() || result->first != step) {
+ keyValues.insert(result, pair);
+ } else {
+ if (value.isValid())
+ result->second = value; // replaces the previous value
+ else if (step == 0 && !hasStartValue && defaultStartValue.isValid())
+ result->second = defaultStartValue; // resets to the default start value
+ else
+ keyValues.erase(result); // removes the previous value
+ }
+
+ recalculateCurrentInterval(/*force=*/true);
+}
+
+void QVariantAnimationPrivate::setDefaultStartValue(const QVariant &value)
+{
+ defaultStartValue = value;
+ if (!hasStartValue)
+ setValueAt(0, value);
+}
+
+/*!
+ Construct a QVariantAnimation object. \a parent is passed to QAbstractAnimation's
+ constructor.
+*/
+QVariantAnimation::QVariantAnimation(QObject *parent) : QAbstractAnimation(*new QVariantAnimationPrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QVariantAnimation::QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent) : QAbstractAnimation(dd, parent)
+{
+}
+
+/*!
+ Destroys the animation.
+*/
+QVariantAnimation::~QVariantAnimation()
+{
+}
+
+/*!
+ \property QVariantAnimation::easingCurve
+ \brief the easing curve of the animation
+
+ This property defines the easing curve of the animation. By
+ default, a linear easing curve is used, resulting in linear
+ interpolation. Other curves are provided, for instance,
+ QEasingCurve::InCirc, which provides a circular entry curve.
+ Another example is QEasingCurve::InOutElastic, which provides an
+ elastic effect on the values of the interpolated variant.
+
+ The easing curve is used with the interpolator, the interpolated()
+ virtual function, the animation's duration, and iterationCount, to
+ control how the current value changes as the animation progresses.
+*/
+QEasingCurve QVariantAnimation::easingCurve() const
+{
+ Q_D(const QVariantAnimation);
+ return d->easing;
+}
+
+void QVariantAnimation::setEasingCurve(const QEasingCurve &easing)
+{
+ Q_D(QVariantAnimation);
+ d->easing = easing;
+ d->recalculateCurrentInterval();
+}
+
+typedef QVector<QVariantAnimation::Interpolator> QInterpolatorVector;
+Q_GLOBAL_STATIC(QInterpolatorVector, registeredInterpolators)
+
+/*!
+ \fn void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+ \relates QVariantAnimation
+ \threadsafe
+
+ Registers a custom interpolator \a func for the template type \c{T}.
+ The interpolator has to be registered before the animation is constructed.
+ To unregister (and use the default interpolator) set \a func to 0.
+ */
+
+/*!
+ \internal
+ \typedef QVariantAnimation::Interpolator
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+ \code
+ QVariant myInterpolator(const QVariant &from, const QVariant &to, qreal progress);
+ \endcode
+
+*/
+
+/*! \internal
+ * Registers a custom interpolator \a func for the specific \a interpolationType.
+ * The interpolator has to be registered before the animation is constructed.
+ * To unregister (and use the default interpolator) set \a func to 0.
+ */
+void QVariantAnimation::registerInterpolator(QVariantAnimation::Interpolator func, int interpolationType)
+{
+ // will override any existing interpolators
+ QInterpolatorVector *interpolators = registeredInterpolators();
+ QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
+ if (int(interpolationType) >= interpolators->count())
+ interpolators->resize(int(interpolationType) + 1);
+ interpolators->replace(interpolationType, func);
+}
+
+
+template<typename T> static inline QVariantAnimation::Interpolator castToInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress))
+{
+ return reinterpret_cast<QVariantAnimation::Interpolator>(func);
+}
+
+QVariantAnimation::Interpolator QVariantAnimationPrivate::getInterpolator(int interpolationType)
+{
+ QInterpolatorVector *interpolators = registeredInterpolators();
+ QMutexLocker locker(QMutexPool::globalInstanceGet(interpolators));
+ QVariantAnimation::Interpolator ret = 0;
+ if (interpolationType < interpolators->count()) {
+ ret = interpolators->at(interpolationType);
+ if (ret) return ret;
+ }
+
+ switch(interpolationType)
+ {
+ case QMetaType::Int:
+ return castToInterpolator(_q_interpolateVariant<int>);
+ case QMetaType::Double:
+ return castToInterpolator(_q_interpolateVariant<double>);
+ case QMetaType::Float:
+ return castToInterpolator(_q_interpolateVariant<float>);
+ case QMetaType::QLine:
+ return castToInterpolator(_q_interpolateVariant<QLine>);
+ case QMetaType::QLineF:
+ return castToInterpolator(_q_interpolateVariant<QLineF>);
+ case QMetaType::QPoint:
+ return castToInterpolator(_q_interpolateVariant<QPoint>);
+ case QMetaType::QPointF:
+ return castToInterpolator(_q_interpolateVariant<QPointF>);
+ case QMetaType::QSize:
+ return castToInterpolator(_q_interpolateVariant<QSize>);
+ case QMetaType::QSizeF:
+ return castToInterpolator(_q_interpolateVariant<QSizeF>);
+ case QMetaType::QRect:
+ return castToInterpolator(_q_interpolateVariant<QRect>);
+ case QMetaType::QRectF:
+ return castToInterpolator(_q_interpolateVariant<QRectF>);
+ default:
+ return 0; //this type is not handled
+ }
+}
+
+/*!
+ \property QVariantAnimation::duration
+ \brief the duration of the animation
+
+ This property describes the duration in milliseconds of the
+ animation. The default duration is 250 milliseconds.
+
+ \sa QAbstractAnimation::duration()
+ */
+int QVariantAnimation::duration() const
+{
+ Q_D(const QVariantAnimation);
+ return d->duration;
+}
+
+void QVariantAnimation::setDuration(int msecs)
+{
+ Q_D(QVariantAnimation);
+ if (msecs < 0) {
+ qWarning("QVariantAnimation::setDuration: cannot set a negative duration");
+ return;
+ }
+ if (d->duration == msecs)
+ return;
+ d->duration = msecs;
+ d->recalculateCurrentInterval();
+}
+
+/*!
+ \property QVariantAnimation::startValue
+ \brief the optional start value of the animation
+
+ This property describes the optional start value of the animation. If
+ omitted, or if a null QVariant is assigned as the start value, the
+ animation will use the current position of the end when the animation
+ is started.
+
+ \sa endValue
+*/
+QVariant QVariantAnimation::startValue() const
+{
+ return keyValueAt(0);
+}
+
+void QVariantAnimation::setStartValue(const QVariant &value)
+{
+ setKeyValueAt(0, value);
+}
+
+/*!
+ \property QVariantAnimation::endValue
+ \brief the end value of the animation
+
+ This property describes the end value of the animation.
+
+ \sa startValue
+ */
+QVariant QVariantAnimation::endValue() const
+{
+ return keyValueAt(1);
+}
+
+void QVariantAnimation::setEndValue(const QVariant &value)
+{
+ setKeyValueAt(1, value);
+}
+
+
+/*!
+ Returns the key frame value for the given \a step. The given \a step
+ must be in the range 0 to 1. If there is no KeyValue for \a step,
+ it returns an invalid QVariant.
+
+ \sa keyValues(), setKeyValueAt()
+*/
+QVariant QVariantAnimation::keyValueAt(qreal step) const
+{
+ Q_D(const QVariantAnimation);
+ if (step == 0 && !d->hasStartValue)
+ return QVariant(); //special case where we don't have an explicit startValue
+
+ return d->valueAt(step);
+}
+
+/*!
+ \typedef QVariantAnimation::KeyValue
+
+ This is a typedef for QPair<qreal, QVariant>.
+*/
+/*!
+ \typedef QVariantAnimation::KeyValues
+
+ This is a typedef for QVector<KeyValue>
+*/
+
+/*!
+ Creates a key frame at the given \a step with the given \a value.
+ The given \a step must be in the range 0 to 1.
+
+ \sa setKeyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValueAt(qreal step, const QVariant &value)
+{
+ Q_D(QVariantAnimation);
+ if (step == 0)
+ d->hasStartValue = value.isValid();
+ d->setValueAt(step, value);
+}
+
+/*!
+ Returns the key frames of this animation.
+
+ \sa keyValueAt(), setKeyValues()
+*/
+QVariantAnimation::KeyValues QVariantAnimation::keyValues() const
+{
+ Q_D(const QVariantAnimation);
+ QVariantAnimation::KeyValues ret = d->keyValues;
+ //in case we added the default start value, we remove it
+ if (!d->hasStartValue && !ret.isEmpty() && ret.at(0).first == 0)
+ ret.remove(0);
+ return ret;
+}
+
+/*!
+ Replaces the current set of key frames with the given \a keyValues.
+ the step of the key frames must be in the range 0 to 1.
+
+ \sa keyValues(), keyValueAt()
+*/
+void QVariantAnimation::setKeyValues(const KeyValues &keyValues)
+{
+ Q_D(QVariantAnimation);
+ d->keyValues = keyValues;
+ qSort(d->keyValues.begin(), d->keyValues.end(), animationValueLessThan);
+ d->hasStartValue = !d->keyValues.isEmpty() && d->keyValues.at(0).first == 0;
+ d->recalculateCurrentInterval(/*force=*/true);
+}
+
+/*!
+ \property QVariantAnimation::currentValue
+ \brief the current value of the animation.
+
+ This property describes the current value; an interpolated value
+ between the \l{startValue}{start value} and the \l{endValue}{end
+ value}, using the current time for progress. The value itself is
+ obtained from interpolated(), which is called repeatedly as the
+ animation is running.
+
+ QVariantAnimation calls the virtual updateCurrentValue() function
+ when the current value changes. This is particularly useful for
+ subclasses that need to track updates. For example,
+ QPropertyAnimation uses this function to animate Qt \l{Qt's
+ Property System}{properties}.
+
+ \sa startValue, endValue
+*/
+QVariant QVariantAnimation::currentValue() const
+{
+ Q_D(const QVariantAnimation);
+ if (!d->currentValue.isValid())
+ const_cast<QVariantAnimationPrivate*>(d)->recalculateCurrentInterval();
+ return d->currentValue;
+}
+
+/*!
+ \reimp
+ */
+bool QVariantAnimation::event(QEvent *event)
+{
+ return QAbstractAnimation::event(event);
+}
+
+/*!
+ \reimp
+*/
+void QVariantAnimation::updateState(QAbstractAnimation::State oldState,
+ QAbstractAnimation::State newState)
+{
+ Q_UNUSED(oldState);
+ Q_UNUSED(newState);
+}
+
+/*!
+
+ This virtual function returns the linear interpolation between
+ variants \a from and \a to, at \a progress, usually a value
+ between 0 and 1. You can reimplement this function in a subclass
+ of QVariantAnimation to provide your own interpolation algorithm.
+
+ Note that in order for the interpolation to work with a
+ QEasingCurve that return a value smaller than 0 or larger than 1
+ (such as QEasingCurve::InBack) you should make sure that it can
+ extrapolate. If the semantic of the datatype does not allow
+ extrapolation this function should handle that gracefully.
+
+ You should call the QVariantAnimation implementation of this
+ function if you want your class to handle the types already
+ supported by Qt (see class QVariantAnimation description for a
+ list of supported types).
+
+ \sa QEasingCurve
+ */
+QVariant QVariantAnimation::interpolated(const QVariant &from, const QVariant &to, qreal progress) const
+{
+ return d_func()->interpolator(from.constData(), to.constData(), progress);
+}
+
+/*!
+ \reimp
+ */
+void QVariantAnimation::updateCurrentTime(int msecs)
+{
+ Q_UNUSED(msecs);
+ d_func()->recalculateCurrentInterval();
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qvariantanimation.cpp"
+
+#endif //QT_NO_ANIMATION
diff --git a/src/corelib/animation/qvariantanimation.h b/src/corelib/animation/qvariantanimation.h
new file mode 100644
index 0000000..3ae172f
--- /dev/null
+++ b/src/corelib/animation/qvariantanimation.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QANIMATION_H
+#define QANIMATION_H
+
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qabstractanimation.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qpair.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_ANIMATION
+
+class QVariantAnimationPrivate;
+class Q_CORE_EXPORT QVariantAnimation : public QAbstractAnimation
+{
+ Q_OBJECT
+ Q_PROPERTY(QVariant startValue READ startValue WRITE setStartValue)
+ Q_PROPERTY(QVariant endValue READ endValue WRITE setEndValue)
+ Q_PROPERTY(QVariant currentValue READ currentValue NOTIFY currentValueChanged)
+ Q_PROPERTY(int duration READ duration WRITE setDuration)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
+
+public:
+ typedef QPair<qreal, QVariant> KeyValue;
+ typedef QVector<KeyValue> KeyValues;
+
+ QVariantAnimation(QObject *parent = 0);
+ ~QVariantAnimation();
+
+ QVariant startValue() const;
+ void setStartValue(const QVariant &value);
+
+ QVariant endValue() const;
+ void setEndValue(const QVariant &value);
+
+ QVariant keyValueAt(qreal step) const;
+ void setKeyValueAt(qreal step, const QVariant &value);
+
+ KeyValues keyValues() const;
+ void setKeyValues(const KeyValues &values);
+
+ QVariant currentValue() const;
+
+ int duration() const;
+ void setDuration(int msecs);
+
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &easing);
+
+ typedef QVariant (*Interpolator)(const void *from, const void *to, qreal progress);
+
+Q_SIGNALS:
+ void valueChanged(const QVariant &value);
+
+protected:
+ QVariantAnimation(QVariantAnimationPrivate &dd, QObject *parent = 0);
+ bool event(QEvent *event);
+
+ void updateCurrentTime(int msecs);
+ void updateState(QAbstractAnimation::State oldState, QAbstractAnimation::State newState);
+
+ virtual void updateCurrentValue(const QVariant &value) = 0;
+ virtual QVariant interpolated(const QVariant &from, const QVariant &to, qreal progress) const;
+
+private:
+ template <typename T> friend void qRegisterAnimationInterpolator(QVariant (*func)(const T &, const T &, qreal));
+ static void registerInterpolator(Interpolator func, int interpolationType);
+
+ Q_DISABLE_COPY(QVariantAnimation)
+ Q_DECLARE_PRIVATE(QVariantAnimation)
+};
+
+template <typename T>
+void qRegisterAnimationInterpolator(QVariant (*func)(const T &from, const T &to, qreal progress)) {
+ QVariantAnimation::registerInterpolator(reinterpret_cast<QVariantAnimation::Interpolator>(func), qMetaTypeId<T>());
+}
+
+#endif //QT_NO_ANIMATION
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QANIMATION_H
diff --git a/src/gui/painting/qpaintengine_d3d_p.h b/src/corelib/animation/qvariantanimation_p.h
index 8fa5cf6..3ae0e39 100644
--- a/src/gui/painting/qpaintengine_d3d_p.h
+++ b/src/corelib/animation/qvariantanimation_p.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,82 +39,85 @@
**
****************************************************************************/
-#ifndef QPAINTENGINE_D3D_P_H
-#define QPAINTENGINE_D3D_P_H
+#ifndef QANIMATION_P_H
+#define QANIMATION_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
+// of QIODevice. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//
-#include "QtGui/qpaintengine.h"
-#include <d3d9.h>
+#include "qvariantanimation.h"
+#include <QtCore/qeasingcurve.h>
+#include <QtCore/qmetaobject.h>
+#include <QtCore/qvector.h>
+
+#include "private/qabstractanimation_p.h"
QT_BEGIN_NAMESPACE
-class QDirect3DPaintEnginePrivate;
-class QDirect3DPaintEngine : public QPaintEngine
+class QVariantAnimationPrivate : public QAbstractAnimationPrivate
{
- Q_DECLARE_PRIVATE(QDirect3DPaintEngine)
+ Q_DECLARE_PUBLIC(QVariantAnimation)
public:
- QDirect3DPaintEngine();
- ~QDirect3DPaintEngine();
- bool begin(QPaintDevice *device);
-
- void drawEllipse(const QRectF &rect);
- void drawEllipse(const QRect &rect);
- void drawImage(const QRectF &rectangle, const QImage &image, const QRectF &sr,
- Qt::ImageConversionFlags flags = Qt::AutoColor);
+ QVariantAnimationPrivate();
- void drawLines(const QLineF *lines, int lineCount);
- void drawLines(const QLine *lines, int lineCount);
+ static QVariantAnimationPrivate *get(QVariantAnimation *q)
+ {
+ return q->d_func();
+ }
- void drawPath(const QPainterPath &path);
+ void setDefaultStartValue(const QVariant &value);
- void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr);
+ int duration;
+ QEasingCurve easing;
- void drawPoints(const QPointF *points, int pointCount);
- void drawPoints(const QPoint *points, int pointCount);
+ QVariantAnimation::KeyValues keyValues;
+ QVariant currentValue;
+ QVariant defaultStartValue;
+ bool hasStartValue;
- void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode);
- void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode);
+ //this is used to keep track of the KeyValue interval in which we currently are
+ struct
+ {
+ QVariantAnimation::KeyValue start, end;
+ } currentInterval;
- void drawRects(const QRectF *rects, int rectCount);
- void drawRects(const QRect * rects, int rectCount);
+ QVariantAnimation::Interpolator interpolator;
- void drawTextItem(const QPointF &p, const QTextItem &textItem);
+ const quint32 changedSignalMask;
- void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr);
+ void setCurrentValueForProgress(const qreal progress);
+ void recalculateCurrentInterval(bool force=false);
+ void setValueAt(qreal, const QVariant &);
+ QVariant valueAt(qreal step) const;
+ void convertValues(int t);
- bool end();
+ void updateInterpolator();
- Type type() const { return Direct3D; }
- void updateState(const QPaintEngineState &state);
+ //XXX this is needed by dui
+ static Q_CORE_EXPORT QVariantAnimation::Interpolator getInterpolator(int interpolationType);
+};
- void cleanup();
+//this should make the interpolation faster
+template<typename T> inline T _q_interpolate(const T &f, const T &t, qreal progress)
+{
+ return T(f + (t - f) * progress);
+}
- HDC getDC() const;
- void setFlushOnEnd(bool flushOnEnd);
- bool hasDirect3DSupport();
+template<typename T > inline QVariant _q_interpolateVariant(const T &from, const T &to, qreal progress)
+{
+ return _q_interpolate(from, to, progress);
+}
-public:
- void scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect);
- LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd);
- void releaseSwapChain(QPaintDevice *pd);
-
-private:
- Q_DISABLE_COPY(QDirect3DPaintEngine)
- friend class QPixmap;
- friend class QD3DGlyphCache;
-};
QT_END_NAMESPACE
-#endif
+#endif //QANIMATION_P_H
diff --git a/src/corelib/codecs/qisciicodec.cpp b/src/corelib/codecs/qisciicodec.cpp
index 5619580..f9e3292 100644
--- a/src/corelib/codecs/qisciicodec.cpp
+++ b/src/corelib/codecs/qisciicodec.cpp
@@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE
struct Codecs {
- const char *name;
+ const char name[10];
ushort base;
};
diff --git a/src/corelib/codecs/qtextcodec.cpp b/src/corelib/codecs/qtextcodec.cpp
index cfb62c7..fcf0be1 100644
--- a/src/corelib/codecs/qtextcodec.cpp
+++ b/src/corelib/codecs/qtextcodec.cpp
@@ -461,10 +461,10 @@ static const char * const tis_620locales[] = {
// static const char * const tcvnlocales[] = {
// "vi", "vi_VN", 0 };
-static bool try_locale_list(const char * const locale[], const char * lang)
+static bool try_locale_list(const char * const locale[], const QByteArray &lang)
{
int i;
- for(i=0; locale[i] && *locale[i] && strcmp(locale[i], lang); i++)
+ for(i=0; locale[i] && lang != locale[i]; i++)
;
return locale[i] != 0;
}
@@ -516,13 +516,12 @@ static QTextCodec * ru_RU_hack(const char * i) {
#endif
#if !defined(Q_OS_WIN32) && !defined(Q_OS_WINCE)
-static QTextCodec *checkForCodec(const char *name) {
+static QTextCodec *checkForCodec(const QByteArray &name) {
QTextCodec *c = QTextCodec::codecForName(name);
if (!c) {
- const char *at = strchr(name, '@');
- if (at) {
- QByteArray n(name, at - name);
- c = QTextCodec::codecForName(n.data());
+ const int index = name.indexOf('@');
+ if (index != -1) {
+ c = QTextCodec::codecForName(name.left(index));
}
}
return c;
@@ -563,21 +562,19 @@ static void setupLocaleMapper()
// definitely knows it, but since we cannot fully trust it, get ready
// to fall back to environment variables.
#if !defined(QT_NO_SETLOCALE)
- char * ctype = qstrdup(setlocale(LC_CTYPE, 0));
+ const QByteArray ctype = setlocale(LC_CTYPE, 0);
#else
- char * ctype = qstrdup("");
+ const QByteArray ctype;
#endif
// Get the first nonempty value from $LC_ALL, $LC_CTYPE, and $LANG
// environment variables.
- char * lang = qstrdup(qgetenv("LC_ALL").constData());
- if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) {
- if (lang) delete [] lang;
- lang = qstrdup(qgetenv("LC_CTYPE").constData());
+ QByteArray lang = qgetenv("LC_ALL");
+ if (lang.isEmpty() || lang == "C") {
+ lang = qgetenv("LC_CTYPE");
}
- if (!lang || lang[0] == 0 || strcmp(lang, "C") == 0) {
- if (lang) delete [] lang;
- lang = qstrdup(qgetenv("LANG").constData());
+ if (lang.isEmpty() || lang == "C") {
+ lang = qgetenv("LANG");
}
// Now try these in order:
@@ -590,35 +587,35 @@ static void setupLocaleMapper()
// 7. guess locale from lang
// 1. CODESET from ctype if it contains a .CODESET part (e.g. en_US.ISO8859-15)
- char * codeset = ctype ? strchr(ctype, '.') : 0;
- if (codeset && *codeset == '.')
- localeMapper = checkForCodec(codeset + 1);
+ int indexOfDot = ctype.indexOf('.');
+ if (indexOfDot != -1)
+ localeMapper = checkForCodec( ctype.mid(indexOfDot + 1) );
// 2. CODESET from lang if it contains a .CODESET part
- codeset = lang ? strchr(lang, '.') : 0;
- if (!localeMapper && codeset && *codeset == '.')
- localeMapper = checkForCodec(codeset + 1);
+ if (!localeMapper) {
+ indexOfDot = lang.indexOf('.');
+ if (indexOfDot != -1)
+ localeMapper = checkForCodec( lang.mid(indexOfDot + 1) );
+ }
// 3. ctype (maybe the locale is named "ISO-8859-1" or something)
- if (!localeMapper && ctype && *ctype != 0 && strcmp (ctype, "C") != 0)
+ if (!localeMapper && !ctype.isEmpty() && ctype != "C")
localeMapper = checkForCodec(ctype);
// 4. locale (ditto)
- if (!localeMapper && lang && *lang != 0)
+ if (!localeMapper && !lang.isEmpty())
localeMapper = checkForCodec(lang);
// 5. "@euro"
- if ((!localeMapper && ctype && strstr(ctype, "@euro")) || (lang && strstr(lang, "@euro")))
+ if ((!localeMapper && ctype.contains("@euro")) || lang.contains("@euro"))
localeMapper = checkForCodec("ISO 8859-15");
// 6. guess locale from ctype unless ctype is "C"
// 7. guess locale from lang
- char * try_by_name = ctype;
- if (ctype && *ctype != 0 && strcmp (ctype, "C") != 0)
- try_by_name = lang;
+ const QByteArray &try_by_name = (!ctype.isEmpty() && ctype != "C") ? lang : ctype;
// Now do the guessing.
- if (lang && *lang && !localeMapper && try_by_name && *try_by_name) {
+ if (!lang.isEmpty() && !localeMapper && !try_by_name.isEmpty()) {
if (try_locale_list(iso8859_15locales, lang))
localeMapper = QTextCodec::codecForName("ISO 8859-15");
else if (try_locale_list(iso8859_2locales, lang))
@@ -651,8 +648,6 @@ static void setupLocaleMapper()
localeMapper = ru_RU_hack(lang);
}
- delete [] ctype;
- delete [] lang;
}
// If everything failed, we default to 8859-1
@@ -1525,9 +1520,14 @@ QString QTextDecoder::toUnicode(const QByteArray &ba)
/*!
\since 4.4
- Tries to detect the encoding of the provided snippet of HTML in the given byte array, \a ba,
- and returns a QTextCodec instance that is capable of decoding the html to unicode.
- If the codec cannot be detected from the content provided, \a defaultCodec is returned.
+ Tries to detect the encoding of the provided snippet of HTML in
+ the given byte array, \a ba, by checking the BOM (Byte Order Mark)
+ and the content-type meta header and returns a QTextCodec instance
+ that is capable of decoding the html to unicode. If the codec
+ cannot be detected from the content provided, \a defaultCodec is
+ returned.
+
+ \sa codecForUtfText()
*/
QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec)
{
@@ -1535,15 +1535,8 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba, QTextCodec *defaultCo
int pos;
QTextCodec *c = 0;
- if (ba.size() > 1 && (((uchar)ba[0] == 0xfe && (uchar)ba[1] == 0xff)
- || ((uchar)ba[0] == 0xff && (uchar)ba[1] == 0xfe))) {
- c = QTextCodec::codecForMib(1015); // utf16
- } else if (ba.size() > 2
- && (uchar)ba[0] == 0xef
- && (uchar)ba[1] == 0xbb
- && (uchar)ba[2] == 0xbf) {
- c = QTextCodec::codecForMib(106); // utf-8
- } else {
+ c = QTextCodec::codecForUtfText(ba, c);
+ if (!c) {
QByteArray header = ba.left(512).toLower();
if ((pos = header.indexOf("http-equiv=")) != -1) {
pos = header.indexOf("charset=", pos) + int(strlen("charset="));
@@ -1571,6 +1564,61 @@ QTextCodec *QTextCodec::codecForHtml(const QByteArray &ba)
return codecForHtml(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
}
+/*!
+ \since 4.6
+
+ Tries to detect the encoding of the provided snippet \a ba by
+ using the BOM (Byte Order Mark) and returns a QTextCodec instance
+ that is capable of decoding the text to unicode. If the codec
+ cannot be detected from the content provided, \a defaultCodec is
+ returned.
+
+ \sa codecForHtml()
+*/
+QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec)
+{
+ const uint arraySize = ba.size();
+
+ if (arraySize > 3) {
+ if ((uchar)ba[0] == 0x00
+ && (uchar)ba[1] == 0x00
+ && (uchar)ba[2] == 0xFE
+ && (uchar)ba[3] == 0xFF)
+ return QTextCodec::codecForMib(1018); // utf-32 be
+ else if ((uchar)ba[0] == 0xFF
+ && (uchar)ba[1] == 0xFE
+ && (uchar)ba[2] == 0x00
+ && (uchar)ba[3] == 0x00)
+ return QTextCodec::codecForMib(1019); // utf-32 le
+ }
+
+ if (arraySize < 2)
+ return defaultCodec;
+ if ((uchar)ba[0] == 0xfe && (uchar)ba[1] == 0xff)
+ return QTextCodec::codecForMib(1013); // utf16 be
+ else if ((uchar)ba[0] == 0xff && (uchar)ba[1] == 0xfe)
+ return QTextCodec::codecForMib(1014); // utf16 le
+
+ if (arraySize < 3)
+ return defaultCodec;
+ if ((uchar)ba[0] == 0xef
+ && (uchar)ba[1] == 0xbb
+ && (uchar)ba[2] == 0xbf)
+ return QTextCodec::codecForMib(106); // utf-8
+
+ return defaultCodec;
+}
+
+/*!
+ \overload
+
+ If the codec cannot be detected, this overload returns a Latin-1 QTextCodec.
+*/
+QTextCodec *QTextCodec::codecForUtfText(const QByteArray &ba)
+{
+ return codecForUtfText(ba, QTextCodec::codecForMib(/*Latin 1*/ 4));
+}
+
/*! \internal
\since 4.3
diff --git a/src/corelib/codecs/qtextcodec.h b/src/corelib/codecs/qtextcodec.h
index e32650f..83097a5 100644
--- a/src/corelib/codecs/qtextcodec.h
+++ b/src/corelib/codecs/qtextcodec.h
@@ -82,6 +82,9 @@ public:
static QTextCodec *codecForHtml(const QByteArray &ba);
static QTextCodec *codecForHtml(const QByteArray &ba, QTextCodec *defaultCodec);
+ static QTextCodec *codecForUtfText(const QByteArray &ba);
+ static QTextCodec *codecForUtfText(const QByteArray &ba, QTextCodec *defaultCodec);
+
QTextDecoder* makeDecoder() const;
QTextEncoder* makeEncoder() const;
diff --git a/src/corelib/codecs/qtsciicodec_p.h b/src/corelib/codecs/qtsciicodec_p.h
index 8f11e48..425e7fd 100644
--- a/src/corelib/codecs/qtsciicodec_p.h
+++ b/src/corelib/codecs/qtsciicodec_p.h
@@ -88,7 +88,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_CODECS
-class Q_CORE_EXPORT QTsciiCodec : public QTextCodec {
+class QTsciiCodec : public QTextCodec {
public:
~QTsciiCodec();
diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp
index d9defe1..27c0572 100644
--- a/src/corelib/codecs/qutfcodec.cpp
+++ b/src/corelib/codecs/qutfcodec.cpp
@@ -184,7 +184,10 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C
uc = (uc << 6) | (ch & 0x3f);
need--;
if (!need) {
- if (uc > 0xffff && uc < 0x110000) {
+ // utf-8 bom composes into 0xfeff code point
+ if (!headerdone && uc == 0xfeff) {
+ // dont do anything, just skip the BOM
+ } else if (uc > 0xffff && uc < 0x110000) {
// surrogate pair
uc -= 0x10000;
unsigned short high = uc/0x400 + 0xd800;
@@ -206,6 +209,7 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C
} else {
*qch++ = uc;
}
+ headerdone = true;
}
} else {
// error
@@ -213,15 +217,18 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C
*qch++ = replacement;
++invalid;
need = 0;
+ headerdone = true;
}
} else {
if (ch < 128) {
*qch++ = QLatin1Char(ch);
+ headerdone = true;
} else if ((ch & 0xe0) == 0xc0) {
uc = ch & 0x1f;
need = 1;
error = i;
min_uc = 0x80;
+ headerdone = true;
} else if ((ch & 0xf0) == 0xe0) {
uc = ch & 0x0f;
need = 2;
@@ -232,10 +239,12 @@ void QUtf8Codec::convertToUnicode(QString *target, const char *chars, int len, C
need = 3;
error = i;
min_uc = 0x10000;
+ headerdone = true;
} else {
// error
*qch++ = replacement;
++invalid;
+ headerdone = true;
}
}
}
@@ -387,7 +396,7 @@ QString QUtf16Codec::convertToUnicode(const char *chars, int len, ConverterState
result.truncate(qch - result.unicode());
if (state) {
- if (endian != Detect)
+ if (headerdone)
state->flags |= IgnoreHeader;
state->state_data[Endian] = endian;
if (half) {
@@ -569,7 +578,7 @@ QString QUtf32Codec::convertToUnicode(const char *chars, int len, ConverterState
result.truncate(qch - result.unicode());
if (state) {
- if (endian != Detect)
+ if (headerdone)
state->flags |= IgnoreHeader;
state->state_data[Endian] = endian;
state->remainingChars = num;
diff --git a/src/corelib/concurrent/qfuturewatcher_p.h b/src/corelib/concurrent/qfuturewatcher_p.h
index 324839d..d53a1bd 100644
--- a/src/corelib/concurrent/qfuturewatcher_p.h
+++ b/src/corelib/concurrent/qfuturewatcher_p.h
@@ -63,8 +63,8 @@
QT_BEGIN_NAMESPACE
class QFutureWatcherBase;
-class Q_CORE_EXPORT QFutureWatcherBasePrivate : public QObjectPrivate,
- public QFutureCallOutInterface
+class QFutureWatcherBasePrivate : public QObjectPrivate,
+ public QFutureCallOutInterface
{
Q_DECLARE_PUBLIC(QFutureWatcherBase)
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index c55c2da..96e2b5c 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -5,6 +5,7 @@ DEFINES += QT_BUILD_CORE_LIB QT_NO_USING_NAMESPACE
win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x67000000
include(../qbase.pri)
+include(animation/animation.pri)
include(arch/arch.pri)
include(concurrent/concurrent.pri)
include(global/global.pri)
@@ -14,6 +15,7 @@ include(io/io.pri)
include(plugin/plugin.pri)
include(kernel/kernel.pri)
include(codecs/codecs.pri)
+include(statemachine/statemachine.pri)
include(xml/xml.pri)
mac|darwin:LIBS += -framework ApplicationServices
diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h
index 2189723..9f7c7ba 100644
--- a/src/corelib/global/qfeatures.h
+++ b/src/corelib/global/qfeatures.h
@@ -311,6 +311,11 @@
#define QT_NO_ACCESSIBILITY
#endif
+// Animation
+#if !defined(QT_NO_ANIMATION) && (defined(QT_NO_PROPERTIES))
+#define QT_NO_ANIMATION
+#endif
+
// QButtonGroup
#if !defined(QT_NO_BUTTONGROUP) && (defined(QT_NO_GROUPBOX))
#define QT_NO_BUTTONGROUP
@@ -361,6 +366,11 @@
#define QT_NO_MENU
#endif
+// QNetworkDiskCache
+#if !defined(QT_NO_NETWORKDISKCACHE) && (defined(QT_NO_TEMPORARYFILE))
+#define QT_NO_NETWORKDISKCACHE
+#endif
+
// Phonon::SeekSlider
#if !defined(QT_NO_PHONON_SEEKSLIDER) && (defined(QT_NO_SLIDER))
#define QT_NO_PHONON_SEEKSLIDER
diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt
index 40ccb15..9408a5b 100644
--- a/src/corelib/global/qfeatures.txt
+++ b/src/corelib/global/qfeatures.txt
@@ -1085,6 +1085,13 @@ Requires:
Name: QNetworkInterface
SeeAlso: ???
+Feature: NETWORKDISKCACHE
+Description: Supports a disk cache for network resources
+Section: Networking
+Requires: TEMPORARYFILE
+Name: QNetworkDiskCache
+SeeAlso: ???
+
# Utilities
Feature: COMPLETER
@@ -1150,6 +1157,21 @@ Requires: PROPERTIES
Name: Accessibility
SeeAlso: ???
+Feature: ANIMATION
+Description: Provides a framework for animations.
+Section: Utilities
+Requires: PROPERTIES
+Name: Animation
+SeeAlso: ???
+
+Feature: STATEMACHINE
+Description: Provides hierarchical finite state machines.
+Section: Utilities
+Requires: PROPERTIES
+Name: State machine
+SeeAlso: ???
+
+
# SVG
Feature: SVG
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 88f845a..6976c00 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2147,7 +2147,7 @@ void qt_message_output(QtMsgType msgType, const char *buf)
mac_default_handler(buf);
#elif defined(Q_OS_WINCE)
QString fstr = QString::fromLatin1(buf);
- fstr += QLatin1String("\n");
+ fstr += QLatin1Char('\n');
OutputDebugString(reinterpret_cast<const wchar_t *> (fstr.utf16()));
#elif defined(Q_OS_SYMBIAN)
// RDebug::Print has a cap of 256 characters so break it up
@@ -2454,7 +2454,7 @@ bool qputenv(const char *varName, const QByteArray& value)
return _putenv_s(varName, value.constData()) == 0;
#else
QByteArray buffer(varName);
- buffer += "=";
+ buffer += '=';
buffer += value;
return putenv(qstrdup(buffer.constData())) == 0;
#endif
@@ -3170,7 +3170,12 @@ bool QInternal::callFunction(InternalFunction func, void **args)
\relates <QtGlobal>
\since 4.4
\threadsafe
- \overload
+
+ Compares the floating point value \a p1 and \a p2 and
+ returns \c true if they are considered equal, otherwise \c false.
+
+ The two numbers are compared in a relative way, where the
+ exactness is stronger the smaller the numbers are.
*/
/*!
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 14b6895..c95338d 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -44,11 +44,11 @@
#include <stddef.h>
-#define QT_VERSION_STR "4.5.2"
+#define QT_VERSION_STR "4.6.0"
/*
QT_VERSION is (major << 16) + (minor << 8) + patch.
*/
-#define QT_VERSION 0x040502
+#define QT_VERSION 0x040600
/*
can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0))
*/
@@ -772,6 +772,10 @@ namespace QT_NAMESPACE {}
# endif
#elif defined(Q_OS_WINCE)
# define Q_WS_WIN32
+# define Q_WS_WINCE
+# if defined(Q_OS_WINCE_WM)
+# define Q_WS_WINCE_WM
+# endif
#elif defined(Q_OS_OS2)
# define Q_WS_PM
# error "Qt does not work with OS/2 Presentation Manager or Workplace Shell"
@@ -791,10 +795,11 @@ namespace QT_NAMESPACE {}
# endif
#endif
-#if defined(Q_WS_WIN16) || defined(Q_WS_WIN32)
+#if defined(Q_WS_WIN16) || defined(Q_WS_WIN32) || defined(Q_WS_WINCE)
# define Q_WS_WIN
#endif
+
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
@@ -848,17 +853,12 @@ typedef quint64 qulonglong;
sizeof(void *) == sizeof(quintptr)
&& sizeof(void *) == sizeof(qptrdiff)
*/
-template <int> class QUintForSize { private: typedef void Type; };
-template <> class QUintForSize<4> { public: typedef quint32 Type; };
-template <> class QUintForSize<8> { public: typedef quint64 Type; };
-template <typename T> class QUintForType : public QUintForSize<sizeof(T)> { };
-typedef QUintForType<void *>::Type quintptr;
-
-template <int> class QIntForSize { private: typedef void Type; };
-template <> class QIntForSize<4> { public: typedef qint32 Type; };
-template <> class QIntForSize<8> { public: typedef qint64 Type; };
-template <typename T> class QIntForType : public QIntForSize<sizeof(T)> { };
-typedef QIntForType<void *>::Type qptrdiff;
+template <int> struct QIntegerForSize;
+template <> struct QIntegerForSize<4> { typedef quint32 Unsigned; typedef qint32 Signed; };
+template <> struct QIntegerForSize<8> { typedef quint64 Unsigned; typedef qint64 Signed; };
+template <class T> struct QIntegerForSizeof: QIntegerForSize<sizeof(T)> { };
+typedef QIntegerForSizeof<void*>::Unsigned quintptr;
+typedef QIntegerForSizeof<void*>::Signed qptrdiff;
/*
Useful type definitions for Qt
@@ -1037,6 +1037,7 @@ typedef int QNoImplicitBoolCast;
#define QT_NO_FPU
#endif
+// This logic must match the one in qmetatype.h
#if defined(QT_COORD_TYPE)
typedef QT_COORD_TYPE qreal;
#elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
@@ -1805,6 +1806,22 @@ static inline bool qFuzzyCompare(float p1, float p2)
return (qAbs(p1 - p2) <= 0.00001f * qMin(qAbs(p1), qAbs(p2)));
}
+/*!
+ \internal
+*/
+static inline bool qFuzzyIsNull(double d)
+{
+ return qAbs(d) <= 0.000000000001;
+}
+
+/*!
+ \internal
+*/
+static inline bool qFuzzyIsNull(float f)
+{
+ return qAbs(f) <= 0.00001f;
+}
+
/*
This function tests a double for a null value. It doesn't
check whether the actual value is 0 or close to 0, but whether
@@ -1936,7 +1953,7 @@ enum { /* TYPEINFO flags */
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
template <> \
-class QTypeInfo<TYPE> \
+class QTypeInfo<TYPE > \
{ \
public: \
enum { \
diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp
index 5e4b9bd..6eb6c3a 100644
--- a/src/corelib/global/qlibraryinfo.cpp
+++ b/src/corelib/global/qlibraryinfo.cpp
@@ -420,14 +420,14 @@ QLibraryInfo::location(LibraryLocation loc)
#else
if (QCoreApplication::instance()) {
#ifdef Q_OS_MAC
- CFBundleRef bundleRef = CFBundleGetMainBundle();
- if (bundleRef) {
- QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
- if (urlRef) {
- QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
- return QDir::cleanPath(path + QLatin1String("/Contents"));
- }
- }
+ CFBundleRef bundleRef = CFBundleGetMainBundle();
+ if (bundleRef) {
+ QCFType<CFURLRef> urlRef = CFBundleCopyBundleURL(bundleRef);
+ if (urlRef) {
+ QCFString path = CFURLCopyFileSystemPath(urlRef, kCFURLPOSIXPathStyle);
+ return QDir::cleanPath(path + QLatin1String("/Contents/") + ret);
+ }
+ }
#endif
return QDir(QCoreApplication::applicationDirPath()).absoluteFilePath(ret);
} else {
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index 43740ed..a94d6d0 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -192,6 +192,12 @@ public:
#endif
};
+ enum TileRule {
+ Stretch,
+ Repeat,
+ Round
+ };
+
// Text formatting flags for QPainter::drawText and QLabel.
// The following two enums can be combined to one integer which
// is passed as 'flags' to drawText and qt_format_text.
@@ -501,6 +507,8 @@ public:
AA_NativeWindows = 3,
AA_DontCreateNativeWidgetSiblings = 4,
AA_MacPluginApplication = 5,
+ AA_DontUseNativeMenuBar = 6,
+ AA_MacDontSwapCtrlAndMeta = 7,
// Add new attributes before this line
AA_AttributeCount
@@ -1323,7 +1331,8 @@ public:
DirectConnection,
QueuedConnection,
AutoCompatConnection,
- BlockingQueuedConnection
+ BlockingQueuedConnection,
+ UniqueConnection = 0x80
};
enum ShortcutContext {
diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h
index 2ce4059..7fc7f47 100644
--- a/src/corelib/global/qt_windows.h
+++ b/src/corelib/global/qt_windows.h
@@ -106,6 +106,9 @@
#ifndef WM_MOUSEWHEEL
#define WM_MOUSEWHEEL 0x020A
#endif
+#ifndef WM_MOUSEHWHEEL
+#define WM_MOUSEHWHEEL 0x020E
+#endif
#ifndef ETO_PDY
#define ETO_PDY 0x2000
#endif
diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri
index 845dc2e..edbab9c 100644
--- a/src/corelib/io/io.pri
+++ b/src/corelib/io/io.pri
@@ -13,6 +13,7 @@ HEADERS += \
io/qfileinfo_p.h \
io/qiodevice.h \
io/qiodevice_p.h \
+ io/qnoncontiguousbytedevice_p.h \
io/qprocess.h \
io/qprocess_p.h \
io/qtextstream.h \
@@ -38,6 +39,7 @@ SOURCES += \
io/qfile.cpp \
io/qfileinfo.cpp \
io/qiodevice.cpp \
+ io/qnoncontiguousbytedevice.cpp \
io/qprocess.cpp \
io/qtextstream.cpp \
io/qtemporaryfile.cpp \
diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h
index 4c8295e..077e720 100644
--- a/src/corelib/io/qdatastream.h
+++ b/src/corelib/io/qdatastream.h
@@ -65,9 +65,8 @@ template <typename T> class QSet;
template <class Key, class T> class QHash;
template <class Key, class T> class QMap;
-class QDataStreamPrivate;
-
#ifndef QT_NO_DATASTREAM
+class QDataStreamPrivate;
class Q_CORE_EXPORT QDataStream
{
public:
@@ -83,10 +82,11 @@ public:
Qt_4_2 = 8,
Qt_4_3 = 9,
Qt_4_4 = 10,
- Qt_4_5 = 11
-#if QT_VERSION >= 0x040600
+ Qt_4_5 = 11,
+ Qt_4_6 = Qt_4_5
+#if QT_VERSION >= 0x040700
#error Add the datastream version for this Qt version
- , Qt_4_6 = Qt_4_5
+ Qt_4_7 = Qt_4_6
#endif
};
diff --git a/src/corelib/io/qdebug.h b/src/corelib/io/qdebug.h
index 60dc688..332058e 100644
--- a/src/corelib/io/qdebug.h
+++ b/src/corelib/io/qdebug.h
@@ -51,6 +51,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qvector.h>
#include <QtCore/qset.h>
+#include <QtCore/qcontiguouscache.h>
QT_BEGIN_HEADER
@@ -87,11 +88,11 @@ public:
delete stream;
}
}
- inline QDebug &space() { stream->space = true; stream->ts << " "; return *this; }
+ inline QDebug &space() { stream->space = true; stream->ts << ' '; return *this; }
inline QDebug &nospace() { stream->space = false; return *this; }
- inline QDebug &maybeSpace() { if (stream->space) stream->ts << " "; return *this; }
+ inline QDebug &maybeSpace() { if (stream->space) stream->ts << ' '; return *this; }
- inline QDebug &operator<<(QChar t) { stream->ts << "\'" << t << "\'"; return maybeSpace(); }
+ inline QDebug &operator<<(QChar t) { stream->ts << '\'' << t << '\''; return maybeSpace(); }
inline QDebug &operator<<(QBool t) { stream->ts << (bool(t) ? "true" : "false"); return maybeSpace(); }
inline QDebug &operator<<(bool t) { stream->ts << (t ? "true" : "false"); return maybeSpace(); }
inline QDebug &operator<<(char t) { stream->ts << t; return maybeSpace(); }
@@ -108,10 +109,10 @@ public:
inline QDebug &operator<<(float t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(double t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(const char* t) { stream->ts << QString::fromAscii(t); return maybeSpace(); }
- inline QDebug &operator<<(const QString & t) { stream->ts << "\"" << t << "\""; return maybeSpace(); }
+ inline QDebug &operator<<(const QString & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
inline QDebug &operator<<(const QStringRef & t) { return operator<<(t.toString()); }
- inline QDebug &operator<<(const QLatin1String &t) { stream->ts << "\"" << t.latin1() << "\""; return maybeSpace(); }
- inline QDebug &operator<<(const QByteArray & t) { stream->ts << "\"" << t << "\""; return maybeSpace(); }
+ inline QDebug &operator<<(const QLatin1String &t) { stream->ts << '\"' << t.latin1() << '\"'; return maybeSpace(); }
+ inline QDebug &operator<<(const QByteArray & t) { stream->ts << '\"' << t << '\"'; return maybeSpace(); }
inline QDebug &operator<<(const void * t) { stream->ts << t; return maybeSpace(); }
inline QDebug &operator<<(QTextStreamFunction f) {
stream->ts << f;
@@ -161,13 +162,13 @@ template <class T>
inline QDebug operator<<(QDebug debug, const QList<T> &list)
#endif
{
- debug.nospace() << "(";
+ debug.nospace() << '(';
for (Q_TYPENAME QList<T>::size_type i = 0; i < list.count(); ++i) {
if (i)
debug << ", ";
debug << list.at(i);
}
- debug << ")";
+ debug << ')';
return debug.space();
}
@@ -194,9 +195,9 @@ inline QDebug operator<<(QDebug debug, const QMap<aKey, aT> &map)
debug.nospace() << "QMap(";
for (typename QMap<aKey, aT>::const_iterator it = map.constBegin();
it != map.constEnd(); ++it) {
- debug << "(" << it.key() << ", " << it.value() << ")";
+ debug << '(' << it.key() << ", " << it.value() << ')';
}
- debug << ")";
+ debug << ')';
return debug.space();
}
@@ -211,8 +212,8 @@ inline QDebug operator<<(QDebug debug, const QHash<aKey, aT> &hash)
debug.nospace() << "QHash(";
for (typename QHash<aKey, aT>::const_iterator it = hash.constBegin();
it != hash.constEnd(); ++it)
- debug << "(" << it.key() << ", " << it.value() << ")";
- debug << ")";
+ debug << '(' << it.key() << ", " << it.value() << ')';
+ debug << ')';
return debug.space();
}
@@ -224,7 +225,7 @@ template <class T1, class T2>
inline QDebug operator<<(QDebug debug, const QPair<T1, T2> &pair)
#endif
{
- debug.nospace() << "QPair(" << pair.first << "," << pair.second << ")";
+ debug.nospace() << "QPair(" << pair.first << ',' << pair.second << ')';
return debug.space();
}
@@ -235,6 +236,24 @@ inline QDebug operator<<(QDebug debug, const QSet<T> &set)
return operator<<(debug, set.toList());
}
+#if defined(FORCE_UREF)
+template <class T>
+inline QDebug &operator<<(QDebug debug, const QContiguousCache<T> &cache)
+#else
+template <class T>
+inline QDebug operator<<(QDebug debug, const QContiguousCache<T> &cache)
+#endif
+{
+ debug.nospace() << "QContiguousCache(";
+ for (int i = cache.firstIndex(); i <= cache.lastIndex(); ++i) {
+ debug << cache[i];
+ if (i != cache.lastIndex())
+ debug << ", ";
+ }
+ debug << ')';
+ return debug.space();
+}
+
#if !defined(QT_NO_DEBUG_STREAM)
Q_CORE_EXPORT_INLINE QDebug qDebug() { return QDebug(QtDebugMsg); }
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index e1cc7ac..46c29d4 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -45,6 +45,7 @@
#ifndef QT_NO_DEBUG_STREAM
#include "qdebug.h"
#endif
+#include "qdiriterator.h"
#include "qfsfileengine.h"
#include "qdatetime.h"
#include "qstring.h"
@@ -55,6 +56,8 @@
# include "qresource.h"
#endif
+#include "qvarlengtharray.h"
+
#include "../kernel/qcoreglobaldata_p.h"
#include <stdlib.h>
@@ -91,7 +94,7 @@ protected:
QString initFileEngine(const QString &file);
void updateFileLists() const;
- void sortFileList(QDir::SortFlags, QStringList &, QStringList *, QFileInfoList *) const;
+ void sortFileList(QDir::SortFlags, QFileInfoList &, QStringList *, QFileInfoList *) const;
private:
#ifdef QT3_SUPPORT
@@ -261,45 +264,57 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt
? f1->filename_cache.localeAwareCompare(f2->filename_cache)
: f1->filename_cache.compare(f2->filename_cache);
}
-
+ if (r == 0) // Enforce an order - the order the items appear in the array
+ r = (&n1) - (&n2);
if (qt_cmp_si_sort_flags & QDir::Reversed)
return r > 0;
return r < 0;
}
-inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QStringList &l,
+inline void QDirPrivate::sortFileList(QDir::SortFlags sort, QFileInfoList &l,
QStringList *names, QFileInfoList *infos) const
{
if(names)
names->clear();
if(infos)
infos->clear();
- if(!l.isEmpty()) {
- QDirSortItem *si= new QDirSortItem[l.count()];
- int i;
- for (i = 0; i < l.size(); ++i) {
- QString path = data->path;
- if (!path.isEmpty() && !path.endsWith(QLatin1Char('/')))
- path += QLatin1Char('/');
- si[i].item = QFileInfo(path + l.at(i));
- }
- if ((sort & QDir::SortByMask) != QDir::Unsorted)
- qStableSort(si, si+i, QDirSortItemComparator(sort));
- // put them back in the list(s)
- for (int j = 0; j<i; j++) {
+ int n = l.size();
+ if(n > 0) {
+ if (n == 1 || (sort & QDir::SortByMask) == QDir::Unsorted) {
if(infos)
- infos->append(si[j].item);
- if(names)
- names->append(si[j].item.fileName());
+ *infos = l;
+ if(names) {
+ for (int i = 0; i < n; ++i)
+ names->append(l.at(i).fileName());
+ }
+ } else {
+ QDirSortItem *si = new QDirSortItem[n];
+ for (int i = 0; i < n; ++i)
+ si[i].item = l.at(i);
+ qSort(si, si+n, QDirSortItemComparator(sort));
+ // put them back in the list(s)
+ if(infos) {
+ for (int i = 0; i < n; ++i)
+ infos->append(si[i].item);
+ }
+ if(names) {
+ for (int i = 0; i < n; ++i)
+ names->append(si[i].item.fileName());
+ }
+ delete [] si;
}
- delete [] si;
}
}
inline void QDirPrivate::updateFileLists() const
{
if(data->listsDirty) {
- QStringList l = data->fileEngine->entryList(data->filters, data->nameFilters);
+ QFileInfoList l;
+ QDirIterator it(data->path, data->nameFilters, data->filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
sortFileList(data->sort, l, &data->files, &data->fileInfos);
data->listsDirty = 0;
}
@@ -1303,7 +1318,6 @@ QStringList QDir::entryList(Filters filters, SortFlags sort) const
\sa entryList(), setNameFilters(), setSorting(), setFilter(), isReadable(), exists()
*/
-
QFileInfoList QDir::entryInfoList(Filters filters, SortFlags sort) const
{
Q_D(const QDir);
@@ -1345,10 +1359,12 @@ QStringList QDir::entryList(const QStringList &nameFilters, Filters filters,
d->updateFileLists();
return d->data->files;
}
- QStringList l = d->data->fileEngine->entryList(filters, nameFilters);
- if ((sort & QDir::SortByMask) == QDir::Unsorted)
- return l;
-
+ QFileInfoList l;
+ QDirIterator it(d->data->path, nameFilters, filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
QStringList ret;
d->sortFileList(sort, l, &ret, 0);
return ret;
@@ -1388,8 +1404,13 @@ QFileInfoList QDir::entryInfoList(const QStringList &nameFilters, Filters filter
d->updateFileLists();
return d->data->fileInfos;
}
+ QFileInfoList l;
+ QDirIterator it(d->data->path, nameFilters, filters);
+ while (it.hasNext()) {
+ it.next();
+ l.append(it.fileInfo());
+ }
QFileInfoList ret;
- QStringList l = d->data->fileEngine->entryList(filters, nameFilters);
d->sortFileList(sort, l, 0, &ret);
return ret;
}
@@ -2056,11 +2077,13 @@ QString QDir::cleanPath(const QString &path)
QString name = path;
QChar dir_separator = separator();
if(dir_separator != QLatin1Char('/'))
- name.replace(dir_separator, QLatin1Char('/'));
+ name.replace(dir_separator, QLatin1Char('/'));
int used = 0, levels = 0;
const int len = name.length();
- QVector<QChar> out(len);
+ QVarLengthArray<QChar> outVector(len);
+ QChar *out = outVector.data();
+
const QChar *p = name.unicode();
for(int i = 0, last = -1, iwrite = 0; i < len; i++) {
if(p[i] == QLatin1Char('/')) {
@@ -2160,7 +2183,7 @@ QString QDir::cleanPath(const QString &path)
if(used == len)
ret = name;
else
- ret = QString(out.data(), used);
+ ret = QString(out, used);
// Strip away last slash except for root directories
if (ret.endsWith(QLatin1Char('/'))
@@ -2223,7 +2246,7 @@ QStringList QDir::nameFiltersFromString(const QString &nameFilter)
\snippet doc/src/snippets/code/src_corelib_io_qdir.cpp 13
- If the file name contains characters that cannot be part of a valid C++ function name
+ If the file name contains characters that cannot be part of a valid C++ function name
(such as '-'), they have to be replaced by the underscore character ('_').
Note: This macro cannot be used in a namespace. It should be called from
@@ -2415,7 +2438,7 @@ QDebug operator<<(QDebug debug, QDir::Filters filters)
if (filters & QDir::System) flags << QLatin1String("System");
if (filters & QDir::CaseSensitive) flags << QLatin1String("CaseSensitive");
}
- debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ")";
+ debug << "QDir::Filters(" << qPrintable(flags.join(QLatin1String("|"))) << ')';
return debug;
}
@@ -2437,8 +2460,8 @@ QDebug operator<<(QDebug debug, QDir::SortFlags sorting)
if (sorting & QDir::LocaleAware) flags << QLatin1String("LocaleAware");
if (sorting & QDir::Type) flags << QLatin1String("Type");
debug << "QDir::SortFlags(" << qPrintable(type)
- << "|"
- << qPrintable(flags.join(QLatin1String("|"))) << ")";
+ << '|'
+ << qPrintable(flags.join(QLatin1String("|"))) << ')';
}
return debug;
}
@@ -2450,9 +2473,9 @@ QDebug operator<<(QDebug debug, const QDir &dir)
<< qPrintable(dir.nameFilters().join(QLatin1String(",")))
<< "}, "
<< dir.sorting()
- << ","
+ << ','
<< dir.filter()
- << ")";
+ << ')';
return debug.space();
}
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 1e3d5a3..9cbd3dc 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -156,17 +156,15 @@ QFilePrivate::setError(QFile::FileError err)
void
QFilePrivate::setError(QFile::FileError err, const QString &errStr)
{
- Q_Q(QFile);
error = err;
- q->setErrorString(errStr);
+ errorString = errStr;
}
void
QFilePrivate::setError(QFile::FileError err, int errNum)
{
- Q_Q(QFile);
error = err;
- q->setErrorString(qt_error_string(errNum));
+ errorString = qt_error_string(errNum);
}
//************* QFile
@@ -707,6 +705,7 @@ QFile::rename(const QString &newName)
d->setError(QFile::RenameError, tr("Destination file exists"));
return false;
}
+ unsetError();
close();
if(error() == QFile::NoError) {
if (fileEngine()->rename(newName)) {
@@ -861,6 +860,7 @@ QFile::copy(const QString &newName)
d->setError(QFile::CopyError, tr("Destination file exists"));
return false;
}
+ unsetError();
close();
if(error() == QFile::NoError) {
if(fileEngine()->copy(newName)) {
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index b36fb69..82b21e9 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -48,73 +48,10 @@
#include "qatomic.h"
#include "qhash.h"
#include "qdir.h"
+#include "qfileinfo_p.h"
QT_BEGIN_NAMESPACE
-class QFileInfoPrivate
-{
-public:
- QFileInfoPrivate(const QFileInfo *copy=0);
- ~QFileInfoPrivate();
-
- void initFileEngine(const QString &);
-
- enum Access {
- ReadAccess,
- WriteAccess,
- ExecuteAccess
- };
- bool hasAccess(Access access) const;
-
- uint getFileFlags(QAbstractFileEngine::FileFlags) const;
- QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
- QString getFileName(QAbstractFileEngine::FileName) const;
-
- enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
- CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
- CachedSize =0x08 };
- struct Data {
- inline Data()
- : ref(1), fileEngine(0), cache_enabled(1)
- { clear(); }
- inline Data(const Data &copy)
- : ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)),
- fileName(copy.fileName), cache_enabled(copy.cache_enabled)
- { clear(); }
- inline ~Data() { delete fileEngine; }
- inline void clearFlags() {
- fileFlags = 0;
- cachedFlags = 0;
- if (fileEngine)
- (void)fileEngine->fileFlags(QFSFileEngine::Refresh);
- }
- inline void clear() {
- fileNames.clear();
- clearFlags();
- }
- mutable QAtomicInt ref;
-
- QAbstractFileEngine *fileEngine;
- mutable QString fileName;
- mutable QHash<int, QString> fileNames;
-
- mutable uint cachedFlags : 31;
- mutable uint cache_enabled : 1;
- mutable uint fileFlags;
- mutable qint64 fileSize;
- mutable QDateTime fileTimes[3];
- inline bool getCachedFlag(uint c) const
- { return cache_enabled ? (cachedFlags & c) : 0; }
- inline void setCachedFlag(uint c)
- { if (cache_enabled) cachedFlags |= c; }
- } *data;
- inline void reset() {
- detach();
- data->clear();
- }
- void detach();
-};
-
QFileInfoPrivate::QFileInfoPrivate(const QFileInfo *copy)
{
if(copy) {
@@ -535,8 +472,7 @@ QFileInfo &QFileInfo::operator=(const QFileInfo &fileinfo)
void QFileInfo::setFile(const QString &file)
{
- Q_D(QFileInfo);
- d->initFileEngine(file);
+ *this = QFileInfo(file);
}
/*!
@@ -553,8 +489,7 @@ void QFileInfo::setFile(const QString &file)
void QFileInfo::setFile(const QFile &file)
{
- Q_D(QFileInfo);
- d->initFileEngine(file.fileName());
+ *this = QFileInfo(file.fileName());
}
/*!
@@ -571,8 +506,7 @@ void QFileInfo::setFile(const QFile &file)
void QFileInfo::setFile(const QDir &dir, const QString &file)
{
- Q_D(QFileInfo);
- d->initFileEngine(dir.filePath(file));
+ *this = QFileInfo(dir.filePath(file));
}
/*!
@@ -919,7 +853,7 @@ QString QFileInfo::suffix() const
\bold{Note:} The QDir returned always corresponds to the object's
parent directory, even if the QFileInfo represents a directory.
-
+
For each of the follwing, dir() returns a QDir for
\c{"~/examples/191697"}.
diff --git a/src/corelib/io/qfileinfo_p.h b/src/corelib/io/qfileinfo_p.h
index 7d66581..8155bcb 100644
--- a/src/corelib/io/qfileinfo_p.h
+++ b/src/corelib/io/qfileinfo_p.h
@@ -46,8 +46,8 @@
// W A R N I N G
// -------------
//
-// This file is not part of the Qt API. It exists for the convenience
-// of QIODevice. This header file may change from version to
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
@@ -76,70 +76,51 @@ public:
QDateTime &getFileTime(QAbstractFileEngine::FileTime) const;
QString getFileName(QAbstractFileEngine::FileName) const;
- enum {
- CachedFileFlags = 0x01,
- CachedLinkTypeFlag = 0x02,
- CachedBundleTypeFlag= 0x04,
- CachedMTime = 0x10,
- CachedCTime = 0x20,
- CachedATime = 0x40,
- CachedSize = 0x08
- };
-
- struct Data
- {
+ enum { CachedFileFlags=0x01, CachedLinkTypeFlag=0x02, CachedBundleTypeFlag=0x04,
+ CachedMTime=0x10, CachedCTime=0x20, CachedATime=0x40,
+ CachedSize =0x08 };
+ struct Data {
inline Data()
: ref(1), fileEngine(0), cache_enabled(1)
- {
- clear();
- }
-
+ { clear(); }
inline Data(const Data &copy)
: ref(1), fileEngine(QAbstractFileEngine::create(copy.fileName)),
fileName(copy.fileName), cache_enabled(copy.cache_enabled)
- {
- clear();
- }
-
- inline ~Data()
- {
- delete fileEngine;
- }
-
- inline void clear()
- {
- fileNames.clear();
+ { clear(); }
+ inline ~Data() { delete fileEngine; }
+ inline void clearFlags() {
fileFlags = 0;
cachedFlags = 0;
+ if (fileEngine)
+ (void)fileEngine->fileFlags(QFSFileEngine::Refresh);
+ }
+ inline void clear() {
+ fileNames.clear();
+ clearFlags();
}
-
mutable QAtomicInt ref;
QAbstractFileEngine *fileEngine;
mutable QString fileName;
mutable QHash<int, QString> fileNames;
+
mutable uint cachedFlags : 31;
mutable uint cache_enabled : 1;
mutable uint fileFlags;
mutable qint64 fileSize;
mutable QDateTime fileTimes[3];
-
inline bool getCachedFlag(uint c) const
{ return cache_enabled ? (cachedFlags & c) : 0; }
-
inline void setCachedFlag(uint c)
{ if (cache_enabled) cachedFlags |= c; }
} *data;
-
inline void reset() {
detach();
data->clear();
}
-
void detach();
};
-
QT_END_NAMESPACE
-#endif
+#endif // QFILEINFO_P_H
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index b83ab85..c5a58e2 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -120,7 +120,7 @@ public:
void stop();
-private slots:
+private Q_SLOTS:
void timeout();
};
diff --git a/src/corelib/io/qfilesystemwatcher_dnotify.cpp b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
index e87375a..a8397f8 100644
--- a/src/corelib/io/qfilesystemwatcher_dnotify.cpp
+++ b/src/corelib/io/qfilesystemwatcher_dnotify.cpp
@@ -114,7 +114,7 @@ private:
bool isExecing;
};
-Q_GLOBAL_STATIC(QDnotifySignalThread, dnotifySignal);
+Q_GLOBAL_STATIC(QDnotifySignalThread, dnotifySignal)
QDnotifySignalThread::QDnotifySignalThread()
: isExecing(false)
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 45e547f..c29e4ec 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -103,12 +103,12 @@ static QByteArray openModeToFopenMode(QIODevice::OpenMode flags, const QString &
} else if (flags & QIODevice::WriteOnly) {
mode = "wb";
if (flags & QIODevice::ReadOnly)
- mode += "+";
+ mode += '+';
}
if (flags & QIODevice::Append) {
mode = "ab";
if (flags & QIODevice::ReadOnly)
- mode += "+";
+ mode += '+';
}
return mode;
}
@@ -986,7 +986,7 @@ QString QFSFileEngine::fileName(FileName file) const
bool isDir = ret.endsWith(QLatin1Char('/'));
ret = QDir::cleanPath(ret);
if (isDir)
- ret += QLatin1String("/");
+ ret += QLatin1Char('/');
if (file == AbsolutePathName) {
int slash = ret.lastIndexOf(QLatin1Char('/'));
if (slash == -1)
@@ -1202,6 +1202,8 @@ bool QFSFileEngine::setSize(qint64 size)
Q_D(QFSFileEngine);
if (d->fd != -1)
return !QT_FTRUNCATE(d->fd, size);
+ if (d->fh)
+ return !QT_FTRUNCATE(QT_FILENO(d->fh), size);
return !QT_TRUNCATE(d->nativeFilePath.constData(), size);
}
diff --git a/src/corelib/io/qfsfileengine_win.cpp b/src/corelib/io/qfsfileengine_win.cpp
index 6ae13e9..896bcc1 100644
--- a/src/corelib/io/qfsfileengine_win.cpp
+++ b/src/corelib/io/qfsfileengine_win.cpp
@@ -433,7 +433,7 @@ static QString nativeAbsoluteFilePathW(const QString &path)
if (retLen != 0)
ret = QString::fromUtf16((unsigned short *)buf.data(), retLen);
#else
- if (path.startsWith(QLatin1String("/")) || path.startsWith(QLatin1String("\\")))
+ if (path.startsWith(QLatin1Char('/')) || path.startsWith(QLatin1Char('\\')))
ret = QDir::toNativeSeparators(path);
else
ret = QDir::toNativeSeparators(QDir::cleanPath(qfsPrivateCurrentDir + QLatin1Char('/') + path));
@@ -1240,7 +1240,7 @@ QString QFSFileEngine::rootPath()
QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData());
if(ret.isEmpty())
ret = QLatin1String("c:");
- ret += QLatin1String("/");
+ ret += QLatin1Char('/');
#elif defined(Q_OS_OS2EMX)
char dir[4];
_abspath(dir, QLatin1String("/"), _MAX_PATH);
@@ -1288,19 +1288,17 @@ QFileInfoList QFSFileEngine::drives()
exit(1);
driveBits &= 0x3ffffff;
#endif
- char driveName[4];
-
- qstrcpy(driveName, "A:/");
+ char driveName[] = "A:/";
while(driveBits) {
if(driveBits & 1)
- ret.append(QString::fromLatin1(driveName).toUpper());
+ ret.append(QString::fromLatin1(driveName));
driveName[0]++;
driveBits = driveBits >> 1;
}
return ret;
#else
- ret.append(QString::fromLatin1("/").toUpper());
+ ret.append(QString::fromLatin1("/"));
return ret;
#endif
}
@@ -1333,8 +1331,6 @@ bool QFSFileEnginePrivate::doStat() const
if (tmpAttributes != -1) {
fileAttrib = tmpAttributes;
could_stat = true;
- } else {
- return false;
}
#endif
} else {
@@ -1774,10 +1770,10 @@ QString QFSFileEngine::fileName(FileName file) const
if(slash == -1) {
if(d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
return d->filePath.left(2);
- return QString::fromLatin1(".");
+ return QString(QLatin1Char('.'));
} else {
if(!slash)
- return QString::fromLatin1("/");
+ return QString(QLatin1Char('/'));
if(slash == 2 && d->filePath.length() >= 2 && d->filePath.at(1) == QLatin1Char(':'))
slash++;
return d->filePath.left(slash);
@@ -1835,7 +1831,7 @@ QString QFSFileEngine::fileName(FileName file) const
if (slash == -1)
ret = QDir::currentPath();
else if (slash == 0)
- ret = QLatin1String("/");
+ ret = QString(QLatin1Char('/'));
ret = ret.left(slash);
}
return ret;
@@ -1897,7 +1893,7 @@ QString QFSFileEngine::owner(FileOwner own) const
#else
Q_UNUSED(own);
#endif
- return QString(QLatin1String(""));
+ return QString();
}
bool QFSFileEngine::setPermissions(uint perms)
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 765bf40..82e54fa 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -48,6 +48,10 @@
#include "qstringlist.h"
#include <limits.h>
+#ifdef QIODEVICE_DEBUG
+# include <ctype.h>
+#endif
+
QT_BEGIN_NAMESPACE
#ifdef QIODEVICE_DEBUG
@@ -1756,7 +1760,7 @@ QDebug operator<<(QDebug debug, QIODevice::OpenMode modes)
}
qSort(modeList);
debug << modeList.join(QLatin1String("|"));
- debug << ")";
+ debug << ')';
return debug;
}
#endif
diff --git a/src/corelib/io/qnoncontiguousbytedevice.cpp b/src/corelib/io/qnoncontiguousbytedevice.cpp
new file mode 100644
index 0000000..1ff3a4c
--- /dev/null
+++ b/src/corelib/io/qnoncontiguousbytedevice.cpp
@@ -0,0 +1,544 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnoncontiguousbytedevice_p.h"
+#include <QObject>
+#include <QBuffer>
+#include <QDebug>
+#include <QFile>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QNonContiguousByteDevice
+ \brief A QNonContiguousByteDevice is a representation of a
+ file, array or buffer that allows access with a read pointer.
+ \since 4.6
+
+ \inmodule QtCore
+
+ The goal of this class is to have a data representation that
+ allows us to avoid doing a memcpy as we have to do with QIODevice.
+
+ \sa QNonContiguousByteDeviceFactory
+
+ \internal
+*/
+/*!
+ \fn virtual const char* QNonContiguousByteDevice::readPointer(qint64 maximumLength, qint64 &len)
+
+ Return a byte pointer for at most \a maximumLength bytes of that device.
+ if \a maximumLength is -1, the caller does not care about the length and
+ the device may return what it desires to.
+ The actual number of bytes the pointer is valid for is returned in
+ the \a len variable.
+ \a len will be -1 if EOF or an error occurs.
+ If it was really EOF can then afterwards be checked with atEnd()
+ Returns 0 if it is not possible to read at that position.
+
+ \sa atEnd()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::advanceReadPointer(qint64 amount)
+
+ will advance the internal read pointer by \a amount bytes.
+ The old readPointer is invalid after this call.
+
+ \sa readPointer()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::atEnd()
+
+ Returns true if everything has been read and the read
+ pointer cannot be advanced anymore.
+
+ \sa readPointer(), advanceReadPointer(), reset()
+
+ \internal
+*/
+/*!
+ \fn virtual bool QNonContiguousByteDevice::reset()
+
+ Moves the internal read pointer back to the beginning.
+ Returns false if this was not possible.
+
+ \sa atEnd(), disableReset()
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::disableReset()
+
+ Disable the reset() call, e.g. it will always
+ do nothing and return false.
+
+ \sa reset()
+
+ \internal
+*/
+/*!
+ \fn virtual qint64 QNonContiguousByteDevice::size()
+
+ Returns the size of the complete device or -1 if unknown.
+ May also return less/more than what can be actually read with readPointer()
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::readyRead()
+
+ Emitted when there is data available
+
+ \internal
+*/
+/*!
+ \fn void QNonContiguousByteDevice::readProgress(qint64 current, qint64 total)
+
+ Emitted when data has been "read" by advancing the read pointer
+
+ \internal
+*/
+
+QNonContiguousByteDevice::QNonContiguousByteDevice() : QObject((QObject*)0), resetDisabled(false)
+{
+}
+
+QNonContiguousByteDevice::~QNonContiguousByteDevice()
+{
+}
+
+void QNonContiguousByteDevice::disableReset()
+{
+ resetDisabled = true;
+}
+
+QNonContiguousByteDeviceBufferImpl::QNonContiguousByteDeviceBufferImpl(QBuffer *b) : QNonContiguousByteDevice()
+{
+ buffer = b;
+ byteArray = QByteArray::fromRawData(buffer->buffer().constData() + buffer->pos(), buffer->size() - buffer->pos());
+ arrayImpl = new QNonContiguousByteDeviceByteArrayImpl(&byteArray);
+ arrayImpl->setParent(this);
+ connect(arrayImpl, SIGNAL(readyRead()), SIGNAL(readyRead()));
+ connect(arrayImpl, SIGNAL(readProgress(qint64,qint64)), SIGNAL(readProgress(qint64,qint64)));
+}
+
+QNonContiguousByteDeviceBufferImpl::~QNonContiguousByteDeviceBufferImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceBufferImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ return arrayImpl->readPointer(maximumLength, len);
+}
+
+bool QNonContiguousByteDeviceBufferImpl::advanceReadPointer(qint64 amount)
+{
+ return arrayImpl->advanceReadPointer(amount);
+}
+
+bool QNonContiguousByteDeviceBufferImpl::atEnd()
+{
+ return arrayImpl->atEnd();
+}
+
+bool QNonContiguousByteDeviceBufferImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+ return arrayImpl->reset();
+}
+
+qint64 QNonContiguousByteDeviceBufferImpl::size()
+{
+ return arrayImpl->size();
+}
+
+QNonContiguousByteDeviceByteArrayImpl::QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba) : QNonContiguousByteDevice(), currentPosition(0)
+{
+ byteArray = ba;
+}
+
+QNonContiguousByteDeviceByteArrayImpl::~QNonContiguousByteDeviceByteArrayImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceByteArrayImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (atEnd()) {
+ len = -1;
+ return 0;
+ }
+
+ if (maximumLength != -1)
+ len = qMin(maximumLength, size() - currentPosition);
+ else
+ len = size() - currentPosition;
+
+ return byteArray->constData() + currentPosition;
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::advanceReadPointer(qint64 amount)
+{
+ currentPosition += amount;
+ emit readProgress(currentPosition, size());
+ return true;
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::atEnd()
+{
+ return currentPosition >= size();
+}
+
+bool QNonContiguousByteDeviceByteArrayImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ currentPosition = 0;
+ return true;
+}
+
+qint64 QNonContiguousByteDeviceByteArrayImpl::size()
+{
+ return byteArray->size();
+}
+
+QNonContiguousByteDeviceRingBufferImpl::QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb)
+ : QNonContiguousByteDevice(), currentPosition(0)
+{
+ ringBuffer = rb;
+}
+
+QNonContiguousByteDeviceRingBufferImpl::~QNonContiguousByteDeviceRingBufferImpl()
+{
+}
+
+const char* QNonContiguousByteDeviceRingBufferImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (atEnd()) {
+ len = -1;
+ return 0;
+ }
+
+ const char *returnValue = ringBuffer->readPointerAtPosition(currentPosition, len);
+
+ if (maximumLength != -1)
+ len = qMin(len, maximumLength);
+
+ return returnValue;
+}
+
+bool QNonContiguousByteDeviceRingBufferImpl::advanceReadPointer(qint64 amount)
+{
+ currentPosition += amount;
+ emit readProgress(currentPosition, size());
+ return true;
+}
+
+bool QNonContiguousByteDeviceRingBufferImpl::atEnd()
+{
+ return currentPosition >= size();
+}
+
+bool QNonContiguousByteDeviceRingBufferImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ currentPosition = 0;
+ return true;
+}
+
+qint64 QNonContiguousByteDeviceRingBufferImpl::size()
+{
+ return ringBuffer->size();
+}
+
+QNonContiguousByteDeviceIoDeviceImpl::QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d)
+ : QNonContiguousByteDevice(),
+ currentReadBuffer(0), currentReadBufferSize(16*1024),
+ currentReadBufferAmount(0), currentReadBufferPosition(0), totalAdvancements(0),
+ eof(false)
+{
+ device = d;
+ initialPosition = d->pos();
+ connect(device, SIGNAL(readyRead()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+ connect(device, SIGNAL(readChannelFinished()), this, SIGNAL(readyRead()), Qt::QueuedConnection);
+}
+
+QNonContiguousByteDeviceIoDeviceImpl::~QNonContiguousByteDeviceIoDeviceImpl()
+{
+ delete currentReadBuffer;
+}
+
+const char* QNonContiguousByteDeviceIoDeviceImpl::readPointer(qint64 maximumLength, qint64 &len)
+{
+ if (eof == true) {
+ len = -1;
+ return 0;
+ }
+
+ if (currentReadBuffer == 0)
+ currentReadBuffer = new QByteArray(currentReadBufferSize, '\0'); // lazy alloc
+
+ if (maximumLength == -1)
+ maximumLength = currentReadBufferSize;
+
+ if (currentReadBufferAmount - currentReadBufferPosition > 0) {
+ len = currentReadBufferAmount - currentReadBufferPosition;
+ return currentReadBuffer->data() + currentReadBufferPosition;
+ }
+
+ qint64 haveRead = device->read(currentReadBuffer->data(), qMin(maximumLength, currentReadBufferSize));
+
+ if ((haveRead == -1) || (haveRead == 0 && device->atEnd() && !device->isSequential())) {
+ eof = true;
+ len = -1;
+ // size was unknown before, emit a readProgress with the final size
+ if (size() == -1)
+ emit readProgress(totalAdvancements, totalAdvancements);
+ return 0;
+ }
+
+ currentReadBufferAmount = haveRead;
+ currentReadBufferPosition = 0;
+
+ len = haveRead;
+ return currentReadBuffer->data();
+}
+
+bool QNonContiguousByteDeviceIoDeviceImpl::advanceReadPointer(qint64 amount)
+{
+ totalAdvancements += amount;
+
+ // normal advancement
+ currentReadBufferPosition += amount;
+
+ // advancing over that what has actually been read before
+ if (currentReadBufferPosition > currentReadBufferAmount) {
+ qint64 i = currentReadBufferPosition - currentReadBufferAmount;
+ while (i > 0) {
+ if (device->getChar(0) == false) {
+ emit readProgress(totalAdvancements - i, size());
+ return false; // ### FIXME handle eof
+ }
+ i--;
+ }
+
+ currentReadBufferPosition = 0;
+ currentReadBufferAmount = 0;
+ }
+
+ if (size() == -1)
+ emit readProgress(totalAdvancements, totalAdvancements);
+ else
+ emit readProgress(totalAdvancements, size());
+
+ return true;
+}
+
+bool QNonContiguousByteDeviceIoDeviceImpl::atEnd()
+{
+ return eof == true;
+}
+
+bool QNonContiguousByteDeviceIoDeviceImpl::reset()
+{
+ if (resetDisabled)
+ return false;
+
+ if (device->seek(initialPosition)) {
+ eof = false; // assume eof is false, it will be true after a read has been attempted
+ return true;
+ }
+
+ return false;
+}
+
+qint64 QNonContiguousByteDeviceIoDeviceImpl::size()
+{
+ // note that this is different from the size() implementation of QIODevice!
+
+ if (device->isSequential())
+ return -1;
+
+ return device->size() - initialPosition;
+}
+
+QByteDeviceWrappingIoDevice::QByteDeviceWrappingIoDevice(QNonContiguousByteDevice *bd) : QIODevice((QObject*)0)
+{
+ byteDevice = bd;
+ connect(bd, SIGNAL(readyRead()), SIGNAL(readyRead()));
+
+ open(ReadOnly);
+}
+
+QByteDeviceWrappingIoDevice::~QByteDeviceWrappingIoDevice()
+{
+
+}
+
+bool QByteDeviceWrappingIoDevice::isSequential() const
+{
+ return (byteDevice->size() == -1);
+}
+
+bool QByteDeviceWrappingIoDevice::atEnd() const
+{
+ return byteDevice->atEnd();
+}
+
+bool QByteDeviceWrappingIoDevice::reset()
+{
+ return byteDevice->reset();
+}
+
+qint64 QByteDeviceWrappingIoDevice::size() const
+{
+ if (isSequential())
+ return 0;
+
+ return byteDevice->size();
+}
+
+
+qint64 QByteDeviceWrappingIoDevice::readData( char * data, qint64 maxSize)
+{
+ qint64 len;
+ const char *readPointer = byteDevice->readPointer(maxSize, len);
+ if (len == -1)
+ return -1;
+
+ memcpy(data, readPointer, len);
+ byteDevice->advanceReadPointer(len);
+ return len;
+}
+
+qint64 QByteDeviceWrappingIoDevice::writeData( const char* data, qint64 maxSize)
+{
+ Q_UNUSED(data);
+ Q_UNUSED(maxSize);
+ return -1;
+}
+
+/*!
+ \class QNonContiguousByteDeviceFactory
+ \since 4.6
+
+ \inmodule QtCore
+
+ Creates a QNonContiguousByteDevice out of a QIODevice,
+ QByteArray etc.
+
+ \sa QNonContiguousByteDevice
+
+ \internal
+*/
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device);
+
+ Create a QNonContiguousByteDevice out of a QIODevice.
+ For QFile, QBuffer and all other QIoDevice, sequential or not.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QIODevice *device)
+{
+ // shortcut if it is a QBuffer
+ if (QBuffer* buffer = qobject_cast<QBuffer*>(device)) {
+ return new QNonContiguousByteDeviceBufferImpl(buffer);
+ }
+
+ // ### FIXME special case if device is a QFile that supports map()
+ // then we can actually deal with the file without using read/peek
+
+ // generic QIODevice
+ return new QNonContiguousByteDeviceIoDeviceImpl(device); // FIXME
+}
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer);
+
+ Create a QNonContiguousByteDevice out of a QRingBuffer.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QRingBuffer *ringBuffer)
+{
+ return new QNonContiguousByteDeviceRingBufferImpl(ringBuffer);
+}
+
+/*!
+ \fn static QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray);
+
+ Create a QNonContiguousByteDevice out of a QByteArray.
+
+ \internal
+*/
+QNonContiguousByteDevice* QNonContiguousByteDeviceFactory::create(QByteArray *byteArray)
+{
+ return new QNonContiguousByteDeviceByteArrayImpl(byteArray);
+}
+
+/*!
+ \fn static QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice);
+
+ Wrap the \a byteDevice (possibly again) into a QIODevice.
+
+ \internal
+*/
+QIODevice* QNonContiguousByteDeviceFactory::wrap(QNonContiguousByteDevice* byteDevice)
+{
+ // ### FIXME if it already has been based on QIoDevice, we could that one out again
+ // and save some calling
+
+ // needed for FTP backend
+
+ return new QByteDeviceWrappingIoDevice(byteDevice);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/corelib/io/qnoncontiguousbytedevice_p.h b/src/corelib/io/qnoncontiguousbytedevice_p.h
new file mode 100644
index 0000000..562b759
--- /dev/null
+++ b/src/corelib/io/qnoncontiguousbytedevice_p.h
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNONCONTIGUOUSBYTEDEVICE_H
+#define QNONCONTIGUOUSBYTEDEVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of a number of Qt sources files. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QObject>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qbuffer.h>
+#include <QtCore/qiodevice.h>
+#include "private/qringbuffer_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_CORE_EXPORT QNonContiguousByteDevice : public QObject
+{
+ Q_OBJECT
+public:
+ virtual const char* readPointer(qint64 maximumLength, qint64 &len) = 0;
+ virtual bool advanceReadPointer(qint64 amount) = 0;
+ virtual bool atEnd() = 0;
+ virtual bool reset() = 0;
+ void disableReset();
+ virtual qint64 size() = 0;
+
+protected:
+ QNonContiguousByteDevice();
+ virtual ~QNonContiguousByteDevice();
+
+ bool resetDisabled;
+Q_SIGNALS:
+ void readyRead();
+ void readProgress(qint64 current, qint64 total);
+};
+
+class Q_CORE_EXPORT QNonContiguousByteDeviceFactory
+{
+public:
+ static QNonContiguousByteDevice* create(QIODevice *device);
+ static QNonContiguousByteDevice* create(QByteArray *byteArray);
+ static QNonContiguousByteDevice* create(QRingBuffer *ringBuffer);
+ static QIODevice* wrap(QNonContiguousByteDevice* byteDevice);
+};
+
+// the actual implementations
+//
+
+class QNonContiguousByteDeviceByteArrayImpl : public QNonContiguousByteDevice
+{
+public:
+ QNonContiguousByteDeviceByteArrayImpl(QByteArray *ba);
+ ~QNonContiguousByteDeviceByteArrayImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QByteArray* byteArray;
+ qint64 currentPosition;
+};
+
+class QNonContiguousByteDeviceRingBufferImpl : public QNonContiguousByteDevice
+{
+public:
+ QNonContiguousByteDeviceRingBufferImpl(QRingBuffer *rb);
+ ~QNonContiguousByteDeviceRingBufferImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QRingBuffer* ringBuffer;
+ qint64 currentPosition;
+};
+
+
+class QNonContiguousByteDeviceIoDeviceImpl : public QNonContiguousByteDevice
+{
+public:
+ QNonContiguousByteDeviceIoDeviceImpl(QIODevice *d);
+ ~QNonContiguousByteDeviceIoDeviceImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QIODevice* device;
+ QByteArray* currentReadBuffer;
+ qint64 currentReadBufferSize;
+ qint64 currentReadBufferAmount;
+ qint64 currentReadBufferPosition;
+ qint64 totalAdvancements;
+ bool eof;
+ qint64 initialPosition;
+};
+
+class QNonContiguousByteDeviceBufferImpl : public QNonContiguousByteDevice
+{
+public:
+ QNonContiguousByteDeviceBufferImpl(QBuffer *b);
+ ~QNonContiguousByteDeviceBufferImpl();
+ const char* readPointer(qint64 maximumLength, qint64 &len);
+ bool advanceReadPointer(qint64 amount);
+ bool atEnd();
+ bool reset();
+ qint64 size();
+protected:
+ QBuffer* buffer;
+ QByteArray byteArray;
+ QNonContiguousByteDeviceByteArrayImpl* arrayImpl;
+};
+
+// ... and the reverse thing
+class QByteDeviceWrappingIoDevice : public QIODevice
+{
+public:
+ QByteDeviceWrappingIoDevice (QNonContiguousByteDevice *bd);
+ ~QByteDeviceWrappingIoDevice ();
+ virtual bool isSequential () const;
+ virtual bool atEnd () const;
+ virtual bool reset ();
+ virtual qint64 size () const;
+protected:
+ virtual qint64 readData ( char * data, qint64 maxSize );
+ virtual qint64 writeData ( const char * data, qint64 maxSize );
+
+ QNonContiguousByteDevice *byteDevice;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 8183527..0becbb6 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -101,6 +101,29 @@ QT_END_NAMESPACE
QT_BEGIN_NAMESPACE
+static QHash<QString, QString> environmentHashFromList(const QStringList &environment)
+{
+ QHash<QString, QString> result;
+ QStringList::ConstIterator it = environment.constBegin(),
+ end = environment.constEnd();
+ for ( ; it != end; ++it) {
+ int equals = it->indexOf(QLatin1Char('='));
+
+ QString name = *it;
+ QString value;
+ if (equals != -1) {
+ name.truncate(equals);
+#ifdef Q_OS_WIN
+ name = name.toUpper();
+#endif
+ value = it->mid(equals + 1);
+ }
+ result.insert(name, value);
+ }
+
+ return result;
+}
+
void QProcessPrivate::Channel::clear()
{
switch (type) {
@@ -421,6 +444,7 @@ QProcessPrivate::QProcessPrivate()
sequenceNumber = 0;
exitCode = 0;
exitStatus = QProcess::NormalExit;
+ environment = 0;
startupSocketNotifier = 0;
deathNotifier = 0;
notifier = 0;
@@ -451,6 +475,7 @@ QProcessPrivate::QProcessPrivate()
*/
QProcessPrivate::~QProcessPrivate()
{
+ delete environment;
if (stdinChannel.process)
stdinChannel.process->stdoutChannel.clear();
if (stdoutChannel.process)
@@ -1211,29 +1236,83 @@ QProcess::ProcessState QProcess::state() const
\snippet doc/src/snippets/qprocess-environment/main.cpp 0
- \sa environment(), systemEnvironment()
+ \sa environment(), systemEnvironment(), setEnvironmentHash()
*/
void QProcess::setEnvironment(const QStringList &environment)
{
- Q_D(QProcess);
- d->environment = environment;
+ setEnvironmentHash(environmentHashFromList(environment));
}
/*!
Returns the environment that QProcess will use when starting a
process, or an empty QStringList if no environment has been set
- using setEnvironment(). If no environment has been set, the
- environment of the calling process will be used.
+ using setEnvironment() or setEnvironmentHash(). If no environment
+ has been set, the environment of the calling process will be used.
\note The environment settings are ignored on Windows CE and Symbian,
as there is no concept of an environment.
- \sa setEnvironment(), systemEnvironment()
+ \sa environmentHash(), setEnvironment(), systemEnvironment()
*/
QStringList QProcess::environment() const
{
Q_D(const QProcess);
- return d->environment;
+
+ QStringList result;
+ if (!d->environment)
+ return result;
+
+ QHash<QString, QString>::ConstIterator it = d->environment->constBegin(),
+ end = d->environment->constEnd();
+ for ( ; it != end; ++it) {
+ QString data = it.key();
+ data.reserve(data.length() + it.value().length() + 1);
+ data.append(QLatin1Char('='));
+ data.append(it.value());
+ result << data;
+ }
+ return result;
+}
+
+/*!
+ \since 4.5
+ Sets the environment that QProcess will use when starting a process to the
+ \a environment hash map.
+
+ For example, the following code adds the \c{C:\\BIN} directory to the list of
+ executable paths (\c{PATHS}) on Windows and sets \c{TMPDIR}:
+
+ \snippet doc/src/snippets/qprocess-environment/main.cpp 1
+
+ \sa environment(), systemEnvironmentHash(), setEnvironment()
+*/
+void QProcess::setEnvironmentHash(const QHash<QString, QString> &environment)
+{
+ Q_D(QProcess);
+ if (!d->environment)
+ d->environment = new QHash<QString, QString>(environment);
+ else
+ *d->environment = environment;
+}
+
+/*!
+ \since 4.5
+ Returns the environment that QProcess will use when starting a
+ process, or an empty QHash if no environment has been set using
+ setEnvironment() or setEnvironmentHash(). If no environment has
+ been set, the environment of the calling process will be used.
+
+ \note The environment settings are ignored on Windows CE,
+ as there is no concept of an environment.
+
+ \sa setEnvironmentHash(), setEnvironment(), systemEnvironmentHash()
+*/
+QHash<QString, QString> QProcess::environmentHash() const
+{
+ Q_D(const QProcess);
+ if (d->environment)
+ return *d->environment;
+ return QHash<QString, QString>();
}
/*!
@@ -1527,7 +1606,7 @@ void QProcess::start(const QString &program, const QStringList &arguments, OpenM
}
#if defined QPROCESS_DEBUG
- qDebug() << "QProcess::start(" << program << "," << arguments << "," << mode << ")";
+ qDebug() << "QProcess::start(" << program << ',' << arguments << ',' << mode << ')';
#endif
d->outputReadBuffer.clear();
@@ -1838,7 +1917,7 @@ QT_END_INCLUDE_NAMESPACE
\snippet doc/src/snippets/code/src_corelib_io_qprocess.cpp 8
- \sa environment(), setEnvironment()
+ \sa systemEnvironmentHash(), environment(), setEnvironment()
*/
QStringList QProcess::systemEnvironment()
{
@@ -1851,6 +1930,18 @@ QStringList QProcess::systemEnvironment()
}
/*!
+ \since 4.5
+
+ Returns the environment of the calling process as a QHash.
+
+ \sa systemEnvironment(), environmentHash(), setEnvironmentHash()
+*/
+QHash<QString, QString> QProcess::systemEnvironmentHash()
+{
+ return environmentHashFromList(systemEnvironment());
+}
+
+/*!
\typedef Q_PID
\relates QProcess
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index ae40de3..65b5b3e 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -53,6 +53,8 @@ QT_MODULE(Core)
#ifndef QT_NO_PROCESS
+template <class Key, class T> class QHash;
+
#if (!defined(Q_OS_WIN32) && !defined(Q_OS_WINCE) && !defined(Q_OS_SYMBIAN)) || defined(qdoc)
typedef qint64 Q_PID;
#elif defined(Q_OS_SYMBIAN)
@@ -126,6 +128,8 @@ public:
void setEnvironment(const QStringList &environment);
QStringList environment() const;
+ void setEnvironmentHash(const QHash<QString, QString> &environment);
+ QHash<QString, QString> environmentHash() const;
QProcess::ProcessError error() const;
QProcess::ProcessState state() const;
@@ -161,6 +165,7 @@ public:
static bool startDetached(const QString &program);
static QStringList systemEnvironment();
+ static QHash<QString, QString> systemEnvironmentHash();
public Q_SLOTS:
void terminate();
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 554c477..6a3342a 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -161,7 +161,7 @@ public:
QString program;
QStringList arguments;
- QStringList environment;
+ QHash<QString, QString> *environment;
QRingBuffer outputReadBuffer;
QRingBuffer errorReadBuffer;
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index 1fedd55..e87c314 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -385,17 +385,10 @@ static void qt_create_pipe(int *pipe)
qt_native_close(pipe[0]);
if (pipe[1] != -1)
qt_native_close(pipe[1]);
-#ifdef Q_OS_IRIX
- if (::socketpair(AF_UNIX, SOCK_STREAM, 0, pipe) == -1) {
- qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
- pipe, qPrintable(qt_error_string(errno)));
- }
-#else
if (::pipe(pipe) != 0) {
qWarning("QProcessPrivate::createPipe: Cannot create pipe %p: %s",
pipe, qPrintable(qt_error_string(errno)));
}
-#endif
::fcntl(pipe[0], F_SETFD, FD_CLOEXEC);
::fcntl(pipe[1], F_SETFD, FD_CLOEXEC);
}
@@ -522,8 +515,12 @@ bool QProcessPrivate::createChannel(Channel &channel)
}
}
-static char **_q_dupEnvironment(const QStringList &environment, int *envc)
+static char **_q_dupEnvironment(const QHash<QString, QString> *environment, int *envc)
{
+ *envc = 0;
+ if (!environment)
+ return 0; // use the default environment
+
// if LD_LIBRARY_PATH exists in the current environment, but
// not in the environment list passed by the programmer, then
// copy it over.
@@ -532,27 +529,29 @@ static char **_q_dupEnvironment(const QStringList &environment, int *envc)
#else
static const char libraryPath[] = "LD_LIBRARY_PATH";
#endif
- const QString libraryPathString = QLatin1String(libraryPath);
- QStringList env = environment;
- QStringList matches = env.filter(
- QRegExp(QLatin1Char('^') + libraryPathString + QLatin1Char('=')));
- const QString envLibraryPath = QString::fromLocal8Bit(::getenv(libraryPath));
- if (matches.isEmpty() && !envLibraryPath.isEmpty()) {
- QString entry = libraryPathString;
- entry += QLatin1Char('=');
- entry += envLibraryPath;
- env << libraryPathString + QLatin1Char('=') + envLibraryPath;
- }
-
- char **envp = new char *[env.count() + 1];
- envp[env.count()] = 0;
-
- for (int j = 0; j < env.count(); ++j) {
- QString item = env.at(j);
- envp[j] = ::strdup(item.toLocal8Bit().constData());
+ const QByteArray envLibraryPath = qgetenv(libraryPath);
+ bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
+ !environment->contains(QLatin1String(libraryPath));
+
+ char **envp = new char *[environment->count() + 2];
+ envp[environment->count()] = 0;
+ envp[environment->count() + 1] = 0;
+
+ QHash<QString, QString>::ConstIterator it = environment->constBegin();
+ const QHash<QString, QString>::ConstIterator end = environment->constEnd();
+ for ( ; it != end; ++it) {
+ QByteArray key = it.key().toLocal8Bit();
+ QByteArray value = it.value().toLocal8Bit();
+ key.reserve(key.length() + 1 + value.length());
+ key.append('=');
+ key.append(value);
+
+ envp[(*envc)++] = ::strdup(key.constData());
}
- *envc = env.count();
+ if (needToAddLibraryPath)
+ envp[(*envc)++] = ::strdup(QByteArray(libraryPath) + '=' +
+ envLibraryPath);
return envp;
}
@@ -581,29 +580,27 @@ void QProcessPrivate::startProcess()
processManager()->start();
// Initialize pipes
+ if (!createChannel(stdinChannel) ||
+ !createChannel(stdoutChannel) ||
+ !createChannel(stderrChannel))
+ return;
qt_create_pipe(childStartedPipe);
+ qt_create_pipe(deathPipe);
+ ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC);
+ ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC);
+
if (threadData->eventDispatcher) {
startupSocketNotifier = new QSocketNotifier(childStartedPipe[0],
QSocketNotifier::Read, q);
QObject::connect(startupSocketNotifier, SIGNAL(activated(int)),
q, SLOT(_q_startupNotification()));
- }
- qt_create_pipe(deathPipe);
- ::fcntl(deathPipe[0], F_SETFD, FD_CLOEXEC);
- ::fcntl(deathPipe[1], F_SETFD, FD_CLOEXEC);
- if (threadData->eventDispatcher) {
deathNotifier = new QSocketNotifier(deathPipe[0],
QSocketNotifier::Read, q);
QObject::connect(deathNotifier, SIGNAL(activated(int)),
q, SLOT(_q_processDied()));
}
- if (!createChannel(stdinChannel) ||
- !createChannel(stdoutChannel) ||
- !createChannel(stderrChannel))
- return;
-
// Start the process (platform dependent)
q->setProcessState(QProcess::Starting);
@@ -791,7 +788,7 @@ void QProcessPrivate::execChild(const char *workingDir, char **path, char **argv
q->setupChildProcess();
// execute the process
- if (environment.isEmpty()) {
+ if (!envp) {
qt_native_execvp(argv[0], argv);
} else {
if (path) {
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 0e36760..179c3d0 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -272,12 +272,12 @@ static QString qt_create_commandline(const QString &program, const QStringList &
QString args;
if (!program.isEmpty()) {
QString programName = program;
- if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1String(" ")))
- programName = QLatin1String("\"") + programName + QLatin1String("\"");
- programName.replace(QLatin1String("/"), QLatin1String("\\"));
+ if (!programName.startsWith(QLatin1Char('\"')) && !programName.endsWith(QLatin1Char('\"')) && programName.contains(QLatin1Char(' ')))
+ programName = QLatin1Char('\"') + programName + QLatin1Char('\"');
+ programName.replace(QLatin1Char('/'), QLatin1Char('\\'));
// add the prgram as the first arg ... it works better
- args = programName + QLatin1String(" ");
+ args = programName + QLatin1Char(' ');
}
for (int i=0; i<arguments.size(); ++i) {
@@ -285,16 +285,16 @@ static QString qt_create_commandline(const QString &program, const QStringList &
// in the case of \" already being in the string the \ must also be escaped
tmp.replace( QLatin1String("\\\""), QLatin1String("\\\\\"") );
// escape a single " because the arguments will be parsed
- tmp.replace( QLatin1String("\""), QLatin1String("\\\"") );
+ tmp.replace( QLatin1Char('\"'), QLatin1String("\\\"") );
if (tmp.isEmpty() || tmp.contains(QLatin1Char(' ')) || tmp.contains(QLatin1Char('\t'))) {
// The argument must not end with a \ since this would be interpreted
// as escaping the quote -- rather put the \ behind the quote: e.g.
// rather use "foo"\ than "foo\"
- QString endQuote(QLatin1String("\""));
+ QString endQuote(QLatin1Char('\"'));
int i = tmp.length();
while (i>0 && tmp.at(i-1) == QLatin1Char('\\')) {
--i;
- endQuote += QLatin1String("\\");
+ endQuote += QLatin1Char('\\');
}
args += QLatin1String(" \"") + tmp.left(i) + endQuote;
} else {
@@ -304,44 +304,69 @@ static QString qt_create_commandline(const QString &program, const QStringList &
return args;
}
-static QByteArray qt_create_environment(const QStringList &environment)
+static QByteArray qt_create_environment(const QHash<QString, QString> *environment)
{
QByteArray envlist;
- if (!environment.isEmpty()) {
- QStringList envStrings = environment;
- int pos = 0;
- // add PATH if necessary (for DLL loading)
- if (envStrings.filter(QRegExp(QLatin1String("^PATH="),Qt::CaseInsensitive)).isEmpty()) {
+ if (environment) {
+ QHash<QString, QString> copy = *environment;
+
+ // add PATH if necessary (for DLL loading)
+ if (!copy.contains(QLatin1String("PATH"))) {
QByteArray path = qgetenv("PATH");
if (!path.isEmpty())
- envStrings.prepend(QString(QLatin1String("PATH=%1")).arg(QString::fromLocal8Bit(path)));
+ copy.insert(QLatin1String("PATH"), QString::fromLocal8Bit(path));
}
+
// add systemroot if needed
- if (envStrings.filter(QRegExp(QLatin1String("^SystemRoot="),Qt::CaseInsensitive)).isEmpty()) {
- QByteArray systemRoot = qgetenv("SystemRoot");
+ if (!copy.contains(QLatin1String("SYSTEMROOT"))) {
+ QByteArray systemRoot = qgetenv("SYSTEMROOT");
if (!systemRoot.isEmpty())
- envStrings.prepend(QString(QLatin1String("SystemRoot=%1")).arg(QString::fromLocal8Bit(systemRoot)));
+ copy.insert(QLatin1String("SYSTEMROOT"), QString::fromLocal8Bit(systemRoot));
}
+
+ int pos = 0;
+ QHash<QString, QString>::ConstIterator it = copy.constBegin(),
+ end = copy.constEnd();
#ifdef UNICODE
if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
- for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); ++it) {
- QString tmp = *it;
- uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
+ static const TCHAR equal = L'=';
+ static const TCHAR nul = L'\0';
+
+ for ( ; it != end; ++it) {
+ uint tmpSize = sizeof(TCHAR) * (it.key().length() + it.value().length() + 2);
+ // ignore empty strings
+ if (tmpSize == sizeof(TCHAR)*2)
+ continue;
envlist.resize(envlist.size() + tmpSize);
- memcpy(envlist.data()+pos, tmp.utf16(), tmpSize);
+
+ tmpSize = it.key().length() * sizeof(TCHAR);
+ memcpy(envlist.data()+pos, it.key().utf16(), tmpSize);
+ pos += tmpSize;
+
+ memcpy(envlist.data()+pos, &equal, sizeof(TCHAR));
+ pos += sizeof(TCHAR);
+
+ tmpSize = it.value().length() * sizeof(TCHAR);
+ memcpy(envlist.data()+pos, it.value().utf16(), tmpSize);
pos += tmpSize;
- }
- // add the 2 terminating 0 (actually 4, just to be on the safe side)
- envlist.resize( envlist.size()+4 );
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
- envlist[pos++] = 0;
+
+ memcpy(envlist.data()+pos, &nul, sizeof(TCHAR));
+ pos += sizeof(TCHAR);
+ }
+ // add the 2 terminating 0 (actually 4, just to be on the safe side)
+ envlist.resize( envlist.size()+4 );
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
+ envlist[pos++] = 0;
} else
#endif // UNICODE
{
- for (QStringList::ConstIterator it = envStrings.constBegin(); it != envStrings.constEnd(); it++) {
- QByteArray tmp = (*it).toLocal8Bit();
+ for ( ; it != end; it++) {
+ QByteArray tmp = it.key().toLocal8Bit();
+ tmp.append('=');
+ tmp.append(it.value().toLocal8Bit());
+
uint tmpSize = tmp.length() + 1;
envlist.resize(envlist.size() + tmpSize);
memcpy(envlist.data()+pos, tmp.data(), tmpSize);
@@ -402,7 +427,7 @@ void QProcessPrivate::startProcess()
QString fullPathProgram = program;
if (!QDir::isAbsolutePath(fullPathProgram))
fullPathProgram = QFileInfo(fullPathProgram).absoluteFilePath();
- fullPathProgram.replace(QLatin1String("/"), QLatin1String("\\"));
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
success = CreateProcessW((WCHAR*)fullPathProgram.utf16(),
(WCHAR*)args.utf16(),
0, 0, false, 0, 0, 0, 0, pid);
@@ -418,7 +443,7 @@ void QProcessPrivate::startProcess()
};
success = CreateProcessW(0, (WCHAR*)args.utf16(),
0, 0, TRUE, dwCreationFlags,
- environment.isEmpty() ? 0 : envlist.data(),
+ environment ? envlist.data() : 0,
workingDirectory.isEmpty() ? 0
: (WCHAR*)QDir::toNativeSeparators(workingDirectory).utf16(),
&startupInfo, pid);
@@ -437,7 +462,7 @@ void QProcessPrivate::startProcess()
};
success = CreateProcessA(0, args.toLocal8Bit().data(),
- 0, 0, TRUE, dwCreationFlags, environment.isEmpty() ? 0 : envlist.data(),
+ 0, 0, TRUE, dwCreationFlags, environment ? envlist.data() : 0,
workingDirectory.isEmpty() ? 0
: QDir::toNativeSeparators(workingDirectory).toLocal8Bit().data(),
&startupInfo, pid);
@@ -862,8 +887,8 @@ bool QProcessPrivate::startDetached(const QString &program, const QStringList &a
#if defined(Q_OS_WINCE)
QString fullPathProgram = program;
if (!QDir::isAbsolutePath(fullPathProgram))
- fullPathProgram.prepend(QDir::currentPath().append(QLatin1String("/")));
- fullPathProgram.replace(QLatin1String("/"), QLatin1String("\\"));
+ fullPathProgram.prepend(QDir::currentPath().append(QLatin1Char('/')));
+ fullPathProgram.replace(QLatin1Char('/'), QLatin1Char('\\'));
success = CreateProcessW((WCHAR*)fullPathProgram.utf16(),
(WCHAR*)args.utf16(),
0, 0, false, CREATE_NEW_CONSOLE, 0, 0, 0, &pinfo);
diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp
index 0cbcc41..c3c7b76 100644
--- a/src/corelib/io/qresource.cpp
+++ b/src/corelib/io/qresource.cpp
@@ -60,6 +60,37 @@
QT_BEGIN_NAMESPACE
+
+class QStringSplitter
+{
+public:
+ QStringSplitter(const QString &s)
+ : m_string(s), m_data(m_string.constData()), m_len(s.length()), m_pos(0)
+ {
+ m_splitChar = QLatin1Char('/');
+ }
+
+ inline bool hasNext() {
+ while (m_pos < m_len && m_data[m_pos] == m_splitChar)
+ ++m_pos;
+ return m_pos < m_len;
+ }
+
+ inline QStringRef next() {
+ int start = m_pos;
+ while (m_pos < m_len && m_data[m_pos] != m_splitChar)
+ ++m_pos;
+ return QStringRef(&m_string, start, m_pos - start);
+ }
+
+ QString m_string;
+ const QChar *m_data;
+ QChar m_splitChar;
+ int m_len;
+ int m_pos;
+};
+
+
//resource glue
class QResourceRoot
{
@@ -101,6 +132,16 @@ protected:
}
};
+static QString cleanPath(const QString &_path)
+{
+ QString path = QDir::cleanPath(_path);
+ // QDir::cleanPath does not remove two trailing slashes under _Windows_
+ // due to support for UNC paths. Remove those manually.
+ if (path.startsWith(QLatin1String("//")))
+ path.remove(0, 1);
+ return path;
+}
+
Q_DECLARE_TYPEINFO(QResourceRoot, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, resourceMutex, (QMutex::Recursive))
@@ -216,9 +257,10 @@ QResourcePrivate::load(const QString &file)
related.clear();
QMutexLocker lock(resourceMutex());
const ResourceList *list = resourceList();
+ QString cleaned = cleanPath(file);
for(int i = 0; i < list->size(); ++i) {
QResourceRoot *res = list->at(i);
- const int node = res->findNode(file);
+ const int node = res->findNode(cleaned);
if(node != -1) {
if(related.isEmpty()) {
container = res->isContainer(node);
@@ -292,6 +334,7 @@ QResourcePrivate::ensureChildren() const
if(path.startsWith(QLatin1Char(':')))
path = path.mid(1);
QSet<QString> kids;
+ QString cleaned = cleanPath(path);
for(int i = 0; i < related.size(); ++i) {
QResourceRoot *res = related.at(i);
if(res->mappingRootSubdir(path, &k) && !k.isEmpty()) {
@@ -300,7 +343,7 @@ QResourcePrivate::ensureChildren() const
kids.insert(k);
}
} else {
- const int node = res->findNode(path);
+ const int node = res->findNode(cleaned);
if(node != -1) {
QStringList related_children = res->children(node);
for(int kid = 0; kid < related_children.size(); ++kid) {
@@ -561,30 +604,32 @@ inline QString QResourceRoot::name(int node) const
(names[name_offset+1] << 0);
name_offset += 2;
name_offset += 4; //jump past hash
- for(int i = 0; i < name_length*2; i+=2)
- ret += QChar(names[name_offset+i+1], names[name_offset+i]);
+
+ ret.resize(name_length);
+ QChar *strData = ret.data();
+ for(int i = 0; i < name_length*2; i+=2) {
+ QChar c(names[name_offset+i+1], names[name_offset+i]);
+ *strData = c;
+ ++strData;
+ }
return ret;
}
+
int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
{
- QString path = QDir::cleanPath(_path);
- // QDir::cleanPath does not remove two trailing slashes under _Windows_
- // due to support for UNC paths. Remove those manually.
- if (path.startsWith(QLatin1String("//")))
- path.remove(0, 1);
-
+ QString path = _path;
{
QString root = mappingRoot();
if(!root.isEmpty()) {
if(root == path) {
- path = QLatin1String("/");
+ path = QLatin1Char('/');
} else {
- if(!root.endsWith(QLatin1String("/")))
- root += QLatin1String("/");
+ if(!root.endsWith(QLatin1Char('/')))
+ root += QLatin1Char('/');
if(path.size() >= root.size() && path.startsWith(root))
path = path.mid(root.length()-1);
if(path.isEmpty())
- path = QLatin1String("/");
+ path = QLatin1Char('/');
}
}
}
@@ -603,12 +648,11 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
//now iterate up the tree
int node = -1;
- QStringList segments = path.split(QLatin1Char('/'), QString::SkipEmptyParts);
-#ifdef DEBUG_RESOURCE_MATCH
- qDebug() << "****" << segments;
-#endif
- for(int i = 0; child_count && i < segments.size(); ++i) {
- const QString &segment = segments[i];
+
+ QStringSplitter splitter(path);
+ while (child_count && splitter.hasNext()) {
+ QStringRef segment = splitter.next();
+
#ifdef DEBUG_RESOURCE_MATCH
qDebug() << " CHILDREN" << segment;
for(int j = 0; j < child_count; ++j) {
@@ -650,7 +694,7 @@ int QResourceRoot::findNode(const QString &_path, const QLocale &locale) const
(tree[offset+1] << 0);
offset += 2;
- if(i == segments.size()-1) {
+ if(!splitter.hasNext()) {
if(!(flags & Directory)) {
const short country = (tree[offset+0] << 8) +
(tree[offset+1] << 0);
diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h
index 1bdbf2c..a0f19a4 100644
--- a/src/corelib/io/qsettings_p.h
+++ b/src/corelib/io/qsettings_p.h
@@ -146,7 +146,7 @@ inline QString QSettingsGroup::toString() const
return result;
}
-class Q_CORE_EXPORT QConfFile
+class Q_AUTOTEST_EXPORT QConfFile
{
public:
ParsedSettingsMap mergedKeyMap() const;
diff --git a/src/corelib/io/qsettings_win.cpp b/src/corelib/io/qsettings_win.cpp
index a08c969..57f65d6 100644
--- a/src/corelib/io/qsettings_win.cpp
+++ b/src/corelib/io/qsettings_win.cpp
@@ -148,7 +148,7 @@ static QString errorCodeToString(DWORD errorCode)
if (data != 0)
LocalFree(data);
})
- if (result.endsWith(QLatin1String("\n")))
+ if (result.endsWith(QLatin1Char('\n')))
result.truncate(result.length() - 1);
return result;
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 45a03e3..2d0d9b8 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -203,7 +203,7 @@ static int _gettemp(char *path, int *doopen, int domkdir, int slen)
if (QDir::isAbsolutePath(QString::fromLatin1(path)))
targetPath = QLatin1String(path);
else
- targetPath = QDir::currentPath().append(QLatin1String("/")) + QLatin1String(path);
+ targetPath = QDir::currentPath().append(QLatin1Char('/')) + QLatin1String(path);
if ((*doopen =
QT_OPEN(targetPath.toLocal8Bit(), O_CREAT|O_EXCL|O_RDWR
diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/io/qtextstream.cpp
index 9382fae..0261c19 100644
--- a/src/corelib/io/qtextstream.cpp
+++ b/src/corelib/io/qtextstream.cpp
@@ -333,7 +333,7 @@ public:
this->stream = stream;
}
-public slots:
+public Q_SLOTS:
inline void flushStream() { stream->flush(); }
private:
@@ -411,6 +411,7 @@ public:
QString writeBuffer;
QString readBuffer;
int readBufferOffset;
+ int readConverterSavedStateOffset; //the offset between readBufferStartDevicePos and that start of the buffer
qint64 readBufferStartDevicePos;
// streaming parameters
@@ -437,6 +438,7 @@ QTextStreamPrivate::QTextStreamPrivate(QTextStream *q_ptr)
#ifndef QT_NO_TEXTCODEC
readConverterSavedState(0),
#endif
+ readConverterSavedStateOffset(0),
locale(QLocale::C)
{
this->q_ptr = q_ptr;
@@ -559,13 +561,8 @@ bool QTextStreamPrivate::fillReadBuffer(qint64 maxBytes)
if (!codec || autoDetectUnicode) {
autoDetectUnicode = false;
- if (bytesRead >= 4 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe && uchar(buf[2]) == 0 && uchar(buf[3]) == 0)
- || (uchar(buf[0]) == 0 && uchar(buf[1]) == 0 && uchar(buf[2]) == 0xfe && uchar(buf[3]) == 0xff))) {
- codec = QTextCodec::codecForName("UTF-32");
- } else if (bytesRead >= 2 && ((uchar(buf[0]) == 0xff && uchar(buf[1]) == 0xfe)
- || (uchar(buf[0]) == 0xfe && uchar(buf[1]) == 0xff))) {
- codec = QTextCodec::codecForName("UTF-16");
- } else if (!codec) {
+ codec = QTextCodec::codecForUtfText(QByteArray::fromRawData(buf, bytesRead), codec);
+ if (!codec) {
codec = QTextCodec::codecForLocale();
writeConverterState.flags |= QTextCodec::IgnoreHeader;
}
@@ -835,6 +832,10 @@ inline void QTextStreamPrivate::consume(int size)
readBufferOffset = 0;
readBuffer.clear();
saveConverterState(device->pos());
+ } else if (readBufferOffset > QTEXTSTREAM_BUFFERSIZE) {
+ readBuffer = readBuffer.remove(0,readBufferOffset);
+ readConverterSavedStateOffset += readBufferOffset;
+ readBufferOffset = 0;
}
}
}
@@ -856,6 +857,7 @@ inline void QTextStreamPrivate::saveConverterState(qint64 newPos)
#endif
readBufferStartDevicePos = newPos;
+ readConverterSavedStateOffset = 0;
}
/*! \internal
@@ -1217,7 +1219,7 @@ qint64 QTextStream::pos() const
// Rewind the device to get to the current position Ensure that
// readBufferOffset is unaffected by fillReadBuffer()
- int oldReadBufferOffset = d->readBufferOffset;
+ int oldReadBufferOffset = d->readBufferOffset + d->readConverterSavedStateOffset;
while (d->readBuffer.size() < oldReadBufferOffset) {
if (!thatd->fillReadBuffer(1))
return qint64(-1);
@@ -2287,7 +2289,7 @@ bool QTextStreamPrivate::putNumber(qulonglong number, bool negative)
// ShowBase flag set zero should be written as '00'
if (number == 0 && base == 8 && numberFlags & QTextStream::ShowBase
&& result == QLatin1String("0")) {
- result.prepend(QLatin1String("0"));
+ result.prepend(QLatin1Char('0'));
}
}
return putString(result, true);
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index d1a5cdd..5846e23 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -5330,7 +5330,7 @@ QString QUrl::toString(FormattingOptions options) const
url += QLatin1Char('/');
url += ourPath;
// check if we need to remove trailing slashes
- while ((options & StripTrailingSlash) && url.right(1) == QLatin1String("/"))
+ while ((options & StripTrailingSlash) && url.endsWith(QLatin1Char('/')))
url.chop(1);
}
@@ -5698,7 +5698,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
// magic for drives on windows
if (deslashified.length() > 1 && deslashified.at(1) == QLatin1Char(':') && deslashified.at(0) != QLatin1Char('/')) {
- url.setPath(QLatin1String("/") + deslashified);
+ url.setPath(QLatin1Char('/') + deslashified);
// magic for shared drive on windows
} else if (deslashified.startsWith(QLatin1String("//"))) {
int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
@@ -5728,7 +5728,7 @@ QString QUrl::toLocalFile() const
// magic for shared drive on windows
if (!d->host.isEmpty()) {
tmp = QLatin1String("//") + d->host + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/')
- ? QLatin1String("/") + ourPath : ourPath);
+ ? QLatin1Char('/') + ourPath : ourPath);
} else {
tmp = ourPath;
// magic for drives on windows
@@ -5976,7 +5976,7 @@ QDataStream &operator>>(QDataStream &in, QUrl &url)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QUrl &url)
{
- d.maybeSpace() << "QUrl(" << url.toString() << ")";
+ d.maybeSpace() << "QUrl(" << url.toString() << ')';
return d.space();
}
#endif
diff --git a/src/corelib/io/qurl.h b/src/corelib/io/qurl.h
index 9242092..e9c4a8d 100644
--- a/src/corelib/io/qurl.h
+++ b/src/corelib/io/qurl.h
@@ -223,7 +223,7 @@ public:
inline QT3_SUPPORT QString ref() const { return fragment(); }
inline QT3_SUPPORT void setRef(const QString &txt) { setFragment(txt); }
inline QT3_SUPPORT bool hasRef() const { return !fragment().isEmpty(); }
- inline QT3_SUPPORT void addPath(const QString &p) { setPath(path() + QLatin1String("/") + p); }
+ inline QT3_SUPPORT void addPath(const QString &p) { setPath(path() + QLatin1Char('/') + p); }
QT3_SUPPORT void setFileName(const QString &txt);
QT3_SUPPORT QString fileName() const;
QT3_SUPPORT QString dirPath() const;
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index 9458946..f7d4208 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -12,7 +12,7 @@ HEADERS += \
kernel/qcoreevent.h \
kernel/qmetaobject.h \
kernel/qmetatype.h \
- kernel/qmimedata.h \
+ kernel/qmimedata.h \
kernel/qobject.h \
kernel/qobjectdefs.h \
kernel/qsignalmapper.h \
@@ -27,8 +27,8 @@ HEADERS += \
kernel/qvariant_p.h \
kernel/qmetaobject_p.h \
kernel/qobject_p.h \
- kernel/qcoreglobaldata_p.h \
- kernel/qsharedmemory.h \
+ kernel/qcoreglobaldata_p.h \
+ kernel/qsharedmemory.h \
kernel/qsharedmemory_p.h \
kernel/qsystemsemaphore.h \
kernel/qsystemsemaphore_p.h \
@@ -43,7 +43,7 @@ SOURCES += \
kernel/qcoreevent.cpp \
kernel/qmetaobject.cpp \
kernel/qmetatype.cpp \
- kernel/qmimedata.cpp \
+ kernel/qmimedata.cpp \
kernel/qobject.cpp \
kernel/qobjectcleanuphandler.cpp \
kernel/qsignalmapper.cpp \
@@ -53,7 +53,8 @@ SOURCES += \
kernel/qvariant.cpp \
kernel/qcoreglobaldata.cpp \
kernel/qsharedmemory.cpp \
- kernel/qsystemsemaphore.cpp
+ kernel/qsystemsemaphore.cpp \
+ kernel/qpointer.cpp
win32 {
SOURCES += \
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index fd0e105..6d6caf5 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -428,8 +428,8 @@ bool QPersistentModelIndex::isValid() const
QDebug operator<<(QDebug dbg, const QModelIndex &idx)
{
#ifndef Q_BROKEN_DEBUG_STREAM
- dbg.nospace() << "QModelIndex(" << idx.row() << "," << idx.column()
- << "," << idx.internalPointer() << "," << idx.model() << ")";
+ dbg.nospace() << "QModelIndex(" << idx.row() << ',' << idx.column()
+ << ',' << idx.internalPointer() << ',' << idx.model() << ')';
return dbg.space();
#else
qWarning("This compiler doesn't support streaming QModelIndex to QDebug");
@@ -467,6 +467,37 @@ QAbstractItemModel *QAbstractItemModelPrivate::staticEmptyModel()
return qEmptyModel();
}
+/*!
+ \internal
+ return true if \a value contains a numerical type
+
+ This function is used by our Q{Tree,Widget,Table}WidgetModel classes to sort.
+ We cannot rely on QVariant::canConvert because this would take strings as double
+ and then not sort strings correctly
+*/
+bool QAbstractItemModelPrivate::canConvertToDouble(const QVariant &value)
+{
+ switch (value.userType()) {
+ case QVariant::Bool:
+ case QVariant::Int:
+ case QVariant::UInt:
+ case QVariant::LongLong:
+ case QVariant::ULongLong:
+ case QVariant::Double:
+ case QVariant::Char:
+ case QMetaType::Float:
+ case QMetaType::Short:
+ case QMetaType::UShort:
+ case QMetaType::UChar:
+ case QMetaType::ULong:
+ case QMetaType::Long:
+ return true;
+ default:
+ return false;
+ }
+ return false;
+}
+
void QAbstractItemModelPrivate::removePersistentIndexData(QPersistentModelIndexData *data)
{
if (data->index.isValid()) {
@@ -525,7 +556,7 @@ void QAbstractItemModelPrivate::rowsInserted(const QModelIndex &parent,
if (data->index.isValid()) {
persistent.insertMultiAtEnd(data->index, data);
} else {
- qWarning() << "QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count << "," << old.column() << ") in model" << q_func();
+ qWarning() << "QAbstractItemModel::endInsertRows: Invalid index (" << old.row() + count << ',' << old.column() << ") in model" << q_func();
}
}
}
@@ -574,7 +605,7 @@ void QAbstractItemModelPrivate::rowsRemoved(const QModelIndex &parent,
if (data->index.isValid()) {
persistent.insertMultiAtEnd(data->index, data);
} else {
- qWarning() << "QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count << "," << old.column() << ") in model" << q_func();
+ qWarning() << "QAbstractItemModel::endRemoveRows: Invalid index (" << old.row() - count << ',' << old.column() << ") in model" << q_func();
}
}
QVector<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
@@ -619,7 +650,7 @@ void QAbstractItemModelPrivate::columnsInserted(const QModelIndex &parent,
if (data->index.isValid()) {
persistent.insertMultiAtEnd(data->index, data);
} else {
- qWarning() << "QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() << "," << old.column() + count << ") in model" << q_func();
+ qWarning() << "QAbstractItemModel::endInsertColumns: Invalid index (" << old.row() << ',' << old.column() + count << ") in model" << q_func();
}
}
}
@@ -669,7 +700,7 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
if (data->index.isValid()) {
persistent.insertMultiAtEnd(data->index, data);
} else {
- qWarning() << "QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() << "," << old.column() - count << ") in model" << q_func();
+ qWarning() << "QAbstractItemModel::endRemoveColumns: Invalid index (" << old.row() << ',' << old.column() - count << ") in model" << q_func();
}
}
QVector<QPersistentModelIndexData *> persistent_invalidated = persistent.invalidated.pop();
diff --git a/src/corelib/kernel/qabstractitemmodel_p.h b/src/corelib/kernel/qabstractitemmodel_p.h
index df1a6ce..70c35cb 100644
--- a/src/corelib/kernel/qabstractitemmodel_p.h
+++ b/src/corelib/kernel/qabstractitemmodel_p.h
@@ -61,7 +61,7 @@
QT_BEGIN_NAMESPACE
-class Q_CORE_EXPORT QPersistentModelIndexData
+class QPersistentModelIndexData
{
public:
QPersistentModelIndexData() : model(0) {}
@@ -89,6 +89,7 @@ public:
void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last);
void columnsRemoved(const QModelIndex &parent, int first, int last);
static QAbstractItemModel *staticEmptyModel();
+ static bool canConvertToDouble(const QVariant &value);
inline QModelIndex createIndex(int row, int column, void *data = 0) const {
return q_func()->createIndex(row, column, data);
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 5c3fd76..4fbd63c 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -420,12 +420,12 @@ QString qAppName()
QLibrary) can be retrieved with libraryPaths() and manipulated by
setLibraryPaths(), addLibraryPath(), and removeLibraryPath().
- On Unix/Linux Qt is configured to use the system local settings by
- default. This can cause a conflict when using POSIX functions, for
- instance, when converting between data types such as floats and
- strings, since the notation may differ between locales. To get
- around this problem call the POSIX function setlocale(LC_NUMERIC,"C")
- right after initializing QApplication or QCoreApplication to reset
+ On Unix/Linux Qt is configured to use the system local settings by
+ default. This can cause a conflict when using POSIX functions, for
+ instance, when converting between data types such as floats and
+ strings, since the notation may differ between locales. To get
+ around this problem call the POSIX function setlocale(LC_NUMERIC,"C")
+ right after initializing QApplication or QCoreApplication to reset
the locale that is used for number formatting to "C"-locale.
\sa QApplication, QAbstractEventDispatcher, QEventLoop,
@@ -613,6 +613,20 @@ void QCoreApplication::setAttribute(Qt::ApplicationAttribute attribute, bool on)
QCoreApplicationPrivate::attribs |= 1 << attribute;
else
QCoreApplicationPrivate::attribs &= ~(1 << attribute);
+#ifdef Q_OS_MAC
+ // Turn on the no native menubar here, since we used to
+ // do this implicitly. We DO NOT flip it off if someone sets
+ // it to false.
+ // Ideally, we'd have magic that would be something along the lines of
+ // "follow MacPluginApplication" unless explicitly set.
+ // Considering this attribute isn't only at the beginning
+ // it's unlikely it will ever be a problem, but I want
+ // to have the behavior documented here.
+ if (attribute == Qt::AA_MacPluginApplication && on
+ && !testAttribute(Qt::AA_DontUseNativeMenuBar)) {
+ setAttribute(Qt::AA_DontUseNativeMenuBar, true);
+ }
+#endif
}
/*!
@@ -1880,7 +1894,7 @@ QString QCoreApplication::applicationFilePath()
*/
QByteArray pEnv = qgetenv("PATH");
QDir currentDir = QDir::current();
- QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1String(":"));
+ QStringList paths = QString::fromLocal8Bit(pEnv.constData()).split(QLatin1Char(':'));
for (QStringList::const_iterator p = paths.constBegin(); p != paths.constEnd(); ++p) {
if ((*p).isEmpty())
continue;
@@ -1990,7 +2004,7 @@ QStringList QCoreApplication::arguments()
wchar_t tempFilename[MAX_PATH+1];
if (GetModuleFileNameW(0, tempFilename, MAX_PATH)) {
tempFilename[MAX_PATH] = 0;
- cmdline.prepend(QString(QLatin1String("\"")) + QString::fromUtf16((unsigned short *)tempFilename) + QString(QLatin1String("\" ")));
+ cmdline.prepend(QLatin1Char('\"') + QString::fromUtf16((unsigned short *)tempFilename) + QLatin1String("\" "));
}
#endif // Q_OS_WINCE
@@ -2004,8 +2018,7 @@ QStringList QCoreApplication::arguments()
l1arg == "-qdebug" ||
l1arg == "-reverse" ||
l1arg == "-stylesheet" ||
- l1arg == "-widgetcount" ||
- l1arg == "-direct3d")
+ l1arg == "-widgetcount")
;
else if (l1arg.startsWith("-style="))
;
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 225821f..9c1c235 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -51,12 +51,11 @@
QT_BEGIN_NAMESPACE
-// ############### DON'T EXPORT HERE!!!
-Q_CORE_EXPORT char appFileName[MAX_PATH+1]; // application file name
-Q_CORE_EXPORT char theAppName[MAX_PATH+1]; // application name
-Q_CORE_EXPORT HINSTANCE appInst = 0; // handle to app instance
-Q_CORE_EXPORT HINSTANCE appPrevInst = 0; // handle to prev app instance
-Q_CORE_EXPORT int appCmdShow = 0;
+char appFileName[MAX_PATH+1]; // application file name
+char theAppName[MAX_PATH+1]; // application name
+HINSTANCE appInst = 0; // handle to app instance
+HINSTANCE appPrevInst = 0; // handle to prev app instance
+int appCmdShow = 0;
bool usingWinMain = false; // whether the qWinMain() is used or not
Q_CORE_EXPORT HINSTANCE qWinAppInst() // get Windows app handle
@@ -69,6 +68,12 @@ Q_CORE_EXPORT HINSTANCE qWinAppPrevInst() // get Windows prev app
return appPrevInst;
}
+Q_CORE_EXPORT int qWinAppCmdShow() // get main window show command
+{
+ return appCmdShow;
+}
+
+
void set_winapp_name()
{
static bool already_set = false;
@@ -89,6 +94,14 @@ void set_winapp_name()
int l = qstrlen(theAppName);
if ((l > 4) && !qstricmp(theAppName + l - 4, ".exe"))
theAppName[l-4] = '\0'; // drop .exe extension
+
+ if (appInst == 0) {
+ QT_WA({
+ appInst = GetModuleHandle(0);
+ }, {
+ appInst = GetModuleHandleA(0);
+ });
+ }
}
}
@@ -134,11 +147,11 @@ Q_CORE_EXPORT void qWinMsgHandler(QtMsgType t, const char* str)
staticCriticalSection.lock();
QT_WA({
QString s(QString::fromLocal8Bit(str));
- s += QLatin1String("\n");
+ s += QLatin1Char('\n');
OutputDebugStringW((TCHAR*)s.utf16());
}, {
QByteArray s(str);
- s += "\n";
+ s += '\n';
OutputDebugStringA(s.data());
})
staticCriticalSection.unlock();
@@ -173,14 +186,14 @@ void qWinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR cmdParam,
// Create command line
- set_winapp_name();
-
argv = qWinCmdLine<char>(cmdParam, int(strlen(cmdParam)), argc);
// Get Windows parameters
appInst = instance;
appPrevInst = prevInstance;
appCmdShow = cmdShow;
+
+ set_winapp_name();
}
/*!
@@ -396,6 +409,7 @@ struct {
{ 0x020B, "WM_XBUTTONDOWN" },
{ 0x020C, "WM_XBUTTONUP" },
{ 0x020D, "WM_XBUTTONDBLCLK" },
+ { 0x020E, "WM_MOUSEHWHEEL" },
{ 0x0210, "WM_PARENTNOTIFY" },
{ 0x0211, "WM_ENTERMENULOOP" },
{ 0x0212, "WM_EXITMENULOOP" },
@@ -618,7 +632,7 @@ QString valueCheck(uint actual, ...)
#ifdef Q_CC_BOR
-Q_CORE_EXPORT QString decodeMSG(const MSG& msg)
+QString decodeMSG(const MSG& msg)
{
return QString::fromLatin1("THis is not supported on Borland");
}
@@ -827,7 +841,7 @@ QString decodeMSG(const MSG& msg)
FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 2),
FLGSTR(ISC_SHOWUICANDIDATEWINDOW << 3),
FLAG_STRING());
- parameters.sprintf("Input context(%s) Show flags(%s)", (fSet?"Active":"Inactive"), showFlgs.toLatin1().data());
+ parameters.sprintf("Input context(%s) Show flags(%s)", (fSet? "Active" : "Inactive"), showFlgs.toLatin1().data());
}
break;
#endif
@@ -885,6 +899,9 @@ QString decodeMSG(const MSG& msg)
#ifdef WM_MOUSEWHEEL
case WM_MOUSEWHEEL:
#endif
+#ifdef WM_MOUSEHWHEEL
+ case WM_MOUSEHWHEEL:
+#endif
#ifdef WM_LBUTTONDBLCLK
case WM_LBUTTONDBLCLK:
#endif
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index e0be174..6d26db6 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -266,6 +266,8 @@ QT_BEGIN_NAMESPACE
\omitvalue NetworkReplyUpdated
\omitvalue FutureCallOut
\omitvalue CocoaRequestModal
+ \omitvalue Wrapped
+ \omitvalue Signal
*/
/*!
diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h
index d229ac9..1dd2ee4 100644
--- a/src/corelib/kernel/qcoreevent.h
+++ b/src/corelib/kernel/qcoreevent.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qbytearray.h>
+#include <QtCore/qobjectdefs.h>
QT_BEGIN_HEADER
@@ -54,7 +55,9 @@ QT_MODULE(Core)
class QEventPrivate;
class Q_CORE_EXPORT QEvent // event base class
{
+ Q_GADGET
QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted)
+ Q_ENUMS(Type)
public:
enum Type {
/*
@@ -266,10 +269,12 @@ public:
CocoaRequestModal = 190, // Internal for requesting an application modal Cocoa Window
MacGLClearDrawable = 191, // Internal Cocoa, the window has changed, so we must clear
- RequestSoftwareInputPanel = 192,
- CloseSoftwareInputPanel = 193,
+ Signal = 192,
+ Wrapped = 193,
+ RequestSoftwareInputPanel = 194,
+ CloseSoftwareInputPanel = 195,
- // 512 reserved for Qt Jambi's MetaCall event
+ // 512 reserved for Qt Jambi's MetaCall event
// 513 reserved for Qt Jambi's DeleteOnMainThread event
User = 1000, // first user event id
diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp
index ea8299c..fe0db73 100644
--- a/src/corelib/kernel/qeventdispatcher_unix.cpp
+++ b/src/corelib/kernel/qeventdispatcher_unix.cpp
@@ -263,7 +263,7 @@ QTimerInfoList::QTimerInfoList()
# if (_POSIX_MONOTONIC_CLOCK == 0)
// detect if the system support monotonic timers
long x = sysconf(_SC_MONOTONIC_CLOCK);
- useMonotonicTimers = x >= 200112L;
+ useMonotonicTimers = x != -1;
# endif
getTime(currentTime);
diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h
index 816add5..ac2de50 100644
--- a/src/corelib/kernel/qeventdispatcher_unix_p.h
+++ b/src/corelib/kernel/qeventdispatcher_unix_p.h
@@ -154,14 +154,14 @@ public:
int activateTimers();
};
-struct Q_CORE_EXPORT QSockNot
+struct QSockNot
{
QSocketNotifier *obj;
int fd;
fd_set *queue;
};
-class Q_CORE_EXPORT QSockNotType
+class QSockNotType
{
public:
QSockNotType();
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index c4061f4..7d3a13a 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -396,13 +396,6 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
{ return PostMessageA(hWnd, msg, wParam, lParam); });
}
-Q_CORE_EXPORT bool winGetMessage(MSG* msg, HWND hWnd, UINT wMsgFilterMin,
- UINT wMsgFilterMax)
-{
- QT_WA({ return GetMessage(msg, hWnd, wMsgFilterMin, wMsgFilterMax); } ,
- { return GetMessageA(msg, hWnd, wMsgFilterMin, wMsgFilterMax); });
-}
-
// This function is called by a workerthread
void WINAPI CALLBACK qt_fast_timer_proc(uint timerId, uint /*reserved*/, DWORD_PTR user, DWORD_PTR /*reserved*/, DWORD_PTR /*reserved*/)
{
@@ -703,7 +696,8 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
&& msg.message <= WM_KEYLAST)
|| (msg.message >= WM_MOUSEFIRST
&& msg.message <= WM_MOUSELAST)
- || msg.message == WM_MOUSEWHEEL)) {
+ || msg.message == WM_MOUSEWHEEL
+ || msg.message == WM_MOUSEHWHEEL)) {
// queue user input events for later processing
haveMessage = false;
d->queuedUserInputEvents.append(msg);
diff --git a/src/corelib/kernel/qfunctions_wince.cpp b/src/corelib/kernel/qfunctions_wince.cpp
index 1c929c7..e0f7687 100644
--- a/src/corelib/kernel/qfunctions_wince.cpp
+++ b/src/corelib/kernel/qfunctions_wince.cpp
@@ -285,11 +285,6 @@ int qt_wince_SetErrorMode(int newValue)
return result;
}
-HRESULT qt_wince_CoInitialize(void* reserved)
-{
- return CoInitializeEx(reserved, 0);
-}
-
bool qt_wince__chmod(const char *file, int mode)
{
return _wchmod( reinterpret_cast<const wchar_t *> (QString::fromLatin1(file).utf16()), mode);
diff --git a/src/corelib/kernel/qfunctions_wince.h b/src/corelib/kernel/qfunctions_wince.h
index 123bd23..5f08bb3 100644
--- a/src/corelib/kernel/qfunctions_wince.h
+++ b/src/corelib/kernel/qfunctions_wince.h
@@ -199,7 +199,9 @@ int qt_wince__fstat( int handle, struct stat *buffer);
#define SEM_FAILCRITICALERRORS 0x0001
#define SEM_NOOPENFILEERRORBOX 0x0002
int qt_wince_SetErrorMode(int);
-HRESULT qt_wince_CoInitialize(void* reserved);
+#ifndef CoInitialize
+#define CoInitialize(x) CoInitializeEx(x, COINIT_MULTITHREADED)
+#endif
bool qt_wince__chmod(const char *file, int mode);
bool qt_wince__wchmod(const WCHAR *file, int mode);
@@ -376,7 +378,6 @@ typedef DWORD OLE_COLOR;
#define _rename(a,b) qt_wince__rename(a,b)
#define _remove(a) qt_wince__remove(a)
#define SetErrorMode(a) qt_wince_SetErrorMode(a)
-#define CoInitialize(a) qt_wince_CoInitialize(a)
#define _chmod(a,b) qt_wince__chmod(a,b)
#define _wchmod(a,b) qt_wince__wchmod(a,b)
#define CreateFileA(a,b,c,d,e,f,g) qt_wince_CreateFileA(a,b,c,d,e,f,g)
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index b65f956..6f3316c 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -2003,6 +2003,11 @@ QVariant::Type QMetaProperty::type() const
if (enumMetaTypeId == 0)
return QVariant::Int;
}
+#ifdef QT_COORD_TYPE
+ // qreal metatype must be resolved at runtime.
+ if (strcmp(typeName(), "qreal") == 0)
+ return QVariant::Type(qMetaTypeId<qreal>());
+#endif
return QVariant::UserType;
}
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index ce10bae..6b40f46 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -179,6 +179,7 @@ QT_BEGIN_NAMESPACE
\omitvalue LastCoreExtType
\omitvalue LastCoreType
\omitvalue LastGuiType
+ \omitvalue QReal
Additional types can be registered using Q_DECLARE_METATYPE().
@@ -359,7 +360,7 @@ void QMetaType::registerStreamOperators(const char *typeName, SaveOperator saveO
inf.saveOp = saveOp;
inf.loadOp = loadOp;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
Returns the type name associated with the given \a type, or 0 if no
@@ -884,7 +885,7 @@ bool QMetaType::load(QDataStream &stream, int type, void *data)
}
return true;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
Returns a copy of \a copy, assuming it is of type \a type. If \a
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index 648f933..687a070 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -86,6 +86,15 @@ public:
UShort = 133, UChar = 134, Float = 135, QObjectStar = 136, QWidgetStar = 137,
LastCoreExtType = 137 /* QWidgetStar */,
+// This logic must match the one in qglobal.h
+#if defined(QT_COORD_TYPE)
+ QReal = 0,
+#elif defined(QT_NO_FPU) || defined(QT_ARCH_ARM) || defined(QT_ARCH_WINDOWSCE) || defined(QT_ARCH_SYMBIAN)
+ QReal = Float,
+#else
+ QReal = Double,
+#endif
+
User = 256
};
@@ -174,7 +183,7 @@ void qRegisterMetaTypeStreamOperators(const char *typeName
QMetaType::registerStreamOperators(typeName, reinterpret_cast<QMetaType::SaveOperator>(sptr),
reinterpret_cast<QMetaType::LoadOperator>(lptr));
}
-#endif
+#endif // QT_NO_DATASTREAM
template <typename T>
struct QMetaTypeId
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index ac505e1..eeb3550 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -58,6 +58,7 @@
#include <qsemaphore.h>
#include <private/qorderedmutexlocker_p.h>
+#include <private/qmutexpool_p.h>
#include <new>
@@ -70,7 +71,7 @@ static int DIRECT_CONNECTION_ONLY = 0;
static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
{
- int *types = static_cast<int *>(qMalloc((typeNames.count() + 1) * sizeof(int)));
+ int *types = new int [typeNames.count() + 1];
for (int i = 0; i < typeNames.count(); ++i) {
const QByteArray typeName = typeNames.at(i);
if (typeName.endsWith('*'))
@@ -82,7 +83,7 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
qWarning("QObject::connect: Cannot queue arguments of type '%s'\n"
"(Make sure '%s' is registered using qRegisterMetaType().)",
typeName.constData(), typeName.constData());
- qFree(types);
+ delete [] types;
return 0;
}
}
@@ -91,16 +92,38 @@ static int *queuedConnectionTypes(const QList<QByteArray> &typeNames)
return types;
}
+static QBasicAtomicPointer<QMutexPool> signalSlotMutexes = Q_BASIC_ATOMIC_INITIALIZER(0);
+static QBasicAtomicInt objectCount = Q_BASIC_ATOMIC_INITIALIZER(0);
+
+/** \internal
+ * mutex to be locked when accessing the connectionlists or the senders list
+ */
+static QMutex *signalSlotLock(const QObject *o)
+{
+ if (!signalSlotMutexes) {
+ QMutexPool *mp = new QMutexPool;
+ if (!signalSlotMutexes.testAndSetOrdered(0, mp)) {
+ delete mp;
+ }
+ }
+ return signalSlotMutexes->get(o);
+}
+
extern "C" Q_CORE_EXPORT void qt_addObject(QObject *)
{
+ objectCount.ref();
}
extern "C" Q_CORE_EXPORT void qt_removeObject(QObject *)
{
+ if(!objectCount.deref()) {
+ QMutexPool *old = signalSlotMutexes.fetchAndStoreAcquire(0);
+ delete old;
+ }
}
QObjectPrivate::QObjectPrivate(int version)
- : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0)
+ : threadData(0), currentSender(0), currentChildBeingDeleted(0), connectionLists(0), senders(0)
{
if (version != QObjectPrivateVersion)
qFatal("Cannot mix incompatible Qt libraries");
@@ -120,6 +143,7 @@ QObjectPrivate::QObjectPrivate(int version)
inEventHandler = false;
inThreadChangeEvent = false;
deleteWatch = 0;
+ hasGuards = false;
}
QObjectPrivate::~QObjectPrivate()
@@ -216,19 +240,20 @@ public:
}
};
+// Used by QAccessibleWidget
bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
{
Q_Q(const QObject);
int signal_index = q->metaObject()->indexOfSignal(signal);
if (signal_index < 0)
return false;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q));
if (connectionLists) {
if (signal_index < connectionLists->count()) {
const ConnectionList &connectionList = connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (c.receiver && c.receiver == receiver)
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (c->receiver == receiver)
return true;
}
}
@@ -236,6 +261,7 @@ bool QObjectPrivate::isSender(const QObject *receiver, const char *signal) const
return false;
}
+// Used by QAccessibleWidget
QObjectList QObjectPrivate::receiverList(const char *signal) const
{
Q_Q(const QObject);
@@ -243,26 +269,27 @@ QObjectList QObjectPrivate::receiverList(const char *signal) const
int signal_index = q->metaObject()->indexOfSignal(signal);
if (signal_index < 0)
return returnValue;
- QMutexLocker locker(&threadData->mutex);
+ QMutexLocker locker(signalSlotLock(q));
if (connectionLists) {
if (signal_index < connectionLists->count()) {
const ConnectionList &connectionList = connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (c.receiver)
- returnValue << c.receiver;
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (c->receiver)
+ returnValue << c->receiver;
}
}
}
return returnValue;
}
+// Used by QAccessibleWidget
QObjectList QObjectPrivate::senderList() const
{
QObjectList returnValue;
- QMutexLocker locker(&threadData->mutex);
- for (int i = 0; i < senders.count(); ++i)
- returnValue << senders.at(i).sender;
+ QMutexLocker locker(signalSlotLock(q_func()));
+ for (Connection *c = senders; c; c = c->next)
+ returnValue << c->sender;
return returnValue;
}
@@ -274,33 +301,10 @@ void QObjectPrivate::addConnection(int signal, Connection *c)
connectionLists->resize(signal + 1);
ConnectionList &connectionList = (*connectionLists)[signal];
- connectionList.append(*c);
-
+ connectionList.append(c);
cleanConnectionLists();
}
-void QObjectPrivate::removeReceiver(int signal, QObject *receiver)
-{
- if (!connectionLists)
- return;
-
- if (signal >= connectionLists->count())
- return;
-
- ConnectionList &connectionList = (*connectionLists)[signal];
- for (int i = 0; i < connectionList.count(); ++i) {
- Connection &c = connectionList[i];
- if (c.receiver == receiver) {
- c.receiver = 0;
- if (c.argumentTypes && c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c.argumentTypes);
- c.argumentTypes = 0;
- }
- connectionLists->dirty = true;
- }
- }
-}
-
void QObjectPrivate::cleanConnectionLists()
{
if (connectionLists->dirty && !connectionLists->inUse) {
@@ -308,43 +312,17 @@ void QObjectPrivate::cleanConnectionLists()
for (int signal = -1; signal < connectionLists->count(); ++signal) {
QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal];
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (!c.receiver)
+ QObjectPrivate::Connection *c = connectionList.at(i);
+ if (!c->receiver) {
+ delete c;
connectionList.removeAt(i--);
+ }
}
}
connectionLists->dirty = false;
}
}
-void QObjectPrivate::refSender(QObject *sender, int signal)
-{
- for (int i = 0; i < senders.count(); ++i) {
- Sender &s = senders[i];
- if (s.sender == sender && s.signal == signal) {
- ++s.ref;
- return;
- }
- }
-
- Sender s = { sender, signal, 1 };
- senders.append(s);
-}
-
-void QObjectPrivate::derefSender(QObject *sender, int signal)
-{
- for (int i = 0; i < senders.count(); ++i) {
- Sender &s = senders[i];
- if (s.sender == sender && s.signal == signal) {
- if (--s.ref == 0) {
- senders.removeAt(i);
- break;
- }
- }
- }
- // Q_ASSERT_X(false, "QObjectPrivate::derefSender", "sender not found");
-}
-
QObjectPrivate::Sender *QObjectPrivate::setCurrentSender(QObject *receiver,
Sender *sender)
{
@@ -382,6 +360,7 @@ void QMetaObject::addGuard(QObject **ptr)
return;
}
QMutexLocker locker(guardHashLock());
+ QObjectPrivate::get(*ptr)->hasGuards = true;
hash->insert(*ptr, ptr);
}
@@ -399,12 +378,17 @@ void QMetaObject::removeGuard(QObject **ptr)
QMutexLocker locker(guardHashLock());
GuardHash::iterator it = hash->find(*ptr);
const GuardHash::iterator end = hash->end();
+ bool more = false; //if the QObject has more pointer attached to it.
for (; it.key() == *ptr && it != end; ++it) {
if (it.value() == ptr) {
- (void) hash->erase(it);
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
break;
}
+ more = true;
}
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
}
/*!\internal
@@ -418,24 +402,33 @@ void QMetaObject::changeGuard(QObject **ptr, QObject *o)
}
QMutexLocker locker(guardHashLock());
if (*ptr) {
+ bool more = false; //if the QObject has more pointer attached to it.
GuardHash::iterator it = hash->find(*ptr);
const GuardHash::iterator end = hash->end();
for (; it.key() == *ptr && it != end; ++it) {
if (it.value() == ptr) {
- (void) hash->erase(it);
+ it = hash->erase(it);
+ if (!more) more = (it != end && it.key() == *ptr);
break;
}
+ more = true;
}
+ if (!more)
+ QObjectPrivate::get(*ptr)->hasGuards = false;
}
*ptr = o;
- if (*ptr)
+ if (*ptr) {
hash->insert(*ptr, ptr);
+ QObjectPrivate::get(*ptr)->hasGuards = true;
+ }
}
/*! \internal
*/
void QObjectPrivate::clearGuards(QObject *object)
{
+ if (!QObjectPrivate::get(object)->hasGuards)
+ return;
GuardHash *hash = 0;
QMutex *mutex = 0;
QT_TRY {
@@ -776,7 +769,7 @@ QObject::~QObject()
}
{
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
// set ref to zero to indicate that this object has been deleted
if (d->currentSender != 0)
@@ -789,23 +782,23 @@ QObject::~QObject()
for (int signal = -1; signal < d->connectionLists->count(); ++signal) {
QObjectPrivate::ConnectionList &connectionList = (*d->connectionLists)[signal];
for (int i = 0; i < connectionList.count(); ++i) {
- QObjectPrivate::Connection *c = &connectionList[i];
- if (!c->receiver)
+ QObjectPrivate::Connection *c = connectionList[i];
+ if (!c->receiver) {
+ delete c;
continue;
+ }
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- c = &connectionList[i];
- if (c->receiver)
- c->receiver->d_func()->derefSender(this, signal);
+ c = connectionList[i];
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
+ }
if (needToUnlock)
m->unlock();
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
- }
- c->receiver = 0;
+ delete c;
}
}
@@ -818,25 +811,25 @@ QObject::~QObject()
}
// disconnect all senders
- for (int i = 0; i < d->senders.count(); ) {
- QObjectPrivate::Sender *s = &d->senders[i];
-
- QMutex *m = &s->sender->d_func()->threadData->mutex;
+ QObjectPrivate::Connection *node = d->senders;
+ while (node) {
+ QMutex *m = signalSlotLock(node->sender);
+ node->prev = &node;
bool needToUnlock = QOrderedMutexLocker::relock(locker.mutex(), m);
- if (m < locker.mutex()) {
- if (i >= d->senders.count() || s != &d->senders[i]) {
- if (needToUnlock)
- m->unlock();
- continue;
- }
+ //the node has maybe been removed while the mutex was unlocked in relock?
+ if (!node || signalSlotLock(node->sender) != m) {
+ m->unlock();
+ continue;
}
- s->sender->d_func()->removeReceiver(s->signal, this);
+ node->receiver = 0;
+ QObjectConnectionListVector *senderLists = node->sender->d_func()->connectionLists;
+ if (senderLists)
+ senderLists->dirty = true;
+
if (needToUnlock)
m->unlock();
- ++i;
+ node = node->next;
}
-
- d->senders.clear();
}
if (d->pendTimer) {
@@ -874,6 +867,12 @@ QObject::~QObject()
#endif
}
+QObjectPrivate::Connection::~Connection()
+{
+ if (argumentTypes != &DIRECT_CONNECTION_ONLY)
+ delete [] argumentTypes;
+}
+
/*!
\fn QMetaObject *QObject::metaObject() const
@@ -2261,11 +2260,11 @@ static void err_method_notfound(const QObject *object,
if (strchr(method,')') == 0) // common typing mistake
qWarning("Object::%s: Parentheses expected, %s %s::%s%s%s",
func, type, object->metaObject()->className(), method+1,
- loc ? " in ":"\0", loc ? loc : "\0");
+ loc ? " in ": "", loc ? loc : "");
else
qWarning("Object::%s: No such %s %s::%s%s%s",
func, type, object->metaObject()->className(), method+1,
- loc ? " in ":"\0", loc ? loc : "\0");
+ loc ? " in ": "", loc ? loc : "");
}
@@ -2308,14 +2307,14 @@ QObject *QObject::sender() const
{
Q_D(const QObject);
- QMutexLocker(&d->threadData->mutex);
+ QMutexLocker(signalSlotLock(this));
if (!d->currentSender)
return 0;
// Return 0 if d->currentSender isn't in d->senders
bool found = false;
- for (int i = 0; !found && i < d->senders.count(); ++i)
- found = (d->senders.at(i).sender == d->currentSender->sender);
+ for (QObjectPrivate::Connection *c = d->senders; c && !found; c = c->next)
+ found = (c->sender == d->currentSender->sender);
if (!found)
return 0;
return d->currentSender->sender;
@@ -2364,14 +2363,14 @@ int QObject::receivers(const char *signal) const
}
Q_D(const QObject);
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
if (d->connectionLists) {
if (signal_index < d->connectionLists->count()) {
const QObjectPrivate::ConnectionList &connectionList =
d->connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- receivers += c.receiver ? 1 : 0;
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ receivers += c->receiver ? 1 : 0;
}
}
}
@@ -2410,7 +2409,8 @@ int QObject::receivers(const char *signal) const
can be connected to one slot.
If a signal is connected to several slots, the slots are activated
- in an arbitrary order when the signal is emitted.
+ in the same order as the order the connection was made, when the
+ signal is emitted.
The function returns true if it successfully connects the signal
to the slot. It will return false if it cannot create the
@@ -2418,9 +2418,13 @@ int QObject::receivers(const char *signal) const
existence of either \a signal or \a method, or if their signatures
aren't compatible.
- For every connection you make, a signal is emitted; two signals are emitted
- for duplicate connections. You can break all of these connections with a
- single disconnect() call.
+ By default, a signal is emitted for every connection you make;
+ two signals are emitted for duplicate connections. You can break
+ all of these connections with a single disconnect() call.
+ If you pass the Qt::UniqueConnection \a type, the connection will only
+ be made if it is not a duplicate. If there is already a duplicate
+ (exact same signal to the exact same slot on the same objects),
+ the connection will fail and connect will return false
The optional \a type parameter describes the type of connection
to establish. In particular, it determines whether a particular
@@ -2553,7 +2557,8 @@ bool QObject::connect(const QObject *sender, const char *signal,
}
}
#endif
- QMetaObject::connect(sender, signal_index, receiver, method_index, type, types);
+ if (!QMetaObject::connect(sender, signal_index, receiver, method_index, type, types))
+ return false;
const_cast<QObject*>(sender)->connectNotify(signal - 1);
return true;
}
@@ -2804,20 +2809,35 @@ bool QMetaObject::connect(const QObject *sender, int signal_index,
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
- QOrderedMutexLocker locker(&s->d_func()->threadData->mutex,
- &r->d_func()->threadData->mutex);
+ QOrderedMutexLocker locker(signalSlotLock(sender),
+ signalSlotLock(receiver));
-#if defined(Q_CC_HPACC) && defined(QT_ARCH_PARISC)
- QObjectPrivate::Connection c;
- c.receiver = r;
- c.method = method_index;
- c.connectionType = type;
- c.argumentTypes = types;
-#else
- QObjectPrivate::Connection c = { r, method_index, type, Q_BASIC_ATOMIC_INITIALIZER(types) };
-#endif
- s->d_func()->addConnection(signal_index, &c);
- r->d_func()->refSender(s, signal_index);
+ if (type & Qt::UniqueConnection) {
+ QObjectConnectionListVector *connectionLists = s->d_func()->connectionLists;
+ if (connectionLists && connectionLists->count() > signal_index) {
+ QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index];
+ for (int i = 0; i < connectionList.count(); ++i) {
+ QObjectPrivate::Connection *c2 = connectionList.at(i);
+ if (c2->receiver == receiver && c2->method == method_index)
+ return false;
+ }
+ }
+ type &= Qt::UniqueConnection - 1;
+ }
+
+ QObjectPrivate::Connection *c = new QObjectPrivate::Connection;
+ c->sender = s;
+ c->receiver = r;
+ c->method = method_index;
+ c->connectionType = type;
+ c->argumentTypes = types;
+ c->prev = &r->d_func()->senders;
+ c->next = *c->prev;
+ *c->prev = c;
+ if (c->next)
+ c->next->prev = &c->next;
+
+ s->d_func()->addConnection(signal_index, c);
if (signal_index < 0)
sender->d_func()->connectedSignals = ~0u;
@@ -2839,8 +2859,8 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
QObject *s = const_cast<QObject *>(sender);
QObject *r = const_cast<QObject *>(receiver);
- QMutex *senderMutex = &s->d_func()->threadData->mutex;
- QMutex *receiverMutex = r ? &r->d_func()->threadData->mutex : 0;
+ QMutex *senderMutex = signalSlotLock(sender);
+ QMutex *receiverMutex = receiver ? signalSlotLock(receiver) : 0;
QOrderedMutexLocker locker(senderMutex, receiverMutex);
QObjectConnectionListVector *connectionLists = s->d_func()->connectionLists;
@@ -2856,27 +2876,25 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
for (signal_index = -1; signal_index < connectionLists->count(); ++signal_index) {
QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index];
for (int i = 0; i < connectionList.count(); ++i) {
- QObjectPrivate::Connection *c = &connectionList[i];
+ QObjectPrivate::Connection *c = connectionList[i];
if (c->receiver
&& (r == 0 || (c->receiver == r
&& (method_index < 0 || c->method == method_index)))) {
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = false;
if (!receiverMutex && senderMutex != m) {
// need to relock this receiver and sender in the correct order
- bool needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
- c = &connectionList[i];
- if (c->receiver)
- c->receiver->d_func()->derefSender(s, signal_index);
- if (needToUnlock)
- m->unlock();
- } else {
- // no need to unlock
- c->receiver->d_func()->derefSender(s, signal_index);
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = connectionList[i];
}
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
}
+
+ if (needToUnlock)
+ m->unlock();
+
c->receiver = 0;
success = true;
@@ -2887,27 +2905,24 @@ bool QMetaObject::disconnect(const QObject *sender, int signal_index,
} else if (signal_index < connectionLists->count()) {
QObjectPrivate::ConnectionList &connectionList = (*connectionLists)[signal_index];
for (int i = 0; i < connectionList.count(); ++i) {
- QObjectPrivate::Connection *c = &connectionList[i];
+ QObjectPrivate::Connection *c = connectionList[i];
if (c->receiver
&& (r == 0 || (c->receiver == r
&& (method_index < 0 || c->method == method_index)))) {
- QMutex *m = &c->receiver->d_func()->threadData->mutex;
+ QMutex *m = signalSlotLock(c->receiver);
+ bool needToUnlock = false;
if (!receiverMutex && senderMutex != m) {
// need to relock this receiver and sender in the correct order
- bool needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
- c = &connectionList[i];
- if (c->receiver)
- c->receiver->d_func()->derefSender(s, signal_index);
- if (needToUnlock)
- m->unlock();
- } else {
- // no need to unlock
- c->receiver->d_func()->derefSender(s, signal_index);
+ needToUnlock = QOrderedMutexLocker::relock(senderMutex, m);
+ c = connectionList[i];
}
- if (c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
- qFree(c->argumentTypes);
- c->argumentTypes = 0;
+ if (c->receiver) {
+ *c->prev = c->next;
+ if (c->next) c->next->prev = c->prev;
}
+
+ if (needToUnlock)
+ m->unlock();
c->receiver = 0;
success = true;
@@ -2990,32 +3005,31 @@ void QMetaObject::connectSlotsByName(QObject *o)
}
}
-static void queued_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c,
+static void queued_activate(QObject *sender, int signal, QObjectPrivate::Connection *c,
void **argv, QSemaphore *semaphore = 0)
{
- if (!c.argumentTypes || c.argumentTypes != &DIRECT_CONNECTION_ONLY) {
+ if (!c->argumentTypes && c->argumentTypes != &DIRECT_CONNECTION_ONLY) {
QMetaMethod m = sender->metaObject()->method(signal);
- QObjectPrivate::Connection &x = const_cast<QObjectPrivate::Connection &>(c);
int *tmp = queuedConnectionTypes(m.parameterTypes());
if (!tmp) // cannot queue arguments
tmp = &DIRECT_CONNECTION_ONLY;
- if (!x.argumentTypes.testAndSetOrdered(0, tmp)) {
+ if (!c->argumentTypes.testAndSetOrdered(0, tmp)) {
if (tmp != &DIRECT_CONNECTION_ONLY)
- qFree(tmp);
+ delete [] tmp;
}
}
- if (c.argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
+ if (c->argumentTypes == &DIRECT_CONNECTION_ONLY) // cannot activate
return;
int nargs = 1; // include return type
- while (c.argumentTypes[nargs-1])
+ while (c->argumentTypes[nargs-1])
++nargs;
int *types = (int *) qMalloc(nargs*sizeof(int));
void **args = (void **) qMalloc(nargs*sizeof(void *));
types[0] = 0; // return type
args[0] = 0; // return value
for (int n = 1; n < nargs; ++n)
- args[n] = QMetaType::construct((types[n] = c.argumentTypes[n-1]), argv[n]);
- QCoreApplication::postEvent(c.receiver, new QMetaCallEvent(c.method,
+ args[n] = QMetaType::construct((types[n] = c->argumentTypes[n-1]), argv[n]);
+ QCoreApplication::postEvent(c->receiver, new QMetaCallEvent(c->method,
sender,
signal,
nargs,
@@ -3024,13 +3038,13 @@ static void queued_activate(QObject *sender, int signal, const QObjectPrivate::C
semaphore));
}
-static void blocking_activate(QObject *sender, int signal, const QObjectPrivate::Connection &c, void **argv)
+static void blocking_activate(QObject *sender, int signal, QObjectPrivate::Connection *c, void **argv)
{
- if (QThread::currentThread() == c.receiver->thread()) {
+ if (QThread::currentThread() == c->receiver->thread()) {
qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
"Sender is %s(%p), receiver is %s(%p)",
sender->metaObject()->className(), sender,
- c.receiver->metaObject()->className(), c.receiver);
+ c->receiver->metaObject()->className(), c->receiver);
}
#ifdef QT_NO_THREAD
@@ -3038,7 +3052,7 @@ static void blocking_activate(QObject *sender, int signal, const QObjectPrivate:
#else
QSemaphore semaphore;
queued_activate(sender, signal, c, argv, &semaphore);
- QMutex *mutex = &QThreadData::get2(sender->thread())->mutex;
+ QMutex *mutex = signalSlotLock(sender);
mutex->unlock();
semaphore.acquire();
mutex->lock();
@@ -3058,7 +3072,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
argv ? argv : empty_argv);
}
- QMutexLocker locker(&sender->d_func()->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(sender));
QThreadData *currentThreadData = QThreadData::current();
QObjectConnectionListVector *connectionLists = sender->d_func()->connectionLists;
@@ -3080,7 +3094,7 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
}
int count = connectionLists->at(signal).count();
for (int i = 0; i < count; ++i) {
- const QObjectPrivate::Connection *c = &connectionLists->at(signal)[i];
+ QObjectPrivate::Connection *c = connectionLists->at(signal)[i];
if (!c->receiver)
continue;
@@ -3092,10 +3106,10 @@ void QMetaObject::activate(QObject *sender, int from_signal_index, int to_signal
&& (currentThreadData != sender->d_func()->threadData
|| receiver->d_func()->threadData != sender->d_func()->threadData))
|| (c->connectionType == Qt::QueuedConnection)) {
- queued_activate(sender, signal, *c, argv);
+ queued_activate(sender, signal, c, argv);
continue;
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
- blocking_activate(sender, signal, *c, argv);
+ blocking_activate(sender, signal, c, argv);
continue;
}
@@ -3410,7 +3424,7 @@ void QObject::dumpObjectInfo()
objectName().isEmpty() ? "unnamed" : objectName().toLocal8Bit().data());
Q_D(QObject);
- QMutexLocker locker(&d->threadData->mutex);
+ QMutexLocker locker(signalSlotLock(this));
// first, look for connections where this object is the sender
qDebug(" SIGNALS OUT");
@@ -3423,16 +3437,16 @@ void QObject::dumpObjectInfo()
// receivers
const QObjectPrivate::ConnectionList &connectionList = d->connectionLists->at(signal_index);
for (int i = 0; i < connectionList.count(); ++i) {
- const QObjectPrivate::Connection &c = connectionList.at(i);
- if (!c.receiver) {
+ const QObjectPrivate::Connection *c = connectionList.at(i);
+ if (!c->receiver) {
qDebug(" <Disconnected receiver>");
continue;
}
- const QMetaObject *receiverMetaObject = c.receiver->metaObject();
- const QMetaMethod method = receiverMetaObject->method(c.method);
+ const QMetaObject *receiverMetaObject = c->receiver->metaObject();
+ const QMetaMethod method = receiverMetaObject->method(c->method);
qDebug(" --> %s::%s %s",
receiverMetaObject->className(),
- c.receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c.receiver->objectName()),
+ c->receiver->objectName().isEmpty() ? "unnamed" : qPrintable(c->receiver->objectName()),
method.signature());
}
}
@@ -3443,18 +3457,16 @@ void QObject::dumpObjectInfo()
// now look for connections where this object is the receiver
qDebug(" SIGNALS IN");
- if (!d->senders.isEmpty()) {
- for (int i = 0; i < d->senders.count(); ++i) {
- const QObjectPrivate::Sender &s = d->senders.at(i);
- const QMetaObject *senderMetaObject = s.sender->metaObject();
- const QMetaMethod signal = senderMetaObject->method(s.signal);
- qDebug(" <-- %s::%s %s",
- senderMetaObject->className(),
- s.sender->objectName().isEmpty() ? "unnamed" : qPrintable(s.sender->objectName()),
- signal.signature());
+ if (d->senders) {
+ for (QObjectPrivate::Connection *s = d->senders; s; s = s->next) {
+ const QMetaMethod slot = metaObject()->method(s->method);
+ qDebug(" <-- %s::%s %s",
+ s->sender->metaObject()->className(),
+ s->sender->objectName().isEmpty() ? "unnamed" : qPrintable(s->sender->objectName()),
+ slot.signature());
}
} else {
- qDebug(" <None>");
+ qDebug(" <None>");
}
#endif
}
@@ -3507,7 +3519,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
#ifndef Q_BROKEN_DEBUG_STREAM
if (!o)
return dbg << "QObject(0x0) ";
- dbg.nospace() << o->metaObject()->className() << "(" << (void *)o;
+ dbg.nospace() << o->metaObject()->className() << '(' << (void *)o;
if (!o->objectName().isEmpty())
dbg << ", name = " << o->objectName();
dbg << ')';
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 8d5c4e3..72f2a65 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -107,7 +107,8 @@ public:
uint receiveChildEvents : 1;
uint inEventHandler : 1;
uint inThreadChangeEvent : 1;
- uint unused : 23;
+ uint hasGuards : 1; //true iff there is one or more QPointer attached to this object
+ uint unused : 22;
int postedEvents;
};
diff --git a/src/corelib/kernel/qobject_p.h b/src/corelib/kernel/qobject_p.h
index 0eed938..d699061 100644
--- a/src/corelib/kernel/qobject_p.h
+++ b/src/corelib/kernel/qobject_p.h
@@ -114,7 +114,6 @@ public:
int signal;
int ref;
};
-
// object currently activating the object
Sender *currentSender;
@@ -148,21 +147,23 @@ public:
// Note: you must hold the signalSlotLock() before accessing the lists below or calling the functions
struct Connection
{
+ QObject *sender;
QObject *receiver;
int method;
uint connectionType : 3; // 0 == auto, 1 == direct, 2 == queued, 4 == blocking
QBasicAtomicPointer<int> argumentTypes;
+ //senders linked list
+ Connection *next;
+ Connection **prev;
+ ~Connection();
};
- typedef QList<Connection> ConnectionList;
+ typedef QList<Connection *> ConnectionList;
QObjectConnectionListVector *connectionLists;
void addConnection(int signal, Connection *c);
- void removeReceiver(int signal, QObject *receiver);
void cleanConnectionLists();
- QList<Sender> senders;
- void refSender(QObject *sender, int signal);
- void derefSender(QObject *sender, int signal);
+ Connection *senders; //linked list;
static Sender *setCurrentSender(QObject *receiver,
Sender *sender);
@@ -207,7 +208,7 @@ private:
QSemaphore *semaphore_;
};
-class Q_CORE_EXPORT QBoolBlocker
+class QBoolBlocker
{
public:
inline QBoolBlocker(bool &b, bool value=true):block(b), reset(b){block = value;}
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 3a22323..f5d08ce 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -55,7 +55,7 @@ class QByteArray;
class QString;
#ifndef Q_MOC_OUTPUT_REVISION
-#define Q_MOC_OUTPUT_REVISION 61
+#define Q_MOC_OUTPUT_REVISION 62
#endif
// The following macros are our "extensions" to C++
diff --git a/src/corelib/kernel/qtimer.cpp b/src/corelib/kernel/qtimer.cpp
index 4b3feb0..29bdf7e 100644
--- a/src/corelib/kernel/qtimer.cpp
+++ b/src/corelib/kernel/qtimer.cpp
@@ -211,7 +211,7 @@ void QTimer::start()
*/
void QTimer::start(int msec)
{
- setInterval(msec);
+ inter = msec;
start();
}
@@ -251,7 +251,7 @@ void QTimer::stop()
/*!
- \reimp
+ \reimp
*/
void QTimer::timerEvent(QTimerEvent *e)
{
@@ -269,7 +269,7 @@ class QSingleShotTimer : public QObject
public:
~QSingleShotTimer();
QSingleShotTimer(int msec, QObject *r, const char * m);
-signals:
+Q_SIGNALS:
void timeout();
protected:
void timerEvent(QTimerEvent *);
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index df904a6..38fa216 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -209,8 +209,6 @@ static int numerusHelper(int n, const uchar *rules, int rulesSize)
return -1;
}
-extern bool qt_detectRTLLanguage();
-
class QTranslatorPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTranslator)
@@ -351,7 +349,7 @@ QTranslator::QTranslator(QObject * parent, const char * name)
QTranslator::~QTranslator()
{
if (QCoreApplication::instance())
- QCoreApplication::instance()->removeTranslator(this);
+ QCoreApplication::removeTranslator(this);
Q_D(QTranslator);
d->clear();
}
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 0d85b93..9fc230e 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -71,27 +71,6 @@ QT_BEGIN_NAMESPACE
# define FLT_DIG 6
#endif
-
-static const void *constDataHelper(const QVariant::Private &d)
-{
- switch (d.type) {
- case QVariant::Int:
- return &d.data.i;
- case QVariant::UInt:
- return &d.data.u;
- case QVariant::Bool:
- return &d.data.b;
- case QVariant::LongLong:
- return &d.data.ll;
- case QVariant::ULongLong:
- return &d.data.ull;
- case QVariant::Double:
- return &d.data.d;
- default:
- return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
- }
-}
-
static void construct(QVariant::Private *x, const void *copy)
{
x->is_shared = false;
@@ -188,6 +167,9 @@ static void construct(QVariant::Private *x, const void *copy)
x->data.d = copy ? *static_cast<const double*>(copy) : 0.0;
#endif
break;
+ case QMetaType::Float:
+ x->data.f = copy ? *static_cast<const float*>(copy) : 0.0f;
+ break;
case QVariant::LongLong:
#if defined(Q_CC_RVCT)
// Using trinary operator with 64bit constants crashes when ran on Symbian device
@@ -301,6 +283,7 @@ static void clear(QVariant::Private *d)
case QVariant::LongLong:
case QVariant::ULongLong:
case QVariant::Double:
+ case QMetaType::Float:
break;
case QVariant::Invalid:
case QVariant::UserType:
@@ -369,6 +352,7 @@ static bool isNull(const QVariant::Private *d)
case QVariant::ULongLong:
case QVariant::Bool:
case QVariant::Double:
+ case QMetaType::Float:
break;
}
return d->is_null;
@@ -460,6 +444,8 @@ static bool compare(const QVariant::Private *a, const QVariant::Private *b)
return a->data.b == b->data.b;
case QVariant::Double:
return a->data.d == b->data.d;
+ case QMetaType::Float:
+ return a->data.f == b->data.f;
case QVariant::Date:
return *v_cast<QDate>(a) == *v_cast<QDate>(b);
case QVariant::Time:
@@ -518,7 +504,7 @@ static qlonglong qMetaTypeNumber(const QVariant::Private *d)
case QMetaType::Long:
return qlonglong(*static_cast<long *>(d->data.shared->ptr));
case QMetaType::Float:
- return qRound64(*static_cast<float *>(d->data.shared->ptr));
+ return qRound64(d->data.f);
case QVariant::Double:
return qRound64(d->data.d);
}
@@ -632,6 +618,15 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
ok = &dummy;
switch (uint(t)) {
+ case QVariant::Url:
+ switch (d->type) {
+ case QVariant::String:
+ *static_cast<QUrl *>(result) = QUrl(*v_cast<QString>(d));
+ break;
+ default:
+ return false;
+ }
+ break;
case QVariant::String: {
QString *str = static_cast<QString *>(result);
switch (d->type) {
@@ -655,7 +650,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*str = QString::number(qMetaTypeUNumber(d));
break;
case QMetaType::Float:
- *str = QString::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG);
+ *str = QString::number(d->data.f, 'g', FLT_DIG);
break;
case QVariant::Double:
*str = QString::number(d->data.d, 'g', DBL_DIG);
@@ -681,6 +676,8 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
if (v_cast<QStringList>(d)->count() == 1)
*str = v_cast<QStringList>(d)->at(0);
break;
+ case QVariant::Url:
+ *str = v_cast<QUrl>(d)->toString();
default:
return false;
}
@@ -826,7 +823,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*ba = QByteArray::number(d->data.d, 'g', DBL_DIG);
break;
case QMetaType::Float:
- *ba = QByteArray::number(*static_cast<float *>(d->data.shared->ptr), 'g', FLT_DIG);
+ *ba = QByteArray::number(d->data.f, 'g', FLT_DIG);
break;
case QMetaType::Char:
case QMetaType::UChar:
@@ -928,7 +925,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
*f = double(d->data.b);
break;
case QMetaType::Float:
- *f = *static_cast<float *>(d->data.shared->ptr);
+ *f = double(d->data.f);
break;
case QVariant::LongLong:
case QVariant::Int:
@@ -1062,7 +1059,7 @@ static bool convert(const QVariant::Private *d, QVariant::Type t, void *result,
#if !defined(QT_NO_DEBUG_STREAM) && !defined(Q_BROKEN_DEBUG_STREAM)
static void streamDebug(QDebug dbg, const QVariant &v)
{
- switch (v.type()) {
+ switch (v.userType()) {
case QVariant::Int:
dbg.nospace() << v.toInt();
break;
@@ -1075,6 +1072,9 @@ static void streamDebug(QDebug dbg, const QVariant &v)
case QVariant::ULongLong:
dbg.nospace() << v.toULongLong();
break;
+ case QMetaType::Float:
+ dbg.nospace() << qVariantValue<float>(v);
+ break;
case QVariant::Double:
dbg.nospace() << v.toDouble();
break;
@@ -1383,7 +1383,7 @@ void QVariant::create(int type, const void *copy)
QVariant::~QVariant()
{
- if (d.type > Char && (!d.is_shared || !d.data.shared->ref.deref()))
+ if (d.type > Char && d.type != QMetaType::Float && (!d.is_shared || !d.data.shared->ref.deref()))
handler->clear(&d);
}
@@ -1399,7 +1399,7 @@ QVariant::QVariant(const QVariant &p)
{
if (d.is_shared) {
d.data.shared->ref.ref();
- } else if (p.d.type > Char) {
+ } else if (p.d.type > Char && p.d.type != QMetaType::Float) {
handler->construct(&d, p.constData());
d.is_null = p.d.is_null;
}
@@ -1593,6 +1593,12 @@ QVariant::QVariant(const char *val)
*/
/*!
+ \fn QVariant::QVariant(float val)
+
+ Constructs a new variant with a floating point value, \a val.
+*/
+
+/*!
\fn QVariant::QVariant(const QList<QVariant> &val)
Constructs a new variant with a list value, \a val.
@@ -1647,44 +1653,44 @@ QVariant::QVariant(double val)
{ d.is_null = false; d.type = Double; d.data.d = val; }
QVariant::QVariant(const QByteArray &val)
-{ create(ByteArray, &val); }
+{ d.is_null = false; d.type = ByteArray; v_construct<QByteArray>(&d, val); }
QVariant::QVariant(const QBitArray &val)
-{ create(BitArray, &val); }
+{ d.is_null = false; d.type = BitArray; v_construct<QBitArray>(&d, val); }
QVariant::QVariant(const QString &val)
-{ create(String, &val); }
+{ d.is_null = false; d.type = String; v_construct<QString>(&d, val); }
QVariant::QVariant(const QChar &val)
-{ create (Char, &val); }
+{ d.is_null = false; d.type = Char; v_construct<QChar>(&d, val); }
QVariant::QVariant(const QLatin1String &val)
-{ QString str(val); create(String, &str); }
+{ QString str(val); d.is_null = false; d.type = String; v_construct<QString>(&d, str); }
QVariant::QVariant(const QStringList &val)
-{ create(StringList, &val); }
+{ d.is_null = false; d.type = StringList; v_construct<QStringList>(&d, val); }
QVariant::QVariant(const QDate &val)
-{ create(Date, &val); }
+{ d.is_null = false; d.type = Date; v_construct<QDate>(&d, val); }
QVariant::QVariant(const QTime &val)
-{ create(Time, &val); }
+{ d.is_null = false; d.type = Time; v_construct<QTime>(&d, val); }
QVariant::QVariant(const QDateTime &val)
-{ create(DateTime, &val); }
+{ d.is_null = false; d.type = DateTime; v_construct<QDateTime>(&d, val); }
QVariant::QVariant(const QList<QVariant> &list)
-{ create(List, &list); }
+{ d.is_null = false; d.type = List; v_construct<QVariantList>(&d, list); }
QVariant::QVariant(const QMap<QString, QVariant> &map)
-{ create(Map, &map); }
+{ d.is_null = false; d.type = Map; v_construct<QVariantMap>(&d, map); }
QVariant::QVariant(const QHash<QString, QVariant> &hash)
-{ create(Hash, &hash); }
+{ d.is_null = false; d.type = Hash; v_construct<QVariantHash>(&d, hash); }
#ifndef QT_NO_GEOM_VARIANT
-QVariant::QVariant(const QPoint &pt) { create(Point, &pt); }
-QVariant::QVariant(const QPointF &pt) { create (PointF, &pt); }
-QVariant::QVariant(const QRectF &r) { create (RectF, &r); }
-QVariant::QVariant(const QLineF &l) { create (LineF, &l); }
-QVariant::QVariant(const QLine &l) { create (Line, &l); }
-QVariant::QVariant(const QRect &r) { create(Rect, &r); }
-QVariant::QVariant(const QSize &s) { create(Size, &s); }
-QVariant::QVariant(const QSizeF &s) { create(SizeF, &s); }
+QVariant::QVariant(const QPoint &pt) { d.is_null = false; d.type = Point; v_construct<QPoint>(&d, pt); }
+QVariant::QVariant(const QPointF &pt) { d.is_null = false; d.type = PointF; v_construct<QPointF>(&d, pt); }
+QVariant::QVariant(const QRectF &r) { d.is_null = false; d.type = RectF; v_construct<QRectF>(&d, r); }
+QVariant::QVariant(const QLineF &l) { d.is_null = false; d.type = LineF; v_construct<QLineF>(&d, l); }
+QVariant::QVariant(const QLine &l) { d.is_null = false; d.type = Line; v_construct<QLine>(&d, l); }
+QVariant::QVariant(const QRect &r) { d.is_null = false; d.type = Rect; v_construct<QRect>(&d, r); }
+QVariant::QVariant(const QSize &s) { d.is_null = false; d.type = Size; v_construct<QSize>(&d, s); }
+QVariant::QVariant(const QSizeF &s) { d.is_null = false; d.type = SizeF; v_construct<QSizeF>(&d, s); }
#endif
-QVariant::QVariant(const QUrl &u) { create(Url, &u); }
-QVariant::QVariant(const QLocale &l) { create(Locale, &l); }
+QVariant::QVariant(const QUrl &u) { d.is_null = false; d.type = Url; v_construct<QUrl>(&d, u); }
+QVariant::QVariant(const QLocale &l) { d.is_null = false; d.type = Locale; v_construct<QLocale>(&d, l); }
#ifndef QT_NO_REGEXP
-QVariant::QVariant(const QRegExp &regExp) { create(RegExp, &regExp); }
+QVariant::QVariant(const QRegExp &regExp) { d.is_null = false; d.type = RegExp; v_construct<QRegExp>(&d, regExp); }
#endif
QVariant::QVariant(Qt::GlobalColor color) { create(62, &color); }
@@ -1749,7 +1755,7 @@ QVariant& QVariant::operator=(const QVariant &variant)
if (variant.d.is_shared) {
variant.d.data.shared->ref.ref();
d = variant.d;
- } else if (variant.d.type > Char) {
+ } else if (variant.d.type > Char && variant.d.type != QMetaType::Float) {
d.type = variant.d.type;
handler->construct(&d, variant.constData());
d.is_null = variant.d.is_null;
@@ -1855,7 +1861,7 @@ QVariant::Type QVariant::nameToType(const char *name)
#ifndef QT_NO_DATASTREAM
enum { MapFromThreeCount = 35 };
-static const uint map_from_three[MapFromThreeCount] =
+static const ushort map_from_three[MapFromThreeCount] =
{
QVariant::Invalid,
QVariant::Map,
@@ -1935,7 +1941,7 @@ void QVariant::load(QDataStream &s)
}
// const cast is safe since we operate on a newly constructed variant
- if (!QMetaType::load(s, d.type, const_cast<void *>(constDataHelper(d)))) {
+ if (!QMetaType::load(s, d.type, const_cast<void *>(constData()))) {
s.setStatus(QDataStream::ReadCorruptData);
qWarning("QVariant::load: unable to load type %d.", d.type);
}
@@ -1975,7 +1981,7 @@ void QVariant::save(QDataStream &s) const
return;
}
- if (!QMetaType::save(s, d.type, constDataHelper(d))) {
+ if (!QMetaType::save(s, d.type, constData())) {
Q_ASSERT_X(false, "QVariant::save", "Invalid type to save");
qWarning("QVariant::save: unable to save type %d.", d.type);
}
@@ -2516,7 +2522,8 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
/*QString*/ 1 << QVariant::StringList | 1 << QVariant::ByteArray | 1 << QVariant::Int
| 1 << QVariant::UInt | 1 << QVariant::Bool | 1 << QVariant::Double
| 1 << QVariant::Date | 1 << QVariant::Time | 1 << QVariant::DateTime
- | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char,
+ | 1 << QVariant::LongLong | 1 << QVariant::ULongLong | 1 << QVariant::Char
+ | 1 << QVariant::Url,
/*QStringList*/ 1 << QVariant::List | 1 << QVariant::String,
@@ -2531,7 +2538,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
/*QDateTime*/ 1 << QVariant::String | 1 << QVariant::Date,
-/*QUrl*/ 0,
+/*QUrl*/ 1 << QVariant::String,
/*QLocale*/ 0,
@@ -2593,57 +2600,63 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] =
*/
bool QVariant::canConvert(Type t) const
{
- if (d.type == uint(t))
+ //we can treat floats as double
+ //the reason for not doing it the "proper" way is that QMetaType::Float's value is 135,
+ //which can't be handled by qCanConvertMatrix
+ //In addition QVariant::Type doesn't have a Float value, so we're using QMetaType::Float
+ const uint currentType = ((d.type == QMetaType::Float) ? QVariant::Double : d.type);
+ if (uint(t) == uint(QMetaType::Float)) t = QVariant::Double;
+
+ if (currentType == uint(t))
return true;
- if (d.type > QVariant::LastCoreType || t > QVariant::LastCoreType) {
+ if (currentType > QVariant::LastCoreType || t > QVariant::LastCoreType) {
switch (uint(t)) {
case QVariant::Int:
- return d.type == QVariant::KeySequence
- || d.type == QMetaType::ULong
- || d.type == QMetaType::Long
- || d.type == QMetaType::UShort
- || d.type == QMetaType::UChar
- || d.type == QMetaType::Char
- || d.type == QMetaType::Short;
+ return currentType == QVariant::KeySequence
+ || currentType == QMetaType::ULong
+ || currentType == QMetaType::Long
+ || currentType == QMetaType::UShort
+ || currentType == QMetaType::UChar
+ || currentType == QMetaType::Char
+ || currentType == QMetaType::Short;
case QVariant::Image:
- return d.type == QVariant::Pixmap || d.type == QVariant::Bitmap;
+ return currentType == QVariant::Pixmap || currentType == QVariant::Bitmap;
case QVariant::Pixmap:
- return d.type == QVariant::Image || d.type == QVariant::Bitmap
- || d.type == QVariant::Brush;
+ return currentType == QVariant::Image || currentType == QVariant::Bitmap
+ || currentType == QVariant::Brush;
case QVariant::Bitmap:
- return d.type == QVariant::Pixmap || d.type == QVariant::Image;
+ return currentType == QVariant::Pixmap || currentType == QVariant::Image;
case QVariant::ByteArray:
- return d.type == QVariant::Color;
+ return currentType == QVariant::Color;
case QVariant::String:
- return d.type == QVariant::KeySequence || d.type == QVariant::Font
- || d.type == QVariant::Color;
+ return currentType == QVariant::KeySequence || currentType == QVariant::Font
+ || currentType == QVariant::Color;
case QVariant::KeySequence:
- return d.type == QVariant::String || d.type == QVariant::Int;
+ return currentType == QVariant::String || currentType == QVariant::Int;
case QVariant::Font:
- return d.type == QVariant::String;
+ return currentType == QVariant::String;
case QVariant::Color:
- return d.type == QVariant::String || d.type == QVariant::ByteArray
- || d.type == QVariant::Brush;
+ return currentType == QVariant::String || currentType == QVariant::ByteArray
+ || currentType == QVariant::Brush;
case QVariant::Brush:
- return d.type == QVariant::Color || d.type == QVariant::Pixmap;
+ return currentType == QVariant::Color || currentType == QVariant::Pixmap;
case QMetaType::Long:
case QMetaType::Char:
case QMetaType::UChar:
case QMetaType::ULong:
case QMetaType::Short:
case QMetaType::UShort:
- case QMetaType::Float:
- return qCanConvertMatrix[QVariant::Int] & (1 << d.type) || d.type == QVariant::Int;
+ return qCanConvertMatrix[QVariant::Int] & (1 << currentType) || currentType == QVariant::Int;
default:
return false;
}
}
- if(t == String && d.type == StringList)
+ if(t == String && currentType == StringList)
return v_cast<QStringList>(&d)->count() == 1;
else
- return qCanConvertMatrix[t] & (1 << d.type);
+ return qCanConvertMatrix[t] & (1 << currentType);
}
/*!
@@ -2754,7 +2767,7 @@ bool QVariant::cmp(const QVariant &v) const
const void *QVariant::constData() const
{
- return constDataHelper(d);
+ return d.is_shared ? d.data.shared->ptr : reinterpret_cast<const void *>(&d.data.ptr);
}
/*!
@@ -2767,7 +2780,7 @@ const void *QVariant::constData() const
void* QVariant::data()
{
detach();
- return const_cast<void *>(constDataHelper(d));
+ return const_cast<void *>(constData());
}
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index d7b7e3c..d73fcbc 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -181,6 +181,7 @@ class Q_CORE_EXPORT QVariant
QVariant(qulonglong ull);
QVariant(bool b);
QVariant(double d);
+ QVariant(float f) { d.is_null = false; d.type = QMetaType::Float; d.data.f = f; }
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN_CONSTRUCTOR QVariant(const char *str);
#endif
@@ -349,6 +350,7 @@ class Q_CORE_EXPORT QVariant
uint u;
bool b;
double d;
+ float f;
qlonglong ll;
qulonglong ull;
void *ptr;
@@ -443,7 +445,18 @@ inline QVariant qVariantFromValue(const QVariant &t) { return t; }
template <typename T>
inline void qVariantSetValue(QVariant &v, const T &t)
{
- v = QVariant(qMetaTypeId<T>(reinterpret_cast<T *>(0)), &t);
+ //if possible we reuse the current QVariant private
+ const int type = qMetaTypeId<T>(reinterpret_cast<T *>(0));
+ QVariant::Private &d = v.data_ptr();
+ if (type <= int(QVariant::Char) || (type == d.type && v.isDetached())) {
+ d.type = type;
+ T *old = reinterpret_cast<T*>(d.is_shared ? d.data.shared->ptr : &d.data.ptr);
+ if (QTypeInfo<T>::isComplex)
+ old->~T();
+ new (old) T(t); //call the copy constructor
+ } else {
+ v = QVariant(type, &t);
+ }
}
inline QVariant::QVariant() {}
diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h
index 727a390..02b507e 100644
--- a/src/corelib/kernel/qvariant_p.h
+++ b/src/corelib/kernel/qvariant_p.h
@@ -91,13 +91,25 @@ inline T *v_cast(QVariant::Private *d, T * = 0)
#endif
+
+//a simple template that avoids to allocate 2 memory chunks when creating a QVariant
+template <class T> class QVariantPrivateSharedEx : public QVariant::PrivateShared
+{
+public:
+ QVariantPrivateSharedEx() : QVariant::PrivateShared(&m_t) { }
+ QVariantPrivateSharedEx(const T&t) : QVariant::PrivateShared(&m_t), m_t(t) { }
+
+private:
+ T m_t;
+};
+
// constructs a new variant if copy is 0, otherwise copy-constructs
template <class T>
inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
{
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
- x->data.shared = copy ? new QVariant::PrivateShared(new T(*static_cast<const T *>(copy)))
- : new QVariant::PrivateShared(new T);
+ x->data.shared = copy ? new QVariantPrivateSharedEx<T>(*static_cast<const T *>(copy))
+ : new QVariantPrivateSharedEx<T>;
x->is_shared = true;
} else {
if (copy)
@@ -107,16 +119,30 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0)
}
}
+template <class T>
+inline void v_construct(QVariant::Private *x, const T &t)
+{
+ if (sizeof(T) > sizeof(QVariant::Private::Data)) {
+ x->data.shared = new QVariantPrivateSharedEx<T>(t);
+ x->is_shared = true;
+ } else {
+ new (&x->data.ptr) T(t);
+ }
+}
+
// deletes the internal structures
template <class T>
inline void v_clear(QVariant::Private *d, T* = 0)
{
+
if (sizeof(T) > sizeof(QVariant::Private::Data)) {
- delete v_cast<T>(d);
- delete d->data.shared;
+ //now we need to cast
+ //because QVariant::PrivateShared doesn't have a virtual destructor
+ delete static_cast<QVariantPrivateSharedEx<T>*>(d->data.shared);
} else {
v_cast<T>(d)->~T();
}
+
}
QT_END_NAMESPACE
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
index 5163027..4740bf1 100644
--- a/src/corelib/plugin/qfactoryloader.cpp
+++ b/src/corelib/plugin/qfactoryloader.cpp
@@ -55,7 +55,7 @@
QT_BEGIN_NAMESPACE
-Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders);
+Q_GLOBAL_STATIC(QList<QFactoryLoader *>, qt_factory_loaders)
Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_factoryloader_mutex, (QMutex::Recursive))
diff --git a/src/corelib/plugin/qlibrary_unix.cpp b/src/corelib/plugin/qlibrary_unix.cpp
index c868d4a..f6830f2 100644
--- a/src/corelib/plugin/qlibrary_unix.cpp
+++ b/src/corelib/plugin/qlibrary_unix.cpp
@@ -71,7 +71,7 @@ static QString qdlerror()
#else
const char *err = strerror(errno);
#endif
- return err ? QLatin1String("(")+QString::fromLocal8Bit(err) + QLatin1String(")"): QString();
+ return err ? QLatin1Char('(') + QString::fromLocal8Bit(err) + QLatin1Char(')'): QString();
}
bool QLibraryPrivate::load_sys()
diff --git a/src/corelib/plugin/qplugin.h b/src/corelib/plugin/qplugin.h
index 4d0e53c..e3b9d32 100644
--- a/src/corelib/plugin/qplugin.h
+++ b/src/corelib/plugin/qplugin.h
@@ -63,6 +63,21 @@ typedef QObject *(*QtPluginInstanceFunction)();
void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunction function);
+struct qt_plugin_instance_deleter
+{
+ qt_plugin_instance_deleter(QPointer<QObject> &instance)
+ : instance_(instance)
+ {
+ }
+
+ ~qt_plugin_instance_deleter()
+ {
+ delete instance_;
+ }
+
+ QPointer<QObject> &instance_;
+};
+
#define Q_IMPORT_PLUGIN(PLUGIN) \
extern QT_PREPEND_NAMESPACE(QObject) *qt_plugin_instance_##PLUGIN(); \
class Static##PLUGIN##PluginInstance{ \
@@ -76,8 +91,10 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio
#define Q_PLUGIN_INSTANCE(IMPLEMENTATION) \
{ \
static QT_PREPEND_NAMESPACE(QPointer)<QT_PREPEND_NAMESPACE(QObject)> _instance; \
- if (!_instance) \
+ if (!_instance) { \
+ static QT_PREPEND_NAMESPACE(qt_plugin_instance_deleter) deleter(_instance); \
_instance = new IMPLEMENTATION; \
+ } \
return _instance; \
}
@@ -114,7 +131,7 @@ void Q_CORE_EXPORT qRegisterStaticPluginInstanceFunction(QtPluginInstanceFunctio
"pattern=""QT_PLUGIN_VERIFICATION_DATA""\n" \
"version="QT_VERSION_STR"\n" \
"debug="QPLUGIN_DEBUG_STR"\n" \
- "buildkey="QT_BUILD_KEY"\0";
+ "buildkey="QT_BUILD_KEY;
# if defined (Q_OS_WIN32) && defined(Q_CC_BOR)
# define Q_STANDARD_CALL __stdcall
diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp
index 4365c98..a6138a1 100644
--- a/src/corelib/plugin/quuid.cpp
+++ b/src/corelib/plugin/quuid.cpp
@@ -405,7 +405,7 @@ QDataStream &operator>>(QDataStream &s, QUuid &id)
}
return s;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
Returns true if this is the null UUID
diff --git a/src/corelib/statemachine/qabstractstate.cpp b/src/corelib/statemachine/qabstractstate.cpp
new file mode 100644
index 0000000..973057b
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate.cpp
@@ -0,0 +1,206 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstractstate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qabstractstate_p.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractState
+
+ \brief The QAbstractState class is the base class of states of a QStateMachine.
+
+ \since 4.6
+ \ingroup statemachine
+
+ The QAbstractState class is the abstract base class of states that are part
+ of a QStateMachine. It defines the interface that all state objects have in
+ common. QAbstractState is part of \l{The State Machine Framework}.
+
+ The entered() signal is emitted when the state has been entered. The
+ exited() signal is emitted when the state has been exited.
+
+ The parentState() function returns the state's parent state. The machine()
+ function returns the state machine that the state is part of.
+
+ \section1 Subclassing
+
+ The onEntry() function is called when the state is entered; reimplement this
+ function to perform custom processing when the state is entered.
+
+ The onExit() function is called when the state is exited; reimplement this
+ function to perform custom processing when the state is exited.
+*/
+
+QAbstractStatePrivate::QAbstractStatePrivate()
+{
+}
+
+QAbstractStatePrivate *QAbstractStatePrivate::get(QAbstractState *q)
+{
+ return q->d_func();
+}
+
+QStateMachine *QAbstractStatePrivate::machine() const
+{
+ QObject *par = parent;
+ while (par != 0) {
+ if (QStateMachine *mach = qobject_cast<QStateMachine*>(par))
+ return mach;
+ par = par->parent();
+ }
+ return 0;
+}
+
+void QAbstractStatePrivate::callOnEntry(QEvent *e)
+{
+ Q_Q(QAbstractState);
+ q->onEntry(e);
+}
+
+void QAbstractStatePrivate::callOnExit(QEvent *e)
+{
+ Q_Q(QAbstractState);
+ q->onExit(e);
+}
+
+void QAbstractStatePrivate::emitEntered()
+{
+ Q_Q(QAbstractState);
+ emit q->entered();
+}
+
+void QAbstractStatePrivate::emitExited()
+{
+ Q_Q(QAbstractState);
+ emit q->exited();
+}
+
+/*!
+ Constructs a new state with the given \a parent state.
+*/
+QAbstractState::QAbstractState(QState *parent)
+ : QObject(*new QAbstractStatePrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAbstractState::QAbstractState(QAbstractStatePrivate &dd, QState *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Destroys this state.
+*/
+QAbstractState::~QAbstractState()
+{
+}
+
+/*!
+ Returns this state's parent state, or 0 if the state has no parent state.
+*/
+QState *QAbstractState::parentState() const
+{
+ return qobject_cast<QState*>(parent());
+}
+
+/*!
+ Returns the state machine that this state is part of, or 0 if the state is
+ not part of a state machine.
+*/
+QStateMachine *QAbstractState::machine() const
+{
+ Q_D(const QAbstractState);
+ return d->machine();
+}
+
+/*!
+ \fn QAbstractState::onExit(QEvent *event)
+
+ This function is called when the state is exited. The given \a event is what
+ caused the state to be exited. Reimplement this function to perform custom
+ processing when the state is exited.
+*/
+
+/*!
+ \fn QAbstractState::onEntry(QEvent *event)
+
+ This function is called when the state is entered. The given \a event is
+ what caused the state to be entered. Reimplement this function to perform
+ custom processing when the state is entered.
+*/
+
+/*!
+ \fn QAbstractState::entered()
+
+ This signal is emitted when the state has been entered (after onEntry() has
+ been called).
+*/
+
+/*!
+ \fn QAbstractState::exited()
+
+ This signal is emitted when the state has been exited (after onExit() has
+ been called).
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractState::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/embedded/qkbdpc101_qws.h b/src/corelib/statemachine/qabstractstate.h
index f9f0104..ee55541 100644
--- a/src/gui/embedded/qkbdpc101_qws.h
+++ b/src/corelib/statemachine/qabstractstate.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the QtGui module of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,57 +39,56 @@
**
****************************************************************************/
-#ifndef QKBDPC101_QWS_H
-#define QKBDPC101_QWS_H
+#ifndef QABSTRACTSTATE_H
+#define QABSTRACTSTATE_H
-#include <QtGui/qkbd_qws.h>
+#include <QtCore/qobject.h>
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
-QT_MODULE(Gui)
+QT_MODULE(Core)
-#ifndef QT_NO_QWS_KEYBOARD
+#ifndef QT_NO_STATEMACHINE
-#ifndef QT_NO_QWS_KBD_PC101
+class QState;
+class QStateMachine;
-struct QWSKeyMap {
- uint key_code;
- ushort unicode;
- ushort shift_unicode;
- ushort ctrl_unicode;
-};
-
-class QWSPC101KeyboardHandler : public QWSKeyboardHandler
+class QAbstractStatePrivate;
+class Q_CORE_EXPORT QAbstractState : public QObject
{
+ Q_OBJECT
public:
- explicit QWSPC101KeyboardHandler(const QString&);
- virtual ~QWSPC101KeyboardHandler();
+ ~QAbstractState();
+
+ QState *parentState() const;
+ QStateMachine *machine() const;
- virtual void doKey(uchar scancode);
- virtual const QWSKeyMap *keyMap() const;
+Q_SIGNALS:
+ void entered();
+ void exited();
protected:
- bool shift;
- bool alt;
- bool ctrl;
- bool caps;
-#if defined(QT_QWS_IPAQ)
- uint ipaq_return_pressed:1;
-#endif
- uint extended:2;
- Qt::KeyboardModifiers modifiers;
- int prevuni;
- int prevkey;
-};
+ QAbstractState(QState *parent = 0);
-#endif // QT_NO_QWS_KBD_PC101
+ virtual void onEntry(QEvent *event) = 0;
+ virtual void onExit(QEvent *event) = 0;
-#endif // QT_NO_QWS_KEYBOARD
+ bool event(QEvent *e);
+
+protected:
+ QAbstractState(QAbstractStatePrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractState)
+ Q_DECLARE_PRIVATE(QAbstractState)
+};
+
+#endif //QT_NO_STATEMACHINE
QT_END_NAMESPACE
QT_END_HEADER
-#endif // QKBDPC101_QWS_H
+#endif
diff --git a/src/corelib/statemachine/qabstractstate_p.h b/src/corelib/statemachine/qabstractstate_p.h
new file mode 100644
index 0000000..b4f3108
--- /dev/null
+++ b/src/corelib/statemachine/qabstractstate_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTSTATE_P_H
+#define QABSTRACTSTATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStateMachine;
+
+class QAbstractState;
+class QAbstractStatePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractState)
+
+public:
+ QAbstractStatePrivate();
+
+ static QAbstractStatePrivate *get(QAbstractState *q);
+
+ QStateMachine *machine() const;
+
+ void callOnEntry(QEvent *e);
+ void callOnExit(QEvent *e);
+
+ void emitEntered();
+ void emitExited();
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qabstracttransition.cpp b/src/corelib/statemachine/qabstracttransition.cpp
new file mode 100644
index 0000000..c1b553c
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition.cpp
@@ -0,0 +1,345 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qabstracttransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qabstracttransition_p.h"
+#include "qabstractstate.h"
+#include "qstate.h"
+#include "qstatemachine.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QAbstractTransition
+
+ \brief The QAbstractTransition class is the base class of transitions between QAbstractState objects.
+
+ \since 4.6
+ \ingroup statemachine
+
+ The QAbstractTransition class is the abstract base class of transitions
+ between states (QAbstractState objects) of a
+ QStateMachine. QAbstractTransition is part of \l{The State Machine
+ Framework}.
+
+ The sourceState() function returns the source of the transition. The
+ targetStates() function returns the targets of the transition. The machine()
+ function returns the state machine that the transition is part of.
+
+ Transitions can cause animations to be played. Use the addAnimation()
+ function to add an animation to the transition.
+
+ \section1 Subclassing
+
+ The eventTest() function is called by the state machine to determine whether
+ an event should trigger the transition. In your reimplementation you
+ typically check the event type and cast the event object to the proper type,
+ and check that one or more properties of the event meet your criteria.
+
+ The onTransition() function is called when the transition is triggered;
+ reimplement this function to perform custom processing for the transition.
+*/
+
+/*!
+ \property QAbstractTransition::sourceState
+
+ \brief the source state (parent) of this transition
+*/
+
+/*!
+ \property QAbstractTransition::targetState
+
+ \brief the target state of this transition
+*/
+
+/*!
+ \property QAbstractTransition::targetStates
+
+ \brief the target states of this transition
+
+ If multiple states are specified, all must be descendants of the same
+ parallel group state.
+*/
+
+QAbstractTransitionPrivate::QAbstractTransitionPrivate()
+{
+}
+
+QAbstractTransitionPrivate *QAbstractTransitionPrivate::get(QAbstractTransition *q)
+{
+ return q->d_func();
+}
+
+QStateMachine *QAbstractTransitionPrivate::machine() const
+{
+ QObject *par = parent;
+ while (par != 0) {
+ if (QStateMachine *mach = qobject_cast<QStateMachine*>(par))
+ return mach;
+ par = par->parent();
+ }
+ return 0;
+}
+
+bool QAbstractTransitionPrivate::callEventTest(QEvent *e)
+{
+ Q_Q(QAbstractTransition);
+ return q->eventTest(e);
+}
+
+void QAbstractTransitionPrivate::callOnTransition(QEvent *e)
+{
+ Q_Q(QAbstractTransition);
+ q->onTransition(e);
+}
+
+QState *QAbstractTransitionPrivate::sourceState() const
+{
+ return qobject_cast<QState*>(parent);
+}
+
+/*!
+ Constructs a new QAbstractTransition object with the given \a sourceState.
+*/
+QAbstractTransition::QAbstractTransition(QState *sourceState)
+ : QObject(*new QAbstractTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new QAbstractTransition object with the given \a targets and \a
+ sourceState.
+*/
+QAbstractTransition::QAbstractTransition(const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QObject(*new QAbstractTransitionPrivate, sourceState)
+{
+ setTargetStates(targets);
+}
+
+/*!
+ \internal
+*/
+QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
+ QState *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QAbstractTransition::QAbstractTransition(QAbstractTransitionPrivate &dd,
+ const QList<QAbstractState*> &targets,
+ QState *parent)
+ : QObject(dd, parent)
+{
+ setTargetStates(targets);
+}
+
+/*!
+ Destroys this transition.
+*/
+QAbstractTransition::~QAbstractTransition()
+{
+}
+
+/*!
+ Returns the source state of this transition, or 0 if this transition has no
+ source state.
+*/
+QState *QAbstractTransition::sourceState() const
+{
+ Q_D(const QAbstractTransition);
+ return d->sourceState();
+}
+
+/*!
+ Returns the target state of this transition, or 0 if the transition has no
+ target.
+*/
+QAbstractState *QAbstractTransition::targetState() const
+{
+ Q_D(const QAbstractTransition);
+ if (d->targetStates.isEmpty())
+ return 0;
+ return d->targetStates.first();
+}
+
+/*!
+ Sets the \a target state of this transition.
+*/
+void QAbstractTransition::setTargetState(QAbstractState* target)
+{
+ Q_D(QAbstractTransition);
+ if (!target)
+ d->targetStates.clear();
+ else
+ setTargetStates(QList<QAbstractState*>() << target);
+}
+
+/*!
+ Returns the target states of this transition, or an empty list if this
+ transition has no target states.
+*/
+QList<QAbstractState*> QAbstractTransition::targetStates() const
+{
+ Q_D(const QAbstractTransition);
+ QList<QAbstractState*> result;
+ for (int i = 0; i < d->targetStates.size(); ++i) {
+ QAbstractState *target = d->targetStates.at(i);
+ if (target)
+ result.append(target);
+ }
+ return result;
+}
+
+/*!
+ Sets the target states of this transition to be the given \a targets.
+*/
+void QAbstractTransition::setTargetStates(const QList<QAbstractState*> &targets)
+{
+ Q_D(QAbstractTransition);
+
+ for (int i=0; i<targets.size(); ++i) {
+ QAbstractState *target = targets.at(i);
+ if (!target) {
+ qWarning("QAbstractTransition::setTargetStates: target state(s) cannot be null");
+ return;
+ }
+ if (target->machine() != 0 && target->machine()->rootState() == target) {
+ qWarning("QAbstractTransition::setTargetStates: root state cannot be target of transition");
+ return;
+ }
+ }
+
+ d->targetStates.clear();
+ for (int i = 0; i < targets.size(); ++i)
+ d->targetStates.append(targets.at(i));
+}
+
+/*!
+ Returns the state machine that this transition is part of, or 0 if the
+ transition is not part of a state machine.
+*/
+QStateMachine *QAbstractTransition::machine() const
+{
+ Q_D(const QAbstractTransition);
+ return d->machine();
+}
+
+#ifndef QT_NO_ANIMATION
+
+/*!
+ Adds the given \a animation to this transition.
+ The transition does not take ownership of the animation.
+
+ \sa removeAnimation(), animations()
+*/
+void QAbstractTransition::addAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAbstractTransition);
+ if (!animation) {
+ qWarning("QAbstractTransition::addAnimation: cannot add null animation");
+ return;
+ }
+ d->animations.append(animation);
+}
+
+/*!
+ Removes the given \a animation from this transition.
+
+ \sa addAnimation()
+*/
+void QAbstractTransition::removeAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QAbstractTransition);
+ if (!animation) {
+ qWarning("QAbstractTransition::removeAnimation: cannot remove null animation");
+ return;
+ }
+ d->animations.removeOne(animation);
+}
+
+/*!
+ Returns the list of animations associated with this transition, or an empty
+ list if it has no animations.
+
+ \sa addAnimation()
+*/
+QList<QAbstractAnimation*> QAbstractTransition::animations() const
+{
+ Q_D(const QAbstractTransition);
+ return d->animations;
+}
+
+#endif
+
+/*!
+ \fn QAbstractTransition::eventTest(QEvent *event)
+
+ This function is called to determine whether the given \a event should cause
+ this transition to trigger. Reimplement this function and return true if the
+ event should trigger the transition, otherwise return false.
+*/
+
+/*!
+ \fn QAbstractTransition::onTransition(QEvent *event)
+
+ This function is called when the transition is triggered. The given \a event
+ is what caused the transition to trigger. Reimplement this function to
+ perform custom processing when the transition is triggered.
+*/
+
+/*!
+ \reimp
+*/
+bool QAbstractTransition::event(QEvent *e)
+{
+ return QObject::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
new file mode 100644
index 0000000..a1a62c9
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTTRANSITION_H
+#define QABSTRACTTRANSITION_H
+
+#include <QtCore/qobject.h>
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QEvent;
+class QAbstractState;
+class QState;
+class QStateMachine;
+
+#ifndef QT_NO_ANIMATION
+class QAbstractAnimation;
+#endif
+
+class QAbstractTransitionPrivate;
+class Q_CORE_EXPORT QAbstractTransition : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QState* sourceState READ sourceState)
+ Q_PROPERTY(QAbstractState* targetState READ targetState WRITE setTargetState)
+ Q_PROPERTY(QList<QAbstractState*> targetStates READ targetStates WRITE setTargetStates)
+public:
+ QAbstractTransition(QState *sourceState = 0);
+ QAbstractTransition(const QList<QAbstractState*> &targets, QState *sourceState = 0);
+ virtual ~QAbstractTransition();
+
+ QState *sourceState() const;
+ QAbstractState *targetState() const;
+ void setTargetState(QAbstractState* target);
+ QList<QAbstractState*> targetStates() const;
+ void setTargetStates(const QList<QAbstractState*> &targets);
+
+ QStateMachine *machine() const;
+
+#ifndef QT_NO_ANIMATION
+ void addAnimation(QAbstractAnimation *animation);
+ void removeAnimation(QAbstractAnimation *animation);
+ QList<QAbstractAnimation*> animations() const;
+#endif
+
+protected:
+ virtual bool eventTest(QEvent *event) = 0;
+
+ virtual void onTransition(QEvent *event) = 0;
+
+ bool event(QEvent *e);
+
+protected:
+ QAbstractTransition(QAbstractTransitionPrivate &dd, QState *parent);
+ QAbstractTransition(QAbstractTransitionPrivate &dd,
+ const QList<QAbstractState*> &targets, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QAbstractTransition)
+ Q_DECLARE_PRIVATE(QAbstractTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qabstracttransition_p.h b/src/corelib/statemachine/qabstracttransition_p.h
new file mode 100644
index 0000000..f067984
--- /dev/null
+++ b/src/corelib/statemachine/qabstracttransition_p.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QABSTRACTTRANSITION_P_H
+#define QABSTRACTTRANSITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qpointer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QAbstractState;
+class QState;
+class QStateMachine;
+
+class QAbstractTransition;
+class Q_CORE_EXPORT QAbstractTransitionPrivate
+ : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QAbstractTransition)
+public:
+ QAbstractTransitionPrivate();
+
+ static QAbstractTransitionPrivate *get(QAbstractTransition *q);
+
+ bool callEventTest(QEvent *e);
+ void callOnTransition(QEvent *e);
+ QState *sourceState() const;
+ QStateMachine *machine() const;
+
+ QList<QPointer<QAbstractState> > targetStates;
+
+#ifndef QT_NO_ANIMATION
+ QList<QAbstractAnimation*> animations;
+#endif
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qeventtransition.cpp b/src/corelib/statemachine/qeventtransition.cpp
new file mode 100644
index 0000000..4c40256
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition.cpp
@@ -0,0 +1,290 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qeventtransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qeventtransition_p.h"
+#include "qwrappedevent.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QEventTransition
+
+ \brief The QEventTransition class provides a QObject-specific transition for Qt events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A QEventTransition object binds an event to a particular QObject.
+ QEventTransition is part of \l{The State Machine Framework}.
+
+ Example:
+
+ \code
+ QPushButton *button = ...;
+ QState *s1 = ...;
+ QState *s2 = ...;
+ // If in s1 and the button receives an Enter event, transition to s2
+ QEventTransition *enterTransition = new QEventTransition(button, QEvent::Enter);
+ enterTransition->setTargetState(s2);
+ s1->addTransition(enterTransition);
+ // If in s2 and the button receives an Exit event, transition back to s1
+ QEventTransition *leaveTransition = new QEventTransition(button, QEvent::Leave);
+ leaveTransition->setTargetState(s1);
+ s2->addTransition(leaveTransition);
+ \endcode
+
+ \section1 Subclassing
+
+ When reimplementing the eventTest() function, you should first call the base
+ implementation to verify that the event is a QWrappedEvent for the proper
+ object and event type. You may then cast the event to a QWrappedEvent and
+ get the original event by calling QWrappedEvent::event(), and perform
+ additional checks on that object.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QEventTransition::eventObject
+
+ \brief the event source that this event transition is associated with
+*/
+
+/*!
+ \property QEventTransition::eventType
+
+ \brief the type of event that this event transition is associated with
+*/
+QEventTransitionPrivate::QEventTransitionPrivate()
+{
+ object = 0;
+ eventType = QEvent::None;
+ registered = false;
+}
+
+QEventTransitionPrivate *QEventTransitionPrivate::get(QEventTransition *q)
+{
+ return q->d_func();
+}
+
+void QEventTransitionPrivate::unregister()
+{
+ Q_Q(QEventTransition);
+ if (!registered || !machine())
+ return;
+ QStateMachinePrivate::get(machine())->unregisterEventTransition(q);
+}
+
+void QEventTransitionPrivate::maybeRegister()
+{
+ Q_Q(QEventTransition);
+ if (!machine() || !machine()->configuration().contains(sourceState()))
+ return;
+ QStateMachinePrivate::get(machine())->registerEventTransition(q);
+}
+
+/*!
+ Constructs a new QEventTransition object with the given \a sourceState.
+*/
+QEventTransition::QEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new QEventTransition object associated with events of the given
+ \a type for the given \a object, and with the given \a sourceState.
+*/
+QEventTransition::QEventTransition(QObject *object, QEvent::Type type,
+ QState *sourceState)
+ : QAbstractTransition(*new QEventTransitionPrivate, sourceState)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ Constructs a new QEventTransition object associated with events of the given
+ \a type for the given \a object. The transition has the given \a targets and
+ \a sourceState.
+*/
+QEventTransition::QEventTransition(QObject *object, QEvent::Type type,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QAbstractTransition(*new QEventTransitionPrivate, targets, sourceState)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ \internal
+*/
+QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QState *parent)
+ : QAbstractTransition(dd, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, QState *parent)
+ : QAbstractTransition(dd, parent)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ \internal
+*/
+QEventTransition::QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, const QList<QAbstractState*> &targets,
+ QState *parent)
+ : QAbstractTransition(dd, targets, parent)
+{
+ Q_D(QEventTransition);
+ d->registered = false;
+ d->object = object;
+ d->eventType = type;
+}
+
+/*!
+ Destroys this QObject event transition.
+*/
+QEventTransition::~QEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this event transition is associated with.
+*/
+QEvent::Type QEventTransition::eventType() const
+{
+ Q_D(const QEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this event transition is associated with.
+*/
+void QEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QEventTransition);
+ if (d->eventType == type)
+ return;
+ d->unregister();
+ d->eventType = type;
+ d->maybeRegister();
+}
+
+/*!
+ Returns the event source associated with this event transition.
+*/
+QObject *QEventTransition::eventObject() const
+{
+ Q_D(const QEventTransition);
+ return d->object;
+}
+
+/*!
+ Sets the event source associated with this event transition to be the given
+ \a object.
+*/
+void QEventTransition::setEventObject(QObject *object)
+{
+ Q_D(QEventTransition);
+ if (d->object == object)
+ return;
+ d->unregister();
+ d->object = object;
+ d->maybeRegister();
+}
+
+/*!
+ \reimp
+*/
+bool QEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QEventTransition);
+ if (event->type() == QEvent::Wrapped) {
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ return (we->object() == d->object)
+ && (we->event()->type() == d->eventType);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QEventTransition::onTransition(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QEventTransition::event(QEvent *e)
+{
+ return QAbstractTransition::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qeventtransition.h b/src/corelib/statemachine/qeventtransition.h
new file mode 100644
index 0000000..40ffecf
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTTRANSITION_H
+#define QEVENTTRANSITION_H
+
+#include <QtCore/qabstracttransition.h>
+#include <QtCore/qcoreevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QEventTransitionPrivate;
+class Q_CORE_EXPORT QEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject* eventObject READ eventObject WRITE setEventObject)
+ Q_PROPERTY(QEvent::Type eventType READ eventType WRITE setEventType)
+public:
+ QEventTransition(QState *sourceState = 0);
+ QEventTransition(QObject *object, QEvent::Type type, QState *sourceState = 0);
+ QEventTransition(QObject *object, QEvent::Type type,
+ const QList<QAbstractState*> &targets, QState *sourceState = 0);
+ ~QEventTransition();
+
+ QObject *eventObject() const;
+ void setEventObject(QObject *object);
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+ QEventTransition(QEventTransitionPrivate &dd, QState *parent);
+ QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, QState *parent);
+ QEventTransition(QEventTransitionPrivate &dd, QObject *object,
+ QEvent::Type type, const QList<QAbstractState*> &targets,
+ QState *parent);
+
+private:
+ Q_DISABLE_COPY(QEventTransition)
+ Q_DECLARE_PRIVATE(QEventTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qeventtransition_p.h b/src/corelib/statemachine/qeventtransition_p.h
new file mode 100644
index 0000000..ab17ad3
--- /dev/null
+++ b/src/corelib/statemachine/qeventtransition_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVENTTRANSITION_P_H
+#define QEVENTTRANSITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qabstracttransition_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEventTransition;
+class Q_CORE_EXPORT QEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QEventTransition)
+public:
+ QEventTransitionPrivate();
+
+ static QEventTransitionPrivate *get(QEventTransition *q);
+
+ void unregister();
+ void maybeRegister();
+
+ bool registered;
+ QObject *object;
+ QEvent::Type eventType;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qfinalstate.cpp b/src/corelib/statemachine/qfinalstate.cpp
new file mode 100644
index 0000000..0eb531f
--- /dev/null
+++ b/src/corelib/statemachine/qfinalstate.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qfinalstate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qabstractstate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QFinalState
+
+ \brief The QFinalState class provides a final state.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A final state is used to communicate that (part of) a QStateMachine has
+ finished its work. When a final top-level state is entered, the state
+ machine's \l{QStateMachine::finished()}{finished}() signal is emitted. In
+ general, when a final substate (a child of a QState) is entered, the parent
+ state's \l{QState::finished()}{finished}() signal is emitted. QFinalState
+ is part of \l{The State Machine Framework}.
+
+ To use a final state, you create a QFinalState object and add a transition
+ to it from another state. Example:
+
+ \code
+ QPushButton button;
+
+ QStateMachine machine;
+ QState *s1 = new QState();
+ QFinalState *s2 = new QFinalState();
+ s1->addTransition(&button, SIGNAL(clicked()), s2);
+ machine.addState(s1);
+ machine.addState(s2);
+
+ QObject::connect(&machine, SIGNAL(finished()), QApplication::instance(), SLOT(quit()));
+ machine.setInitialState(s1);
+ machine.start();
+ \endcode
+
+ \sa QStateMachine::finished(), QState::finished()
+*/
+
+class QFinalStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QFinalState)
+
+public:
+ QFinalStatePrivate();
+};
+
+QFinalStatePrivate::QFinalStatePrivate()
+{
+}
+
+/*!
+ Constructs a new QFinalState object with the given \a parent state.
+*/
+QFinalState::QFinalState(QState *parent)
+ : QAbstractState(*new QFinalStatePrivate, parent)
+{
+}
+
+/*!
+ Destroys this final state.
+*/
+QFinalState::~QFinalState()
+{
+}
+
+/*!
+ \reimp
+*/
+void QFinalState::onEntry(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+void QFinalState::onExit(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QFinalState::event(QEvent *e)
+{
+ return QAbstractState::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/plugins/kbddrivers/linuxis/linuxiskbdhandler.h b/src/corelib/statemachine/qfinalstate.h
index 3211309..865f333 100644
--- a/src/plugins/kbddrivers/linuxis/linuxiskbdhandler.h
+++ b/src/corelib/statemachine/qfinalstate.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtCore module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,42 +39,42 @@
**
****************************************************************************/
-#ifndef LINUXISKBDHANDLER_H
-#define LINUXISKBDHANDLER_H
+#ifndef QFINALSTATE_H
+#define QFINALSTATE_H
-#include <QObject>
-#include <QWSKeyboardHandler>
+#include <QtCore/qabstractstate.h>
-class QSocketNotifier;
-class LinuxInputSubsystemKbdHandler : public QObject, public QWSKeyboardHandler {
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QFinalStatePrivate;
+class Q_CORE_EXPORT QFinalState : public QAbstractState
+{
Q_OBJECT
public:
- LinuxInputSubsystemKbdHandler(const QString &device = QString("/dev/input/event0"));
- ~LinuxInputSubsystemKbdHandler();
+ QFinalState(QState *parent = 0);
+ ~QFinalState();
- struct keytable_s {
- int code;
- int unicode;
- int keycode;
- };
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
- struct keymap_s {
- int unicode;
- int keycode;
- };
+ bool event(QEvent *e);
private:
- void initmap();
+ Q_DISABLE_COPY(QFinalState)
+ Q_DECLARE_PRIVATE(QFinalState)
+};
- QSocketNotifier *m_notify;
- int kbdFD;
- bool shift;
+#endif //QT_NO_STATEMACHINE
- static struct keytable_s keytable[];
- static struct keymap_s keymap[];
+QT_END_NAMESPACE
-private Q_SLOTS:
- void readKbdData();
-};
+QT_END_HEADER
-#endif // LINUXISKBDHANDLER_H
+#endif
diff --git a/src/corelib/statemachine/qhistorystate.cpp b/src/corelib/statemachine/qhistorystate.cpp
new file mode 100644
index 0000000..4304da3
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qhistorystate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qhistorystate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QHistoryState
+
+ \brief The QHistoryState class provides a means of returning to a previously active substate.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A history state is a pseudo-state that represents the child state that the
+ parent state was in the last time the parent state was exited. A transition
+ with a history state as its target is in fact a transition to one of the
+ other child states of the parent state. QHistoryState is part of \l{The
+ State Machine Framework}.
+
+ Use the setDefaultState() function to set the state that should be entered
+ if the parent state has never been entered. Example:
+
+ \code
+ QStateMachine machine;
+
+ QState *s1 = new QState();
+ QState *s11 = new QState(s1);
+ QState *s12 = new QState(s1);
+
+ QHistoryState *s1h = new QHistoryState(s1);
+ s1h->setDefaultState(s11);
+
+ machine.addState(s1);
+
+ QState *s2 = new QState();
+ machine.addState(s2);
+
+ QPushButton *button = new QPushButton();
+ // Clicking the button will cause the state machine to enter the child state
+ // that s1 was in the last time s1 was exited, or the history state's default
+ // state if s1 has never been entered.
+ s1->addTransition(button, SIGNAL(clicked()), s1h);
+ \endcode
+
+ By default a history state is shallow, meaning that it won't remember nested
+ states. This can be configured through the historyType property.
+*/
+
+/*!
+ \property QHistoryState::defaultState
+
+ \brief the default state of this history state
+*/
+
+/*!
+ \property QHistoryState::historyType
+
+ \brief the type of history that this history state records
+
+ The default value of this property is QHistoryState::ShallowHistory.
+*/
+
+/*!
+ \enum QHistoryState::HistoryType
+
+ This enum specifies the type of history that a QHistoryState records.
+
+ \value ShallowHistory Only the immediate child states of the parent state
+ are recorded. In this case a transition with the history state as its
+ target will end up in the immediate child state that the parent was in the
+ last time it was exited. This is the default.
+
+ \value DeepHistory Nested states are recorded. In this case a transition
+ with the history state as its target will end up in the most deeply nested
+ descendant state the parent was in the last time it was exited.
+*/
+
+QHistoryStatePrivate::QHistoryStatePrivate()
+ : defaultState(0)
+{
+}
+
+QHistoryStatePrivate *QHistoryStatePrivate::get(QHistoryState *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new shallow history state with the given \a parent state.
+*/
+QHistoryState::QHistoryState(QState *parent)
+ : QAbstractState(*new QHistoryStatePrivate, parent)
+{
+ Q_D(QHistoryState);
+ d->historyType = ShallowHistory;
+}
+/*!
+ Constructs a new history state of the given \a type, with the given \a
+ parent state.
+*/
+QHistoryState::QHistoryState(HistoryType type, QState *parent)
+ : QAbstractState(*new QHistoryStatePrivate, parent)
+{
+ Q_D(QHistoryState);
+ d->historyType = type;
+}
+
+/*!
+ Destroys this history state.
+*/
+QHistoryState::~QHistoryState()
+{
+}
+
+/*!
+ Returns this history state's default state. The default state indicates the
+ state to transition to if the parent state has never been entered before.
+*/
+QAbstractState *QHistoryState::defaultState() const
+{
+ Q_D(const QHistoryState);
+ return d->defaultState;
+}
+
+/*!
+ Sets this history state's default state to be the given \a state.
+ \a state must be a sibling of this history state.
+*/
+void QHistoryState::setDefaultState(QAbstractState *state)
+{
+ Q_D(QHistoryState);
+ if (state && state->parentState() != parentState()) {
+ qWarning("QHistoryState::setDefaultState: state %p does not belong "
+ "to this history state's group (%p)", state, parentState());
+ return;
+ }
+ d->defaultState = state;
+}
+
+/*!
+ Returns the type of history that this history state records.
+*/
+QHistoryState::HistoryType QHistoryState::historyType() const
+{
+ Q_D(const QHistoryState);
+ return d->historyType;
+}
+
+/*!
+ Sets the \a type of history that this history state records.
+*/
+void QHistoryState::setHistoryType(HistoryType type)
+{
+ Q_D(QHistoryState);
+ d->historyType = type;
+}
+
+/*!
+ \reimp
+*/
+void QHistoryState::onEntry(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+void QHistoryState::onExit(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QHistoryState::event(QEvent *e)
+{
+ return QAbstractState::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
new file mode 100644
index 0000000..eee43d1
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHISTORYSTATE_H
+#define QHISTORYSTATE_H
+
+#include <QtCore/qabstractstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QHistoryStatePrivate;
+class Q_CORE_EXPORT QHistoryState : public QAbstractState
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractState* defaultState READ defaultState WRITE setDefaultState)
+ Q_PROPERTY(HistoryType historyType READ historyType WRITE setHistoryType)
+ Q_ENUMS(HistoryType)
+public:
+ enum HistoryType {
+ ShallowHistory,
+ DeepHistory
+ };
+
+ QHistoryState(QState *parent = 0);
+ QHistoryState(HistoryType type, QState *parent = 0);
+ ~QHistoryState();
+
+ QAbstractState *defaultState() const;
+ void setDefaultState(QAbstractState *state);
+
+ HistoryType historyType() const;
+ void setHistoryType(HistoryType type);
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QHistoryState)
+ Q_DECLARE_PRIVATE(QHistoryState)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qhistorystate_p.h b/src/corelib/statemachine/qhistorystate_p.h
new file mode 100644
index 0000000..875dac8
--- /dev/null
+++ b/src/corelib/statemachine/qhistorystate_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QHISTORYSTATE_P_H
+#define QHISTORYSTATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qabstractstate_p.h"
+
+#include <QtCore/qlist.h>
+
+QT_BEGIN_NAMESPACE
+
+class QHistoryState;
+class QHistoryStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QHistoryState)
+
+public:
+ QHistoryStatePrivate();
+
+ static QHistoryStatePrivate *get(QHistoryState *q);
+
+ QAbstractState *defaultState;
+ QHistoryState::HistoryType historyType;
+ QList<QAbstractState*> configuration;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qsignalevent.h b/src/corelib/statemachine/qsignalevent.h
new file mode 100644
index 0000000..79d1053
--- /dev/null
+++ b/src/corelib/statemachine/qsignalevent.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALEVENT_H
+#define QSIGNALEVENT_H
+
+#include <QtCore/qcoreevent.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class Q_CORE_EXPORT QSignalEvent : public QEvent
+{
+public:
+ QSignalEvent(const QObject *sender, int signalIndex,
+ const QList<QVariant> &arguments);
+ ~QSignalEvent();
+
+ inline const QObject *sender() const { return m_sender; }
+ inline int signalIndex() const { return m_signalIndex; }
+ inline QList<QVariant> arguments() const { return m_arguments; }
+
+private:
+ const QObject *m_sender;
+ int m_signalIndex;
+ QList<QVariant> m_arguments;
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qsignaleventgenerator_p.h b/src/corelib/statemachine/qsignaleventgenerator_p.h
new file mode 100644
index 0000000..cf0ea1e
--- /dev/null
+++ b/src/corelib/statemachine/qsignaleventgenerator_p.h
@@ -0,0 +1,78 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALEVENTGENERATOR_P_H
+#define QSIGNALEVENTGENERATOR_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QStateMachine;
+
+class QSignalEventGenerator : public QObject
+{
+public:
+ QSignalEventGenerator(QStateMachine *parent);
+
+ static const QMetaObject staticMetaObject;
+ virtual const QMetaObject *metaObject() const;
+ virtual void *qt_metacast(const char *);
+ virtual int qt_metacall(QMetaObject::Call, int, void **argv);
+
+private:
+ Q_DISABLE_COPY(QSignalEventGenerator)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qsignaltransition.cpp b/src/corelib/statemachine/qsignaltransition.cpp
new file mode 100644
index 0000000..2e150a7
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition.cpp
@@ -0,0 +1,265 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsignaltransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qsignaltransition_p.h"
+#include "qsignalevent.h"
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QSignalTransition
+
+ \brief The QSignalTransition class provides a transition based on a Qt signal.
+
+ \since 4.6
+ \ingroup statemachine
+
+ Typically you would use the overload of QState::addTransition() that takes a
+ sender and signal as arguments, rather than creating QSignalTransition
+ objects directly. QSignalTransition is part of \l{The State Machine
+ Framework}.
+
+ You can subclass QSignalTransition and reimplement eventTest() to make a
+ signal transition conditional; the event object passed to eventTest() will
+ be a QSignalEvent object. Example:
+
+ \code
+ class CheckedTransition : public QSignalTransition
+ {
+ public:
+ CheckedTransition(QCheckBox *check)
+ : QSignalTransition(check, SIGNAL(stateChanged(int))) {}
+ protected:
+ bool eventTest(QEvent *e) const {
+ if (!QSignalTransition::eventTest(e))
+ return false;
+ QSignalEvent *se = static_cast<QSignalEvent*>(e);
+ return (se->arguments().at(0).toInt() == Qt::Checked);
+ }
+ };
+
+ ...
+
+ QCheckBox *check = new QCheckBox();
+ check->setTristate(true);
+
+ QState *s1 = new QState();
+ QState *s2 = new QState();
+ CheckedTransition *t1 = new CheckedTransition(check);
+ t1->setTargetState(s2);
+ s1->addTransition(t1);
+ \endcode
+*/
+
+/*!
+ \property QSignalTransition::senderObject
+
+ \brief the sender object that this signal transition is associated with
+*/
+
+/*!
+ \property QSignalTransition::signal
+
+ \brief the signal that this signal transition is associated with
+*/
+
+QSignalTransitionPrivate::QSignalTransitionPrivate()
+{
+ sender = 0;
+ signalIndex = -1;
+}
+
+QSignalTransitionPrivate *QSignalTransitionPrivate::get(QSignalTransition *q)
+{
+ return q->d_func();
+}
+
+void QSignalTransitionPrivate::unregister()
+{
+ Q_Q(QSignalTransition);
+ if ((signalIndex == -1) || !machine())
+ return;
+ QStateMachinePrivate::get(machine())->unregisterSignalTransition(q);
+}
+
+void QSignalTransitionPrivate::maybeRegister()
+{
+ Q_Q(QSignalTransition);
+ if (!machine() || !machine()->configuration().contains(sourceState()))
+ return;
+ QStateMachinePrivate::get(machine())->registerSignalTransition(q);
+}
+
+/*!
+ Constructs a new signal transition with the given \a sourceState.
+*/
+QSignalTransition::QSignalTransition(QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new signal transition associated with the given \a signal of
+ the given \a sender, and with the given \a sourceState.
+*/
+QSignalTransition::QSignalTransition(QObject *sender, const char *signal,
+ QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, sourceState)
+{
+ Q_D(QSignalTransition);
+ d->sender = sender;
+ d->signal = signal;
+}
+
+/*!
+ Constructs a new signal transition associated with the given \a signal of
+ the given \a sender. The transition has the given \a targets and \a
+ sourceState.
+*/
+QSignalTransition::QSignalTransition(QObject *sender, const char *signal,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QAbstractTransition(*new QSignalTransitionPrivate, targets, sourceState)
+{
+ Q_D(QSignalTransition);
+ d->sender = sender;
+ d->signal = signal;
+}
+
+/*!
+ Destroys this signal transition.
+*/
+QSignalTransition::~QSignalTransition()
+{
+}
+
+/*!
+ Returns the sender object associated with this signal transition.
+*/
+QObject *QSignalTransition::senderObject() const
+{
+ Q_D(const QSignalTransition);
+ return d->sender;
+}
+
+/*!
+ Sets the \a sender object associated with this signal transition.
+*/
+void QSignalTransition::setSenderObject(QObject *sender)
+{
+ Q_D(QSignalTransition);
+ if (sender == d->sender)
+ return;
+ d->unregister();
+ d->sender = sender;
+ d->maybeRegister();
+}
+
+/*!
+ Returns the signal associated with this signal transition.
+*/
+QByteArray QSignalTransition::signal() const
+{
+ Q_D(const QSignalTransition);
+ return d->signal;
+}
+
+/*!
+ Sets the \a signal associated with this signal transition.
+*/
+void QSignalTransition::setSignal(const QByteArray &signal)
+{
+ Q_D(QSignalTransition);
+ if (signal == d->signal)
+ return;
+ d->unregister();
+ d->signal = signal;
+ d->maybeRegister();
+}
+
+/*!
+ \reimp
+
+ The \a event is a QSignalEvent object. The default implementation returns
+ true if the event's sender and signal index match this transition, and
+ returns false otherwise.
+*/
+bool QSignalTransition::eventTest(QEvent *event)
+{
+ Q_D(const QSignalTransition);
+ if (event->type() == QEvent::Signal) {
+ if (d->signalIndex == -1)
+ return false;
+ QSignalEvent *se = static_cast<QSignalEvent*>(event);
+ return (se->sender() == d->sender)
+ && (se->signalIndex() == d->signalIndex);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QSignalTransition::onTransition(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+bool QSignalTransition::event(QEvent *e)
+{
+ return QAbstractTransition::event(e);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
new file mode 100644
index 0000000..02b1de9
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALTRANSITION_H
+#define QSIGNALTRANSITION_H
+
+#include <QtCore/qabstracttransition.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QSignalTransitionPrivate;
+class Q_CORE_EXPORT QSignalTransition : public QAbstractTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(QObject* senderObject READ senderObject WRITE setSenderObject)
+ Q_PROPERTY(QByteArray signal READ signal WRITE setSignal)
+public:
+ QSignalTransition(QState *sourceState = 0);
+ QSignalTransition(QObject *sender, const char *signal,
+ QState *sourceState = 0);
+ QSignalTransition(QObject *sender, const char *signal,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState = 0);
+ ~QSignalTransition();
+
+ QObject *senderObject() const;
+ void setSenderObject(QObject *sender);
+
+ QByteArray signal() const;
+ void setSignal(const QByteArray &signal);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *event);
+
+ bool event(QEvent *e);
+
+private:
+ Q_DISABLE_COPY(QSignalTransition)
+ Q_DECLARE_PRIVATE(QSignalTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qsignaltransition_p.h b/src/corelib/statemachine/qsignaltransition_p.h
new file mode 100644
index 0000000..aacb6fc
--- /dev/null
+++ b/src/corelib/statemachine/qsignaltransition_p.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSIGNALTRANSITION_P_H
+#define QSIGNALTRANSITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qabstracttransition_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QSignalTransition;
+class QSignalTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QSignalTransition)
+public:
+ QSignalTransitionPrivate();
+
+ static QSignalTransitionPrivate *get(QSignalTransition *q);
+
+ void unregister();
+ void maybeRegister();
+
+ QObject *sender;
+ QByteArray signal;
+ int signalIndex;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qstate.cpp b/src/corelib/statemachine/qstate.cpp
new file mode 100644
index 0000000..5dd56c0
--- /dev/null
+++ b/src/corelib/statemachine/qstate.cpp
@@ -0,0 +1,489 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstate.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qstate_p.h"
+#include "qhistorystate.h"
+#include "qhistorystate_p.h"
+#include "qabstracttransition.h"
+#include "qabstracttransition_p.h"
+#include "qsignaltransition.h"
+#include "qstatemachine.h"
+#include "qstatemachine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QState
+
+ \brief The QState class provides a general-purpose state for QStateMachine.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QState objects can have child states, and can have transitions to other
+ states. QState is part of \l{The State Machine Framework}.
+
+ The addTransition() function adds a transition. The removeTransition()
+ function removes a transition.
+
+ The assignProperty() function is used for defining property assignments that
+ should be performed when a state is entered.
+
+ Top-level states must be passed QStateMachine::rootState() as their parent
+ state, or added to a state machine using QStateMachine::addState().
+
+ \section1 States with Child States
+
+ The childMode property determines how child states are treated. For
+ non-parallel state groups, the setInitialState() function must be called to
+ set the initial state. The child states are mutually exclusive states, and
+ the state machine needs to know which child state to enter when the parent
+ state is the target of a transition.
+
+ The state emits the QState::finished() signal when a final child state
+ (QFinalState) is entered.
+
+ The setErrorState() sets the state's error state. The error state is the
+ state that the state machine will transition to if an error is detected when
+ attempting to enter the state (e.g. because no initial state has been set).
+
+*/
+
+/*!
+ \property QState::initialState
+
+ \brief the initial state of this state (one of its child states)
+*/
+
+/*!
+ \property QState::errorState
+
+ \brief the error state of this state
+*/
+
+/*!
+ \property QState::childMode
+
+ \brief the child mode of this state
+
+ The default value of this property is QState::ExclusiveStates.
+*/
+
+/*!
+ \enum QState::ChildMode
+
+ This enum specifies how a state's child states are treated.
+
+ \value ExclusiveStates The child states are mutually exclusive and an
+ initial state must be set by calling QState::setInitialState().
+
+ \value ParallelStates The child states are parallel. When the parent state
+ is entered, all its child states are entered in parallel.
+*/
+
+QStatePrivate::QStatePrivate()
+ : errorState(0), initialState(0), childMode(QState::ExclusiveStates)
+{
+}
+
+QStatePrivate::~QStatePrivate()
+{
+}
+
+void QStatePrivate::emitFinished()
+{
+ Q_Q(QState);
+ emit q->finished();
+}
+
+void QStatePrivate::emitPolished()
+{
+ Q_Q(QState);
+ emit q->polished();
+}
+
+/*!
+ Constructs a new state with the given \a parent state.
+*/
+QState::QState(QState *parent)
+ : QAbstractState(*new QStatePrivate, parent)
+{
+}
+
+/*!
+ Constructs a new state with the given \a childMode and the given \a parent
+ state.
+*/
+QState::QState(ChildMode childMode, QState *parent)
+ : QAbstractState(*new QStatePrivate, parent)
+{
+ Q_D(QState);
+ d->childMode = childMode;
+}
+
+/*!
+ \internal
+*/
+QState::QState(QStatePrivate &dd, QState *parent)
+ : QAbstractState(dd, parent)
+{
+}
+
+/*!
+ Destroys this state.
+*/
+QState::~QState()
+{
+}
+
+QList<QAbstractState*> QStatePrivate::childStates() const
+{
+ QList<QAbstractState*> result;
+ QList<QObject*>::const_iterator it;
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
+ QAbstractState *s = qobject_cast<QAbstractState*>(*it);
+ if (!s || qobject_cast<QHistoryState*>(s))
+ continue;
+ result.append(s);
+ }
+ return result;
+}
+
+QList<QHistoryState*> QStatePrivate::historyStates() const
+{
+ QList<QHistoryState*> result;
+ QList<QObject*>::const_iterator it;
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
+ QHistoryState *h = qobject_cast<QHistoryState*>(*it);
+ if (h)
+ result.append(h);
+ }
+ return result;
+}
+
+QList<QAbstractTransition*> QStatePrivate::transitions() const
+{
+ QList<QAbstractTransition*> result;
+ QList<QObject*>::const_iterator it;
+ for (it = children.constBegin(); it != children.constEnd(); ++it) {
+ QAbstractTransition *t = qobject_cast<QAbstractTransition*>(*it);
+ if (t)
+ result.append(t);
+ }
+ return result;
+}
+
+/*!
+ Instructs this state to set the property with the given \a name of the given
+ \a object to the given \a value when the state is entered.
+
+ \sa polished()
+*/
+void QState::assignProperty(QObject *object, const char *name,
+ const QVariant &value)
+{
+ Q_D(QState);
+ if (!object) {
+ qWarning("QState::assignProperty: cannot assign property '%s' of null object", name);
+ return;
+ }
+ for (int i = 0; i < d->propertyAssignments.size(); ++i) {
+ QPropertyAssignment &assn = d->propertyAssignments[i];
+ if ((assn.object == object) && (assn.propertyName == name)) {
+ assn.value = value;
+ return;
+ }
+ }
+ d->propertyAssignments.append(QPropertyAssignment(object, name, value));
+}
+
+/*!
+ Returns this state group's error state.
+
+ \sa QStateMachine::errorState(), QStateMachine::setErrorState()
+*/
+QAbstractState *QState::errorState() const
+{
+ Q_D(const QState);
+ return d->errorState;
+}
+
+/*!
+ Sets this state's error state to be the given \a state. If the error state
+ is not set, or if it is set to 0, the state will inherit its parent's error
+ state recursively.
+
+ \sa QStateMachine::setErrorState(), QStateMachine::errorState()
+*/
+void QState::setErrorState(QAbstractState *state)
+{
+ Q_D(QState);
+ if (state != 0 && state->machine() != machine()) {
+ qWarning("QState::setErrorState: error state cannot belong "
+ "to a different state machine");
+ return;
+ }
+ if (state != 0 && state->machine() != 0 && state->machine()->rootState() == state) {
+ qWarning("QStateMachine::setErrorState: root state cannot be error state");
+ return;
+ }
+
+ d->errorState = state;
+}
+
+/*!
+ Adds the given \a transition. The transition has this state as the source.
+ This state takes ownership of the transition. If the transition is successfully
+ added, the function will return the \a transition pointer. Otherwise it will return null.
+*/
+QAbstractTransition *QState::addTransition(QAbstractTransition *transition)
+{
+ Q_D(QState);
+ if (!transition) {
+ qWarning("QState::addTransition: cannot add null transition");
+ return 0;
+ }
+
+ // machine() will always be non-null for root state
+ if (machine() != 0 && machine()->rootState() == this) {
+ qWarning("QState::addTransition: cannot add transition from root state");
+ return 0;
+ }
+
+ const QList<QPointer<QAbstractState> > &targets = QAbstractTransitionPrivate::get(transition)->targetStates;
+ for (int i = 0; i < targets.size(); ++i) {
+ QAbstractState *t = targets.at(i);
+ if (!t) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
+ if ((QAbstractStatePrivate::get(t)->machine() != d->machine())
+ && QAbstractStatePrivate::get(t)->machine() && d->machine()) {
+ qWarning("QState::addTransition: cannot add transition "
+ "to a state in a different state machine");
+ return 0;
+ }
+ }
+ transition->setParent(this);
+ if (machine() != 0 && machine()->configuration().contains(this))
+ QStateMachinePrivate::get(machine())->registerTransitions(this);
+ return transition;
+}
+
+/*!
+ Adds a transition associated with the given \a signal of the given \a sender
+ object, and returns the new QSignalTransition object. The transition has
+ this state as the source, and the given \a target as the target state.
+*/
+QSignalTransition *QState::addTransition(QObject *sender, const char *signal,
+ QAbstractState *target)
+{
+ if (!sender) {
+ qWarning("QState::addTransition: sender cannot be null");
+ return 0;
+ }
+ if (!signal) {
+ qWarning("QState::addTransition: signal cannot be null");
+ return 0;
+ }
+ if (!target) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
+ int offset = (*signal == '0'+QSIGNAL_CODE) ? 1 : 0;
+ if (sender->metaObject()->indexOfSignal(signal+offset) == -1) {
+ qWarning("QState::addTransition: no such signal %s::%s",
+ sender->metaObject()->className(), signal+offset);
+ return 0;
+ }
+ QSignalTransition *trans = new QSignalTransition(sender, signal, QList<QAbstractState*>() << target);
+ addTransition(trans);
+ return trans;
+}
+
+namespace {
+
+// ### Make public?
+class UnconditionalTransition : public QAbstractTransition
+{
+public:
+ UnconditionalTransition(QAbstractState *target)
+ : QAbstractTransition(QList<QAbstractState*>() << target) {}
+protected:
+ void onTransition(QEvent *) {}
+ bool eventTest(QEvent *) { return true; }
+};
+
+} // namespace
+
+/*!
+ Adds an unconditional transition from this state to the given \a target
+ state, and returns then new transition object.
+*/
+QAbstractTransition *QState::addTransition(QAbstractState *target)
+{
+ if (!target) {
+ qWarning("QState::addTransition: cannot add transition to null state");
+ return 0;
+ }
+ UnconditionalTransition *trans = new UnconditionalTransition(target);
+ return addTransition(trans);
+}
+
+/*!
+ Removes the given \a transition from this state. The state releases
+ ownership of the transition.
+
+ \sa addTransition()
+*/
+void QState::removeTransition(QAbstractTransition *transition)
+{
+ Q_D(QState);
+ if (!transition) {
+ qWarning("QState::removeTransition: cannot remove null transition");
+ return;
+ }
+ if (transition->sourceState() != this) {
+ qWarning("QState::removeTransition: transition %p's source state (%p)"
+ " is different from this state (%p)",
+ transition, transition->sourceState(), this);
+ return;
+ }
+ QStateMachinePrivate *mach = QStateMachinePrivate::get(d->machine());
+ if (mach)
+ mach->unregisterTransition(transition);
+ transition->setParent(0);
+}
+
+/*!
+ \reimp
+*/
+void QState::onEntry(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \reimp
+*/
+void QState::onExit(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ Returns this state's initial state, or 0 if the state has no initial state.
+*/
+QAbstractState *QState::initialState() const
+{
+ Q_D(const QState);
+ return d->initialState;
+}
+
+/*!
+ Sets this state's initial state to be the given \a state.
+ \a state has to be a child of this state.
+*/
+void QState::setInitialState(QAbstractState *state)
+{
+ Q_D(QState);
+ if (d->childMode == QState::ParallelStates) {
+ qWarning("QState::setInitialState: ignoring attempt to set initial state "
+ "of parallel state group %p", this);
+ return;
+ }
+ if (state && (state->parentState() != this)) {
+ qWarning("QState::setInitialState: state %p is not a child of this state (%p)",
+ state, this);
+ return;
+ }
+ d->initialState = state;
+}
+
+/*!
+ Returns the child mode of this state.
+*/
+QState::ChildMode QState::childMode() const
+{
+ Q_D(const QState);
+ return d->childMode;
+}
+
+/*!
+ Sets the child \a mode of this state.
+*/
+void QState::setChildMode(ChildMode mode)
+{
+ Q_D(QState);
+ d->childMode = mode;
+}
+
+/*!
+ \reimp
+*/
+bool QState::event(QEvent *e)
+{
+ return QAbstractState::event(e);
+}
+
+/*!
+ \fn QState::finished()
+
+ This signal is emitted when a final child state of this state is entered.
+
+ \sa QFinalState
+*/
+
+/*!
+ \fn QState::polished()
+
+ This signal is emitted when all properties have been assigned their final value.
+
+ \sa QState::assignProperty(), QAbstractTransition::addAnimation()
+*/
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
new file mode 100644
index 0000000..c98bb64
--- /dev/null
+++ b/src/corelib/statemachine/qstate.h
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATE_H
+#define QSTATE_H
+
+#include <QtCore/qabstractstate.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QAbstractTransition;
+class QSignalTransition;
+
+class QStatePrivate;
+class Q_CORE_EXPORT QState : public QAbstractState
+{
+ Q_OBJECT
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
+ Q_PROPERTY(ChildMode childMode READ childMode WRITE setChildMode)
+ Q_ENUMS(ChildMode)
+public:
+ enum ChildMode {
+ ExclusiveStates,
+ ParallelStates
+ };
+
+ QState(QState *parent = 0);
+ QState(ChildMode childMode, QState *parent = 0);
+ ~QState();
+
+ QAbstractState *errorState() const;
+ void setErrorState(QAbstractState *state);
+
+ QAbstractTransition *addTransition(QAbstractTransition *transition);
+ QSignalTransition *addTransition(QObject *sender, const char *signal, QAbstractState *target);
+ QAbstractTransition *addTransition(QAbstractState *target);
+ void removeTransition(QAbstractTransition *transition);
+
+ QAbstractState *initialState() const;
+ void setInitialState(QAbstractState *state);
+
+ ChildMode childMode() const;
+ void setChildMode(ChildMode mode);
+
+ void assignProperty(QObject *object, const char *name,
+ const QVariant &value);
+
+Q_SIGNALS:
+ void finished();
+ void polished();
+
+protected:
+ void onEntry(QEvent *event);
+ void onExit(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+ QState(QStatePrivate &dd, QState *parent);
+
+private:
+ Q_DISABLE_COPY(QState)
+ Q_DECLARE_PRIVATE(QState)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qstate_p.h b/src/corelib/statemachine/qstate_p.h
new file mode 100644
index 0000000..eddd831
--- /dev/null
+++ b/src/corelib/statemachine/qstate_p.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATE_P_H
+#define QSTATE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qabstractstate_p.h"
+
+#include <QtCore/qlist.h>
+#include <QtCore/qbytearray.h>
+#include <QtCore/qvariant.h>
+
+QT_BEGIN_NAMESPACE
+
+struct QPropertyAssignment
+{
+ QPropertyAssignment()
+ : object(0) {}
+ QPropertyAssignment(QObject *o, const QByteArray &n,
+ const QVariant &v, bool es = true)
+ : object(o), propertyName(n), value(v), explicitlySet(es)
+ {}
+ QObject *object;
+ QByteArray propertyName;
+ QVariant value;
+ bool explicitlySet;
+};
+
+class QAbstractTransition;
+class QHistoryState;
+
+class QState;
+class Q_AUTOTEST_EXPORT QStatePrivate : public QAbstractStatePrivate
+{
+ Q_DECLARE_PUBLIC(QState)
+public:
+ QStatePrivate();
+ ~QStatePrivate();
+
+ static QStatePrivate *get(QState *q) { return q ? q->d_func() : 0; }
+ static const QStatePrivate *get(const QState *q) { return q? q->d_func() : 0; }
+
+ QList<QAbstractState*> childStates() const;
+ QList<QHistoryState*> historyStates() const;
+ QList<QAbstractTransition*> transitions() const;
+
+ void emitFinished();
+ void emitPolished();
+
+ QAbstractState *errorState;
+ QAbstractState *initialState;
+ QState::ChildMode childMode;
+
+ QList<QPropertyAssignment> propertyAssignments;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
new file mode 100644
index 0000000..64b33ac
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -0,0 +1,2214 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstatemachine.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qstate.h"
+#include "qstate_p.h"
+#include "qstatemachine_p.h"
+#include "qabstracttransition.h"
+#include "qabstracttransition_p.h"
+#include "qsignaltransition.h"
+#include "qsignaltransition_p.h"
+#include "qsignalevent.h"
+#include "qsignaleventgenerator_p.h"
+#include "qabstractstate.h"
+#include "qabstractstate_p.h"
+#include "qfinalstate.h"
+#include "qhistorystate.h"
+#include "qhistorystate_p.h"
+#include "private/qobject_p.h"
+#include "private/qthread_p.h"
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+#include "qeventtransition.h"
+#include "qeventtransition_p.h"
+#include "qwrappedevent.h"
+#endif
+
+#ifndef QT_NO_ANIMATION
+#include "qpropertyanimation.h"
+#include "qanimationgroup.h"
+#include <private/qvariantanimation_p.h>
+#endif
+
+#include <QtCore/qmetaobject.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QStateMachine
+ \reentrant
+
+ \brief The QStateMachine class provides a hierarchical finite state machine.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QStateMachine is based on the concepts and notation of
+ \l{Statecharts: A visual formalism for complex
+ systems}{Statecharts}. QStateMachine is part of \l{The State
+ Machine Framework}.
+
+ A state machine manages a set of states (classes that inherit from
+ QAbstractState) and transitions (descendants of
+ QAbstractTransition) between those states; these states and
+ transitions define a state graph. Once a state graph has been
+ built, the state machine can execute it. QStateMachine's
+ execution algorithm is based on the \l{State Chart XML: State
+ Machine Notation for Control Abstraction}{State Chart XML (SCXML)}
+ algorithm. The framework's \l{The State Machine
+ Framework}{overview} gives several state graphs and the code to
+ build them.
+
+ The rootState() is the parent of all top-level states in the
+ machine; it is used, for instance, when the state graph is
+ deleted. It is created by the machine.
+
+ Use the addState() function to add a state to the state machine.
+ All top-level states are added to the root state. States are
+ removed with the removeState() function. Removing states while the
+ machine is running is discouraged.
+
+ Before the machine can be started, the \l{initialState}{initial
+ state} must be set. The initial state is the state that the
+ machine enters when started. You can then start() the state
+ machine. The started() signal is emitted when the initial state is
+ entered.
+
+ The machine is event driven and keeps its own event loop. Events
+ are posted to the machine through postEvent(). Note that this
+ means that it executes asynchronously, and that it will not
+ progress without a running event loop. You will normally not have
+ to post events to the machine directly as Qt's transitions, e.g.,
+ QEventTransition and its subclasses, handle this. But for custom
+ transitions triggered by events, postEvent() is useful.
+
+ The state machine processes events and takes transitions until a
+ top-level final state is entered; the state machine then emits the
+ finished() signal. You can also stop() the state machine
+ explicitly. The stopped() signal is emitted in this case.
+
+ The following snippet shows a state machine that will finish when a button
+ is clicked:
+
+ \code
+ QPushButton button;
+
+ QStateMachine machine;
+ QState *s1 = new QState();
+ s1->assignProperty(&button, "text", "Click me");
+
+ QFinalState *s2 = new QFinalState();
+ s1->addTransition(&button, SIGNAL(clicked()), s2);
+
+ machine.addState(s1);
+ machine.addState(s2);
+ machine.setInitialState(s1);
+ machine.start();
+ \endcode
+
+ This code example uses QState, which inherits QAbstractState. The
+ QState class provides a state that you can use to set properties
+ and invoke methods on \l{QObject}s when the state is entered or
+ exited. It also contains convenience functions for adding
+ transitions, e.g., \l{QSignalTransition}s as in this example. See
+ the QState class description for further details.
+
+ If an error is encountered, the machine will enter the
+ \l{errorState}{error state}, which is a special state created by
+ the machine. The types of errors possible are described by the
+ \l{QStateMachine::}{Error} enum. After the error state is entered,
+ the type of the error can be retrieved with error(). The execution
+ of the state graph will not stop when the error state is entered.
+ So it is possible to handle the error, for instance, by connecting
+ to the \l{QAbstractState::}{entered()} signal of the error state.
+ It is also possible to set a custom error state with
+ setErrorState().
+
+ \omit This stuff will be moved elsewhere
+This is
+ typically used in conjunction with \l{Signals and Slots}{signals}; the
+ signals determine the flow of the state graph, whereas the states' property
+ assignments and method invocations are the actions.
+
+ The postEvent() function posts an event to the state machine. This is useful
+ when you are using custom events to trigger transitions.
+ \endomit
+
+ \sa QAbstractState, QAbstractTransition, QState, {The State Machine Framework}
+*/
+
+/*!
+ \property QStateMachine::rootState
+
+ \brief the root state of this state machine
+*/
+
+/*!
+ \property QStateMachine::initialState
+
+ \brief the initial state of this state machine
+
+ The initial state must be one of the rootState()'s child states.
+*/
+
+/*!
+ \property QStateMachine::errorState
+
+ \brief the error state of this state machine
+*/
+
+/*!
+ \property QStateMachine::errorString
+
+ \brief the error string of this state machine
+*/
+
+/*!
+ \property QStateMachine::globalRestorePolicy
+
+ \brief the restore policy for states of this state machine.
+
+ The default value of this property is
+ QStateMachine::DoNotRestoreProperties.
+*/
+
+#ifndef QT_NO_ANIMATION
+/*!
+ \property QStateMachine::animationsEnabled
+
+ \brief whether animations are enabled
+
+ The default value of this property is true.
+
+ \sa QAbstractTransition::addAnimation()
+*/
+#endif
+
+// #define QSTATEMACHINE_DEBUG
+
+QStateMachinePrivate::QStateMachinePrivate()
+{
+ state = NotRunning;
+ processing = false;
+ processingScheduled = false;
+ stop = false;
+ error = QStateMachine::NoError;
+ globalRestorePolicy = QStateMachine::DoNotRestoreProperties;
+ rootState = 0;
+ initialErrorStateForRoot = 0;
+ signalEventGenerator = 0;
+#ifndef QT_NO_ANIMATION
+ animationsEnabled = true;
+#endif
+}
+
+QStateMachinePrivate::~QStateMachinePrivate()
+{
+ qDeleteAll(internalEventQueue);
+ qDeleteAll(externalEventQueue);
+}
+
+QStateMachinePrivate *QStateMachinePrivate::get(QStateMachine *q)
+{
+ if (q)
+ return q->d_func();
+ return 0;
+}
+
+static QEvent *cloneEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::None:
+ return new QEvent(*e);
+ case QEvent::Timer:
+ return new QTimerEvent(*static_cast<QTimerEvent*>(e));
+ default:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ }
+ return 0;
+}
+
+const QStateMachinePrivate::Handler qt_kernel_statemachine_handler = {
+ cloneEvent
+};
+
+const QStateMachinePrivate::Handler *QStateMachinePrivate::handler = &qt_kernel_statemachine_handler;
+
+Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler()
+{
+ return &qt_kernel_statemachine_handler;
+}
+
+static int indexOfDescendant(QState *s, QAbstractState *desc)
+{
+ QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates();
+ for (int i = 0; i < childStates.size(); ++i) {
+ QAbstractState *c = childStates.at(i);
+ if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
+{
+ if (s1->parent() == s2->parent()) {
+ return s1->children().indexOf(s1)
+ < s2->children().indexOf(s2);
+ } else if (isDescendantOf(s1, s2)) {
+ return false;
+ } else if (isDescendantOf(s2, s1)) {
+ return true;
+ } else {
+ QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2);
+ Q_ASSERT(lca != 0);
+ return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+ }
+}
+
+bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState *s2)
+{
+ if (s1->parent() == s2->parent()) {
+ return s1->children().indexOf(s1)
+ < s2->children().indexOf(s2);
+ } else if (isDescendantOf(s1, s2)) {
+ return true;
+ } else if (isDescendantOf(s2, s1)) {
+ return false;
+ } else {
+ QState *lca = findLCA(QList<QAbstractState*>() << s1 << s2);
+ Q_ASSERT(lca != 0);
+ return (indexOfDescendant(lca, s1) < indexOfDescendant(lca, s2));
+ }
+}
+
+QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states)
+{
+ if (states.isEmpty())
+ return 0;
+ QList<QState*> ancestors = properAncestors(states.at(0), 0);
+ for (int i = 0; i < ancestors.size(); ++i) {
+ QState *anc = ancestors.at(i);
+ bool ok = true;
+ for (int j = states.size() - 1; (j > 0) && ok; --j) {
+ const QAbstractState *s = states.at(j);
+ if (!isDescendantOf(s, anc))
+ ok = false;
+ }
+ if (ok)
+ return anc;
+ }
+ return 0;
+}
+
+bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const
+{
+ QSet<QAbstractTransition*>::const_iterator it;
+ for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) {
+ QAbstractTransition *t = *it;
+ QList<QAbstractState*> lst = t->targetStates();
+ if (!lst.isEmpty()) {
+ lst.prepend(t->sourceState());
+ QAbstractState *lca = findLCA(lst);
+ if (isDescendantOf(s, lca)) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from"
+ << s << "because" << s << "is a descendant of" << lca;
+#endif
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) const
+{
+ Q_Q(const QStateMachine);
+ QSet<QAbstractTransition*> enabledTransitions;
+ QSet<QAbstractState*>::const_iterator it;
+ const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *state = *it;
+ if (!isAtomic(state))
+ continue;
+ if (isPreempted(state, enabledTransitions))
+ continue;
+ QList<QState*> lst = properAncestors(state, 0);
+ if (QState *grp = qobject_cast<QState*>(state))
+ lst.prepend(grp);
+ bool found = false;
+ for (int j = 0; (j < lst.size()) && !found; ++j) {
+ QState *s = lst.at(j);
+ QList<QAbstractTransition*> transitions = QStatePrivate::get(s)->transitions();
+ for (int k = 0; k < transitions.size(); ++k) {
+ QAbstractTransition *t = transitions.at(k);
+ if (QAbstractTransitionPrivate::get(t)->callEventTest(event)) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": selecting transition" << t;
+#endif
+ enabledTransitions.insert(t);
+ found = true;
+ break;
+ }
+ }
+ }
+ }
+ const_cast<QStateMachine*>(q)->endSelectTransitions(event);
+ return enabledTransitions;
+}
+
+void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
+ qDebug() << q_func() << ": configuration before exiting states:" << configuration;
+#endif
+ QList<QAbstractState*> exitedStates = exitStates(event, enabledTransitions);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": configuration after exiting states:" << configuration;
+#endif
+ executeTransitionContent(event, enabledTransitions);
+ QList<QAbstractState*> enteredStates = enterStates(event, enabledTransitions);
+ applyProperties(enabledTransitions, exitedStates, enteredStates);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": configuration after entering states:" << configuration;
+ qDebug() << q_func() << ": end microstep";
+#endif
+}
+
+QList<QAbstractState*> QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+// qDebug() << "exitStates(" << enabledTransitions << ')';
+ QSet<QAbstractState*> statesToExit;
+// QSet<QAbstractState*> statesToSnapshot;
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+ QList<QAbstractState*> lst = t->targetStates();
+ if (lst.isEmpty())
+ continue;
+ lst.prepend(t->sourceState());
+ QAbstractState *lca = findLCA(lst);
+ if (lca == 0) {
+ setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
+ lst = pendingErrorStates.toList();
+ lst.prepend(t->sourceState());
+
+ lca = findLCA(lst);
+ Q_ASSERT(lca != 0);
+ }
+
+ {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *s = *it;
+ if (isDescendantOf(s, lca))
+ statesToExit.insert(s);
+ }
+ }
+ }
+ QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
+ qSort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
+ for (int i = 0; i < statesToExit_sorted.size(); ++i) {
+ QAbstractState *s = statesToExit_sorted.at(i);
+ if (QState *grp = qobject_cast<QState*>(s)) {
+ QList<QHistoryState*> hlst = QStatePrivate::get(grp)->historyStates();
+ for (int j = 0; j < hlst.size(); ++j) {
+ QHistoryState *h = hlst.at(j);
+ QHistoryStatePrivate::get(h)->configuration.clear();
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ QAbstractState *s0 = *it;
+ if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) {
+ if (isAtomic(s0) && isDescendantOf(s0, s))
+ QHistoryStatePrivate::get(h)->configuration.append(s0);
+ } else if (s0->parentState() == s) {
+ QHistoryStatePrivate::get(h)->configuration.append(s0);
+ }
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": recorded" << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
+ << "history for" << s << "in" << h << ':' << QHistoryStatePrivate::get(h)->configuration;
+#endif
+ }
+ }
+ }
+ for (int i = 0; i < statesToExit_sorted.size(); ++i) {
+ QAbstractState *s = statesToExit_sorted.at(i);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": exiting" << s;
+#endif
+ QAbstractStatePrivate::get(s)->callOnExit(event);
+ configuration.remove(s);
+ QAbstractStatePrivate::get(s)->emitExited();
+ }
+ return statesToExit_sorted;
+}
+
+void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": triggering" << t;
+#endif
+ QAbstractTransitionPrivate::get(t)->callOnTransition(event);
+ }
+}
+
+QList<QAbstractState*> QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
+{
+#ifdef QSTATEMACHINE_DEBUG
+ Q_Q(QStateMachine);
+#endif
+// qDebug() << "enterStates(" << enabledTransitions << ')';
+ QSet<QAbstractState*> statesToEnter;
+ QSet<QAbstractState*> statesForDefaultEntry;
+
+ if (pendingErrorStates.isEmpty()) {
+ for (int i = 0; i < enabledTransitions.size(); ++i) {
+ QAbstractTransition *t = enabledTransitions.at(i);
+ QList<QAbstractState*> lst = t->targetStates();
+ if (lst.isEmpty())
+ continue;
+ lst.prepend(t->sourceState());
+ QState *lca = findLCA(lst);
+ for (int j = 1; j < lst.size(); ++j) {
+ QAbstractState *s = lst.at(j);
+ addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry);
+ if (isParallel(lca)) {
+ QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates();
+ foreach (QAbstractState* child,lcac) {
+ if (!statesToEnter.contains(child))
+ addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry);
+ }
+ }
+ }
+ }
+ }
+
+ // Did an error occur while selecting transitions? Then we enter the error state.
+ if (!pendingErrorStates.isEmpty()) {
+ statesToEnter.clear();
+ statesToEnter = pendingErrorStates;
+ statesForDefaultEntry = pendingErrorStatesForDefaultEntry;
+ pendingErrorStates.clear();
+ pendingErrorStatesForDefaultEntry.clear();
+ }
+
+ QList<QAbstractState*> statesToEnter_sorted = statesToEnter.toList();
+ qSort(statesToEnter_sorted.begin(), statesToEnter_sorted.end(), stateEntryLessThan);
+
+ for (int i = 0; i < statesToEnter_sorted.size(); ++i) {
+ QAbstractState *s = statesToEnter_sorted.at(i);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": entering" << s;
+#endif
+ configuration.insert(s);
+ registerTransitions(s);
+ QAbstractStatePrivate::get(s)->callOnEntry(event);
+ QAbstractStatePrivate::get(s)->emitEntered();
+ if (statesForDefaultEntry.contains(s)) {
+ // ### executeContent(s.initial.transition.children())
+ }
+ if (isFinal(s)) {
+ QState *parent = s->parentState();
+ if (parent) {
+ QState *grandparent = parent->parentState();
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << parent;
+#endif
+ QStatePrivate::get(parent)->emitFinished();
+ if (grandparent && isParallel(grandparent)) {
+ bool allChildStatesFinal = true;
+ QList<QAbstractState*> childStates = QStatePrivate::get(grandparent)->childStates();
+ for (int j = 0; j < childStates.size(); ++j) {
+ QAbstractState *cs = childStates.at(j);
+ if (!isInFinalState(cs)) {
+ allChildStatesFinal = false;
+ break;
+ }
+ }
+ if (allChildStatesFinal) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << grandparent;
+#endif
+ QStatePrivate::get(grandparent)->emitFinished();
+ }
+ }
+ }
+ }
+ }
+ {
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
+ if (isFinal(*it) && (*it)->parentState() == rootState) {
+ processing = false;
+ stopProcessingReason = Finished;
+ break;
+ }
+ }
+ }
+// qDebug() << "configuration:" << configuration.toList();
+ return statesToEnter_sorted;
+}
+
+void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry)
+{
+ if (QHistoryState *h = qobject_cast<QHistoryState*>(s)) {
+ QList<QAbstractState*> hconf = QHistoryStatePrivate::get(h)->configuration;
+ if (!hconf.isEmpty()) {
+ for (int k = 0; k < hconf.size(); ++k) {
+ QAbstractState *s0 = hconf.at(k);
+ addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
+ }
+ #ifdef QSTATEMACHINE_DEBUG
+ qDebug() <<q_func() << ": restoring"
+ << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
+ << "history from" << s << ':' << hconf;
+ #endif
+ } else {
+ QList<QAbstractState*> hlst;
+ if (QHistoryStatePrivate::get(h)->defaultState)
+ hlst.append(QHistoryStatePrivate::get(h)->defaultState);
+
+ if (hlst.isEmpty()) {
+ setError(QStateMachine::NoDefaultStateInHistoryStateError, h);
+ } else {
+ for (int k = 0; k < hlst.size(); ++k) {
+ QAbstractState *s0 = hlst.at(k);
+ addStatesToEnter(s0, root, statesToEnter, statesForDefaultEntry);
+ }
+ #ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": initial history targets for" << s << ':' << hlst;
+ #endif
+ }
+ }
+ } else {
+ statesToEnter.insert(s);
+ if (isParallel(s)) {
+ QState *grp = qobject_cast<QState*>(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *child = lst.at(i);
+ addStatesToEnter(child, grp, statesToEnter, statesForDefaultEntry);
+ }
+ } else if (isCompound(s)) {
+ statesForDefaultEntry.insert(s);
+ QState *grp = qobject_cast<QState*>(s);
+ QAbstractState *initial = grp->initialState();
+ if (initial != 0) {
+ addStatesToEnter(initial, grp, statesToEnter, statesForDefaultEntry);
+ } else {
+ setError(QStateMachine::NoInitialStateError, grp);
+ return;
+ }
+ }
+ QList<QState*> ancs = properAncestors(s, root);
+ for (int i = 0; i < ancs.size(); ++i) {
+ QState *anc = ancs.at(i);
+ if (!anc->parentState())
+ continue;
+ statesToEnter.insert(anc);
+ if (isParallel(anc)) {
+ QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates();
+ for (int j = 0; j < lst.size(); ++j) {
+ QAbstractState *child = lst.at(j);
+ bool hasDescendantInList = false;
+ QSet<QAbstractState*>::const_iterator it;
+ for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) {
+ if (isDescendantOf(*it, child)) {
+ hasDescendantInList = true;
+ break;
+ }
+ }
+ if (!hasDescendantInList)
+ addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry);
+ }
+ }
+ }
+ }
+}
+
+void QStateMachinePrivate::applyProperties(const QList<QAbstractTransition*> &transitionList,
+ const QList<QAbstractState*> &exitedStates,
+ const QList<QAbstractState*> &enteredStates)
+{
+#ifdef QT_NO_ANIMATION
+ Q_UNUSED(transitionList);
+ Q_UNUSED(exitedStates);
+#else
+ Q_Q(QStateMachine);
+#endif
+ // Process the property assignments of the entered states.
+ QHash<QAbstractState*, QList<QPropertyAssignment> > propertyAssignmentsForState;
+ QHash<RestorableId, QVariant> pendingRestorables = registeredRestorables;
+ for (int i = 0; i < enteredStates.size(); ++i) {
+ QState *s = qobject_cast<QState*>(enteredStates.at(i));
+ if (!s)
+ continue;
+
+ QList<QPropertyAssignment> assignments = QStatePrivate::get(s)->propertyAssignments;
+ for (int j = 0; j < assignments.size(); ++j) {
+ const QPropertyAssignment &assn = assignments.at(j);
+ if (globalRestorePolicy == QStateMachine::RestoreProperties) {
+ registerRestorable(assn.object, assn.propertyName);
+ }
+ pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
+ propertyAssignmentsForState[s].append(assn);
+ }
+
+ // Remove pending restorables for all parent states to avoid restoring properties
+ // before the state that assigned them is exited. If state does not explicitly
+ // assign a property which is assigned by the parent, it inherits the parent's assignment.
+ QState *parentState = s;
+ while ((parentState = parentState->parentState()) != 0) {
+ assignments = QStatePrivate::get(parentState)->propertyAssignments;
+ for (int j=0; j<assignments.size(); ++j) {
+ const QPropertyAssignment &assn = assignments.at(j);
+ int c = pendingRestorables.remove(RestorableId(assn.object, assn.propertyName));
+ if (c > 0)
+ propertyAssignmentsForState[s].append(assn);
+ }
+ }
+ }
+ if (!pendingRestorables.isEmpty()) {
+ QAbstractState *s;
+ if (!enteredStates.isEmpty())
+ s = enteredStates.last(); // ### handle if parallel
+ else
+ s = 0;
+ propertyAssignmentsForState[s] << restorablesToPropertyList(pendingRestorables);
+ }
+
+#ifndef QT_NO_ANIMATION
+ // Gracefully terminate playing animations for states that are exited.
+ for (int i = 0; i < exitedStates.size(); ++i) {
+ QAbstractState *s = exitedStates.at(i);
+ QList<QAbstractAnimation*> animations = animationsForState.take(s);
+ for (int j = 0; j < animations.size(); ++j) {
+ QAbstractAnimation *anim = animations.at(j);
+ QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ stateForAnimation.remove(anim);
+
+ // Stop the (top-level) animation.
+ // ### Stopping nested animation has weird behavior.
+ QAbstractAnimation *topLevelAnim = anim;
+ while (QAnimationGroup *group = topLevelAnim->group())
+ topLevelAnim = group;
+ topLevelAnim->stop();
+
+ if (resetAnimationEndValues.contains(anim)) {
+ qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
+ resetAnimationEndValues.remove(anim);
+ }
+ QPropertyAssignment assn = propertyForAnimation.take(anim);
+ Q_ASSERT(assn.object != 0);
+ // If there is no property assignment that sets this property,
+ // set the property to its target value.
+ bool found = false;
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
+ for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
+ const QList<QPropertyAssignment> &assignments = it.value();
+ for (int k = 0; k < assignments.size(); ++k) {
+ if ((assignments.at(k).object == assn.object)
+ && (assignments.at(k).propertyName == assn.propertyName)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ assn.object->setProperty(assn.propertyName, assn.value);
+ }
+ }
+ }
+
+ // Find the animations to use for the state change.
+ QList<QAbstractAnimation*> selectedAnimations;
+ if (animationsEnabled) {
+ for (int i = 0; i < transitionList.size(); ++i) {
+ QAbstractTransition *transition = transitionList.at(i);
+
+ selectedAnimations << transition->animations();
+ selectedAnimations << defaultAnimationsForSource.values(transition->sourceState());
+
+ QList<QAbstractState *> targetStates = transition->targetStates();
+ for (int j=0; j<targetStates.size(); ++j)
+ selectedAnimations << defaultAnimationsForTarget.values(targetStates.at(j));
+ }
+ selectedAnimations << defaultAnimations;
+ }
+
+ // Initialize animations from property assignments.
+ for (int i = 0; i < selectedAnimations.size(); ++i) {
+ QAbstractAnimation *anim = selectedAnimations.at(i);
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::iterator it;
+ for (it = propertyAssignmentsForState.begin(); it != propertyAssignmentsForState.end(); ) {
+ QList<QPropertyAssignment>::iterator it2;
+ QAbstractState *s = it.key();
+ QList<QPropertyAssignment> &assignments = it.value();
+ for (it2 = assignments.begin(); it2 != assignments.end(); ) {
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
+ ret = initializeAnimation(anim, *it2);
+ QList<QAbstractAnimation*> handlers = ret.first;
+ if (!handlers.isEmpty()) {
+ for (int j = 0; j < handlers.size(); ++j) {
+ QAbstractAnimation *a = handlers.at(j);
+ propertyForAnimation.insert(a, *it2);
+ stateForAnimation.insert(a, s);
+ animationsForState[s].append(a);
+ // ### connect to just the top-level animation?
+ QObject::connect(a, SIGNAL(finished()), q, SLOT(_q_animationFinished()), Qt::UniqueConnection);
+ }
+ it2 = assignments.erase(it2);
+ } else {
+ ++it2;
+ }
+ for (int j = 0; j < ret.second.size(); ++j)
+ resetAnimationEndValues.insert(ret.second.at(j));
+ }
+ if (assignments.isEmpty())
+ it = propertyAssignmentsForState.erase(it);
+ else
+ ++it;
+ }
+ // We require that at least one animation is valid.
+ // ### generalize
+ QList<QVariantAnimation*> variantAnims = qFindChildren<QVariantAnimation*>(anim);
+ if (QVariantAnimation *va = qobject_cast<QVariantAnimation*>(anim))
+ variantAnims.append(va);
+
+ bool hasValidEndValue = false;
+ for (int j = 0; j < variantAnims.size(); ++j) {
+ if (variantAnims.at(j)->endValue().isValid()) {
+ hasValidEndValue = true;
+ break;
+ }
+ }
+
+ if (hasValidEndValue) {
+ anim->start();
+ }
+ }
+#endif // !QT_NO_ANIMATION
+
+ // Immediately set the properties that are not animated.
+ {
+ QHash<QAbstractState*, QList<QPropertyAssignment> >::const_iterator it;
+ for (it = propertyAssignmentsForState.constBegin(); it != propertyAssignmentsForState.constEnd(); ++it) {
+ const QList<QPropertyAssignment> &assignments = it.value();
+ for (int i = 0; i < assignments.size(); ++i) {
+ const QPropertyAssignment &assn = assignments.at(i);
+ assn.object->setProperty(assn.propertyName, assn.value);
+ }
+ }
+ }
+
+ // Emit polished signal for entered states that have no animated properties.
+ for (int i = 0; i < enteredStates.size(); ++i) {
+ QState *s = qobject_cast<QState*>(enteredStates.at(i));
+ if (s
+#ifndef QT_NO_ANIMATION
+ && !animationsForState.contains(s)
+#endif
+ )
+ QStatePrivate::get(s)->emitPolished();
+ }
+}
+
+bool QStateMachinePrivate::isFinal(const QAbstractState *s)
+{
+ return qobject_cast<const QFinalState*>(s) != 0;
+}
+
+bool QStateMachinePrivate::isParallel(const QAbstractState *s)
+{
+ const QState *ss = qobject_cast<const QState*>(s);
+ return ss && (QStatePrivate::get(ss)->childMode == QState::ParallelStates);
+}
+
+bool QStateMachinePrivate::isCompound(const QAbstractState *s)
+{
+ const QState *group = qobject_cast<const QState*>(s);
+ if (!group)
+ return false;
+ return (!isParallel(group) && !QStatePrivate::get(group)->childStates().isEmpty())
+ || (qobject_cast<QStateMachine*>(group->parent()) != 0);
+}
+
+bool QStateMachinePrivate::isAtomic(const QAbstractState *s)
+{
+ const QState *ss = qobject_cast<const QState*>(s);
+ return (ss && QStatePrivate::get(ss)->childStates().isEmpty())
+ || isFinal(s);
+}
+
+
+bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
+{
+ Q_ASSERT(state != 0);
+ for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) {
+ if (s == other)
+ return true;
+ }
+ return false;
+}
+
+QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound)
+{
+ Q_ASSERT(state != 0);
+ QList<QState*> result;
+ for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) {
+ result.append(s);
+ }
+ return result;
+}
+
+bool QStateMachinePrivate::isInFinalState(QAbstractState* s) const
+{
+ if (isCompound(s)) {
+ QState *grp = qobject_cast<QState*>(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *cs = lst.at(i);
+ if (isFinal(cs) && configuration.contains(cs))
+ return true;
+ }
+ return false;
+ } else if (isParallel(s)) {
+ QState *grp = qobject_cast<QState*>(s);
+ QList<QAbstractState*> lst = QStatePrivate::get(grp)->childStates();
+ for (int i = 0; i < lst.size(); ++i) {
+ QAbstractState *cs = lst.at(i);
+ if (!isInFinalState(cs))
+ return false;
+ }
+ return true;
+ }
+ else
+ return false;
+}
+
+void QStateMachinePrivate::registerRestorable(QObject *object, const QByteArray &propertyName)
+{
+ RestorableId id(object, propertyName);
+ if (!registeredRestorables.contains(id))
+ registeredRestorables.insert(id, object->property(propertyName));
+}
+
+QList<QPropertyAssignment> QStateMachinePrivate::restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const
+{
+ QList<QPropertyAssignment> result;
+ QHash<RestorableId, QVariant>::const_iterator it;
+ for (it = restorables.constBegin(); it != restorables.constEnd(); ++it) {
+// qDebug() << "restorable:" << it.key().first << it.key().second << it.value();
+ result.append(QPropertyAssignment(it.key().first, it.key().second, it.value(), /*explicitlySet=*/false));
+ }
+ return result;
+}
+
+/*!
+ \internal
+ Returns true if the variable with the given \a id has been registered for restoration.
+*/
+bool QStateMachinePrivate::hasRestorable(QObject *object, const QByteArray &propertyName) const
+{
+ return registeredRestorables.contains(RestorableId(object, propertyName));
+}
+
+QVariant QStateMachinePrivate::restorableValue(QObject *object, const QByteArray &propertyName) const
+{
+ return registeredRestorables.value(RestorableId(object, propertyName), QVariant());
+}
+
+
+/*!
+ \internal
+ Unregisters the variable identified by \a id
+*/
+void QStateMachinePrivate::unregisterRestorable(QObject *object, const QByteArray &propertyName)
+{
+// qDebug() << "unregisterRestorable(" << object << propertyName << ')';
+ RestorableId id(object, propertyName);
+ registeredRestorables.remove(id);
+}
+
+QAbstractState *QStateMachinePrivate::findErrorState(QAbstractState *context)
+{
+ // If the user sets the root state's error state to 0, we return the initial error state
+ if (context == 0)
+ return initialErrorStateForRoot;
+
+ // Find error state recursively in parent hierarchy if not set explicitly for context state
+ QAbstractState *errorState = 0;
+
+ QState *s = qobject_cast<QState*>(context);
+ if (s)
+ errorState = s->errorState();
+
+ if (!errorState)
+ errorState = findErrorState(context->parentState());
+
+ return errorState;
+}
+
+void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractState *currentContext)
+{
+ error = errorCode;
+
+ switch (errorCode) {
+ case QStateMachine::NoInitialStateError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("Missing initial state in compound state '%1'")
+ .arg(currentContext->objectName());
+
+ break;
+ case QStateMachine::NoDefaultStateInHistoryStateError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("Missing default state in history state '%1'")
+ .arg(currentContext->objectName());
+ break;
+
+ case QStateMachine::NoCommonAncestorForTransitionError:
+ Q_ASSERT(currentContext != 0);
+
+ errorString = QStateMachine::tr("No common ancestor for targets and source of transition from state '%1'")
+ .arg(currentContext->objectName());
+ break;
+ default:
+ errorString = QStateMachine::tr("Unknown error");
+ };
+
+ pendingErrorStates.clear();
+ pendingErrorStatesForDefaultEntry.clear();
+
+ QAbstractState *currentErrorState = findErrorState(currentContext);
+
+ // Avoid infinite loop if the error state itself has an error
+ if (currentContext == currentErrorState) {
+ Q_ASSERT(currentContext != initialErrorStateForRoot); // RootErrorState is broken
+ currentErrorState = initialErrorStateForRoot;
+ }
+
+ Q_ASSERT(currentErrorState != 0);
+ Q_ASSERT(currentErrorState != rootState);
+
+ QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
+ addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
+}
+
+#ifndef QT_NO_ANIMATION
+
+QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
+QStateMachinePrivate::initializeAnimation(QAbstractAnimation *abstractAnimation,
+ const QPropertyAssignment &prop)
+{
+ QList<QAbstractAnimation*> handledAnimations;
+ QList<QAbstractAnimation*> localResetEndValues;
+ QAnimationGroup *group = qobject_cast<QAnimationGroup*>(abstractAnimation);
+ if (group) {
+ for (int i = 0; i < group->animationCount(); ++i) {
+ QAbstractAnimation *animationChild = group->animationAt(i);
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> > ret;
+ ret = initializeAnimation(animationChild, prop);
+ handledAnimations << ret.first;
+ localResetEndValues << ret.second;
+ }
+ } else {
+ QPropertyAnimation *animation = qobject_cast<QPropertyAnimation *>(abstractAnimation);
+ if (animation != 0
+ && prop.object == animation->targetObject()
+ && prop.propertyName == animation->propertyName()) {
+
+ // Only change end value if it is undefined
+ if (!animation->endValue().isValid()) {
+ animation->setEndValue(prop.value);
+ localResetEndValues.append(animation);
+ }
+ handledAnimations.append(animation);
+ }
+ }
+ return qMakePair(handledAnimations, localResetEndValues);
+}
+
+void QStateMachinePrivate::_q_animationFinished()
+{
+ Q_Q(QStateMachine);
+ QAbstractAnimation *anim = qobject_cast<QAbstractAnimation*>(q->sender());
+ Q_ASSERT(anim != 0);
+ QObject::disconnect(anim, SIGNAL(finished()), q, SLOT(_q_animationFinished()));
+ if (resetAnimationEndValues.contains(anim)) {
+ qobject_cast<QVariantAnimation*>(anim)->setEndValue(QVariant()); // ### generalize
+ resetAnimationEndValues.remove(anim);
+ }
+
+ // Set the final property value.
+ QPropertyAssignment assn = propertyForAnimation.take(anim);
+ Q_ASSERT(assn.object != 0);
+ assn.object->setProperty(assn.propertyName, assn.value);
+ if (!assn.explicitlySet)
+ unregisterRestorable(assn.object, assn.propertyName);
+
+ QAbstractState *state = stateForAnimation.take(anim);
+ Q_ASSERT(state != 0);
+ QHash<QAbstractState*, QList<QAbstractAnimation*> >::iterator it;
+ it = animationsForState.find(state);
+ Q_ASSERT(it != animationsForState.end());
+ QList<QAbstractAnimation*> &animations = it.value();
+ animations.removeOne(anim);
+ if (animations.isEmpty()) {
+ animationsForState.erase(it);
+ QStatePrivate::get(qobject_cast<QState*>(state))->emitPolished();
+ }
+}
+
+#endif // !QT_NO_ANIMATION
+
+namespace {
+
+class StartState : public QState
+{
+public:
+ StartState(QState *parent)
+ : QState(parent) {}
+protected:
+ void onEntry(QEvent *) {}
+ void onExit(QEvent *) {}
+};
+
+class InitialTransition : public QAbstractTransition
+{
+public:
+ InitialTransition(QAbstractState *target)
+ : QAbstractTransition(QList<QAbstractState*>() << target) {}
+protected:
+ virtual bool eventTest(QEvent *) { return true; }
+ virtual void onTransition(QEvent *) {}
+};
+
+} // namespace
+
+void QStateMachinePrivate::_q_start()
+{
+ Q_Q(QStateMachine);
+ Q_ASSERT(state == Starting);
+ if (!rootState) {
+ state = NotRunning;
+ return;
+ }
+ QAbstractState *initial = rootState->initialState();
+ if (initial == 0)
+ setError(QStateMachine::NoInitialStateError, rootState);
+
+ configuration.clear();
+ qDeleteAll(internalEventQueue);
+ internalEventQueue.clear();
+ qDeleteAll(externalEventQueue);
+ externalEventQueue.clear();
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": starting";
+#endif
+ state = Running;
+ processingScheduled = true; // we call _q_process() below
+ emit q->started();
+
+ StartState *start = new StartState(rootState);
+ QAbstractTransition *initialTransition = new InitialTransition(initial);
+ start->addTransition(initialTransition);
+ QList<QAbstractTransition*> transitions;
+ transitions.append(initialTransition);
+ QEvent nullEvent(QEvent::None);
+ executeTransitionContent(&nullEvent, transitions);
+ enterStates(&nullEvent, transitions);
+ applyProperties(transitions, QList<QAbstractState*>() << start,
+ QList<QAbstractState*>() << initial);
+ delete start;
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": initial configuration:" << configuration;
+#endif
+ _q_process();
+}
+
+void QStateMachinePrivate::_q_process()
+{
+ Q_Q(QStateMachine);
+ Q_ASSERT(state == Running);
+ Q_ASSERT(!processing);
+ processing = true;
+ processingScheduled = false;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": starting the event processing loop";
+#endif
+ while (processing) {
+ if (stop) {
+ stop = false;
+ processing = false;
+ stopProcessingReason = Stopped;
+ break;
+ }
+ QSet<QAbstractTransition*> enabledTransitions;
+ QEvent *e = new QEvent(QEvent::None);
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ if (enabledTransitions.isEmpty() && !internalEventQueue.isEmpty()) {
+ e = internalEventQueue.takeFirst();
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": dequeued internal event" << e << "of type" << e->type();
+#endif
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ }
+ if (enabledTransitions.isEmpty()) {
+ if (externalEventQueue.isEmpty()) {
+ if (internalEventQueue.isEmpty()) {
+ processing = false;
+ stopProcessingReason = EventQueueEmpty;
+ }
+ } else {
+ e = externalEventQueue.takeFirst();
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": dequeued external event" << e << "of type" << e->type();
+#endif
+ enabledTransitions = selectTransitions(e);
+ if (enabledTransitions.isEmpty()) {
+ delete e;
+ e = 0;
+ }
+ }
+ }
+ if (!enabledTransitions.isEmpty()) {
+ q->beginMicrostep(e);
+ microstep(e, enabledTransitions.toList());
+ q->endMicrostep(e);
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ else {
+ qDebug() << q << ": no transitions enabled";
+ }
+#endif
+ delete e;
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": finished the event processing loop";
+#endif
+ switch (stopProcessingReason) {
+ case EventQueueEmpty:
+ break;
+ case Finished:
+ state = NotRunning;
+ unregisterAllTransitions();
+ emit q->finished();
+ break;
+ case Stopped:
+ state = NotRunning;
+ unregisterAllTransitions();
+ emit q->stopped();
+ break;
+ }
+}
+
+void QStateMachinePrivate::scheduleProcess()
+{
+ if ((state != Running) || processing || processingScheduled)
+ return;
+ processingScheduled = true;
+ QMetaObject::invokeMethod(q_func(), "_q_process", Qt::QueuedConnection);
+}
+
+void QStateMachinePrivate::registerTransitions(QAbstractState *state)
+{
+ QState *group = qobject_cast<QState*>(state);
+ if (!group)
+ return;
+ QList<QAbstractTransition*> transitions = QStatePrivate::get(group)->transitions();
+ for (int i = 0; i < transitions.size(); ++i) {
+ QAbstractTransition *t = transitions.at(i);
+ if (QSignalTransition *st = qobject_cast<QSignalTransition*>(t)) {
+ registerSignalTransition(st);
+ }
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ else if (QEventTransition *oet = qobject_cast<QEventTransition*>(t)) {
+ registerEventTransition(oet);
+ }
+#endif
+ }
+}
+
+void QStateMachinePrivate::unregisterTransition(QAbstractTransition *transition)
+{
+ if (QSignalTransition *st = qobject_cast<QSignalTransition*>(transition)) {
+ unregisterSignalTransition(st);
+ }
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ else if (QEventTransition *oet = qobject_cast<QEventTransition*>(transition)) {
+ unregisterEventTransition(oet);
+ }
+#endif
+}
+
+void QStateMachinePrivate::registerSignalTransition(QSignalTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (QSignalTransitionPrivate::get(transition)->signalIndex != -1)
+ return; // already registered
+ QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
+ if (!sender)
+ return;
+ QByteArray signal = QSignalTransitionPrivate::get(transition)->signal;
+ if (signal.startsWith('0'+QSIGNAL_CODE))
+ signal.remove(0, 1);
+ int signalIndex = sender->metaObject()->indexOfSignal(signal);
+ if (signalIndex == -1) {
+ qWarning("QSignalTransition: no such signal: %s::%s",
+ sender->metaObject()->className(), signal.constData());
+ return;
+ }
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ if (connectedSignalIndexes.size() <= signalIndex)
+ connectedSignalIndexes.resize(signalIndex+1);
+ if (connectedSignalIndexes.at(signalIndex) == 0) {
+ if (!signalEventGenerator)
+ signalEventGenerator = new QSignalEventGenerator(q);
+ bool ok = QMetaObject::connect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ if (!ok) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": FAILED to add signal transition from" << transition->sourceState()
+ << ": ( sender =" << sender << ", signal =" << signal
+ << ", targets =" << transition->targetStates() << ')';
+#endif
+ return;
+ }
+ }
+ ++connectedSignalIndexes[signalIndex];
+ QSignalTransitionPrivate::get(transition)->signalIndex = signalIndex;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": added signal transition from" << transition->sourceState()
+ << ": ( sender =" << sender << ", signal =" << signal
+ << ", targets =" << transition->targetStates() << ')';
+#endif
+}
+
+void QStateMachinePrivate::unregisterSignalTransition(QSignalTransition *transition)
+{
+ int signalIndex = QSignalTransitionPrivate::get(transition)->signalIndex;
+ if (signalIndex == -1)
+ return; // not registered
+ QSignalTransitionPrivate::get(transition)->signalIndex = -1;
+ const QObject *sender = QSignalTransitionPrivate::get(transition)->sender;
+ QVector<int> &connectedSignalIndexes = connections[sender];
+ Q_ASSERT(connectedSignalIndexes.size() > signalIndex);
+ Q_ASSERT(connectedSignalIndexes.at(signalIndex) != 0);
+ if (--connectedSignalIndexes[signalIndex] == 0) {
+ Q_ASSERT(signalEventGenerator != 0);
+ QMetaObject::disconnect(sender, signalIndex, signalEventGenerator,
+ signalEventGenerator->metaObject()->methodOffset());
+ int sum = 0;
+ for (int i = 0; i < connectedSignalIndexes.size(); ++i)
+ sum += connectedSignalIndexes.at(i);
+ if (sum == 0)
+ connections.remove(sender);
+ }
+}
+
+void QStateMachinePrivate::unregisterAllTransitions()
+{
+ {
+ QList<QSignalTransition*> transitions = qFindChildren<QSignalTransition*>(rootState);
+ for (int i = 0; i < transitions.size(); ++i)
+ unregisterSignalTransition(transitions.at(i));
+ }
+ {
+ QList<QEventTransition*> transitions = qFindChildren<QEventTransition*>(rootState);
+ for (int i = 0; i < transitions.size(); ++i)
+ unregisterEventTransition(transitions.at(i));
+ }
+}
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+void QStateMachinePrivate::registerEventTransition(QEventTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (QEventTransitionPrivate::get(transition)->registered)
+ return;
+ if (transition->eventType() >= QEvent::User) {
+ qWarning("QObject event transitions are not supported for custom types");
+ return;
+ }
+ QObject *object = QEventTransitionPrivate::get(transition)->object;
+ if (!object)
+ return;
+ QObjectPrivate *od = QObjectPrivate::get(object);
+ if (!od->eventFilters.contains(q))
+ object->installEventFilter(q);
+ ++qobjectEvents[object][transition->eventType()];
+ QEventTransitionPrivate::get(transition)->registered = true;
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": added event transition from" << transition->sourceState()
+ << ": ( object =" << object << ", event =" << transition->eventType()
+ << ", targets =" << transition->targetStates() << ')';
+#endif
+}
+
+void QStateMachinePrivate::unregisterEventTransition(QEventTransition *transition)
+{
+ Q_Q(QStateMachine);
+ if (!QEventTransitionPrivate::get(transition)->registered)
+ return;
+ QObject *object = QEventTransitionPrivate::get(transition)->object;
+ QHash<QEvent::Type, int> &events = qobjectEvents[object];
+ Q_ASSERT(events.value(transition->eventType()) > 0);
+ if (--events[transition->eventType()] == 0) {
+ events.remove(transition->eventType());
+ int sum = 0;
+ QHash<QEvent::Type, int>::const_iterator it;
+ for (it = events.constBegin(); it != events.constEnd(); ++it)
+ sum += it.value();
+ if (sum == 0) {
+ qobjectEvents.remove(object);
+ object->removeEventFilter(q);
+ }
+ }
+ QEventTransitionPrivate::get(transition)->registered = false;
+}
+#endif
+
+void QStateMachinePrivate::handleTransitionSignal(const QObject *sender, int signalIndex,
+ void **argv)
+{
+ Q_ASSERT(connections[sender].at(signalIndex) != 0);
+ const QMetaObject *meta = sender->metaObject();
+ QMetaMethod method = meta->method(signalIndex);
+ QList<QByteArray> parameterTypes = method.parameterTypes();
+ int argc = parameterTypes.count();
+ QList<QVariant> vargs;
+ for (int i = 0; i < argc; ++i) {
+ int type = QMetaType::type(parameterTypes.at(i));
+ vargs.append(QVariant(type, argv[i+1]));
+ }
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": sending signal event ( sender =" << sender
+ << ", signal =" << sender->metaObject()->method(signalIndex).signature() << ')';
+#endif
+ internalEventQueue.append(new QSignalEvent(sender, signalIndex, vargs));
+ scheduleProcess();
+}
+
+/*!
+ Constructs a new state machine with the given \a parent.
+*/
+QStateMachine::QStateMachine(QObject *parent)
+ : QObject(*new QStateMachinePrivate, parent)
+{
+}
+
+/*!
+ \internal
+*/
+QStateMachine::QStateMachine(QStateMachinePrivate &dd, QObject *parent)
+ : QObject(dd, parent)
+{
+}
+
+/*!
+ Destroys this state machine.
+*/
+QStateMachine::~QStateMachine()
+{
+}
+
+namespace {
+
+class RootErrorState : public QAbstractState
+{
+public:
+ RootErrorState(QState *parent)
+ : QAbstractState(parent)
+ {
+ setObjectName(QString::fromLatin1("DefaultErrorState"));
+ }
+
+ void onEntry(QEvent *)
+ {
+ QAbstractStatePrivate *d = QAbstractStatePrivate::get(this);
+ QStateMachine *machine = d->machine();
+
+ qWarning("Unrecoverable error detected in running state machine: %s",
+ qPrintable(machine->errorString()));
+ }
+
+ void onExit(QEvent *) {}
+};
+
+class RootState : public QState
+{
+public:
+ RootState(QState *parent)
+ : QState(parent)
+ {
+ }
+
+ void onEntry(QEvent *) {}
+ void onExit(QEvent *) {}
+};
+
+} // namespace
+
+/*!
+ Returns this state machine's root state.
+*/
+QState *QStateMachine::rootState() const
+{
+ Q_D(const QStateMachine);
+ if (!d->rootState) {
+ const_cast<QStateMachinePrivate*>(d)->rootState = new RootState(0);
+ const_cast<QStateMachinePrivate*>(d)->initialErrorStateForRoot = new RootErrorState(d->rootState);
+ d->rootState->setParent(const_cast<QStateMachine*>(this));
+ d->rootState->setErrorState(d->initialErrorStateForRoot);
+ }
+ return d->rootState;
+}
+
+/*!
+ Returns the error state of the state machine's root state.
+
+ \sa QState::errorState()
+*/
+QAbstractState *QStateMachine::errorState() const
+{
+ return rootState()->errorState();
+}
+
+/*!
+ Sets the error state of this state machine's root state to be \a state. When a running state
+ machine encounters an error which puts it in an undefined state, it will enter an error state
+ based on the context of the error that occurred. It will enter this state regardless of what
+ is currently in the event queue.
+
+ If the erroneous state has an error state set, this will be entered by the machine. If no error
+ state has been set, the state machine will search the parent hierarchy recursively for an
+ error state. The error state of the root state can thus be seen as a global error state that
+ applies for the states for which a more specific error state has not been set.
+
+ Before entering the error state, the state machine will set the error code returned by error() and
+ error message returned by errorString().
+
+ The default error state will print a warning to the console containing the information returned by
+ errorString(). By setting a new error state on either the state machine itself, or on specific
+ states, you can fine tune error handling in the state machine.
+
+ If the root state's error state is set to 0, or if the error state selected by the machine itself
+ contains an error, the default error state will be used.
+
+ \sa QState::setErrorState(), rootState()
+*/
+void QStateMachine::setErrorState(QAbstractState *state)
+{
+ rootState()->setErrorState(state);
+}
+
+/*! \enum QStateMachine::Error
+
+ This enum type defines errors that can occur in the state machine at run time. When the state
+ machine encounters an unrecoverable error at run time, it will set the error code returned
+ by error(), the error message returned by errorString(), and enter an error state based on
+ the context of the error.
+
+ \value NoError No error has occurred.
+ \value NoInitialStateError The machine has entered a QState with children which does not have an
+ initial state set. The context of this error is the state which is missing an initial
+ state.
+ \value NoDefaultStateInHistoryStateError The machine has entered a QHistoryState which does not have
+ a default state set. The context of this error is the QHistoryState which is missing a
+ default state.
+ \value NoCommonAncestorForTransitionError The machine has selected a transition whose source
+ and targets are not part of the same tree of states, and thus are not part of the same
+ state machine. Commonly, this could mean that one of the states has not been given
+ any parent or added to any machine. The context of this error is the source state of
+ the transition.
+
+ \sa setErrorState()
+*/
+
+/*!
+ \enum QStateMachine::RestorePolicy
+
+ This enum specifies the restore policy type. The restore policy
+ takes effect when the machine enters a state which sets one or more
+ properties. If the restore policy is set to RestoreProperties,
+ the state machine will save the original value of the property before the
+ new value is set.
+
+ Later, when the machine either enters a state which does not set
+ a value for the given property, the property will automatically be restored
+ to its initial value.
+
+ Only one initial value will be saved for any given property. If a value for a property has
+ already been saved by the state machine, it will not be overwritten until the property has been
+ successfully restored.
+
+ \value DoNotRestoreProperties The state machine should not save the initial values of properties
+ and restore them later.
+ \value RestoreProperties The state machine should save the initial values of properties
+ and restore them later.
+
+ \sa QStateMachine::globalRestorePolicy QState::assignProperty()
+*/
+
+
+/*!
+ Returns the error code of the last error that occurred in the state machine.
+*/
+QStateMachine::Error QStateMachine::error() const
+{
+ Q_D(const QStateMachine);
+ return d->error;
+}
+
+/*!
+ Returns the error string of the last error that occurred in the state machine.
+*/
+QString QStateMachine::errorString() const
+{
+ Q_D(const QStateMachine);
+ return d->errorString;
+}
+
+/*!
+ Clears the error string and error code of the state machine.
+*/
+void QStateMachine::clearError()
+{
+ Q_D(QStateMachine);
+ d->errorString.clear();
+ d->error = NoError;
+}
+
+/*!
+ Returns the restore policy of the state machine.
+
+ \sa setGlobalRestorePolicy()
+*/
+QStateMachine::RestorePolicy QStateMachine::globalRestorePolicy() const
+{
+ Q_D(const QStateMachine);
+ return d->globalRestorePolicy;
+}
+
+/*!
+ Sets the restore policy of the state machine to \a restorePolicy. The default
+ restore policy is QAbstractState::DoNotRestoreProperties.
+
+ \sa globalRestorePolicy()
+*/
+void QStateMachine::setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy)
+{
+ Q_D(QStateMachine);
+ d->globalRestorePolicy = restorePolicy;
+}
+
+/*!
+ Returns this state machine's initial state, or 0 if no initial state has
+ been set.
+*/
+QAbstractState *QStateMachine::initialState() const
+{
+ Q_D(const QStateMachine);
+ if (!d->rootState)
+ return 0;
+ return d->rootState->initialState();
+}
+
+/*!
+ Sets this state machine's initial \a state.
+*/
+void QStateMachine::setInitialState(QAbstractState *state)
+{
+ Q_D(QStateMachine);
+ if (!d->rootState) {
+ if (!state)
+ return;
+ rootState()->setInitialState(state);
+ }
+ d->rootState->setInitialState(state);
+}
+
+/*!
+ Adds the given \a state to this state machine. The state becomes a top-level
+ state (i.e. a child of the rootState()).
+
+ If the state is already in a different machine, it will first be removed
+ from its old machine, and then added to this machine.
+
+ \sa removeState(), rootState(), setInitialState()
+*/
+void QStateMachine::addState(QAbstractState *state)
+{
+ if (!state) {
+ qWarning("QStateMachine::addState: cannot add null state");
+ return;
+ }
+ if (QAbstractStatePrivate::get(state)->machine() == this) {
+ qWarning("QStateMachine::addState: state has already been added to this machine");
+ return;
+ }
+ state->setParent(rootState());
+}
+
+/*!
+ Removes the given \a state from this state machine. The state machine
+ releases ownership of the state.
+
+ \sa addState()
+*/
+void QStateMachine::removeState(QAbstractState *state)
+{
+ if (!state) {
+ qWarning("QStateMachine::removeState: cannot remove null state");
+ return;
+ }
+ if (QAbstractStatePrivate::get(state)->machine() != this) {
+ qWarning("QStateMachine::removeState: state %p's machine (%p)"
+ " is different from this machine (%p)",
+ state, QAbstractStatePrivate::get(state)->machine(), this);
+ return;
+ }
+ state->setParent(0);
+}
+
+/*!
+ Returns whether this state machine is running.
+
+ start(), stop()
+*/
+bool QStateMachine::isRunning() const
+{
+ Q_D(const QStateMachine);
+ return (d->state == QStateMachinePrivate::Running);
+}
+
+/*!
+ Starts this state machine. The machine will reset its configuration and
+ transition to the initial state. When a final top-level state (QFinalState)
+ is entered, the machine will emit the finished() signal.
+
+ \sa started(), finished(), stop(), initialState()
+*/
+void QStateMachine::start()
+{
+ Q_D(QStateMachine);
+
+ if (rootState()->initialState() == 0) {
+ qWarning("QStateMachine::start: No initial state set for machine. Refusing to start.");
+ return;
+ }
+
+ switch (d->state) {
+ case QStateMachinePrivate::NotRunning:
+ d->state = QStateMachinePrivate::Starting;
+ QMetaObject::invokeMethod(this, "_q_start", Qt::QueuedConnection);
+ break;
+ case QStateMachinePrivate::Starting:
+ break;
+ case QStateMachinePrivate::Running:
+ qWarning("QStateMachine::start(): already running");
+ break;
+ }
+}
+
+/*!
+ Stops this state machine. The state machine will stop processing events and
+ then emit the stopped() signal.
+
+ \sa stopped(), start()
+*/
+void QStateMachine::stop()
+{
+ Q_D(QStateMachine);
+ switch (d->state) {
+ case QStateMachinePrivate::NotRunning:
+ break;
+ case QStateMachinePrivate::Starting:
+ // the machine will exit as soon as it enters the event processing loop
+ d->stop = true;
+ break;
+ case QStateMachinePrivate::Running:
+ d->stop = true;
+ d->scheduleProcess();
+ break;
+ }
+}
+
+/*!
+ Posts the given \a event for processing by this state machine, with a delay
+ of \a delay milliseconds.
+
+ This function returns immediately. The event is added to the state machine's
+ event queue. Events are processed in the order posted. The state machine
+ takes ownership of the event and deletes it once it has been processed.
+
+ You can only post events when the state machine is running.
+*/
+void QStateMachine::postEvent(QEvent *event, int delay)
+{
+ Q_D(QStateMachine);
+ if (d->state != QStateMachinePrivate::Running) {
+ qWarning("QStateMachine::postEvent: cannot post event when the state machine is not running");
+ return;
+ }
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << this << ": posting external event" << event << "with delay" << delay;
+#endif
+ if (delay) {
+ int tid = startTimer(delay);
+ d->delayedEvents[tid] = event;
+ } else {
+ d->externalEventQueue.append(event);
+ d->scheduleProcess();
+ }
+}
+
+/*!
+ \internal
+
+ Posts the given internal \a event for processing by this state machine.
+*/
+void QStateMachine::postInternalEvent(QEvent *event)
+{
+ Q_D(QStateMachine);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << this << ": posting internal event" << event;
+#endif
+ d->internalEventQueue.append(event);
+ d->scheduleProcess();
+}
+
+/*!
+ \internal
+
+ Returns the maximal consistent set of states (including parallel and final
+ states) that this state machine is currently in. If a state \c s is in the
+ configuration, it is always the case that the parent of \c s is also in
+ c. Note, however, that the rootState() is not an explicit member of the
+ configuration.
+*/
+QSet<QAbstractState*> QStateMachine::configuration() const
+{
+ Q_D(const QStateMachine);
+ return d->configuration;
+}
+
+/*!
+ \fn QStateMachine::started()
+
+ This signal is emitted when the state machine has entered its initial state
+ (QStateMachine::initialState).
+
+ \sa QStateMachine::finished(), QStateMachine::start()
+*/
+
+/*!
+ \fn QStateMachine::finished()
+
+ This signal is emitted when the state machine has reached a top-level final
+ state (QFinalState).
+
+ \sa QStateMachine::started()
+*/
+
+/*!
+ \fn QStateMachine::stopped()
+
+ This signal is emitted when the state machine has stopped.
+
+ \sa QStateMachine::stop(), QStateMachine::finished()
+*/
+
+/*!
+ \reimp
+*/
+bool QStateMachine::event(QEvent *e)
+{
+ Q_D(QStateMachine);
+ if (e->type() == QEvent::Timer) {
+ QTimerEvent *te = static_cast<QTimerEvent*>(e);
+ int tid = te->timerId();
+ if (d->delayedEvents.contains(tid)) {
+ killTimer(tid);
+ QEvent *ee = d->delayedEvents.take(tid);
+ d->externalEventQueue.append(ee);
+ d->scheduleProcess();
+ return true;
+ }
+ } else if (e->type() == QEvent::ChildAdded) {
+ QChildEvent *ce = static_cast<QChildEvent*>(e);
+ if (QAbstractState *state = qobject_cast<QAbstractState*>(ce->child())) {
+ if (state != rootState()) {
+ state->setParent(rootState());
+ return true;
+ }
+ }
+ }
+ return QObject::event(e);
+}
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+/*!
+ \reimp
+*/
+bool QStateMachine::eventFilter(QObject *watched, QEvent *event)
+{
+ Q_D(QStateMachine);
+ Q_ASSERT(d->qobjectEvents.contains(watched));
+ if (d->qobjectEvents[watched].contains(event->type()))
+ postEvent(new QWrappedEvent(watched, d->handler->cloneEvent(event)));
+ return false;
+}
+#endif
+
+/*!
+ \internal
+
+ This function is called when the state machine is about to select
+ transitions based on the given \a event.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::beginSelectTransitions(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \internal
+
+ This function is called when the state machine has finished selecting
+ transitions based on the given \a event.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::endSelectTransitions(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \internal
+
+ This function is called when the state machine is about to do a microstep.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::beginMicrostep(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+/*!
+ \internal
+
+ This function is called when the state machine has finished doing a
+ microstep.
+
+ The default implementation does nothing.
+*/
+void QStateMachine::endMicrostep(QEvent *event)
+{
+ Q_UNUSED(event);
+}
+
+#ifndef QT_NO_ANIMATION
+
+/*!
+ Returns whether animations are enabled for this state machine.
+*/
+bool QStateMachine::animationsEnabled() const
+{
+ Q_D(const QStateMachine);
+ return d->animationsEnabled;
+}
+
+/*!
+ Sets whether animations are \a enabled for this state machine.
+*/
+void QStateMachine::setAnimationsEnabled(bool enabled)
+{
+ Q_D(QStateMachine);
+ d->animationsEnabled = enabled;
+}
+
+/*!
+ Adds a default \a animation to be considered for any transition.
+*/
+void QStateMachine::addDefaultAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QStateMachine);
+ d->defaultAnimations.append(animation);
+}
+
+/*!
+ Returns the list of default animations that will be considered for any transition.
+*/
+QList<QAbstractAnimation*> QStateMachine::defaultAnimations() const
+{
+ Q_D(const QStateMachine);
+ return d->defaultAnimations;
+}
+
+/*!
+ Removes \a animation from the list of default animations.
+*/
+void QStateMachine::removeDefaultAnimation(QAbstractAnimation *animation)
+{
+ Q_D(QStateMachine);
+ d->defaultAnimations.removeAll(animation);
+}
+
+#endif // QT_NO_ANIMATION
+
+
+static const uint qt_meta_data_QSignalEventGenerator[] = {
+
+ // content:
+ 2, // revision
+ 0, // classname
+ 0, 0, // classinfo
+ 1, 12, // methods
+ 0, 0, // properties
+ 0, 0, // enums/sets
+ 0, 0, // constructors
+
+ // slots: signature, parameters, type, tag, flags
+ 23, 22, 22, 22, 0x0a,
+
+ 0 // eod
+};
+
+static const char qt_meta_stringdata_QSignalEventGenerator[] = {
+ "QSignalEventGenerator\0\0execute()\0"
+};
+
+const QMetaObject QSignalEventGenerator::staticMetaObject = {
+ { &QObject::staticMetaObject, qt_meta_stringdata_QSignalEventGenerator,
+ qt_meta_data_QSignalEventGenerator, 0 }
+};
+
+const QMetaObject *QSignalEventGenerator::metaObject() const
+{
+ return &staticMetaObject;
+}
+
+void *QSignalEventGenerator::qt_metacast(const char *_clname)
+{
+ if (!_clname) return 0;
+ if (!strcmp(_clname, qt_meta_stringdata_QSignalEventGenerator))
+ return static_cast<void*>(const_cast< QSignalEventGenerator*>(this));
+ return QObject::qt_metacast(_clname);
+}
+
+int QSignalEventGenerator::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
+{
+ _id = QObject::qt_metacall(_c, _id, _a);
+ if (_id < 0)
+ return _id;
+ if (_c == QMetaObject::InvokeMetaMethod) {
+ switch (_id) {
+ case 0: {
+// ### in Qt 4.6 we can use QObject::senderSignalIndex()
+ QObjectPrivate *d = static_cast<QObjectPrivate *>(d_ptr);
+ int signalIndex = -1;
+ QObject *sender = this->sender();
+ if (sender && d->currentSender)
+ signalIndex = d->currentSender->signal;
+
+ Q_ASSERT(signalIndex != -1);
+ QStateMachine *machine = qobject_cast<QStateMachine*>(parent());
+ QStateMachinePrivate::get(machine)->handleTransitionSignal(sender, signalIndex, _a);
+ break;
+ }
+ default: ;
+ }
+ _id -= 1;
+ }
+ return _id;
+}
+
+QSignalEventGenerator::QSignalEventGenerator(QStateMachine *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ \class QSignalEvent
+
+ \brief The QSignalEvent class represents a Qt signal event.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A signal event is generated by a QStateMachine in response to a Qt
+ signal. The QSignalTransition class provides a transition associated with a
+ signal event. QSignalEvent is part of \l{The State Machine Framework}.
+
+ The sender() function returns the object that generated the signal. The
+ signalIndex() function returns the index of the signal. The arguments()
+ function returns the arguments of the signal.
+
+ \sa QSignalTransition
+*/
+
+/*!
+ \internal
+
+ Constructs a new QSignalEvent object with the given \a sender, \a
+ signalIndex and \a arguments.
+*/
+QSignalEvent::QSignalEvent(const QObject *sender, int signalIndex,
+ const QList<QVariant> &arguments)
+ : QEvent(QEvent::Signal), m_sender(sender),
+ m_signalIndex(signalIndex), m_arguments(arguments)
+{
+}
+
+/*!
+ Destroys this QSignalEvent.
+*/
+QSignalEvent::~QSignalEvent()
+{
+}
+
+/*!
+ \fn QSignalEvent::sender() const
+
+ Returns the object that emitted the signal.
+
+ \sa QObject::sender()
+*/
+
+/*!
+ \fn QSignalEvent::signalIndex() const
+
+ Returns the index of the signal.
+
+ \sa QMetaObject::indexOfSignal(), QMetaObject::method()
+*/
+
+/*!
+ \fn QSignalEvent::arguments() const
+
+ Returns the arguments of the signal.
+*/
+
+
+/*!
+ \class QWrappedEvent
+
+ \brief The QWrappedEvent class holds a clone of an event associated with a QObject.
+
+ \since 4.6
+ \ingroup statemachine
+
+ A wrapped event is generated by a QStateMachine in response to a Qt
+ event. The QEventTransition class provides a transition associated with a
+ such an event. QWrappedEvent is part of \l{The State Machine Framework}.
+
+ The object() function returns the object that generated the event. The
+ event() function returns a clone of the original event.
+
+ \sa QEventTransition
+*/
+
+/*!
+ \internal
+
+ Constructs a new QWrappedEvent object with the given \a object
+ and \a event.
+*/
+QWrappedEvent::QWrappedEvent(QObject *object, QEvent *event)
+ : QEvent(QEvent::Wrapped), m_object(object), m_event(event)
+{
+}
+
+/*!
+ Destroys this QWrappedEvent.
+*/
+QWrappedEvent::~QWrappedEvent()
+{
+}
+
+/*!
+ \fn QWrappedEvent::object() const
+
+ Returns the object that the event is associated with.
+*/
+
+/*!
+ \fn QWrappedEvent::event() const
+
+ Returns a clone of the original event.
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qstatemachine.cpp"
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
new file mode 100644
index 0000000..0b3c728
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -0,0 +1,170 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATEMACHINE_H
+#define QSTATEMACHINE_H
+
+#include <QtCore/qabstractstate.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qobject.h>
+#include <QtCore/qset.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QEvent;
+class QAbstractState;
+class QState;
+
+class QStateMachinePrivate;
+class QAbstractAnimation;
+class QAbstractState;
+class Q_CORE_EXPORT QStateMachine : public QObject
+{
+ Q_OBJECT
+ Q_PROPERTY(QState* rootState READ rootState)
+ Q_PROPERTY(QAbstractState* initialState READ initialState WRITE setInitialState)
+ Q_PROPERTY(QAbstractState* errorState READ errorState WRITE setErrorState)
+ Q_PROPERTY(QString errorString READ errorString)
+ Q_PROPERTY(RestorePolicy globalRestorePolicy READ globalRestorePolicy WRITE setGlobalRestorePolicy)
+ Q_ENUMS(RestorePolicy)
+#ifndef QT_NO_ANIMATION
+ Q_PROPERTY(bool animationsEnabled READ animationsEnabled WRITE setAnimationsEnabled)
+#endif
+public:
+ enum RestorePolicy {
+ DoNotRestoreProperties,
+ RestoreProperties
+ };
+
+ enum Error {
+ NoError,
+ NoInitialStateError,
+ NoDefaultStateInHistoryStateError,
+ NoCommonAncestorForTransitionError
+ };
+
+ QStateMachine(QObject *parent = 0);
+ ~QStateMachine();
+
+ void addState(QAbstractState *state);
+ void removeState(QAbstractState *state);
+
+ QState *rootState() const;
+
+ QAbstractState *initialState() const;
+ void setInitialState(QAbstractState *state);
+
+ QAbstractState *errorState() const;
+ void setErrorState(QAbstractState *state);
+
+ Error error() const;
+ QString errorString() const;
+ void clearError();
+
+ bool isRunning() const;
+
+#ifndef QT_NO_ANIMATION
+ bool animationsEnabled() const;
+ void setAnimationsEnabled(bool enabled);
+
+ void addDefaultAnimation(QAbstractAnimation *animation);
+ QList<QAbstractAnimation *> defaultAnimations() const;
+ void removeDefaultAnimation(QAbstractAnimation *animation);
+#endif // QT_NO_ANIMATION
+
+ QStateMachine::RestorePolicy globalRestorePolicy() const;
+ void setGlobalRestorePolicy(QStateMachine::RestorePolicy restorePolicy);
+
+ void postEvent(QEvent *event, int delay = 0);
+
+ QSet<QAbstractState*> configuration() const;
+
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ bool eventFilter(QObject *watched, QEvent *event);
+#endif
+
+public Q_SLOTS:
+ void start();
+ void stop();
+
+Q_SIGNALS:
+ void started();
+ void stopped();
+ void finished();
+
+protected:
+ void postInternalEvent(QEvent *event);
+
+ virtual void beginSelectTransitions(QEvent *event);
+ virtual void endSelectTransitions(QEvent *event);
+
+ virtual void beginMicrostep(QEvent *event);
+ virtual void endMicrostep(QEvent *event);
+
+ bool event(QEvent *e);
+
+protected:
+ QStateMachine(QStateMachinePrivate &dd, QObject *parent);
+
+private:
+ Q_DISABLE_COPY(QStateMachine)
+ Q_DECLARE_PRIVATE(QStateMachine)
+ Q_PRIVATE_SLOT(d_func(), void _q_start())
+ Q_PRIVATE_SLOT(d_func(), void _q_process())
+#ifndef QT_NO_ANIMATION
+ Q_PRIVATE_SLOT(d_func(), void _q_animationFinished())
+#endif
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
new file mode 100644
index 0000000..24073ca
--- /dev/null
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTATEMACHINE_P_H
+#define QSTATEMACHINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <private/qobject_p.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qset.h>
+#include <QtCore/qvector.h>
+
+#include "qstate.h"
+#include "private/qstate_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QEvent;
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+class QEventTransition;
+#endif
+class QSignalEventGenerator;
+class QSignalTransition;
+class QAbstractState;
+class QAbstractTransition;
+class QState;
+
+#ifndef QT_NO_ANIMATION
+class QAbstractAnimation;
+#endif
+
+class QStateMachine;
+class QStateMachinePrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QStateMachine)
+public:
+ enum State {
+ NotRunning,
+ Starting,
+ Running
+ };
+ enum StopProcessingReason {
+ EventQueueEmpty,
+ Finished,
+ Stopped
+ };
+
+ QStateMachinePrivate();
+ ~QStateMachinePrivate();
+
+ static QStateMachinePrivate *get(QStateMachine *q);
+
+ static QState *findLCA(const QList<QAbstractState*> &states);
+
+ static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2);
+ static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2);
+
+ QAbstractState *findErrorState(QAbstractState *context);
+ void setError(QStateMachine::Error error, QAbstractState *currentContext);
+
+ // private slots
+ void _q_start();
+ void _q_process();
+#ifndef QT_NO_ANIMATION
+ void _q_animationFinished();
+#endif
+
+ void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const;
+ QSet<QAbstractTransition*> selectTransitions(QEvent *event) const;
+ QList<QAbstractState*> exitStates(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList);
+ QList<QAbstractState*> enterStates(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions);
+ void addStatesToEnter(QAbstractState *s, QState *root,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry);
+
+ void applyProperties(const QList<QAbstractTransition*> &transitionList,
+ const QList<QAbstractState*> &exitedStates,
+ const QList<QAbstractState*> &enteredStates);
+
+ bool isInFinalState(QAbstractState *s) const;
+ static bool isFinal(const QAbstractState *s);
+ static bool isParallel(const QAbstractState *s);
+ static bool isCompound(const QAbstractState *s);
+ static bool isAtomic(const QAbstractState *s);
+ static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other);
+ static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound);
+
+ void registerTransitions(QAbstractState *state);
+ void registerSignalTransition(QSignalTransition *transition);
+ void unregisterSignalTransition(QSignalTransition *transition);
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ void registerEventTransition(QEventTransition *transition);
+ void unregisterEventTransition(QEventTransition *transition);
+#endif
+ void unregisterTransition(QAbstractTransition *transition);
+ void unregisterAllTransitions();
+ void handleTransitionSignal(const QObject *sender, int signalIndex,
+ void **args);
+ void scheduleProcess();
+
+ typedef QPair<QObject *, QByteArray> RestorableId;
+ QHash<RestorableId, QVariant> registeredRestorables;
+ void registerRestorable(QObject *object, const QByteArray &propertyName);
+ void unregisterRestorable(QObject *object, const QByteArray &propertyName);
+ bool hasRestorable(QObject *object, const QByteArray &propertyName) const;
+ QVariant restorableValue(QObject *object, const QByteArray &propertyName) const;
+ QList<QPropertyAssignment> restorablesToPropertyList(const QHash<RestorableId, QVariant> &restorables) const;
+
+ State state;
+ bool processing;
+ bool processingScheduled;
+ bool stop;
+ StopProcessingReason stopProcessingReason;
+ QState *rootState;
+ QSet<QAbstractState*> configuration;
+ QList<QEvent*> internalEventQueue;
+ QList<QEvent*> externalEventQueue;
+
+ QStateMachine::Error error;
+ QStateMachine::RestorePolicy globalRestorePolicy;
+
+ QString errorString;
+ QSet<QAbstractState *> pendingErrorStates;
+ QSet<QAbstractState *> pendingErrorStatesForDefaultEntry;
+ QAbstractState *initialErrorStateForRoot;
+
+#ifndef QT_NO_ANIMATION
+ bool animationsEnabled;
+
+ QPair<QList<QAbstractAnimation*>, QList<QAbstractAnimation*> >
+ initializeAnimation(QAbstractAnimation *abstractAnimation,
+ const QPropertyAssignment &prop);
+
+ QHash<QAbstractState*, QList<QAbstractAnimation*> > animationsForState;
+ QHash<QAbstractAnimation*, QPropertyAssignment> propertyForAnimation;
+ QHash<QAbstractAnimation*, QAbstractState*> stateForAnimation;
+ QSet<QAbstractAnimation*> resetAnimationEndValues;
+
+ QList<QAbstractAnimation *> defaultAnimations;
+ QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForSource;
+ QMultiHash<QAbstractState *, QAbstractAnimation *> defaultAnimationsForTarget;
+
+#endif // QT_NO_ANIMATION
+
+ QSignalEventGenerator *signalEventGenerator;
+
+ QHash<const QObject*, QVector<int> > connections;
+#ifndef QT_NO_STATEMACHINE_EVENTFILTER
+ QHash<QObject*, QHash<QEvent::Type, int> > qobjectEvents;
+#endif
+ QHash<int, QEvent*> delayedEvents;
+
+ typedef QEvent* (*f_cloneEvent)(QEvent*);
+ struct Handler {
+ f_cloneEvent cloneEvent;
+ };
+
+ static Q_CORE_EXPORT const Handler *handler;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/corelib/statemachine/qwrappedevent.h b/src/corelib/statemachine/qwrappedevent.h
new file mode 100644
index 0000000..cb4261b
--- /dev/null
+++ b/src/corelib/statemachine/qwrappedevent.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWRAPPEDEVENT_H
+#define QWRAPPEDEVENT_H
+
+#include <QtCore/qcoreevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QObject;
+
+class Q_CORE_EXPORT QWrappedEvent : public QEvent
+{
+public:
+ QWrappedEvent(QObject *object, QEvent *event);
+ ~QWrappedEvent();
+
+ inline QObject *object() const { return m_object; }
+ inline QEvent *event() const { return m_event; }
+
+private:
+ QObject *m_object;
+ QEvent *m_event;
+
+private:
+ Q_DISABLE_COPY(QWrappedEvent)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/statemachine/statemachine.pri b/src/corelib/statemachine/statemachine.pri
new file mode 100644
index 0000000..5b19bc1
--- /dev/null
+++ b/src/corelib/statemachine/statemachine.pri
@@ -0,0 +1,30 @@
+HEADERS += $$PWD/qstatemachine.h \
+ $$PWD/qstatemachine_p.h \
+ $$PWD/qsignaleventgenerator_p.h \
+ $$PWD/qabstractstate.h \
+ $$PWD/qabstractstate_p.h \
+ $$PWD/qstate.h \
+ $$PWD/qstate_p.h \
+ $$PWD/qfinalstate.h \
+ $$PWD/qhistorystate.h \
+ $$PWD/qhistorystate_p.h \
+ $$PWD/qabstracttransition.h \
+ $$PWD/qabstracttransition_p.h \
+ $$PWD/qsignalevent.h \
+ $$PWD/qsignaltransition.h \
+ $$PWD/qsignaltransition_p.h
+
+SOURCES += $$PWD/qstatemachine.cpp \
+ $$PWD/qabstractstate.cpp \
+ $$PWD/qstate.cpp \
+ $$PWD/qfinalstate.cpp \
+ $$PWD/qhistorystate.cpp \
+ $$PWD/qabstracttransition.cpp \
+ $$PWD/qsignaltransition.cpp
+
+!contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) {
+HEADERS += $$PWD/qwrappedevent.h \
+ $$PWD/qeventtransition.h \
+ $$PWD/qeventtransition_p.h
+SOURCES += $$PWD/qeventtransition.cpp
+}
diff --git a/src/corelib/thread/qmutexpool.cpp b/src/corelib/thread/qmutexpool.cpp
index 96a9940..0d7c890 100644
--- a/src/corelib/thread/qmutexpool.cpp
+++ b/src/corelib/thread/qmutexpool.cpp
@@ -49,7 +49,7 @@ QT_BEGIN_NAMESPACE
// qt_global_mutexpool is here for backwards compatability only,
// use QMutexpool::instance() in new clode.
Q_CORE_EXPORT QMutexPool *qt_global_mutexpool = 0;
-Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (true))
+Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (QMutex::Recursive))
/*!
\class QMutexPool
@@ -88,17 +88,17 @@ Q_GLOBAL_STATIC_WITH_ARGS(QMutexPool, globalMutexPool, (true))
*/
/*!
- Constructs a QMutexPool, reserving space for \a size QMutexes. If
- \a recursive is true, all QMutexes in the pool will be recursive
- mutexes; otherwise they will all be non-recursive (the default).
+ Constructs a QMutexPool, reserving space for \a size QMutexes. All
+ mutexes in the pool are created with \a recursionMode. By default,
+ all mutexes are non-recursive.
The QMutexes are created when needed, and deleted when the
QMutexPool is destructed.
*/
-QMutexPool::QMutexPool(bool recursive, int size)
- : mutexes(size), count(size), recurs(recursive)
+QMutexPool::QMutexPool(QMutex::RecursionMode recursionMode, int size)
+ : mutexes(size), recursionMode(recursionMode)
{
- for (int index = 0; index < count; ++index) {
+ for (int index = 0; index < mutexes.count(); ++index) {
mutexes[index] = 0;
}
}
@@ -109,7 +109,7 @@ QMutexPool::QMutexPool(bool recursive, int size)
*/
QMutexPool::~QMutexPool()
{
- for (int index = 0; index < count; ++index) {
+ for (int index = 0; index < mutexes.count(); ++index) {
delete mutexes[index];
mutexes[index] = 0;
}
@@ -130,11 +130,11 @@ QMutexPool *QMutexPool::instance()
QMutex *QMutexPool::get(const void *address)
{
Q_ASSERT_X(address != 0, "QMutexPool::get()", "'address' argument cannot be zero");
- int index = int((quintptr(address) >> (sizeof(address) >> 1)) % count);
+ int index = int((quintptr(address) >> (sizeof(address) >> 1)) % mutexes.count());
if (!mutexes[index]) {
// mutex not created, create one
- QMutex *newMutex = new QMutex(recurs ? QMutex::Recursive : QMutex::NonRecursive);
+ QMutex *newMutex = new QMutex(recursionMode);
if (!mutexes[index].testAndSetOrdered(0, newMutex))
delete newMutex;
}
diff --git a/src/corelib/thread/qmutexpool_p.h b/src/corelib/thread/qmutexpool_p.h
index 1009ebb..30a16d4 100644
--- a/src/corelib/thread/qmutexpool_p.h
+++ b/src/corelib/thread/qmutexpool_p.h
@@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE
class Q_CORE_EXPORT QMutexPool
{
public:
- explicit QMutexPool(bool recursive = false, int size = 128);
+ explicit QMutexPool(QMutex::RecursionMode recursionMode = QMutex::NonRecursive, int size = 131);
~QMutexPool();
QMutex *get(const void *address);
@@ -72,9 +72,8 @@ public:
static QMutex *globalInstanceGet(const void *address);
private:
- QVarLengthArray<QAtomicPointer<QMutex>, 128> mutexes;
- int count;
- bool recurs;
+ QVarLengthArray<QAtomicPointer<QMutex>, 131> mutexes;
+ QMutex::RecursionMode recursionMode;
};
extern Q_CORE_EXPORT QMutexPool *qt_global_mutexpool;
diff --git a/src/corelib/thread/qthread.cpp b/src/corelib/thread/qthread.cpp
index f1bdc64..a2b944d 100644
--- a/src/corelib/thread/qthread.cpp
+++ b/src/corelib/thread/qthread.cpp
@@ -113,12 +113,6 @@ QThreadData::~QThreadData()
// fprintf(stderr, "QThreadData %p destroyed\n", this);
}
-QThreadData *QThreadData::get2(QThread *thread)
-{
- Q_ASSERT_X(thread != 0, "QThread", "internal error");
- return thread->d_func()->data;
-}
-
void QThreadData::ref()
{
#ifndef QT_NO_THREAD
diff --git a/src/corelib/thread/qthread_p.h b/src/corelib/thread/qthread_p.h
index 0bf773c..c575005 100644
--- a/src/corelib/thread/qthread_p.h
+++ b/src/corelib/thread/qthread_p.h
@@ -111,51 +111,6 @@ public:
{ }
};
-class Q_CORE_EXPORT QThreadData
-{
- QAtomicInt _ref;
-
-public:
- QThreadData(int initialRefCount = 1);
- ~QThreadData();
-
- static QThreadData *current();
- static QThreadData *get2(QThread *thread);
-
- void ref();
- void deref();
-
- QThread *thread;
- bool quitNow;
- int loopLevel;
- QAbstractEventDispatcher *eventDispatcher;
- QStack<QEventLoop *> eventLoops;
- QPostEventList postEventList;
- bool canWait;
- QMap<int, void *> tls;
-
- QMutex mutex;
-
-# ifdef Q_OS_SYMBIAN
- RThread symbian_thread_handle;
-# endif
-};
-
-// thread wrapper for the main() thread
-class QAdoptedThread : public QThread
-{
- Q_DECLARE_PRIVATE(QThread)
-
-public:
- QAdoptedThread(QThreadData *data = 0);
- ~QAdoptedThread();
- void init();
-
- static QThread *createThreadForAdoption();
-private:
- void run();
-};
-
#ifndef QT_NO_THREAD
class QThreadPrivate : public QObjectPrivate
{
@@ -224,6 +179,38 @@ public:
#endif // QT_NO_THREAD
+class QThreadData
+{
+ QAtomicInt _ref;
+
+public:
+ QThreadData(int initialRefCount = 1);
+ ~QThreadData();
+
+ static QThreadData *current();
+ static QThreadData *get2(QThread *thread)
+ { Q_ASSERT_X(thread != 0, "QThread", "internal error"); return thread->d_func()->data; }
+
+
+ void ref();
+ void deref();
+
+ QThread *thread;
+ bool quitNow;
+ int loopLevel;
+ QAbstractEventDispatcher *eventDispatcher;
+ QStack<QEventLoop *> eventLoops;
+ QPostEventList postEventList;
+ bool canWait;
+ QMap<int, void *> tls;
+
+ QMutex mutex;
+
+# ifdef Q_OS_SYMBIAN
+ RThread symbian_thread_handle;
+# endif
+};
+
QT_END_NAMESPACE
#endif // QTHREAD_P_H
diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp
index 7168a9a..5653842 100644
--- a/src/corelib/tools/qbitarray.cpp
+++ b/src/corelib/tools/qbitarray.cpp
@@ -655,6 +655,7 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
QBitArray stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
/*!
\relates QBitArray
@@ -662,7 +663,7 @@ QBitArray operator^(const QBitArray &a1, const QBitArray &a2)
\sa \link datastreamformat.html Format of the QDataStream operators \endlink
*/
-#ifndef QT_NO_DATASTREAM
+
QDataStream &operator<<(QDataStream &out, const QBitArray &ba)
{
quint32 len = ba.size();
@@ -715,7 +716,7 @@ QDataStream &operator>>(QDataStream &in, QBitArray &ba)
*ba.d.data() = ba.d.size() * 8 - len;
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
\fn DataPtr &QBitArray::data_ptr()
diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp
index ae6561f..f73adf8 100644
--- a/src/corelib/tools/qbytearray.cpp
+++ b/src/corelib/tools/qbytearray.cpp
@@ -579,7 +579,7 @@ static inline char qToLower(char c)
return c;
}
-Q_CORE_EXPORT QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
+QByteArray::Data QByteArray::shared_null = {Q_BASIC_ATOMIC_INITIALIZER(1),
0, 0, shared_null.array, {0} };
QByteArray::Data QByteArray::shared_empty = { Q_BASIC_ATOMIC_INITIALIZER(1),
0, 0, shared_empty.array, {0} };
@@ -2581,6 +2581,8 @@ void QByteArray::clear()
d->ref.ref();
}
+#ifndef QT_NO_DATASTREAM
+
/*! \relates QByteArray
Writes byte array \a ba to the stream \a out and returns a reference
@@ -2588,7 +2590,6 @@ void QByteArray::clear()
\sa {Format of the QDataStream operators}
*/
-#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &out, const QByteArray &ba)
{
@@ -2631,7 +2632,7 @@ QDataStream &operator>>(QDataStream &in, QByteArray &ba)
return in;
}
-#endif //QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
/*! \fn bool QByteArray::operator==(const QString &str) const
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index a940cda..250dad0 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -1321,7 +1321,7 @@ QDataStream &operator>>(QDataStream &in, QChar &chr)
chr.unicode() = ushort(u);
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
\fn ushort & QChar::unicode()
diff --git a/src/corelib/tools/qcontiguouscache.cpp b/src/corelib/tools/qcontiguouscache.cpp
new file mode 100644
index 0000000..fc75cc0
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.cpp
@@ -0,0 +1,432 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcontiguouscache.h"
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+#include <QDebug>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+void QContiguousCacheData::dump() const
+{
+ qDebug() << "capacity:" << alloc;
+ qDebug() << "count:" << count;
+ qDebug() << "start:" << start;
+ qDebug() << "offset:" << offset;
+}
+#endif
+
+/*! \class QContiguousCache
+ \brief The QContiguousCache class is a template class that provides a contiguous cache.
+ \ingroup tools
+ \ingroup shared
+ \reentrant
+
+ The QContiguousCache class provides an efficient way of caching items for
+ display in a user interface view. Unlike QCache, it adds a restriction
+ that elements within the cache are contiguous. This has the advantage
+ of matching how user interface views most commonly request data, as
+ a set of rows localized around the current scrolled position. This
+ restriction allows the cache to consume less memory and processor
+ cycles than QCache. The QContiguousCache class also can provide
+ an upper bound on memory usage via setCapacity().
+
+ The simplest way of using a contiguous cache is to use the append()
+ and prepend().
+
+\code
+MyRecord record(int row) const
+{
+ Q_ASSERT(row >= 0 && row < count());
+
+ while(row > cache.lastIndex())
+ cache.append(slowFetchRecord(cache.lastIndex()+1));
+ while(row < cache.firstIndex())
+ cache.prepend(slowFetchRecord(cache.firstIndex()-1));
+
+ return cache.at(row);
+}
+\endcode
+
+ If the cache is full then the item at the opposite end of the cache from
+ where the new item is appended or prepended will be removed.
+
+ This usage can be further optimized by using the insert() function
+ in the case where the requested row is a long way from the currently cached
+ items. If there is a gap between where the new item is inserted and the currently
+ cached items then the existing cached items are first removed to retain
+ the contiguous nature of the cache. Hence it is important to take some care then
+ when using insert() in order to avoid unwanted clearing of the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Calling prepend() such that the first index would become less
+ than 0 or append() such that the last index would become greater
+ than INT_MAX can result in the indexes of the cache being invalid.
+ When the cache indexes are invalid it is important to call
+ normalizeIndexes() before calling any of containsIndex(), firstIndex(),
+ lastIndex(), at() or the [] operator. Calling these
+ functions when the cache has invalid indexes will result in undefined
+ behavior. The indexes can be checked by using areIndexesValid()
+
+ In most cases the indexes will not exceed 0 to INT_MAX, and
+ normalizeIndexes() will not need to be used.
+
+ See the \l{Contiguous Cache Example}{Contiguous Cache} example.
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(int capacity)
+
+ Constructs a cache with the given \a capacity.
+
+ \sa setCapacity()
+*/
+
+/*! \fn QContiguousCache::QContiguousCache(const QContiguousCache<T> &other)
+
+ Constructs a copy of \a other.
+
+ This operation takes \l{constant time}, because QContiguousCache is
+ \l{implicitly shared}. This makes returning a QContiguousCache from a
+ function very fast. If a shared instance is modified, it will be
+ copied (copy-on-write), and that takes \l{linear time}.
+
+ \sa operator=()
+*/
+
+/*! \fn QContiguousCache::~QContiguousCache()
+
+ Destroys the cache.
+*/
+
+/*! \fn void QContiguousCache::detach()
+
+ \internal
+*/
+
+/*! \fn bool QContiguousCache::isDetached() const
+
+ \internal
+*/
+
+/*! \fn void QContiguousCache::setSharable(bool sharable)
+
+ \internal
+*/
+
+/*! \fn QContiguousCache<T> &QContiguousCache::operator=(const QContiguousCache<T> &other)
+
+ Assigns \a other to this cache and returns a reference to this cache.
+*/
+
+/*! \fn bool QContiguousCache::operator==(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is equal to this cache; otherwise returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator!=()
+*/
+
+/*! \fn bool QContiguousCache::operator!=(const QContiguousCache<T> &other) const
+
+ Returns true if \a other is not equal to this cache; otherwise
+ returns false.
+
+ Two caches are considered equal if they contain the same values at the same
+ indexes. This function requires the value type to implement the \c operator==().
+
+ \sa operator==()
+*/
+
+/*! \fn int QContiguousCache::capacity() const
+
+ Returns the number of items the cache can store before it is full.
+ When a cache contains a number of items equal to its capacity, adding new
+ items will cause items farthest from the added item to be removed.
+
+ \sa setCapacity(), size()
+*/
+
+/*! \fn int QContiguousCache::count() const
+
+ \overload
+
+ Same as size().
+*/
+
+/*! \fn int QContiguousCache::size() const
+
+ Returns the number of items contained within the cache.
+
+ \sa capacity()
+*/
+
+/*! \fn bool QContiguousCache::isEmpty() const
+
+ Returns true if no items are stored within the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn bool QContiguousCache::isFull() const
+
+ Returns true if the number of items stored within the cache is equal
+ to the capacity of the cache.
+
+ \sa size(), capacity()
+*/
+
+/*! \fn int QContiguousCache::available() const
+
+ Returns the number of items that can be added to the cache before it becomes full.
+
+ \sa size(), capacity(), isFull()
+*/
+
+/*! \fn void QContiguousCache::clear()
+
+ Removes all items from the cache. The capacity is unchanged.
+*/
+
+/*! \fn void QContiguousCache::setCapacity(int size)
+
+ Sets the capacity of the cache to the given \a size. A cache can hold a
+ number of items equal to its capacity. When inserting, appending or prepending
+ items to the cache, if the cache is already full then the item farthest from
+ the added item will be removed.
+
+ If the given \a size is smaller than the current count of items in the cache
+ then only the last \a size items from the cache will remain.
+
+ \sa capacity(), isFull()
+*/
+
+/*! \fn const T &QContiguousCache::at(int i) const
+
+ Returns the item at index position \a i in the cache. \a i must
+ be a valid index position in the cache (i.e, firstIndex() <= \a i <= lastIndex()).
+
+ The indexes in the cache refer to the number of positions the item is from the
+ first item appended into the cache. That is to say a cache with a capacity of
+ 100, that has had 150 items appended will have a valid index range of
+ 50 to 149. This allows inserting and retrieving items into the cache based
+ on a theoretical infinite list
+
+ \sa firstIndex(), lastIndex(), insert(), operator[]()
+*/
+
+/*! \fn T &QContiguousCache::operator[](int i)
+
+ Returns the item at index position \a i as a modifiable reference. If
+ the cache does not contain an item at the given index position \a i
+ then it will first insert an empty item at that position.
+
+ In most cases it is better to use either at() or insert().
+
+ Note that using non-const operators can cause QContiguousCache to do a deep
+ copy.
+
+ \sa insert(), at()
+*/
+
+/*! \fn const T &QContiguousCache::operator[](int i) const
+
+ \overload
+
+ Same as at(\a i).
+*/
+
+/*! \fn void QContiguousCache::append(const T &value)
+
+ Inserts \a value at the end of the cache. If the cache is already full
+ the item at the start of the cache will be removed.
+
+ \sa prepend(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::prepend(const T &value)
+
+ Inserts \a value at the start of the cache. If the cache is already full
+ the item at the end of the cache will be removed.
+
+ \sa append(), insert(), isFull()
+*/
+
+/*! \fn void QContiguousCache::insert(int i, const T &value)
+
+ Inserts the \a value at the index position \a i. If the cache already contains
+ an item at \a i then that value is replaced. If \a i is either one more than
+ lastIndex() or one less than firstIndex() it is the equivalent to an append()
+ or a prepend().
+
+ If the given index \a i is not within the current range of the cache nor adjacent
+ to the bounds of the cache's index range, the cache is first cleared before
+ inserting the item. At this point the cache will have a size of 1. It is
+ worthwhile taking effort to insert items in an order that starts adjacent
+ to the current index range for the cache.
+
+ The range of valid indexes for the QContiguousCache class are from
+ 0 to INT_MAX. Inserting outside of this range has undefined behavior.
+
+
+ \sa prepend(), append(), isFull(), firstIndex(), lastIndex()
+*/
+
+/*! \fn bool QContiguousCache::containsIndex(int i) const
+
+ Returns true if the cache's index range includes the given index \a i.
+
+ \sa firstIndex(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::firstIndex() const
+
+ Returns the first valid index in the cache. The index will be invalid if the
+ cache is empty.
+
+ \sa capacity(), size(), lastIndex()
+*/
+
+/*! \fn int QContiguousCache::lastIndex() const
+
+ Returns the last valid index in the cache. The index will be invalid if the cache is empty.
+
+ \sa capacity(), size(), firstIndex()
+*/
+
+
+/*! \fn T &QContiguousCache::first()
+
+ Returns a reference to the first item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa last(), isEmpty()
+*/
+
+/*! \fn T &QContiguousCache::last()
+
+ Returns a reference to the last item in the cache. This function
+ assumes that the cache isn't empty.
+
+ \sa first(), isEmpty()
+*/
+
+/*! \fn const T& QContiguousCache::first() const
+
+ \overload
+*/
+
+/*! \fn const T& QContiguousCache::last() const
+
+ \overload
+*/
+
+/*! \fn void QContiguousCache::removeFirst()
+
+ Removes the first item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeLast()
+*/
+
+/*! \fn void QContiguousCache::removeLast()
+
+ Removes the last item from the cache. This function assumes that
+ the cache isn't empty.
+
+ \sa removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeFirst()
+
+ Removes the first item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeFirst() is more efficient.
+
+ \sa takeLast(), removeFirst()
+*/
+
+/*! \fn T QContiguousCache::takeLast()
+
+ Removes the last item in the cache and returns it. This function
+ assumes that the cache isn't empty.
+
+ If you don't use the return value, removeLast() is more efficient.
+
+ \sa takeFirst(), removeLast()
+*/
+
+/*! \fn void QContiguousCache::normalizeIndexes()
+
+ Moves the first index and last index of the cache
+ such that they point to valid indexes. The function does not modify
+ the contents of the cache or the ordering of elements within the cache.
+
+ It is provided so that index overflows can be corrected when using the
+ cache as a circular buffer.
+
+ \code
+ QContiguousCache<int> cache(10);
+ cache.insert(INT_MAX, 1); // cache contains one value and has valid indexes, INT_MAX to INT_MAX
+ cache.append(2); // cache contains two values but does not have valid indexes.
+ cache.normalizeIndexes(); // cache has two values, 1 and 2. New first index will be in the range of 0 to capacity().
+ \endcode
+
+ \sa areIndexesValid(), append(), prepend()
+*/
+
+/*! \fn bool QContiguousCache::areIndexesValid() const
+
+ Returns whether the indexes for items stored in the cache are valid.
+ Indexes can become invalid if items are appended after the index position
+ INT_MAX or prepended before the index position 0. This is only expected
+ to occur in very long lived circular buffer style usage of the
+ contiguous cache. Indexes can be made valid again by calling
+ normalizeIndexs().
+
+ \sa normalizeIndexes(), append(), prepend()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qcontiguouscache.h b/src/corelib/tools/qcontiguouscache.h
new file mode 100644
index 0000000..2437f63
--- /dev/null
+++ b/src/corelib/tools/qcontiguouscache.h
@@ -0,0 +1,430 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCONTIGUOUSCACHE_H
+#define QCONTIGUOUSCACHE_H
+
+#include <QtCore/qatomic.h>
+#include <limits.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+#undef QT_QCONTIGUOUSCACHE_DEBUG
+QT_MODULE(Core)
+
+
+struct Q_CORE_EXPORT QContiguousCacheData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const;
+#endif
+};
+
+template <typename T>
+struct QContiguousCacheTypedData
+{
+ QBasicAtomicInt ref;
+ int alloc;
+ int count;
+ int start;
+ int offset;
+ uint sharable : 1;
+
+ T array[1];
+};
+
+template<typename T>
+class QContiguousCache {
+ typedef QContiguousCacheTypedData<T> Data;
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; };
+public:
+ explicit QContiguousCache(int capacity = 0);
+ QContiguousCache(const QContiguousCache<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
+
+ inline ~QContiguousCache() { if (!d) return; if (!d->ref.deref()) free(d); }
+
+ inline void detach() { if (d->ref != 1) detach_helper(); }
+ inline bool isDetached() const { return d->ref == 1; }
+ inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
+
+ QContiguousCache<T> &operator=(const QContiguousCache<T> &other);
+ bool operator==(const QContiguousCache<T> &other) const;
+ inline bool operator!=(const QContiguousCache<T> &other) const { return !(*this == other); }
+
+ inline int capacity() const {return d->alloc; }
+ inline int count() const { return d->count; }
+ inline int size() const { return d->count; }
+
+ inline bool isEmpty() const { return d->count == 0; }
+ inline bool isFull() const { return d->count == d->alloc; }
+ inline int available() const { return d->alloc - d->count; }
+
+ void clear();
+ void setCapacity(int size);
+
+ const T &at(int pos) const;
+ T &operator[](int i);
+ const T &operator[](int i) const;
+
+ void append(const T &value);
+ void prepend(const T &value);
+ void insert(int pos, const T &value);
+
+ inline bool containsIndex(int pos) const { return pos >= d->offset && pos - d->offset < d->count; }
+ inline int firstIndex() const { return d->offset; }
+ inline int lastIndex() const { return d->offset + d->count - 1; }
+
+ inline const T &first() const { Q_ASSERT(!isEmpty()); return d->array[d->start]; }
+ inline const T &last() const { Q_ASSERT(!isEmpty()); return d->array[(d->start + d->count -1) % d->alloc]; }
+ inline T &first() { Q_ASSERT(!isEmpty()); detach(); return d->array[d->start]; }
+ inline T &last() { Q_ASSERT(!isEmpty()); detach(); return d->array[(d->start + d->count -1) % d->alloc]; }
+
+ void removeFirst();
+ T takeFirst();
+ void removeLast();
+ T takeLast();
+
+ inline bool areIndexesValid() const
+ { return d->offset >= 0 && d->offset < INT_MAX - d->count && (d->offset % d->alloc) == d->start; }
+
+ inline void normalizeIndexes() { d->offset = d->start; }
+
+#ifdef QT_QCONTIGUOUSCACHE_DEBUG
+ void dump() const { p->dump(); }
+#endif
+private:
+ void detach_helper();
+
+ QContiguousCacheData *malloc(int aalloc);
+ void free(Data *x);
+ int sizeOfTypedData() {
+ // this is more or less the same as sizeof(Data), except that it doesn't
+ // count the padding at the end
+ return reinterpret_cast<const char *>(&(reinterpret_cast<const Data *>(this))->array[1]) - reinterpret_cast<const char *>(this);
+ }
+};
+
+template <typename T>
+void QContiguousCache<T>::detach_helper()
+{
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+
+ x.p = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->count = d->count;
+ x.d->start = d->start;
+ x.d->offset = d->offset;
+ x.d->alloc = d->alloc;
+ x.d->sharable = true;
+
+ T *dest = x.d->array + x.d->start;
+ T *src = d->array + d->start;
+ int count = x.d->count;
+ while (count--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ dest++;
+ if (dest == x.d->array + x.d->alloc)
+ dest = x.d->array;
+ src++;
+ if (src == d->array + d->alloc)
+ src = d->array;
+ }
+
+ if (!d->ref.deref())
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::setCapacity(int asize)
+{
+ if (asize == d->alloc)
+ return;
+ detach();
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+ x.p = malloc(asize);
+ x.d->alloc = asize;
+ x.d->count = qMin(d->count, asize);
+ x.d->offset = d->offset + d->count - x.d->count;
+ x.d->start = x.d->offset % x.d->alloc;
+ T *dest = x.d->array + (x.d->start + x.d->count-1) % x.d->alloc;
+ T *src = d->array + (d->start + d->count-1) % d->alloc;
+ int count = x.d->count;
+ while (count--) {
+ if (QTypeInfo<T>::isComplex) {
+ new (dest) T(*src);
+ } else {
+ *dest = *src;
+ }
+ if (dest == x.d->array)
+ dest = x.d->array + x.d->alloc;
+ dest--;
+ if (src == d->array)
+ src = d->array + d->alloc;
+ src--;
+ }
+ /* free old */
+ free(d);
+ d = x.d;
+}
+
+template <typename T>
+void QContiguousCache<T>::clear()
+{
+ if (d->ref == 1) {
+ if (QTypeInfo<T>::isComplex) {
+ int count = d->count;
+ T * i = d->array + d->start;
+ T * e = d->array + d->alloc;
+ while (count--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = d->array;
+ }
+ }
+ d->count = d->start = d->offset = 0;
+ } else {
+ union { QContiguousCacheData *p; QContiguousCacheTypedData<T> *d; } x;
+ x.p = malloc(d->alloc);
+ x.d->ref = 1;
+ x.d->alloc = d->alloc;
+ x.d->count = x.d->start = x.d->offset = 0;
+ x.d->sharable = true;
+ if (!d->ref.deref()) free(d);
+ d = x.d;
+ }
+}
+
+template <typename T>
+inline QContiguousCacheData *QContiguousCache<T>::malloc(int aalloc)
+{
+ return static_cast<QContiguousCacheData *>(qMalloc(sizeOfTypedData() + (aalloc - 1) * sizeof(T)));
+}
+
+template <typename T>
+QContiguousCache<T>::QContiguousCache(int capacity)
+{
+ p = malloc(capacity);
+ d->ref = 1;
+ d->alloc = capacity;
+ d->count = d->start = d->offset = 0;
+ d->sharable = true;
+}
+
+template <typename T>
+QContiguousCache<T> &QContiguousCache<T>::operator=(const QContiguousCache<T> &other)
+{
+ other.d->ref.ref();
+ if (!d->ref.deref())
+ free(d);
+ d = other.d;
+ if (!d->sharable)
+ detach_helper();
+ return *this;
+}
+
+template <typename T>
+bool QContiguousCache<T>::operator==(const QContiguousCache<T> &other) const
+{
+ if (other.d == d)
+ return true;
+ if (other.d->start != d->start
+ || other.d->count != d->count
+ || other.d->offset != d->offset
+ || other.d->alloc != d->alloc)
+ return false;
+ for (int i = firstIndex(); i <= lastIndex(); ++i)
+ if (!(at(i) == other.at(i)))
+ return false;
+ return true;
+}
+
+template <typename T>
+void QContiguousCache<T>::free(Data *x)
+{
+ if (QTypeInfo<T>::isComplex) {
+ int count = d->count;
+ T * i = d->array + d->start;
+ T * e = d->array + d->alloc;
+ while (count--) {
+ i->~T();
+ i++;
+ if (i == e)
+ i = d->array;
+ }
+ }
+ qFree(x);
+}
+template <typename T>
+void QContiguousCache<T>::append(const T &value)
+{
+ detach();
+ if (QTypeInfo<T>::isComplex) {
+ if (d->count == d->alloc)
+ (d->array + (d->start+d->count) % d->alloc)->~T();
+ new (d->array + (d->start+d->count) % d->alloc) T(value);
+ } else {
+ d->array[(d->start+d->count) % d->alloc] = value;
+ }
+
+ if (d->count == d->alloc) {
+ d->start++;
+ d->start %= d->alloc;
+ d->offset++;
+ } else {
+ d->count++;
+ }
+}
+
+template<typename T>
+void QContiguousCache<T>::prepend(const T &value)
+{
+ detach();
+ if (d->start)
+ d->start--;
+ else
+ d->start = d->alloc-1;
+ d->offset--;
+
+ if (d->count != d->alloc)
+ d->count++;
+ else
+ if (d->count == d->alloc)
+ (d->array + d->start)->~T();
+
+ if (QTypeInfo<T>::isComplex)
+ new (d->array + d->start) T(value);
+ else
+ d->array[d->start] = value;
+}
+
+template<typename T>
+void QContiguousCache<T>::insert(int pos, const T &value)
+{
+ Q_ASSERT_X(pos >= 0 && pos < INT_MAX, "QContiguousCache<T>::insert", "index out of range");
+ detach();
+ if (containsIndex(pos)) {
+ if(QTypeInfo<T>::isComplex)
+ new (d->array + pos % d->alloc) T(value);
+ else
+ d->array[pos % d->alloc] = value;
+ } else if (pos == d->offset-1)
+ prepend(value);
+ else if (pos == d->offset+d->count)
+ append(value);
+ else {
+ // we don't leave gaps.
+ clear();
+ d->offset = pos;
+ d->start = pos % d->alloc;
+ d->count = 1;
+ if (QTypeInfo<T>::isComplex)
+ new (d->array + d->start) T(value);
+ else
+ d->array[d->start] = value;
+ }
+}
+
+template <typename T>
+inline const T &QContiguousCache<T>::at(int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+template <typename T>
+inline const T &QContiguousCache<T>::operator[](int pos) const
+{ Q_ASSERT_X(pos >= d->offset && pos - d->offset < d->count, "QContiguousCache<T>::at", "index out of range"); return d->array[pos % d->alloc]; }
+
+template <typename T>
+inline T &QContiguousCache<T>::operator[](int pos)
+{
+ detach();
+ if (!containsIndex(pos))
+ insert(pos, T());
+ return d->array[pos % d->alloc];
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeFirst()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (d->array + d->start)->~T();
+ d->start = (d->start + 1) % d->alloc;
+ d->offset++;
+}
+
+template <typename T>
+inline void QContiguousCache<T>::removeLast()
+{
+ Q_ASSERT(d->count > 0);
+ detach();
+ d->count--;
+ if (QTypeInfo<T>::isComplex)
+ (d->array + (d->start + d->count) % d->alloc)->~T();
+}
+
+template <typename T>
+inline T QContiguousCache<T>::takeFirst()
+{ T t = first(); removeFirst(); return t; }
+
+template <typename T>
+inline T QContiguousCache<T>::takeLast()
+{ T t = last(); removeLast(); return t; }
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index b43891c..356c56e 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -3831,19 +3831,19 @@ void QDateTimePrivate::getUTC(QDate &outDate, QTime &outTime) const
#if !defined(QT_NO_DEBUG_STREAM) && !defined(QT_NO_DATESTRING)
QDebug operator<<(QDebug dbg, const QDate &date)
{
- dbg.nospace() << "QDate(" << date.toString() << ")";
+ dbg.nospace() << "QDate(" << date.toString() << ')';
return dbg.space();
}
QDebug operator<<(QDebug dbg, const QTime &time)
{
- dbg.nospace() << "QTime(" << time.toString() << ")";
+ dbg.nospace() << "QTime(" << time.toString() << ')';
return dbg.space();
}
QDebug operator<<(QDebug dbg, const QDateTime &date)
{
- dbg.nospace() << "QDateTime(" << date.toString() << ")";
+ dbg.nospace() << "QDateTime(" << date.toString() << ')';
return dbg.space();
}
#endif
@@ -4686,7 +4686,7 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos
if (fixup && tmpstate == Intermediate && used < sn.count) {
const FieldInfo fi = fieldInfo(index);
if ((fi & (Numeric|FixedWidth)) == (Numeric|FixedWidth)) {
- const QString newText = QString(QLatin1String("%1")).arg(num, sn.count, 10, QLatin1Char('0'));
+ const QString newText = QString::fromLatin1("%1").arg(num, sn.count, 10, QLatin1Char('0'));
input.replace(pos, used, newText);
used = sn.count;
}
diff --git a/src/corelib/tools/qdumper.cpp b/src/corelib/tools/qdumper.cpp
deleted file mode 100644
index c3b8524..0000000
--- a/src/corelib/tools/qdumper.cpp
+++ /dev/null
@@ -1,1157 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtCore module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qdatetime.h>
-#include <qdebug.h>
-#include <qdir.h>
-#include <qfileinfo.h>
-#include <qhash.h>
-#include <qmap.h>
-#include <qmetaobject.h>
-#include <qobject.h>
-#include <qstring.h>
-#include <qvariant.h>
-#include <qvector.h>
-
-#if !defined(Q_OS_WINCE) && !defined(QT_NO_DUMPER)
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#ifdef Q_OS_WIN
-# include <windows.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-namespace {
-
-// This is used to abort evaluation of custom data dumpers in a "coordinated"
-// way. Abortion will happen anyway when we try to access a non-initialized
-// non-trivial object, so there is no way to prevent this from occuring at all
-// conceptionally. Gdb will catch SIGSEGV and return to the calling frame.
-// This is just fine provided we only _read_ memory in the custom handlers
-// below.
-
-volatile int qProvokeSegFaultHelper;
-
-static void qCheckAccess(const void *d)
-{
- // provoke segfault when address is not readable
- qProvokeSegFaultHelper = *(char*)d;
-}
-
-static void qCheckPointer(const void *d)
-{
- if (!d)
- return;
- qProvokeSegFaultHelper = *(char*)d;
-}
-
-static void qProvokeSegFault()
-{
- // provoke segfault unconditionally
- qCheckAccess(0);
-}
-
-static char qDumpInBuffer[100];
-static char qDumpBuffer[1000];
-#ifdef Q_OS_WIN
-static char qDumpBuffer2[sizeof(qDumpBuffer) + 100];
-#endif
-
-static char toHex(int n)
-{
- return n < 10 ? '0' + n : 'a' - 10 + n;
-}
-
-
-struct QDumper
-{
- explicit QDumper();
- ~QDumper();
- void flush();
- QDumper &operator<<(long c);
- QDumper &operator<<(int i);
- QDumper &operator<<(unsigned long c);
- QDumper &operator<<(unsigned int i);
- QDumper &operator<<(const void *p);
- void put(char c);
- void addCommaIfNeeded();
- void putEncoded(unsigned c);
- QDumper &operator<<(const char *str);
- QDumper &operator<<(const QString &str);
- void disarm();
-
- void beginHash(); // start of data hash output
- void endHash(); // start of data hash output
-
- // the dumper arguments
- int protocolVersion; // dumper protocol version
- int token; // some token to show on success
- const char *outertype; // object type
- const char *iname; // object name used for display
- const char *exp; // object expression
- const char *innertype; // 'inner type' for class templates
- const void *data; // pointer to raw data
- bool dumpChildren; // do we want to see children?
-
- // handling of nested templates
- void setupTemplateParameters();
- enum { maxTemplateParameters = 10 };
- const char *templateParameters[maxTemplateParameters + 1];
- int templateParametersCount;
-
- // internal state
- bool success; // are we finished?
- size_t pos;
-};
-
-
-QDumper::QDumper()
-{
- success = false;
- pos = 0;
-}
-
-QDumper::~QDumper()
-{
- flush();
- put(0); // our end marker
-#ifdef Q_OS_WIN
- sprintf(qDumpBuffer2, "@@CDD/%d/done\n", token);
- OutputDebugStringA(qDumpBuffer2);
-#else
- fprintf(stderr, "%d/done\n", token);
-#endif
- qDumpInBuffer[0] = 0;
-}
-
-void QDumper::flush()
-{
- qDumpBuffer[pos++] = 0;
-#ifdef Q_OS_WIN
- sprintf(qDumpBuffer2, "@@CDD#%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
- OutputDebugStringA(qDumpBuffer2);
-#else
- fprintf(stderr, "%d#%d,%s\n", token, int(pos - 1), qDumpBuffer);
-#endif
- pos = 0;
-}
-
-void QDumper::setupTemplateParameters()
-{
- char *s = const_cast<char *>(innertype);
-
- templateParametersCount = 1;
- templateParameters[0] = s;
- for (int i = 1; i != maxTemplateParameters + 1; ++i)
- templateParameters[i] = 0;
-
- while (*s) {
- while (*s && *s != '@')
- ++s;
- if (*s) {
- *s = '\0';
- ++s;
- templateParameters[templateParametersCount++] = s;
- }
- }
-}
-
-QDumper &QDumper::operator<<(unsigned long c)
-{
- static char buf[100];
- sprintf(buf, "%lu", c);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(unsigned int i)
-{
- static char buf[100];
- sprintf(buf, "%u", i);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(long c)
-{
- static char buf[100];
- sprintf(buf, "%ld", c);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(int i)
-{
- static char buf[100];
- sprintf(buf, "%d", i);
- return (*this) << buf;
-}
-
-QDumper &QDumper::operator<<(const void *p)
-{
- static char buf[100];
- sprintf(buf, "%p", p);
- // we get a '0x' prefix only on some implementations.
- // if it isn't there, write it out manually.
- if (buf[1] != 'x') {
- put('0');
- put('x');
- }
- return (*this) << buf;
-}
-
-void QDumper::put(char c)
-{
- if (pos >= sizeof(qDumpBuffer) - 100)
- flush();
- qDumpBuffer[pos++] = c;
-}
-
-void QDumper::addCommaIfNeeded()
-{
- if (pos == 0)
- return;
- if (qDumpBuffer[pos - 1] == '}' || qDumpBuffer[pos - 1] == '"')
- put(',');
-}
-
-void QDumper::putEncoded(unsigned c)
-{
- if (c >= 32 && c <= 126 && c != '"' && c != '\\') {
- put(c);
- } else {
- put('\\');
- put('u');
- put(toHex((c >> 12) & 0xf));
- put(toHex((c >> 8) & 0xf));
- put(toHex((c >> 4) & 0xf));
- put(toHex( c & 0xf));
- }
-}
-
-QDumper &QDumper::operator<<(const char *str)
-{
- while (*str)
- put(*(str++));
- return *this;
-}
-
-QDumper &QDumper::operator<<(const QString &str)
-{
- int n = str.size();
- if (n < 0) {
- qProvokeSegFault();
- } else {
- //(*this) << "[" << n << "]";
- if (n > 1000000)
- n = 1000000;
- //put(' ');
- put('\\');
- put('"');
- for (int i = 0; i != n; ++i)
- putEncoded(str[i].unicode());
- put('\\');
- put('"');
- if (n < str.size())
- (*this) << "<incomplete string>";
- }
- return *this;
-}
-
-void QDumper::disarm()
-{
- flush();
- success = true;
-}
-
-void QDumper::beginHash()
-{
- addCommaIfNeeded();
- put('{');
-}
-
-void QDumper::endHash()
-{
- put('}');
-}
-
-
-//
-// Some helpers to keep the dumper code short
-//
-
-// dump property=value pair
-#undef P
-#define P(dumper,name,value) \
- do { \
- dumper.addCommaIfNeeded(); \
- dumper << (name) << "=\"" << value << "\""; \
- } while (0)
-
-// simple string property
-#undef S
-#define S(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", value); \
- P(dumper, "type", "QString"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-// simple integer property
-#undef I
-#define I(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", value); \
- P(dumper, "type", "int"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-// simple boolean property
-#undef BL
-#define BL(dumper, name, value) \
- dumper.beginHash(); \
- P(dumper, "name", name); \
- P(dumper, "value", (value ? "true" : "false")); \
- P(dumper, "type", "bool"); \
- P(dumper, "numchild", "0"); \
- dumper.endHash();
-
-#undef TT
-#define TT(type, value) \
- "<tr><td>" << type << "</td><td> : </td><td>" << value << "</td></tr>"
-
-static void qDumpUnknown(QDumper &d)
-{
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<internal error>");
- P(d, "type", d.outertype);
- P(d, "numchild", "0");
- d.disarm();
-}
-
-static void qDumpQPropertyList(QDumper &d)
-{
- const QObject *ob = (const QObject *)d.data;
- const QMetaObject *mo = ob->metaObject();
- P(d, "iname", d.iname);
- P(d, "addr", "<synthetic>");
- P(d, "type", "QObject");
- P(d, "numchild", mo->propertyCount());
- if (d.dumpChildren) {
- d << ",children=[";
- for (int i = mo->propertyCount(); --i >= 0; ) {
- const QMetaProperty & prop = mo->property(i);
- d.beginHash();
- P(d, "name", prop.name());
- if (QLatin1String(prop.typeName()) == QLatin1String("QString")) {
- P(d, "value", prop.read(ob).toString());
- P(d, "numchild", "0");
- } else if (QLatin1String(prop.typeName()) == QLatin1String("bool")) {
- P(d, "value", (prop.read(ob).toBool() ? "true" : "false"));
- P(d, "numchild", "0");
- } else if (QLatin1String(prop.typeName()) == QLatin1String("int")) {
- P(d, "value", prop.read(ob).toInt());
- P(d, "numchild", "0");
- } else {
- P(d, "exp", "((" << mo->className() << "*)" << ob
- << ")->" << prop.name() << "()");
- }
- P(d, "type", prop.typeName());
- P(d, "numchild", "1");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQObject(QDumper &d)
-{
- const QObject *ob = reinterpret_cast<const QObject *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", (void*)d.data);
- P(d, "type", "QObject");
- P(d, "numchild", 4);
- if (d.dumpChildren) {
- const QMetaObject *mo = ob->metaObject();
- const QObjectList &children = ob->children();
- d << ",children=[";
- S(d, "objectName", ob->objectName());
- d.beginHash();
- P(d, "name", "properties");
- // FIXME: Note that when simply using '(QObject*)'
- // in the cast below, Gdb/MI _sometimes misparses
- // expressions further down in the tree.
- P(d, "exp", "*(class QObject*)" << d.data);
- P(d, "type", "QPropertyList");
- P(d, "value", "<" << mo->propertyCount() << " items>");
- P(d, "numchild", mo->propertyCount());
- d.endHash();
- d.beginHash();
- P(d, "name", "children");
- P(d, "exp", "((class QObject*)" << d.data << ")->children()");
- P(d, "type", "QList<QObject *>");
- P(d, "value", "<" << children.size() << " items>");
- P(d, "numchild", children.size());
- d.endHash();
- d.beginHash();
- P(d, "name", "parent");
- P(d, "exp", "((class QObject*)" << d.data << ")->parent()");
- P(d, "type", "QObject *");
- P(d, "numchild", (ob->parent() ? "1" : "0"));
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQDir(QDumper &d)
-{
- const QDir &dir = *reinterpret_cast<const QDir *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", dir.path());
- P(d, "type", "QDir");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- S(d, "absolutePath", dir.absolutePath());
- S(d, "canonicalPath", dir.canonicalPath());
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQFileInfo(QDumper &d)
-{
- const QFileInfo &info = *reinterpret_cast<const QFileInfo *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", info.filePath());
- P(d, "type", "QDir");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- S(d, "absolutePath", info.absolutePath());
- S(d, "absoluteFilePath", info.absoluteFilePath());
- S(d, "canonicalPath", info.canonicalPath());
- S(d, "canonicalFilePath", info.canonicalFilePath());
- S(d, "completeBaseName", info.completeBaseName());
- S(d, "completeSuffix", info.completeSuffix());
- S(d, "baseName", info.baseName());
-#ifdef Q_OS_MACX
- BL(d, "isBundle", info.isBundle());
- S(d, "bundleName", info.bundleName());
-#endif
- S(d, "completeSuffix", info.completeSuffix());
- S(d, "fileName", info.fileName());
- S(d, "filePath", info.filePath());
- S(d, "group", info.group());
- S(d, "owner", info.owner());
- S(d, "path", info.path());
-
- I(d, "groupid", (long)info.groupId());
- I(d, "ownerid", (long)info.ownerId());
- //QFile::Permissions permissions () const
- I(d, "permissions", info.permissions());
-
- //QDir absoluteDir () const
- //QDir dir () const
-
- BL(d, "caching", info.caching());
- BL(d, "exists", info.exists());
- BL(d, "isAbsolute", info.isAbsolute());
- BL(d, "isDir", info.isDir());
- BL(d, "isExecutable", info.isExecutable());
- BL(d, "isFile", info.isFile());
- BL(d, "isHidden", info.isHidden());
- BL(d, "isReadable", info.isReadable());
- BL(d, "isRelative", info.isRelative());
- BL(d, "isRoot", info.isRoot());
- BL(d, "isSymLink", info.isSymLink());
- BL(d, "isWritable", info.isWritable());
-
-#ifndef QT_NO_DATESTRING
- d.beginHash();
- P(d, "name", "created");
- P(d, "value", info.created().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->created()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "lastModified");
- P(d, "value", info.lastModified().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->lastModified()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "lastRead");
- P(d, "value", info.lastRead().toString());
- P(d, "exp", "((QFileInfo*)" << d.data << ")->lastRead()");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-#endif
-
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQDateTime(QDumper &d)
-{
-#ifdef QT_NO_DATESTRING
- qDumpUnknown(d);
-#else
- const QDateTime &date = *reinterpret_cast<const QDateTime *>(d.data);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", date.toString());
- P(d, "type", "QDateTime");
- P(d, "numchild", "3");
- if (d.dumpChildren) {
- d << ",children=[";
- BL(d, "isNull", date.isNull());
- I(d, "toTime_t", (long)date.toTime_t());
- S(d, "toString", date.toString());
- S(d, "toString_(ISO)", date.toString(Qt::ISODate));
- S(d, "toString_(SystemLocale)", date.toString(Qt::SystemLocaleDate));
- S(d, "toString_(Locale)", date.toString(Qt::LocaleDate));
- S(d, "toString", date.toString());
-
- d.beginHash();
- P(d, "name", "toUTC");
- P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::UTC)");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d.beginHash();
- P(d, "name", "toLocalTime");
- P(d, "exp", "((QDateTime*)" << d.data << ")->toTimeSpec(Qt::LocalTime)");
- P(d, "type", "QDateTime");
- P(d, "numchild", "1");
- d.endHash();
-
- d << "]";
- }
- d.disarm();
-#endif // ifdef QT_NO_DATESTRING
-}
-
-static void qDumpQString(QDumper &d)
-{
- const QString &str = *reinterpret_cast<const QString *>(d.data);
-
- // Try to provoke segfaults early to prevent the frontend
- // from asking for unavailable child details
- if (!str.isEmpty()) {
- volatile ushort dummy = 0;
- dummy += str.at(0).unicode();
- dummy += str.at(str.size() - 1).unicode();
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", str);
- P(d, "type", "QString");
- P(d, "numchild", "0");
- d.disarm();
-}
-
-static void qDumpQStringList(QDumper &d)
-{
- const QStringList &list = *reinterpret_cast<const QStringList *>(d.data);
- int n = list.size();
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(&list.front());
- qCheckAccess(&list.back());
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- S(d, "[" << i << "]", list[i]);
- }
- if (n < list.size()) {
- d.beginHash();
- P(d, "value", "<incomplete>");
- P(d, "type", " ");
- P(d, "numchild", "0");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQVariantHelper(const void *data, QString *value,
- QString *exp, int *numchild)
-{
- const QVariant &v = *reinterpret_cast<const QVariant *>(data);
- switch (v.type()) {
- case QVariant::Invalid:
- *value = QLatin1String("<invalid>");
- *numchild = 0;
- break;
- case QVariant::String:
- *value = QLatin1Char('"') + v.toString() + QLatin1Char('"');
- *numchild = 0;
- break;
- case QVariant::StringList:
- *exp = QString(QLatin1String("((QVariant*)%1)->d.data.c"))
- .arg((qulonglong)data);
- *numchild = v.toStringList().size();
- break;
- case QVariant::Int:
- *value = QString::number(v.toInt());
- *numchild= 0;
- break;
- case QVariant::Double:
- *value = QString::number(v.toDouble());
- *numchild = 0;
- break;
- default:
- // FIXME
- //*exp = QString("qVariantValue<" << v.typeName() << ">"
- // << "(*(QVariant*)" << data << ")");
- break;
- }
-}
-
-static void qDumpQVariant(QDumper &d)
-{
- const QVariant &v = *reinterpret_cast<const QVariant *>(d.data);
- QString value;
- QString exp;
- int numchild = 0;
- qDumpQVariantHelper(d.data, &value, &exp, &numchild);
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "(" << v.typeName() << ") " << qPrintable(value));
- P(d, "type", "QVariant");
- P(d, "numchild", 1);
- if (d.dumpChildren) {
- d << ",children=[";
- d.beginHash();
- P(d, "name", "value");
- if (!exp.isEmpty())
- P(d, "exp", qPrintable(exp));
- if (!value.isEmpty())
- P(d, "value", qPrintable(value));
- P(d, "type", v.typeName());
- P(d, "numchild", numchild);
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQList(QDumper &d)
-{
- // This uses the knowledge that QList<T> has only a single member
- // of type union { QListData p; QListData::Data *d; };
- const QListData &ldata = *reinterpret_cast<const QListData*>(d.data);
- const QListData::Data *pdata = *reinterpret_cast<const QListData::Data* const*>(d.data);
- int nn = ldata.size();
- if (nn < 0)
- qProvokeSegFault();
- if (nn > 0) {
- qCheckAccess(ldata.d->array);
- //qCheckAccess(ldata.d->array[0]);
- //qCheckAccess(ldata.d->array[nn - 1]);
- }
-
- int n = nn;
- P(d, "iname", d.iname);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- // The exact condition here is:
- // QTypeInfo<T>::isLarge || QTypeInfo<T>::isStatic
- // but this data is not available in the compiled binary.
- // So as first approximation only do the 'isLarge' check:
- void *p = &(ldata.d->array[i + pdata->begin]);
- unsigned long voidpsize = sizeof(void*);
- P(d, "exp", "(sizeof(" << d.innertype << ")>" << voidpsize <<
- "?(**(" << d.innertype << "**)(" << p << "))"
- ":(*(" << d.innertype << "*)(" << p << ")))");
- P(d, "type", d.innertype);
- d.endHash();
- }
- if (n < nn) {
- d << ",{";
- P(d, "value", "<incomplete>");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQVector(QDumper &d)
-{
- // Use 'int' as representative value. No way (and no need)
- // to deduce proper type here.
- const QVector<int> &vec = *reinterpret_cast<const QVector<int> *>(d.data);
- const int nn = vec.size();
-
- // Try to provoke segfaults early to prevent the frontend
- // from asking for unavailable child details
- if (nn < 0)
- qProvokeSegFault();
- if (nn > 0) {
- qCheckAccess(&vec.front());
- qCheckAccess(&vec.back());
- }
-
- //int innersize = 0;
- //scanf(qDumpInBuffer, "%d", &innersize);
-
- int n = nn;
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- for (int i = 0; i != n; ++i) {
- if (i)
- d << ",";
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "exp", "(" << d.exp << ".d->array[" << i << "])");
- P(d, "type", d.innertype);
- d.endHash();
- }
- if (n < nn) {
- d << ",{";
- P(d, "value", "<incomplete>");
- d.endHash();
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQHashNode(QDumper &d)
-{
- struct NodeOS { void *next; uint k; uint v; } nodeOS; // int-key optimization, small value
- struct NodeOL { void *next; uint k; void *v; } nodeOL; // int-key optimiatzion, large value
- struct NodeNS { void *next; uint h; uint k; uint v; } nodeNS; // no optimization, small value
- struct NodeNL { void *next; uint h; uint k; void *v; } nodeNL; // no optimization, large value
- struct NodeL { void *next; uint h; void *k; void *v; } nodeL; // complex key
-
- // offsetof(...,...) not yet in Standard C++
- const ulong nodeOSk ( (char *)&nodeOS.k - (char *)&nodeOS );
- const ulong nodeOSv ( (char *)&nodeOS.v - (char *)&nodeOS );
- const ulong nodeOLk ( (char *)&nodeOL.k - (char *)&nodeOL );
- const ulong nodeOLv ( (char *)&nodeOL.v - (char *)&nodeOL );
- const ulong nodeNSk ( (char *)&nodeNS.k - (char *)&nodeNS );
- const ulong nodeNSv ( (char *)&nodeNS.v - (char *)&nodeNS );
- const ulong nodeNLk ( (char *)&nodeNL.k - (char *)&nodeNL );
- const ulong nodeNLv ( (char *)&nodeNL.v - (char *)&nodeNL );
- const ulong nodeLk ( (char *)&nodeL.k - (char *)&nodeL );
- const ulong nodeLv ( (char *)&nodeL.v - (char *)&nodeL );
-
- const QHashData *h = reinterpret_cast<const QHashData *>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "");
- P(d, "numchild", 2);
- if (d.dumpChildren) {
- // there is a hash specialization in cast the key are integers or shorts
- bool isOptimizedIntKey = qstrcmp(keyType, "int") == 0
-#if defined(Q_BYTE_ORDER) && Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- || qstrcmp(keyType, "short") == 0
- || qstrcmp(keyType, "ushort") == 0
-#endif
- || qstrcmp(keyType, "uint") == 0;
-
- d << ",children=[";
- d.beginHash();
- P(d, "name", "key");
- P(d, "type", keyType);
- unsigned long intsize = sizeof(int);
- if (isOptimizedIntKey) {
- P(d, "exp", "*(" << keyType << "*)"
- "(((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeOLk << ":" << nodeOSk <<
- ")+(char*)" << h << ")");
- } else {
- P(d, "exp", "*(" << keyType << "*)"
- "(((sizeof(" << keyType << ")>" << intsize << ")?"
- << nodeLk << ":"
- "((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeNLk << ":" << nodeNSk << "))+(char*)" << h << ")");
- }
- d.endHash();
- d.beginHash();
- P(d, "name", "value");
- P(d, "type", valueType);
- if (isOptimizedIntKey) {
- P(d, "exp", "*(" << valueType << "*)"
- "(((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeOLv << ":" << nodeOSv << ")+(char*)" << h << ")");
- } else {
- P(d, "exp", "*(" << valueType << "*)"
- "(((sizeof(" << keyType << ")>" << intsize << ")?" << nodeLv << ":"
- "((sizeof(" << valueType << ")>" << intsize << ")?"
- << nodeNLv << ":" << nodeNSv << "))+(char*)" << h << ")");
- }
- d.endHash();
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQHash(QDumper &d)
-{
- QHashData *h = *reinterpret_cast<QHashData *const*>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- qCheckPointer(h->fakeNext);
- qCheckPointer(h->buckets);
-
- int n = h->size;
-
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckPointer(h->fakeNext);
- qCheckPointer(*h->buckets);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
-
- QHashData::Node *node = h->firstNode();
- QHashData::Node *end = reinterpret_cast<QHashData::Node *>(h);
- int i = 0;
-
- while (node != end) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", "QHashNode<" << keyType << "," << valueType << " >");
- P(d, "exp", "*(QHashNode<" << keyType << "," << valueType << " >*)" << node);
- d.endHash();
-
- ++i;
- node = QHashData::nextNode(node);
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void qDumpQMapNode(QDumper &d)
-{
- const QMapData *h = reinterpret_cast<const QMapData *>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- qCheckAccess(h->backward);
- qCheckAccess(h->forward[0]);
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "");
- P(d, "numchild", 2);
- if (d.dumpChildren) {
- unsigned long voidpsize = sizeof(void*);
- d << ",children=[";
- d.beginHash();
- P(d, "name", "key");
- P(d, "type", keyType);
- P(d, "exp", "*(" << keyType << "*)"
- << "("
- << 2 * voidpsize
- << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
- << "+(char*)" << h
- << ")");
- d.endHash();
- d.beginHash();
- P(d, "name", "value");
- P(d, "type", valueType);
- P(d, "exp", "*(" << valueType << "*)"
- << "("
- << "(size_t)&(('QMap<" << keyType << "," << valueType << ">::Node'*)0)->value"
- << "+" << 2 * voidpsize
- << "-sizeof('QMap<" << keyType << "," << valueType << ">::Node')"
- << "+(char*)" << h
- << ")");
- d.endHash();
- d << "]";
- }
-
- d.disarm();
-}
-
-static void qDumpQMap(QDumper &d)
-{
- QMapData *h = *reinterpret_cast<QMapData *const*>(d.data);
- const char *keyType = d.templateParameters[0];
- const char *valueType = d.templateParameters[1];
-
- int n = h->size;
-
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(h->backward);
- qCheckAccess(h->forward[0]);
- qCheckPointer(h->backward->backward);
- qCheckPointer(h->forward[0]->backward);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "numchild", n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
-
- QMapData::Node *node = reinterpret_cast<QMapData::Node *>(h->forward[0]);
- QMapData::Node *end = reinterpret_cast<QMapData::Node *>(h);
- int i = 0;
-
- while (node != end) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", "QMap<" << keyType << "," << valueType << ">::Node");
- P(d, "exp", "*('QMap<" << keyType << "," << valueType << ">::Node'*)" << node);
- d.endHash();
-
- ++i;
- node = node->forward[0];
- }
- d << "]";
- }
-
- d.disarm();
-}
-
-static void qDumpQSet(QDumper &d)
-{
- // This uses the knowledge that QHash<T> has only a single member
- // of union { QHashData *d; QHashNode<Key, T> *e; };
- QHashData *hd = *(QHashData**)d.data;
- QHashData::Node *node = hd->firstNode();
-
- int n = hd->size;
- if (n < 0)
- qProvokeSegFault();
- if (n > 0) {
- qCheckAccess(node);
- qCheckPointer(node->next);
- }
-
- P(d, "iname", d.iname);
- P(d, "addr", d.data);
- P(d, "value", "<" << n << " items>");
- P(d, "valuedisabled", "true");
- P(d, "numchild", 2 * n);
- if (d.dumpChildren) {
- if (n > 100)
- n = 100;
- d << ",children=[";
- int i = 0;
- for (int bucket = 0; bucket != hd->numBuckets; ++bucket) {
- for (node = hd->buckets[bucket]; node->next; node = node->next) {
- d.beginHash();
- P(d, "name", "[" << i << "]");
- P(d, "type", d.innertype);
- P(d, "exp", "(('QHashNode<" << d.innertype
- << ",QHashDummyValue>'*)"
- << static_cast<const void*>(node) << ")->key"
- );
- d.endHash();
- ++i;
- }
- }
- d << "]";
- }
- d.disarm();
-}
-
-static void handleProtocolVersion2(QDumper & d)
-{
- if (!d.outertype[0]) {
- qDumpUnknown(d);
- return;
- }
-
- d.setupTemplateParameters();
- // d.outertype[0] is usally 'Q', so don't use it
- switch (d.outertype[1]) {
- case 'D':
- if (qstrcmp(d.outertype, "QDateTime") == 0)
- qDumpQDateTime(d);
- else if (qstrcmp(d.outertype, "QDir") == 0)
- qDumpQDir(d);
- break;
- case 'F':
- if (qstrcmp(d.outertype, "QFileInfo") == 0)
- qDumpQFileInfo(d);
- break;
- case 'H':
- if (qstrcmp(d.outertype, "QHash") == 0)
- qDumpQHash(d);
- else if (qstrcmp(d.outertype, "QHashNode") == 0)
- qDumpQHashNode(d);
- break;
- case 'L':
- if (qstrcmp(d.outertype, "QList") == 0)
- qDumpQList(d);
- break;
- case 'M':
- if (qstrcmp(d.outertype, "QMap") == 0)
- qDumpQMap(d);
- else if (qstrcmp(d.outertype, "QMap::Node") == 0)
- qDumpQMapNode(d);
- break;
- case 'O':
- if (qstrcmp(d.outertype, "QObject") == 0)
- qDumpQObject(d);
- break;
- case 'P':
- if (qstrcmp(d.outertype, "QPropertyList") == 0)
- qDumpQPropertyList(d);
- break;
- case 'S':
- if (qstrcmp(d.outertype, "QSet") == 0)
- qDumpQSet(d);
- else if (qstrcmp(d.outertype, "QString") == 0)
- qDumpQString(d);
- else if (qstrcmp(d.outertype, "QStringList") == 0)
- qDumpQStringList(d);
- break;
- case 'V':
- if (qstrcmp(d.outertype, "QVariant") == 0)
- qDumpQVariant(d);
- else if (qstrcmp(d.outertype, "QVector") == 0)
- qDumpQVector(d);
- break;
- }
-
- if (!d.success)
- qDumpUnknown(d);
-}
-
-} // anonymous namespace
-
-
-extern "C" Q_CORE_EXPORT void qDumpObjectData(
- int protocolVersion,
- int token,
- const char *outertype,
- const char *iname,
- const char *exp,
- const char *innertype,
- const void *data,
- bool dumpChildren)
-{
- if (protocolVersion == 1) {
- // used to test whether error output gets through
- //fprintf(stderr, "using stderr, qDebug follows: %d\n", token);
- //qDebug() << "using qDebug, stderr already used: " << token;
- }
-
- else if (protocolVersion == 2) {
- QDumper d;
- d.protocolVersion = protocolVersion;
- d.token = token;
- d.outertype = outertype ? outertype : "";
- d.iname = iname ? iname : "";
- d.exp = exp ? exp : "";
- d.innertype = innertype ? innertype : "";
- d.data = data ? data : "";
- d.dumpChildren = dumpChildren;
- handleProtocolVersion2(d);
- }
-
- else {
- qDebug() << "Unsupported protocol version" << protocolVersion;
- }
-}
-
-QT_END_NAMESPACE
-
-#endif // !Q_OS_WINCE && !QT_NO_QDUMPER
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
new file mode 100644
index 0000000..2b027fc
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -0,0 +1,846 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+
+| *property* | *Used for type* |
+| period | QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| amplitude | QEasingCurve::{In,Out,InOut,OutIn}Bounce, QEasingCurve::{In,Out,InOut,OutIn}Elastic |
+| overshoot | QEasingCurve::{In,Out,InOut,OutIn}Back |
+
+*/
+
+
+
+
+/*!
+ \class QEasingCurve
+ \since 4.6
+ \ingroup animation
+ \brief The QEasingCurve class provides easing curves for controlling animation.
+
+ Easing curves describe a function that controls how the speed of the interpolation
+ between 0 and 1 should be. Easing curves allow transitions from
+ one value to another to appear more natural than a simple constant speed would allow.
+ The QEasingCurve class is usually used in conjunction with the QAnimation class,
+ but can be used on its own.
+
+ To calculate the speed of the interpolation, the easing curve provides the function
+ valueForProgress(), where the \a progress argument specifies the progress of the
+ interpolation: 0 is the start value of the interpolation, 1 is the end value of the
+ interpolation. The returned value is the effective progress of the interpolation.
+ If the returned value is the same as the input value for all input values the easing
+ curve is a linear curve. This is the default behaviour.
+
+ For example,
+ \code
+ QEasingCurve easing(QEasingCurve::InOutQuad);
+
+ for(qreal t = 0.0; t < 1.0; t+=0.1)
+ qWarning() << "Effective progress" << t << " is
+ << easing.valueForProgress(t);
+ \endcode
+ will print the effective progress of the interpolation between 0 and 1.
+
+ When using a QAnimation, the easing curve will be used to control the
+ progress of the interpolation between startValue and endValue:
+ \code
+ QAnimation animation;
+ animation.setStartValue(0);
+ animation.setEndValue(1000);
+ animation.setDuration(1000);
+ animation.setEasingCurve(QEasingCurve::InOutQuad);
+ \endcode
+ */
+
+/*!
+ \enum QEasingCurve::Type
+
+ The type of easing curve.
+
+ \value Linear \inlineimage qeasingcurve-linear.png
+ \br
+ Easing equation function for a simple linear tweening,
+ with no easing.
+ \value InQuad \inlineimage qeasingcurve-inquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ in: accelerating from zero velocity.
+ \value OutQuad \inlineimage qeasingcurve-outquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ out: decelerating to zero velocity.
+ \value InOutQuad \inlineimage qeasingcurve-inoutquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInQuad \inlineimage qeasingcurve-outinquad.png
+ \br
+ Easing equation function for a quadratic (t^2) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InCubic \inlineimage qeasingcurve-incubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ in: accelerating from zero velocity.
+ \value OutCubic \inlineimage qeasingcurve-outcubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ out: decelerating from zero velocity.
+ \value InOutCubic \inlineimage qeasingcurve-inoutcubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInCubic \inlineimage qeasingcurve-outincubic.png
+ \br
+ Easing equation function for a cubic (t^3) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InQuart \inlineimage qeasingcurve-inquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ in: accelerating from zero velocity.
+ \value OutQuart \inlineimage qeasingcurve-outquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ out: decelerating from zero velocity.
+ \value InOutQuart \inlineimage qeasingcurve-inoutquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInQuart \inlineimage qeasingcurve-outinquart.png
+ \br
+ Easing equation function for a quartic (t^4) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InQuint \inlineimage qeasingcurve-inquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ in: accelerating from zero velocity.
+ \value OutQuint \inlineimage qeasingcurve-outquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ out: decelerating from zero velocity.
+ \value InOutQuint \inlineimage qeasingcurve-inoutquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInQuint \inlineimage qeasingcurve-outinquint.png
+ \br
+ Easing equation function for a quintic (t^5) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InSine \inlineimage qeasingcurve-insine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ in: accelerating from zero velocity.
+ \value OutSine \inlineimage qeasingcurve-outsine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ out: decelerating from zero velocity.
+ \value InOutSine \inlineimage qeasingcurve-inoutsine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInSine \inlineimage qeasingcurve-outinsine.png
+ \br
+ Easing equation function for a sinusoidal (sin(t)) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InExpo \inlineimage qeasingcurve-inexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ in: accelerating from zero velocity.
+ \value OutExpo \inlineimage qeasingcurve-outexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ out: decelerating from zero velocity.
+ \value InOutExpo \inlineimage qeasingcurve-inoutexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInExpo \inlineimage qeasingcurve-outinexpo.png
+ \br
+ Easing equation function for an exponential (2^t) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InCirc \inlineimage qeasingcurve-incirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ in: accelerating from zero velocity.
+ \value OutCirc \inlineimage qeasingcurve-outcirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ out: decelerating from zero velocity.
+ \value InOutCirc \inlineimage qeasingcurve-inoutcirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ in/out: acceleration until halfway, then deceleration.
+ \value OutInCirc \inlineimage qeasingcurve-outincirc.png
+ \br
+ Easing equation function for a circular (sqrt(1-t^2)) easing
+ out/in: deceleration until halfway, then acceleration.
+ \value InElastic \inlineimage qeasingcurve-inelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing in:
+ accelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value OutElastic \inlineimage qeasingcurve-outelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing out:
+ decelerating from zero velocity. The peak amplitude
+ can be set with the \e amplitude parameter, and the
+ period of decay by the \e period parameter.
+ \value InOutElastic \inlineimage qeasingcurve-inoutelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInElastic \inlineimage qeasingcurve-outinelastic.png
+ \br
+ Easing equation function for an elastic
+ (exponentially decaying sine wave) easing out/in:
+ deceleration until halfway, then acceleration.
+ \value InBack \inlineimage qeasingcurve-inback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing in:
+ accelerating from zero velocity.
+ \value OutBack \inlineimage qeasingcurve-outback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out:
+ decelerating from zero velocity.
+ \value InOutBack \inlineimage qeasingcurve-inoutback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBack \inlineimage qeasingcurve-outinback.png
+ \br
+ Easing equation function for a back (overshooting
+ cubic easing: (s+1)*t^3 - s*t^2) easing out/in:
+ deceleration until halfway, then acceleration.
+ \value InBounce \inlineimage qeasingcurve-inbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing in: accelerating
+ from zero velocity.
+ \value OutBounce \inlineimage qeasingcurve-outbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing out: decelerating
+ from zero velocity.
+ \value InOutBounce \inlineimage qeasingcurve-inoutbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing in/out:
+ acceleration until halfway, then deceleration.
+ \value OutInBounce \inlineimage qeasingcurve-outinbounce.png
+ \br
+ Easing equation function for a bounce (exponentially
+ decaying parabolic bounce) easing out/in:
+ deceleration until halfway, then acceleration.
+ \omitvalue InCurve
+ \omitvalue OutCurve
+ \omitvalue SineCurve
+ \omitvalue CosineCurve
+ \value Custom This is returned if the user have specified a custom curve type with setCustomType(). Note that you cannot call setType() with this value, but type() can return it.
+ \omitvalue NCurveTypes
+*/
+
+/*!
+ \typedef QEasingCurve::EasingFunction
+
+ This is a typedef for a pointer to a function with the following
+ signature:
+
+ \snippet doc/src/snippets/code/src_corelib_tools_qeasingcurve.cpp 0
+*/
+
+#include "qeasingcurve.h"
+
+#ifndef QT_NO_DEBUG_STREAM
+#include <QtCore/qdebug.h>
+#include <QtCore/QString>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static bool isConfigFunction(QEasingCurve::Type type)
+{
+ return type >= QEasingCurve::InElastic
+ && type <= QEasingCurve::OutInBounce;
+}
+
+class QEasingCurveFunction
+{
+public:
+ enum Type { In, Out, InOut, OutIn };
+
+ QEasingCurveFunction(QEasingCurveFunction::Type type = In, qreal period = 0.3, qreal amplitude = 1.0,
+ qreal overshoot = 1.70158f)
+ : _t(type), _p(period), _a(amplitude), _o(overshoot)
+ { }
+ virtual ~QEasingCurveFunction() {}
+ virtual qreal value(qreal t);
+ virtual QEasingCurveFunction *copy() const;
+ bool operator==(const QEasingCurveFunction& other);
+
+ Type _t;
+ qreal _p;
+ qreal _a;
+ qreal _o;
+};
+
+qreal QEasingCurveFunction::value(qreal t)
+{
+ return t;
+}
+
+QEasingCurveFunction *QEasingCurveFunction::copy() const
+{
+ return new QEasingCurveFunction(_t, _p, _a, _o);
+}
+
+bool QEasingCurveFunction::operator==(const QEasingCurveFunction& other)
+{
+ return _t == other._t &&
+ _p == other._p &&
+ _a == other._a &&
+ _o == other._o;
+}
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include "../../3rdparty/easing/easing.cpp"
+QT_END_INCLUDE_NAMESPACE
+
+class QEasingCurvePrivate
+{
+public:
+ QEasingCurvePrivate()
+ : type(QEasingCurve::Linear),
+ config(0),
+ func(&easeNone)
+ { }
+ ~QEasingCurvePrivate() { delete config; }
+ void setType_helper(QEasingCurve::Type);
+
+ QEasingCurve::Type type;
+ QEasingCurveFunction *config;
+ QEasingCurve::EasingFunction func;
+};
+
+struct ElasticEase : public QEasingCurveFunction
+{
+ ElasticEase(Type type)
+ : QEasingCurveFunction(type, qreal(0.3), qreal(1.0))
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ ElasticEase *rv = new ElasticEase(_t);
+ rv->_p = _p;
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal p = (_p < 0) ? 0.3f : _p;
+ qreal a = (_a < 0) ? 1.0f : _a;
+ switch(_t) {
+ case In:
+ return easeInElastic(t, a, p);
+ case Out:
+ return easeOutElastic(t, a, p);
+ case InOut:
+ return easeInOutElastic(t, a, p);
+ case OutIn:
+ return easeOutInElastic(t, a, p);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BounceEase : public QEasingCurveFunction
+{
+ BounceEase(Type type)
+ : QEasingCurveFunction(type, 0.3f, 1.0f)
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BounceEase *rv = new BounceEase(_t);
+ rv->_a = _a;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal a = (_a < 0) ? 1.0f : _a;
+ switch(_t) {
+ case In:
+ return easeInBounce(t, a);
+ case Out:
+ return easeOutBounce(t, a);
+ case InOut:
+ return easeInOutBounce(t, a);
+ case OutIn:
+ return easeOutInBounce(t, a);
+ default:
+ return t;
+ }
+ }
+};
+
+struct BackEase : public QEasingCurveFunction
+{
+ BackEase(Type type)
+ : QEasingCurveFunction(type, 0.3f, 1.0f, 1.70158f)
+ { }
+
+ QEasingCurveFunction *copy() const
+ {
+ BackEase *rv = new BackEase(_t);
+ rv->_o = _o;
+ return rv;
+ }
+
+ qreal value(qreal t)
+ {
+ qreal o = (_o < 0) ? 1.70158f : _o;
+ switch(_t) {
+ case In:
+ return easeInBack(t, o);
+ case Out:
+ return easeOutBack(t, o);
+ case InOut:
+ return easeInOutBack(t, o);
+ case OutIn:
+ return easeOutInBack(t, o);
+ default:
+ return t;
+ }
+ }
+};
+
+static QEasingCurve::EasingFunction curveToFunc(QEasingCurve::Type curve)
+{
+ switch(curve) {
+ case QEasingCurve::Linear:
+ return &easeNone;
+ case QEasingCurve::InQuad:
+ return &easeInQuad;
+ case QEasingCurve::OutQuad:
+ return &easeOutQuad;
+ case QEasingCurve::InOutQuad:
+ return &easeInOutQuad;
+ case QEasingCurve::OutInQuad:
+ return &easeOutInQuad;
+ case QEasingCurve::InCubic:
+ return &easeInCubic;
+ case QEasingCurve::OutCubic:
+ return &easeOutCubic;
+ case QEasingCurve::InOutCubic:
+ return &easeInOutCubic;
+ case QEasingCurve::OutInCubic:
+ return &easeOutInCubic;
+ case QEasingCurve::InQuart:
+ return &easeInQuart;
+ case QEasingCurve::OutQuart:
+ return &easeOutQuart;
+ case QEasingCurve::InOutQuart:
+ return &easeInOutQuart;
+ case QEasingCurve::OutInQuart:
+ return &easeOutInQuart;
+ case QEasingCurve::InQuint:
+ return &easeInQuint;
+ case QEasingCurve::OutQuint:
+ return &easeOutQuint;
+ case QEasingCurve::InOutQuint:
+ return &easeInOutQuint;
+ case QEasingCurve::OutInQuint:
+ return &easeOutInQuint;
+ case QEasingCurve::InSine:
+ return &easeInSine;
+ case QEasingCurve::OutSine:
+ return &easeOutSine;
+ case QEasingCurve::InOutSine:
+ return &easeInOutSine;
+ case QEasingCurve::OutInSine:
+ return &easeOutInSine;
+ case QEasingCurve::InExpo:
+ return &easeInExpo;
+ case QEasingCurve::OutExpo:
+ return &easeOutExpo;
+ case QEasingCurve::InOutExpo:
+ return &easeInOutExpo;
+ case QEasingCurve::OutInExpo:
+ return &easeOutInExpo;
+ case QEasingCurve::InCirc:
+ return &easeInCirc;
+ case QEasingCurve::OutCirc:
+ return &easeOutCirc;
+ case QEasingCurve::InOutCirc:
+ return &easeInOutCirc;
+ case QEasingCurve::OutInCirc:
+ return &easeOutInCirc;
+ // Internal for, compatibility with QTimeLine only ??
+ case QEasingCurve::InCurve:
+ return &easeInCurve;
+ case QEasingCurve::OutCurve:
+ return &easeOutCurve;
+ case QEasingCurve::SineCurve:
+ return &easeSineCurve;
+ case QEasingCurve::CosineCurve:
+ return &easeCosineCurve;
+ default:
+ return 0;
+ };
+}
+
+static QEasingCurveFunction *curveToFunctionObject(QEasingCurve::Type type)
+{
+ QEasingCurveFunction *curveFunc = 0;
+ switch(type) {
+ case QEasingCurve::InElastic:
+ curveFunc = new ElasticEase(ElasticEase::In);
+ break;
+ case QEasingCurve::OutElastic:
+ curveFunc = new ElasticEase(ElasticEase::Out);
+ break;
+ case QEasingCurve::InOutElastic:
+ curveFunc = new ElasticEase(ElasticEase::InOut);
+ break;
+ case QEasingCurve::OutInElastic:
+ curveFunc = new ElasticEase(ElasticEase::OutIn);
+ break;
+ case QEasingCurve::OutBounce:
+ curveFunc = new BounceEase(BounceEase::Out);
+ break;
+ case QEasingCurve::InBounce:
+ curveFunc = new BounceEase(BounceEase::In);
+ break;
+ case QEasingCurve::OutInBounce:
+ curveFunc = new BounceEase(BounceEase::OutIn);
+ break;
+ case QEasingCurve::InOutBounce:
+ curveFunc = new BounceEase(BounceEase::InOut);
+ break;
+ case QEasingCurve::InBack:
+ curveFunc = new BackEase(BackEase::In);
+ break;
+ case QEasingCurve::OutBack:
+ curveFunc = new BackEase(BackEase::Out);
+ break;
+ case QEasingCurve::InOutBack:
+ curveFunc = new BackEase(BackEase::InOut);
+ break;
+ case QEasingCurve::OutInBack:
+ curveFunc = new BackEase(BackEase::OutIn);
+ break;
+ default:
+ curveFunc = new QEasingCurveFunction(QEasingCurveFunction::In, 0.3f, 1.0f, 1.70158f); // ###
+ }
+
+ return curveFunc;
+}
+
+/*!
+ Constructs an easing curve of the given \a type.
+ */
+QEasingCurve::QEasingCurve(Type type)
+ : d_ptr(new QEasingCurvePrivate)
+{
+ setType(type);
+}
+
+/*!
+ Construct a copy of \a other.
+ */
+QEasingCurve::QEasingCurve(const QEasingCurve &other)
+: d_ptr(new QEasingCurvePrivate)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ *d_ptr = *other.d_ptr;
+ if(other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+}
+
+/*!
+ Destructor.
+ */
+
+QEasingCurve::~QEasingCurve()
+{
+ delete d_ptr;
+}
+
+/*!
+ Copy \a other.
+ */
+QEasingCurve &QEasingCurve::operator=(const QEasingCurve &other)
+{
+ // ### non-atomic, requires malloc on shallow copy
+ if (d_ptr->config) {
+ delete d_ptr->config;
+ d_ptr->config = 0;
+ }
+
+ *d_ptr = *other.d_ptr;
+ if(other.d_ptr->config)
+ d_ptr->config = other.d_ptr->config->copy();
+
+ return *this;
+}
+
+/*!
+ Compare this easing curve with \a other and returns true if they are
+ equal. It will also compare the properties of a curve.
+ */
+bool QEasingCurve::operator==(const QEasingCurve &other) const
+{
+ bool res = d_ptr->func == other.d_ptr->func
+ && d_ptr->type == other.d_ptr->type;
+ if (res && d_ptr->config && other.d_ptr->config) {
+ // catch the config content
+ res = d_ptr->config->operator==(*(other.d_ptr->config));
+ }
+ return res;
+}
+
+/*!
+ \fn bool QEasingCurve::operator!=(const QEasingCurve &other) const
+ Compare this easing curve with \a other and returns true if they are not equal.
+ It will also compare the properties of a curve.
+
+ \sa operator==()
+*/
+
+/*!
+ Returns the amplitude. This is not applicable for all curve types.
+ It is only applicable for bounce and elastic curves (curves of type()
+ QEasingCurve::InBounce, QEasingCurve::OutBounce, QEasingCurve::InOutBounce,
+ QEasingCurve::OutInBounce, QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic).
+ */
+qreal QEasingCurve::amplitude() const
+{
+ return d_ptr->config ? d_ptr->config->_a : 1.0;
+}
+
+/*!
+ Sets the amplitude to \a amplitude.
+
+ This will set the amplitude of the bounce or the amplitude of the
+ elastic "spring" effect. The higher the number, the higher the amplitude.
+ \sa amplitude()
+*/
+void QEasingCurve::setAmplitude(qreal amplitude)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_a = amplitude;
+}
+
+/*!
+ Returns the period. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InElastic, QEasingCurve::OutElastic,
+ QEasingCurve::InOutElastic or QEasingCurve::OutInElastic.
+ */
+qreal QEasingCurve::period() const
+{
+ return d_ptr->config ? d_ptr->config->_p : 0.3;
+}
+
+/*!
+ Sets the period to \a period.
+ Setting a small period value will give a high frequency of the curve. A
+ large period will give it a small frequency.
+
+ \sa period()
+*/
+void QEasingCurve::setPeriod(qreal period)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_p = period;
+}
+
+/*!
+ Returns the overshoot. This is not applicable for all curve types.
+ It is only applicable if type() is QEasingCurve::InBack, QEasingCurve::OutBack,
+ QEasingCurve::InOutBack or QEasingCurve::OutInBack.
+ */
+qreal QEasingCurve::overshoot() const
+{
+ return d_ptr->config ? d_ptr->config->_o : 1.70158f;
+}
+
+/*!
+ Sets the overshoot to \a overshoot.
+
+ 0 produces no overshoot, and the default value of 1.70158 produces an overshoot of 10 percent.
+
+ \sa overshoot()
+*/
+void QEasingCurve::setOvershoot(qreal overshoot)
+{
+ if (!d_ptr->config)
+ d_ptr->config = curveToFunctionObject(d_ptr->type);
+ d_ptr->config->_o = overshoot;
+}
+
+/*!
+ Returns the type of the easing curve.
+*/
+QEasingCurve::Type QEasingCurve::type() const
+{
+ return d_ptr->type;
+}
+
+void QEasingCurvePrivate::setType_helper(QEasingCurve::Type newType)
+{
+ qreal amp = -1.0;
+ qreal period = -1.0;
+ qreal overshoot = -1.0;
+
+ if (config) {
+ amp = config->_a;
+ period = config->_p;
+ overshoot = config->_o;
+ delete config;
+ config = 0;
+ }
+
+ if (isConfigFunction(newType) || (amp != -1.0) || (period != -1.0) || (overshoot != -1.0)) {
+ config = curveToFunctionObject(newType);
+ if (amp != -1.0)
+ config->_a = amp;
+ if (period != -1.0)
+ config->_p = period;
+ if (overshoot != -1.0)
+ config->_o = overshoot;
+ func = 0;
+ } else if (newType != QEasingCurve::Custom) {
+ func = curveToFunc(newType);
+ }
+ Q_ASSERT((func == 0) == (config != 0));
+ type = newType;
+}
+
+/*!
+ Sets the type of the easing curve to \a type.
+*/
+void QEasingCurve::setType(Type type)
+{
+ if (d_ptr->type == type)
+ return;
+ if (type < Linear || type >= NCurveTypes - 1) {
+ qWarning("QEasingCurve: Invalid curve type %d", type);
+ return;
+ }
+
+ d_ptr->setType_helper(type);
+}
+
+/*!
+ Sets a custom easing curve that is defined by the user in the function \a func.
+ The signature of the function is qreal myEasingFunction(qreal progress),
+ where \e progress and the return value is considered to be normalized between 0 and 1.
+ (In some cases the return value can be outside that range)
+ After calling this function type() will return QEasingCurve::Custom.
+ \a func cannot be zero.
+
+ \sa customType()
+ \sa valueForProgress()
+*/
+void QEasingCurve::setCustomType(EasingFunction func)
+{
+ if (!func) {
+ qWarning("Function pointer must not be null");
+ return;
+ }
+ d_ptr->func = func;
+ d_ptr->setType_helper(Custom);
+}
+
+/*!
+ Returns the function pointer to the custom easing curve.
+ If type() does not return QEasingCurve::Custom, this function
+ will return 0.
+*/
+QEasingCurve::EasingFunction QEasingCurve::customType() const
+{
+ return d_ptr->type == Custom ? d_ptr->func : 0;
+}
+
+/*!
+ Return the effective progress for the easing curve at \a progress.
+ While \a progress must be between 0 and 1, the returned effective progress
+ can be outside those bounds. For instance, QEasingCurve::InBack will
+ return negative values in the beginning of the function.
+ */
+qreal QEasingCurve::valueForProgress(qreal progress) const
+{
+ progress = qBound<qreal>(0, progress, 1);
+ if (d_ptr->func)
+ return d_ptr->func(progress);
+ else if (d_ptr->config)
+ return d_ptr->config->value(progress);
+ else
+ return progress;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QEasingCurve &item)
+{
+ debug << "type:" << item.d_ptr->type
+ << "func:" << item.d_ptr->func;
+ if (item.d_ptr->config) {
+ debug << QString::fromAscii("period:%1").arg(item.d_ptr->config->_p, 0, 'f', 20)
+ << QString::fromAscii("amp:%1").arg(item.d_ptr->config->_a, 0, 'f', 20)
+ << QString::fromAscii("overshoot:%1").arg(item.d_ptr->config->_o, 0, 'f', 20);
+ }
+ return debug;
+}
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/corelib/tools/qeasingcurve.h b/src/corelib/tools/qeasingcurve.h
new file mode 100644
index 0000000..a240bc0
--- /dev/null
+++ b/src/corelib/tools/qeasingcurve.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEASINGCURVE_H
+#define QEASINGCURVE_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qobjectdefs.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+class QEasingCurvePrivate;
+class Q_CORE_EXPORT QEasingCurve
+{
+ Q_GADGET
+ Q_ENUMS(Type)
+public:
+ enum Type {
+ Linear,
+ InQuad, OutQuad, InOutQuad, OutInQuad,
+ InCubic, OutCubic, InOutCubic, OutInCubic,
+ InQuart, OutQuart, InOutQuart, OutInQuart,
+ InQuint, OutQuint, InOutQuint, OutInQuint,
+ InSine, OutSine, InOutSine, OutInSine,
+ InExpo, OutExpo, InOutExpo, OutInExpo,
+ InCirc, OutCirc, InOutCirc, OutInCirc,
+ InElastic, OutElastic, InOutElastic, OutInElastic,
+ InBack, OutBack, InOutBack, OutInBack,
+ InBounce, OutBounce, InOutBounce, OutInBounce,
+ InCurve, OutCurve, SineCurve, CosineCurve,
+ Custom, NCurveTypes
+ };
+
+ QEasingCurve(Type type = Linear);
+ QEasingCurve(const QEasingCurve &other);
+ ~QEasingCurve();
+
+ QEasingCurve &operator=(const QEasingCurve &other);
+ bool operator==(const QEasingCurve &other) const;
+ inline bool operator!=(const QEasingCurve &other) const
+ { return !(this->operator==(other)); }
+
+ qreal amplitude() const;
+ void setAmplitude(qreal amplitude);
+
+ qreal period() const;
+ void setPeriod(qreal period);
+
+ qreal overshoot() const;
+ void setOvershoot(qreal overshoot);
+
+ Type type() const;
+ void setType(Type type);
+ typedef qreal (*EasingFunction)(qreal progress);
+ void setCustomType(EasingFunction func);
+ EasingFunction customType() const;
+
+ qreal valueForProgress(qreal progress) const;
+private:
+ QEasingCurvePrivate *d_ptr;
+ friend Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_CORE_EXPORT QDebug operator<<(QDebug debug, const QEasingCurve &item);
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/corelib/tools/qline.cpp b/src/corelib/tools/qline.cpp
index f615dcd..88825a3 100644
--- a/src/corelib/tools/qline.cpp
+++ b/src/corelib/tools/qline.cpp
@@ -260,7 +260,7 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QLine &p)
{
- d << "QLine(" << p.p1() << "," << p.p2() << ")";
+ d << "QLine(" << p.p1() << ',' << p.p2() << ')';
return d;
}
#endif
@@ -822,7 +822,7 @@ qreal QLineF::angle(const QLineF &l) const
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QLineF &p)
{
- d << "QLineF(" << p.p1() << "," << p.p2() << ")";
+ d << "QLineF(" << p.p1() << ',' << p.p2() << ')';
return d;
}
#endif
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 4317933..357b5d7 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -42,7 +42,6 @@
#include "qglobal.h"
#ifndef QT_NO_SYSTEMLOCALE
-#define QLOCALE_CPP
QT_BEGIN_NAMESPACE
class QSystemLocale;
static QSystemLocale *QSystemLocale_globalSystemLocale();
@@ -120,7 +119,7 @@ static char *_qdtoa( NEEDS_VOLATILE double d, int mode, int ndigits, int *decpt,
Q_CORE_EXPORT char *qdtoa(double d, int mode, int ndigits, int *decpt,
int *sign, char **rve, char **digits_str);
Q_CORE_EXPORT double qstrtod(const char *s00, char const **se, bool *ok);
-Q_CORE_EXPORT qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok);
+static qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok);
static qulonglong qstrtoull(const char *nptr, const char **endptr, register int base, bool *ok);
#if defined(Q_CC_MWERKS) && defined(Q_OS_WIN32)
@@ -328,7 +327,7 @@ static QString readEscapedFormatString(const QString &format, int *idx)
{
int &i = *idx;
- Q_ASSERT(format.at(i).unicode() == '\'');
+ Q_ASSERT(format.at(i) == QLatin1Char('\''));
++i;
if (i == format.size())
return QString();
@@ -642,7 +641,7 @@ static QLocale::MeasurementSystem winSystemMeasurementSystem()
QString iMeasure = QT_WA_INLINE(
QString::fromUtf16(reinterpret_cast<ushort*>(output)),
QString::fromLocal8Bit(reinterpret_cast<char*>(output)));
- if (iMeasure == QString::fromLatin1("1")) {
+ if (iMeasure == QLatin1String("1")) {
return QLocale::ImperialSystem;
}
}
@@ -780,7 +779,7 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const
Instead it can return a "Windows code". This maps windows codes to ISO country names. */
struct WindowsToISOListElt {
- int windows_code;
+ ushort windows_code;
char iso_name[6];
};
@@ -1143,7 +1142,7 @@ static QString macToQtFormat(const QString &sys_fmt)
break;
case 'S': // fractional second
if (repeat < 3)
- result += QLatin1String("z");
+ result += QLatin1Char('z');
else
result += QLatin1String("zzz");
break;
@@ -1157,7 +1156,7 @@ static QString macToQtFormat(const QString &sys_fmt)
if (repeat >= 2)
result += QLatin1String("dd");
else
- result += QLatin1String("d");
+ result += QLatin1Char('d');
break;
case 'a':
result += QLatin1String("AP");
@@ -1541,7 +1540,7 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
l = QLocale(s);
return ds;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
@@ -1609,6 +1608,8 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
This constructor converts the locale name to a language/country
pair; it does not use the system locale database.
+ QLocale's data is based on Common Locale Data Repository v1.6.1.
+
The double-to-string and string-to-double conversion functions are
covered by the following licenses:
@@ -1629,8 +1630,6 @@ QDataStream &operator>>(QDataStream &ds, QLocale &l)
This product includes software developed by the University of
California, Berkeley and its contributors.
- QLocale's data is based on Common Locale Data Repository v1.6.1.
-
\sa QString::arg(), QString::toInt(), QString::toDouble()
*/
@@ -4678,7 +4677,7 @@ static qulonglong qstrtoull(const char *nptr, const char **endptr, register int
* Ignores `locale' stuff. Assumes that the upper and lower case
* alphabets and digits are each contiguous.
*/
-Q_CORE_EXPORT qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok)
+static qlonglong qstrtoll(const char *nptr, const char **endptr, register int base, bool *ok)
{
register const char *s;
register qulonglong acc;
@@ -5375,6 +5374,14 @@ static Bigint *mult(Bigint *a, Bigint *b)
static Bigint *p5s;
+struct p5s_deleter
+{
+ ~p5s_deleter()
+ {
+ Bfree(p5s);
+ }
+};
+
static Bigint *pow5mult(Bigint *b, int k)
{
Bigint *b1, *p5, *p51;
@@ -5396,6 +5403,7 @@ static Bigint *pow5mult(Bigint *b, int k)
return b;
if (!(p5 = p5s)) {
/* first time */
+ static p5s_deleter deleter;
p5 = p5s = i2b(625);
p5->next = 0;
}
diff --git a/src/corelib/tools/qlocale.h b/src/corelib/tools/qlocale.h
index 5b611eb..987ab4e 100644
--- a/src/corelib/tools/qlocale.h
+++ b/src/corelib/tools/qlocale.h
@@ -99,11 +99,9 @@ public:
virtual QVariant query(QueryType type, QVariant in) const;
virtual QLocale fallbackLocale() const;
-#ifdef QLOCALE_CPP
private:
QSystemLocale(bool);
friend QSystemLocale *QSystemLocale_globalSystemLocale();
-#endif
};
#endif
diff --git a/src/corelib/tools/qlocale_data_p.h b/src/corelib/tools/qlocale_data_p.h
index 37f59a4..e0eecf3 100644
--- a/src/corelib/tools/qlocale_data_p.h
+++ b/src/corelib/tools/qlocale_data_p.h
@@ -60,8 +60,8 @@ QT_BEGIN_NAMESPACE
*/
struct CountryLanguage
{
- quint32 languageId;
- quint32 countryId;
+ quint16 languageId;
+ quint16 countryId;
};
static const CountryLanguage ImperialMeasurementSystems[] = {
{ 31, 225 },
@@ -83,7 +83,7 @@ static const int ImperialMeasurementSystemsCount =
*/
-static const uint locale_index[] = {
+static const quint16 locale_index[] = {
0, // unused
0, // C
0, // Abkhazian
@@ -2313,7 +2313,7 @@ static const char language_name_list[] =
"Chewa\0"
;
-static const uint language_name_index[] = {
+static const quint16 language_name_index[] = {
0, // Unused
8, // C
10, // Abkhazian
@@ -2727,7 +2727,7 @@ static const char country_name_list[] =
"SerbiaAndMontenegro\0"
;
-static const uint country_name_index[] = {
+static const quint16 country_name_index[] = {
0, // AnyCountry
8, // Afghanistan
20, // Albania
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index 9d36a83..ed7fc10 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -96,7 +96,7 @@ public:
ShowBase = 0x80,
UppercaseBase = 0x100,
- ForcePoint = Alternate,
+ ForcePoint = Alternate
};
enum GroupSeparatorMode {
@@ -140,29 +140,29 @@ public:
QString dateTimeToString(const QString &format, const QDate *date, const QTime *time,
const QLocale *q) const;
- quint32 m_language_id, m_country_id;
+ quint16 m_language_id, m_country_id;
quint16 m_decimal, m_group, m_list, m_percent,
m_zero, m_minus, m_plus, m_exponential;
- quint32 m_short_date_format_idx, m_short_date_format_size;
- quint32 m_long_date_format_idx, m_long_date_format_size;
- quint32 m_short_time_format_idx, m_short_time_format_size;
- quint32 m_long_time_format_idx, m_long_time_format_size;
- quint32 m_standalone_short_month_names_idx, m_standalone_short_month_names_size;
- quint32 m_standalone_long_month_names_idx, m_standalone_long_month_names_size;
- quint32 m_standalone_narrow_month_names_idx, m_standalone_narrow_month_names_size;
- quint32 m_short_month_names_idx, m_short_month_names_size;
- quint32 m_long_month_names_idx, m_long_month_names_size;
- quint32 m_narrow_month_names_idx, m_narrow_month_names_size;
- quint32 m_standalone_short_day_names_idx, m_standalone_short_day_names_size;
- quint32 m_standalone_long_day_names_idx, m_standalone_long_day_names_size;
- quint32 m_standalone_narrow_day_names_idx, m_standalone_narrow_day_names_size;
- quint32 m_short_day_names_idx, m_short_day_names_size;
- quint32 m_long_day_names_idx, m_long_day_names_size;
- quint32 m_narrow_day_names_idx, m_narrow_day_names_size;
- quint32 m_am_idx, m_am_size;
- quint32 m_pm_idx, m_pm_size;
+ quint16 m_short_date_format_idx, m_short_date_format_size;
+ quint16 m_long_date_format_idx, m_long_date_format_size;
+ quint16 m_short_time_format_idx, m_short_time_format_size;
+ quint16 m_long_time_format_idx, m_long_time_format_size;
+ quint16 m_standalone_short_month_names_idx, m_standalone_short_month_names_size;
+ quint16 m_standalone_long_month_names_idx, m_standalone_long_month_names_size;
+ quint16 m_standalone_narrow_month_names_idx, m_standalone_narrow_month_names_size;
+ quint16 m_short_month_names_idx, m_short_month_names_size;
+ quint16 m_long_month_names_idx, m_long_month_names_size;
+ quint16 m_narrow_month_names_idx, m_narrow_month_names_size;
+ quint16 m_standalone_short_day_names_idx, m_standalone_short_day_names_size;
+ quint16 m_standalone_long_day_names_idx, m_standalone_long_day_names_size;
+ quint16 m_standalone_narrow_day_names_idx, m_standalone_narrow_day_names_size;
+ quint16 m_short_day_names_idx, m_short_day_names_size;
+ quint16 m_long_day_names_idx, m_long_day_names_size;
+ quint16 m_narrow_day_names_idx, m_narrow_day_names_size;
+ quint16 m_am_idx, m_am_size;
+ quint16 m_pm_idx, m_pm_size;
};
inline char QLocalePrivate::digitToCLocale(const QChar &in) const
diff --git a/src/corelib/tools/qmap.h b/src/corelib/tools/qmap.h
index bd9ba74..65247cd 100644
--- a/src/corelib/tools/qmap.h
+++ b/src/corelib/tools/qmap.h
@@ -1016,7 +1016,7 @@ Q_INLINE_TEMPLATE int QMultiMap<Key, T>::remove(const Key &key, const T &value)
{
int n = 0;
typename QMap<Key, T>::iterator i(find(key));
- typename QMap<Key, T>::const_iterator end(QMap<Key, T>::constEnd());
+ typename QMap<Key, T>::iterator end(QMap<Key, T>::end());
while (i != end && !qMapLessThanKey<Key>(key, i.key())) {
if (i.value() == value) {
#if defined(Q_CC_RVCT)
diff --git a/src/corelib/tools/qpoint.cpp b/src/corelib/tools/qpoint.cpp
index feea473..90b44b1 100644
--- a/src/corelib/tools/qpoint.cpp
+++ b/src/corelib/tools/qpoint.cpp
@@ -373,7 +373,7 @@ QDebug operator<<(QDebug dbg, const QPoint &p) {
QDebug operator<<(QDebug d, const QPointF &p)
{
- d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ")";
+ d.nospace() << "QPointF(" << p.x() << ", " << p.y() << ')';
return d;
}
#endif
@@ -442,6 +442,19 @@ QDebug operator<<(QDebug d, const QPointF &p)
otherwise returns false.
*/
+
+/*!
+ Returns the sum of the absolute values of x() and y(),
+ traditionally known as the "Manhattan length" of the vector from
+ the origin to the point.
+
+ \sa QPoint::manhattanLength()
+*/
+qreal QPointF::manhattanLength() const
+{
+ return qAbs(x())+qAbs(y());
+}
+
/*!
\fn qreal QPointF::x() const
diff --git a/src/corelib/tools/qpoint.h b/src/corelib/tools/qpoint.h
index 1dab7e2..e716bf7 100644
--- a/src/corelib/tools/qpoint.h
+++ b/src/corelib/tools/qpoint.h
@@ -192,6 +192,8 @@ public:
QPointF(const QPoint &p);
QPointF(qreal xpos, qreal ypos);
+ qreal manhattanLength() const;
+
bool isNull() const;
qreal x() const;
diff --git a/src/corelib/tools/qregexp.cpp b/src/corelib/tools/qregexp.cpp
index f357956..92ac3ba 100644
--- a/src/corelib/tools/qregexp.cpp
+++ b/src/corelib/tools/qregexp.cpp
@@ -4076,6 +4076,6 @@ QDataStream &operator>>(QDataStream &in, QRegExp &regExp)
regExp = newRegExp;
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
QT_END_NAMESPACE
diff --git a/src/corelib/tools/qringbuffer_p.h b/src/corelib/tools/qringbuffer_p.h
index a1bfab0..939f4e0 100644
--- a/src/corelib/tools/qringbuffer_p.h
+++ b/src/corelib/tools/qringbuffer_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class Q_CORE_EXPORT QRingBuffer
+class QRingBuffer
{
public:
inline QRingBuffer(int growth = 4096) : basicBlockSize(growth) {
@@ -74,6 +74,52 @@ public:
return buffers.isEmpty() ? 0 : (buffers.first().constData() + head);
}
+ // access the bytes at a specified position
+ // the out-variable length will contain the amount of bytes readable
+ // from there, e.g. the amount still the same QByteArray
+ inline const char *readPointerAtPosition(qint64 pos, qint64 &length) const {
+ if (buffers.isEmpty()) {
+ length = 0;
+ return 0;
+ }
+
+ if (pos >= bufferSize) {
+ length = 0;
+ return 0;
+ }
+
+ // special case: it is in the first buffer
+ int nextDataBlockSizeValue = nextDataBlockSize();
+ if (pos - head < nextDataBlockSizeValue) {
+ length = nextDataBlockSizeValue - pos;
+ return buffers.at(0).constData() + head + pos;
+ }
+
+ // special case: we only had one buffer and tried to read over it
+ if (buffers.length() == 1) {
+ length = 0;
+ return 0;
+ }
+
+ // skip the first
+ pos -= nextDataBlockSizeValue;
+
+ // normal case: it is somewhere in the second to the-one-before-the-tailBuffer
+ for (int i = 1; i < tailBuffer; i++) {
+ if (pos >= buffers[i].size()) {
+ pos -= buffers[i].size();
+ continue;
+ }
+
+ length = buffers[i].length() - pos;
+ return buffers[i].constData() + pos;
+ }
+
+ // it is in the tail buffer
+ length = tail - pos;
+ return buffers[tailBuffer].constData() + pos;
+ }
+
inline void free(int bytes) {
bufferSize -= bytes;
if (bufferSize < 0)
diff --git a/src/corelib/tools/qset.h b/src/corelib/tools/qset.h
index 4b19adc..993ce48 100644
--- a/src/corelib/tools/qset.h
+++ b/src/corelib/tools/qset.h
@@ -85,6 +85,8 @@ public:
inline bool contains(const T &value) const { return q_hash.contains(value); }
+ bool contains(const QSet<T> &set) const;
+
class const_iterator;
class iterator
@@ -274,6 +276,18 @@ Q_INLINE_TEMPLATE QSet<T> &QSet<T>::subtract(const QSet<T> &other)
return *this;
}
+template <class T>
+Q_INLINE_TEMPLATE bool QSet<T>::contains(const QSet<T> &other) const
+{
+ typename QSet<T>::const_iterator i = other.constBegin();
+ while (i != other.constEnd()) {
+ if (!contains(*i))
+ return false;
+ ++i;
+ }
+ return true;
+}
+
template <typename T>
Q_OUTOFLINE_TEMPLATE QList<T> QSet<T>::toList() const
{
diff --git a/src/corelib/tools/qsize.h b/src/corelib/tools/qsize.h
index 57c55ca..237625e 100644
--- a/src/corelib/tools/qsize.h
+++ b/src/corelib/tools/qsize.h
@@ -98,8 +98,10 @@ Q_DECLARE_TYPEINFO(QSize, Q_MOVABLE_TYPE);
QSize stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSize &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSize &);
+#endif
/*****************************************************************************
@@ -171,14 +173,14 @@ inline const QSize operator*(qreal c, const QSize &s)
inline QSize &QSize::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
wd = qRound(wd/c); ht = qRound(ht/c);
return *this;
}
inline const QSize operator/(const QSize &s, qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
return QSize(qRound(s.wd/c), qRound(s.ht/c));
}
@@ -249,8 +251,10 @@ Q_DECLARE_TYPEINFO(QSizeF, Q_MOVABLE_TYPE);
QSizeF stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_CORE_EXPORT QDataStream &operator<<(QDataStream &, const QSizeF &);
Q_CORE_EXPORT QDataStream &operator>>(QDataStream &, QSizeF &);
+#endif
/*****************************************************************************
@@ -327,14 +331,14 @@ inline const QSizeF operator*(qreal c, const QSizeF &s)
inline QSizeF &QSizeF::operator/=(qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
wd = wd/c; ht = ht/c;
return *this;
}
inline const QSizeF operator/(const QSizeF &s, qreal c)
{
- Q_ASSERT(!qFuzzyCompare(c + 1, 1));
+ Q_ASSERT(!qFuzzyIsNull(c));
return QSizeF(s.wd/c, s.ht/c);
}
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index e61a568..6ae3c38 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -195,6 +195,68 @@ static int ucstrnicmp(const ushort *a, const ushort *b, int l)
return ucstricmp(a, a + l, b, b + l);
}
+static bool qMemEquals(const quint16 *a, const quint16 *b, int length)
+{
+ // Benchmarking indicates that doing memcmp is much slower than
+ // executing the comparison ourselves.
+ // To make it even faster, we do a 32-bit comparison, comparing
+ // twice the amount of data as a normal word-by-word comparison.
+ //
+ // Benchmarking results on a 2.33 GHz Core2 Duo, with a 64-QChar
+ // block of data, with 4194304 iterations (per iteration):
+ // operation usec cpu ticks
+ // memcmp 330 710
+ // 16-bit 79 167-171
+ // 32-bit aligned 49 105-109
+ //
+ // Testing also indicates that unaligned 32-bit loads are as
+ // performant as 32-bit aligned.
+ if (a == b || !length)
+ return true;
+
+ register union {
+ const quint16 *w;
+ const quint32 *d;
+ quintptr value;
+ } sa, sb;
+ sa.w = a;
+ sb.w = b;
+
+ // check alignment
+ if ((sa.value & 2) == (sb.value & 2)) {
+ // both addresses have the same alignment
+ if (sa.value & 2) {
+ // both addresses are not aligned to 4-bytes boundaries
+ // compare the first character
+ if (*sa.w != *sb.w)
+ return false;
+ --length;
+ ++sa.w;
+ ++sb.w;
+
+ // now both addresses are 4-bytes aligned
+ }
+
+ // both addresses are 4-bytes aligned
+ // do a fast 32-bit comparison
+ register const quint32 *e = sa.d + (length >> 1);
+ for ( ; sa.d != e; ++sa.d, ++sb.d) {
+ if (*sa.d != *sb.d)
+ return false;
+ }
+
+ // do we have a tail?
+ return (length & 1) ? *sa.w == *sb.w : true;
+ } else {
+ // one of the addresses isn't 4-byte aligned but the other is
+ register const quint16 *e = sa.w + length;
+ for ( ; sa.w != e; ++sa.w, ++sb.w) {
+ if (*sa.w != *sb.w)
+ return false;
+ }
+ }
+ return true;
+}
/*!
\internal
@@ -884,6 +946,23 @@ QString::QString(int size, QChar ch)
}
}
+/*!
+ Constructs a string of the given \a size without initializing the
+ characters. This is only used in \c QStringBuilder::toString().
+
+ \internal
+*/
+
+QString::QString(int size, Uninitialized)
+{
+ d = (Data*) qMalloc(sizeof(Data)+size*sizeof(QChar));
+ d->ref = 1;
+ d->alloc = d->size = size;
+ d->clean = d->asciiCache = d->simpletext = d->righttoleft = d->capacity = 0;
+ d->data = d->array;
+ d->array[size] = '\0';
+}
+
/*! \fn QString::QString(const QLatin1String &str)
Constructs a copy of the Latin-1 string \a str.
@@ -1910,8 +1989,10 @@ QString &QString::replace(QChar c, const QLatin1String &after, Qt::CaseSensitivi
*/
bool QString::operator==(const QString &other) const
{
- return (size() == other.size()) &&
- (memcmp((char*)unicode(),(char*)other.unicode(), size()*sizeof(QChar))==0);
+ if (d->size != other.d->size)
+ return false;
+
+ return qMemEquals(d->data, other.d->data, d->size);
}
/*!
@@ -3138,7 +3219,7 @@ bool QString::startsWith(const QString& s, Qt::CaseSensitivity cs) const
if (s.d->size > d->size)
return false;
if (cs == Qt::CaseSensitive) {
- return memcmp((char*)d->data, (char*)s.d->data, s.d->size*sizeof(QChar)) == 0;
+ return qMemEquals(d->data, s.d->data, s.d->size);
} else {
uint last = 0;
uint olast = 0;
@@ -3209,7 +3290,7 @@ bool QString::endsWith(const QString& s, Qt::CaseSensitivity cs) const
if (pos < 0)
return false;
if (cs == Qt::CaseSensitive) {
- return memcmp((char*)&d->data[pos], (char*)s.d->data, s.d->size*sizeof(QChar)) == 0;
+ return qMemEquals(d->data + pos, s.d->data, s.d->size);
} else {
uint last = 0;
uint olast = 0;
@@ -7696,7 +7777,8 @@ QString QStringRef::toString() const {
*/
bool operator==(const QStringRef &s1,const QStringRef &s2)
{ return (s1.size() == s2.size() &&
- (memcmp((char*)s1.unicode(), (char*)s2.unicode(), s1.size()*sizeof(QChar))==0)); }
+ qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+}
/*! \relates QStringRef
@@ -7705,7 +7787,8 @@ bool operator==(const QStringRef &s1,const QStringRef &s2)
*/
bool operator==(const QString &s1,const QStringRef &s2)
{ return (s1.size() == s2.size() &&
- (memcmp((char*)s1.unicode(), (char*)s2.unicode(), s1.size()*sizeof(QChar))==0)); }
+ qMemEquals((const ushort *)s1.unicode(), (const ushort *)s2.unicode(), s1.size()));
+}
/*! \relates QStringRef
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 69c4f2f..7c0d6a3 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -579,6 +579,9 @@ public:
bool isSimpleText() const { if (!d->clean) updateProperties(); return d->simpletext; }
bool isRightToLeft() const { if (!d->clean) updateProperties(); return d->righttoleft; }
+ struct Uninitialized {};
+ QString(int size, Uninitialized);
+
private:
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
QString &operator+=(const char *s);
@@ -1001,13 +1004,15 @@ inline int QByteArray::findRev(const QString &s, int from) const
# endif // QT3_SUPPORT
#endif // QT_NO_CAST_TO_ASCII
+#ifndef QT_USE_FAST_OPERATOR_PLUS
+# ifndef QT_USE_FAST_CONCATENATION
inline const QString operator+(const QString &s1, const QString &s2)
{ QString t(s1); t += s2; return t; }
inline const QString operator+(const QString &s1, QChar s2)
{ QString t(s1); t += s2; return t; }
inline const QString operator+(QChar s1, const QString &s2)
{ QString t(s1); t += s2; return t; }
-#ifndef QT_NO_CAST_FROM_ASCII
+# ifndef QT_NO_CAST_FROM_ASCII
inline QT_ASCII_CAST_WARN const QString operator+(const QString &s1, const char *s2)
{ QString t(s1); t += QString::fromAscii(s2); return t; }
inline QT_ASCII_CAST_WARN const QString operator+(const char *s1, const QString &s2)
@@ -1020,7 +1025,9 @@ inline QT_ASCII_CAST_WARN const QString operator+(const QByteArray &ba, const QS
{ QString t = QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); t += s; return t; }
inline QT_ASCII_CAST_WARN const QString operator+(const QString &s, const QByteArray &ba)
{ QString t(s); t += QString::fromAscii(ba.constData(), qstrnlen(ba.constData(), ba.size())); return t; }
-#endif
+# endif // QT_NO_CAST_FROM_ASCII
+# endif // QT_USE_FAST_CONCATENATION
+#endif // QT_USE_FAST_OPERATOR_PLUS
#ifndef QT_NO_STL
inline std::string QString::toStdString() const
@@ -1229,6 +1236,8 @@ inline int QStringRef::localeAwareCompare(const QStringRef &s1, const QStringRef
QT_END_NAMESPACE
-QT_END_HEADER
+#ifdef QT_USE_FAST_CONCATENATION
+#include <QtCore/qstringbuilder.h>
+#endif
#endif // QSTRING_H
diff --git a/src/corelib/tools/qstringbuilder.cpp b/src/corelib/tools/qstringbuilder.cpp
new file mode 100644
index 0000000..366a07b
--- /dev/null
+++ b/src/corelib/tools/qstringbuilder.cpp
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstringbuilder.h"
+
+/*!
+ \class QLatin1Literal
+ \reentrant
+ \since 4.6
+
+ \brief The QLatin1Literal class provides a thin wrapper around string
+ literals used in source code.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup text
+ \mainclass
+
+ Unlike \c QLatin1String, a \c QLatin1Literal can retrieve its size
+ without iterating over the literal.
+
+ The main use of \c QLatin1Literal is in conjunction with \c QStringBuilder
+ to reduce the number of reallocations needed to build up a string from
+ smaller chunks.
+
+ \sa QStringBuilder, QLatin1String, QString, QStringRef
+*/
+
+/*! \fn int QLatin1Literal::size() const
+
+ Returns the number of characters in the literal \e{excluding} the trailing
+ NULL char.
+*/
+
+/*! \fn QLatin1Literal::QLatin1Literal(const char(&string)[N])
+
+ Constructs a new literal from the given \a string.
+*/
+
+/*! \fn char *QLatin1Literal::data() const
+
+ Returns a pointer to the first character of the string literal.
+ The string literal is terminated by a NUL character.
+*/
+
+/*! \fn QLatin1Literal::operator QString() const
+
+ Converts the \c QLatin1Literal into a \c QString object.
+*/
+
+
+
+/*!
+ \class QStringBuilder
+ \reentrant
+ \since 4.6
+
+ \brief The QStringBuilder class is a template class that provides a facility to build
+ up QStrings from smaller chunks.
+
+ \ingroup tools
+ \ingroup shared
+ \ingroup text
+ \mainclass
+
+ When creating strings from smaller chunks, typically \c QString::operator+()
+ is used, resulting in \e{n - 1} reallocations when operating on \e{n} chunks.
+
+ QStringBuilder uses expression templates to collect the individual parts,
+ compute the total size, allocate memory for the resulting QString object,
+ and copy the contents of the chunks into the result.
+
+ The QStringBuilder class is not to be used explicitly in user code.
+ Instances of the class are created as return values of the operator%()
+ function, acting on objects of type \c QString, \c QLatin1String,
+ \c QLatin1Literal, \c \QStringRef, \c QChar, \c QCharRef,
+ \c QLatin1Char, and \c char.
+
+ Concatenating strings with operator%() generally yields better
+ performance then using \c QString::operator+() on the same chunks
+ if there are three or more of them, and performs equally well in other
+ cases.
+
+ \sa QLatin1Literal, QString
+*/
+
+/* \fn template <class A, class B> QStringBuilder<A, B> operator%(const A &a, const B &b)
+
+ Returns a \c QStringBuilder object that is converted to a QString object
+ when assigned to a variable of QString type or passed to a function that
+ takes a QString parameter.
+
+ This function is usable with arguments of type \c QString,
+ \c QLatin1String, \c QLatin1Literal, \c QStringRef,
+ \c QChar, \c QCharRef, \c QLatin1Char, and \c char.
+*/
+
diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h
new file mode 100644
index 0000000..30a7c67
--- /dev/null
+++ b/src/corelib/tools/qstringbuilder.h
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSTRINGBUILDER_H
+#define QSTRINGBUILDER_H
+
+#include <QtCore/qstring.h>
+
+#include <string.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Core)
+
+// ### Qt 5: merge with QLatin1String
+class QLatin1Literal
+{
+public:
+ template <int N>
+ QLatin1Literal(const char (&str)[N]) : m_size(N - 1), m_data(str) {}
+
+ inline int size() const { return m_size; }
+ inline const char *data() const { return m_data; }
+
+private:
+ const int m_size;
+ const char *m_data;
+};
+
+
+template <typename T> class QConcatenable {};
+
+template <typename A, typename B>
+class QStringBuilder
+{
+public:
+ QStringBuilder(const A &a_, const B &b_) : a(a_), b(b_) {}
+
+ operator QString() const
+ {
+ QString s(QConcatenable< QStringBuilder<A, B> >::size(*this),
+ QString::Uninitialized());
+
+ QChar *d = s.data();
+ QConcatenable< QStringBuilder<A, B> >::appendTo(*this, d);
+ return s;
+ }
+ QByteArray toLatin1() const { return QString(*this).toLatin1(); }
+
+ const A &a;
+ const B &b;
+};
+
+
+template <> struct QConcatenable<char>
+{
+ typedef char type;
+ static int size(const char) { return 1; }
+ static inline void appendTo(const char c, QChar *&out)
+ {
+ *out++ = QLatin1Char(c);
+ }
+};
+
+template <> struct QConcatenable<QLatin1Char>
+{
+ typedef QLatin1Char type;
+ static int size(const QLatin1Char) { return 1; }
+ static inline void appendTo(const QLatin1Char c, QChar *&out)
+ {
+ *out++ = c;
+ }
+};
+
+template <> struct QConcatenable<QChar>
+{
+ typedef QChar type;
+ static int size(const QChar) { return 1; }
+ static inline void appendTo(const QChar c, QChar *&out)
+ {
+ *out++ = c;
+ }
+};
+
+template <> struct QConcatenable<QCharRef>
+{
+ typedef QCharRef type;
+ static int size(const QCharRef &) { return 1; }
+ static inline void appendTo(const QCharRef &c, QChar *&out)
+ {
+ *out++ = QChar(c);
+ }
+};
+
+template <> struct QConcatenable<QLatin1String>
+{
+ typedef QLatin1String type;
+ static int size(const QLatin1String &a) { return qstrlen(a.latin1()); }
+ static inline void appendTo(const QLatin1String &a, QChar *&out)
+ {
+ for (const char *s = a.latin1(); *s; )
+ *out++ = QLatin1Char(*s++);
+ }
+
+};
+
+template <> struct QConcatenable<QLatin1Literal>
+{
+ typedef QLatin1Literal type;
+ static int size(const QLatin1Literal &a) { return a.size(); }
+ static inline void appendTo(const QLatin1Literal &a, QChar *&out)
+ {
+ for (const char *s = a.data(); *s; )
+ *out++ = QLatin1Char(*s++);
+ }
+};
+
+template <> struct QConcatenable<QString>
+{
+ typedef QString type;
+ static int size(const QString &a) { return a.size(); }
+ static inline void appendTo(const QString &a, QChar *&out)
+ {
+ const int n = a.size();
+ memcpy(out, (char*)a.constData(), sizeof(QChar) * n);
+ out += n;
+ }
+};
+
+template <> struct QConcatenable<QStringRef>
+{
+ typedef QStringRef type;
+ static int size(const QStringRef &a) { return a.size(); }
+ static inline void appendTo(QStringRef a, QChar *&out)
+ {
+ const int n = a.size();
+ memcpy(out, (char*)a.constData(), sizeof(QChar) * n);
+ out += n;
+ }
+};
+
+#ifndef QT_NO_CAST_FROM_ASCII
+template <int N> struct QConcatenable<char[N]>
+{
+ typedef char type[N];
+ static int size(const char[N]) { return N - 1; }
+ static inline void appendTo(const char a[N], QChar *&out)
+ {
+ for (int i = 0; i < N - 1; ++i)
+ *out++ = QLatin1Char(a[i]);
+ }
+};
+
+template <> struct QConcatenable<const char *>
+{
+ typedef char const *type;
+ static int size(const char *a) { return qstrlen(a); }
+ static inline void appendTo(const char *a, QChar *&out)
+ {
+ while (*a)
+ *out++ = QLatin1Char(*a++);
+ }
+};
+#endif
+
+template <typename A, typename B>
+struct QConcatenable< QStringBuilder<A, B> >
+{
+ typedef QStringBuilder<A, B> type;
+ static int size(const type &p)
+ {
+ return QConcatenable<A>::size(p.a) + QConcatenable<B>::size(p.b);
+ }
+ static inline void appendTo(const QStringBuilder<A, B> &p, QChar *&out)
+ {
+ QConcatenable<A>::appendTo(p.a, out);
+ QConcatenable<B>::appendTo(p.b, out);
+ }
+};
+
+template <typename A, typename B>
+QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
+operator%(const A &a, const B &b)
+{
+ return QStringBuilder<A, B>(a, b);
+}
+
+#ifdef QT_USE_FAST_OPERATOR_PLUS
+template <typename A, typename B>
+QStringBuilder<typename QConcatenable<A>::type, typename QConcatenable<B>::type>
+operator+(const A &a, const B &b)
+{
+ return QStringBuilder<A, B>(a, b);
+}
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSTRINGBUILDER_H
diff --git a/src/corelib/tools/qtimeline.cpp b/src/corelib/tools/qtimeline.cpp
index 3a03558..ee4f73c 100644
--- a/src/corelib/tools/qtimeline.cpp
+++ b/src/corelib/tools/qtimeline.cpp
@@ -48,20 +48,6 @@
QT_BEGIN_NAMESPACE
-static const qreal pi = qreal(3.14159265359);
-static const qreal halfPi = pi / qreal(2.0);
-
-
-static inline qreal qt_sinProgress(qreal value)
-{
- return qSin((value * pi) - halfPi) / 2 + qreal(0.5);
-}
-
-static inline qreal qt_smoothBeginEndMixFactor(qreal value)
-{
- return qMin(qMax(1 - value * 2 + qreal(0.3), qreal(0.0)), qreal(1.0));
-}
-
class QTimeLinePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QTimeLine)
@@ -70,7 +56,7 @@ public:
: startTime(0), duration(1000), startFrame(0), endFrame(0),
updateInterval(1000 / 25),
totalLoopCount(1), currentLoopCount(0), currentTime(0), timerId(0),
- direction(QTimeLine::Forward), curveShape(QTimeLine::EaseInOutCurve),
+ direction(QTimeLine::Forward), easingCurve(QEasingCurve::InOutSine),
state(QTimeLine::NotRunning)
{ }
@@ -88,7 +74,7 @@ public:
QTime timer;
QTimeLine::Direction direction;
- QTimeLine::CurveShape curveShape;
+ QEasingCurve easingCurve;
QTimeLine::State state;
inline void setState(QTimeLine::State newState)
{
@@ -523,12 +509,68 @@ void QTimeLine::setUpdateInterval(int interval)
QTimeLine::CurveShape QTimeLine::curveShape() const
{
Q_D(const QTimeLine);
- return d->curveShape;
+ switch (d->easingCurve.type()) {
+ default:
+ case QEasingCurve::InOutSine:
+ return EaseInOutCurve;
+ case QEasingCurve::InCurve:
+ return EaseInCurve;
+ case QEasingCurve::OutCurve:
+ return EaseOutCurve;
+ case QEasingCurve::Linear:
+ return LinearCurve;
+ case QEasingCurve::SineCurve:
+ return SineCurve;
+ case QEasingCurve::CosineCurve:
+ return CosineCurve;
+ }
+ return EaseInOutCurve;
}
+
void QTimeLine::setCurveShape(CurveShape shape)
{
+ switch (shape) {
+ default:
+ case EaseInOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InOutSine));
+ break;
+ case EaseInCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::InCurve));
+ break;
+ case EaseOutCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::OutCurve));
+ break;
+ case LinearCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::Linear));
+ break;
+ case SineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::SineCurve));
+ break;
+ case CosineCurve:
+ setEasingCurve(QEasingCurve(QEasingCurve::CosineCurve));
+ break;
+ }
+}
+
+/*!
+ \property QTimeLine::easingCurve
+
+ Specifies the easing curve that the timeline will use.
+ If both easing curve and curveShape are set, the last set property will
+ override the previous one. (If valueForTime() is reimplemented it will
+ override both)
+*/
+
+QEasingCurve QTimeLine::easingCurve() const
+{
+ Q_D(const QTimeLine);
+ return d->easingCurve;
+}
+
+void QTimeLine::setEasingCurve(const QEasingCurve& curve)
+{
Q_D(QTimeLine);
- d->curveShape = shape;
+ d->easingCurve = curve;
}
/*!
@@ -608,42 +650,8 @@ qreal QTimeLine::valueForTime(int msec) const
Q_D(const QTimeLine);
msec = qMin(qMax(msec, 0), d->duration);
- // Simple linear interpolation
qreal value = msec / qreal(d->duration);
-
- switch (d->curveShape) {
- case EaseInOutCurve:
- value = qt_sinProgress(value);
- break;
- // SmoothBegin blends Smooth and Linear Interpolation.
- // Progress 0 - 0.3 : Smooth only
- // Progress 0.3 - ~ 0.5 : Mix of Smooth and Linear
- // Progress ~ 0.5 - 1 : Linear only
- case EaseInCurve: {
- const qreal sinProgress = qt_sinProgress(value);
- const qreal linearProgress = value;
- const qreal mix = qt_smoothBeginEndMixFactor(value);
- value = sinProgress * mix + linearProgress * (1 - mix);
- break;
- }
- case EaseOutCurve: {
- const qreal sinProgress = qt_sinProgress(value);
- const qreal linearProgress = value;
- const qreal mix = qt_smoothBeginEndMixFactor(1 - value);
- value = sinProgress * mix + linearProgress * (1 - mix);
- break;
- }
- case SineCurve:
- value = (qSin(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2;
- break;
- case CosineCurve:
- value = (qCos(((msec * pi * 2) / d->duration) - pi/2) + 1) / 2;
- break;
- default:
- break;
- }
-
- return value;
+ return d->easingCurve.valueForProgress(value);
}
/*!
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
index 18c3980..48c9232 100644
--- a/src/corelib/tools/qtimeline.h
+++ b/src/corelib/tools/qtimeline.h
@@ -42,6 +42,7 @@
#ifndef QTIMELINE_H
#define QTIMELINE_H
+#include <QtCore/qeasingcurve.h>
#include <QtCore/qobject.h>
QT_BEGIN_HEADER
@@ -60,6 +61,7 @@ class Q_CORE_EXPORT QTimeLine : public QObject
Q_PROPERTY(Direction direction READ direction WRITE setDirection)
Q_PROPERTY(int loopCount READ loopCount WRITE setLoopCount)
Q_PROPERTY(CurveShape curveShape READ curveShape WRITE setCurveShape)
+ Q_PROPERTY(QEasingCurve easingCurve READ easingCurve WRITE setEasingCurve)
public:
enum State {
NotRunning,
@@ -105,6 +107,9 @@ public:
CurveShape curveShape() const;
void setCurveShape(CurveShape shape);
+ QEasingCurve easingCurve() const;
+ void setEasingCurve(const QEasingCurve &curve);
+
int currentTime() const;
int currentFrame() const;
qreal currentValue() const;
diff --git a/src/corelib/tools/qunicodetables_p.h b/src/corelib/tools/qunicodetables_p.h
index e588313..5f696dd 100644
--- a/src/corelib/tools/qunicodetables_p.h
+++ b/src/corelib/tools/qunicodetables_p.h
@@ -178,7 +178,7 @@ namespace QUnicodeTables {
}
Q_CORE_EXPORT int QT_FASTCALL script(uint ucs4);
- Q_CORE_EXPORT_INLINE int QT_FASTCALL script(const QChar &ch) {
+ inline int script(const QChar &ch) {
return script(ch.unicode());
}
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index 610b8e7..d9fad3a 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -83,19 +83,9 @@ struct Q_CORE_EXPORT QVectorData
};
template <typename T>
-struct QVectorTypedData
-{
- QBasicAtomicInt ref;
- int alloc;
- int size;
-#if defined(QT_ARCH_SPARC) && defined(Q_CC_GNU) && defined(__LP64__) && defined(QT_BOOTSTRAPPED)
- // workaround for bug in gcc 3.4.2
- uint sharable;
- uint capacity;
-#else
- uint sharable : 1;
- uint capacity : 1;
-#endif
+struct QVectorTypedData : private QVectorData
+{ // private inheritance as we must not access QVectorData member thought QVectorTypedData
+ // as this would break strict aliasing rules. (in the case of shared_null)
T array[1];
};
@@ -105,14 +95,21 @@ template <typename T>
class QVector
{
typedef QVectorTypedData<T> Data;
- union { QVectorData *p; QVectorTypedData<T> *d; };
+ union {
+ QVectorData *d;
+#if defined(Q_CC_SUN) && (__SUNPRO_CC <= 0x550)
+ QVectorTypedData<T> *p;
+#else
+ Data *p;
+#endif
+ };
public:
- inline QVector() : p(&QVectorData::shared_null) { d->ref.ref(); }
+ inline QVector() : d(&QVectorData::shared_null) { d->ref.ref(); }
explicit QVector(int size);
QVector(int size, const T &t);
inline QVector(const QVector<T> &v) : d(v.d) { d->ref.ref(); if (!d->sharable) detach_helper(); }
- inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(d); }
+ inline ~QVector() { if (!d) return; if (!d->ref.deref()) free(p); }
QVector<T> &operator=(const QVector<T> &v);
bool operator==(const QVector<T> &v) const;
inline bool operator!=(const QVector<T> &v) const { return !(*this == v); }
@@ -131,9 +128,9 @@ public:
inline bool isDetached() const { return d->ref == 1; }
inline void setSharable(bool sharable) { if (!sharable) detach(); d->sharable = sharable; }
- inline T *data() { detach(); return d->array; }
- inline const T *data() const { return d->array; }
- inline const T *constData() const { return d->array; }
+ inline T *data() { detach(); return p->array; }
+ inline const T *data() const { return p->array; }
+ inline const T *constData() const { return p->array; }
void clear();
const T &at(int i) const;
@@ -226,12 +223,12 @@ public:
typedef T* iterator;
typedef const T* const_iterator;
#endif
- inline iterator begin() { detach(); return d->array; }
- inline const_iterator begin() const { return d->array; }
- inline const_iterator constBegin() const { return d->array; }
- inline iterator end() { detach(); return d->array + d->size; }
- inline const_iterator end() const { return d->array + d->size; }
- inline const_iterator constEnd() const { return d->array + d->size; }
+ inline iterator begin() { detach(); return p->array; }
+ inline const_iterator begin() const { return p->array; }
+ inline const_iterator constBegin() const { return p->array; }
+ inline iterator end() { detach(); return p->array + d->size; }
+ inline const_iterator end() const { return p->array + d->size; }
+ inline const_iterator constEnd() const { return p->array + d->size; }
iterator insert(iterator before, int n, const T &x);
inline iterator insert(iterator before, const T &x) { return insert(before, 1, x); }
iterator erase(iterator begin, iterator end);
@@ -328,11 +325,11 @@ inline void QVector<T>::clear()
template <typename T>
inline const T &QVector<T>::at(int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::at", "index out of range");
- return d->array[i]; }
+ return p->array[i]; }
template <typename T>
inline const T &QVector<T>::operator[](int i) const
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
- return d->array[i]; }
+ return p->array[i]; }
template <typename T>
inline T &QVector<T>::operator[](int i)
{ Q_ASSERT_X(i >= 0 && i < d->size, "QVector<T>::operator[]", "index out of range");
@@ -370,7 +367,7 @@ QVector<T> &QVector<T>::operator=(const QVector<T> &v)
{
v.d->ref.ref();
if (!d->ref.deref())
- free(d);
+ free(p);
d = v.d;
if (!d->sharable)
detach_helper();
@@ -388,31 +385,31 @@ inline QVectorData *QVector<T>::malloc(int aalloc)
template <typename T>
QVector<T>::QVector(int asize)
{
- p = malloc(asize);
+ d = malloc(asize);
d->ref = 1;
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
if (QTypeInfo<T>::isComplex) {
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
new (--i) T;
} else {
- qMemSet(d->array, 0, asize * sizeof(T));
+ qMemSet(p->array, 0, asize * sizeof(T));
}
}
template <typename T>
QVector<T>::QVector(int asize, const T &t)
{
- p = malloc(asize);
+ d = malloc(asize);
d->ref = 1;
d->alloc = d->size = asize;
d->sharable = true;
d->capacity = false;
- T* i = d->array + d->size;
- while (i != d->array)
+ T* i = p->array + d->size;
+ while (i != p->array)
new (--i) T(t);
}
@@ -421,7 +418,7 @@ void QVector<T>::free(Data *x)
{
if (QTypeInfo<T>::isComplex) {
T* b = x->array;
- T* i = b + x->size;
+ T* i = b + reinterpret_cast<QVectorData *>(x)->size;
while (i-- != b)
i->~T();
}
@@ -433,7 +430,7 @@ void QVector<T>::realloc(int asize, int aalloc)
{
T *pOld;
T *pNew;
- union { QVectorData *p; Data *d; } x;
+ union { QVectorData *d; Data *p; } x;
x.d = d;
if (QTypeInfo<T>::isComplex && asize < d->size && d->ref == 1 ) {
@@ -506,7 +503,7 @@ void QVector<T>::realloc(int asize, int aalloc)
if (d != x.d) {
if (!d->ref.deref())
- free(d);
+ free(p);
d = x.d;
}
}
@@ -514,15 +511,15 @@ void QVector<T>::realloc(int asize, int aalloc)
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i) const
{
- if (i < 0 || i >= p->size) {
+ if (i < 0 || i >= d->size) {
return T();
}
- return d->array[i];
+ return p->array[i];
}
template<typename T>
Q_OUTOFLINE_TEMPLATE T QVector<T>::value(int i, const T &defaultValue) const
{
- return ((i < 0 || i >= p->size) ? defaultValue : d->array[i]);
+ return ((i < 0 || i >= d->size) ? defaultValue : p->array[i]);
}
template <typename T>
@@ -533,14 +530,14 @@ void QVector<T>::append(const T &t)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + 1, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isComplex)
- new (d->array + d->size) T(copy);
+ new (p->array + d->size) T(copy);
else
- d->array[d->size] = copy;
+ p->array[d->size] = copy;
} else {
if (QTypeInfo<T>::isComplex)
- new (d->array + d->size) T(t);
+ new (p->array + d->size) T(t);
else
- d->array[d->size] = t;
+ p->array[d->size] = t;
}
++d->size;
}
@@ -548,27 +545,27 @@ void QVector<T>::append(const T &t)
template <typename T>
Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n, const T &t)
{
- int offset = before - d->array;
+ int offset = before - p->array;
if (n != 0) {
const T copy(t);
if (d->ref != 1 || d->size + n > d->alloc)
realloc(d->size, QVectorData::grow(sizeOfTypedData(), d->size + n, sizeof(T),
QTypeInfo<T>::isStatic));
if (QTypeInfo<T>::isStatic) {
- T *b = d->array + d->size;
- T *i = d->array + d->size + n;
+ T *b = p->array + d->size;
+ T *i = p->array + d->size + n;
while (i != b)
new (--i) T;
- i = d->array + d->size;
+ i = p->array + d->size;
T *j = i + n;
- b = d->array + offset;
+ b = p->array + offset;
while (i != b)
*--j = *--i;
i = b+n;
while (i != b)
*--i = copy;
} else {
- T *b = d->array + offset;
+ T *b = p->array + offset;
T *i = b + n;
memmove(i, b, (d->size - offset) * sizeof(T));
while (i != b)
@@ -576,29 +573,29 @@ Q_TYPENAME QVector<T>::iterator QVector<T>::insert(iterator before, size_type n,
}
d->size += n;
}
- return d->array + offset;
+ return p->array + offset;
}
template <typename T>
Q_TYPENAME QVector<T>::iterator QVector<T>::erase(iterator abegin, iterator aend)
{
- int f = abegin - d->array;
- int l = aend - d->array;
+ int f = abegin - p->array;
+ int l = aend - p->array;
int n = l - f;
detach();
if (QTypeInfo<T>::isComplex) {
- qCopy(d->array+l, d->array+d->size, d->array+f);
- T *i = d->array+d->size;
- T* b = d->array+d->size-n;
+ qCopy(p->array+l, p->array+d->size, p->array+f);
+ T *i = p->array+d->size;
+ T* b = p->array+d->size-n;
while (i != b) {
--i;
i->~T();
}
} else {
- memmove(d->array + f, d->array + l, (d->size-l)*sizeof(T));
+ memmove(p->array + f, p->array + l, (d->size-l)*sizeof(T));
}
d->size -= n;
- return d->array + f;
+ return p->array + f;
}
template <typename T>
@@ -608,9 +605,9 @@ bool QVector<T>::operator==(const QVector<T> &v) const
return false;
if (d == v.d)
return true;
- T* b = d->array;
+ T* b = p->array;
T* i = b + d->size;
- T* j = v.d->array + d->size;
+ T* j = v.p->array + d->size;
while (i != b)
if (!(*--i == *--j))
return false;
@@ -623,8 +620,8 @@ QVector<T> &QVector<T>::fill(const T &from, int asize)
const T copy(from);
resize(asize < 0 ? d->size : asize);
if (d->size) {
- T *i = d->array + d->size;
- T *b = d->array;
+ T *i = p->array + d->size;
+ T *b = p->array;
while (i != b)
*--i = copy;
}
@@ -637,9 +634,9 @@ QVector<T> &QVector<T>::operator+=(const QVector &l)
int newSize = d->size + l.d->size;
realloc(d->size, newSize);
- T *w = d->array + newSize;
- T *i = l.d->array + l.d->size;
- T *b = l.d->array;
+ T *w = p->array + newSize;
+ T *i = l.p->array + l.d->size;
+ T *b = l.p->array;
while (i != b) {
if (QTypeInfo<T>::isComplex)
new (--w) T(*--i);
@@ -656,11 +653,11 @@ int QVector<T>::indexOf(const T &t, int from) const
if (from < 0)
from = qMax(from + d->size, 0);
if (from < d->size) {
- T* n = d->array + from - 1;
- T* e = d->array + d->size;
+ T* n = p->array + from - 1;
+ T* e = p->array + d->size;
while (++n != e)
if (*n == t)
- return n - d->array;
+ return n - p->array;
}
return -1;
}
@@ -673,8 +670,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
else if (from >= d->size)
from = d->size-1;
if (from >= 0) {
- T* b = d->array;
- T* n = d->array + from + 1;
+ T* b = p->array;
+ T* n = p->array + from + 1;
while (n != b) {
if (*--n == t)
return n - b;
@@ -686,8 +683,8 @@ int QVector<T>::lastIndexOf(const T &t, int from) const
template <typename T>
bool QVector<T>::contains(const T &t) const
{
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
if (*--i == t)
return true;
@@ -698,8 +695,8 @@ template <typename T>
int QVector<T>::count(const T &t) const
{
int c = 0;
- T* b = d->array;
- T* i = d->array + d->size;
+ T* b = p->array;
+ T* i = p->array + d->size;
while (i != b)
if (*--i == t)
++c;
diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri
index 8d27100..cf13cc9 100644
--- a/src/corelib/tools/tools.pri
+++ b/src/corelib/tools/tools.pri
@@ -11,6 +11,7 @@ HEADERS += \
tools/qcryptographichash.h \
tools/qdatetime.h \
tools/qdatetime_p.h \
+ tools/qeasingcurve.h \
tools/qhash.h \
tools/qline.h \
tools/qlinkedlist.h \
@@ -19,6 +20,7 @@ HEADERS += \
tools/qlocale_p.h \
tools/qlocale_data_p.h \
tools/qmap.h \
+ tools/qcontiguouscache.h \
tools/qpodlist_p.h \
tools/qpoint.h \
tools/qqueue.h \
@@ -30,6 +32,7 @@ HEADERS += \
tools/qsize.h \
tools/qstack.h \
tools/qstring.h \
+ tools/qstringbuilder.h \
tools/qstringlist.h \
tools/qstringmatcher.h \
tools/qtextboundaryfinder.h \
@@ -46,7 +49,7 @@ SOURCES += \
tools/qbytearraymatcher.cpp \
tools/qcryptographichash.cpp \
tools/qdatetime.cpp \
- tools/qdumper.cpp \
+ tools/qeasingcurve.cpp \
tools/qhash.cpp \
tools/qline.cpp \
tools/qlinkedlist.cpp \
@@ -54,12 +57,14 @@ SOURCES += \
tools/qlocale.cpp \
tools/qpoint.cpp \
tools/qmap.cpp \
+ tools/qcontiguouscache.cpp \
tools/qrect.cpp \
tools/qregexp.cpp \
tools/qshareddata.cpp \
tools/qsharedpointer.cpp \
tools/qsize.cpp \
tools/qstring.cpp \
+ tools/qstringbuilder.cpp \
tools/qstringlist.cpp \
tools/qtextboundaryfinder.cpp \
tools/qtimeline.cpp \
diff --git a/src/corelib/xml/make-parser.sh b/src/corelib/xml/make-parser.sh
index 0c2ba12..0e2cbe1 100755
--- a/src/corelib/xml/make-parser.sh
+++ b/src/corelib/xml/make-parser.sh
@@ -6,10 +6,8 @@ mkdir -p $me/out
for f in $me/out/*.h; do
n=$(basename $f)
- p4 open $n
cp $f $n
done
-p4 revert -a ...
-p4 diff -dub ...
+git diff .
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp
index 6fe6ebf..bce7161 100644
--- a/src/corelib/xml/qxmlstream.cpp
+++ b/src/corelib/xml/qxmlstream.cpp
@@ -628,7 +628,7 @@ while (<STDIN>) {
$sizes[$i++] = $counter;
$counter += length 1 + $_;
}
-print " \"\\0\";\n\nstatic const int QXmlStreamReader_tokenTypeString_indices[] = {\n ";
+print " \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n ";
for ($j = 0; $j < $i; ++$j) {
printf "$sizes[$j], ";
}
@@ -659,10 +659,9 @@ static const char QXmlStreamReader_tokenTypeString_string[] =
"Comment\0"
"DTD\0"
"EntityReference\0"
- "ProcessingInstruction\0"
- "\0";
+ "ProcessingInstruction\0";
-static const int QXmlStreamReader_tokenTypeString_indices[] = {
+static const short QXmlStreamReader_tokenTypeString_indices[] = {
0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
};
@@ -3059,7 +3058,7 @@ QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNa
QString s;
int n = ++namespacePrefixCount;
forever {
- s = QLatin1String("n") + QString::number(n++);
+ s = QLatin1Char('n') + QString::number(n++);
int j = namespaceDeclarations.size() - 2;
while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
--j;
diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/xml/qxmlstream.g
index d5e64a6..0cc744e 100644
--- a/src/corelib/xml/qxmlstream.g
+++ b/src/corelib/xml/qxmlstream.g
@@ -1533,8 +1533,8 @@ attribute ::= qname space_opt EQ space_opt attribute_value;
QStringRef namespacePrefix = symString(attribute.key);
QStringRef namespaceUri = symString(attribute.value);
attributeStack.pop();
- if ((namespacePrefix == QLatin1String("xml")
- ^ namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))
+ if (((namespacePrefix == QLatin1String("xml"))
+ ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
|| namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
|| namespaceUri.isEmpty()
|| namespacePrefix == QLatin1String("xmlns"))
diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h
index 201f0c1..26509ff 100644
--- a/src/corelib/xml/qxmlstream_p.h
+++ b/src/corelib/xml/qxmlstream_p.h
@@ -1,3 +1,4 @@
+// This file was generated by qlalr - DO NOT EDIT!
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
@@ -126,27 +127,22 @@ public:
GOTO_CHECK_OFFSET = 1017
};
- static const char *const spell [];
- static const int lhs [];
- static const int rhs [];
- static const int goto_default [];
- static const int action_default [];
- static const int action_index [];
- static const int action_info [];
- static const int action_check [];
+ static const char *const spell [];
+ static const qint16 lhs [];
+ static const qint16 rhs [];
+ static const qint16 goto_default [];
+ static const qint16 action_default [];
+ static const qint16 action_index [];
+ static const qint16 action_info [];
+ static const qint16 action_check [];
static inline int nt_action (int state, int nt)
{
- const int *const goto_index = &action_index [GOTO_INDEX_OFFSET];
- const int *const goto_check = &action_check [GOTO_CHECK_OFFSET];
-
- const int yyn = goto_index [state] + nt;
-
- if (yyn < 0 || goto_check [yyn] != nt)
+ const int yyn = action_index [GOTO_INDEX_OFFSET + state] + nt;
+ if (yyn < 0 || action_check [GOTO_CHECK_OFFSET + yyn] != nt)
return goto_default [nt];
- const int *const goto_info = &action_info [GOTO_INFO_OFFSET];
- return goto_info [yyn];
+ return action_info [GOTO_INFO_OFFSET + yyn];
}
static inline int t_action (int state, int token)
@@ -169,7 +165,7 @@ const char *const QXmlStreamReader_Table::spell [] = {
"EMPTY", "ANY", "PCDATA", 0, 0, 0, 0, "CDATA", "ID", "IDREF",
"IDREFS", "ENTITIES", "NMTOKEN", "NMTOKENS", "<?xml", "version", 0};
-const int QXmlStreamReader_Table::lhs [] = {
+const qint16 QXmlStreamReader_Table::lhs [] = {
57, 57, 59, 59, 59, 59, 59, 59, 59, 59,
67, 68, 64, 72, 72, 72, 75, 66, 66, 66,
66, 79, 78, 80, 80, 80, 80, 80, 80, 81,
@@ -198,7 +194,7 @@ const int QXmlStreamReader_Table::lhs [] = {
58, 58, 58, 58, 58, 58, 58, 58, 74, 69,
69, 77, 111, 102, 102, 102, 102, 102, 140};
-const int QXmlStreamReader_Table:: rhs[] = {
+const qint16 QXmlStreamReader_Table:: rhs[] = {
2, 1, 4, 2, 2, 2, 2, 2, 2, 0,
1, 1, 9, 2, 4, 0, 4, 4, 6, 6,
4, 1, 3, 1, 1, 1, 2, 2, 2, 1,
@@ -227,7 +223,7 @@ const int QXmlStreamReader_Table:: rhs[] = {
2, 2, 2, 2, 2, 2, 2, 0, 1, 0,
1, 1, 1, 1, 1, 1, 1, 1, 2};
-const int QXmlStreamReader_Table::action_default [] = {
+const qint16 QXmlStreamReader_Table::action_default [] = {
10, 258, 0, 2, 1, 0, 124, 116, 118, 119,
126, 128, 122, 11, 113, 107, 0, 108, 127, 110,
114, 112, 120, 123, 125, 106, 109, 111, 117, 115,
@@ -272,7 +268,7 @@ const int QXmlStreamReader_Table::action_default [] = {
260, 0, 230, 0, 0, 13, 269, 9, 5, 8,
4, 0, 7, 258, 6, 0, 3};
-const int QXmlStreamReader_Table::goto_default [] = {
+const qint16 QXmlStreamReader_Table::goto_default [] = {
2, 4, 3, 49, 388, 43, 37, 52, 47, 41,
249, 53, 127, 84, 393, 81, 85, 126, 42, 46,
169, 130, 131, 146, 145, 149, 138, 136, 140, 147,
@@ -283,7 +279,7 @@ const int QXmlStreamReader_Table::goto_default [] = {
264, 252, 251, 250, 339, 326, 325, 329, 398, 399,
50, 51, 59, 0};
-const int QXmlStreamReader_Table::action_index [] = {
+const qint16 QXmlStreamReader_Table::action_index [] = {
-21, -57, 33, 119, 960, 70, -57, -57, -57, -57,
-57, -57, -57, -57, -57, -57, 105, -57, -57, -57,
-57, -57, -57, -57, -57, -57, -57, -57, -57, -57,
@@ -372,7 +368,7 @@ const int QXmlStreamReader_Table::action_index [] = {
28, 15, 82, -84, -84, -84, -84, -84, -84, -84,
-84, -84, -84, 3, -84, 98, -84};
-const int QXmlStreamReader_Table::action_info [] = {
+const qint16 QXmlStreamReader_Table::action_info [] = {
65, 332, 65, 405, 392, 385, 377, 65, 414, 410,
415, 55, 397, 374, 373, 217, 206, 408, 65, 65,
207, 211, 216, 1, 55, 199, 182, 192, 70, 70,
@@ -506,7 +502,7 @@ const int QXmlStreamReader_Table::action_info [] = {
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0};
-const int QXmlStreamReader_Table::action_check [] = {
+const qint16 QXmlStreamReader_Table::action_check [] = {
26, 18, 26, 14, 4, 4, 4, 26, 24, 14,
4, 26, 4, 4, 4, 4, 22, 55, 26, 26,
42, 4, 4, 44, 26, 22, 19, 12, 2, 2,
diff --git a/src/dbus/qdbus_symbols_p.h b/src/dbus/qdbus_symbols_p.h
index 764d368..db5e1bb 100644
--- a/src/dbus/qdbus_symbols_p.h
+++ b/src/dbus/qdbus_symbols_p.h
@@ -353,7 +353,7 @@ DEFINEFUNC(dbus_bool_t , dbus_signature_validate_single, (const char *
DBusError *error),
(signature, error), return)
DEFINEFUNC(dbus_bool_t , dbus_type_is_basic, (int typecode),
- (typecode), return);
+ (typecode), return)
DEFINEFUNC(dbus_bool_t , dbus_type_is_fixed, (int typecode),
(typecode), return)
diff --git a/src/dbus/qdbuserror.cpp b/src/dbus/qdbuserror.cpp
index 955a31c..2347a54 100644
--- a/src/dbus/qdbuserror.cpp
+++ b/src/dbus/qdbuserror.cpp
@@ -339,7 +339,7 @@ QString QDBusError::errorString(ErrorType error)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QDBusError &msg)
{
- dbg.nospace() << "QDBusError(" << msg.name() << ", " << msg.message() << ")";
+ dbg.nospace() << "QDBusError(" << msg.name() << ", " << msg.message() << ')';
return dbg.space();
}
#endif
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index f40a45f..33f44ab 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -74,7 +74,7 @@ static inline QDebug operator<<(QDebug dbg, const QThread *th)
dbg.nospace() << "QThread(ptr=" << (void*)th;
if (th && !th->objectName().isEmpty())
dbg.nospace() << ", name=" << th->objectName();
- dbg.nospace() << ")";
+ dbg.nospace() << ')';
return dbg.space();
}
@@ -90,7 +90,7 @@ static inline QDebug operator<<(QDebug dbg, const QDBusConnectionPrivate *conn)
dbg.nospace() << "same thread";
else
dbg.nospace() << conn->thread();
- dbg.nospace() << ")";
+ dbg.nospace() << ')';
return dbg.space();
}
@@ -565,7 +565,7 @@ static void huntAndEmit(DBusConnection *connection, DBusMessage *msg,
QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator it = haystack.children.constBegin();
QDBusConnectionPrivate::ObjectTreeNode::DataList::ConstIterator end = haystack.children.constEnd();
for ( ; it != end; ++it)
- huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1String("/") + it->name);
+ huntAndEmit(connection, msg, needle, *it, isScriptable, isAdaptor, path + QLatin1Char('/') + it->name);
if (needle == haystack.obj) {
// is this a signal we should relay?
diff --git a/src/dbus/qdbusmetaobject.cpp b/src/dbus/qdbusmetaobject.cpp
index 8eb8b1a..ce76ecc 100644
--- a/src/dbus/qdbusmetaobject.cpp
+++ b/src/dbus/qdbusmetaobject.cpp
@@ -601,7 +601,7 @@ QDBusMetaObject *QDBusMetaObject::createMetaObject(const QString &interface, con
// mark as an error
error = QDBusError(QDBusError::UnknownInterface,
- QString( QLatin1String("Interface '%1' was not found") )
+ QString::fromLatin1("Interface '%1' was not found")
.arg(interface));
return 0;
}
diff --git a/src/dbus/qdbusthreaddebug_p.h b/src/dbus/qdbusthreaddebug_p.h
index 20d819f..f2ac598 100644
--- a/src/dbus/qdbusthreaddebug_p.h
+++ b/src/dbus/qdbusthreaddebug_p.h
@@ -100,7 +100,7 @@ enum ThreadAction {
RemoveWatchAction = 61,
ToggleWatchAction = 62,
SocketReadAction = 63,
- SocketWriteAction = 64,
+ SocketWriteAction = 64
};
struct QDBusLockerBase
diff --git a/src/dbus/qdbusutil.cpp b/src/dbus/qdbusutil.cpp
index 471b899..dd983a0 100644
--- a/src/dbus/qdbusutil.cpp
+++ b/src/dbus/qdbusutil.cpp
@@ -80,15 +80,15 @@ static bool variantToString(const QVariant &arg, QString &out)
int argType = arg.userType();
if (argType == QVariant::StringList) {
- out += QLatin1String("{");
+ out += QLatin1Char('{');
QStringList list = arg.toStringList();
foreach (QString item, list)
out += QLatin1Char('\"') + item + QLatin1String("\", ");
if (!list.isEmpty())
out.chop(2);
- out += QLatin1String("}");
+ out += QLatin1Char('}');
} else if (argType == QVariant::ByteArray) {
- out += QLatin1String("{");
+ out += QLatin1Char('{');
QByteArray list = arg.toByteArray();
for (int i = 0; i < list.count(); ++i) {
out += QString::number(list.at(i));
@@ -96,9 +96,9 @@ static bool variantToString(const QVariant &arg, QString &out)
}
if (!list.isEmpty())
out.chop(2);
- out += QLatin1String("}");
+ out += QLatin1Char('}');
} else if (argType == QVariant::List) {
- out += QLatin1String("{");
+ out += QLatin1Char('{');
QList<QVariant> list = arg.toList();
foreach (QVariant item, list) {
if (!variantToString(item, out))
@@ -107,7 +107,7 @@ static bool variantToString(const QVariant &arg, QString &out)
}
if (!list.isEmpty())
out.chop(2);
- out += QLatin1String("}");
+ out += QLatin1Char('}');
} else if (argType == QMetaType::Char || argType == QMetaType::Short || argType == QMetaType::Int
|| argType == QMetaType::Long || argType == QMetaType::LongLong) {
out += QString::number(arg.toLongLong());
@@ -142,7 +142,7 @@ static bool variantToString(const QVariant &arg, QString &out)
return false;
out += QLatin1Char(']');
} else if (arg.canConvert(QVariant::String)) {
- out += QLatin1String("\"") + arg.toString() + QLatin1String("\"");
+ out += QLatin1Char('\"') + arg.toString() + QLatin1Char('\"');
} else {
out += QLatin1Char('[');
out += QLatin1String(arg.typeName());
@@ -226,7 +226,7 @@ bool argToString(const QDBusArgument &busArg, QString &out)
if (elementType != QDBusArgument::BasicType && elementType != QDBusArgument::VariantType
&& elementType != QDBusArgument::MapEntryType)
- out += QLatin1String("]");
+ out += QLatin1Char(']');
return true;
}
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index b0878ab..bd8a9ec 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -394,7 +394,7 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
(QAccessibleFactoryInterface_iid, QLatin1String("/accessible")))
#endif
-Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories);
+Q_GLOBAL_STATIC(QList<QAccessible::InterfaceFactory>, qAccessibleFactories)
QAccessible::UpdateHandler QAccessible::updateHandler = 0;
QAccessible::RootObjectHandler QAccessible::rootObjectHandler = 0;
diff --git a/src/gui/accessible/qaccessible_win.cpp b/src/gui/accessible/qaccessible_win.cpp
index 99cc272..6195451 100644
--- a/src/gui/accessible/qaccessible_win.cpp
+++ b/src/gui/accessible/qaccessible_win.cpp
@@ -50,7 +50,7 @@
#include <winuser.h>
#if !defined(WINABLEAPI)
-# if defined(Q_OS_WINCE)
+# if defined(Q_WS_WINCE)
# include <bldver.h>
# endif
# include <winable.h>
@@ -61,7 +61,7 @@
#include <comdef.h>
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
#endif
@@ -239,7 +239,7 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
typedef void (WINAPI *PtrNotifyWinEvent)(DWORD, HWND, LONG, LONG);
-#if defined(Q_OS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
+#if defined(Q_WS_WINCE) // ### TODO: check for NotifyWinEvent in CE 6.0
// There is no user32.lib nor NotifyWinEvent for CE
return;
#else
@@ -270,9 +270,9 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (!w) {
if (reason != QAccessible::ContextHelpStart &&
reason != QAccessible::ContextHelpEnd)
- w = qApp->focusWidget();
+ w = QApplication::focusWidget();
if (!w) {
- w = qApp->activeWindow();
+ w = QApplication::activeWindow();
if (!w)
return;
@@ -289,7 +289,7 @@ void QAccessible::updateAccessibility(QObject *o, int who, Event reason)
if (reason != MenuCommand) { // MenuCommand is faked
ptrNotifyWinEvent(reason, w->winId(), OBJID_CLIENT, who);
}
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
}
void QAccessible::setRootObject(QObject *o)
diff --git a/src/gui/accessible/qaccessibleobject.cpp b/src/gui/accessible/qaccessibleobject.cpp
index 7df097b..0c710f0 100644
--- a/src/gui/accessible/qaccessibleobject.cpp
+++ b/src/gui/accessible/qaccessibleobject.cpp
@@ -212,7 +212,7 @@ QAccessibleApplication::QAccessibleApplication()
static QWidgetList topLevelWidgets()
{
QWidgetList list;
- const QWidgetList tlw(qApp->topLevelWidgets());
+ const QWidgetList tlw(QApplication::topLevelWidgets());
for (int i = 0; i < tlw.count(); ++i) {
QWidget *w = tlw.at(i);
if (!(w->windowType() == Qt::Popup) && !(w->windowType() == Qt::Desktop))
@@ -308,7 +308,7 @@ int QAccessibleApplication::navigate(RelationFlag relation, int entry,
}
break;
case FocusChild:
- targetObject = qApp->activeWindow();
+ targetObject = QApplication::activeWindow();
break;
default:
break;
@@ -322,11 +322,11 @@ QString QAccessibleApplication::text(Text t, int) const
{
switch (t) {
case Name:
- if (qApp->activeWindow())
- return qApp->activeWindow()->windowTitle();
+ if (QApplication::activeWindow())
+ return QApplication::activeWindow()->windowTitle();
break;
case Description:
- return qApp->applicationFilePath();
+ return QApplication::applicationFilePath();
default:
break;
}
@@ -342,7 +342,7 @@ QAccessible::Role QAccessibleApplication::role(int) const
/*! \reimp */
QAccessible::State QAccessibleApplication::state(int) const
{
- return qApp->activeWindow() ? Focused : Normal;
+ return QApplication::activeWindow() ? Focused : Normal;
}
/*! \reimp */
@@ -356,7 +356,7 @@ bool QAccessibleApplication::doAction(int action, int child, const QVariantList
{
if (action == 0 || action == 1) {
QWidget *w = 0;
- w = qApp->activeWindow();
+ w = QApplication::activeWindow();
if (!w)
w = topLevelWidgets().at(0);
if (!w)
diff --git a/src/gui/accessible/qaccessiblewidget.cpp b/src/gui/accessible/qaccessiblewidget.cpp
index 753ac57..1c2fcef 100644
--- a/src/gui/accessible/qaccessiblewidget.cpp
+++ b/src/gui/accessible/qaccessiblewidget.cpp
@@ -102,24 +102,7 @@ static QString buddyString(const QWidget *widget)
QString Q_GUI_EXPORT qt_accStripAmp(const QString &text)
{
- if (text.isEmpty())
- return text;
-
- const QChar *ch = text.unicode();
- int length = text.length();
- QString str;
- while (length > 0) {
- if (*ch == QLatin1Char('&')) {
- ++ch;
- --length;
- if (!ch)
- --ch;
- }
- str += *ch;
- ++ch;
- --length;
- }
- return str;
+ return QString(text).remove(QLatin1Char('&'));
}
QString Q_GUI_EXPORT qt_accHotKey(const QString &text)
diff --git a/src/gui/animation/animation.pri b/src/gui/animation/animation.pri
new file mode 100644
index 0000000..27763ca
--- /dev/null
+++ b/src/gui/animation/animation.pri
@@ -0,0 +1,3 @@
+# Qt gui animation module
+
+SOURCES += animation/qguivariantanimation.cpp
diff --git a/src/gui/animation/qguivariantanimation.cpp b/src/gui/animation/qguivariantanimation.cpp
new file mode 100644
index 0000000..bcffb85
--- /dev/null
+++ b/src/gui/animation/qguivariantanimation.cpp
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_ANIMATION
+
+#include <QtCore/qvariantanimation.h>
+#include <private/qvariantanimation_p.h>
+
+#include <QtGui/qcolor.h>
+
+QT_BEGIN_NAMESPACE
+
+template<> Q_INLINE_TEMPLATE QColor _q_interpolate(const QColor &f,const QColor &t, qreal progress)
+{
+ return QColor(_q_interpolate(f.red(), t.red(), progress),
+ _q_interpolate(f.green(), t.green(), progress),
+ _q_interpolate(f.blue(), t.blue(), progress),
+ _q_interpolate(f.alpha(), t.alpha(), progress));
+}
+
+static int qRegisterGuiGetInterpolator()
+{
+ qRegisterAnimationInterpolator<QColor>(_q_interpolateVariant<QColor>);
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiGetInterpolator)
+
+static int qUnregisterGuiGetInterpolator()
+{
+ qRegisterAnimationInterpolator<QColor>(
+ (QVariant (*)(const QColor &, const QColor &, qreal))0); // cast required by Sun CC 5.5
+
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiGetInterpolator)
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_ANIMATION
diff --git a/src/gui/dialogs/qcolordialog.cpp b/src/gui/dialogs/qcolordialog.cpp
index 4702d14..8299381 100644
--- a/src/gui/dialogs/qcolordialog.cpp
+++ b/src/gui/dialogs/qcolordialog.cpp
@@ -1066,7 +1066,7 @@ QColorShower::QColorShower(QColorDialog *parent)
QGridLayout *gl = new QGridLayout(this);
gl->setMargin(gl->spacing());
lab = new QColorShowLabel(this);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
lab->setMinimumWidth(60);
#else
lab->setMinimumWidth(20);
@@ -1369,13 +1369,13 @@ void QColorDialogPrivate::init(const QColor &initial)
leftLay = 0;
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
smallDisplay = true;
const int lumSpace = 20;
#else
// small displays (e.g. PDAs) cannot fit the full color dialog,
// so just use the color picker.
- smallDisplay = (qApp->desktop()->width() < 480 || qApp->desktop()->height() < 350);
+ smallDisplay = (QApplication::desktop()->width() < 480 || QApplication::desktop()->height() < 350);
const int lumSpace = topLay->spacing() / 2;
#endif
@@ -1409,7 +1409,7 @@ void QColorDialogPrivate::init(const QColor &initial)
leftLay->addWidget(lblBasicColors);
leftLay->addWidget(standard);
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
leftLay->addStretch();
#endif
@@ -1578,10 +1578,11 @@ void QColorDialog::setCurrentColor(const QColor &color)
{
Q_D(QColorDialog);
d->setCurrentColor(color.rgb());
- d->selectColor(color.rgb());
+ d->selectColor(color);
d->setCurrentAlpha(color.alpha());
#ifdef Q_WS_MAC
+ d->setCurrentQColor(color);
if (d->delegate)
QColorDialogPrivate::setColor(d->delegate, color);
#endif
diff --git a/src/gui/dialogs/qcolordialog_mac.mm b/src/gui/dialogs/qcolordialog_mac.mm
index 2556265..9862c1c 100644
--- a/src/gui/dialogs/qcolordialog_mac.mm
+++ b/src/gui/dialogs/qcolordialog_mac.mm
@@ -234,16 +234,22 @@ QT_USE_NAMESPACE
CGFloat cyan, magenta, yellow, black, alpha;
[color getCyan:&cyan magenta:&magenta yellow:&yellow black:&black alpha:&alpha];
mQtColor->setCmykF(cyan, magenta, yellow, black, alpha);
+ } else if (colorSpace == NSCalibratedRGBColorSpace || colorSpace == NSDeviceRGBColorSpace) {
+ CGFloat red, green, blue, alpha;
+ [color getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
} else {
- NSColor *tmpColor;
- if (colorSpace == NSCalibratedRGBColorSpace || colorSpace == NSDeviceRGBColorSpace) {
- tmpColor = color;
+ NSColorSpace *colorSpace = [color colorSpace];
+ if ([colorSpace colorSpaceModel] == NSCMYKColorSpaceModel && [color numberOfComponents] == 5){
+ CGFloat components[5];
+ [color getComponents:components];
+ mQtColor->setCmykF(components[0], components[1], components[2], components[3], components[4]);
} else {
- tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ NSColor *tmpColor = [color colorUsingColorSpaceName:NSCalibratedRGBColorSpace];
+ CGFloat red, green, blue, alpha;
+ [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
+ mQtColor->setRgbF(red, green, blue, alpha);
}
- CGFloat red, green, blue, alpha;
- [tmpColor getRed:&red green:&green blue:&blue alpha:&alpha];
- mQtColor->setRgbF(red, green, blue, alpha);
}
if (mPriv)
@@ -414,10 +420,20 @@ void QColorDialogPrivate::setColor(void *delegate, const QColor &color)
{
QMacCocoaAutoReleasePool pool;
QCocoaColorPanelDelegate *theDelegate = static_cast<QCocoaColorPanelDelegate *>(delegate);
- NSColor *nsColor = [NSColor colorWithCalibratedRed:color.red() / 255.0
- green:color.green() / 255.0
- blue:color.blue() / 255.0
- alpha:color.alpha() / 255.0];
+ NSColor *nsColor;
+ const QColor::Spec spec = color.spec();
+ if (spec == QColor::Cmyk) {
+ nsColor = [NSColor colorWithDeviceCyan:color.cyanF()
+ magenta:color.magentaF()
+ yellow:color.yellowF()
+ black:color.blackF()
+ alpha:color.alphaF()];
+ } else {
+ nsColor = [NSColor colorWithCalibratedRed:color.redF()
+ green:color.greenF()
+ blue:color.blueF()
+ alpha:color.alphaF()];
+ }
[[theDelegate colorPanel] setColor:nsColor];
}
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index cecbb87..2d31c0b 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -55,7 +55,7 @@
#ifndef QT_NO_ACCESSIBILITY
#include "qaccessible.h"
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qt_windows.h"
#include "qmenubar.h"
#include "qpointer.h"
@@ -255,7 +255,7 @@ QDialog::QDialog(QWidget *parent, Qt::WindowFlags f)
: QWidget(*new QDialogPrivate, parent,
f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
#endif
@@ -284,7 +284,7 @@ QDialog::QDialog(QWidget *parent, const char *name, bool modal, Qt::WindowFlags
QDialog::QDialog(QDialogPrivate &dd, QWidget *parent, Qt::WindowFlags f)
: QWidget(dd, parent, f | QFlag((f & Qt::WindowType_Mask) == 0 ? Qt::Dialog : 0))
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_smartphone())
setWindowFlags(windowFlags() | Qt::WindowOkButtonHint | QFlag(qt_wince_is_mobile() ? 0 : Qt::WindowCancelButtonHint));
#endif
@@ -372,8 +372,8 @@ void QDialogPrivate::resetModalitySetByOpen()
resetModalityTo = -1;
}
-#ifdef Q_OS_WINCE
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE
+#ifdef Q_WS_WINCE_WM
void QDialogPrivate::_q_doneAction()
{
//Done...
@@ -481,7 +481,7 @@ int QDialog::exec()
setResult(0);
//On Windows Mobile we create an empty menu to hide the current menu
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
#ifndef QT_NO_MENUBAR
QMenuBar *menuBar = 0;
if (!findChild<QMenuBar *>())
@@ -492,7 +492,7 @@ int QDialog::exec()
connect(doneAction, SIGNAL(triggered()), this, SLOT(_q_doneAction()));
}
#endif //QT_NO_MENUBAR
-#endif //Q_OS_WINCE_WM
+#endif //Q_WS_WINCE_WM
#ifdef Q_OS_SYMBIAN
#ifndef QT_NO_MENUBAR
@@ -528,12 +528,12 @@ int QDialog::exec()
int res = result();
if (deleteOnClose)
delete this;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
#ifndef QT_NO_MENUBAR
else if (menuBar)
delete menuBar;
#endif //QT_NO_MENUBAR
-#endif //Q_OS_WINCE_WM
+#endif //Q_WS_WINCE_WM
#ifdef Q_OS_SYMBIAN
#ifndef QT_NO_MENUBAR
else if (menuBar)
diff --git a/src/gui/dialogs/qdialog.h b/src/gui/dialogs/qdialog.h
index ee1997a..bd86251 100644
--- a/src/gui/dialogs/qdialog.h
+++ b/src/gui/dialogs/qdialog.h
@@ -107,7 +107,7 @@ public Q_SLOTS:
protected:
QDialog(QDialogPrivate &, QWidget *parent, Qt::WindowFlags f = 0);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
bool event(QEvent *e);
#endif
void keyPressEvent(QKeyEvent *);
@@ -124,7 +124,7 @@ private:
Q_DECLARE_PRIVATE(QDialog)
Q_DISABLE_COPY(QDialog)
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
Q_PRIVATE_SLOT(d_func(), void _q_doneAction())
#endif
};
diff --git a/src/gui/dialogs/qdialog_p.h b/src/gui/dialogs/qdialog_p.h
index 81a7b19..e4f551a 100644
--- a/src/gui/dialogs/qdialog_p.h
+++ b/src/gui/dialogs/qdialog_p.h
@@ -93,7 +93,7 @@ public:
void hideDefault();
void resetModalitySetByOpen();
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
void _q_doneAction();
#endif
diff --git a/src/gui/dialogs/qerrormessage.cpp b/src/gui/dialogs/qerrormessage.cpp
index f79c6b2..d24d348 100644
--- a/src/gui/dialogs/qerrormessage.cpp
+++ b/src/gui/dialogs/qerrormessage.cpp
@@ -61,7 +61,7 @@
#include <stdio.h>
#include <stdlib.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
@@ -100,7 +100,7 @@ public:
QSize QErrorMessageTextView::minimumSizeHint() const
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (qt_wince_is_high_dpi())
return QSize(200, 200);
@@ -115,7 +115,7 @@ QSize QErrorMessageTextView::minimumSizeHint() const
QSize QErrorMessageTextView::sizeHint() const
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (qt_wince_is_high_dpi())
return QSize(400, 200);
@@ -240,7 +240,7 @@ QErrorMessage::QErrorMessage(QWidget * parent)
d->again->setChecked(true);
grid->addWidget(d->again, 1, 1, Qt::AlignTop);
d->ok = new QPushButton(this);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
d->ok->setFixedSize(0,0);
#endif
connect(d->ok, SIGNAL(clicked()), this, SLOT(accept()));
@@ -300,7 +300,7 @@ QErrorMessage * QErrorMessage::qtHandler()
if (!qtMessageHandler) {
qtMessageHandler = new QErrorMessage(0);
qAddPostRoutine(deleteStaticcQErrorMessage); // clean up
- qtMessageHandler->setWindowTitle(qApp->applicationName());
+ qtMessageHandler->setWindowTitle(QApplication::applicationName());
qInstallMsgHandler(jump);
}
return qtMessageHandler;
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 9768162..e3a4ca4 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -58,7 +58,7 @@
#include <qdebug.h>
#include <qapplication.h>
#include <qstylepainter.h>
-#if !defined(Q_OS_WINCE) && !defined(Q_WS_S60)
+#if !defined(Q_WS_WINCE) && !defined(Q_WS_S60)
#include "ui_qfiledialog.h"
#else
#define Q_EMBEDDED_SMALLSCREEN
@@ -874,8 +874,8 @@ QStringList QFileDialogPrivate::addDefaultSuffixToFiles(const QStringList filesT
// This check is needed since we might be at the root directory
// and on Windows it already ends with slash.
QString path = rootPath();
- if (!path.endsWith(QLatin1String("/")))
- path += QLatin1String("/");
+ if (!path.endsWith(QLatin1Char('/')))
+ path += QLatin1Char('/');
path += name;
files.append(path);
}
@@ -1898,7 +1898,7 @@ QString QFileDialog::getExistingDirectory(QWidget *parent,
#if defined(Q_WS_WIN)
if (qt_use_native_dialogs && !(args.options & DontUseNativeDialog) && (options & ShowDirsOnly)
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
&& qt_priv_ptr_valid
#endif
) {
@@ -2687,7 +2687,7 @@ void QFileDialogPrivate::_q_deleteCurrent()
void QFileDialogPrivate::_q_autoCompleteFileName(const QString &text)
{
- if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1String("\\"))) {
+ if (text.startsWith(QLatin1String("//")) || text.startsWith(QLatin1Char('\\'))) {
qFileDialogUi->listView->selectionModel()->clearSelection();
return;
}
@@ -2729,7 +2729,7 @@ void QFileDialogPrivate::_q_updateOkButton()
QStringList files = q->selectedFiles();
QString lineEditText = lineEdit()->text();
- if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1String("\\"))) {
+ if (lineEditText.startsWith(QLatin1String("//")) || lineEditText.startsWith(QLatin1Char('\\'))) {
button->setEnabled(true);
if (acceptMode == QFileDialog::AcceptSave)
button->setText(isOpenDirectory ? QFileDialog::tr("&Open") : acceptLabel);
@@ -3238,7 +3238,7 @@ QStringList QFSCompleter::splitPath(const QString &path) const
doubleSlash.clear();
#endif
- QRegExp re(QLatin1String("[") + QRegExp::escape(sep) + QLatin1String("]"));
+ QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
#if defined(Q_OS_SYMBIAN)
QStringList parts = pathCopy.split(re, QString::SkipEmptyParts);
diff --git a/src/gui/dialogs/qfiledialog_mac.mm b/src/gui/dialogs/qfiledialog_mac.mm
index 90af9fc..39a231b 100644
--- a/src/gui/dialogs/qfiledialog_mac.mm
+++ b/src/gui/dialogs/qfiledialog_mac.mm
@@ -911,8 +911,9 @@ void QFileDialogPrivate::createNavServicesDialog()
navOptions.windowTitle = QCFString::toCFStringRef(q->windowTitle());
- static const int w = 450, h = 350;
- navOptions.location.h = navOptions.location.v = -1;
+ navOptions.location.h = -1;
+ navOptions.location.v = -1;
+
QWidget *parent = q->parentWidget();
if (parent && parent->isVisible()) {
WindowClass wclass;
@@ -920,20 +921,6 @@ void QFileDialogPrivate::createNavServicesDialog()
parent = parent->window();
QString s = parent->windowTitle();
navOptions.clientName = QCFString::toCFStringRef(s);
- navOptions.location.h = (parent->x() + (parent->width() / 2)) - (w / 2);
- navOptions.location.v = (parent->y() + (parent->height() / 2)) - (h / 2);
-
- QRect r = QApplication::desktop()->screenGeometry(
- QApplication::desktop()->screenNumber(parent));
- const int border = 10;
- if (navOptions.location.h + w > r.right())
- navOptions.location.h -= (navOptions.location.h + w) - r.right() + border;
- if (navOptions.location.v + h > r.bottom())
- navOptions.location.v -= (navOptions.location.v + h) - r.bottom() + border;
- if (navOptions.location.h < r.left())
- navOptions.location.h = r.left() + border;
- if (navOptions.location.v < r.top())
- navOptions.location.v = r.top() + border;
}
filterInfo.currentSelection = 0;
diff --git a/src/gui/dialogs/qfiledialog_p.h b/src/gui/dialogs/qfiledialog_p.h
index 3195583..2925c8c 100644
--- a/src/gui/dialogs/qfiledialog_p.h
+++ b/src/gui/dialogs/qfiledialog_p.h
@@ -233,7 +233,10 @@ public:
// data
QStringList watching;
QFileSystemModel *model;
- QFSCompleter *completer;
+
+#ifndef QT_NO_COMPLETER
+ QFSCompletor *completer;
+#endif //QT_NO_COMPLETER
QFileDialog::FileMode fileMode;
QFileDialog::AcceptMode acceptMode;
diff --git a/src/gui/dialogs/qfiledialog_win.cpp b/src/gui/dialogs/qfiledialog_win.cpp
index 8431488..4e818be 100644
--- a/src/gui/dialogs/qfiledialog_win.cpp
+++ b/src/gui/dialogs/qfiledialog_win.cpp
@@ -60,7 +60,7 @@
#include <shlobj.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include <commdlg.h>
# ifndef BFFM_SETSELECTION
# define BFFM_SETSELECTION (WM_USER + 102)
@@ -112,7 +112,7 @@ static void qt_win_resolve_libs()
triedResolve = true;
if (!(QSysInfo::WindowsVersion & QSysInfo::WV_DOS_based)) {
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QLibrary lib(QLatin1String("shell32"));
ptrSHBrowseForFolder = (PtrSHBrowseForFolder) lib.resolve("SHBrowseForFolderW");
ptrSHGetPathFromIDList = (PtrSHGetPathFromIDList) lib.resolve("SHGetPathFromIDListW");
@@ -186,7 +186,7 @@ static QString qt_win_selected_filter(const QString &filter, DWORD idx)
return qt_win_make_filters_list(filter).at((int)idx - 1);
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// Static vars for OFNA funcs:
static QByteArray aInitDir;
static QByteArray aInitSel;
@@ -206,7 +206,7 @@ static OPENFILENAMEA *qt_win_make_OFNA(QWidget *parent,
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
aTitle = title.toLocal8Bit();
aInitDir = QDir::toNativeSeparators(initialDirectory).toLocal8Bit();
@@ -214,10 +214,10 @@ static OPENFILENAMEA *qt_win_make_OFNA(QWidget *parent,
aInitSel = "";
} else {
aInitSel = QDir::toNativeSeparators(initialSelection).toLocal8Bit();
- aInitSel.replace("<", "");
- aInitSel.replace(">", "");
- aInitSel.replace("\"", "");
- aInitSel.replace("|", "");
+ aInitSel.replace('<', "");
+ aInitSel.replace('>', "");
+ aInitSel.replace('\"', "");
+ aInitSel.replace('|', "");
}
int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;
aInitSel.resize(maxLen + 1); // make room for return value
@@ -279,17 +279,17 @@ static OPENFILENAME* qt_win_make_OFN(QWidget *parent,
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
tInitDir = QDir::toNativeSeparators(initialDirectory);
tFilters = filters;
tTitle = title;
QString initSel = QDir::toNativeSeparators(initialSelection);
if (!initSel.isEmpty()) {
- initSel.replace(QLatin1String("<"), QLatin1String(""));
- initSel.replace(QLatin1String(">"), QLatin1String(""));
- initSel.replace(QLatin1String("\""), QLatin1String(""));
- initSel.replace(QLatin1String("|"), QLatin1String(""));
+ initSel.remove(QLatin1Char('<'));
+ initSel.remove(QLatin1Char('>'));
+ initSel.remove(QLatin1Char('\"'));
+ initSel.remove(QLatin1Char('|'));
}
int maxLen = mode == QFileDialog::ExistingFiles ? maxMultiLen : maxNameLen;
@@ -505,7 +505,7 @@ QString qt_win_get_save_file_name(const QFileDialogArgs &args,
}
qt_win_clean_up_OFNA(&ofn);
});
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
int semIndex = result.indexOf(QLatin1Char(';'));
if (semIndex >= 0)
result = result.left(semIndex);
@@ -692,7 +692,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
if (parent)
parent->createWinId();
@@ -700,7 +700,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
modal_widget.setParent(parent, Qt::Window);
QApplicationPrivate::enterModal(&modal_widget);
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QT_WA({
qt_win_resolve_libs();
QString initDir = QDir::toNativeSeparators(args.directory);
@@ -811,7 +811,7 @@ QString qt_win_get_existing_directory(const QFileDialogArgs &args)
QDir::setCurrent(currentDir);
if (!result.isEmpty())
- result.replace(QLatin1String("\\"), QLatin1String("/"));
+ result.replace(QLatin1Char('\\'), QLatin1Char('/'));
return result;
}
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 44adc75..d9ae5bf 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -337,7 +337,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
{
Q_Q(const QFileSystemModel);
Q_UNUSED(q);
- if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1String(":")))
+ if (path.isEmpty() || path == myComputer() || path.startsWith(QLatin1Char(':')))
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
// Construct the nodes up to the new root path if they need to be built
@@ -1419,7 +1419,7 @@ void QFileSystemModel::setIconProvider(QFileIconProvider *provider)
{
Q_D(QFileSystemModel);
d->fileInfoGatherer.setIconProvider(provider);
- qApp->processEvents();
+ QApplication::processEvents();
d->root.updateIcon(provider, QString());
}
diff --git a/src/gui/dialogs/qfontdialog.cpp b/src/gui/dialogs/qfontdialog.cpp
index 9ea06ac..3384132 100644
--- a/src/gui/dialogs/qfontdialog.cpp
+++ b/src/gui/dialogs/qfontdialog.cpp
@@ -311,11 +311,11 @@ void QFontDialogPrivate::init()
buttonBox->addButton(QDialogButtonBox::Cancel);
QObject::connect(buttonBox, SIGNAL(rejected()), q, SLOT(reject()));
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
q->resize(180, 120);
#else
q->resize(500, 360);
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
sizeEdit->installEventFilter(q);
familyList->installEventFilter(q);
diff --git a/src/gui/dialogs/qinputdialog.cpp b/src/gui/dialogs/qinputdialog.cpp
index 8754324..289459c 100644
--- a/src/gui/dialogs/qinputdialog.cpp
+++ b/src/gui/dialogs/qinputdialog.cpp
@@ -307,8 +307,7 @@ void QInputDialogPrivate::ensureEnabledConnection(QAbstractSpinBox *spinBox)
{
if (spinBox) {
QAbstractButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
- QObject::disconnect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)));
- QObject::connect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)));
+ QObject::connect(spinBox, SIGNAL(textChanged(bool)), okButton, SLOT(setEnabled(bool)), Qt::UniqueConnection);
}
}
@@ -1250,9 +1249,9 @@ double QInputDialog::getDouble(QWidget *parent, const QString &title, const QStr
QInputDialog dialog(parent, flags);
dialog.setWindowTitle(title);
dialog.setLabelText(label);
+ dialog.setDoubleDecimals(decimals);
dialog.setDoubleRange(min, max);
dialog.setDoubleValue(value);
- dialog.setDoubleDecimals(decimals);
int ret = dialog.exec();
if (ok)
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index 00baf01..68044c8 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -63,7 +63,7 @@
#include <QtGui/qfontmetrics.h>
#include <QtGui/qclipboard.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_smartphone();//defined in qguifunctions_wince.cpp
extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
@@ -152,7 +152,7 @@ public:
int layoutMinimumWidth();
void retranslateStrings();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void hideSpecial();
#endif
@@ -258,10 +258,8 @@ void QMessageBoxPrivate::init(const QString &title, const QString &text)
int QMessageBoxPrivate::layoutMinimumWidth()
{
- Q_Q(QMessageBox);
-
- q->layout()->activate();
- return q->layout()->totalMinimumSize().width();
+ layout->activate();
+ return layout->totalMinimumSize().width();
}
void QMessageBoxPrivate::updateSize()
@@ -272,10 +270,7 @@ void QMessageBoxPrivate::updateSize()
return;
QSize screenSize = QApplication::desktop()->availableGeometry(QCursor::pos()).size();
-#ifdef Q_WS_QWS
- // the width of the screen, less the window border.
- int hardLimit = screenSize.width() - (q->frameGeometry().width() - q->geometry().width());
-#elif defined(Q_OS_WINCE) || defined(Q_OS_SYMBIAN)
+#if defined(Q_WS_QWS) || defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
// the width of the screen, less the window border.
int hardLimit = screenSize.width() - (q->frameGeometry().width() - q->geometry().width());
#else
@@ -290,11 +285,11 @@ void QMessageBoxPrivate::updateSize()
int softLimit = qMin(hardLimit, 500);
#else
// note: ideally on windows, hard and soft limits but it breaks compat
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
int softLimit = qMin(screenSize.width()/2, 500);
#else
int softLimit = qMin(screenSize.width() * 3 / 4, 500);
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
#endif
if (informativeLabel)
@@ -337,21 +332,21 @@ void QMessageBoxPrivate::updateSize()
label->setSizePolicy(policy);
}
- QFontMetrics fm(qApp->font("QWorkspaceTitleBar"));
+ QFontMetrics fm(QApplication::font("QWorkspaceTitleBar"));
int windowTitleWidth = qMin(fm.width(q->windowTitle()) + 50, hardLimit);
if (windowTitleWidth > width)
width = windowTitleWidth;
- q->layout()->activate();
- int height = (q->layout()->hasHeightForWidth())
- ? q->layout()->totalHeightForWidth(width)
- : q->layout()->totalMinimumSize().height();
+ layout->activate();
+ int height = (layout->hasHeightForWidth())
+ ? layout->totalHeightForWidth(width)
+ : layout->totalMinimumSize().height();
q->setFixedSize(width, height);
QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
/*!
\internal
Hides special buttons which are rather shown in the title bar
@@ -366,7 +361,7 @@ void QMessageBoxPrivate::hideSpecial()
QPushButton *pb = list.at(i);
QString text = pb->text();
text.remove(QChar::fromLatin1('&'));
- if (text == qApp->translate("QMessageBox", "OK" ))
+ if (text == QApplication::translate("QMessageBox", "OK" ))
pb->setFixedSize(0,0);
}
}
@@ -1208,13 +1203,13 @@ bool QMessageBox::event(QEvent *e)
case QEvent::LanguageChange:
d_func()->retranslateStrings();
break;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
case QEvent::OkRequest:
case QEvent::HelpRequest: {
QString bName =
(e->type() == QEvent::OkRequest)
- ? qApp->translate("QMessageBox", "OK")
- : qApp->translate("QMessageBox", "Help");
+ ? QApplication::translate("QMessageBox", "OK")
+ : QApplication::translate("QMessageBox", "Help");
QList<QPushButton*> list = qFindChildren<QPushButton*>(this);
for (int i=0; i<list.size(); ++i) {
QPushButton *pb = list.at(i);
@@ -1313,7 +1308,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
if (e == QKeySequence::Copy) {
QString separator = QString::fromLatin1("---------------------------\n");
QString textToCopy = separator;
- separator.prepend(QLatin1String("\n"));
+ separator.prepend(QLatin1Char('\n'));
textToCopy += windowTitle() + separator; // title
textToCopy += d->label->text() + separator; // text
@@ -1327,7 +1322,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
}
textToCopy += buttonTexts + separator;
- qApp->clipboard()->setText(textToCopy);
+ QApplication::clipboard()->setText(textToCopy);
return;
}
#endif //QT_NO_SHORTCUT QT_NO_CLIPBOARD Q_OS_WIN
@@ -1351,7 +1346,7 @@ void QMessageBox::keyPressEvent(QKeyEvent *e)
QDialog::keyPressEvent(e);
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
/*!
\reimp
*/
@@ -1420,7 +1415,7 @@ void QMessageBox::showEvent(QShowEvent *e)
Q_D(QMessageBox);
if (d->autoAddOkButton) {
addButton(Ok);
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
d->hideSpecial();
#endif
}
@@ -1687,10 +1682,13 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
}
#endif
- QString translatedTextAboutQt;
- translatedTextAboutQt = QMessageBox::tr(
+ QString translatedTextAboutQtCaption;
+ translatedTextAboutQtCaption = QMessageBox::tr(
"<h3>About Qt</h3>"
"<p>This program uses Qt version %1.</p>"
+ ).arg(QLatin1String(QT_VERSION_STR));
+ QString translatedTextAboutQtText;
+ translatedTextAboutQtText = QMessageBox::tr(
"<p>Qt is a C++ toolkit for cross-platform application "
"development.</p>"
"<p>Qt provides single-source portability across MS&nbsp;Windows, "
@@ -1699,7 +1697,7 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"and Qt for Windows CE.</p>"
"<p>Qt is available under three different licensing options designed "
"to accommodate the needs of our various users.</p>"
- "Qt licensed under our commercial license agreement is appropriate "
+ "<p>Qt licensed under our commercial license agreement is appropriate "
"for development of proprietary/commercial software where you do not "
"want to share any source code with third parties or otherwise cannot "
"comply with the terms of the GNU LGPL version 2.1 or GNU GPL version "
@@ -1718,17 +1716,17 @@ void QMessageBox::aboutQt(QWidget *parent, const QString &title)
"<p>Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).</p>"
"<p>Qt is a Nokia product. See <a href=\"http://www.qtsoftware.com/qt/\">www.qtsoftware.com/qt</a> "
"for more information.</p>"
- ).arg(QLatin1String(QT_VERSION_STR));
-
+ );
QMessageBox *msgBox = new QMessageBox(parent);
msgBox->setAttribute(Qt::WA_DeleteOnClose);
msgBox->setWindowTitle(title.isEmpty() ? tr("About Qt") : title);
- msgBox->setInformativeText(translatedTextAboutQt);
+ msgBox->setText(translatedTextAboutQtCaption);
+ msgBox->setInformativeText(translatedTextAboutQtText);
QPixmap pm(QLatin1String(":/trolltech/qmessagebox/images/qtlogo-64.png"));
if (!pm.isNull())
msgBox->setIconPixmap(pm);
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
msgBox->setDefaultButton(msgBox->addButton(QMessageBox::Ok));
#endif
diff --git a/src/gui/dialogs/qmessagebox.h b/src/gui/dialogs/qmessagebox.h
index e1667d6..c6fb3bc 100644
--- a/src/gui/dialogs/qmessagebox.h
+++ b/src/gui/dialogs/qmessagebox.h
@@ -145,7 +145,7 @@ public:
QPushButton *addButton(StandardButton button);
void removeButton(QAbstractButton *button);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void setVisible(bool visible);
#endif
@@ -191,6 +191,8 @@ public:
static StandardButton information(QWidget *parent, const QString &title,
const QString &text, StandardButtons buttons = Ok,
StandardButton defaultButton = NoButton);
+ // ### Qt 5: Replace Ok with Yes|No in question() function.
+ // Also consider if Ok == Yes and Cancel == No.
static StandardButton question(QWidget *parent, const QString &title,
const QString &text, StandardButtons buttons = Ok,
StandardButton defaultButton = NoButton);
diff --git a/src/gui/dialogs/qpagesetupdialog_win.cpp b/src/gui/dialogs/qpagesetupdialog_win.cpp
index bdce8ab..ffad77c 100644
--- a/src/gui/dialogs/qpagesetupdialog_win.cpp
+++ b/src/gui/dialogs/qpagesetupdialog_win.cpp
@@ -98,7 +98,7 @@ int QPageSetupDialog::exec()
psd.hDevNames = tempDevNames;
QWidget *parent = parentWidget();
- parent = parent ? parent->window() : qApp->activeWindow();
+ parent = parent ? parent->window() : QApplication::activeWindow();
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
psd.hwndOwner = parent ? parent->winId() : 0;
diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp
index 17d0047..2f7f7c1 100644
--- a/src/gui/dialogs/qprintdialog_unix.cpp
+++ b/src/gui/dialogs/qprintdialog_unix.cpp
@@ -669,7 +669,7 @@ QUnixPrintWidgetPrivate::QUnixPrintWidgetPrivate(QUnixPrintWidget *p)
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
- printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
+ printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
widget.printers->addItem(printerName);
if (cupsPrinters[i].is_default)
@@ -813,7 +813,7 @@ void QUnixPrintWidgetPrivate::_q_printerChanged(int index)
optionsPane->selectPrinter(0);
#endif
if (lprPrinters.count() > 0) {
- QString type = lprPrinters.at(index).name + QLatin1String("@") + lprPrinters.at(index).host;
+ QString type = lprPrinters.at(index).name + QLatin1Char('@') + lprPrinters.at(index).host;
if (!lprPrinters.at(index).comment.isEmpty())
type += QLatin1String(", ") + lprPrinters.at(index).comment;
widget.type->setText(type);
@@ -1194,9 +1194,9 @@ QVariant QPPDOptionsModel::headerData(int section, Qt::Orientation, int role) co
switch(section){
case 0:
- return QVariant(QApplication::translate("QPPDOptionsModel","Name"));
+ return QVariant(QApplication::translate("QPPDOptionsModel", "Name"));
case 1:
- return QVariant(QApplication::translate("QPPDOptionsModel","Value"));
+ return QVariant(QApplication::translate("QPPDOptionsModel", "Value"));
default:
return QVariant();
}
diff --git a/src/gui/dialogs/qprintdialog_win.cpp b/src/gui/dialogs/qprintdialog_win.cpp
index 936d1ed..2561227 100644
--- a/src/gui/dialogs/qprintdialog_win.cpp
+++ b/src/gui/dialogs/qprintdialog_win.cpp
@@ -225,7 +225,7 @@ int QPrintDialogPrivate::openWindowsPrintDialogModally()
if (parent)
parent = parent->window();
else
- parent = qApp->activeWindow();
+ parent = QApplication::activeWindow();
QWidget modal_widget;
modal_widget.setAttribute(Qt::WA_NoChildEventsForParent, true);
diff --git a/src/gui/dialogs/qprintpreviewdialog.cpp b/src/gui/dialogs/qprintpreviewdialog.cpp
index 61949d8..835f372 100644
--- a/src/gui/dialogs/qprintpreviewdialog.cpp
+++ b/src/gui/dialogs/qprintpreviewdialog.cpp
@@ -55,6 +55,9 @@
#include <QtGui/qtoolbutton.h>
#include <QtGui/qvalidator.h>
#include <QtGui/qfiledialog.h>
+#include <QtGui/qmainwindow.h>
+#include <QtGui/qtoolbar.h>
+#include <QtGui/qformlayout.h>
#include <QtCore/QCoreApplication>
#include <math.h>
@@ -64,6 +67,13 @@
QT_BEGIN_NAMESPACE
namespace {
+class QPrintPreviewMainWindow : public QMainWindow
+{
+public:
+ QPrintPreviewMainWindow(QWidget *parent) : QMainWindow(parent) {}
+ QMenu *createPopupMenu() { return 0; }
+};
+
class ZoomFactorValidator : public QDoubleValidator
{
public:
@@ -197,7 +207,6 @@ public:
QActionGroup *printerGroup;
QAction *printAction;
QAction *pageSetupAction;
- QAction *closeAction;
QPointer<QObject> receiverToDisconnectOnClose;
QByteArray memberToDisconnectOnClose;
@@ -219,27 +228,12 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QObject::connect(preview, SIGNAL(previewChanged()), q, SLOT(_q_previewChanged()));
setupActions();
- // Navigation
- QToolButton* nextPageButton = new QToolButton;
- nextPageButton->setDefaultAction(nextPageAction);
- QToolButton* prevPageButton = new QToolButton;
- prevPageButton->setDefaultAction(prevPageAction);
- QToolButton* firstPageButton = new QToolButton;
- firstPageButton->setDefaultAction(firstPageAction);
- QToolButton* lastPageButton = new QToolButton;
- lastPageButton->setDefaultAction(lastPageAction);
-
pageNumEdit = new LineEdit;
pageNumEdit->setAlignment(Qt::AlignRight);
- pageNumEdit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::MinimumExpanding));
+ pageNumEdit->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
pageNumLabel = new QLabel;
QObject::connect(pageNumEdit, SIGNAL(editingFinished()), q, SLOT(_q_pageNumEdited()));
- QToolButton* fitWidthButton = new QToolButton;
- fitWidthButton->setDefaultAction(fitWidthAction);
- QToolButton* fitPageButton = new QToolButton;
- fitPageButton->setDefaultAction(fitPageAction);
-
zoomFactor = new QComboBox;
zoomFactor->setEditable(true);
zoomFactor->setMinimumContentsLength(7);
@@ -255,77 +249,66 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
QObject::connect(zoomFactor, SIGNAL(currentIndexChanged(int)),
q, SLOT(_q_zoomFactorChanged()));
- QToolButton* zoomInButton = new QToolButton;
- zoomInButton->setDefaultAction(zoomInAction);
+ QPrintPreviewMainWindow *mw = new QPrintPreviewMainWindow(q);
+ QToolBar *toolbar = new QToolBar(mw);
+ toolbar->addAction(fitWidthAction);
+ toolbar->addAction(fitPageAction);
+ toolbar->addSeparator();
+ toolbar->addWidget(zoomFactor);
+ toolbar->addAction(zoomOutAction);
+ toolbar->addAction(zoomInAction);
+ toolbar->addSeparator();
+ toolbar->addAction(portraitAction);
+ toolbar->addAction(landscapeAction);
+ toolbar->addSeparator();
+ toolbar->addAction(firstPageAction);
+ toolbar->addAction(prevPageAction);
+
+ // this is to ensure the label text and the editor text are
+ // aligned in all styles - the extra QVBoxLayout is a workaround
+ // for bug in QFormLayout
+ QWidget *pageEdit = new QWidget(toolbar);
+ QVBoxLayout *vboxLayout = new QVBoxLayout;
+ vboxLayout->setContentsMargins(0, 0, 0, 0);
+ QFormLayout *formLayout = new QFormLayout;
+ formLayout->setWidget(0, QFormLayout::LabelRole, pageNumEdit);
+ formLayout->setWidget(0, QFormLayout::FieldRole, pageNumLabel);
+ vboxLayout->addLayout(formLayout);
+ vboxLayout->setAlignment(Qt::AlignVCenter);
+ pageEdit->setLayout(vboxLayout);
+ toolbar->addWidget(pageEdit);
+
+ toolbar->addAction(nextPageAction);
+ toolbar->addAction(lastPageAction);
+ toolbar->addSeparator();
+ toolbar->addAction(singleModeAction);
+ toolbar->addAction(facingModeAction);
+ toolbar->addAction(overviewModeAction);
+ toolbar->addSeparator();
+ toolbar->addAction(pageSetupAction);
+ toolbar->addAction(printAction);
+
+ // Cannot use the actions' triggered signal here, since it doesn't autorepeat
+ QToolButton *zoomInButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomInAction));
+ QToolButton *zoomOutButton = static_cast<QToolButton *>(toolbar->widgetForAction(zoomOutAction));
zoomInButton->setAutoRepeat(true);
zoomInButton->setAutoRepeatInterval(200);
zoomInButton->setAutoRepeatDelay(200);
-
- QToolButton* zoomOutButton = new QToolButton;
- zoomOutButton->setDefaultAction(zoomOutAction);
zoomOutButton->setAutoRepeat(true);
zoomOutButton->setAutoRepeatInterval(200);
zoomOutButton->setAutoRepeatDelay(200);
-
- //Cannot use the actions' triggered signal here, since it doesnt autorepeat
QObject::connect(zoomInButton, SIGNAL(clicked()), q, SLOT(_q_zoomIn()));
QObject::connect(zoomOutButton, SIGNAL(clicked()), q, SLOT(_q_zoomOut()));
- QToolButton* portraitButton = new QToolButton;
- portraitButton->setDefaultAction(portraitAction);
- QToolButton* landscapeButton = new QToolButton;
- landscapeButton->setDefaultAction(landscapeAction);
-
- QToolButton* singleModeButton = new QToolButton;
- singleModeButton->setDefaultAction(singleModeAction);
- QToolButton* facingModeButton = new QToolButton;
- facingModeButton->setDefaultAction(facingModeAction);
- QToolButton* overviewModeButton = new QToolButton;
- overviewModeButton->setDefaultAction(overviewModeAction);
-
- QToolButton *printButton = new QToolButton;
- printButton->setDefaultAction(printAction);
- QToolButton *pageSetupButton = new QToolButton;
- pageSetupButton->setDefaultAction(pageSetupAction);
- QToolButton *closeButton = new QToolButton;
- closeButton->setDefaultAction(closeAction);
-
- QHBoxLayout* modeLayout = new QHBoxLayout;
- modeLayout->setSpacing(0);
- modeLayout->addWidget(singleModeButton);
- modeLayout->addWidget(facingModeButton);
- modeLayout->addWidget(overviewModeButton);
-
- QHBoxLayout *barLayout = new QHBoxLayout;
- barLayout->addWidget(fitWidthButton);
- barLayout->addWidget(fitPageButton);
- barLayout->addWidget(zoomFactor);
- barLayout->addWidget(zoomOutButton);
- barLayout->addWidget(zoomInButton);
- barLayout->addWidget(portraitButton);
- barLayout->addWidget(landscapeButton);
- barLayout->addStretch();
- barLayout->addWidget(firstPageButton);
- barLayout->addWidget(prevPageButton);
- barLayout->addWidget(pageNumEdit);
- barLayout->addWidget(pageNumLabel);
- barLayout->addWidget(nextPageButton);
- barLayout->addWidget(lastPageButton);
- barLayout->addStretch();
- barLayout->addLayout(modeLayout);
- barLayout->addStretch();
- barLayout->addWidget(pageSetupButton);
- barLayout->addWidget(printButton);
- barLayout->addWidget(closeButton);
-
- QWidget* buttonBar = new QWidget;
- buttonBar->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Maximum));
- barLayout->setMargin(0);
- buttonBar->setLayout(barLayout);
+ mw->addToolBar(toolbar);
+ mw->setCentralWidget(preview);
+ // QMainWindows are always created as top levels, force it to be a
+ // plain widget
+ mw->setParent(q, Qt::Widget);
QVBoxLayout *topLayout = new QVBoxLayout;
- topLayout->addWidget(buttonBar);
- topLayout->addWidget(preview);
+ topLayout->addWidget(mw);
+ topLayout->setMargin(0);
q->setLayout(topLayout);
QString caption = QCoreApplication::translate("QPrintPreviewDialog", "Print Preview");
@@ -338,7 +321,8 @@ void QPrintPreviewDialogPrivate::init(QPrinter *_printer)
|| printer->outputFormat() != QPrinter::NativeFormat
#endif
)
- pageSetupButton->setEnabled(false);
+ pageSetupAction->setEnabled(false);
+ preview->setFocus();
}
static inline void qt_setupActionIcon(QAction *action, const QLatin1String &name)
@@ -418,12 +402,10 @@ void QPrintPreviewDialogPrivate::setupActions()
printerGroup = new QActionGroup(q);
printAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Print"));
pageSetupAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Page setup"));
- closeAction = printerGroup->addAction(QCoreApplication::translate("QPrintPreviewDialog", "Close"));
qt_setupActionIcon(printAction, QLatin1String("print"));
qt_setupActionIcon(pageSetupAction, QLatin1String("page-setup"));
QObject::connect(printAction, SIGNAL(triggered(bool)), q, SLOT(_q_print()));
QObject::connect(pageSetupAction, SIGNAL(triggered(bool)), q, SLOT(_q_pageSetup()));
- QObject::connect(closeAction, SIGNAL(triggered(bool)), q, SLOT(reject()));
// Initial state:
fitPageAction->setChecked(true);
@@ -478,7 +460,7 @@ void QPrintPreviewDialogPrivate::updatePageNumLabel()
int numPages = preview->numPages();
int maxChars = QString::number(numPages).length();
- pageNumLabel->setText(QString(QLatin1String("/ %1")).arg(numPages));
+ pageNumLabel->setText(QString::fromLatin1("/ %1").arg(numPages));
int cyphersWidth = q->fontMetrics().width(QString().fill(QLatin1Char('8'), maxChars));
int maxWidth = pageNumEdit->minimumSizeHint().width() + cyphersWidth;
pageNumEdit->setMinimumWidth(maxWidth);
@@ -576,7 +558,7 @@ void QPrintPreviewDialogPrivate::_q_print()
suffix = QLatin1String(".ps");
}
QString fileName = QFileDialog::getSaveFileName(q, title, printer->outputFileName(),
- QLatin1String("*") + suffix);
+ QLatin1Char('*') + suffix);
if (!fileName.isEmpty()) {
if (QFileInfo(fileName).suffix().isEmpty())
fileName.append(suffix);
@@ -629,7 +611,7 @@ void QPrintPreviewDialogPrivate::_q_zoomFactorChanged()
factor = qMax(qreal(1.0), qMin(qreal(1000.0), factor));
if (ok) {
preview->setZoomFactor(factor/100.0);
- zoomFactor->setEditText(QString(QLatin1String("%1%")).arg(factor));
+ zoomFactor->setEditText(QString::fromLatin1("%1%").arg(factor));
setFitting(false);
}
}
diff --git a/src/gui/dialogs/qprogressdialog.cpp b/src/gui/dialogs/qprogressdialog.cpp
index 66a1285..b68a0a72 100644
--- a/src/gui/dialogs/qprogressdialog.cpp
+++ b/src/gui/dialogs/qprogressdialog.cpp
@@ -643,7 +643,7 @@ void QProgressDialog::setValue(int progress)
if (d->shown_once) {
if (isModal())
- qApp->processEvents();
+ QApplication::processEvents();
} else {
if (progress == 0) {
d->starttime.start();
diff --git a/src/gui/dialogs/qwizard.cpp b/src/gui/dialogs/qwizard.cpp
index 298f23f..7fc8a63 100644
--- a/src/gui/dialogs/qwizard.cpp
+++ b/src/gui/dialogs/qwizard.cpp
@@ -69,7 +69,7 @@
#include "private/qdialog_p.h"
#include <qdebug.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
#endif
@@ -377,7 +377,7 @@ void QWizardHeader::setup(const QWizardLayoutInfo &info, const QString &title,
/*
There is no widthForHeight() function, so we simulate it with a loop.
*/
- int candidateSubTitleWidth = qMin(512, 2 * qApp->desktop()->width() / 3);
+ int candidateSubTitleWidth = qMin(512, 2 * QApplication::desktop()->width() / 3);
int delta = candidateSubTitleWidth >> 1;
while (delta > 0) {
if (subTitleLabel->heightForWidth(candidateSubTitleWidth - delta)
@@ -1241,8 +1241,10 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
#endif
QSize minimumSize = mainLayout->totalMinimumSize() + QSize(0, extraHeight);
QSize maximumSize;
+ bool skipMaxSize = false;
#if defined(Q_WS_WIN)
- if (QSysInfo::WindowsVersion > QSysInfo::WV_Me) // ### See Tasks 164078 and 161660
+ if (QSysInfo::WindowsVersion <= QSysInfo::WV_Me) // ### See Tasks 164078 and 161660
+ skipMaxSize = true;
#endif
maximumSize = mainLayout->totalMaximumSize();
if (info.header && headerWidget->maximumWidth() != QWIDGETSIZE_MAX) {
@@ -1263,11 +1265,13 @@ void QWizardPrivate::updateMinMaxSizes(const QWizardLayoutInfo &info)
}
if (q->maximumWidth() == maximumWidth) {
maximumWidth = maximumSize.width();
- q->setMaximumWidth(maximumWidth);
+ if (!skipMaxSize)
+ q->setMaximumWidth(maximumWidth);
}
if (q->maximumHeight() == maximumHeight) {
maximumHeight = maximumSize.height();
- q->setMaximumHeight(maximumHeight);
+ if (!skipMaxSize)
+ q->setMaximumHeight(maximumHeight);
}
}
@@ -2120,7 +2124,7 @@ QWizard::QWizard(QWidget *parent, Qt::WindowFlags flags)
{
Q_D(QWizard);
d->init();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_mobile())
setWindowFlags(windowFlags() & ~Qt::WindowOkButtonHint);
#endif
diff --git a/src/gui/dialogs/qwizard_win.cpp b/src/gui/dialogs/qwizard_win.cpp
index 8aad4af..e0aaa19 100644
--- a/src/gui/dialogs/qwizard_win.cpp
+++ b/src/gui/dialogs/qwizard_win.cpp
@@ -279,7 +279,7 @@ QVistaHelper::VistaState QVistaHelper::vistaState()
QColor QVistaHelper::basicWindowFrameColor()
{
DWORD rgb;
- HANDLE hTheme = pOpenThemeData(qApp->desktop()->winId(), L"WINDOW");
+ HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW");
pGetThemeColor(
hTheme, WIZ_WP_CAPTION, WIZ_CS_ACTIVE,
wizard->isActiveWindow() ? WIZ_TMT_FILLCOLORHINT : WIZ_TMT_BORDERCOLORHINT,
@@ -611,7 +611,7 @@ bool QVistaHelper::drawTitleText(QPainter *painter, const QString &text, const Q
{
bool value = false;
if (vistaState() == VistaAero) {
- HANDLE hTheme = pOpenThemeData(qApp->desktop()->winId(), L"WINDOW");
+ HANDLE hTheme = pOpenThemeData(QApplication::desktop()->winId(), L"WINDOW");
if (!hTheme) return false;
// Set up a memory DC and bitmap that we'll draw into
HDC dcMem;
diff --git a/src/gui/embedded/embedded.pri b/src/gui/embedded/embedded.pri
index 95c4132..4a9aa3f 100644
--- a/src/gui/embedded/embedded.pri
+++ b/src/gui/embedded/embedded.pri
@@ -89,6 +89,8 @@ embedded {
HEADERS += embedded/qscreendriverplugin_qws.h \
embedded/qscreendriverfactory_qws.h \
embedded/qkbd_qws.h \
+ embedded/qkbd_qws_p.h \
+ embedded/qkbd_defaultmap_qws_p.h \
embedded/qkbddriverplugin_qws.h \
embedded/qkbddriverfactory_qws.h \
embedded/qmouse_qws.h \
@@ -152,17 +154,11 @@ embedded {
contains( kbd-drivers, tty ) {
HEADERS +=embedded/qkbdtty_qws.h
SOURCES +=embedded/qkbdtty_qws.cpp
- !contains( kbd-drivers, pc101 ) {
- kbd-drivers += pc101
- }
}
- contains( kbd-drivers, usb ) {
- HEADERS +=embedded/qkbdusb_qws.h
- SOURCES +=embedded/qkbdusb_qws.cpp
- !contains( kbd-drivers, pc101 ) {
- kbd-drivers += pc101
- }
+ contains( kbd-drivers, linuxinput ) {
+ HEADERS +=embedded/qkbdlinuxinput_qws.h
+ SOURCES +=embedded/qkbdlinuxinput_qws.cpp
}
contains( kbd-drivers, um ) {
@@ -170,11 +166,6 @@ embedded {
SOURCES +=embedded/qkbdum_qws.cpp
}
- contains( kbd-drivers, pc101 ) {
- HEADERS +=embedded/qkbdpc101_qws.h
- SOURCES +=embedded/qkbdpc101_qws.cpp
- }
-
contains( kbd-drivers, yopy ) {
HEADERS +=embedded/qkbdyopy_qws.h
SOURCES +=embedded/qkbdyopy_qws.cpp
diff --git a/src/gui/embedded/qkbd_defaultmap_qws_p.h b/src/gui/embedded/qkbd_defaultmap_qws_p.h
new file mode 100644
index 0000000..0d6d77d
--- /dev/null
+++ b/src/gui/embedded/qkbd_defaultmap_qws_p.h
@@ -0,0 +1,796 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSKEYBOARDHANDLER_DEFAULTMAP_H
+#define QWSKEYBOARDHANDLER_DEFAULTMAP_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+const QWSKeyboard::Mapping QWSKbPrivate::s_keymap_default[] = {
+ { 1, 0xffff, 0x01000000, 0x00, 0x00, 0x0000 },
+ { 2, 0x0031, 0x00000031, 0x00, 0x00, 0x0000 },
+ { 2, 0x0021, 0x00000021, 0x01, 0x00, 0x0000 },
+ { 3, 0x0032, 0x00000032, 0x00, 0x00, 0x0000 },
+ { 3, 0x0040, 0x00000040, 0x01, 0x00, 0x0000 },
+ { 3, 0x0040, 0x00000040, 0x02, 0x00, 0x0000 },
+ { 4, 0x0033, 0x00000033, 0x00, 0x00, 0x0000 },
+ { 4, 0x0023, 0x00000023, 0x01, 0x00, 0x0000 },
+ { 4, 0xffff, 0x01000000, 0x04, 0x00, 0x0000 },
+ { 5, 0x0034, 0x00000034, 0x00, 0x00, 0x0000 },
+ { 5, 0x0024, 0x00000024, 0x01, 0x00, 0x0000 },
+ { 5, 0x0024, 0x00000024, 0x02, 0x00, 0x0000 },
+ { 5, 0x005c, 0x0400005c, 0x04, 0x00, 0x0000 },
+ { 6, 0x0035, 0x00000035, 0x00, 0x00, 0x0000 },
+ { 6, 0x0025, 0x00000025, 0x01, 0x00, 0x0000 },
+ { 6, 0x005d, 0x0400005d, 0x04, 0x00, 0x0000 },
+ { 7, 0x0036, 0x00000036, 0x00, 0x00, 0x0000 },
+ { 7, 0x005e, 0x0000005e, 0x01, 0x00, 0x0000 },
+ { 7, 0x005e, 0x01001252, 0x02, 0x01, 0x0000 },
+ { 7, 0x005e, 0x0400005e, 0x04, 0x00, 0x0000 },
+ { 8, 0x0037, 0x00000037, 0x00, 0x00, 0x0000 },
+ { 8, 0x0026, 0x00000026, 0x01, 0x00, 0x0000 },
+ { 8, 0x007b, 0x0000007b, 0x02, 0x00, 0x0000 },
+ { 8, 0x005f, 0x0400005f, 0x04, 0x00, 0x0000 },
+ { 9, 0x0038, 0x00000038, 0x00, 0x00, 0x0000 },
+ { 9, 0x002a, 0x0000002a, 0x01, 0x00, 0x0000 },
+ { 9, 0x005b, 0x0000005b, 0x02, 0x00, 0x0000 },
+ { 9, 0xffff, 0x01000003, 0x04, 0x00, 0x0000 },
+ { 10, 0x0039, 0x00000039, 0x00, 0x00, 0x0000 },
+ { 10, 0x0028, 0x00000028, 0x01, 0x00, 0x0000 },
+ { 10, 0x005d, 0x0000005d, 0x02, 0x00, 0x0000 },
+ { 11, 0x0030, 0x00000030, 0x00, 0x00, 0x0000 },
+ { 11, 0x0029, 0x00000029, 0x01, 0x00, 0x0000 },
+ { 11, 0x007d, 0x0000007d, 0x02, 0x00, 0x0000 },
+ { 12, 0x002d, 0x0000002d, 0x00, 0x00, 0x0000 },
+ { 12, 0x005f, 0x0000005f, 0x01, 0x00, 0x0000 },
+ { 12, 0x005c, 0x0000005c, 0x02, 0x00, 0x0000 },
+ { 12, 0x005f, 0x0400005f, 0x04, 0x00, 0x0000 },
+ { 12, 0x005f, 0x0400005f, 0x05, 0x00, 0x0000 },
+ { 13, 0x003d, 0x0000003d, 0x00, 0x00, 0x0000 },
+ { 13, 0x002b, 0x0000002b, 0x01, 0x00, 0x0000 },
+ { 14, 0xffff, 0x01000003, 0x00, 0x00, 0x0000 },
+ { 14, 0xffff, 0x01000000, 0x0c, 0x08, 0x0300 },
+ { 15, 0xffff, 0x01000001, 0x00, 0x00, 0x0000 },
+ { 16, 0x0071, 0x00000051, 0x00, 0x00, 0x0000 },
+ { 16, 0x0051, 0x00000051, 0x01, 0x00, 0x0000 },
+ { 16, 0x0071, 0x00000051, 0x02, 0x00, 0x0000 },
+ { 16, 0x0051, 0x00000051, 0x03, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x04, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x05, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x06, 0x00, 0x0000 },
+ { 16, 0x0071, 0x04000051, 0x07, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x08, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x09, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x0a, 0x00, 0x0000 },
+ { 16, 0x0071, 0x08000051, 0x0b, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0c, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0d, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0e, 0x00, 0x0000 },
+ { 16, 0x0071, 0x0c000051, 0x0f, 0x00, 0x0000 },
+ { 17, 0x0077, 0x00000057, 0x00, 0x00, 0x0000 },
+ { 17, 0x0057, 0x00000057, 0x01, 0x00, 0x0000 },
+ { 17, 0x0077, 0x00000057, 0x02, 0x00, 0x0000 },
+ { 17, 0x0057, 0x00000057, 0x03, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x04, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x05, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x06, 0x00, 0x0000 },
+ { 17, 0x0077, 0x04000057, 0x07, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x08, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x09, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x0a, 0x00, 0x0000 },
+ { 17, 0x0077, 0x08000057, 0x0b, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0c, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0d, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0e, 0x00, 0x0000 },
+ { 17, 0x0077, 0x0c000057, 0x0f, 0x00, 0x0000 },
+ { 18, 0x0065, 0x00000045, 0x00, 0x00, 0x0000 },
+ { 18, 0x0045, 0x00000045, 0x01, 0x00, 0x0000 },
+ { 18, 0x0065, 0x00000045, 0x02, 0x00, 0x0000 },
+ { 18, 0x0045, 0x00000045, 0x03, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x04, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x05, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x06, 0x00, 0x0000 },
+ { 18, 0x0065, 0x04000045, 0x07, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x08, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x09, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x0a, 0x00, 0x0000 },
+ { 18, 0x0065, 0x08000045, 0x0b, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0c, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0d, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0e, 0x00, 0x0000 },
+ { 18, 0x0065, 0x0c000045, 0x0f, 0x00, 0x0000 },
+ { 19, 0x0072, 0x00000052, 0x00, 0x00, 0x0000 },
+ { 19, 0x0052, 0x00000052, 0x01, 0x00, 0x0000 },
+ { 19, 0x0072, 0x00000052, 0x02, 0x00, 0x0000 },
+ { 19, 0x0052, 0x00000052, 0x03, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x04, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x05, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x06, 0x00, 0x0000 },
+ { 19, 0x0072, 0x04000052, 0x07, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x08, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x09, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x0a, 0x00, 0x0000 },
+ { 19, 0x0072, 0x08000052, 0x0b, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0c, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0d, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0e, 0x00, 0x0000 },
+ { 19, 0x0072, 0x0c000052, 0x0f, 0x00, 0x0000 },
+ { 20, 0x0074, 0x00000054, 0x00, 0x00, 0x0000 },
+ { 20, 0x0054, 0x00000054, 0x01, 0x00, 0x0000 },
+ { 20, 0x0074, 0x00000054, 0x02, 0x00, 0x0000 },
+ { 20, 0x0054, 0x00000054, 0x03, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x04, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x05, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x06, 0x00, 0x0000 },
+ { 20, 0x0074, 0x04000054, 0x07, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x08, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x09, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x0a, 0x00, 0x0000 },
+ { 20, 0x0074, 0x08000054, 0x0b, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0c, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0d, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0e, 0x00, 0x0000 },
+ { 20, 0x0074, 0x0c000054, 0x0f, 0x00, 0x0000 },
+ { 21, 0x0079, 0x00000059, 0x00, 0x00, 0x0000 },
+ { 21, 0x0059, 0x00000059, 0x01, 0x00, 0x0000 },
+ { 21, 0x0079, 0x00000059, 0x02, 0x00, 0x0000 },
+ { 21, 0x0059, 0x00000059, 0x03, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x04, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x05, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x06, 0x00, 0x0000 },
+ { 21, 0x0079, 0x04000059, 0x07, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x08, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x09, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x0a, 0x00, 0x0000 },
+ { 21, 0x0079, 0x08000059, 0x0b, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0c, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0d, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0e, 0x00, 0x0000 },
+ { 21, 0x0079, 0x0c000059, 0x0f, 0x00, 0x0000 },
+ { 22, 0x0075, 0x00000055, 0x00, 0x00, 0x0000 },
+ { 22, 0x0055, 0x00000055, 0x01, 0x00, 0x0000 },
+ { 22, 0x0075, 0x00000055, 0x02, 0x00, 0x0000 },
+ { 22, 0x0055, 0x00000055, 0x03, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x04, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x05, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x06, 0x00, 0x0000 },
+ { 22, 0x0075, 0x04000055, 0x07, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x08, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x09, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x0a, 0x00, 0x0000 },
+ { 22, 0x0075, 0x08000055, 0x0b, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0c, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0d, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0e, 0x00, 0x0000 },
+ { 22, 0x0075, 0x0c000055, 0x0f, 0x00, 0x0000 },
+ { 23, 0x0069, 0x00000049, 0x00, 0x00, 0x0000 },
+ { 23, 0x0049, 0x00000049, 0x01, 0x00, 0x0000 },
+ { 23, 0x0069, 0x00000049, 0x02, 0x00, 0x0000 },
+ { 23, 0x0049, 0x00000049, 0x03, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x04, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x05, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x06, 0x00, 0x0000 },
+ { 23, 0x0069, 0x04000049, 0x07, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x08, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x09, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x0a, 0x00, 0x0000 },
+ { 23, 0x0069, 0x08000049, 0x0b, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0c, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0d, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0e, 0x00, 0x0000 },
+ { 23, 0x0069, 0x0c000049, 0x0f, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0000004f, 0x00, 0x00, 0x0000 },
+ { 24, 0x004f, 0x0000004f, 0x01, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0000004f, 0x02, 0x00, 0x0000 },
+ { 24, 0x004f, 0x0000004f, 0x03, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x04, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x05, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x06, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0400004f, 0x07, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x08, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x09, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x0a, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0800004f, 0x0b, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0c, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0d, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0e, 0x00, 0x0000 },
+ { 24, 0x006f, 0x0c00004f, 0x0f, 0x00, 0x0000 },
+ { 25, 0x0070, 0x00000050, 0x00, 0x00, 0x0000 },
+ { 25, 0x0050, 0x00000050, 0x01, 0x00, 0x0000 },
+ { 25, 0x0070, 0x00000050, 0x02, 0x00, 0x0000 },
+ { 25, 0x0050, 0x00000050, 0x03, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x04, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x05, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x06, 0x00, 0x0000 },
+ { 25, 0x0070, 0x04000050, 0x07, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x08, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x09, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x0a, 0x00, 0x0000 },
+ { 25, 0x0070, 0x08000050, 0x0b, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0c, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0d, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0e, 0x00, 0x0000 },
+ { 25, 0x0070, 0x0c000050, 0x0f, 0x00, 0x0000 },
+ { 26, 0x005b, 0x0000005b, 0x00, 0x00, 0x0000 },
+ { 26, 0x007b, 0x0000007b, 0x01, 0x00, 0x0000 },
+ { 26, 0xffff, 0x01000000, 0x04, 0x00, 0x0000 },
+ { 27, 0x005d, 0x0000005d, 0x00, 0x00, 0x0000 },
+ { 27, 0x007d, 0x0000007d, 0x01, 0x00, 0x0000 },
+ { 27, 0x007e, 0x0000007e, 0x02, 0x00, 0x0000 },
+ { 27, 0x005d, 0x0400005d, 0x04, 0x00, 0x0000 },
+ { 28, 0xffff, 0x01000004, 0x00, 0x00, 0x0000 },
+ { 28, 0x006d, 0x0c00004d, 0x08, 0x00, 0x0000 },
+ { 29, 0xffff, 0x01000021, 0x00, 0x04, 0x0004 },
+ { 30, 0x0061, 0x00000041, 0x00, 0x00, 0x0000 },
+ { 30, 0x0041, 0x00000041, 0x01, 0x00, 0x0000 },
+ { 30, 0x0061, 0x00000041, 0x02, 0x00, 0x0000 },
+ { 30, 0x0041, 0x00000041, 0x03, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x04, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x05, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x06, 0x00, 0x0000 },
+ { 30, 0x0061, 0x04000041, 0x07, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x08, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x09, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x0a, 0x00, 0x0000 },
+ { 30, 0x0061, 0x08000041, 0x0b, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0c, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0d, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0e, 0x00, 0x0000 },
+ { 30, 0x0061, 0x0c000041, 0x0f, 0x00, 0x0000 },
+ { 31, 0x0073, 0x00000053, 0x00, 0x00, 0x0000 },
+ { 31, 0x0053, 0x00000053, 0x01, 0x00, 0x0000 },
+ { 31, 0x0073, 0x00000053, 0x02, 0x00, 0x0000 },
+ { 31, 0x0053, 0x00000053, 0x03, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x04, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x05, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x06, 0x00, 0x0000 },
+ { 31, 0x0073, 0x04000053, 0x07, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x08, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x09, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x0a, 0x00, 0x0000 },
+ { 31, 0x0073, 0x08000053, 0x0b, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0c, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0d, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0e, 0x00, 0x0000 },
+ { 31, 0x0073, 0x0c000053, 0x0f, 0x00, 0x0000 },
+ { 32, 0x0064, 0x00000044, 0x00, 0x00, 0x0000 },
+ { 32, 0x0044, 0x00000044, 0x01, 0x00, 0x0000 },
+ { 32, 0x0064, 0x00000044, 0x02, 0x00, 0x0000 },
+ { 32, 0x0044, 0x00000044, 0x03, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x04, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x05, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x06, 0x00, 0x0000 },
+ { 32, 0x0064, 0x04000044, 0x07, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x08, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x09, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x0a, 0x00, 0x0000 },
+ { 32, 0x0064, 0x08000044, 0x0b, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0c, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0d, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0e, 0x00, 0x0000 },
+ { 32, 0x0064, 0x0c000044, 0x0f, 0x00, 0x0000 },
+ { 33, 0x0066, 0x00000046, 0x00, 0x00, 0x0000 },
+ { 33, 0x0046, 0x00000046, 0x01, 0x00, 0x0000 },
+ { 33, 0x0066, 0x00000046, 0x02, 0x00, 0x0000 },
+ { 33, 0x0046, 0x00000046, 0x03, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x04, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x05, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x06, 0x00, 0x0000 },
+ { 33, 0x0066, 0x04000046, 0x07, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x08, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x09, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x0a, 0x00, 0x0000 },
+ { 33, 0x0066, 0x08000046, 0x0b, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0c, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0d, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0e, 0x00, 0x0000 },
+ { 33, 0x0066, 0x0c000046, 0x0f, 0x00, 0x0000 },
+ { 34, 0x0067, 0x00000047, 0x00, 0x00, 0x0000 },
+ { 34, 0x0047, 0x00000047, 0x01, 0x00, 0x0000 },
+ { 34, 0x0067, 0x00000047, 0x02, 0x00, 0x0000 },
+ { 34, 0x0047, 0x00000047, 0x03, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x04, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x05, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x06, 0x00, 0x0000 },
+ { 34, 0x0067, 0x04000047, 0x07, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x08, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x09, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x0a, 0x00, 0x0000 },
+ { 34, 0x0067, 0x08000047, 0x0b, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0c, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0d, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0e, 0x00, 0x0000 },
+ { 34, 0x0067, 0x0c000047, 0x0f, 0x00, 0x0000 },
+ { 35, 0x0068, 0x00000048, 0x00, 0x00, 0x0000 },
+ { 35, 0x0048, 0x00000048, 0x01, 0x00, 0x0000 },
+ { 35, 0x0068, 0x00000048, 0x02, 0x00, 0x0000 },
+ { 35, 0x0048, 0x00000048, 0x03, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x04, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x05, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x06, 0x00, 0x0000 },
+ { 35, 0x0068, 0x04000048, 0x07, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x08, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x09, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x0a, 0x00, 0x0000 },
+ { 35, 0x0068, 0x08000048, 0x0b, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0c, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0d, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0e, 0x00, 0x0000 },
+ { 35, 0x0068, 0x0c000048, 0x0f, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0000004a, 0x00, 0x00, 0x0000 },
+ { 36, 0x004a, 0x0000004a, 0x01, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0000004a, 0x02, 0x00, 0x0000 },
+ { 36, 0x004a, 0x0000004a, 0x03, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x04, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x05, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x06, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0400004a, 0x07, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x08, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x09, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x0a, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0800004a, 0x0b, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0c, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0d, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0e, 0x00, 0x0000 },
+ { 36, 0x006a, 0x0c00004a, 0x0f, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0000004b, 0x00, 0x00, 0x0000 },
+ { 37, 0x004b, 0x0000004b, 0x01, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0000004b, 0x02, 0x00, 0x0000 },
+ { 37, 0x004b, 0x0000004b, 0x03, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x04, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x05, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x06, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0400004b, 0x07, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x08, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x09, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x0a, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0800004b, 0x0b, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0c, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0d, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0e, 0x00, 0x0000 },
+ { 37, 0x006b, 0x0c00004b, 0x0f, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0000004c, 0x00, 0x00, 0x0000 },
+ { 38, 0x004c, 0x0000004c, 0x01, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0000004c, 0x02, 0x00, 0x0000 },
+ { 38, 0x004c, 0x0000004c, 0x03, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x04, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x05, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x06, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0400004c, 0x07, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x08, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x09, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x0a, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0800004c, 0x0b, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0c, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0d, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0e, 0x00, 0x0000 },
+ { 38, 0x006c, 0x0c00004c, 0x0f, 0x00, 0x0000 },
+ { 39, 0x003b, 0x0000003b, 0x00, 0x00, 0x0000 },
+ { 39, 0x003a, 0x0000003a, 0x01, 0x00, 0x0000 },
+ { 40, 0x0027, 0x00000027, 0x00, 0x00, 0x0000 },
+ { 40, 0x0022, 0x00000022, 0x01, 0x00, 0x0000 },
+ { 40, 0x0027, 0x01001251, 0x02, 0x01, 0x0000 },
+ { 40, 0x0022, 0x01001257, 0x03, 0x01, 0x0000 },
+ { 40, 0x0067, 0x04000047, 0x04, 0x00, 0x0000 },
+ { 41, 0x0060, 0x00000060, 0x00, 0x00, 0x0000 },
+ { 41, 0x007e, 0x0000007e, 0x01, 0x00, 0x0000 },
+ { 41, 0x0060, 0x01001250, 0x02, 0x01, 0x0000 },
+ { 41, 0x007e, 0x01001253, 0x03, 0x01, 0x0000 },
+ { 42, 0xffff, 0x01000020, 0x00, 0x04, 0x0001 },
+ { 43, 0x005c, 0x0000005c, 0x00, 0x00, 0x0000 },
+ { 43, 0x007c, 0x0000007c, 0x01, 0x00, 0x0000 },
+ { 43, 0x005c, 0x0400005c, 0x04, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0000005a, 0x00, 0x00, 0x0000 },
+ { 44, 0x005a, 0x0000005a, 0x01, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0000005a, 0x02, 0x00, 0x0000 },
+ { 44, 0x005a, 0x0000005a, 0x03, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x04, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x05, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x06, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0400005a, 0x07, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x08, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x09, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x0a, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0800005a, 0x0b, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0c, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0d, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0e, 0x00, 0x0000 },
+ { 44, 0x007a, 0x0c00005a, 0x0f, 0x00, 0x0000 },
+ { 45, 0x0078, 0x00000058, 0x00, 0x00, 0x0000 },
+ { 45, 0x0058, 0x00000058, 0x01, 0x00, 0x0000 },
+ { 45, 0x0078, 0x00000058, 0x02, 0x00, 0x0000 },
+ { 45, 0x0058, 0x00000058, 0x03, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x04, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x05, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x06, 0x00, 0x0000 },
+ { 45, 0x0078, 0x04000058, 0x07, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x08, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x09, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x0a, 0x00, 0x0000 },
+ { 45, 0x0078, 0x08000058, 0x0b, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0c, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0d, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0e, 0x00, 0x0000 },
+ { 45, 0x0078, 0x0c000058, 0x0f, 0x00, 0x0000 },
+ { 46, 0x0063, 0x00000043, 0x00, 0x00, 0x0000 },
+ { 46, 0x0043, 0x00000043, 0x01, 0x00, 0x0000 },
+ { 46, 0x0063, 0x00000043, 0x02, 0x00, 0x0000 },
+ { 46, 0x0043, 0x00000043, 0x03, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x04, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x05, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x06, 0x00, 0x0000 },
+ { 46, 0x0063, 0x04000043, 0x07, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x08, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x09, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x0a, 0x00, 0x0000 },
+ { 46, 0x0063, 0x08000043, 0x0b, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0c, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0d, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0e, 0x00, 0x0000 },
+ { 46, 0x0063, 0x0c000043, 0x0f, 0x00, 0x0000 },
+ { 47, 0x0076, 0x00000056, 0x00, 0x00, 0x0000 },
+ { 47, 0x0056, 0x00000056, 0x01, 0x00, 0x0000 },
+ { 47, 0x0076, 0x00000056, 0x02, 0x00, 0x0000 },
+ { 47, 0x0056, 0x00000056, 0x03, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x04, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x05, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x06, 0x00, 0x0000 },
+ { 47, 0x0076, 0x04000056, 0x07, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x08, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x09, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x0a, 0x00, 0x0000 },
+ { 47, 0x0076, 0x08000056, 0x0b, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0c, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0d, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0e, 0x00, 0x0000 },
+ { 47, 0x0076, 0x0c000056, 0x0f, 0x00, 0x0000 },
+ { 48, 0x0062, 0x00000042, 0x00, 0x00, 0x0000 },
+ { 48, 0x0042, 0x00000042, 0x01, 0x00, 0x0000 },
+ { 48, 0x0062, 0x00000042, 0x02, 0x00, 0x0000 },
+ { 48, 0x0042, 0x00000042, 0x03, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x04, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x05, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x06, 0x00, 0x0000 },
+ { 48, 0x0062, 0x04000042, 0x07, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x08, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x09, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x0a, 0x00, 0x0000 },
+ { 48, 0x0062, 0x08000042, 0x0b, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0c, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0d, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0e, 0x00, 0x0000 },
+ { 48, 0x0062, 0x0c000042, 0x0f, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0000004e, 0x00, 0x00, 0x0000 },
+ { 49, 0x004e, 0x0000004e, 0x01, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0000004e, 0x02, 0x00, 0x0000 },
+ { 49, 0x004e, 0x0000004e, 0x03, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x04, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x05, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x06, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0400004e, 0x07, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x08, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x09, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x0a, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0800004e, 0x0b, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0c, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0d, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0e, 0x00, 0x0000 },
+ { 49, 0x006e, 0x0c00004e, 0x0f, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0000004d, 0x00, 0x00, 0x0000 },
+ { 50, 0x004d, 0x0000004d, 0x01, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0000004d, 0x02, 0x00, 0x0000 },
+ { 50, 0x004d, 0x0000004d, 0x03, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x04, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x05, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x06, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0400004d, 0x07, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x08, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x09, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x0a, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0800004d, 0x0b, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0c, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0d, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0e, 0x00, 0x0000 },
+ { 50, 0x006d, 0x0c00004d, 0x0f, 0x00, 0x0000 },
+ { 51, 0x002c, 0x0000002c, 0x00, 0x00, 0x0000 },
+ { 51, 0x003c, 0x0000003c, 0x01, 0x00, 0x0000 },
+ { 51, 0x002c, 0x0100125b, 0x02, 0x01, 0x0000 },
+ { 52, 0x002e, 0x0000002e, 0x00, 0x00, 0x0000 },
+ { 52, 0x003e, 0x0000003e, 0x01, 0x00, 0x0000 },
+ { 52, 0xffff, 0x01001120, 0x02, 0x00, 0x0000 },
+ { 53, 0x002f, 0x0000002f, 0x00, 0x00, 0x0000 },
+ { 53, 0x003f, 0x0000003f, 0x01, 0x00, 0x0000 },
+ { 53, 0xffff, 0x01000003, 0x04, 0x00, 0x0000 },
+ { 54, 0xffff, 0x01000020, 0x00, 0x04, 0x0001 },
+ { 55, 0x002a, 0x2000002a, 0x00, 0x00, 0x0000 },
+ { 56, 0xffff, 0x01000023, 0x00, 0x04, 0x0008 },
+ { 57, 0x0020, 0x00000020, 0x00, 0x00, 0x0000 },
+ { 58, 0xffff, 0x01000024, 0x00, 0x00, 0x0000 },
+ { 59, 0xffff, 0x01000030, 0x00, 0x00, 0x0000 },
+ { 59, 0xffff, 0x0100003c, 0x01, 0x00, 0x0000 },
+ { 59, 0xffff, 0x01000048, 0x04, 0x00, 0x0000 },
+ { 59, 0xffff, 0x01000000, 0x0c, 0x08, 0x0100 },
+ { 60, 0xffff, 0x01000031, 0x00, 0x00, 0x0000 },
+ { 60, 0xffff, 0x0100003d, 0x01, 0x00, 0x0000 },
+ { 60, 0xffff, 0x01000049, 0x04, 0x00, 0x0000 },
+ { 60, 0xffff, 0x01000000, 0x0c, 0x08, 0x0101 },
+ { 61, 0xffff, 0x01000032, 0x00, 0x00, 0x0000 },
+ { 61, 0xffff, 0x0100003e, 0x01, 0x00, 0x0000 },
+ { 61, 0xffff, 0x0100004a, 0x04, 0x00, 0x0000 },
+ { 61, 0xffff, 0x01000000, 0x0c, 0x08, 0x0102 },
+ { 62, 0xffff, 0x01000033, 0x00, 0x00, 0x0000 },
+ { 62, 0xffff, 0x0100003f, 0x01, 0x00, 0x0000 },
+ { 62, 0xffff, 0x0100004b, 0x04, 0x00, 0x0000 },
+ { 62, 0xffff, 0x01000000, 0x0c, 0x08, 0x0103 },
+ { 63, 0xffff, 0x01000034, 0x00, 0x00, 0x0000 },
+ { 63, 0xffff, 0x01000040, 0x01, 0x00, 0x0000 },
+ { 63, 0xffff, 0x0100004c, 0x04, 0x00, 0x0000 },
+ { 63, 0xffff, 0x01000000, 0x0c, 0x08, 0x0104 },
+ { 64, 0xffff, 0x01000035, 0x00, 0x00, 0x0000 },
+ { 64, 0xffff, 0x01000041, 0x01, 0x00, 0x0000 },
+ { 64, 0xffff, 0x0100004d, 0x04, 0x00, 0x0000 },
+ { 64, 0xffff, 0x01000000, 0x0c, 0x08, 0x0105 },
+ { 65, 0xffff, 0x01000036, 0x00, 0x00, 0x0000 },
+ { 65, 0xffff, 0x01000042, 0x01, 0x00, 0x0000 },
+ { 65, 0xffff, 0x0100004e, 0x04, 0x00, 0x0000 },
+ { 65, 0xffff, 0x01000000, 0x0c, 0x08, 0x0106 },
+ { 66, 0xffff, 0x01000037, 0x00, 0x00, 0x0000 },
+ { 66, 0xffff, 0x01000043, 0x01, 0x00, 0x0000 },
+ { 66, 0xffff, 0x0100004f, 0x04, 0x00, 0x0000 },
+ { 66, 0xffff, 0x01000000, 0x0c, 0x08, 0x0107 },
+ { 67, 0xffff, 0x01000038, 0x00, 0x00, 0x0000 },
+ { 67, 0xffff, 0x01000044, 0x01, 0x00, 0x0000 },
+ { 67, 0xffff, 0x01000050, 0x04, 0x00, 0x0000 },
+ { 67, 0xffff, 0x01000000, 0x0c, 0x08, 0x0108 },
+ { 68, 0xffff, 0x01000039, 0x00, 0x00, 0x0000 },
+ { 68, 0xffff, 0x01000045, 0x01, 0x00, 0x0000 },
+ { 68, 0xffff, 0x01000051, 0x04, 0x00, 0x0000 },
+ { 68, 0xffff, 0x01000000, 0x0c, 0x08, 0x0109 },
+ { 69, 0xffff, 0x01000025, 0x00, 0x00, 0x0000 },
+ { 70, 0xffff, 0x01000026, 0x00, 0x00, 0x0000 },
+ { 70, 0xffff, 0x01000026, 0x08, 0x00, 0x0000 },
+ { 71, 0x0037, 0x20000037, 0x00, 0x00, 0x0000 },
+ { 72, 0x0038, 0x20000038, 0x00, 0x00, 0x0000 },
+ { 73, 0x0039, 0x20000039, 0x00, 0x00, 0x0000 },
+ { 74, 0x002d, 0x2000002d, 0x00, 0x00, 0x0000 },
+ { 75, 0x0034, 0x20000034, 0x00, 0x00, 0x0000 },
+ { 76, 0x0035, 0x20000035, 0x00, 0x00, 0x0000 },
+ { 77, 0x0036, 0x20000036, 0x00, 0x00, 0x0000 },
+ { 78, 0x002b, 0x2000002b, 0x00, 0x00, 0x0000 },
+ { 79, 0x0031, 0x20000031, 0x00, 0x00, 0x0000 },
+ { 80, 0x0032, 0x20000032, 0x00, 0x00, 0x0000 },
+ { 81, 0x0033, 0x20000033, 0x00, 0x00, 0x0000 },
+ { 82, 0x0030, 0x20000030, 0x00, 0x00, 0x0000 },
+ { 83, 0x002e, 0x2000002e, 0x00, 0x00, 0x0000 },
+ { 83, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
+ { 83, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+ { 86, 0x003c, 0x0000003c, 0x00, 0x00, 0x0000 },
+ { 86, 0x003e, 0x0000003e, 0x01, 0x00, 0x0000 },
+ { 86, 0x007c, 0x0000007c, 0x02, 0x00, 0x0000 },
+ { 87, 0xffff, 0x0100003a, 0x00, 0x00, 0x0000 },
+ { 87, 0xffff, 0x01000046, 0x01, 0x00, 0x0000 },
+ { 87, 0xffff, 0x01000052, 0x04, 0x00, 0x0000 },
+ { 87, 0xffff, 0x01000000, 0x0c, 0x08, 0x010a },
+ { 88, 0xffff, 0x0100003b, 0x00, 0x00, 0x0000 },
+ { 88, 0xffff, 0x01000047, 0x01, 0x00, 0x0000 },
+ { 88, 0xffff, 0x01000000, 0x0c, 0x08, 0x010b },
+ { 96, 0xffff, 0x21000005, 0x00, 0x00, 0x0000 },
+ { 97, 0xffff, 0x01000021, 0x00, 0x04, 0x0004 },
+ { 98, 0x002f, 0x2000002f, 0x00, 0x00, 0x0000 },
+ { 99, 0x005c, 0x0400005c, 0x00, 0x00, 0x0000 },
+ { 100, 0xffff, 0x01001103, 0x00, 0x04, 0x0002 },
+ { 102, 0xffff, 0x01000010, 0x00, 0x00, 0x0000 },
+ { 103, 0xffff, 0x01000013, 0x00, 0x00, 0x0000 },
+ { 104, 0xffff, 0x01000016, 0x00, 0x00, 0x0000 },
+ { 105, 0xffff, 0x01000012, 0x00, 0x00, 0x0000 },
+ { 105, 0xffff, 0x01000000, 0x0c, 0x08, 0x0180 },
+ { 106, 0xffff, 0x01000014, 0x00, 0x00, 0x0000 },
+ { 106, 0xffff, 0x01000000, 0x0c, 0x08, 0x0181 },
+ { 107, 0xffff, 0x01000011, 0x00, 0x00, 0x0000 },
+ { 108, 0xffff, 0x01000015, 0x00, 0x00, 0x0000 },
+ { 109, 0xffff, 0x01000017, 0x00, 0x00, 0x0000 },
+ { 110, 0xffff, 0x01000006, 0x00, 0x00, 0x0000 },
+ { 111, 0xffff, 0x01000007, 0x00, 0x00, 0x0000 },
+ { 111, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 },
+ { 111, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 },
+ { 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 },
+};
+
+const QWSKeyboard::Composing QWSKbPrivate::s_keycompose_default[] = {
+ { 0x0060, 0x0041, 0x00c0 },
+ { 0x0060, 0x0061, 0x00e0 },
+ { 0x0027, 0x0041, 0x00c1 },
+ { 0x0027, 0x0061, 0x00e1 },
+ { 0x005e, 0x0041, 0x00c2 },
+ { 0x005e, 0x0061, 0x00e2 },
+ { 0x007e, 0x0041, 0x00c3 },
+ { 0x007e, 0x0061, 0x00e3 },
+ { 0x0022, 0x0041, 0x00c4 },
+ { 0x0022, 0x0061, 0x00e4 },
+ { 0x002d, 0x0061, 0x00aa },
+ { 0x002d, 0x0041, 0x00aa },
+ { 0x004f, 0x0041, 0x00c5 },
+ { 0x006f, 0x0061, 0x00e5 },
+ { 0x0030, 0x0041, 0x00c5 },
+ { 0x0030, 0x0061, 0x00e5 },
+ { 0x0041, 0x0041, 0x00c5 },
+ { 0x0061, 0x0061, 0x00e5 },
+ { 0x00b0, 0x0041, 0x00c5 },
+ { 0x00b0, 0x0061, 0x00e5 },
+ { 0x0041, 0x0045, 0x00c6 },
+ { 0x0061, 0x0065, 0x00e6 },
+ { 0x002c, 0x0043, 0x00c7 },
+ { 0x002c, 0x0063, 0x00e7 },
+ { 0x005e, 0x0043, 0x00c7 },
+ { 0x005e, 0x0063, 0x00e7 },
+ { 0x0060, 0x0045, 0x00c8 },
+ { 0x0060, 0x0065, 0x00e8 },
+ { 0x0027, 0x0045, 0x00c9 },
+ { 0x0027, 0x0065, 0x00e9 },
+ { 0x005e, 0x0045, 0x00ca },
+ { 0x005e, 0x0065, 0x00ea },
+ { 0x0022, 0x0045, 0x00cb },
+ { 0x0022, 0x0065, 0x00eb },
+ { 0x0060, 0x0049, 0x00cc },
+ { 0x0060, 0x0069, 0x00ec },
+ { 0x0027, 0x0049, 0x00cd },
+ { 0x0027, 0x0069, 0x00ed },
+ { 0x005e, 0x0049, 0x00ce },
+ { 0x005e, 0x0069, 0x00ee },
+ { 0x0022, 0x0049, 0x00cf },
+ { 0x0022, 0x0069, 0x00ef },
+ { 0x002d, 0x0044, 0x00d0 },
+ { 0x002d, 0x0064, 0x00f0 },
+ { 0x005e, 0x0044, 0x00d0 },
+ { 0x005e, 0x0064, 0x00f0 },
+ { 0x007e, 0x004e, 0x00d1 },
+ { 0x007e, 0x006e, 0x00f1 },
+ { 0x005e, 0x004e, 0x00d1 },
+ { 0x005e, 0x006e, 0x00f1 },
+ { 0x0060, 0x004f, 0x00d2 },
+ { 0x0060, 0x006f, 0x00f2 },
+ { 0x0027, 0x004f, 0x00d3 },
+ { 0x0027, 0x006f, 0x00f3 },
+ { 0x005e, 0x004f, 0x00d4 },
+ { 0x005e, 0x006f, 0x00f4 },
+ { 0x007e, 0x004f, 0x00d5 },
+ { 0x007e, 0x006f, 0x00f5 },
+ { 0x0022, 0x004f, 0x00d6 },
+ { 0x0022, 0x006f, 0x00f6 },
+ { 0x002f, 0x004f, 0x00d8 },
+ { 0x002f, 0x006f, 0x00f8 },
+ { 0x002d, 0x006f, 0x00ba },
+ { 0x002d, 0x004f, 0x00ba },
+ { 0x0060, 0x0055, 0x00d9 },
+ { 0x0060, 0x0075, 0x00f9 },
+ { 0x0027, 0x0055, 0x00da },
+ { 0x0027, 0x0075, 0x00fa },
+ { 0x005e, 0x0055, 0x00db },
+ { 0x005e, 0x0075, 0x00fb },
+ { 0x0022, 0x0055, 0x00dc },
+ { 0x0022, 0x0075, 0x00fc },
+ { 0x0027, 0x0059, 0x00dd },
+ { 0x0027, 0x0079, 0x00fd },
+ { 0x0054, 0x0048, 0x00de },
+ { 0x0074, 0x0068, 0x00fe },
+ { 0x0073, 0x0073, 0x00df },
+ { 0x0022, 0x0079, 0x00ff },
+ { 0x0073, 0x007a, 0x00df },
+ { 0x006e, 0x006e, 0x00f1 },
+ { 0x006e, 0x0068, 0x00f1 },
+ { 0x004e, 0x0059, 0x00d1 },
+ { 0x004e, 0x004e, 0x00d1 },
+ { 0x004e, 0x0048, 0x00d1 },
+ { 0x004e, 0x0079, 0x00d1 },
+ { 0x004e, 0x006e, 0x00d1 },
+ { 0x004e, 0x0068, 0x00d1 },
+ { 0x002d, 0x004c, 0x00a3 },
+ { 0x003c, 0x003c, 0x00ab },
+ { 0x003e, 0x003e, 0x00bb },
+ { 0x003f, 0x003f, 0x00bf },
+ { 0x005e, 0x003f, 0x00bf },
+ { 0x0021, 0x0021, 0x00a1 },
+ { 0x005e, 0x0021, 0x00a1 },
+ { 0x005e, 0x0031, 0x00b9 },
+ { 0x005e, 0x0032, 0x00b2 },
+ { 0x005e, 0x0033, 0x00b3 },
+ { 0x002b, 0x002d, 0x00b1 },
+ { 0x0063, 0x003d, 0x00a2 },
+ { 0x0063, 0x002f, 0x00a2 },
+ { 0x002f, 0x0063, 0x00a2 },
+ { 0x002d, 0x0063, 0x00a2 },
+ { 0x002d, 0x0043, 0x00a2 },
+ { 0x004c, 0x003d, 0x00a3 },
+ { 0x002d, 0x004c, 0x00a3 },
+ { 0x002d, 0x006c, 0x00a3 },
+ { 0x005e, 0x002a, 0x00d7 },
+ { 0x005e, 0x0078, 0x00d7 },
+ { 0x0078, 0x0078, 0x00d7 },
+ { 0x005e, 0x002e, 0x00b7 },
+ { 0x002e, 0x002e, 0x00b7 },
+ { 0x005e, 0x002f, 0x00f7 },
+ { 0x005e, 0x003a, 0x00f7 },
+ { 0x002d, 0x003a, 0x00f7 },
+ { 0x003a, 0x002d, 0x00f7 },
+ { 0x0059, 0x003d, 0x00a5 },
+ { 0x002d, 0x0059, 0x00a5 },
+ { 0x002d, 0x006c, 0x00a5 },
+ { 0x0028, 0x0063, 0x00a9 },
+ { 0x0022, 0x0063, 0x00a9 },
+ { 0x002d, 0x0061, 0x00aa },
+ { 0x002d, 0x0041, 0x00aa },
+ { 0x002d, 0x006f, 0x00ba },
+ { 0x002d, 0x004f, 0x00ba },
+ { 0x0028, 0x0072, 0x00ae },
+ { 0x0022, 0x0072, 0x00ae },
+ { 0x006d, 0x0075, 0x00b5 },
+ { 0x0031, 0x0034, 0x0152 },
+ { 0x0031, 0x0032, 0x0153 },
+ { 0x0033, 0x0034, 0x0178 },
+ { 0x0065, 0x003d, 0x20ac },
+ { 0x002d, 0x0065, 0x20ac },
+ { 0x002d, 0x0045, 0x20ac },
+ { 0x0076, 0x0053, 0x0160 },
+ { 0x005e, 0x0053, 0x0160 },
+ { 0x0076, 0x0073, 0x0161 },
+ { 0x005e, 0x0073, 0x0161 },
+ { 0x0076, 0x005a, 0x017d },
+ { 0x005e, 0x005a, 0x017d },
+ { 0x0076, 0x007a, 0x017e },
+ { 0x005e, 0x007a, 0x017e },
+ { 0x004f, 0x0045, 0x0152 },
+ { 0x004f, 0x0065, 0x0152 },
+ { 0x006f, 0x0065, 0x0153 },
+ { 0x0022, 0x0059, 0x0178 },
+ { 0x0069, 0x006a, 0x00ff },
+ { 0x0049, 0x004a, 0x0178 },
+};
+
+#endif
diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp
index 8cf87db..dc92a01 100644
--- a/src/gui/embedded/qkbd_qws.cpp
+++ b/src/gui/embedded/qkbd_qws.cpp
@@ -40,56 +40,217 @@
****************************************************************************/
#include "qkbd_qws.h"
+#include "qkbd_qws_p.h"
#ifndef QT_NO_QWS_KEYBOARD
+#include <QFile>
+#include <QDataStream>
+#include <QStringList>
+
#include "qwindowsystem_qws.h"
#include "qscreen_qws.h"
#include "qtimer.h"
#include <stdlib.h>
+//#define QT_DEBUG_KEYMAP
+
+
QT_BEGIN_NAMESPACE
class QWSKbPrivate : public QObject
{
Q_OBJECT
public:
- QWSKbPrivate(QWSKeyboardHandler *h) {
- handler = h;
- arTimer = new QTimer(this);
- arTimer->setSingleShot(true);
- connect(arTimer, SIGNAL(timeout()), SLOT(autoRepeat()));
- repeatdelay = 400;
- repeatperiod = 80;
+ QWSKbPrivate(QWSKeyboardHandler *h, const QString &device)
+ : m_handler(h), m_modifiers(0), m_composing(0), m_dead_unicode(0xffff),
+ m_no_zap(false), m_do_compose(false),
+ m_keymap(0), m_keymap_size(0), m_keycompose(0), m_keycompose_size(0)
+ {
+ m_ar_timer = new QTimer(this);
+ m_ar_timer->setSingleShot(true);
+ connect(m_ar_timer, SIGNAL(timeout()), SLOT(autoRepeat()));
+ m_ar_delay = 400;
+ m_ar_period = 80;
+
+ memset(m_locks, 0, sizeof(m_locks));
+
+ QString keymap;
+ QStringList args = device.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("keymap=")))
+ keymap = arg.mid(7);
+ else if (arg == QLatin1String("disable-zap"))
+ m_no_zap = true;
+ else if (arg == QLatin1String("enable-compose"))
+ m_do_compose = true;
+ else if (arg.startsWith(QLatin1String("repeat-delay=")))
+ m_ar_delay = arg.mid(13).toInt();
+ else if (arg.startsWith(QLatin1String("repeat-rate=")))
+ m_ar_period = arg.mid(12).toInt();
+ }
+
+ if (keymap.isEmpty() || !loadKeymap(keymap))
+ unloadKeymap();
}
- void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod) {
- unicode = uni;
- keycode = code;
- modifier = mod;
- arTimer->start(repeatdelay);
+ ~QWSKbPrivate()
+ {
+ unloadKeymap();
}
- void endAutoRepeat() {
- arTimer->stop();
+
+ void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod)
+ {
+ m_ar_unicode = uni;
+ m_ar_keycode = code;
+ m_ar_modifier = mod;
+ m_ar_timer->start(m_ar_delay);
}
+ void endAutoRepeat()
+ {
+ m_ar_timer->stop();
+ }
+
+ static Qt::KeyboardModifiers toQtModifiers(quint8 mod)
+ {
+ Qt::KeyboardModifiers qtmod = Qt::NoModifier;
+
+ if (mod & (QWSKeyboard::ModShift | QWSKeyboard::ModShiftL | QWSKeyboard::ModShiftR))
+ qtmod |= Qt::ShiftModifier;
+ if (mod & (QWSKeyboard::ModControl | QWSKeyboard::ModCtrlL | QWSKeyboard::ModCtrlR))
+ qtmod |= Qt::ControlModifier;
+ if (mod & QWSKeyboard::ModAlt)
+ qtmod |= Qt::AltModifier;
+
+ return qtmod;
+ }
+
+ void unloadKeymap();
+ bool loadKeymap(const QString &file);
+
private slots:
- void autoRepeat() {
- handler->processKeyEvent(unicode, keycode, modifier, false, true);
- handler->processKeyEvent(unicode, keycode, modifier, true, true);
- arTimer->start(repeatperiod);
+ void autoRepeat()
+ {
+ m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, false, true);
+ m_handler->processKeyEvent(m_ar_unicode, m_ar_keycode, m_ar_modifier, true, true);
+ m_ar_timer->start(m_ar_period);
}
private:
- QWSKeyboardHandler *handler;
- int unicode;
- int keycode;
- Qt::KeyboardModifiers modifier;
- int repeatdelay;
- int repeatperiod;
- QTimer *arTimer;
+ QWSKeyboardHandler *m_handler;
+
+ // auto repeat simulation
+ int m_ar_unicode;
+ int m_ar_keycode;
+ Qt::KeyboardModifiers m_ar_modifier;
+ int m_ar_delay;
+ int m_ar_period;
+ QTimer *m_ar_timer;
+
+ // keymap handling
+ quint8 m_modifiers;
+ quint8 m_locks[3];
+ int m_composing;
+ quint16 m_dead_unicode;
+
+ bool m_no_zap;
+ bool m_do_compose;
+
+ const QWSKeyboard::Mapping *m_keymap;
+ int m_keymap_size;
+ const QWSKeyboard::Composing *m_keycompose;
+ int m_keycompose_size;
+
+ static const QWSKeyboard::Mapping s_keymap_default[];
+ static const QWSKeyboard::Composing s_keycompose_default[];
+
+ friend class QWSKeyboardHandler;
};
+// simple builtin US keymap
+#include "qkbd_defaultmap_qws_p.h"
+
+// the unloadKeymap() function needs to be AFTER the defaultmap include,
+// since the sizeof(s_keymap_default) wouldn't work otherwise.
+
+void QWSKbPrivate::unloadKeymap()
+{
+ if (m_keymap && m_keymap != s_keymap_default)
+ delete [] m_keymap;
+ if (m_keycompose && m_keycompose != s_keycompose_default)
+ delete [] m_keycompose;
+
+ m_keymap = s_keymap_default;
+ m_keymap_size = sizeof(s_keymap_default) / sizeof(s_keymap_default[0]);
+ m_keycompose = s_keycompose_default;
+ m_keycompose_size = sizeof(s_keycompose_default) / sizeof(s_keycompose_default[0]);
+
+ // reset state, so we could switch keymaps at runtime
+ m_modifiers = 0;
+ memset(m_locks, 0, sizeof(m_locks));
+ m_composing = 0;
+ m_dead_unicode = 0xffff;
+}
+
+bool QWSKbPrivate::loadKeymap(const QString &file)
+{
+ QFile f(file);
+
+ if (!f.open(QIODevice::ReadOnly)) {
+ qWarning("Could not open keymap file '%s'", qPrintable(file));
+ return false;
+ }
+
+ // .qmap files have a very simple structure:
+ // quint32 magic (QWSKeyboard::FileMagic)
+ // quint32 version (1)
+ // quint32 keymap_size (# of struct QWSKeyboard::Mappings)
+ // quint32 keycompose_size (# of struct QWSKeyboard::Composings)
+ // all QWSKeyboard::Mappings via QDataStream::operator(<<|>>)
+ // all QWSKeyboard::Composings via QDataStream::operator(<<|>>)
+
+ quint32 qmap_magic, qmap_version, qmap_keymap_size, qmap_keycompose_size;
+
+ QDataStream ds(&f);
+
+ ds >> qmap_magic >> qmap_version >> qmap_keymap_size >> qmap_keycompose_size;
+
+ if (ds.status() != QDataStream::Ok || qmap_magic != QWSKeyboard::FileMagic || qmap_version != 1 || qmap_keymap_size == 0) {
+ qWarning("'%s' is ot a valid.qmap keymap file.", qPrintable(file));
+ return false;
+ }
+
+ QWSKeyboard::Mapping *qmap_keymap = new QWSKeyboard::Mapping[qmap_keymap_size];
+ QWSKeyboard::Composing *qmap_keycompose = qmap_keycompose_size ? new QWSKeyboard::Composing[qmap_keycompose_size] : 0;
+
+ for (quint32 i = 0; i < qmap_keymap_size; ++i)
+ ds >> qmap_keymap[i];
+ for (quint32 i = 0; i < qmap_keycompose_size; ++i)
+ ds >> qmap_keycompose[i];
+
+ if (ds.status() != QDataStream::Ok) {
+ delete [] qmap_keymap;
+ delete [] qmap_keycompose;
+
+ qWarning("Keymap file '%s' can not be loaded.", qPrintable(file));
+ return false;
+ }
+
+ // unload currently active and clear state
+ unloadKeymap();
+
+ m_keymap = qmap_keymap;
+ m_keymap_size = qmap_keymap_size;
+ m_keycompose = qmap_keycompose;
+ m_keycompose_size = qmap_keycompose_size;
+
+ m_do_compose = true;
+
+ return true;
+}
+
+
/*!
\class QWSKeyboardHandler
\ingroup qws
@@ -132,18 +293,29 @@ private:
/*!
- Constructs a keyboard driver.
+ Constructs a keyboard driver. The \a device argument is passed by the
+ QWS_KEYBOARD environment variable.
Call the QWSServer::setKeyboardHandler() function to make the
newly created keyboard driver, the primary driver. Note that the
primary driver is controlled by the system, i.e., the system will
delete it upon exit.
*/
+QWSKeyboardHandler::QWSKeyboardHandler(const QString &device)
+{
+ d = new QWSKbPrivate(this, device);
+}
+
+/*!
+ \overload
+*/
QWSKeyboardHandler::QWSKeyboardHandler()
{
- d = new QWSKbPrivate(this);
+ d = new QWSKbPrivate(this, QString());
}
+
+
/*!
Destroys this keyboard driver.
@@ -172,7 +344,10 @@ QWSKeyboardHandler::~QWSKeyboardHandler()
event is caused by an auto-repeat mechanism and not an actual key
press.
- \sa beginAutoRepeat(), endAutoRepeat(), transformDirKey()
+ Note that this function does not handle key mapping. Please use
+ processKeycode() if you need that functionality.
+
+ \sa processKeycode(), beginAutoRepeat(), endAutoRepeat(), transformDirKey()
*/
void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
bool isPress, bool autoRepeat)
@@ -241,6 +416,256 @@ void QWSKeyboardHandler::endAutoRepeat()
d->endAutoRepeat();
}
+/*!
+ \enum QWSKeyboardHandler::KeycodeAction
+
+ This enum describes the various special actions that actual
+ QWSKeyboardHandler implementations have to take care of.
+
+ \value None No further action required.
+
+ \value CapsLockOn Set the state of the Caps lock LED to on.
+ \value CapsLockOff Set the state of the Caps lock LED to off.
+ \value NumLockOn Set the state of the Num lock LED to on.
+ \value NumLockOff Set the state of the Num lock LED to off.
+ \value ScrollLockOn Set the state of the Scroll lock LED to on.
+ \value ScrollLockOff Set the state of the Scroll lock LED to off.
+
+ \value PreviousConsole Switch to the previous virtual console (by
+ default Ctrl+Alt+Left on Linux).
+ \value NextConsole Switch to the next virtual console (by default
+ Ctrl+Alt+Right on Linux).
+ \value SwitchConsoleFirst Switch to the first virtual console (0).
+ \value SwitchConsoleLast Switch to the last virtual console (255).
+ \value SwitchConsoleMask If the KeyAction value is between SwitchConsoleFirst
+ and SwitchConsoleLast, you can use this mask to get
+ the specific virtual console number to switch to.
+
+ \value Reboot Reboot the machine - this is ignored in both the TTY and
+ LinuxInput handlers though (by default Ctrl+Alt+Del on Linux).
+
+ \sa processKeycode()
+*/
+
+/*!
+ \fn QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool isPress, bool autoRepeat)
+
+ Maps \a keycode according to a keymap and sends that key event to the
+ \l{Qt for Embedded Linux} server application.
+
+ Please see the QWS_KEYBOARD documentation for a description on how to
+ create and use keymap files.
+
+ The key event is identified by its \a keycode value and the \a isPress
+ and \a autoRepeat parameters.
+
+ The \a keycode parameter is \bold NOT the Qt keycode value as defined by
+ the Qt::Key enum. This functions expects a standard Linux 16 bit kernel
+ keycode as it is used in the Linux Input Event sub-system. This
+ \a keycode is transformed to a Qt::Key code by using either a
+ compiled-in US keyboard layout or by dynamically loading a keymap at
+ startup which can be specified via the QWS_KEYBOARD environment
+ variable.
+
+ The \a isPress parameter is true if the event is a key press event and
+ \a autoRepeat is true if the event is caused by an auto-repeat mechanism
+ and not an actual key press.
+
+ The return value indicates if the actual QWSKeyboardHandler
+ implementation needs to take care of a special action, like console
+ switching or LED handling.
+
+ Standard Linux console keymaps can be found at the
+ \l {http://lct.sourceforege.net}{LCT project}
+
+ If standard Linux console keymaps are used, \a keycode must be one of the
+ standardized values defined in \c /usr/include/linux/input.h
+
+ \sa processKeyEvent(), KeycodeAction
+*/
+
+QWSKeyboardHandler::KeycodeAction QWSKeyboardHandler::processKeycode(quint16 keycode, bool pressed, bool autorepeat)
+{
+ KeycodeAction result = None;
+ bool first_press = pressed && !autorepeat;
+
+ const QWSKeyboard::Mapping *map_plain = 0;
+ const QWSKeyboard::Mapping *map_withmod = 0;
+
+ // get a specific and plain mapping for the keycode and the current modifiers
+ for (int i = 0; i < d->m_keymap_size && !(map_plain && map_withmod); ++i) {
+ const QWSKeyboard::Mapping *m = d->m_keymap + i;
+ if (m->keycode == keycode) {
+ if (m->modifiers == 0)
+ map_plain = m;
+
+ quint8 testmods = d->m_modifiers;
+ if (d->m_locks[0] /*CapsLock*/ && (m->flags & QWSKeyboard::IsLetter))
+ testmods ^= QWSKeyboard::ModShift;
+ if (m->modifiers == testmods)
+ map_withmod = m;
+ }
+ }
+
+#ifdef QT_DEBUG_KEYMAP
+ qWarning("Processing key event: keycode=%3d, modifiers=%02x pressed=%d, autorepeat=%d | plain=%d, withmod=%d, size=%d", \
+ keycode, d->m_modifiers, pressed ? 1 : 0, autorepeat ? 1 : 0, \
+ map_plain ? map_plain - d->m_keymap : -1, \
+ map_withmod ? map_withmod - d->m_keymap : -1, \
+ d->m_keymap_size);
+#endif
+
+ const QWSKeyboard::Mapping *it = map_withmod ? map_withmod : map_plain;
+
+ if (!it) {
+#ifdef QT_DEBUG_KEYMAP
+ // we couldn't even find a plain mapping
+ qWarning("Could not find a suitable mapping for keycode: %3d, modifiers: %02x", keycode, d->m_modifiers);
+#endif
+ return result;
+ }
+
+ bool skip = false;
+ quint16 unicode = it->unicode;
+ quint32 qtcode = it->qtcode;
+
+ if ((it->flags & QWSKeyboard::IsModifier) && it->special) {
+ // this is a modifier, i.e. Shift, Alt, ...
+ if (pressed)
+ d->m_modifiers |= quint8(it->special);
+ else
+ d->m_modifiers &= ~quint8(it->special);
+ } else if (qtcode >= Qt::Key_CapsLock && qtcode <= Qt::Key_ScrollLock) {
+ // (Caps|Num|Scroll)Lock
+ if (first_press) {
+ quint8 &lock = d->m_locks[qtcode - Qt::Key_CapsLock];
+ lock ^= 1;
+
+ switch (qtcode) {
+ case Qt::Key_CapsLock : result = lock ? CapsLockOn : CapsLockOff; break;
+ case Qt::Key_NumLock : result = lock ? NumLockOn : NumLockOff; break;
+ case Qt::Key_ScrollLock: result = lock ? ScrollLockOn : ScrollLockOff; break;
+ default : break;
+ }
+ }
+ } else if ((it->flags & QWSKeyboard::IsSystem) && it->special && first_press) {
+ switch (it->special) {
+ case QWSKeyboard::SystemReboot:
+ result = Reboot;
+ break;
+
+ case QWSKeyboard::SystemZap:
+ if (!d->m_no_zap)
+ qApp->quit();
+ break;
+
+ case QWSKeyboard::SystemConsolePrevious:
+ result = PreviousConsole;
+ break;
+
+ case QWSKeyboard::SystemConsoleNext:
+ result = NextConsole;
+ break;
+
+ default:
+ if (it->special >= QWSKeyboard::SystemConsoleFirst &&
+ it->special <= QWSKeyboard::SystemConsoleLast) {
+ result = KeycodeAction(SwitchConsoleFirst + ((it->special & QWSKeyboard::SystemConsoleMask) & SwitchConsoleMask));
+ }
+ break;
+ }
+
+ skip = true; // no need to tell QWS about it
+ } else if ((qtcode == Qt::Key_Multi_key) && d->m_do_compose) {
+ // the Compose key was pressed
+ if (first_press)
+ d->m_composing = 2;
+ skip = true;
+ } else if ((it->flags & QWSKeyboard::IsDead) && d->m_do_compose) {
+ // a Dead key was pressed
+ if (first_press && d->m_composing == 1 && d->m_dead_unicode == unicode) { // twice
+ d->m_composing = 0;
+ qtcode = Qt::Key_unknown; // otherwise it would be Qt::Key_Dead...
+ } else if (first_press && unicode != 0xffff) {
+ d->m_dead_unicode = unicode;
+ d->m_composing = 1;
+ skip = true;
+ } else {
+ skip = true;
+ }
+ }
+
+ if (!skip) {
+ // a normal key was pressed
+ const int modmask = Qt::ShiftModifier | Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier | Qt::KeypadModifier;
+
+ // we couldn't find a specific mapping for the current modifiers,
+ // or that mapping didn't have special modifiers:
+ // so just report the plain mapping with additional modifiers.
+ if ((it == map_plain && it != map_withmod) ||
+ (map_withmod && !(map_withmod->qtcode & modmask))) {
+ qtcode |= QWSKbPrivate::toQtModifiers(d->m_modifiers);
+ }
+
+ if (d->m_composing == 2 && first_press && !(it->flags & QWSKeyboard::IsModifier)) {
+ // the last key press was the Compose key
+ if (unicode != 0xffff) {
+ int idx = 0;
+ // check if this code is in the compose table at all
+ for ( ; idx < d->m_keycompose_size; ++idx) {
+ if (d->m_keycompose[idx].first == unicode)
+ break;
+ }
+ if (idx < d->m_keycompose_size) {
+ // found it -> simulate a Dead key press
+ d->m_dead_unicode = unicode;
+ unicode = 0xffff;
+ d->m_composing = 1;
+ skip = true;
+ } else {
+ d->m_composing = 0;
+ }
+ } else {
+ d->m_composing = 0;
+ }
+ } else if (d->m_composing == 1 && first_press && !(it->flags & QWSKeyboard::IsModifier)) {
+ // the last key press was a Dead key
+ bool valid = false;
+ if (unicode != 0xffff) {
+ int idx = 0;
+ // check if this code is in the compose table at all
+ for ( ; idx < d->m_keycompose_size; ++idx) {
+ if (d->m_keycompose[idx].first == d->m_dead_unicode && d->m_keycompose[idx].second == unicode)
+ break;
+ }
+ if (idx < d->m_keycompose_size) {
+ quint16 composed = d->m_keycompose[idx].result;
+ if (composed != 0xffff) {
+ unicode = composed;
+ qtcode = Qt::Key_unknown;
+ valid = true;
+ }
+ }
+ }
+ if (!valid) {
+ unicode = d->m_dead_unicode;
+ qtcode = Qt::Key_unknown;
+ }
+ d->m_composing = 0;
+ }
+
+ if (!skip) {
+#ifdef QT_DEBUG_KEYMAP
+ qWarning("Processing: uni=%04x, qt=%08x, qtmod=%08x", unicode, qtcode & ~modmask, (qtcode & modmask));
+#endif
+
+ // send the result to the QWS server
+ processKeyEvent(unicode, qtcode & ~modmask, Qt::KeyboardModifiers(qtcode & modmask), pressed, autorepeat);
+ }
+ }
+ return result;
+}
+
QT_END_NAMESPACE
#include "qkbd_qws.moc"
diff --git a/src/gui/embedded/qkbd_qws.h b/src/gui/embedded/qkbd_qws.h
index 8809f0a..171adc0 100644
--- a/src/gui/embedded/qkbd_qws.h
+++ b/src/gui/embedded/qkbd_qws.h
@@ -58,11 +58,33 @@ class Q_GUI_EXPORT QWSKeyboardHandler
{
public:
QWSKeyboardHandler();
+ QWSKeyboardHandler(const QString &device);
virtual ~QWSKeyboardHandler();
virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
bool isPress, bool autoRepeat);
+ enum KeycodeAction {
+ None = 0,
+
+ CapsLockOff = 0x01000000,
+ CapsLockOn = 0x01000001,
+ NumLockOff = 0x02000000,
+ NumLockOn = 0x02000001,
+ ScrollLockOff = 0x03000000,
+ ScrollLockOn = 0x03000001,
+
+ Reboot = 0x04000000,
+
+ PreviousConsole = 0x05000000,
+ NextConsole = 0x05000001,
+ SwitchConsoleFirst = 0x06000000,
+ SwitchConsoleLast = 0x0600007f,
+ SwitchConsoleMask = 0x0000007f,
+ };
+
+ KeycodeAction processKeycode(quint16 keycode, bool pressed, bool autorepeat);
+
protected:
int transformDirKey(int key);
void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod);
diff --git a/src/gui/embedded/qkbd_qws_p.h b/src/gui/embedded/qkbd_qws_p.h
new file mode 100644
index 0000000..2ef1d0c
--- /dev/null
+++ b/src/gui/embedded/qkbd_qws_p.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSKEYBOARD_P_H
+#define QWSKEYBOARD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QDataStream>
+
+namespace QWSKeyboard {
+ const quint32 FileMagic = 0x514d4150; // 'QMAP'
+
+ struct Mapping {
+ quint16 keycode;
+ quint16 unicode;
+ quint32 qtcode;
+ quint8 modifiers;
+ quint8 flags;
+ quint16 special;
+
+ };
+
+ enum Flags {
+ IsDead = 0x01,
+ IsLetter = 0x02,
+ IsModifier = 0x04,
+ IsSystem = 0x08,
+ };
+
+ enum System {
+ SystemConsoleFirst = 0x0100,
+ SystemConsoleMask = 0x007f,
+ SystemConsoleLast = 0x017f,
+ SystemConsolePrevious = 0x0180,
+ SystemConsoleNext = 0x0181,
+ SystemReboot = 0x0200,
+ SystemZap = 0x0300,
+ };
+
+ struct Composing {
+ quint16 first;
+ quint16 second;
+ quint16 result;
+ };
+
+ enum Modifiers {
+ ModPlain = 0x00,
+ ModShift = 0x01,
+ ModAltGr = 0x02,
+ ModControl = 0x04,
+ ModAlt = 0x08,
+ ModShiftL = 0x10,
+ ModShiftR = 0x20,
+ ModCtrlL = 0x40,
+ ModCtrlR = 0x80,
+ // ModCapsShift = 0x100, // not supported!
+ };
+};
+
+#ifndef QT_NO_DATASTREAM
+inline QDataStream &operator>>(QDataStream &ds, QWSKeyboard::Mapping &m)
+{
+ return ds >> m.keycode >> m.unicode >> m.qtcode >> m.modifiers >> m.flags >> m.special;
+}
+
+inline QDataStream &operator<<(QDataStream &ds, const QWSKeyboard::Mapping &m)
+{
+ return ds << m.keycode << m.unicode << m.qtcode << m.modifiers << m.flags << m.special;
+}
+
+inline QDataStream &operator>>(QDataStream &ds, QWSKeyboard::Composing &c)
+{
+ return ds >> c.first >> c.second >> c.result;
+}
+
+inline QDataStream &operator<<(QDataStream &ds, const QWSKeyboard::Composing &c)
+{
+ return ds << c.first << c.second << c.result;
+}
+#endif // QT_NO_DATASTREAM
+
+#endif // QWSKEYBOARD_H
diff --git a/src/gui/embedded/qkbddriverfactory_qws.cpp b/src/gui/embedded/qkbddriverfactory_qws.cpp
index 1ade652..dbfac5c 100644
--- a/src/gui/embedded/qkbddriverfactory_qws.cpp
+++ b/src/gui/embedded/qkbddriverfactory_qws.cpp
@@ -45,7 +45,7 @@
#include "qapplication.h"
#include "qkbdtty_qws.h"
-#include "qkbdusb_qws.h"
+#include "qkbdlinuxinput_qws.h"
#include "qkbdum_qws.h"
#include "qkbdsl5000_qws.h"
#include "qkbdvfb_qws.h"
@@ -121,9 +121,11 @@ QWSKeyboardHandler *QKbdDriverFactory::create(const QString& key, const QString&
if (driver == QLatin1String("tty") || driver.isEmpty())
return new QWSTtyKeyboardHandler(device);
# endif
-# ifndef QT_NO_QWS_KBD_USB
- if (driver == QLatin1String("usb"))
- return new QWSUsbKeyboardHandler(device);
+# ifndef QT_NO_QWS_KBD_LINUXINPUT
+ if (driver == QLatin1String("linuxinput") || \
+ driver == QLatin1String("usb") || \
+ driver == QLatin1String("linuxis"))
+ return new QWSLinuxInputKeyboardHandler(device);
# endif
# ifndef QT_NO_QWS_KBD_UM
if (driver == QLatin1String("um") || driver == QLatin1String("qvfbkeyboard"))
@@ -168,8 +170,8 @@ QStringList QKbdDriverFactory::keys()
#ifndef QT_NO_QWS_KBD_TTY
list << QLatin1String("TTY");
#endif
-#ifndef QT_NO_QWS_KBD_USB
- list << QLatin1String("USB");
+#ifndef QT_NO_QWS_KBD_LINUXINPUT
+ list << QLatin1String("LinuxInput");
#endif
#ifndef QT_NO_QWS_KBD_UM
list << QLatin1String("UM");
diff --git a/src/gui/embedded/qkbdlinuxinput_qws.cpp b/src/gui/embedded/qkbdlinuxinput_qws.cpp
new file mode 100644
index 0000000..1ef2696
--- /dev/null
+++ b/src/gui/embedded/qkbdlinuxinput_qws.cpp
@@ -0,0 +1,241 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdlinuxinput_qws.h"
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#include <QSocketNotifier>
+#include <QStringList>
+
+#include <qplatformdefs.h>
+
+#include <errno.h>
+#include <termios.h>
+
+#include <linux/kd.h>
+#include <linux/input.h>
+
+QT_BEGIN_NAMESPACE
+
+
+class QWSLinuxInputKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSLinuxInputKbPrivate(QWSLinuxInputKeyboardHandler *, const QString &);
+ ~QWSLinuxInputKbPrivate();
+
+private:
+ void switchLed(int, bool);
+
+private Q_SLOTS:
+ void readKeycode();
+
+private:
+ QWSLinuxInputKeyboardHandler *m_handler;
+ int m_fd;
+ int m_tty_fd;
+ struct termios m_tty_attr;
+};
+
+QWSLinuxInputKeyboardHandler::QWSLinuxInputKeyboardHandler(const QString &device)
+ : QWSKeyboardHandler(device)
+{
+ d = new QWSLinuxInputKbPrivate(this, device);
+}
+
+QWSLinuxInputKeyboardHandler::~QWSLinuxInputKeyboardHandler()
+{
+ delete d;
+}
+
+bool QWSLinuxInputKeyboardHandler::filterInputEvent(quint16 &, qint32 &)
+{
+ return false;
+}
+
+QWSLinuxInputKbPrivate::QWSLinuxInputKbPrivate(QWSLinuxInputKeyboardHandler *h, const QString &device)
+ : m_handler(h), m_fd(-1), m_tty_fd(-1)
+
+{
+ setObjectName(QLatin1String("LinuxInputSubsystem Keyboard Handler"));
+
+ QString dev = QLatin1String("/dev/input/event1");
+ int repeat_delay = -1;
+ int repeat_rate = -1;
+
+ QStringList args = device.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("repeat-delay=")))
+ repeat_delay = arg.mid(13).toInt();
+ else if (arg.startsWith(QLatin1String("repeat-rate=")))
+ repeat_rate = arg.mid(12).toInt();
+ else if (arg.startsWith(QLatin1String("/dev/")))
+ dev = arg;
+ }
+
+ m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0);
+ if (m_fd >= 0) {
+ if (repeat_delay > 0 && repeat_rate > 0) {
+ int kbdrep[2] = { repeat_delay, repeat_rate };
+ ::ioctl(m_fd, EVIOCSREP, kbdrep);
+ }
+
+ QSocketNotifier *notifier;
+ notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
+
+ // play nice in case we are started from a shell (e.g. for debugging)
+ m_tty_fd = isatty(0) ? 0 : -1;
+
+ if (m_tty_fd >= 0) {
+ // save tty config for restore.
+ tcgetattr(m_tty_fd, &m_tty_attr);
+
+ struct ::termios termdata;
+ tcgetattr(m_tty_fd, &termdata);
+
+ // setting this tranlation mode is also needed in INPUT mode to prevent
+ // the shell from also interpreting codes, if the process has a tty
+ // attached: e.g. Ctrl+C wouldn't copy, but kill the application.
+ ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW);
+
+ // set the tty layer to pass-through
+ termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
+ termdata.c_oflag = 0;
+ termdata.c_cflag = CREAD | CS8;
+ termdata.c_lflag = 0;
+ termdata.c_cc[VTIME]=0;
+ termdata.c_cc[VMIN]=1;
+ cfsetispeed(&termdata, 9600);
+ cfsetospeed(&termdata, 9600);
+ tcsetattr(m_tty_fd, TCSANOW, &termdata);
+ }
+ } else {
+ qWarning("Cannot open input device '%s': %s", qPrintable(dev), strerror(errno));
+ return;
+ }
+}
+
+QWSLinuxInputKbPrivate::~QWSLinuxInputKbPrivate()
+{
+ if (m_tty_fd >= 0) {
+ ::ioctl(m_tty_fd, KDSKBMODE, K_XLATE);
+ tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr);
+ }
+ if (m_fd >= 0)
+ QT_CLOSE(m_fd);
+}
+
+void QWSLinuxInputKbPrivate::switchLed(int led, bool state)
+{
+ struct ::input_event led_ie;
+ ::gettimeofday(&led_ie.time, 0);
+ led_ie.type = EV_LED;
+ led_ie.code = led;
+ led_ie.value = state;
+
+ QT_WRITE(m_fd, &led_ie, sizeof(led_ie));
+}
+
+void QWSLinuxInputKbPrivate::readKeycode()
+{
+ struct ::input_event buffer[32];
+ int n = 0;
+
+ forever {
+ n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n);
+
+ if (n == 0) {
+ qWarning("Got EOF from the input device.");
+ return;
+ } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+ qWarning("Could not read from input device: %s", strerror(errno));
+ return;
+ } else if (n % sizeof(buffer[0]) == 0) {
+ break;
+ }
+ }
+
+ n /= sizeof(buffer[0]);
+
+ for (int i = 0; i < n; ++i) {
+ if (buffer[i].type != EV_KEY)
+ continue;
+
+ quint16 code = buffer[i].code;
+ qint32 value = buffer[i].value;
+
+ if (m_handler->filterInputEvent(code, value))
+ continue;
+
+ QWSKeyboardHandler::KeycodeAction ka;
+ ka = m_handler->processKeycode(code, value != 0, value == 2);
+
+ switch (ka) {
+ case QWSKeyboardHandler::CapsLockOn:
+ case QWSKeyboardHandler::CapsLockOff:
+ switchLed(LED_CAPSL, ka == QWSKeyboardHandler::CapsLockOn);
+ break;
+
+ case QWSKeyboardHandler::NumLockOn:
+ case QWSKeyboardHandler::NumLockOff:
+ switchLed(LED_NUML, ka == QWSKeyboardHandler::NumLockOn);
+ break;
+
+ case QWSKeyboardHandler::ScrollLockOn:
+ case QWSKeyboardHandler::ScrollLockOff:
+ switchLed(LED_SCROLLL, ka == QWSKeyboardHandler::ScrollLockOn);
+ break;
+
+ default:
+ // ignore console switching and reboot
+ break;
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdlinuxinput_qws.moc"
+
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdusb_qws.h b/src/gui/embedded/qkbdlinuxinput_qws.h
index 81d0103..5fa8214 100644
--- a/src/gui/embedded/qkbdusb_qws.h
+++ b/src/gui/embedded/qkbdlinuxinput_qws.h
@@ -39,10 +39,10 @@
**
****************************************************************************/
-#ifndef QKBDUSB_QWS_H
-#define QKBDUSB_QWS_H
+#ifndef QKBDLINUXINPUT_QWS_H
+#define QKBDLINUXINPUT_QWS_H
-#include <QtGui/qkbdpc101_qws.h>
+#include <QtGui/qkbd_qws.h>
QT_BEGIN_HEADER
@@ -52,21 +52,23 @@ QT_MODULE(Gui)
#ifndef QT_NO_QWS_KEYBOARD
-#ifndef QT_NO_QWS_KBD_USB
+#ifndef QT_NO_QWS_KBD_LINUXINPUT
-class QWSUsbKbPrivate;
+class QWSLinuxInputKbPrivate;
-class QWSUsbKeyboardHandler : public QWSPC101KeyboardHandler
+class QWSLinuxInputKeyboardHandler : public QWSKeyboardHandler
{
public:
- QWSUsbKeyboardHandler(const QString&);
- virtual ~QWSUsbKeyboardHandler();
+ QWSLinuxInputKeyboardHandler(const QString&);
+ virtual ~QWSLinuxInputKeyboardHandler();
+
+ virtual bool filterInputEvent(quint16 &input_code, qint32 &input_value);
private:
- QWSUsbKbPrivate *d;
+ QWSLinuxInputKbPrivate *d;
};
-#endif // QT_NO_QWS_KBD_USB
+#endif // QT_NO_QWS_KBD_LINUXINPUT
#endif // QT_NO_QWS_KEYBOARD
@@ -74,4 +76,4 @@ QT_END_NAMESPACE
QT_END_HEADER
-#endif // QKBDUSB_QWS_H
+#endif // QKBDLINUXINPUT_QWS_H
diff --git a/src/gui/embedded/qkbdpc101_qws.cpp b/src/gui/embedded/qkbdpc101_qws.cpp
deleted file mode 100644
index 3173645..0000000
--- a/src/gui/embedded/qkbdpc101_qws.cpp
+++ /dev/null
@@ -1,485 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkbdpc101_qws.h"
-
-#ifndef QT_NO_QWS_KEYBOARD
-
-#include "qscreen_qws.h"
-#include "qwindowsystem_qws.h"
-#include "qnamespace.h"
-#include "qapplication.h"
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#ifdef Q_OS_LINUX
-#include <sys/kd.h>
-#include <sys/vt.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-static const QWSKeyMap pc101KeyM[] = {
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Escape, 27 , 27 , 0xffff },
- { Qt::Key_1, '1' , '!' , 0xffff },
- { Qt::Key_2, '2' , '@' , 0xffff },
- { Qt::Key_3, '3' , '#' , 0xffff },
- { Qt::Key_4, '4' , '$' , 0xffff },
- { Qt::Key_5, '5' , '%' , 0xffff },
- { Qt::Key_6, '6' , '^' , 0xffff },
- { Qt::Key_7, '7' , '&' , 0xffff },
- { Qt::Key_8, '8' , '*' , 0xffff },
- { Qt::Key_9, '9' , '(' , 0xffff }, // 10
- { Qt::Key_0, '0' , ')' , 0xffff },
- { Qt::Key_Minus, '-' , '_' , 0xffff },
- { Qt::Key_Equal, '=' , '+' , 0xffff },
- { Qt::Key_Backspace, 8 , 8 , 0xffff },
- { Qt::Key_Tab, 9 , 9 , 0xffff },
- { Qt::Key_Q, 'q' , 'Q' , 'Q'-64 },
- { Qt::Key_W, 'w' , 'W' , 'W'-64 },
- { Qt::Key_E, 'e' , 'E' , 'E'-64 },
- { Qt::Key_R, 'r' , 'R' , 'R'-64 },
- { Qt::Key_T, 't' , 'T' , 'T'-64 }, // 20
- { Qt::Key_Y, 'y' , 'Y' , 'Y'-64 },
- { Qt::Key_U, 'u' , 'U' , 'U'-64 },
- { Qt::Key_I, 'i' , 'I' , 'I'-64 },
- { Qt::Key_O, 'o' , 'O' , 'O'-64 },
- { Qt::Key_P, 'p' , 'P' , 'P'-64 },
- { Qt::Key_BraceLeft, '[' , '{' , 0xffff },
- { Qt::Key_BraceRight, ']' , '}' , 0xffff },
- { Qt::Key_Return, 13 , 13 , 0xffff },
- { Qt::Key_Control, 0xffff , 0xffff , 0xffff },
- { Qt::Key_A, 'a' , 'A' , 'A'-64 }, // 30
- { Qt::Key_S, 's' , 'S' , 'S'-64 },
- { Qt::Key_D, 'd' , 'D' , 'D'-64 },
- { Qt::Key_F, 'f' , 'F' , 'F'-64 },
- { Qt::Key_G, 'g' , 'G' , 'G'-64 },
- { Qt::Key_H, 'h' , 'H' , 'H'-64 },
- { Qt::Key_J, 'j' , 'J' , 'J'-64 },
- { Qt::Key_K, 'k' , 'K' , 'K'-64 },
- { Qt::Key_L, 'l' , 'L' , 'L'-64 },
- { Qt::Key_Semicolon, ';' , ':' , 0xffff },
- { Qt::Key_Apostrophe, '\'' , '"' , 0xffff }, // 40
- { Qt::Key_QuoteLeft, '`' , '~' , 0xffff },
- { Qt::Key_Shift, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Backslash, '\\' , '|' , 0xffff },
- { Qt::Key_Z, 'z' , 'Z' , 'Z'-64 },
- { Qt::Key_X, 'x' , 'X' , 'X'-64 },
- { Qt::Key_C, 'c' , 'C' , 'C'-64 },
- { Qt::Key_V, 'v' , 'V' , 'V'-64 },
- { Qt::Key_B, 'b' , 'B' , 'B'-64 },
- { Qt::Key_N, 'n' , 'N' , 'N'-64 },
- { Qt::Key_M, 'm' , 'M' , 'M'-64 }, // 50
- { Qt::Key_Comma, ',' , '<' , 0xffff },
- { Qt::Key_Period, '.' , '>' , 0xffff },
- { Qt::Key_Slash, '/' , '?' , 0xffff },
- { Qt::Key_Shift, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Asterisk, '*' , '*' , 0xffff },
- { Qt::Key_Alt, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Space, ' ' , ' ' , 0xffff },
- { Qt::Key_CapsLock, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F1, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F2, 0xffff , 0xffff , 0xffff }, // 60
- { Qt::Key_F3, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F4, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F5, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F6, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F7, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F8, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F9, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F10, 0xffff , 0xffff , 0xffff },
- { Qt::Key_NumLock, 0xffff , 0xffff , 0xffff },
- { Qt::Key_ScrollLock, 0xffff , 0xffff , 0xffff }, // 70
- { Qt::Key_7, '7' , '7' , 0xffff },
- { Qt::Key_8, '8' , '8' , 0xffff },
- { Qt::Key_9, '9' , '9' , 0xffff },
- { Qt::Key_Minus, '-' , '-' , 0xffff },
- { Qt::Key_4, '4' , '4' , 0xffff },
- { Qt::Key_5, '5' , '5' , 0xffff },
- { Qt::Key_6, '6' , '6' , 0xffff },
- { Qt::Key_Plus, '+' , '+' , 0xffff },
- { Qt::Key_1, '1' , '1' , 0xffff },
- { Qt::Key_2, '2' , '2' , 0xffff }, // 80
- { Qt::Key_3, '3' , '3' , 0xffff },
- { Qt::Key_0, '0' , '0' , 0xffff },
- { Qt::Key_Period, '.' , '.' , 0xffff },
- { Qt::Key_SysReq, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Less, '<' , '>' , 0xffff },
- { Qt::Key_F11, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F12, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 90
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Enter, 13 , 13 , 0xffff },
- { Qt::Key_Control, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Slash, '/' , '/' , 0xffff },
- { Qt::Key_SysReq, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Meta, 0xffff , 0xffff , 0xffff }, // 100
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // break
- { Qt::Key_Home, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Up, 0xffff , 0xffff , 0xffff },
- { Qt::Key_PageUp, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Left, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Right, 0xffff , 0xffff , 0xffff },
- { Qt::Key_End, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Down, 0xffff , 0xffff , 0xffff },
- { Qt::Key_PageDown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Insert, 0xffff , 0xffff , 0xffff }, // 110
- { Qt::Key_Delete, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // macro
- { Qt::Key_F13, 0xffff , 0xffff , 0xffff },
- { Qt::Key_F14, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Help, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // do
- { Qt::Key_F17, 0xffff , 0xffff , 0xffff },
- { Qt::Key_Plus, '+' , '-' , 0xffff },
- { Qt::Key_Pause, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
- { 0, 0xffff , 0xffff , 0xffff }
-};
-
-static const int keyMSize = sizeof(pc101KeyM)/sizeof(QWSKeyMap)-1;
-
-//===========================================================================
-
-//
-// PC-101 type keyboards
-//
-
-/*!
- \class QWSPC101KeyboardHandler
- \ingroup qws
-
- \internal
-*/
-
-QWSPC101KeyboardHandler::QWSPC101KeyboardHandler(const QString&)
-{
- shift = false;
- alt = false;
- ctrl = false;
- extended = 0;
- prevuni = 0;
- prevkey = 0;
- caps = false;
-#if defined(QT_QWS_IPAQ)
- // iPAQ Action Key has ScanCode 0x60: 0x60|0x80 = 0xe0 == extended mode 1 !
- ipaq_return_pressed = false;
-#endif
-}
-
-QWSPC101KeyboardHandler::~QWSPC101KeyboardHandler()
-{
-}
-
-const QWSKeyMap *QWSPC101KeyboardHandler::keyMap() const
-{
- return pc101KeyM;
-}
-
-void QWSPC101KeyboardHandler::doKey(uchar code)
-{
-
- int keyCode = Qt::Key_unknown;
- bool release = false;
- int keypad = 0;
- bool softwareRepeat = false;
-
-#ifndef QT_QWS_USE_KEYCODES
- // extended?
- if (code == 224
-#if defined(QT_QWS_IPAQ)
- && !ipaq_return_pressed
-#endif
- ) {
- extended = 1;
- return;
- } else if (code == 225) {
- extended = 2;
- return;
- }
-#endif
-
- if (code & 0x80) {
- release = true;
- code &= 0x7f;
- }
-
-#ifndef QT_QWS_USE_KEYCODES
- if (extended == 1) {
- switch (code) {
- case 72:
- keyCode = Qt::Key_Up;
- break;
- case 75:
- keyCode = Qt::Key_Left;
- break;
- case 77:
- keyCode = Qt::Key_Right;
- break;
- case 80:
- keyCode = Qt::Key_Down;
- break;
- case 82:
- keyCode = Qt::Key_Insert;
- break;
- case 71:
- keyCode = Qt::Key_Home;
- break;
- case 73:
- keyCode = Qt::Key_PageUp;
- break;
- case 83:
- keyCode = Qt::Key_Delete;
- break;
- case 79:
- keyCode = Qt::Key_End;
- break;
- case 81:
- keyCode = Qt::Key_PageDown;
- break;
- case 28:
- keyCode = Qt::Key_Enter;
- break;
- case 53:
- keyCode = Qt::Key_Slash;
- break;
- case 0x1d:
- keyCode = Qt::Key_Control;
- break;
- case 0x2a:
- keyCode = Qt::Key_Print;
- break;
- case 0x38:
- keyCode = Qt::Key_Alt;
- break;
- case 0x5b:
- keyCode = Qt::Key_Super_L;
- break;
- case 0x5c:
- keyCode = Qt::Key_Super_R;
- break;
- case 0x5d:
- keyCode = Qt::Key_Menu;
- break;
-#if 0
- default:
- qDebug("extended1 code %x release %d", code, release);
- break;
-#endif
- }
- } else if (extended == 2) {
- switch (code) {
- case 0x1d:
- return;
- case 0x45:
- keyCode = Qt::Key_Pause;
- break;
- }
- } else
-#endif
- {
- if (code < keyMSize) {
- keyCode = pc101KeyM[code].key_code;
- }
-
-#if defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX)
- softwareRepeat = true;
-
- switch (code) {
- case 0x7a: case 0x7b: case 0x7c: case 0x7d:
- keyCode = code - 0x7a + Qt::Key_F9;
- softwareRepeat = false;
- break;
- case 0x79:
- keyCode = Qt::Key_SysReq;
- softwareRepeat = false;
- break;
- case 0x78:
-# ifdef QT_QWS_IPAQ
- keyCode = Qt::Key_F24; // record
-# else
- keyCode = Qt::Key_Escape;
-# endif
- softwareRepeat = false;
- break;
- case 0x60:
- keyCode = Qt::Key_Return;
-# ifdef QT_QWS_IPAQ
- ipaq_return_pressed = !release;
-# endif
- break;
- case 0x67:
- keyCode = Qt::Key_Right;
- break;
- case 0x69:
- keyCode = Qt::Key_Up;
- break;
- case 0x6a:
- keyCode = Qt::Key_Down;
- break;
- case 0x6c:
- keyCode = Qt::Key_Left;
- break;
- }
-
- if (qt_screen->isTransformed()
- && keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down)
- {
- keyCode = transformDirKey(keyCode);
- }
-#endif
- /*
- Translate shift+Qt::Key_Tab to Qt::Key_Backtab
- */
- if ((keyCode == Qt::Key_Tab) && shift)
- keyCode = Qt::Key_Backtab;
- }
-
-#ifndef QT_QWS_USE_KEYCODES
- /*
- Qt::Keypad consists of extended keys 53 and 28,
- and non-extended keys 55 and 71 through 83.
- */
- if ((extended == 1) ? (code == 53 || code == 28) :
- (code == 55 || (code >= 71 && code <= 83)))
-#else
- if (code == 55 || code >= 71 && code <= 83 || code == 96
- || code == 98 || code == 118)
-#endif
- {
- keypad = Qt::KeypadModifier;
- }
-
- // Ctrl-Alt-Backspace exits qws
- if (ctrl && alt && keyCode == Qt::Key_Backspace) {
- qApp->quit();
- }
-
- if (keyCode == Qt::Key_Alt) {
- alt = !release;
- } else if (keyCode == Qt::Key_Control) {
- ctrl = !release;
- } else if (keyCode == Qt::Key_Shift) {
- shift = !release;
- } else if (keyCode == Qt::Key_CapsLock && release) {
- caps = !caps;
-#if defined(Q_OS_LINUX)
- char leds;
- ioctl(0, KDGETLED, &leds);
- leds = leds & ~LED_CAP;
- if (caps) leds |= LED_CAP;
- ioctl(0, KDSETLED, leds);
-#endif
- }
- if (keyCode != Qt::Key_unknown) {
- bool bAlt = alt;
- bool bCtrl = ctrl;
- bool bShift = shift;
- int unicode = 0;
- if (code < keyMSize) {
- if (!extended) {
- bool bCaps = shift ||
- (caps ? QChar(keyMap()[code].unicode).isLetter() : false);
- if (bCtrl)
- unicode = keyMap()[code].ctrl_unicode ? keyMap()[code].ctrl_unicode : 0xffff;
- else if (bCaps)
- unicode = keyMap()[code].shift_unicode ? keyMap()[code].shift_unicode : 0xffff;
- else
- unicode = keyMap()[code].unicode ? keyMap()[code].unicode : 0xffff;
-#ifndef QT_QWS_USE_KEYCODES
- } else if (extended==1) {
- if (code == 53)
- unicode = '/';
-#endif
- }
- }
-
- modifiers = 0;
- if (bAlt) modifiers |= Qt::AltModifier;
- if (bCtrl) modifiers |= Qt::ControlModifier;
- if (bShift) modifiers |= Qt::ShiftModifier;
- if (keypad) modifiers |= Qt::KeypadModifier;
-
- // looks wrong -- WWA
- bool repeat = false;
- if (prevuni == unicode && prevkey == keyCode && !release)
- repeat = true;
-
- processKeyEvent(unicode, keyCode, modifiers, !release, repeat);
-
- if (!release) {
- prevuni = unicode;
- prevkey = keyCode;
- } else {
- prevkey = prevuni = 0;
- }
- }
-
- if (softwareRepeat && !release)
- beginAutoRepeat(prevuni, prevkey, modifiers);
- else
- endAutoRepeat();
-
- extended = 0;
-}
-
-QT_END_NAMESPACE
-
-#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdsl5000_qws.cpp b/src/gui/embedded/qkbdsl5000_qws.cpp
index bc412b6..1e8095e 100644
--- a/src/gui/embedded/qkbdsl5000_qws.cpp
+++ b/src/gui/embedded/qkbdsl5000_qws.cpp
@@ -195,6 +195,13 @@ static const int keyMSize = sizeof(sl5000KeyMap)/sizeof(QWSKeyMap)-1;
QWSSL5000KeyboardHandler::QWSSL5000KeyboardHandler(const QString &device)
: QWSTtyKeyboardHandler(device)
{
+ shift = false;
+ alt = false;
+ ctrl = false;
+ extended = 0;
+ prevuni = 0;
+ prevkey = 0;
+ caps = false;
meta = false;
fn = false;
numLock = false;
@@ -220,7 +227,7 @@ const QWSKeyMap *QWSSL5000KeyboardHandler::keyMap() const
return sl5000KeyMap;
}
-void QWSSL5000KeyboardHandler::doKey(uchar code)
+bool QWSSL5000KeyboardHandler::filterKeycode(char &code)
{
int keyCode = Qt::Key_unknown;
bool release = false;
@@ -239,19 +246,19 @@ void QWSSL5000KeyboardHandler::doKey(uchar code)
else if (code == 0x52) { unicode='Z'-'@'; scan=Qt::Key_Z; } // Undo
if (scan) {
processKeyEvent(unicode, scan, Qt::ControlModifier, !release, false);
- return;
+ return true;
}
}
if (code < keyMSize) {
- keyCode = keyMap()[code].key_code;
+ keyCode = keyMap()[int(code)].key_code;
}
bool repeatable = true;
if (release && (keyCode == Qt::Key_F34 || keyCode == Qt::Key_F35))
- return; // no release for power and light keys
- if (keyCode >= Qt::Key_F1 && keyCode <= Qt::Key_F35
+ return true; // no release for power and light keys
+ if ((keyCode >= Qt::Key_F1 && keyCode <= Qt::Key_F35)
|| keyCode == Qt::Key_Escape || keyCode == Qt::Key_Home
|| keyCode == Qt::Key_Shift || keyCode == Qt::Key_Meta)
repeatable = false;
@@ -318,11 +325,11 @@ void QWSSL5000KeyboardHandler::doKey(uchar code)
keyCode = Qt::Key_QuoteLeft;
unicode = '`';
} else if (bCtrl)
- unicode = keyMap()[code].ctrl_unicode ? keyMap()[code].ctrl_unicode : 0xffff;
+ unicode = keyMap()[int(code)].ctrl_unicode ? keyMap()[int(code)].ctrl_unicode : 0xffff;
else if (bCaps)
- unicode = keyMap()[code].shift_unicode ? keyMap()[code].shift_unicode : 0xffff;
+ unicode = keyMap()[int(code)].shift_unicode ? keyMap()[int(code)].shift_unicode : 0xffff;
else
- unicode = keyMap()[code].unicode ? keyMap()[code].unicode : 0xffff;
+ unicode = keyMap()[int(code)].unicode ? keyMap()[int(code)].unicode : 0xffff;
}
modifiers = 0;
@@ -349,6 +356,8 @@ void QWSSL5000KeyboardHandler::doKey(uchar code)
beginAutoRepeat(prevuni, prevkey, modifiers);
else
endAutoRepeat();
+
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/gui/embedded/qkbdsl5000_qws.h b/src/gui/embedded/qkbdsl5000_qws.h
index 514d602..a96e038 100644
--- a/src/gui/embedded/qkbdsl5000_qws.h
+++ b/src/gui/embedded/qkbdsl5000_qws.h
@@ -52,7 +52,13 @@ QT_MODULE(Gui)
#ifndef QT_NO_QWS_KBD_SL5000
-class QWSSL5000KbPrivate;
+struct QWSKeyMap {
+ uint key_code;
+ ushort unicode;
+ ushort shift_unicode;
+ ushort ctrl_unicode;
+};
+
class QWSSL5000KeyboardHandler : public QWSTtyKeyboardHandler
{
@@ -60,14 +66,21 @@ public:
explicit QWSSL5000KeyboardHandler(const QString&);
virtual ~QWSSL5000KeyboardHandler();
- virtual void doKey(uchar scancode);
+ bool filterKeycode(char &keycode);
virtual const QWSKeyMap *keyMap() const;
private:
+ bool shift;
+ bool alt;
+ bool ctrl;
+ bool caps;
+ uint extended:2;
+ Qt::KeyboardModifiers modifiers;
+ int prevuni;
+ int prevkey;
bool meta;
bool fn;
bool numLock;
- QWSSL5000KbPrivate *d;
};
#endif // QT_NO_QWS_KBD_SL5000
diff --git a/src/gui/embedded/qkbdtty_qws.cpp b/src/gui/embedded/qkbdtty_qws.cpp
index 7c162bc..7f10e14 100644
--- a/src/gui/embedded/qkbdtty_qws.cpp
+++ b/src/gui/embedded/qkbdtty_qws.cpp
@@ -43,65 +43,58 @@
#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_TTY)
-#include "qscreen_qws.h"
-
-#include "qwindowsystem_qws.h"
-#include "qapplication.h"
-#include "qsocketnotifier.h"
-#include "qnamespace.h"
-#include "qtimer.h"
-#include <private/qwssignalhandler_p.h>
-#include <private/qwindowsurface_qws_p.h>
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-#include <termios.h>
+#include <QSocketNotifier>
+#include <QStringList>
-#include <qeventloop.h>
+#include <qplatformdefs.h>
-#ifdef Q_OS_LINUX
-#include <sys/kd.h>
-#include <sys/vt.h>
-#endif
+#include <errno.h>
+#include <termios.h>
-QT_BEGIN_NAMESPACE
+#if defined Q_OS_LINUX
+# include <linux/kd.h>
+# include <linux/vt.h> //TODO: move vt handling somewhere else (QLinuxFbScreen?)
-#define VTACQSIG SIGUSR1
-#define VTRELSIG SIGUSR2
+# include "qscreen_qws.h"
+# include "qwindowsystem_qws.h"
+# include "qapplication.h"
+# include "private/qwindowsurface_qws_p.h"
+# include "private/qwssignalhandler_p.h"
-static int vtQws = 0;
-static int kbdFD = -1;
+# define VTACQSIG SIGUSR1
+# define VTRELSIG SIGUSR2
+#endif
-//===========================================================================
-//
-// Tty keyboard
-//
+QT_BEGIN_NAMESPACE
class QWSTtyKbPrivate : public QObject
{
Q_OBJECT
public:
- QWSTtyKbPrivate(QWSPC101KeyboardHandler *, const QString &device);
+ QWSTtyKbPrivate(QWSTtyKeyboardHandler *handler, const QString &device);
~QWSTtyKbPrivate();
-private slots:
- void readKeyboardData();
- void handleTtySwitch(int);
+private:
+ void switchLed(char, bool);
+ void switchConsole(int vt);
+
+private Q_SLOTS:
+ void readKeycode();
+ void handleConsoleSwitch(int sig);
private:
- QWSPC101KeyboardHandler *handler;
- struct termios origTermData;
- int originalKbdMode;
+ QWSTtyKeyboardHandler *m_handler;
+ int m_tty_fd;
+ struct termios m_tty_attr;
+ char m_last_keycode;
+ int m_vt_qws;
+ int m_originalKbdMode;
};
+
QWSTtyKeyboardHandler::QWSTtyKeyboardHandler(const QString &device)
- : QWSPC101KeyboardHandler(device)
+ : QWSKeyboardHandler(device)
{
d = new QWSTtyKbPrivate(this, device);
}
@@ -111,60 +104,66 @@ QWSTtyKeyboardHandler::~QWSTtyKeyboardHandler()
delete d;
}
-void QWSTtyKeyboardHandler::processKeyEvent(int unicode, int keycode,
- Qt::KeyboardModifiers modifiers, bool isPress,
- bool autoRepeat)
+bool QWSTtyKeyboardHandler::filterKeycode(char &)
{
-#if defined(Q_OS_LINUX)
- // Virtual console switching
- int term = 0;
- bool ctrl = modifiers & Qt::ControlModifier;
- bool alt = modifiers & Qt::AltModifier;
- if (ctrl && alt && keycode >= Qt::Key_F1 && keycode <= Qt::Key_F10)
- term = keycode - Qt::Key_F1 + 1;
- else if (ctrl && alt && keycode == Qt::Key_Left)
- term = qMax(vtQws - 1, 1);
- else if (ctrl && alt && keycode == Qt::Key_Right)
- term = qMin(vtQws + 1, 10);
- if (term && isPress) {
- ioctl(kbdFD, VT_ACTIVATE, term);
- return;
- }
-#endif
-
- QWSPC101KeyboardHandler::processKeyEvent(unicode, keycode, modifiers,
- isPress, autoRepeat);
+ return false;
}
-
-QWSTtyKbPrivate::QWSTtyKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
+QWSTtyKbPrivate::QWSTtyKbPrivate(QWSTtyKeyboardHandler *h, const QString &device)
+ : m_handler(h), m_tty_fd(-1), m_last_keycode(0), m_vt_qws(0)
{
- kbdFD = ::open(device.isEmpty()?"/dev/tty0":device.toLatin1().constData(), O_RDWR|O_NDELAY, 0);
+ setObjectName(QLatin1String("TTY Keyboard Handler"));
#ifndef QT_NO_QWS_SIGNALHANDLER
QWSSignalHandler::instance()->addObject(this);
#endif
- if (kbdFD >= 0) {
+ QString dev = QLatin1String("/dev/tty0");
+ int repeat_delay = -1;
+ int repeat_rate = -1;
+
+ QStringList args = device.split(QLatin1Char(':'));
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("repeat-delay=")))
+ repeat_delay = arg.mid(13).toInt();
+ else if (arg.startsWith(QLatin1String("repeat-rate=")))
+ repeat_rate = arg.mid(12).toInt();
+ else if (arg.startsWith(QLatin1String("/dev/")))
+ dev = arg;
+ }
+
+ m_tty_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0);
+ if (m_tty_fd >= 0) {
+ if (repeat_delay > 0 && repeat_rate > 0) {
+#if defined(Q_OS_LINUX)
+ struct ::kbd_repeat kbdrep = { repeat_delay, repeat_rate };
+ ::ioctl(m_tty_fd, KDKBDREP, &kbdrep);
+#endif
+ }
+
QSocketNotifier *notifier;
- notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)),this,
- SLOT(readKeyboardData()));
+ notifier = new QSocketNotifier(m_tty_fd, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode()));
- // save for restore.
- tcgetattr(kbdFD, &origTermData);
+ // save tty config for restore.
+ tcgetattr(m_tty_fd, &m_tty_attr);
- struct termios termdata;
- tcgetattr(kbdFD, &termdata);
+ struct ::termios termdata;
+ tcgetattr(m_tty_fd, &termdata);
#if defined(Q_OS_LINUX)
- ioctl(kbdFD, KDGKBMODE, &originalKbdMode);
-# ifdef QT_QWS_USE_KEYCODES
- ioctl(kbdFD, KDSKBMODE, K_MEDIUMRAW);
-# else
- ioctl(kbdFD, KDSKBMODE, K_RAW);
-# endif
+ // record the original mode so we can restore it again in the constructor
+ ::ioctl(m_tty_fd, KDGKBMODE, m_originalKbdMode);
+
+ // PLEASE NOTE:
+ // The tty keycode interface can only report keycodes 0x01 .. 0x7f
+ // KEY_MAX is however defined to 0x1ff. In practice this is sufficient
+ // for a PC style keyboard though.
+ // we don't support K_RAW anymore - if you need, you habe to add a
+ // scan- to keycode converter.
+ ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW);
#endif
+ // set the tty layer to pass-through
termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP);
termdata.c_oflag = 0;
termdata.c_cflag = CREAD | CS8;
@@ -173,50 +172,145 @@ QWSTtyKbPrivate::QWSTtyKbPrivate(QWSPC101KeyboardHandler *h, const QString &devi
termdata.c_cc[VMIN]=1;
cfsetispeed(&termdata, 9600);
cfsetospeed(&termdata, 9600);
- tcsetattr(kbdFD, TCSANOW, &termdata);
+ tcsetattr(m_tty_fd, TCSANOW, &termdata);
#if defined(Q_OS_LINUX)
-
- connect(QApplication::instance(), SIGNAL(unixSignal(int)), this, SLOT(handleTtySwitch(int)));
+ // VT switching is handled via unix signals
+ connect(QApplication::instance(), SIGNAL(unixSignal(int)), this, SLOT(handleConsoleSwitch(int)));
QApplication::instance()->watchUnixSignal(VTACQSIG, true);
QApplication::instance()->watchUnixSignal(VTRELSIG, true);
- struct vt_mode vtMode;
- ioctl(kbdFD, VT_GETMODE, &vtMode);
+ struct ::vt_mode vtMode;
+ if (::ioctl(m_tty_fd, VT_GETMODE, &vtMode) == 0) {
+ vtMode.mode = VT_PROCESS;
+ vtMode.relsig = VTRELSIG;
+ vtMode.acqsig = VTACQSIG;
- // let us control VT switching
- vtMode.mode = VT_PROCESS;
- vtMode.relsig = VTRELSIG;
- vtMode.acqsig = VTACQSIG;
- ioctl(kbdFD, VT_SETMODE, &vtMode);
+ if (::ioctl(m_tty_fd, VT_SETMODE, &vtMode) == 0) {
+ struct ::vt_stat vtStat;
+ ::memset(&vtStat, 0, sizeof(vtStat));
- struct vt_stat vtStat;
- ioctl(kbdFD, VT_GETSTATE, &vtStat);
- vtQws = vtStat.v_active;
+ if (::ioctl(m_tty_fd, VT_GETSTATE, &vtStat) == 0 ) {
+ m_vt_qws = vtStat.v_active;
+ }
+ }
+ }
+
+ if (!m_vt_qws)
+ qWarning("Could not initialize virtual console switching");
#endif
} else {
- qCritical("Cannot open keyboard: %s", strerror(errno));
+ qWarning("Cannot open input device '%s': %s", qPrintable(dev), strerror(errno));
+ return;
}
}
QWSTtyKbPrivate::~QWSTtyKbPrivate()
{
- if (kbdFD >= 0) {
+ if (m_tty_fd >= 0) {
#if defined(Q_OS_LINUX)
- ioctl(kbdFD, KDSKBMODE, originalKbdMode);
+ ::ioctl(m_tty_fd, KDSKBMODE, m_originalKbdMode);
#endif
- tcsetattr(kbdFD, TCSANOW, &origTermData);
- ::close(kbdFD);
- kbdFD = -1;
+ tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr);
}
}
-void QWSTtyKbPrivate::handleTtySwitch(int sig)
+
+
+void QWSTtyKbPrivate::switchLed(char led, bool state)
{
#if defined(Q_OS_LINUX)
+ char ledstate;
+
+ ::ioctl(m_tty_fd, KDGETLED, &ledstate);
+ if (state)
+ ledstate |= led;
+ else
+ ledstate &= ~led;
+ ::ioctl(m_tty_fd, KDSETLED, ledstate);
+#endif
+}
+
+void QWSTtyKbPrivate::readKeycode()
+{
+ char buffer[32];
+ int n = 0;
+
+ forever {
+ n = QT_READ(m_tty_fd, buffer + n, 32 - n);
+
+ if (n == 0) {
+ qWarning("Got EOF from the input device.");
+ return;
+ } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) {
+ qWarning("Could not read from input device: %s", strerror(errno));
+ return;
+ } else {
+ break;
+ }
+ }
+
+ for (int i = 0; i < n; ++i) {
+ if (m_handler->filterKeycode(buffer[i]))
+ continue;
+
+ QWSKeyboardHandler::KeycodeAction ka;
+ ka = m_handler->processKeycode(buffer[i] & 0x7f, (buffer[i] & 0x80) == 0x00, buffer[i] == m_last_keycode);
+ m_last_keycode = buffer[i];
+
+ switch (ka) {
+ case QWSKeyboardHandler::CapsLockOn:
+ case QWSKeyboardHandler::CapsLockOff:
+ switchLed(LED_CAP, ka == QWSKeyboardHandler::CapsLockOn);
+ break;
+
+ case QWSKeyboardHandler::NumLockOn:
+ case QWSKeyboardHandler::NumLockOff:
+ switchLed(LED_NUM, ka == QWSKeyboardHandler::NumLockOn);
+ break;
+
+ case QWSKeyboardHandler::ScrollLockOn:
+ case QWSKeyboardHandler::ScrollLockOff:
+ switchLed(LED_SCR, ka == QWSKeyboardHandler::ScrollLockOn);
+ break;
+
+ case QWSKeyboardHandler::PreviousConsole:
+ switchConsole(qBound(1, m_vt_qws - 1, 10));
+ break;
+
+ case QWSKeyboardHandler::NextConsole:
+ switchConsole(qBound(1, m_vt_qws + 1, 10));
+ break;
+
+ default:
+ if (ka >= QWSKeyboardHandler::SwitchConsoleFirst &&
+ ka <= QWSKeyboardHandler::SwitchConsoleLast) {
+ switchConsole(1 + (ka & QWSKeyboardHandler::SwitchConsoleMask));
+ }
+ //ignore reboot
+ break;
+ }
+ }
+}
+
+
+void QWSTtyKbPrivate::switchConsole(int vt)
+{
+#if defined(Q_OS_LINUX)
+ if (m_vt_qws && vt && (m_tty_fd >= 0 ))
+ ::ioctl(m_tty_fd, VT_ACTIVATE, vt);
+#endif
+}
+
+void QWSTtyKbPrivate::handleConsoleSwitch(int sig)
+{
+#if defined(Q_OS_LINUX)
+ // received a notification from the kernel that the current VT is
+ // changing: either enable or disable QWS painting accordingly.
+
if (sig == VTACQSIG) {
- if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
+ if (::ioctl(m_tty_fd, VT_RELDISP, VT_ACKACQ) == 0) {
qwsServer->enablePainting(true);
qt_screen->restore();
qwsServer->resumeMouse();
@@ -238,9 +332,9 @@ void QWSTtyKbPrivate::handleTtySwitch(int sig)
}
if (!allWindowsHidden) {
- ioctl(kbdFD, VT_RELDISP, 0); // abort console switch
+ ::ioctl(m_tty_fd, VT_RELDISP, 0); // abort console switch
qwsServer->enablePainting(true);
- } else if (ioctl(kbdFD, VT_RELDISP, 1) == 0) {
+ } else if (::ioctl(m_tty_fd, VT_RELDISP, 1) == 0) {
qt_screen->save();
qwsServer->suspendMouse();
} else {
@@ -250,14 +344,6 @@ void QWSTtyKbPrivate::handleTtySwitch(int sig)
#endif
}
-void QWSTtyKbPrivate::readKeyboardData()
-{
- unsigned char buf[81];
- int n = read(kbdFD, buf, 80);
- for (int loop = 0; loop < n; loop++)
- handler->doKey(buf[loop]);
-}
-
QT_END_NAMESPACE
#include "qkbdtty_qws.moc"
diff --git a/src/gui/embedded/qkbdtty_qws.h b/src/gui/embedded/qkbdtty_qws.h
index 4f93d6c..fc3eaa1 100644
--- a/src/gui/embedded/qkbdtty_qws.h
+++ b/src/gui/embedded/qkbdtty_qws.h
@@ -42,7 +42,7 @@
#ifndef QKBDTTY_QWS_H
#define QKBDTTY_QWS_H
-#include <QtGui/qkbdpc101_qws.h>
+#include <QtGui/qkbd_qws.h>
QT_BEGIN_HEADER
@@ -56,15 +56,13 @@ QT_MODULE(Gui)
class QWSTtyKbPrivate;
-class QWSTtyKeyboardHandler : public QWSPC101KeyboardHandler
+class QWSTtyKeyboardHandler : public QWSKeyboardHandler
{
public:
explicit QWSTtyKeyboardHandler(const QString&);
virtual ~QWSTtyKeyboardHandler();
-protected:
- virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
- bool isPress, bool autoRepeat);
+ virtual bool filterKeycode(char &code);
private:
QWSTtyKbPrivate *d;
diff --git a/src/gui/embedded/qkbdum_qws.cpp b/src/gui/embedded/qkbdum_qws.cpp
index d525c66..fa05d6c 100644
--- a/src/gui/embedded/qkbdum_qws.cpp
+++ b/src/gui/embedded/qkbdum_qws.cpp
@@ -54,6 +54,7 @@
#include <qstring.h>
#include <qwindowsystem_qws.h>
#include <qsocketnotifier.h>
+#include "qplatformdefs.h"
QT_BEGIN_NAMESPACE
@@ -81,13 +82,13 @@ QWSUmKeyboardHandlerPrivate::QWSUmKeyboardHandlerPrivate(const QString &device)
{
kbdBuffer = new unsigned char [kbdBufferLen];
- if ((kbdFD = open((const char *)device.toLocal8Bit(), O_RDONLY | O_NDELAY)) < 0) {
+ if ((kbdFD = QT_OPEN((const char *)device.toLocal8Bit(), O_RDONLY | O_NDELAY, 0)) < 0) {
qDebug("Cannot open %s (%s)", (const char *)device.toLocal8Bit(),
strerror(errno));
} else {
// Clear pending input
char buf[2];
- while (read(kbdFD, buf, 1) > 0) { }
+ while (QT_READ(kbdFD, buf, 1) > 0) { }
notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
@@ -97,7 +98,7 @@ QWSUmKeyboardHandlerPrivate::QWSUmKeyboardHandlerPrivate(const QString &device)
QWSUmKeyboardHandlerPrivate::~QWSUmKeyboardHandlerPrivate()
{
if (kbdFD >= 0)
- close(kbdFD);
+ QT_CLOSE(kbdFD);
delete [] kbdBuffer;
}
@@ -106,7 +107,7 @@ void QWSUmKeyboardHandlerPrivate::readKeyboardData()
{
int n;
do {
- n = read(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
+ n = QT_READ(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
if (n > 0)
kbdIdx += n;
} while (n > 0);
diff --git a/src/gui/embedded/qkbdusb_qws.cpp b/src/gui/embedded/qkbdusb_qws.cpp
deleted file mode 100644
index e35ac55..0000000
--- a/src/gui/embedded/qkbdusb_qws.cpp
+++ /dev/null
@@ -1,401 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qkbdusb_qws.h"
-
-#ifndef QT_NO_QWS_KEYBOARD
-
-#include "qscreen_qws.h"
-
-#include "qwindowsystem_qws.h"
-#include "qapplication.h"
-#include "qsocketnotifier.h"
-#include "qnamespace.h"
-#include "qtimer.h"
-
-#include <unistd.h>
-#include <sys/ioctl.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <signal.h>
-
-#include <linux/input.h>
-
-#ifdef Q_OS_LINUX
-#include <sys/kd.h>
-#include <sys/vt.h>
-#endif
-
-QT_BEGIN_NAMESPACE
-
-/* USB driver */
-
-
-class QWSUsbKbPrivate : public QObject
-{
- Q_OBJECT
-public:
- QWSUsbKbPrivate(QWSPC101KeyboardHandler *, const QString &);
- ~QWSUsbKbPrivate();
-
-private slots:
- void readKeyboardData();
-
-private:
- QWSPC101KeyboardHandler *handler;
- int fd;
-#ifdef QT_QWS_ZYLONITE
- bool shift;
-#endif
-};
-
-QWSUsbKeyboardHandler::QWSUsbKeyboardHandler(const QString &device)
- : QWSPC101KeyboardHandler(device)
-{
- d = new QWSUsbKbPrivate(this, device);
-}
-
-QWSUsbKeyboardHandler::~QWSUsbKeyboardHandler()
-{
- delete d;
-}
-
-QWSUsbKbPrivate::QWSUsbKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
-{
-#ifdef QT_QWS_ZYLONITE
- shift = FALSE;
-#endif
- fd = ::open(device.isEmpty()?"/dev/input/event1":device.toLocal8Bit(),O_RDONLY, 0);
- if (fd >= 0) {
- QSocketNotifier *notifier;
- notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
- connect(notifier, SIGNAL(activated(int)),this,
- SLOT(readKeyboardData()));
- }
-}
-
-QWSUsbKbPrivate::~QWSUsbKbPrivate()
-{
- ::close(fd);
-}
-
-void QWSUsbKbPrivate::readKeyboardData()
-{
- input_event event;
- if (read(fd, &event, sizeof(input_event)) != sizeof(input_event))
- return;
-
- if (event.type != EV_KEY)
- return;
-
-#ifdef QT_QWS_ZYLONITE
- qDebug("keypressed: code=%03d (%s)\n",event.code,((event.value)!=0) ? "Down":"Up");
- int modifiers=0;
- int unicode=0xffff;
- int key_code=0;
-
- switch(event.code)
- {
- case 0xA2:
- key_code = ((!shift) ? Qt::Key_0 : Qt::Key_Plus );
- unicode = ((!shift) ? 0x30 : 0x2B );
- break;
- case 0x70:
- key_code = ((!shift) ? Qt::Key_1 : Qt::Key_At );
- unicode = ((!shift) ? 0x31 : 0x40 );
- break;
- case 0x72:
- key_code = ((!shift) ? Qt::Key_2 : Qt::Key_Ampersand );
- unicode = ((!shift) ? 0x32 : 0x26 );
- break;
- case 0x74:
- key_code = ((!shift) ? Qt::Key_3 : Qt::Key_At );
- unicode = ((!shift) ? 0x33 : 0x3F );
- break;
- case 0x80:
- key_code = ((!shift) ? Qt::Key_4 : Qt::Key_Minus );
- unicode = ((!shift) ? 0x34 : 0x2D );
- break;
- case 0x82:
- key_code = ((!shift) ? Qt::Key_5 : Qt::Key_Apostrophe);
- unicode = ((!shift) ? 0x35 : 0x27 );
- break;
- case 0x84:
- key_code = ((!shift) ? Qt::Key_6 : Qt::Key_Slash );
- unicode = ((!shift) ? 0x36 : 0x5C );
- break;
- case 0x90:
- key_code = ((!shift) ? Qt::Key_7 : Qt::Key_Colon );
- unicode = ((!shift) ? 0x37 : 0x3A );
- break;
- case 0x92:
- key_code = ((!shift) ? Qt::Key_8 : Qt::Key_Semicolon );
- unicode = ((!shift) ? 0x38 : 0x3B );
- break;
- case 0x94:
- key_code = ((!shift) ? Qt::Key_9 : Qt::Key_QuoteDbl );
- unicode = ((!shift) ? 0x39 : 0x22 );
- break;
- case 0x0:
- key_code = Qt::Key_A;
- unicode = ((!shift) ? 0x61 : 0x41 );
- break;
- case 0x10:
- key_code = Qt::Key_B;
- unicode = ((!shift) ? 0x62 : 0x42 );
- break;
- case 0x20:
- key_code = Qt::Key_C;
- unicode = ((!shift) ? 0x63 : 0x43 );
- break;
- case 0x30:
- key_code = Qt::Key_D;
- unicode = ((!shift) ? 0x64 : 0x44 );
- break;
- case 0x40:
- key_code = Qt::Key_E;
- unicode = ((!shift) ? 0x65 : 0x45 );
- break;
- case 0x50:
- key_code = Qt::Key_F;
- unicode = ((!shift) ? 0x66 : 0x46 );
- break;
- case 0x01:
- key_code = Qt::Key_G;
- unicode = ((!shift) ? 0x67 : 0x47 );
- break;
- case 0x11:
- key_code = Qt::Key_H;
- unicode = ((!shift) ? 0x68 : 0x48 );
- break;
- case 0x21:
- key_code = Qt::Key_I;
- unicode = ((!shift) ? 0x69 : 0x49 );
- break;
- case 0x31:
- key_code = Qt::Key_J;
- unicode = ((!shift) ? 0x6A : 0x4A );
- break;
- case 0x41:
- key_code = Qt::Key_K;
- unicode = ((!shift) ? 0x6B : 0x4B );
- break;
- case 0x51:
- key_code = Qt::Key_L;
- unicode = ((!shift) ? 0x6C : 0x4C );
- break;
- case 0x02:
- key_code = Qt::Key_M;
- unicode = ((!shift) ? 0x6D : 0x4D );
- break;
- case 0x12:
- key_code = Qt::Key_N;
- unicode = ((!shift) ? 0x6E : 0x4E );
- break;
- case 0x22:
- key_code = Qt::Key_O;
- unicode = ((!shift) ? 0x6F : 0x4F );
- break;
- case 0x32:
- key_code = Qt::Key_P;
- unicode = ((!shift) ? 0x70 : 0x50 );
- break;
- case 0x42:
- key_code = Qt::Key_Q;
- unicode = ((!shift) ? 0x71 : 0x51 );
- break;
- case 0x52:
- key_code = Qt::Key_R;
- unicode = ((!shift) ? 0x72 : 0x52 );
- break;
- case 0x03:
- key_code = Qt::Key_S;
- unicode = ((!shift) ? 0x73 : 0x53 );
- break;
- case 0x13:
- key_code = Qt::Key_T;
- unicode = ((!shift) ? 0x74 : 0x54 );
- break;
- case 0x23:
- key_code = Qt::Key_U;
- unicode = ((!shift) ? 0x75 : 0x55 );
- break;
- case 0x33:
- key_code = Qt::Key_V;
- unicode = ((!shift) ? 0x76 : 0x56 );
- break;
- case 0x43:
- key_code = Qt::Key_W;
- unicode = ((!shift) ? 0x77 : 0x57 );
- break;
- case 0x53:
- key_code = Qt::Key_X;
- unicode = ((!shift) ? 0x78 : 0x58 );
- break;
- case 0x24:
- key_code = Qt::Key_Y;
- unicode = ((!shift) ? 0x79 : 0x59 );
- break;
- case 0x34:
- key_code = Qt::Key_Z;
- unicode = ((!shift) ? 0x7A : 0x5A );
- break;
- case 0xA4:
- key_code = ((!shift) ? Qt::Key_NumberSign : Qt::Key_Period);
- unicode = ((!shift) ? 0x23 : 0x2E );
- break;
- case 0xA0:
- key_code = ((!shift) ? Qt::Key_Asterisk : Qt::Key_NumberSign );
- unicode = ((!shift) ? 0x2A : 0x2C );
- break;
- case 0x25:
- key_code = Qt::Key_Space;
- unicode = 0x20;
- break;
- case 0x06:
- key_code = Qt::Key_Up;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x16:
- key_code = Qt::Key_Down;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x26:
- key_code = Qt::Key_Left;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x36:
- key_code = Qt::Key_Right;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x46:
- key_code = Qt::Key_Select;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x61:
- key_code = Qt::Key_No;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x60:
- key_code = Qt::Key_Call;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x55:
- key_code = Qt::Key_Hangup;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x62:
- key_code = Qt::Key_Context1;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x63:
- key_code = Qt::Key_No;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x05:
- key_code = Qt::Key_Home;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x15:
- key_code = Qt::Key_Shift;
- unicode = 0xffff; modifiers |= Qt::ShiftModifier;
- if(event.value==0) break;
- if(shift) {
- shift = FALSE;
- qWarning("Caps Off!");
- } else {
- shift = TRUE;
- qWarning("Caps On!");
- }
- break;
- case 0x1C:
- key_code = ((!shift) ? Qt::Key_Back : Qt::Key_Enter );
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x19:
- key_code = Qt::Key_Context2;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x1A:
- key_code = Qt::Key_Context3;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- case 0x1B:
- key_code = Qt::Key_Context4;
- unicode = 0xffff; modifiers |= Qt::KeypadModifier;
- break;
- }
- if(shift) modifiers |= Qt::ShiftModifier;
- handler->processKeyEvent(unicode, key_code, (Qt::KeyboardModifiers)modifiers, event.value!=0, false);
-#else
-
- int key=event.code;
-#ifndef QT_QWS_USE_KEYCODES
- // Handle SOME keys, otherwise it's useless.
-
- if(key==103) {
- handler->processKeyEvent(0, Qt::Key_Up, 0, event.value!=0, false);
- } else if(key==106) {
- handler->processKeyEvent(0, Qt::Key_Right, 0, event.value!=0, false );
- } else if(key==108) {
- handler->processKeyEvent(0, Qt::Key_Down, 0, event.value!=0, false);
- } else if(key==105) {
- handler->processKeyEvent(0, Qt::Key_Left, 0, event.value!=0, false);
- } else
-
-#endif
-
- {
- if(event.value == 0) {
- key=key | 0x80;
- }
- handler->doKey(key);
- }
-#endif
-}
-
-QT_END_NAMESPACE
-
-#include "qkbdusb_qws.moc"
-
-#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qmouse_qws.cpp b/src/gui/embedded/qmouse_qws.cpp
index 044a574..b5eda0c 100644
--- a/src/gui/embedded/qmouse_qws.cpp
+++ b/src/gui/embedded/qmouse_qws.cpp
@@ -413,8 +413,8 @@ void QWSCalibratedMouseHandler::writeCalibration()
QFile file(calFile);
if (file.open(QIODevice::WriteOnly)) {
QTextStream t(&file);
- t << a << " " << b << " " << c << " ";
- t << d << " " << e << " " << f << " " << s << endl;
+ t << a << ' ' << b << ' ' << c << ' ';
+ t << d << ' ' << e << ' ' << f << ' ' << s << endl;
} else
#endif
{
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
index 39a74d5..91121e7 100644
--- a/src/gui/embedded/qscreen_qws.cpp
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -49,6 +49,7 @@
#include "qpixmap.h"
#include "qvarlengtharray.h"
#include "qwsdisplay_qws.h"
+#include "qpainter.h"
#include <private/qdrawhelper_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qpixmap_raster_p.h>
@@ -198,10 +199,12 @@ void QScreenCursor::set(const QImage &image, int hotx, int hoty)
*/
void QScreenCursor::move(int x, int y)
{
- const QRegion r = boundingRect();
+ QRegion r = boundingRect();
pos = QPoint(x,y);
- if (enable && !hwaccel)
- qt_screen->exposeRegion(r | boundingRect(), 0);
+ if (enable && !hwaccel) {
+ r |= boundingRect();
+ qt_screen->exposeRegion(r, 0);
+ }
}
@@ -2708,7 +2711,7 @@ void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
default:
break;
}
- spanData.setup(qwsServer->backgroundBrush(), 256);
+ spanData.setup(qwsServer->backgroundBrush(), 256, QPainter::CompositionMode_SourceOver);
spanData.dx = off.x();
spanData.dy = off.y();
} else if (!surface->isBuffered()) {
@@ -2773,7 +2776,7 @@ void QScreen::paintBackground(const QRegion &r)
rb.prepare(&img);
QSpanData spanData;
spanData.init(&rb, 0);
- spanData.setup(bg, 256);
+ spanData.setup(bg, 256, QPainter::CompositionMode_Source);
spanData.dx = off.x();
spanData.dy = off.y();
Q_ASSERT(spanData.blend);
diff --git a/src/gui/embedded/qscreenmulti_qws.cpp b/src/gui/embedded/qscreenmulti_qws.cpp
index 1914b44..a639e01 100644
--- a/src/gui/embedded/qscreenmulti_qws.cpp
+++ b/src/gui/embedded/qscreenmulti_qws.cpp
@@ -221,9 +221,9 @@ bool QMultiScreen::connect(const QString &displaySpec)
{
QString dSpec = displaySpec;
if (dSpec.startsWith(QLatin1String("Multi:"), Qt::CaseInsensitive))
- dSpec = dSpec.mid(QString(QLatin1String("Multi:")).size());
+ dSpec = dSpec.mid(QString::fromLatin1("Multi:").size());
- const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
if (dSpec.endsWith(displayIdSpec))
dSpec = dSpec.left(dSpec.size() - displayIdSpec.size());
diff --git a/src/gui/embedded/qscreenproxy_qws.cpp b/src/gui/embedded/qscreenproxy_qws.cpp
index 5b8f6f0..7652bd9 100644
--- a/src/gui/embedded/qscreenproxy_qws.cpp
+++ b/src/gui/embedded/qscreenproxy_qws.cpp
@@ -279,6 +279,7 @@ void QProxyScreen::exposeRegion(QRegion r, int changing)
}
realScreen->exposeRegion(r, changing);
+ r &= realScreen->region();
const QVector<QRect> rects = r.rects();
for (int i = 0; i < rects.size(); ++i)
diff --git a/src/gui/embedded/qscreentransformed_qws.cpp b/src/gui/embedded/qscreentransformed_qws.cpp
index e22ea1f..01a18b3 100644
--- a/src/gui/embedded/qscreentransformed_qws.cpp
+++ b/src/gui/embedded/qscreentransformed_qws.cpp
@@ -206,11 +206,11 @@ bool QTransformedScreen::connect(const QString &displaySpec)
{
QString dspec = displaySpec.trimmed();
if (dspec.startsWith(QLatin1String("Transformed:"), Qt::CaseInsensitive))
- dspec = dspec.mid(QString(QLatin1String("Transformed:")).size());
+ dspec = dspec.mid(QString::fromLatin1("Transformed:").size());
else if (!dspec.compare(QLatin1String("Transformed"), Qt::CaseInsensitive))
dspec = QString();
- const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
if (dspec.endsWith(displayIdSpec))
dspec = dspec.left(dspec.size() - displayIdSpec.size());
@@ -223,7 +223,7 @@ bool QTransformedScreen::connect(const QString &displaySpec)
if (!QScreenDriverFactory::keys().contains(driver, Qt::CaseInsensitive))
if (!dspec.isEmpty())
- dspec.prepend(QLatin1String(":"));
+ dspec.prepend(QLatin1Char(':'));
const int id = getDisplayId(dspec);
QScreen *s = qt_get_screen(id, dspec.toLatin1().constData());
diff --git a/src/gui/embedded/qscreenvfb_qws.cpp b/src/gui/embedded/qscreenvfb_qws.cpp
index accfe1f..ec393e3 100644
--- a/src/gui/embedded/qscreenvfb_qws.cpp
+++ b/src/gui/embedded/qscreenvfb_qws.cpp
@@ -330,7 +330,7 @@ void QVFbScreen::disconnect()
bool QVFbScreen::initDevice()
{
#ifndef QT_NO_QWS_MOUSE_QVFB
- const QString mouseDev = QString(QLatin1String(QT_VFB_MOUSE_PIPE))
+ const QString mouseDev = QString::fromLatin1(QT_VFB_MOUSE_PIPE)
.arg(displayId);
d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev);
qwsServer->setDefaultMouse("None");
@@ -339,7 +339,7 @@ bool QVFbScreen::initDevice()
#endif
#if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD)
- const QString keyboardDev = QString(QLatin1String(QT_VFB_KEYBOARD_PIPE))
+ const QString keyboardDev = QString::fromLatin1(QT_VFB_KEYBOARD_PIPE)
.arg(displayId);
d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev);
qwsServer->setDefaultKeyboard("None");
diff --git a/src/gui/embedded/qtransportauth_qws.cpp b/src/gui/embedded/qtransportauth_qws.cpp
index 97ba5b8..6677482 100644
--- a/src/gui/embedded/qtransportauth_qws.cpp
+++ b/src/gui/embedded/qtransportauth_qws.cpp
@@ -834,12 +834,12 @@ QString RequestAnalyzer::analyze( QByteArray *msgQueue )
if ( command_type == QWSCommand::QCopSend )
{
QWSQCopSendCommand *sendCommand = static_cast<QWSQCopSendCommand*>(command);
- request += QString( QLatin1String("/QCop/%1/%2") ).arg( sendCommand->channel ).arg( sendCommand->message );
+ request += QString::fromLatin1("/QCop/%1/%2").arg( sendCommand->channel ).arg( sendCommand->message );
}
if ( command_type == QWSCommand::QCopRegisterChannel )
{
QWSQCopRegisterChannelCommand *registerCommand = static_cast<QWSQCopRegisterChannelCommand*>(command);
- request += QString( QLatin1String("/QCop/RegisterChannel/%1") ).arg( registerCommand->channel );
+ request += QString::fromLatin1("/QCop/RegisterChannel/%1").arg( registerCommand->channel );
}
#endif
dataSize = QWS_PROTOCOL_ITEM_SIZE( *command );
diff --git a/src/gui/embedded/qunixsocket.cpp b/src/gui/embedded/qunixsocket.cpp
index 16f2cae..1600505 100644
--- a/src/gui/embedded/qunixsocket.cpp
+++ b/src/gui/embedded/qunixsocket.cpp
@@ -135,7 +135,7 @@ struct QUnixSocketRightsPrivate : public QSharedData
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocketRightsPrivate: Unable to close managed"
- " file descriptor (" << ::strerror(errno) << ")";
+ " file descriptor (" << ::strerror(errno) << ')';
}
#endif
}
@@ -166,7 +166,7 @@ QUnixSocketRights::QUnixSocketRights(int fd)
#ifdef QUNIXSOCKET_DEBUG
if(-1 == d->fd) {
qDebug() << "QUnixSocketRights: Unable to duplicate fd "
- << fd << " (" << ::strerror(errno) << ")";
+ << fd << " (" << ::strerror(errno) << ')';
}
#endif
}
@@ -237,7 +237,7 @@ int QUnixSocketRights::dupFd() const
#ifdef QUNIXSOCKET_DEBUG
if(-1 == rv)
qDebug() << "QUnixSocketRights: Unable to duplicate managed file "
- "descriptor (" << ::strerror(errno) << ")";
+ "descriptor (" << ::strerror(errno) << ')';
#endif
return rv;
@@ -927,7 +927,7 @@ bool QUnixSocket::connect(const QByteArray & path)
int crv;
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Connect requested to '"
- << path << "'";
+ << path << '\'';
#endif
abort(); // Reset any existing connection
@@ -949,7 +949,7 @@ bool QUnixSocket::connect(const QByteArray & path)
if(-1 == d->fd) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to create socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
d->error = ResourceError;
goto connect_error;
@@ -962,7 +962,7 @@ bool QUnixSocket::connect(const QByteArray & path)
if(-1 == crv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to configure socket ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
d->error = ResourceError;
@@ -981,7 +981,7 @@ bool QUnixSocket::connect(const QByteArray & path)
if(-1 == crv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to connect ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
if(ECONNREFUSED == errno)
d->error = ConnectionRefused;
@@ -1021,7 +1021,7 @@ connect_error: // Cleanup failed connection
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocket: Unable to close file descriptor after "
- "failed connect (" << ::strerror(errno) << ")";
+ "failed connect (" << ::strerror(errno) << ')';
}
#endif
}
@@ -1065,7 +1065,7 @@ bool QUnixSocket::setSocketDescriptor(int socketDescriptor)
if(-1 == crv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to configure client provided socket ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
d->error = ResourceError;
@@ -1136,7 +1136,7 @@ void QUnixSocket::abort()
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocket: Unable to close socket during abort ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
}
#endif
@@ -1686,11 +1686,11 @@ qint64 QUnixSocketPrivate::writeActivated()
}
#ifdef QUNIXSOCKET_DEBUG
- qDebug() << "QUnixSocket: Transmitting message (length" << m.d->size() << ")";
+ qDebug() << "QUnixSocket: Transmitting message (length" << m.d->size() << ')';
#endif
::ssize_t s = ::sendmsg(fd, &sendmessage, MSG_DONTWAIT | MSG_NOSIGNAL);
#ifdef QUNIXSOCKET_DEBUG
- qDebug() << "QUnixSocket: Transmitted message (" << s << ")";
+ qDebug() << "QUnixSocket: Transmitted message (" << s << ')';
#endif
if(-1 == s) {
@@ -1699,13 +1699,13 @@ qint64 QUnixSocketPrivate::writeActivated()
} else if(EPIPE == errno) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Remote side disconnected during transmit "
- "(" << ::strerror(errno) << ")";
+ "(" << ::strerror(errno) << ')';
#endif
me->abort();
} else {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to transmit data ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
error = (QUnixSocket::SocketError)(QUnixSocket::WriteFailure |
CausedAbort);
@@ -1764,12 +1764,12 @@ void QUnixSocketPrivate::readActivated()
int recvrv = ::recvmsg(fd, &message, 0);
#ifdef QUNIXSOCKET_DEBUG
- qDebug() << "QUnixSocket: Received message (" << recvrv << ")";
+ qDebug() << "QUnixSocket: Received message (" << recvrv << ')';
#endif
if(-1 == recvrv) {
#ifdef QUNIXSOCKET_DEBUG
qDebug() << "QUnixSocket: Unable to receive data ("
- << ::strerror(errno) << ")";
+ << ::strerror(errno) << ')';
#endif
error = (QUnixSocket::SocketError)(QUnixSocket::ReadFailure |
CausedAbort);
diff --git a/src/gui/embedded/qunixsocketserver.cpp b/src/gui/embedded/qunixsocketserver.cpp
index 6e9347b..489c40a 100644
--- a/src/gui/embedded/qunixsocketserver.cpp
+++ b/src/gui/embedded/qunixsocketserver.cpp
@@ -172,7 +172,7 @@ void QUnixSocketServer::close()
#ifdef QUNIXSOCKET_DEBUG
if(0 != closerv) {
qDebug() << "QUnixSocketServer: Unable to close socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
}
#endif
}
@@ -245,7 +245,7 @@ bool QUnixSocketServer::listen(const QByteArray & path)
if(-1 == d->fd) {
#ifdef QUNIXSOCKETSERVER_DEBUG
qDebug() << "QUnixSocketServer: Unable to create socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
close();
d->error = ResourceError;
@@ -263,7 +263,7 @@ bool QUnixSocketServer::listen(const QByteArray & path)
if(-1 == ::bind(d->fd, (sockaddr *)&addr, sizeof(sockaddr_un))) {
#ifdef QUNIXSOCKETSERVER_DEBUG
qDebug() << "QUnixSocketServer: Unable to bind socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
close();
d->error = BindError;
@@ -274,7 +274,7 @@ bool QUnixSocketServer::listen(const QByteArray & path)
if(-1 == ::listen(d->fd, d->maxConns)) {
#ifdef QUNIXSOCKETSERVER_DEBUG
qDebug() << "QUnixSocketServer: Unable to listen socket ("
- << strerror(errno) << ")";
+ << strerror(errno) << ')';
#endif
close();
d->error = ListenError;
diff --git a/src/gui/embedded/qwindowsystem_qws.cpp b/src/gui/embedded/qwindowsystem_qws.cpp
index e3d56ad..45d5bce 100644
--- a/src/gui/embedded/qwindowsystem_qws.cpp
+++ b/src/gui/embedded/qwindowsystem_qws.cpp
@@ -2218,7 +2218,7 @@ void QWSServer::sendMouseEvent(const QPoint& pos, int state, int wheel)
{
bool block = qwsServerPrivate->screensaverblockevent(MOUSE, qwsServerPrivate->screensaverinterval, state);
#ifdef EVENT_BLOCK_DEBUG
- qDebug() << "sendMouseEvent" << pos.x() << pos.y() << state << (block?"block":"pass");
+ qDebug() << "sendMouseEvent" << pos.x() << pos.y() << state << (block ? "block" : "pass");
#endif
if (state || wheel)
@@ -4124,7 +4124,7 @@ void QWSServer::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers
block = qwsServerPrivate->screensaverblockevent(KEY, qwsServerPrivate->screensaverinterval, isPress);
#ifdef EVENT_BLOCK_DEBUG
- qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block?"block":"pass");
+ qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block ? "block" : "pass");
#endif
// If we press a key and it's going to be blocked, wake up the screen
diff --git a/src/gui/embedded/qwscommand_qws.cpp b/src/gui/embedded/qwscommand_qws.cpp
index 88e33a3..26d3435 100644
--- a/src/gui/embedded/qwscommand_qws.cpp
+++ b/src/gui/embedded/qwscommand_qws.cpp
@@ -43,7 +43,6 @@
#include "qtransportauth_qws.h"
#include "qtransportauth_qws_p.h"
-#include <sys/uio.h>
#include <unistd.h>
// #define QWSCOMMAND_DEBUG 1 // Uncomment to debug client/server communication
@@ -134,7 +133,7 @@ void QWSHexDump::init()
void QWSHexDump::hexDump()
{
- *outstrm << "(" << dataSize << " bytes):\n" << prefix;
+ *outstrm << '(' << dataSize << " bytes):\n" << prefix;
sprintf(sideviewLayout, " [%%-%us]", wrap);
dataWidth = (2 * wrap) + (wrap / clustering);
@@ -145,7 +144,7 @@ void QWSHexDump::hexDump()
sideview[wrapIndex = i%wrap] = isprint(c) ? c : '.';
if (wrapIndex && (wrapIndex % clustering == 0))
- *outstrm << " ";
+ *outstrm << ' ';
outstrm->setFieldWidth(2);
outstrm->setPadChar('0');
@@ -173,14 +172,14 @@ void QWSHexDump::sideviewDump(int at)
int currentWidth = (2 * at) + (at / clustering) - (at%clustering?0:1);
int missing = qMax(dataWidth - currentWidth, 0);
while (missing--)
- *outstrm << " ";
+ *outstrm << ' ';
*outstrm << " [";
outstrm->setPadChar(' ');
outstrm->setFieldWidth(wrap);
outstrm->setFieldAlignment( QTextStream::AlignLeft );
*outstrm << sideview;
- *outstrm << "]";
+ *outstrm << ']';
}
}
diff --git a/src/gui/embedded/qwssignalhandler.cpp b/src/gui/embedded/qwssignalhandler.cpp
index 0946fb6..e85bd36 100644
--- a/src/gui/embedded/qwssignalhandler.cpp
+++ b/src/gui/embedded/qwssignalhandler.cpp
@@ -44,8 +44,10 @@
#ifndef QT_NO_QWS_SIGNALHANDLER
#include <sys/types.h>
-#include <sys/ipc.h>
-#include <sys/sem.h>
+#ifndef QT_NO_QWS_MULTIPROCESS
+# include <sys/ipc.h>
+# include <sys/sem.h>
+#endif
#include <signal.h>
QT_BEGIN_NAMESPACE
diff --git a/src/gui/graphicsview/graphicsview.pri b/src/gui/graphicsview/graphicsview.pri
index 02d9bb1..4cee6d6 100644
--- a/src/gui/graphicsview/graphicsview.pri
+++ b/src/gui/graphicsview/graphicsview.pri
@@ -1,46 +1,37 @@
# Qt graphicsview module
-
-HEADERS += \
- graphicsview/qgraphicsitem.h \
- graphicsview/qgraphicsitem_p.h \
- graphicsview/qgraphicsitemanimation.h \
- graphicsview/qgraphicsscene.h \
- graphicsview/qgraphicsscene_p.h \
- graphicsview/qgraphicsscene_bsp_p.h \
- graphicsview/qgraphicssceneevent.h \
- graphicsview/qgraphicsview_p.h \
- graphicsview/qgraphicsview.h
-
-SOURCES += \
- graphicsview/qgraphicsitem.cpp \
- graphicsview/qgraphicsitemanimation.cpp \
- graphicsview/qgraphicsscene.cpp \
- graphicsview/qgraphicsscene_bsp.cpp \
- graphicsview/qgraphicssceneevent.cpp \
- graphicsview/qgraphicsview.cpp
+HEADERS += graphicsview/qgraphicsitem.h \
+ graphicsview/qgraphicsitem_p.h \
+ graphicsview/qgraphicsitemanimation.h \
+ graphicsview/qgraphicsscene.h \
+ graphicsview/qgraphicsscene_p.h \
+ graphicsview/qgraphicsscene_bsp_p.h \
+ graphicsview/qgraphicssceneevent.h \
+ graphicsview/qgraphicsview_p.h \
+ graphicsview/qgraphicsview.h
+SOURCES += graphicsview/qgraphicsitem.cpp \
+ graphicsview/qgraphicsitemanimation.cpp \
+ graphicsview/qgraphicsscene.cpp \
+ graphicsview/qgraphicsscene_bsp.cpp \
+ graphicsview/qgraphicssceneevent.cpp \
+ graphicsview/qgraphicsview.cpp
# Widgets on the canvas
-
-HEADERS += \
- graphicsview/qgraphicslayout.h \
- graphicsview/qgraphicslayout_p.h \
- graphicsview/qgraphicslayoutitem.h \
- graphicsview/qgraphicslayoutitem_p.h \
- graphicsview/qgraphicslinearlayout.h \
- graphicsview/qgraphicswidget.h \
- graphicsview/qgraphicswidget_p.h \
- graphicsview/qgridlayoutengine_p.h \
- graphicsview/qgraphicsproxywidget.h \
- graphicsview/qgraphicsgridlayout.h
-
-SOURCES += \
- graphicsview/qgraphicslayout.cpp \
- graphicsview/qgraphicslayout_p.cpp \
- graphicsview/qgraphicslayoutitem.cpp \
- graphicsview/qgraphicslinearlayout.cpp \
- graphicsview/qgraphicswidget.cpp \
- graphicsview/qgraphicswidget_p.cpp \
- graphicsview/qgridlayoutengine.cpp \
- graphicsview/qgraphicsproxywidget.cpp \
- graphicsview/qgraphicsgridlayout.cpp
-
+HEADERS += graphicsview/qgraphicslayout.h \
+ graphicsview/qgraphicslayout_p.h \
+ graphicsview/qgraphicslayoutitem.h \
+ graphicsview/qgraphicslayoutitem_p.h \
+ graphicsview/qgraphicslinearlayout.h \
+ graphicsview/qgraphicswidget.h \
+ graphicsview/qgraphicswidget_p.h \
+ graphicsview/qgridlayoutengine_p.h \
+ graphicsview/qgraphicsproxywidget.h \
+ graphicsview/qgraphicsgridlayout.h
+SOURCES += graphicsview/qgraphicslayout.cpp \
+ graphicsview/qgraphicslayout_p.cpp \
+ graphicsview/qgraphicslayoutitem.cpp \
+ graphicsview/qgraphicslinearlayout.cpp \
+ graphicsview/qgraphicswidget.cpp \
+ graphicsview/qgraphicswidget_p.cpp \
+ graphicsview/qgridlayoutengine.cpp \
+ graphicsview/qgraphicsproxywidget.cpp \
+ graphicsview/qgraphicsgridlayout.cpp
diff --git a/src/gui/graphicsview/qgraphicsgridlayout.cpp b/src/gui/graphicsview/qgraphicsgridlayout.cpp
index 1e21b54..36281f8 100644
--- a/src/gui/graphicsview/qgraphicsgridlayout.cpp
+++ b/src/gui/graphicsview/qgraphicsgridlayout.cpp
@@ -100,7 +100,7 @@ QLayoutStyleInfo QGraphicsGridLayoutPrivate::styleInfo() const
if (!wid)
wid = new QWidget;
QGraphicsItem *item = parentItem();
- QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();
+ QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
return QLayoutStyleInfo(style, wid);
}
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 596326b..d9cba2a 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -91,30 +91,33 @@
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 0
- The boundingRect() function has many different purposes. QGraphicsScene
- bases its item index on boundingRect(), and QGraphicsView uses it both for
- culling invisible items, and for determining the area that needs to be
- recomposed when drawing overlapping items. In addition, QGraphicsItem's
- collision detection mechanisms use boundingRect() to provide an efficient
- cut-off. The fine grained collision algorithm in collidesWithItem() is based
- on calling shape(), which returns an accurate outline of the item's shape
- as a QPainterPath.
-
- QGraphicsScene expects all items boundingRect() and shape() to remain
- unchanged unless it is notified. If you want to change an item's geometry
- in any way, you must first call prepareGeometryChange() to allow
- QGraphicsScene to update its bookkeeping.
+ The boundingRect() function has many different purposes.
+ QGraphicsScene bases its item index on boundingRect(), and
+ QGraphicsView uses it both for culling invisible items, and for
+ determining the area that needs to be recomposed when drawing
+ overlapping items. In addition, QGraphicsItem's collision
+ detection mechanisms use boundingRect() to provide an efficient
+ cut-off. The fine grained collision algorithm in
+ collidesWithItem() is based on calling shape(), which returns an
+ accurate outline of the item's shape as a QPainterPath.
+
+ QGraphicsScene expects all items boundingRect() and shape() to
+ remain unchanged unless it is notified. If you want to change an
+ item's geometry in any way, you must first call
+ prepareGeometryChange() to allow QGraphicsScene to update its
+ bookkeeping.
Collision detection can be done in two ways:
\list 1
- \o Reimplement shape() to return an accurate shape for your item, and rely
- on the default implementation of collidesWithItem() to do shape-shape
- intersection. This can be rather expensive if the shapes are complex.
+ \o Reimplement shape() to return an accurate shape for your item,
+ and rely on the default implementation of collidesWithItem() to do
+ shape-shape intersection. This can be rather expensive if the
+ shapes are complex.
- \o Reimplement collidesWithItem() to provide your own custom item and shape
- collision algorithm.
+ \o Reimplement collidesWithItem() to provide your own custom item
+ and shape collision algorithm.
\endlist
@@ -130,21 +133,42 @@
\img graphicsview-parentchild.png
+ \section1 Transformation
+
QGraphicsItem supports affine transformations in addition to its base
- position, pos(). To change the item's transformation, you can either pass
- a transformation matrix to setTransform(), or call one of the convenience
- functions rotate(), scale(), translate(), or shear(). Item transformations
- accumulate from parent to child, so if both a parent and child item are
- rotated 90 degrees, the child's total transformation will be 180 degrees.
- Similarly, if the item's parent is scaled to 2x its original size, its
- children will also be twice as large. An item's transformation does not
- affect its own local geometry; all geometry functions (e.g., contains(),
+ position, pos(). To change the item's transformation, you can pass
+ a transformation matrix to setTransform()
+
+ Item transformations accumulate from parent to child, so if both a
+ parent and child item are rotated 90 degrees, the child's total
+ transformation will be 180 degrees. Similarly, if the item's
+ parent is scaled to 2x its original size, its children will also
+ be twice as large. An item's transformation does not affect its
+ own local geometry; all geometry functions (e.g., contains(),
update(), and all the mapping functions) still operate in local
coordinates. For convenience, QGraphicsItem provides the functions
- sceneTransform(), which returns the item's total transformation matrix
- (including its position and all parents' positions and transformations),
- and scenePos(), which returns its position in scene coordinates. To reset
- an item's matrix, call resetTransform().
+ sceneTransform(), which returns the item's total transformation
+ matrix (including its position and all parents' positions and
+ transformations), and scenePos(), which returns its position in
+ scene coordinates. To reset an item's matrix, call
+ resetTransform().
+
+ Another way to apply transformation to an item is to use the , or
+ set the different transformation properties (transformOrigin,
+ x/y/zRotation, x/yScale, horizontal/verticalShear). Those
+ properties come in addition to the base transformation
+
+ The order you set the transformation properties does not affect
+ the resulting transformation The resulting transformation is
+ always computed in the following order
+
+ \code
+ [Origin] [Base] [RotateX] [RotateY] [RotateZ] [Shear] [Scale] [-Origin]
+ \endcode
+
+ Where [Base] is the stransformation set by setTransform
+
+ \section1 Painting
The paint() function is called by QGraphicsView to paint the item's
contents. The item has no background or default fill of its own; whatever
@@ -161,6 +185,8 @@
high z-values. Stacking order applies to sibling items; parents are always
drawn before their children.
+ \section1 Events
+
QGraphicsItem receives events from QGraphicsScene through the virtual
function sceneEvent(). This function distributes the most common events
to a set of convenience event handlers:
@@ -186,6 +212,8 @@
by the virtual function sceneEventFilter(). You can remove item
event filters by calling removeSceneEventFilter().
+ \section1 Custom Data
+
Sometimes it's useful to register custom data with an item, be it a custom
item, or a standard item. You can call setData() on any item to store data
in it using a key-value pair (the key being an integer, and the value is a
@@ -274,6 +302,27 @@
this flag, the child will be stacked behind it. This flag is useful for
drop shadow effects and for decoration objects that follow the parent
item's geometry without drawing on top of it.
+
+ \value ItemUsesExtendedStyleOption The item makes use of either
+ QStyleOptionGraphicsItem::exposedRect or QStyleOptionGraphicsItem::matrix.
+ By default, the exposedRect is initialized to the item's boundingRect and
+ the matrix is untransformed. Enable this flag for more fine-grained values.
+ Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
+ and is always initialized to 1.
+ Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more
+ fine-grained value.
+
+ \value ItemHasNoContents The item does not paint anything (i.e., calling
+ paint() on the item has no effect). You should set this flag on items that
+ do not need to be painted to ensure that Graphics View avoids unnecessary
+ painting preparations. This flag was introduced in Qt 4.6.
+
+ \value ItemSendsGeometryChanges The item enables itemChange()
+ notifications for ItemPositionChange, ItemPositionHasChanged,
+ ItemMatrixChange, ItemTransformChange, and ItemTransformHasChanged. For
+ performance reasons, these notifications are disabled by default. You must
+ enable this flag to receive notifications for position and transform
+ changes. This flag was introduced in Qt 4.6.
*/
/*!
@@ -312,33 +361,37 @@
changing. This value is obsolete; you can use ItemTransformChange instead.
\value ItemPositionChange The item's position changes. This notification
- is only sent when the item's local position changes, relative to its
- parent, has changed (i.e., as a result of calling setPos() or
- moveBy()). The value argument is the new position (i.e., a QPointF). You
- can call pos() to get the original position. Do not call setPos() or
- moveBy() in itemChange() as this notification is delivered; instead, you
- can return the new, adjusted position from itemChange(). After this
- notification, QGraphicsItem immediately sends the ItemPositionHasChanged
- notification if the position changed.
+ is sent if the ItemSendsGeometryChanges flag is enabled, and when the
+ item's local position changes, relative to its parent (i.e., as a result
+ of calling setPos() or moveBy()). The value argument is the new position
+ (i.e., a QPointF). You can call pos() to get the original position. Do
+ not call setPos() or moveBy() in itemChange() as this notification is
+ delivered; instead, you can return the new, adjusted position from
+ itemChange(). After this notification, QGraphicsItem immediately sends the
+ ItemPositionHasChanged notification if the position changed.
\value ItemPositionHasChanged The item's position has changed. This
- notification is only sent after the item's local position, relative to its
- parent, has changed. The value argument is the new position (the same as
- pos()), and QGraphicsItem ignores the return value for this notification
- (i.e., a read-only notification).
+ notification is sent if the ItemSendsGeometryChanges flag is enabled, and
+ after the item's local position, relative to its parent, has changed. The
+ value argument is the new position (the same as pos()), and QGraphicsItem
+ ignores the return value for this notification (i.e., a read-only
+ notification).
\value ItemTransformChange The item's transformation matrix changes. This
- notification is only sent when the item's local transformation matrix
- changes (i.e., as a result of calling setTransform(), or one of the
- convenience transformation functions, such as rotate()). The value
- argument is the new matrix (i.e., a QTransform); to get the old matrix,
- call transform(). Do not call setTransform() or any of the transformation
- convenience functions in itemChange() as this notification is delivered;
- instead, you can return the new matrix from itemChange().
+ notification is send if the ItemSendsGeometryChanges flag is enabled, and
+ when the item's local transformation matrix changes (i.e., as a result of
+ calling setTransform(). The value argument is the new matrix (i.e., a
+ QTransform); to get the old matrix, call transform(). Do not call
+ setTransform() or set any of the transformation properties in itemChange()
+ as this notification is delivered; instead, you can return the new matrix
+ from itemChange(). This notification is not sent if you change the
+ transformation properties.
\value ItemTransformHasChanged The item's transformation matrix has
- changed. This notification is only sent after the item's local
- trasformation matrix has changed. The value argument is the new matrix
+ changed either because setTransform is called, or one of the
+ transformation properties is changed. This notification is sent if the
+ ItemSendsGeometryChanges flag is enabled, and after the item's local
+ transformation matrix has changed. The value argument is the new matrix
(same as transform()), and QGraphicsItem ignores the return value for this
notification (i.e., a read-only notification).
@@ -523,6 +576,11 @@
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextengine_p.h>
+#ifdef Q_WS_X11
+#include <private/qt_x11_p.h>
+#include <private/qpixmap_x11_p.h>
+#endif
+
#include <math.h>
QT_BEGIN_NAMESPACE
@@ -560,29 +618,6 @@ Q_GLOBAL_STATIC(QGraphicsItemCustomDataStore, qt_dataStore)
/*!
\internal
- Removes the first instance of \a child from \a children. This is a
- heuristic approach that assumes that it's common to remove items from the
- start or end of the list.
-*/
-static void qt_graphicsitem_removeChild(QGraphicsItem *child, QList<QGraphicsItem *> *children)
-{
- const int n = children->size();
- for (int i = 0; i < (n + 1) / 2; ++i) {
- if (children->at(i) == child) {
- children->removeAt(i);
- return;
- }
- int j = n - i - 1;
- if (children->at(j) == child) {
- children->removeAt(j);
- return;
- }
- }
-}
-
-/*!
- \internal
-
Returns a QPainterPath of \a path when stroked with the \a pen.
Ignoring dash pattern.
*/
@@ -755,12 +790,43 @@ QPointF QGraphicsItemPrivate::genericMapFromScene(const QPointF &pos,
/*!
\internal
- Returns true if this item or any of its ancestors are untransformable.
+ Combines this item's position and transform onto \a transform.
+
+ If you need to change this function (e.g., adding more transformation
+ modes / options), make sure to change all places marked with COMBINE.
+*/
+void QGraphicsItemPrivate::combineTransformToParent(QTransform *x, const QTransform *viewTransform) const
+{
+ // COMBINE
+ if (itemIsUntransformable() && viewTransform) {
+ *x = q_ptr->deviceTransform(*viewTransform);
+ } else {
+ if (transformData)
+ *x *= transformData->computedFullTransform();
+ if (!pos.isNull())
+ *x *= QTransform::fromTranslate(pos.x(), pos.y());
+ }
+}
+
+/*!
+ \internal
+
+ Combines this item's position and transform onto \a transform.
+
+ If you need to change this function (e.g., adding more transformation
+ modes / options), make sure to change QGraphicsItem::deviceTransform() as
+ well.
*/
-bool QGraphicsItemPrivate::itemIsUntransformable() const
+void QGraphicsItemPrivate::combineTransformFromParent(QTransform *x, const QTransform *viewTransform) const
{
- return (flags & QGraphicsItem::ItemIgnoresTransformations)
- || (ancestorFlags & AncestorIgnoresTransformations);
+ // COMBINE
+ if (itemIsUntransformable() && viewTransform) {
+ *x = q_ptr->deviceTransform(*viewTransform);
+ } else {
+ x->translate(pos.x(), pos.y());
+ if (transformData)
+ *x = transformData->computedFullTransform(x);
+ }
}
/*!
@@ -782,11 +848,217 @@ QVariant QGraphicsItemPrivate::inputMethodQueryHelper(Qt::InputMethodQuery query
/*!
\internal
+ Make sure not to trigger any pure virtual function calls (e.g.,
+ prepareGeometryChange) if the item is in its destructor, i.e.
+ inDestructor is 1.
+*/
+void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent)
+{
+ Q_Q(QGraphicsItem);
+ if (newParent == q) {
+ qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
+ return;
+ }
+ if (newParent == parent)
+ return;
+
+ const QVariant newParentVariant(q->itemChange(QGraphicsItem::ItemParentChange,
+ qVariantFromValue<QGraphicsItem *>(newParent)));
+ newParent = qVariantValue<QGraphicsItem *>(newParentVariant);
+ if (newParent == parent)
+ return;
+
+ if (QGraphicsWidget *w = isWidget ? static_cast<QGraphicsWidget *>(q) : q->parentWidget()) {
+ // Update the child focus chain; when reparenting a widget that has a
+ // focus child, ensure that that focus child clears its focus child
+ // chain from our parents before it's reparented.
+ if (QGraphicsWidget *focusChild = w->focusWidget())
+ focusChild->clearFocus();
+ }
+
+ // We anticipate geometry changes. If the item is deleted, it will be
+ // removed from the index at a later stage, and the whole scene will be
+ // updated.
+ if (!inDestructor)
+ q_ptr->prepareGeometryChange();
+
+ const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(q));
+ if (parent) {
+ // Remove from current parent
+ parent->d_ptr->removeChild(q);
+ parent->itemChange(QGraphicsItem::ItemChildRemovedChange, thisPointerVariant);
+ }
+
+ // Update toplevelitem list. If this item is being deleted, its parent
+ // will be 0 but we don't want to register/unregister it in the TLI list.
+ if (scene && !inDestructor) {
+ if (parent && !newParent) {
+ scene->d_func()->registerTopLevelItem(q);
+ } else if (!parent && newParent) {
+ scene->d_func()->unregisterTopLevelItem(q);
+ }
+ }
+
+ if ((parent = newParent)) {
+ bool implicitUpdate = false;
+ if (parent->d_func()->scene && parent->d_func()->scene != scene) {
+ // Move this item to its new parent's scene
+ parent->d_func()->scene->addItem(q);
+ implicitUpdate = true;
+ } else if (!parent->d_func()->scene && scene) {
+ // Remove this item from its former scene
+ scene->removeItem(q);
+ }
+
+ parent->d_ptr->addChild(q);
+ parent->itemChange(QGraphicsItem::ItemChildAddedChange, thisPointerVariant);
+ if (!implicitUpdate && scene) {
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+ }
+
+ // Inherit ancestor flags from the new parent.
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
+ updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ // Update item visible / enabled.
+ if (parent->isVisible() != visible) {
+ if (!parent->isVisible() || !explicitlyHidden)
+ setVisibleHelper(parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
+ }
+ if (parent->isEnabled() != enabled) {
+ if (!parent->isEnabled() || !explicitlyDisabled)
+ setEnabledHelper(parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
+ }
+
+ } else {
+ // Inherit ancestor flags from the new parent.
+ updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
+ updateAncestorFlag(QGraphicsItem::ItemClipsChildrenToShape);
+ updateAncestorFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ if (!inDestructor) {
+ // Update item visible / enabled.
+ if (!visible && !explicitlyHidden)
+ setVisibleHelper(true, /* explicit = */ false);
+ if (!enabled && !explicitlyDisabled)
+ setEnabledHelper(true, /* explicit = */ false);
+
+ // If the item is being deleted, the whole scene will be updated.
+ if (scene) {
+ scene->d_func()->markDirty(q_ptr, QRect(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/true);
+ }
+ }
+ }
+
+ if (scene) {
+ // Invalidate any sort caching; arrival of a new item means we need to
+ // resort.
+ scene->d_func()->invalidateSortCache();
+ }
+
+ // Resolve depth.
+ resolveDepth(parent ? parent->d_ptr->depth : -1);
+ dirtySceneTransform = 1;
+
+ // Deliver post-change notification
+ q->itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
+
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q)->parentChanged();
+}
+
+/*!
+ \internal
+
+ Returns the bounding rect of this item's children (excluding itself).
+*/
+void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rect)
+{
+ if (!dirtyChildrenBoundingRect) {
+ *rect |= x->mapRect(childrenBoundingRect);
+ return;
+ }
+
+ for (int i = 0; i < children.size(); ++i) {
+ QGraphicsItem *child = children.at(i);
+ QGraphicsItemPrivate *childd = child->d_ptr;
+ bool hasPos = !childd->pos.isNull();
+ if (hasPos || childd->transformData) {
+ // COMBINE
+ QTransform matrix = childd->transformToParent() * *x;
+ *rect |= matrix.mapRect(child->boundingRect());
+ if (!childd->children.isEmpty())
+ childd->childrenBoundingRectHelper(&matrix, rect);
+ } else {
+ *rect |= x->mapRect(child->boundingRect());
+ if (!childd->children.isEmpty())
+ childd->childrenBoundingRectHelper(x, rect);
+ }
+ }
+
+ childrenBoundingRect = *rect;
+ dirtyChildrenBoundingRect = 0;
+}
+
+void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
+ const QRegion &exposedRegion, bool allItems) const
+{
+ Q_ASSERT(option);
+ Q_Q(const QGraphicsItem);
+
+ // Initialize standard QStyleOption values.
+ const QRectF brect = q->boundingRect();
+ option->state = QStyle::State_None;
+ option->rect = brect.toRect();
+ option->levelOfDetail = 1;
+ option->exposedRect = brect;
+ if (selected)
+ option->state |= QStyle::State_Selected;
+ if (enabled)
+ option->state |= QStyle::State_Enabled;
+ if (q->hasFocus())
+ option->state |= QStyle::State_HasFocus;
+ if (scene) {
+ if (scene->d_func()->hoverItems.contains(q_ptr))
+ option->state |= QStyle::State_MouseOver;
+ if (q == scene->mouseGrabberItem())
+ option->state |= QStyle::State_Sunken;
+ }
+
+ if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption))
+ return;
+
+ // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
+ option->matrix = worldTransform.toAffine(); //### discards perspective
+
+ if (!allItems) {
+ // Determine the item's exposed area
+ option->exposedRect = QRectF();
+ const QTransform reverseMap = worldTransform.inverted();
+ const QVector<QRect> exposedRects(exposedRegion.rects());
+ for (int i = 0; i < exposedRects.size(); ++i) {
+ option->exposedRect |= reverseMap.mapRect(exposedRects.at(i));
+ if (option->exposedRect.contains(brect))
+ break;
+ }
+ option->exposedRect &= brect;
+ }
+}
+
+/*!
+ \internal
+
Empty all cached pixmaps from the pixmap cache.
*/
void QGraphicsItemCache::purge()
{
QPixmapCache::remove(key);
+ key = QPixmapCache::Key();
QMutableMapIterator<QPaintDevice *, DeviceData> it(deviceData);
while (it.hasNext()) {
DeviceData &data = it.next().value();
@@ -854,26 +1126,23 @@ QGraphicsItem::QGraphicsItem(QGraphicsItemPrivate &dd, QGraphicsItem *parent,
*/
QGraphicsItem::~QGraphicsItem()
{
- clearFocus();
+ d_ptr->inDestructor = 1;
d_ptr->removeExtraItemCache();
- QVariant variant;
- foreach (QGraphicsItem *child, d_ptr->children) {
- if (QGraphicsItem *parent = child->parentItem()) {
- qVariantSetValue<QGraphicsItem *>(variant, child);
- parent->itemChange(ItemChildRemovedChange, variant);
- }
- delete child;
+ clearFocus();
+ if (!d_ptr->children.isEmpty()) {
+ QList<QGraphicsItem *> oldChildren = d_ptr->children;
+ qDeleteAll(oldChildren);
+ Q_ASSERT(d_ptr->children.isEmpty());
}
- d_ptr->children.clear();
- if (QGraphicsItem *parent = parentItem()) {
- qVariantSetValue<QGraphicsItem *>(variant, this);
- parent->itemChange(ItemChildRemovedChange, variant);
- qt_graphicsitem_removeChild(this, &parent->d_func()->children);
- }
if (d_ptr->scene)
- d_ptr->scene->d_func()->_q_removeItemLater(this);
+ d_ptr->scene->d_func()->removeItemHelper(this);
+ else
+ d_ptr->setParentItemHelper(0);
+
+ delete d_ptr->transformData;
+ delete d_ptr;
qt_dataStore()->data.remove(this);
}
@@ -955,6 +1224,20 @@ QGraphicsItem *QGraphicsItem::topLevelItem() const
/*!
\since 4.4
+ Returns a pointer to the item's parent, cast to a QGraphicsObject. returns 0 if the parent item
+ is not a QGraphicsObject.
+
+ \sa parentItem(), childItems()
+*/
+QGraphicsObject *QGraphicsItem::parentObject() const
+{
+ QGraphicsItem *p = d_ptr->parent;
+ return (p && p->d_ptr->isObject) ? static_cast<QGraphicsObject *>(p) : 0;
+}
+
+/*!
+ \since 4.4
+
Returns a pointer to the item's parent widget. The item's parent widget is
the closest parent item that is a widget.
@@ -1002,6 +1285,28 @@ QGraphicsWidget *QGraphicsItem::window() const
}
/*!
+ \since 4.6
+
+ Return the graphics item cast to a QGraphicsObject, if the class is actually a
+ graphics object, 0 otherwise.
+*/
+QGraphicsObject *QGraphicsItem::toGraphicsObject()
+{
+ return d_ptr->isObject ? static_cast<QGraphicsObject *>(this) : 0;
+}
+
+/*!
+ \since 4.6
+
+ Return the graphics item cast to a QGraphicsObject, if the class is actually a
+ graphics object, 0 otherwise.
+*/
+const QGraphicsObject *QGraphicsItem::toGraphicsObject() const
+{
+ return d_ptr->isObject ? static_cast<const QGraphicsObject *>(this) : 0;
+}
+
+/*!
Sets this item's parent item to \a parent. If this item already has a
parent, it is first removed from the previous parent. If \a parent is 0,
this item will become a top-level item.
@@ -1014,98 +1319,7 @@ QGraphicsWidget *QGraphicsItem::window() const
*/
void QGraphicsItem::setParentItem(QGraphicsItem *parent)
{
- if (parent == this) {
- qWarning("QGraphicsItem::setParentItem: cannot assign %p as a parent of itself", this);
- return;
- }
- if (parent == d_ptr->parent)
- return;
- const QVariant newParentVariant(itemChange(ItemParentChange, qVariantFromValue<QGraphicsItem *>(parent)));
- parent = qVariantValue<QGraphicsItem *>(newParentVariant);
- if (parent == d_ptr->parent)
- return;
-
- if (QGraphicsWidget *w = d_ptr->isWidget ? static_cast<QGraphicsWidget *>(this) : parentWidget()) {
- // Update the child focus chain; when reparenting a widget that has a
- // focus child, ensure that that focus child clears its focus child
- // chain from our parents before it's reparented.
- if (QGraphicsWidget *focusChild = w->focusWidget())
- focusChild->clearFocus();
- }
-
- // We anticipate geometry changes
- prepareGeometryChange();
-
- const QVariant thisPointerVariant(qVariantFromValue<QGraphicsItem *>(this));
- if (d_ptr->parent) {
- // Remove from current parent
- qt_graphicsitem_removeChild(this, &d_ptr->parent->d_func()->children);
- d_ptr->parent->itemChange(ItemChildRemovedChange, thisPointerVariant);
- }
-
- if ((d_ptr->parent = parent)) {
- bool implicitUpdate = false;
- if (parent->d_func()->scene && parent->d_func()->scene != d_ptr->scene) {
- // Move this item to its new parent's scene
- parent->d_func()->scene->addItem(this);
- implicitUpdate = true;
- } else if (!parent->d_func()->scene && d_ptr->scene) {
- // Remove this item from its former scene
- d_ptr->scene->removeItem(this);
- }
-
- d_ptr->parent->d_func()->children << this;
- d_ptr->parent->itemChange(ItemChildAddedChange, thisPointerVariant);
- if (!implicitUpdate)
- d_ptr->updateHelper(QRectF(), false, true);
-
- // Inherit ancestor flags from the new parent.
- d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
- d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
- d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
-
- // Update item visible / enabled.
- if (d_ptr->parent->isVisible() != d_ptr->visible) {
- if (!d_ptr->parent->isVisible() || !d_ptr->explicitlyHidden)
- d_ptr->setVisibleHelper(d_ptr->parent->isVisible(), /* explicit = */ false, /* update = */ !implicitUpdate);
- }
- if (d_ptr->parent->isEnabled() != d_ptr->enabled) {
- if (!d_ptr->parent->isEnabled() || !d_ptr->explicitlyDisabled)
- d_ptr->setEnabledHelper(d_ptr->parent->isEnabled(), /* explicit = */ false, /* update = */ !implicitUpdate);
- }
-
- } else {
- // Inherit ancestor flags from the new parent.
- d_ptr->updateAncestorFlag(QGraphicsItem::GraphicsItemFlag(-1));
- d_ptr->updateAncestorFlag(ItemClipsChildrenToShape);
- d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
-
- // Update item visible / enabled.
- if (!d_ptr->visible && !d_ptr->explicitlyHidden)
- d_ptr->setVisibleHelper(true, /* explicit = */ false);
- if (!d_ptr->enabled && !d_ptr->explicitlyDisabled)
- d_ptr->setEnabledHelper(true, /* explicit = */ false);
-
- d_ptr->updateHelper(QRectF(), false, true);
- }
-
- if (d_ptr->scene) {
- // Invalidate any sort caching; arrival of a new item means we need to
- // resort.
- d_ptr->scene->d_func()->invalidateSortCache();
- }
-
- // Resolve opacity.
- d_ptr->updateEffectiveOpacity();
-
- // Resolve depth.
- d_ptr->resolveDepth(parent ? parent->d_ptr->depth : -1);
-
- // Invalidate transform cache.
- d_ptr->invalidateSceneTransformCache();
-
- // Deliver post-change notification
- itemChange(QGraphicsItem::ItemParentHasChanged, newParentVariant);
+ d_ptr->setParentItemHelper(parent);
}
/*!
@@ -1210,7 +1424,9 @@ static void _q_qgraphicsItemSetFlag(QGraphicsItem *item, QGraphicsItem::Graphics
item was selected, and \a flags does not enabled ItemIsSelectable, the
item is automatically unselected.
- By default, no flags are enabled.
+ By default, no flags are enabled. (QGraphicsWidget enables the
+ ItemSendsGeometryChanges flag by default in order to track position
+ changes.)
\sa flags(), setFlag()
*/
@@ -1227,7 +1443,7 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
const quint32 geomChangeFlagsMask = (ItemClipsChildrenToShape | ItemClipsToShape | ItemIgnoresTransformations);
bool fullUpdate = (quint32(flags) & geomChangeFlagsMask) != (d_ptr->flags & geomChangeFlagsMask);
if (fullUpdate)
- d_ptr->fullUpdateHelper(false, true);
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
// Keep the old flags to compare the diff.
GraphicsItemFlags oldFlags = this->flags();
@@ -1235,11 +1451,6 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
// Update flags.
d_ptr->flags = flags;
- // Reresolve effective opacity if the opacity flags change.
- static const quint32 opacityFlagsMask = ItemIgnoresParentOpacity | ItemDoesntPropagateOpacityToChildren;
- if ((flags & opacityFlagsMask) != (oldFlags & opacityFlagsMask))
- d_ptr->updateEffectiveOpacity();
-
if (!(d_ptr->flags & ItemIsFocusable) && hasFocus()) {
// Clear focus on the item if it has focus when the focusable flag
// is unset.
@@ -1267,8 +1478,19 @@ void QGraphicsItem::setFlags(GraphicsItemFlags flags)
d_ptr->updateAncestorFlag(ItemIgnoresTransformations);
}
- // ### Why updateHelper?
- d_ptr->updateHelper(QRectF(), false, true);
+ if ((flags & ItemStacksBehindParent) != (oldFlags & ItemStacksBehindParent)) {
+ // Ensure child item sorting is up to date when toggling this flag.
+ if (d_ptr->parent)
+ d_ptr->parent->d_ptr->needSortChildren = 1;
+ else if (d_ptr->scene)
+ d_ptr->scene->d_func()->needSortTopLevelItems = 1;
+ }
+
+ if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath*/true);
+ }
// Notify change.
itemChange(ItemFlagsHaveChanged, quint32(flags));
@@ -1331,12 +1553,6 @@ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
cache->purge();
if (mode == ItemCoordinateCache) {
- if (cache->key.isEmpty()) {
- // Generate new simple pixmap cache key.
- QString tmp;
- tmp.sprintf("qgv-%p", this);
- cache->key = tmp;
- }
if (lastMode == mode && cache->fixedSize == logicalCacheSize)
noVisualChange = true;
cache->fixedSize = logicalCacheSize;
@@ -1414,7 +1630,9 @@ void QGraphicsItem::setCursor(const QCursor &cursor)
d_ptr->setExtra(QGraphicsItemPrivate::ExtraCursor, qVariantValue<QCursor>(cursorVariant));
d_ptr->hasCursor = 1;
if (d_ptr->scene) {
+ d_ptr->scene->d_func()->allItemsUseDefaultCursor = false;
foreach (QGraphicsView *view, d_ptr->scene->views()) {
+ view->viewport()->setMouseTracking(true);
// Note: Some of this logic is duplicated in QGraphicsView's mouse events.
if (view->underMouse()) {
foreach (QGraphicsItem *itemUnderCursor, view->items(view->mapFromGlobal(QCursor::pos()))) {
@@ -1538,7 +1756,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
if (c)
c->purge();
- updateHelper(QRectF(), /* force = */ true);
+ if (scene) {
+ scene->d_func()->markDirty(q_ptr, QRectF(),
+ /*invalidateChildren=*/false,
+ /*maybeDirtyClipPath=*/false,
+ /*force=*/true);
+ }
}
// Certain properties are dropped as an item becomes invisible.
@@ -1591,6 +1814,9 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
// Deliver post-change notification.
q_ptr->itemChange(QGraphicsItem::ItemVisibleHasChanged, newVisibleVariant);
+
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->visibleChanged();
}
/*!
@@ -1701,8 +1927,8 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo
enabled = newEnabledVariant.toBool();
// Schedule redraw.
- if (update)
- updateHelper();
+ if (update && scene)
+ scene->d_func()->markDirty(q_ptr);
foreach (QGraphicsItem *child, children) {
if (!newEnabled || !child->d_ptr->explicitlyDisabled)
@@ -1711,6 +1937,9 @@ void QGraphicsItemPrivate::setEnabledHelper(bool newEnabled, bool explicitly, bo
// Deliver post-change notification.
q_ptr->itemChange(QGraphicsItem::ItemEnabledHasChanged, newEnabledVariant);
+
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->enabledChanged();
}
/*!
@@ -1803,9 +2032,8 @@ void QGraphicsItem::setSelected(bool selected)
return;
d_ptr->selected = newSelected;
- d_ptr->updateHelper();
-
if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this);
QGraphicsScenePrivate *sceneD = d_ptr->scene->d_func();
if (selected) {
sceneD->selectedItems << this;
@@ -1841,12 +2069,7 @@ void QGraphicsItem::setSelected(bool selected)
*/
qreal QGraphicsItem::opacity() const
{
- if (d_ptr->hasOpacity) {
- QVariant o = d_ptr->extra(QGraphicsItemPrivate::ExtraOpacity);
- if (!o.isNull())
- return o.toDouble();
- }
- return qreal(1.0);
+ return d_ptr->opacity;
}
/*!
@@ -1862,11 +2085,7 @@ qreal QGraphicsItem::opacity() const
*/
qreal QGraphicsItem::effectiveOpacity() const
{
- if (!d_ptr->hasEffectiveOpacity)
- return qreal(1.0);
-
- QVariant effectiveOpacity = d_ptr->extra(QGraphicsItemPrivate::ExtraEffectiveOpacity);
- return effectiveOpacity.isNull() ? qreal(1.0) : qreal(effectiveOpacity.toDouble());
+ return d_ptr->effectiveOpacity();
}
/*!
@@ -1901,30 +2120,24 @@ void QGraphicsItem::setOpacity(qreal opacity)
newOpacity = qBound<qreal>(0.0, newOpacity, 1.0);
// No change? Done.
- if (qFuzzyCompare(newOpacity, this->opacity()))
+ if (newOpacity == d_ptr->opacity)
return;
- // Assign local opacity.
- if (qFuzzyCompare(newOpacity, qreal(1.0))) {
- // Opaque, unset opacity.
- d_ptr->hasOpacity = 0;
- d_ptr->unsetExtra(QGraphicsItemPrivate::ExtraOpacity);
- } else {
- d_ptr->hasOpacity = 1;
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraOpacity, double(newOpacity));
- }
-
- // Resolve effective opacity.
- if (QGraphicsItem *p = d_ptr->parent)
- d_ptr->resolveEffectiveOpacity(p->effectiveOpacity());
- else
- d_ptr->resolveEffectiveOpacity(1.0);
+ d_ptr->opacity = newOpacity;
// Notify change.
- itemChange(ItemOpacityHasChanged, newOpacity);
+ itemChange(ItemOpacityHasChanged, newOpacityVariant);
// Update.
- d_ptr->fullUpdateHelper(/*childrenOnly=*/false, /*maybeDirtyClipPath=*/false, /*ignoreOpacity=*/true);
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath=*/false,
+ /*force=*/false,
+ /*ignoreOpacity=*/true);
+
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->opacityChanged();
}
/*!
@@ -2050,7 +2263,13 @@ bool QGraphicsItem::acceptsHoverEvents() const
*/
void QGraphicsItem::setAcceptHoverEvents(bool enabled)
{
+ if (d_ptr->acceptsHover == quint32(enabled))
+ return;
d_ptr->acceptsHover = quint32(enabled);
+ if (d_ptr->acceptsHover && d_ptr->scene && d_ptr->scene->d_func()->allItemsIgnoreHoverEvents) {
+ d_ptr->scene->d_func()->allItemsIgnoreHoverEvents = false;
+ d_ptr->scene->d_func()->enableMouseTrackingOnViews();
+ }
}
/*!
@@ -2060,7 +2279,7 @@ void QGraphicsItem::setAcceptHoverEvents(bool enabled)
*/
void QGraphicsItem::setAcceptsHoverEvents(bool enabled)
{
- d_ptr->acceptsHover = quint32(enabled);
+ setAcceptHoverEvents(enabled);
}
/*!
@@ -2328,6 +2547,17 @@ QPointF QGraphicsItem::pos() const
*/
/*!
+ Set's the \a x coordinate of the item's position. Equivalent to
+ calling setPos(x, y()).
+
+ \sa x(), setPos()
+*/
+void QGraphicsItem::setX(qreal x)
+{
+ d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y()));
+}
+
+/*!
\fn QGraphicsItem::y() const
This convenience function is equivalent to calling pos().y().
@@ -2336,6 +2566,17 @@ QPointF QGraphicsItem::pos() const
*/
/*!
+ Set's the \a y coordinate of the item's position. Equivalent to
+ calling setPos(x(), y).
+
+ \sa x(), setPos()
+*/
+void QGraphicsItem::setY(qreal y)
+{
+ d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y));
+}
+
+/*!
Returns the item's position in scene coordinates. This is
equivalent to calling \c mapToScene(0, 0).
@@ -2349,35 +2590,37 @@ QPointF QGraphicsItem::scenePos() const
/*!
\internal
- Sets the position \a pos and notifies the change. If \a update is true,
- the item is also updated; otherwise it is not updated before and after the
- change.
+ Sets the position \a pos.
*/
void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
{
Q_Q(QGraphicsItem);
- if (this->pos == pos)
- return;
-
- // Notify the item that the position is changing.
- const QVariant newPosVariant(q->itemChange(QGraphicsItem::ItemPositionChange, pos));
- QPointF newPos = newPosVariant.toPointF();
- if (newPos == this->pos)
- return;
-
- // Update and repositition.
inSetPosHelper = 1;
- updateCachedClipPathFromSetPosHelper(newPos);
- if (scene) {
- fullUpdateHelper(true);
+ updateCachedClipPathFromSetPosHelper(pos);
+ if (scene)
q->prepareGeometryChange();
+ QPointF oldPos = this->pos;
+ this->pos = pos;
+ dirtySceneTransform = 1;
+ inSetPosHelper = 0;
+ if (isObject) {
+ if (pos.x() != oldPos.x())
+ emit static_cast<QGraphicsObject *>(q_ptr)->xChanged();
+ if (pos.y() != oldPos.y())
+ emit static_cast<QGraphicsObject *>(q_ptr)->yChanged();
}
- this->pos = newPos;
- invalidateSceneTransformCache();
+}
- // Send post-notification.
- q->itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
- inSetPosHelper = 0;
+/*!
+ \internal
+
+ Sets the transform \a transform.
+*/
+void QGraphicsItemPrivate::setTransformHelper(const QTransform &transform)
+{
+ q_ptr->prepareGeometryChange();
+ transformData->transform = transform;
+ dirtySceneTransform = 1;
}
/*!
@@ -2392,7 +2635,26 @@ void QGraphicsItemPrivate::setPosHelper(const QPointF &pos)
*/
void QGraphicsItem::setPos(const QPointF &pos)
{
- d_ptr->setPosHelper(pos);
+ if (d_ptr->pos == pos)
+ return;
+
+ // Update and repositition.
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setPosHelper(pos);
+ return;
+ }
+
+ // Notify the item that the position is changing.
+ const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos)));
+ QPointF newPos = newPosVariant.toPointF();
+ if (newPos == d_ptr->pos)
+ return;
+
+ // Update and repositition.
+ d_ptr->setPosHelper(newPos);
+
+ // Send post-notification.
+ itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant);
}
/*!
@@ -2465,19 +2727,391 @@ QMatrix QGraphicsItem::matrix() const
/*!
\since 4.3
- Returns this item's transformation matrix. If no matrix has been set, the
- identity matrix is returned.
+ Returns this item's transformation matrix.
+
+ Either the one set by setTransform, or the resulting transformation from
+ all the transfmation properties
+
+ If no matrix or transformation property has been set, the
+ identity matrix is returned.
\sa setTransform(), sceneTransform()
*/
QTransform QGraphicsItem::transform() const
{
- if (!d_ptr->hasTransform)
+ if (!d_ptr->transformData)
return QTransform();
- return qVariantValue<QTransform>(d_ptr->extra(QGraphicsItemPrivate::ExtraTransform));
+ return d_ptr->transformData->transform;
+}
+
+/*!
+ \since 4.6
+
+ Returns the rotation around the X axis.
+
+ The default is 0
+
+ \warning The value doesn't take in account any rotation set with
+ the setTransform() method.
+
+ \sa setXRotation(), {Transformations}
+*/
+qreal QGraphicsItem::xRotation() const
+{
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->xRotation;
+}
+
+/*!
+ \since 4.6
+
+ Sets the rotation around the X axis to \a angle degrees.
+
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
+
+ \sa xRotation(), setTransformOrigin(), {Transformations}
+*/
+void QGraphicsItem::setXRotation(qreal angle)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xRotation = angle;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the rotation around the Y axis.
+
+ The default is 0
+
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
+
+ \sa setYRotation(), {Transformations}
+*/
+qreal QGraphicsItem::yRotation() const
+{
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->yRotation;
+}
+
+/*!
+ \since 4.6
+
+ Sets the rotation around the Y axis to \a angle degrees.
+
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
+
+ \sa yRotation(), setTransformOrigin() {Transformations}
+*/
+void QGraphicsItem::setYRotation(qreal angle)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->yRotation = angle;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
}
/*!
+ \since 4.6
+
+ Returns the rotation around the Z axis.
+
+ The default is 0
+
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
+
+ \sa setZRotation(), {Transformations}
+*/
+qreal QGraphicsItem::zRotation() const
+{
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->zRotation;
+}
+
+/*!
+ \since 4.6
+
+ Sets the rotation around the Z axis to \a angle degrees.
+
+ \warning The value doesn't take in account any rotation set with the setTransform() method.
+
+ \sa zRotation(), setTransformOrigin(), {Transformations}
+*/
+void QGraphicsItem::setZRotation(qreal angle)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->zRotation = angle;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ This convenience function set the rotation angles around the 3 axes
+ to \a x, \a y and \a z.
+
+ \sa setXRotation(), setYRotation(), setZRotation(), {Transformations}
+*/
+void QGraphicsItem::setRotation(qreal x, qreal y, qreal z)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xRotation = x;
+ d_ptr->transformData->yRotation = y;
+ d_ptr->transformData->zRotation = z;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the scale factor on the X axis.
+
+ The default is 1
+
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
+
+ \sa setXScale(), {Transformations}
+*/
+qreal QGraphicsItem::xScale() const
+{
+ if (!d_ptr->transformData)
+ return 1;
+ return d_ptr->transformData->xScale;
+}
+
+/*!
+ \since 4.6
+
+ Sets the scale factor on the X axis to \a factor.
+
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
+
+ \sa xScale(), setTransformOrigin(), {Transformations}
+*/
+void QGraphicsItem::setXScale(qreal factor)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xScale = factor;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the scale factor on the Y axis.
+
+ The default is 1
+
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
+
+ \sa setYScale(), {Transformations}
+*/
+qreal QGraphicsItem::yScale() const
+{
+ if (!d_ptr->transformData)
+ return 1;
+ return d_ptr->transformData->yScale;
+}
+
+/*!
+ \since 4.6
+
+ Sets the scale factor on the Y axis to \a factor.
+
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
+
+ \sa yScale(), setTransformOrigin(), {Transformations}
+*/
+void QGraphicsItem::setYScale(qreal factor)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->yScale = factor;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ This convenience function set the scaling factors on X and Y axis to \a sx and \a sy.
+
+ \warning The value doesn't take in account any scaling set with the setTransform() method.
+
+ \sa setXScale(), setYScale(), {Transformations}
+*/
+void QGraphicsItem::setScale(qreal sx, qreal sy)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xScale = sx;
+ d_ptr->transformData->yScale = sy;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the horizontal shear.
+
+ The default is 0
+
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
+
+ \sa setHorizontalShear(), {Transformations}
+*/
+qreal QGraphicsItem::horizontalShear() const
+{
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->horizontalShear;
+}
+
+/*!
+ \since 4.6
+
+ Sets the horizontal shear to \a shear.
+
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
+
+ \sa horizontalShear(), {Transformations}
+*/
+void QGraphicsItem::setHorizontalShear(qreal shear)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->horizontalShear = shear;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the vertical shear.
+
+ The default is 0
+
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
+
+ \sa setHorizontalShear(), {Transformations}
+*/
+qreal QGraphicsItem::verticalShear() const
+{
+ if (!d_ptr->transformData)
+ return 0;
+ return d_ptr->transformData->verticalShear;
+}
+
+/*!
+ \since 4.6
+
+ Sets the vertical shear to \a shear.
+
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
+
+ \sa verticalShear(), {Transformations}
+*/
+void QGraphicsItem::setVerticalShear(qreal shear)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->verticalShear = shear;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ This convenience function sets the horizontal shear to \a sh and the vertical shear to \a sv.
+
+ \warning The value doesn't take in account any shearing set with the setTransform() method.
+
+ \sa setHorizontalShear(), setVerticalShear()
+*/
+void QGraphicsItem::setShear(qreal sh, qreal sv)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->horizontalShear = sh;
+ d_ptr->transformData->verticalShear = sv;
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \since 4.6
+
+ Returns the origin point used for transformation in item coordinate.
+
+ The default is QPointF(0,0).
+
+ \sa setTransformOrigin(), {Transformations}
+*/
+QPointF QGraphicsItem::transformOrigin() const
+{
+ if (!d_ptr->transformData)
+ return QPointF(0,0);
+ return QPointF(d_ptr->transformData->xOrigin, d_ptr->transformData->yOrigin);
+}
+
+/*!
+ \since 4.6
+
+ Sets the \a origin for transformation in item coordinate
+
+ \sa transformOrigin(), {Transformations}
+*/
+void QGraphicsItem::setTransformOrigin(const QPointF &origin)
+{
+ prepareGeometryChange();
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+ d_ptr->transformData->xOrigin = origin.x();
+ d_ptr->transformData->yOrigin = origin.y();
+ d_ptr->transformData->onlyTransform = false;
+ d_ptr->dirtySceneTransform = 1;
+}
+
+/*!
+ \fn void QGraphicsItem::setTransformOrigin(qreal x, qreal y)
+
+ \since 4.6
+ \overload
+
+ Sets the origin for the transformation to the point
+ composed of \a x and \a y.
+
+ \sa setTransformOrigin(), {Transformations}
+*/
+
+
+/*!
\obsolete
Use sceneTransform() instead.
@@ -2503,51 +3137,23 @@ QMatrix QGraphicsItem::sceneMatrix() const
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 4
Unlike transform(), which returns only an item's local transformation, this
- function includes the item's (and any parents') position.
+ function includes the item's (and any parents') position, and all the transfomation properties.
- \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}
+ \sa transform(), setTransform(), scenePos(), {The Graphics View Coordinate System}, {Transformations}
*/
QTransform QGraphicsItem::sceneTransform() const
{
- // Check if there's any entry in the transform cache.
- QGraphicsScenePrivate *sd = d_ptr->scene ? d_ptr->scene->d_func() : 0;
- int index = d_ptr->sceneTransformIndex;
- if (sd && index != -1 && sd->validTransforms.testBit(index))
- return sd->sceneTransformCache[index];
-
- // Calculate local transform.
- QTransform m;
- if (d_ptr->hasTransform) {
- m = transform();
- if (!d_ptr->pos.isNull())
- m *= QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- } else if (!d_ptr->pos.isNull()) {
- m = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- }
-
- // Combine with parent and add to cache.
- if (d_ptr->parent) {
- m *= d_ptr->parent->sceneTransform();
- // Don't cache toplevels
- if (sd) {
- if (index == -1) {
- if (!sd->freeSceneTransformSlots.isEmpty()) {
- index = sd->freeSceneTransformSlots.last();
- sd->freeSceneTransformSlots.pop_back();
- } else {
- index = sd->sceneTransformCache.size();
- }
- d_ptr->sceneTransformIndex = index;
- if (index >= sd->validTransforms.size()) {
- sd->validTransforms.resize(index + 1);
- sd->sceneTransformCache.resize(index + 1);
- }
- }
- sd->validTransforms.setBit(index, 1);
- sd->sceneTransformCache[index] = m;
- }
+ if (d_ptr->dirtySceneTransform) {
+ // This item and all its descendants have dirty scene transforms.
+ // We're about to validate this item's scene transform, so we have to
+ // invalidate all the children; otherwise there's no way for the descendants
+ // to detect that the ancestor has changed.
+ d_ptr->invalidateChildrenSceneTransform();
}
- return m;
+
+ QGraphicsItem *that = const_cast<QGraphicsItem *>(this);
+ d_ptr->ensureSceneTransformRecursive(&that);
+ return d_ptr->sceneTransform;
}
/*!
@@ -2597,17 +3203,17 @@ QTransform QGraphicsItem::deviceTransform(const QTransform &viewportTransform) c
// First translate the base untransformable item.
QPointF mappedPoint = (untransformedAncestor->sceneTransform() * viewportTransform).map(QPointF(0, 0));
+
+ // COMBINE
QTransform matrix;
matrix.translate(mappedPoint.x(), mappedPoint.y());
- matrix = untransformedAncestor->transform() * matrix;
+ if (untransformedAncestor->d_ptr->transformData)
+ matrix = untransformedAncestor->d_ptr->transformData->computedFullTransform(&matrix);
// Then transform and translate all children.
for (int i = 0; i < parents.size(); ++i) {
const QGraphicsItem *parent = parents.at(i);
- QPointF pos = parent->pos();
- QTransform moveMatrix;
- moveMatrix.translate(pos.x(), pos.y());
- matrix = (parent->transform() * moveMatrix) * matrix;
+ parent->d_ptr->combineTransformFromParent(&matrix);
}
return matrix;
@@ -2650,51 +3256,40 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
if (parent == other) {
if (ok)
*ok = true;
- const QPointF &itemPos = d_ptr->pos;
- if (itemPos.isNull())
- return d_ptr->hasTransform ? transform() : QTransform();
- if (d_ptr->hasTransform)
- return transform() * QTransform::fromTranslate(itemPos.x(), itemPos.y());
- return QTransform::fromTranslate(itemPos.x(), itemPos.y());
+ QTransform x;
+ d_ptr->combineTransformFromParent(&x);
+ return x;
}
// This is other's parent
if (otherParent == this) {
const QPointF &otherPos = other->d_ptr->pos;
- if (other->d_ptr->hasTransform) {
- QTransform otherToParent = other->transform();
- if (!otherPos.isNull())
- otherToParent *= QTransform::fromTranslate(otherPos.x(), otherPos.y());
+ if (other->d_ptr->transformData) {
+ QTransform otherToParent;
+ other->d_ptr->combineTransformFromParent(&otherToParent);
return otherToParent.inverted(ok);
- } else {
- if (ok)
- *ok = true;
- return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
}
+ if (ok)
+ *ok = true;
+ return QTransform::fromTranslate(-otherPos.x(), -otherPos.y());
}
// Siblings
if (parent == otherParent) {
- bool hasTr = d_ptr->hasTransform;
- bool otherHasTr = other->d_ptr->hasTransform;
+ // COMBINE
const QPointF &itemPos = d_ptr->pos;
const QPointF &otherPos = other->d_ptr->pos;
-
- if (!hasTr && !otherHasTr) {
+ if (!d_ptr->transformData && !other->d_ptr->transformData) {
QPointF delta = itemPos - otherPos;
if (ok)
*ok = true;
return QTransform::fromTranslate(delta.x(), delta.y());
}
- QTransform itemToParent = QTransform::fromTranslate(itemPos.x(), itemPos.y());
- if (hasTr)
- itemToParent = itemPos.isNull() ? transform() : transform() * itemToParent;
-
- QTransform otherToParent = QTransform::fromTranslate(otherPos.x(), otherPos.y());
- if (otherHasTr)
- otherToParent = otherPos.isNull() ? other->transform() : other->transform() * otherToParent;
-
+ QTransform itemToParent;
+ d_ptr->combineTransformFromParent(&itemToParent);
+ QTransform otherToParent;
+ other->d_ptr->combineTransformFromParent(&otherToParent);
return itemToParent * otherToParent.inverted(ok);
}
@@ -2730,11 +3325,7 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
QTransform x;
const QGraphicsItem *p = child;
do {
- const QGraphicsItemPrivate *pd = p->d_ptr.data();
- if (pd->hasTransform)
- x *= p->transform();
- if (!pd->pos.isNull())
- x *= QTransform::fromTranslate(pd->pos.x(), pd->pos.y());
+ p->d_ptr->.data()->combineTransformToParent(&x);
} while ((p = p->d_ptr->parent) && p != root);
if (parentOfOther)
return x.inverted(ok);
@@ -2752,37 +3343,34 @@ QTransform QGraphicsItem::itemTransform(const QGraphicsItem *other, bool *ok) co
Use setTransform() instead.
- \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System}
+ \sa transform(), {The Graphics View Coordinate System}
*/
void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
- QTransform newTransform;
- if (!combine)
- newTransform = QTransform(matrix);
- else
- newTransform = QTransform(matrix) * oldTransform;
- if (oldTransform == newTransform)
- return;
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
- // Notify the item that the matrix is changing.
- QVariant newTransformVariant(itemChange(ItemMatrixChange,
- qVariantFromValue<QMatrix>(newTransform.toAffine())));
- newTransform = QTransform(qVariantValue<QMatrix>(newTransformVariant));
- if (oldTransform == newTransform)
+ QTransform newTransform(combine ? QTransform(matrix) * d_ptr->transformData->transform : QTransform(matrix));
+ if (d_ptr->transformData->transform == newTransform)
return;
// Update and set the new transformation.
- d_ptr->fullUpdateHelper(true, true);
- prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
- d_ptr->invalidateSceneTransformCache();
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setTransformHelper(newTransform);
+ return;
+ }
+
+ // Notify the item that the transformation matrix is changing.
+ const QVariant newMatrixVariant = qVariantFromValue<QMatrix>(newTransform.toAffine());
+ newTransform = QTransform(qVariantValue<QMatrix>(itemChange(ItemMatrixChange, newMatrixVariant)));
+ if (d_ptr->transformData->transform == newTransform)
+ return;
+ // Update and set the new transformation.
+ d_ptr->setTransformHelper(newTransform);
+
// Send post-notification.
- // NB! We have to change the value from QMatrix to QTransform.
- qVariantSetValue<QTransform>(newTransformVariant, newTransform);
- itemChange(ItemTransformHasChanged, newTransformVariant);
+ itemChange(ItemTransformHasChanged, qVariantFromValue<QTransform>(newTransform));
}
/*!
@@ -2800,32 +3388,34 @@ void QGraphicsItem::setMatrix(const QMatrix &matrix, bool combine)
to map an item coordiate to a scene coordinate, or mapFromScene() to map
from scene coordinates to item coordinates.
- \sa transform(), rotate(), scale(), shear(), translate(), {The Graphics View Coordinate System}
+ \warning using this function doesnt affect the value of the transformation properties
+
+ \sa transform(), setRotation(), setScale(), setShear(), setTransformOrigin(), {The Graphics View Coordinate System}, {Transformations}
*/
void QGraphicsItem::setTransform(const QTransform &matrix, bool combine)
{
- QTransform oldTransform = this->transform();
- QTransform newTransform;
- if (!combine)
- newTransform = matrix;
- else
- newTransform = matrix * oldTransform;
- if (oldTransform == newTransform)
+ if (!d_ptr->transformData)
+ d_ptr->transformData = new QGraphicsItemPrivate::TransformData;
+
+ QTransform newTransform(combine ? matrix * d_ptr->transformData->transform : matrix);
+ if (d_ptr->transformData->transform == newTransform)
return;
+ // Update and set the new transformation.
+ if (!(d_ptr->flags & ItemSendsGeometryChanges)) {
+ d_ptr->setTransformHelper(newTransform);
+ return;
+ }
+
// Notify the item that the transformation matrix is changing.
const QVariant newTransformVariant(itemChange(ItemTransformChange,
qVariantFromValue<QTransform>(newTransform)));
newTransform = qVariantValue<QTransform>(newTransformVariant);
- if (oldTransform == newTransform)
+ if (d_ptr->transformData->transform == newTransform)
return;
// Update and set the new transformation.
- d_ptr->fullUpdateHelper(true, true);
- prepareGeometryChange();
- d_ptr->hasTransform = !newTransform.isIdentity();
- d_ptr->setExtra(QGraphicsItemPrivate::ExtraTransform, newTransform);
- d_ptr->invalidateSceneTransformCache();
+ d_ptr->setTransformHelper(newTransform);
// Send post-notification.
itemChange(ItemTransformHasChanged, newTransformVariant);
@@ -2844,8 +3434,9 @@ void QGraphicsItem::resetMatrix()
/*!
\since 4.3
- Resets this item's transformation matrix to the identity matrix. This is
- equivalent to calling \c setTransform(QTransform()).
+ Resets this item's transformation matrix to the identity matrix or
+ all the transformation properties to their default values.
+ This is equivalent to calling \c setTransform(QTransform()).
\sa setTransform(), transform()
*/
@@ -2855,6 +3446,9 @@ void QGraphicsItem::resetTransform()
}
/*!
+ \obsolete
+ Use setZRotation() instead
+
Rotates the current item transformation \a angle degrees clockwise around
its origin. To translate around an arbitrary point (x, y), you need to
combine translation and rotation with setTransform().
@@ -2863,6 +3457,8 @@ void QGraphicsItem::resetTransform()
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 6
+ \warning using this functionhas no effect on the zRotation value
+
\sa setTransform(), transform(), scale(), shear(), translate()
*/
void QGraphicsItem::rotate(qreal angle)
@@ -2871,6 +3467,9 @@ void QGraphicsItem::rotate(qreal angle)
}
/*!
+ \obsolete
+ Use setScale() instead
+
Scales the current item transformation by (\a sx, \a sy) around its
origin. To scale from an arbitrary point (x, y), you need to combine
translation and scaling with setTransform().
@@ -2879,7 +3478,9 @@ void QGraphicsItem::rotate(qreal angle)
\snippet doc/src/snippets/code/src_gui_graphicsview_qgraphicsitem.cpp 7
- \sa setTransform(), transform(), rotate(), shear(), translate()
+ \warning using this function has no effect on the xScale or yScale value
+
+ \sa setTransform(), transform()
*/
void QGraphicsItem::scale(qreal sx, qreal sy)
{
@@ -2887,9 +3488,14 @@ void QGraphicsItem::scale(qreal sx, qreal sy)
}
/*!
+ \obsolete
+ Use setShear instead.
+
Shears the current item transformation by (\a sh, \a sv).
- \sa setTransform(), transform(), rotate(), scale(), translate()
+ \warning using this function has no effect on the horizontalShear or verticalShear value
+
+ \sa setTransform(), transform()
*/
void QGraphicsItem::shear(qreal sh, qreal sv)
{
@@ -2897,13 +3503,16 @@ void QGraphicsItem::shear(qreal sh, qreal sv)
}
/*!
+ \obsolete
+ Use setPos() or setTransformOrigin() instead.
+
Translates the current item transformation by (\a dx, \a dy).
If all you want is to move an item, you should call moveBy() or
setPos() instead; this function changes the item's translation,
which is conceptually separate from its position.
- \sa setTransform(), transform(), rotate(), scale(), shear()
+ \sa setTransform(), transform()
*/
void QGraphicsItem::translate(qreal dx, qreal dy)
{
@@ -2948,11 +3557,11 @@ qreal QGraphicsItem::zValue() const
/*!
Sets the Z-value, or the elevation, of the item, to \a z. The elevation
decides the stacking order of sibling (neighboring) items. An item of high
- Z-value will be drawn on top of an item with a lower Z-value if they
- share the same parent item. In addition, children of an item will always be drawn
- on top of the parent, regardless of the child's Z-value. Sibling items
- that share the same Z-value will be drawn in an undefined order, although
- the order will stay the same for as long as the items live.
+ Z-value will be drawn on top of an item with a lower Z-value if they share
+ the same parent item. In addition, children of an item will always be
+ drawn on top of the parent, regardless of the child's Z-value. Sibling
+ items that share the same Z-value will be drawn in order of insertion; the
+ last inserted child is stacked above previous children.
\img graphicsview-zorder.png
@@ -2980,16 +3589,23 @@ void QGraphicsItem::setZValue(qreal z)
qreal newZ = qreal(newZVariant.toDouble());
if (newZ == d_ptr->z)
return;
- d_ptr->z = z;
- d_ptr->fullUpdateHelper();
+ d_ptr->z = newZ;
+ if (d_ptr->parent)
+ d_ptr->parent->d_ptr->needSortChildren = 1;
+ else if (d_ptr->scene)
+ d_ptr->scene->d_func()->needSortTopLevelItems = 1;
if (d_ptr->scene) {
+ d_ptr->scene->d_func()->markDirty(this, QRectF(), /*invalidateChildren=*/true);
// Invalidate any sort caching; arrival of a new item means we need to
// resort.
d_ptr->scene->d_func()->invalidateSortCache();
}
itemChange(ItemZValueHasChanged, newZVariant);
+
+ if (d_ptr->isObject)
+ emit static_cast<QGraphicsObject *>(this)->zChanged();
}
/*!
@@ -3011,14 +3627,12 @@ void QGraphicsItem::setZValue(qreal z)
*/
QRectF QGraphicsItem::childrenBoundingRect() const
{
+ if (!d_ptr->dirtyChildrenBoundingRect)
+ return d_ptr->childrenBoundingRect;
+
QRectF childRect;
- foreach (QGraphicsItem *child, children()) {
- QPointF childPos = child->pos();
- QTransform matrix = child->transform();
- if (!childPos.isNull())
- matrix *= QTransform::fromTranslate(childPos.x(), childPos.y());
- childRect |= matrix.mapRect(child->boundingRect() | child->childrenBoundingRect());
- }
+ QTransform x;
+ d_ptr->childrenBoundingRectHelper(&x, &childRect);
return childRect;
}
@@ -3032,7 +3646,7 @@ QRectF QGraphicsItem::childrenBoundingRect() const
Although the item's shape can be arbitrary, the bounding rect is
always rectangular, and it is unaffected by the items'
- transformation (scale(), rotate(), etc.).
+ transformation.
If you want to change the item's bounding rectangle, you must first call
prepareGeometryChange(). This notifies the scene of the imminent change,
@@ -3064,12 +3678,13 @@ QRectF QGraphicsItem::childrenBoundingRect() const
QRectF QGraphicsItem::sceneBoundingRect() const
{
// Find translate-only offset
+ // COMBINE
QPointF offset;
const QGraphicsItem *parentItem = this;
const QGraphicsItemPrivate *itemd;
do {
itemd = parentItem->d_ptr.data();
- if (itemd->hasTransform)
+ if (itemd->transformData)
break;
offset += itemd->pos;
} while ((parentItem = itemd->parent));
@@ -3633,7 +4248,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity)
All painting is done in local coordinates.
- \sa setCacheMode(), QPen::width(), {Item Coordinates}
+ \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption
*/
/*!
@@ -3646,7 +4261,7 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore
// No scene, or if the scene is updating everything, means we have nothing
// to do. The only exception is if the scene tracks the growing scene rect.
return (!visible && !ignoreVisibleBit)
- || (dirty && !ignoreDirtyBit)
+ || (!ignoreDirtyBit && fullUpdatePending)
|| !scene
|| (scene->d_func()->updateAll && scene->d_func()->hasSceneRect)
|| (!ignoreClipping && (childrenClippedToShape() && isClippedAway()))
@@ -3656,163 +4271,43 @@ bool QGraphicsItemPrivate::discardUpdateRequest(bool ignoreClipping, bool ignore
/*!
\internal
- Asks the scene to mark this item's scene rect as dirty, requesting a
- redraw. This does not invalidate any cache.
-
- The \a force argument is for the update call in setVisible(), which is the
- only case where the item's background should be marked as dirty even when
- the item isn't visible.
+ Resolves the stacking depth of this object and all its children.
*/
-void QGraphicsItemPrivate::updateHelper(const QRectF &rect, bool force, bool maybeDirtyClipPath)
+void QGraphicsItemPrivate::resolveDepth(int parentDepth)
{
- // No scene, or if the scene is updating everything, means we have nothing
- // to do. The only exception is if the scene tracks the growing scene rect.
- if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/force))
- return;
-
- if (rect.isNull())
- dirty = 1;
- scene->itemUpdated(q_ptr, rect);
+ depth = parentDepth + 1;
+ for (int i = 0; i < children.size(); ++i)
+ children.at(i)->d_ptr->resolveDepth(depth);
}
/*!
\internal
-
- Propagates updates to \a item and all its children.
*/
-void QGraphicsItemPrivate::fullUpdateHelper(bool childrenOnly, bool maybeDirtyClipPath, bool ignoreOpacity)
+void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
{
- if (discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath, /*ignoreVisibleBit=*/false,
- /*ignoreDirtyBit=*/true, ignoreOpacity)) {
- return;
- }
-
- if (!childrenOnly && !dirty) {
- // Effectively the same as updateHelper(QRectF(), false, maybeDirtyClipPath).
- dirty = 1;
- scene->itemUpdated(q_ptr, QRectF());
- }
-
- if (dirtyChildren || childrenClippedToShape()) {
- // Unnecessary to update children as well.
- return;
- }
-
- if (ancestorFlags & AncestorClipsChildren) {
- Q_Q(QGraphicsItem);
- // Check if we can avoid updating all children.
- QGraphicsItem *p = parent;
- QRectF br = q->boundingRect();
- while (p) {
- if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
- bool ok;
- QTransform x = q->itemTransform(p, &ok);
- if (!ok)
- break;
- if (x.mapRect(br).contains(p->boundingRect()))
- return;
- }
- p = p->d_ptr->parent;
- if (!p || !(p->d_ptr->ancestorFlags & AncestorClipsChildren))
- break;
- // ### check one level only
- break;
- }
- }
- foreach (QGraphicsItem *child, children)
- child->d_ptr->fullUpdateHelper(false, maybeDirtyClipPath);
- dirtyChildren = 1;
-}
-
-static inline bool qt_allChildrenCombineOpacity(QGraphicsItem *parent)
-{
- Q_ASSERT(parent);
- if (parent->flags() & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
- return false;
-
- const QList<QGraphicsItem *> children(parent->childItems());
- for (int i = 0; i < children.size(); ++i) {
- if (children.at(i)->flags() & QGraphicsItem::ItemIgnoresParentOpacity)
- return false;
- }
- return true;
-}
-
-void QGraphicsItemPrivate::updateEffectiveOpacity()
-{
- Q_Q(QGraphicsItem);
- if (parent) {
- resolveEffectiveOpacity(parent->effectiveOpacity());
- parent->d_ptr->allChildrenCombineOpacity = qt_allChildrenCombineOpacity(parent);
- } else {
- resolveEffectiveOpacity(1.0);
- }
- allChildrenCombineOpacity = qt_allChildrenCombineOpacity(q);
+ needSortChildren = 1;
+ children.append(child);
}
/*!
\internal
-
- Resolves and propagates this item's effective opacity to its children.
*/
-void QGraphicsItemPrivate::resolveEffectiveOpacity(qreal parentEffectiveOpacity)
+void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
{
- Q_Q(QGraphicsItem);
- QGraphicsItem::GraphicsItemFlags myFlags = q->flags();
- QGraphicsItem::GraphicsItemFlags parentFlags = parent ? parent->flags() : QGraphicsItem::GraphicsItemFlags(0);
-
- // My local opacity is always part of my effective opacity.
- qreal myEffectiveOpacity = q->opacity();
-
- // If I have a parent, and I don't ignore my parent's opacity, and my
- // parent propagates to me, then combine my local opacity with my parent's
- // effective opacity into my effective opacity.
- if (parent
- && !(myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
- && !(parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
- myEffectiveOpacity *= parentEffectiveOpacity;
- }
-
- // Set this item's resolved opacity.
- if (qFuzzyCompare(myEffectiveOpacity, qreal(1.0))) {
- // Opaque, unset effective opacity.
- hasEffectiveOpacity = 0;
- unsetExtra(ExtraEffectiveOpacity);
- } else {
- hasEffectiveOpacity = 1;
- setExtra(ExtraEffectiveOpacity, myEffectiveOpacity);
- }
-
- // Resolve children always.
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->resolveEffectiveOpacity(myEffectiveOpacity);
+ children.removeOne(child);
}
/*!
\internal
-
- Resolves the stacking depth of this object and all its children.
*/
-void QGraphicsItemPrivate::resolveDepth(int parentDepth)
+QGraphicsItemCache *QGraphicsItemPrivate::maybeExtraItemCache() const
{
- depth = parentDepth + 1;
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->resolveDepth(depth);
+ return (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
}
/*!
\internal
*/
-void QGraphicsItemPrivate::invalidateSceneTransformCache()
-{
- if (!scene || (parent && sceneTransformIndex == -1))
- return;
- if (sceneTransformIndex != -1)
- scene->d_func()->validTransforms.setBit(sceneTransformIndex, 0);
- for (int i = 0; i < children.size(); ++i)
- children.at(i)->d_ptr->invalidateSceneTransformCache();
-}
-
QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
{
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
@@ -3824,6 +4319,9 @@ QGraphicsItemCache *QGraphicsItemPrivate::extraItemCache() const
return c;
}
+/*!
+ \internal
+*/
void QGraphicsItemPrivate::removeExtraItemCache()
{
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
@@ -3885,17 +4383,13 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
// Find closest clip ancestor and transform.
Q_Q(QGraphicsItem);
- QTransform thisToParentTransform = hasTransform
- ? q->transform() * QTransform::fromTranslate(newPos.x(), newPos.y())
- : QTransform::fromTranslate(newPos.x(), newPos.y());
+ // COMBINE
+ QTransform thisToParentTransform = QTransform::fromTranslate(newPos.x(), newPos.y());
+ if (transformData)
+ thisToParentTransform = transformData->computedFullTransform(&thisToParentTransform);
QGraphicsItem *clipParent = parent;
while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)) {
- if (clipParent->d_ptr->hasTransform)
- thisToParentTransform *= clipParent->transform();
- if (!clipParent->d_ptr->pos.isNull()) {
- thisToParentTransform *= QTransform::fromTranslate(clipParent->d_ptr->pos.x(),
- clipParent->d_ptr->pos.y());
- }
+ thisToParentTransform *= clipParent->d_ptr->transformToParent();
clipParent = clipParent->d_ptr->parent;
}
@@ -3937,6 +4431,35 @@ void QGraphicsItemPrivate::updateCachedClipPathFromSetPosHelper(const QPointF &n
}
}
+// Traverses all the ancestors up to the top-level and updates the pointer to
+// always point to the top-most item that has a dirty scene transform.
+// It then backtracks to the top-most dirty item and start calculating the
+// scene transform by combining the item's transform (+pos) with the parent's
+// cached scene transform (which we at this point know for sure is valid).
+void QGraphicsItemPrivate::ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem)
+{
+ Q_ASSERT(topMostDirtyItem);
+
+ if (dirtySceneTransform)
+ *topMostDirtyItem = q_ptr;
+
+ if (parent)
+ parent->d_ptr->ensureSceneTransformRecursive(topMostDirtyItem);
+
+ if (*topMostDirtyItem == q_ptr) {
+ if (!dirtySceneTransform)
+ return; // OK, neither my ancestors nor I have dirty scene transforms.
+ *topMostDirtyItem = 0;
+ } else if (*topMostDirtyItem) {
+ return; // Continue backtrack.
+ }
+
+ // COMBINE my transform with the parent's scene transform.
+ sceneTransform = parent ? parent->d_ptr->sceneTransform : QTransform();
+ combineTransformFromParent(&sceneTransform);
+ dirtySceneTransform = 0;
+}
+
/*!
\internal
@@ -3979,25 +4502,62 @@ void QGraphicsItem::update(const QRectF &rect)
}
// Invalidate cache.
- if (rect.isNull()) {
- cache->allExposed = true;
- cache->exposed.clear();
- } else {
- cache->exposed.append(rect);
+ if (!cache->allExposed) {
+ if (rect.isNull()) {
+ cache->allExposed = true;
+ cache->exposed.clear();
+ } else {
+ cache->exposed.append(rect);
+ }
}
// Only invalidate cache; item is already dirty.
- if (d_ptr->dirty)
+ if (d_ptr->fullUpdatePending)
return;
- } else if (d_ptr->discardUpdateRequest()) {
- return;
}
- // Effectively the same as updateHelper(rect);
- if (rect.isNull())
- d_ptr->dirty = 1;
- d_ptr->scene->itemUpdated(this, rect);
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this, rect);
}
+/*!
+ \internal
+
+ Scrolls \a rect in \a pix by \a dx, \a dy.
+
+ ### This can be done much more efficiently by using XCopyArea on X11 with
+ the same dst and src, and through moving pixels in the raster engine. It
+ can probably also be done much better on the other paint engines.
+*/
+void _q_scrollPixmap(QPixmap *pix, const QRect &rect, int dx, int dy)
+{
+#if 0
+ QPainter painter(pix);
+ painter.setClipRect(rect);
+ painter.drawPixmap(rect.translated(dx, dy), *pix, rect);
+ painter.end();
+#elif defined Q_WS_X11
+ GC gc = XCreateGC(X11->display, pix->handle(), 0, 0);
+
+ XRectangle xrect;
+ xrect.x = rect.x();
+ xrect.y = rect.y();
+ xrect.width = rect.width();
+ xrect.height = rect.height();
+ XSetClipRectangles(X11->display, gc, 0, 0, &xrect, 1, YXBanded);
+
+ XCopyArea(X11->display, pix->handle(), pix->handle(), gc,
+ rect.x(), rect.y(), rect.width(), rect.height(),
+ rect.x()+dx, rect.y()+dy);
+ XFreeGC(X11->display, gc);
+#else
+ QPixmap newPix = *pix;
+ QPainter painter(&newPix);
+ painter.setClipRect(rect);
+ painter.drawPixmap(rect.translated(dx, dy), *pix, rect);
+ painter.end();
+ *pix = newPix;
+#endif
+}
/*!
\since 4.4
@@ -4026,11 +4586,45 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
if (!d->scene)
return;
if (d->cacheMode != NoCache) {
- // ### This is very slow, and can be done much better. If the cache is
- // local and matches the below criteria for rotation and scaling, we
- // can easily scroll. And if the cache is in device coordinates, we
- // can scroll both the viewport and the cache.
- update(rect);
+ QGraphicsItemCache *c;
+ bool scrollCache = qFuzzyIsNull(dx - int(dx)) && qFuzzyIsNull(dy - int(dy))
+ && (c = (QGraphicsItemCache *)qVariantValue<void *>(d_ptr->extra(QGraphicsItemPrivate::ExtraCacheData)))
+ && (d->cacheMode == ItemCoordinateCache && !c->fixedSize.isValid());
+ if (scrollCache) {
+ QPixmap pix;
+ if (QPixmapCache::find(c->key, &pix)) {
+ // Adjust with 2 pixel margin. Notice the loss of precision
+ // when converting to QRect.
+ int adjust = 2;
+ QRectF br = boundingRect().adjusted(-adjust, -adjust, adjust, adjust);
+ QRect irect = rect.toRect().translated(-br.x(), -br.y());
+
+ _q_scrollPixmap(&pix, irect, dx, dy);
+
+ QPixmapCache::replace(c->key, pix);
+
+ // Translate the existing expose.
+ foreach (QRectF exposedRect, c->exposed)
+ c->exposed += exposedRect.translated(dx, dy) & rect;
+
+ // Calculate exposure.
+ QRegion exposed;
+ QRect r = rect.toRect();
+ exposed += r;
+ exposed -= r.translated(dx, dy);
+ foreach (QRect rect, exposed.rects())
+ update(rect);
+ d->scene->d_func()->markDirty(this);
+ } else {
+ update(rect);
+ }
+ } else {
+ // ### This is very slow, and can be done much better. If the cache is
+ // local and matches the below criteria for rotation and scaling, we
+ // can easily scroll. And if the cache is in device coordinates, we
+ // can scroll both the viewport and the cache.
+ update(rect);
+ }
return;
}
@@ -4049,13 +4643,7 @@ void QGraphicsItem::scroll(qreal dx, qreal dy, const QRectF &rect)
static const QLineF left(0, 0, -1, 0);
static const QLineF right(0, 0, 1, 0);
- QTransform deviceTr;
- if (d->itemIsUntransformable()) {
- deviceTr = deviceTransform(view->viewportTransform());
- } else {
- deviceTr = sceneTransform() * view->viewportTransform();
- }
-
+ QTransform deviceTr = deviceTransform(view->viewportTransform());
QRect deviceScrollRect = deviceTr.mapRect(scrollRect).toRect();
QLineF v1 = deviceTr.map(right);
QLineF v2 = deviceTr.map(down);
@@ -4187,7 +4775,10 @@ QPointF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPointF &point
*/
QPointF QGraphicsItem::mapToParent(const QPointF &point) const
{
- return d_ptr->pos + (d_ptr->hasTransform ? transform().map(point) : point);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return point + d_ptr->pos;
+ return d_ptr->transformToParent().map(point);
}
/*!
@@ -4252,9 +4843,10 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QRectF &rect
*/
QPolygonF QGraphicsItem::mapToParent(const QRectF &rect) const
{
- QPolygonF p = !d_ptr->hasTransform ? rect : transform().map(rect);
- p.translate(d_ptr->pos);
- return p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(rect);
}
/*!
@@ -4321,8 +4913,10 @@ QRectF QGraphicsItem::mapRectToItem(const QGraphicsItem *item, const QRectF &rec
*/
QRectF QGraphicsItem::mapRectToParent(const QRectF &rect) const
{
- QRectF r = !d_ptr->hasTransform ? rect : transform().mapRect(rect);
- return r.translated(d_ptr->pos);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(d_ptr->pos);
+ return d_ptr->transformToParent().mapRect(rect);
}
/*!
@@ -4393,8 +4987,10 @@ QRectF QGraphicsItem::mapRectFromItem(const QGraphicsItem *item, const QRectF &r
*/
QRectF QGraphicsItem::mapRectFromParent(const QRectF &rect) const
{
- QRectF r = rect.translated(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().mapRect(r) : r;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().mapRect(rect);
}
/*!
@@ -4453,9 +5049,10 @@ QPolygonF QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPolygonF &p
*/
QPolygonF QGraphicsItem::mapToParent(const QPolygonF &polygon) const
{
- QPolygonF p = !d_ptr->hasTransform ? polygon : transform().map(polygon);
- p.translate(d_ptr->pos);
- return p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return polygon.translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(polygon);
}
/*!
@@ -4497,10 +5094,10 @@ QPainterPath QGraphicsItem::mapToItem(const QGraphicsItem *item, const QPainterP
*/
QPainterPath QGraphicsItem::mapToParent(const QPainterPath &path) const
{
- QTransform x = QTransform::fromTranslate(d_ptr->pos.x(), d_ptr->pos.y());
- if (d_ptr->hasTransform)
- x = transform() * x;
- return x.map(path);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return path.translated(d_ptr->pos);
+ return d_ptr->transformToParent().map(path);
}
/*!
@@ -4549,8 +5146,9 @@ QPointF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPointF &poi
*/
QPointF QGraphicsItem::mapFromParent(const QPointF &point) const
{
- if (d_ptr->hasTransform)
- return transform().inverted().map(point - d_ptr->pos);
+ // COMBINE
+ if (d_ptr->transformData)
+ return d_ptr->transformToParent().inverted().map(point);
return point - d_ptr->pos;
}
@@ -4617,8 +5215,10 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QRectF &re
*/
QPolygonF QGraphicsItem::mapFromParent(const QRectF &rect) const
{
- QRectF r = rect.translated(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(r) : r;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return rect.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(rect);
}
/*!
@@ -4673,9 +5273,10 @@ QPolygonF QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPolygonF
*/
QPolygonF QGraphicsItem::mapFromParent(const QPolygonF &polygon) const
{
- QPolygonF p = polygon;
- p.translate(-d_ptr->pos);
- return d_ptr->hasTransform ? transform().inverted().map(p) : p;
+ // COMBINE
+ if (!d_ptr->transformData)
+ return polygon.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(polygon);
}
/*!
@@ -4715,9 +5316,10 @@ QPainterPath QGraphicsItem::mapFromItem(const QGraphicsItem *item, const QPainte
*/
QPainterPath QGraphicsItem::mapFromParent(const QPainterPath &path) const
{
- if (d_ptr->parent)
- return d_ptr->parent->itemTransform(this).map(path);
- return mapFromScene(path);
+ // COMBINE
+ if (!d_ptr->transformData)
+ return path.translated(-d_ptr->pos);
+ return d_ptr->transformToParent().inverted().map(path);
}
/*!
@@ -5235,7 +5837,8 @@ void QGraphicsItem::focusOutEvent(QFocusEvent *event)
void QGraphicsItem::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
- d_ptr->updateHelper();
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this);
}
/*!
@@ -5263,7 +5866,8 @@ void QGraphicsItem::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
void QGraphicsItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
{
Q_UNUSED(event);
- d_ptr->updateHelper();
+ if (d_ptr->scene)
+ d_ptr->scene->d_func()->markDirty(this);
}
/*!
@@ -5693,7 +6297,6 @@ void QGraphicsItem::addToIndex()
}
if (d_ptr->scene)
d_ptr->scene->d_func()->addToIndex(this);
- d_ptr->updateHelper();
}
/*!
@@ -5709,7 +6312,6 @@ void QGraphicsItem::removeFromIndex()
// ### remove from child index only if applicable
return;
}
- d_ptr->updateHelper();
if (d_ptr->scene)
d_ptr->scene->d_func()->removeFromIndex(this);
}
@@ -5730,11 +6332,30 @@ void QGraphicsItem::removeFromIndex()
void QGraphicsItem::prepareGeometryChange()
{
if (d_ptr->scene) {
- d_ptr->updateHelper(QRectF(), false, /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
+ d_ptr->geometryChanged = 1;
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+
QGraphicsScenePrivate *scenePrivate = d_ptr->scene->d_func();
+ scenePrivate->markDirty(this, QRectF(),
+ /*invalidateChildren=*/true,
+ /*maybeDirtyClipPath=*/!d_ptr->inSetPosHelper);
+
+ // For compatibility reasons, we have to update the item's old geometry
+ // if someone is connected to the changed signal or the scene has no views.
+ // Note that this has to be done *after* markDirty to ensure that
+ // _q_processDirtyItems is called before _q_emitUpdated.
+ if ((scenePrivate->connectedSignals & scenePrivate->changedSignalMask)
+ || scenePrivate->views.isEmpty()) {
+ d_ptr->scene->update(sceneTransform().mapRect(boundingRect()));
+ }
+
scenePrivate->removeFromIndex(this);
}
+ QGraphicsItem *parent = this;
+ while ((parent = parent->d_ptr->parent))
+ parent->d_ptr->dirtyChildrenBoundingRect = 1;
+
if (d_ptr->inSetPosHelper)
return;
@@ -5756,7 +6377,7 @@ static void qt_graphicsItem_highlightSelected(
QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
{
const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
- if (qFuzzyCompare(qMax(murect.width(), murect.height()) + 1, 1))
+ if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
return;
const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
@@ -5806,6 +6427,172 @@ static void qt_graphicsItem_highlightSelected(
}
/*!
+ \class QGraphicsObject
+ \brief The QGraphicsObject class provides a base class for all graphics items that
+ require signals, slots and properties.
+ \since 4.6
+ \ingroup graphicsview-api
+
+ The class extends a QGraphicsItem with QObject's signal/slot and property mechanisms.
+ It maps many of QGraphicsItem's basic setters and getters to properties and adds notification
+ signals for many of them.
+*/
+
+/*!
+ Constructs a QGraphicsObject with \a parent.
+*/
+QGraphicsObject::QGraphicsObject(QGraphicsItem *parent)
+ : QGraphicsItem(parent)
+{
+ QGraphicsItem::d_ptr->isObject = true;
+}
+
+/*!
+ \internal
+*/
+QGraphicsObject::QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene)
+ : QGraphicsItem(dd, parent, scene)
+{
+ QGraphicsItem::d_ptr->isObject = true;
+}
+
+/*!
+ \property QGraphicsObject::parent
+ \brief the parent of the item
+
+ \sa QGraphicsItem::setParentItem(), QGraphicsItem::parentObject()
+*/
+
+/*!
+ \property QGraphicsObject::id
+ \brief the id of of the item
+
+ \sa QGraphicsItem::opacity(), QGraphicsItem::setOpacity()
+*/
+
+/*!
+ \property QGraphicsObject::opacity
+ \brief the opacity of the item
+
+ \sa QGraphicsItem::setOpacity(), QGraphicsItem::opacity()
+*/
+
+/*!
+ \fn QGraphicsObject::opacityChanged()
+
+ This signal gets emitted whenever the opacity of the item changes
+
+ \sa QGraphicsItem::opacity()
+*/
+
+/*!
+ \fn QGraphicsObject::parentChanged()
+
+ This signal gets emitted whenever the parent of the item changes
+*/
+
+/*!
+ \property QGraphicsObject::pos
+ \brief the position of the item
+
+ Describes the items position.
+
+ \sa QGraphicsItem::setPos(), QGraphicsItem::pos()
+*/
+
+/*!
+ \property QGraphicsObject::x
+ \brief the x position of the item
+
+ Describes the items x position.
+
+ \sa QGraphicsItem::setX(), setPos(), xChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::xChanged()
+
+ This signal gets emitted whenever the x position of the item changes
+
+ \sa pos()
+*/
+
+/*!
+ \property QGraphicsObject::y
+ \brief the y position of the item
+
+ Describes the items y position.
+
+ \sa QGraphicsItem::setY(), setPos(), yChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::yChanged()
+
+ This signal gets emitted whenever the y position of the item changes.
+
+ \sa pos()
+*/
+
+/*!
+ \property QGraphicsObject::z
+ \brief the z value of the item
+
+ Describes the items z value.
+
+ \sa QGraphicsItem::setZValue(), zValue(), zChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::zChanged()
+
+ This signal gets emitted whenever the z value of the item changes.
+
+ \sa pos()
+*/
+
+
+/*!
+ \property QGraphicsObject::enabled
+ \brief whether the item is enabled or not
+
+ This property is declared in QGraphicsItem.
+
+ By default, this property is true.
+
+ \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled(), enabledChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::enabledChanged()
+
+ This signal gets emitted whenever the item get's enabled or disabled.
+
+ \sa isEnabled()
+*/
+
+/*!
+ \property QGraphicsObject::visible
+ \brief whether the item is visible or not
+
+ This property is declared in QGraphicsItem.
+
+ By default, this property is true.
+
+ \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), visibleChanged()
+*/
+
+/*!
+ \fn QGraphicsObject::visibleChanged()
+
+ This signal gets emitted whenever the visibility of the item changes
+
+ \sa visible
+*/
+
+
+
+/*!
\class QAbstractGraphicsShapeItem
\brief The QAbstractGraphicsShapeItem class provides a common base for
all path items.
@@ -7395,7 +8182,6 @@ void QGraphicsPixmapItem::setTransformationMode(Qt::TransformationMode mode)
{
Q_D(QGraphicsPixmapItem);
if (mode != d->transformationMode) {
- d_ptr->updateHelper();
d->transformationMode = mode;
update();
}
@@ -7483,9 +8269,7 @@ void QGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsIte
painter->setRenderHint(QPainter::SmoothPixmapTransform,
(d->transformationMode == Qt::SmoothTransformation));
- QRectF exposed = option->exposedRect.adjusted(-1, -1, 1, 1);
- exposed &= QRectF(d->offset.x(), d->offset.y(), d->pixmap.width(), d->pixmap.height());
- painter->drawPixmap(exposed, d->pixmap, exposed.translated(-d->offset));
+ painter->drawPixmap(d->offset, d->pixmap);
if (option->state & QStyle::State_Selected)
qt_graphicsItem_highlightSelected(this, painter, option);
@@ -7634,6 +8418,7 @@ public:
QGraphicsTextItem *qq;
};
+
/*!
Constructs a QGraphicsTextItem, using \a text as the default plain
text. \a parent is passed to QGraphicsItem's constructor.
@@ -7646,13 +8431,14 @@ QGraphicsTextItem::QGraphicsTextItem(const QString &text, QGraphicsItem *parent
, QGraphicsScene *scene
#endif
)
- : QGraphicsItem(parent, scene), dd(new QGraphicsTextItemPrivate)
+ : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
{
dd->qq = this;
if (!text.isEmpty())
setPlainText(text);
setAcceptDrops(true);
setAcceptHoverEvents(true);
+ setFlags(ItemUsesExtendedStyleOption);
}
/*!
@@ -7667,11 +8453,12 @@ QGraphicsTextItem::QGraphicsTextItem(QGraphicsItem *parent
, QGraphicsScene *scene
#endif
)
- : QGraphicsItem(parent, scene), dd(new QGraphicsTextItemPrivate)
+ : QGraphicsObject(*new QGraphicsItemPrivate, parent, scene), dd(new QGraphicsTextItemPrivate)
{
dd->qq = this;
setAcceptDrops(true);
setAcceptHoverEvents(true);
+ setFlag(ItemUsesExtendedStyleOption);
}
/*!
@@ -7942,19 +8729,19 @@ bool QGraphicsTextItem::sceneEvent(QEvent *event)
void QGraphicsTextItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
if ((QGraphicsItem::d_ptr->flags & (ItemIsSelectable | ItemIsMovable))
- && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
- // User left-pressed on edge of selectable/movable item, use
- // base impl.
- dd->useDefaultImpl = true;
+ && (event->buttons() & Qt::LeftButton) && dd->_q_mouseOnEdge(event)) {
+ // User left-pressed on edge of selectable/movable item, use
+ // base impl.
+ dd->useDefaultImpl = true;
} else if (event->buttons() == event->button()
- && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
- // User pressed first button on non-interactive item.
- dd->useDefaultImpl = true;
+ && dd->control->textInteractionFlags() == Qt::NoTextInteraction) {
+ // User pressed first button on non-interactive item.
+ dd->useDefaultImpl = true;
}
if (dd->useDefaultImpl) {
QGraphicsItem::mousePressEvent(event);
- if (!event->isAccepted())
- dd->useDefaultImpl = false;
+ if (!event->isAccepted())
+ dd->useDefaultImpl = false;
return;
}
@@ -7991,14 +8778,14 @@ void QGraphicsTextItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
if (dd->useDefaultImpl) {
QGraphicsItem::mouseReleaseEvent(event);
- if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
- && !event->buttons()) {
- // User released last button on non-interactive item.
+ if (dd->control->textInteractionFlags() == Qt::NoTextInteraction
+ && !event->buttons()) {
+ // User released last button on non-interactive item.
dd->useDefaultImpl = false;
- } else if ((event->buttons() & Qt::LeftButton) == 0) {
- // User released the left button on an interactive item.
+ } else if ((event->buttons() & Qt::LeftButton) == 0) {
+ // User released the left button on an interactive item.
dd->useDefaultImpl = false;
- }
+ }
return;
}
@@ -8400,9 +9187,9 @@ bool QGraphicsTextItemPrivate::_q_mouseOnEdge(QGraphicsSceneMouseEvent *event)
Sets the flags \a flags to specify how the text item should react to user
input.
- The default for a QGraphicsTextItem is Qt::NoTextInteraction. Setting a
- value different to Qt::NoTextInteraction will also set the ItemIsFocusable
- QGraphicsItem flag.
+ The default for a QGraphicsTextItem is Qt::NoTextInteraction. This function
+ also affects the ItemIsFocusable QGraphicsItem flag by setting it if \a flags
+ is different from Qt::NoTextInteraction and clearing it otherwise.
By default, the text is read-only. To transform the item into an editor,
set the Qt::TextEditable flag.
@@ -8903,6 +9690,8 @@ void QGraphicsItemGroup::addToGroup(QGraphicsItem *item)
return;
}
+ // COMBINE
+ // ### Use itemTransform() instead.
QTransform oldSceneMatrix = item->sceneTransform();
item->setPos(mapFromItem(item, 0, 0));
item->setParentItem(this);
@@ -9141,6 +9930,15 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStacksBehindParent:
str = "ItemStacksBehindParent";
break;
+ case QGraphicsItem::ItemUsesExtendedStyleOption:
+ str = "ItemUsesExtendedStyleOption";
+ break;
+ case QGraphicsItem::ItemHasNoContents:
+ str = "ItemHasNoContents";
+ break;
+ case QGraphicsItem::ItemSendsGeometryChanges:
+ str = "ItemSendsGeometryChanges";
+ break;
}
debug << str;
return debug;
@@ -9148,17 +9946,17 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlags flags)
{
- debug << "(";
+ debug << '(';
bool f = false;
for (int i = 0; i < 9; ++i) {
if (flags & (1 << i)) {
if (f)
- debug << "|";
+ debug << '|';
f = true;
debug << QGraphicsItem::GraphicsItemFlag(int(flags & (1 << i)));
}
}
- debug << ")";
+ debug << ')';
return debug;
}
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 25678a6..989be43 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -64,6 +64,7 @@ class QBrush;
class QCursor;
class QFocusEvent;
class QGraphicsItemGroup;
+class QGraphicsObject;
class QGraphicsSceneContextMenuEvent;
class QGraphicsSceneDragDropEvent;
class QGraphicsSceneEvent;
@@ -95,7 +96,11 @@ public:
ItemIgnoresTransformations = 0x20,
ItemIgnoresParentOpacity = 0x40,
ItemDoesntPropagateOpacityToChildren = 0x80,
- ItemStacksBehindParent = 0x100
+ ItemStacksBehindParent = 0x100,
+ ItemUsesExtendedStyleOption = 0x200,
+ ItemHasNoContents = 0x400,
+ ItemSendsGeometryChanges = 0x800
+ // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
@@ -147,6 +152,7 @@ public:
QGraphicsItem *parentItem() const;
QGraphicsItem *topLevelItem() const;
+ QGraphicsObject *parentObject() const;
QGraphicsWidget *parentWidget() const;
QGraphicsWidget *topLevelWidget() const;
QGraphicsWidget *window() const;
@@ -156,6 +162,9 @@ public:
bool isWidget() const;
bool isWindow() const;
+ QGraphicsObject *toGraphicsObject();
+ const QGraphicsObject *toGraphicsObject() const;
+
QGraphicsItemGroup *group() const;
void setGroup(QGraphicsItemGroup *group);
@@ -220,7 +229,9 @@ public:
// Positioning in scene coordinates
QPointF pos() const;
inline qreal x() const { return pos().x(); }
+ void setX(qreal x);
inline qreal y() const { return pos().y(); }
+ void setY(qreal y);
QPointF scenePos() const;
void setPos(const QPointF &pos);
inline void setPos(qreal x, qreal y);
@@ -240,11 +251,41 @@ public:
QTransform itemTransform(const QGraphicsItem *other, bool *ok = 0) const;
void setTransform(const QTransform &matrix, bool combine = false);
void resetTransform();
-
- void rotate(qreal angle);
- void scale(qreal sx, qreal sy);
- void shear(qreal sh, qreal sv);
- void translate(qreal dx, qreal dy);
+
+ void rotate(qreal angle); // ### obsolete
+ void scale(qreal sx, qreal sy); // ### obsolete
+ void shear(qreal sh, qreal sv); // ### obsolete
+ void translate(qreal dx, qreal dy); // ### obsolete
+
+ qreal xRotation() const;
+ void setXRotation(qreal angle);
+
+ qreal yRotation() const;
+ void setYRotation(qreal angle);
+
+ qreal zRotation() const;
+ void setZRotation(qreal angle);
+ void setRotation(qreal x, qreal y, qreal z);
+
+ qreal xScale() const;
+ void setXScale(qreal factor);
+
+ qreal yScale() const;
+ void setYScale(qreal factor);
+ void setScale(qreal sx, qreal sy);
+
+ qreal horizontalShear() const;
+ void setHorizontalShear(qreal shear);
+
+ qreal verticalShear() const;
+ void setVerticalShear(qreal shear);
+ void setShear(qreal sh, qreal sv);
+
+ QPointF transformOrigin() const;
+ void setTransformOrigin(const QPointF &origin);
+ inline void setTransformOrigin(qreal x, qreal y)
+ { setTransformOrigin(QPointF(x,y)); }
+
virtual void advance(int phase);
// Stacking order
@@ -451,6 +492,39 @@ inline QRectF QGraphicsItem::mapRectFromParent(qreal ax, qreal ay, qreal w, qrea
inline QRectF QGraphicsItem::mapRectFromScene(qreal ax, qreal ay, qreal w, qreal h) const
{ return mapRectFromScene(QRectF(ax, ay, w, h)); }
+
+class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
+{
+ Q_OBJECT
+ Q_PROPERTY(QGraphicsObject * parent READ parentObject WRITE setParentItem NOTIFY parentChanged DESIGNABLE false)
+ Q_PROPERTY(QString id READ objectName WRITE setObjectName)
+ Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity NOTIFY opacityChanged)
+ Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled NOTIFY enabledChanged)
+ Q_PROPERTY(bool visible READ isVisible WRITE setVisible NOTIFY visibleChanged)
+ Q_PROPERTY(QPointF pos READ pos WRITE setPos)
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY xChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY yChanged)
+ Q_PROPERTY(qreal z READ zValue WRITE setZValue NOTIFY zChanged)
+public:
+ QGraphicsObject(QGraphicsItem *parent = 0);
+
+Q_SIGNALS:
+ void parentChanged();
+ void opacityChanged();
+ void visibleChanged();
+ void enabledChanged();
+ void xChanged();
+ void yChanged();
+ void zChanged();
+
+protected:
+ QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
+private:
+ friend class QGraphicsItem;
+ friend class QGraphicsItemPrivate;
+};
+
+
class QAbstractGraphicsShapeItemPrivate;
class Q_GUI_EXPORT QAbstractGraphicsShapeItem : public QGraphicsItem
{
@@ -802,7 +876,7 @@ inline void QGraphicsPixmapItem::setOffset(qreal ax, qreal ay)
class QGraphicsTextItemPrivate;
class QTextDocument;
class QTextCursor;
-class Q_GUI_EXPORT QGraphicsTextItem : public QObject, public QGraphicsItem
+class Q_GUI_EXPORT QGraphicsTextItem : public QGraphicsObject
{
Q_OBJECT
QDOC_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks)
@@ -1014,4 +1088,3 @@ QT_END_NAMESPACE
QT_END_HEADER
#endif // QGRAPHICSITEM_H
-
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 9ce1bbf..03ec040 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -54,6 +54,9 @@
//
#include "qgraphicsitem.h"
+#include "qpixmapcache.h"
+
+#include <QtCore/qpoint.h>
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
@@ -69,13 +72,14 @@ public:
// ItemCoordinateCache only
QRect boundingRect;
QSize fixedSize;
- QString key;
+ QPixmapCache::Key key;
// DeviceCoordinateCache only
struct DeviceData {
+ DeviceData() {}
QTransform lastTransform;
QPoint cacheIndent;
- QString key;
+ QPixmapCache::Key key;
};
QMap<QPaintDevice *, DeviceData> deviceData;
@@ -92,14 +96,11 @@ class Q_AUTOTEST_EXPORT QGraphicsItemPrivate
Q_DECLARE_PUBLIC(QGraphicsItem)
public:
enum Extra {
- ExtraTransform,
ExtraToolTip,
ExtraCursor,
ExtraCacheData,
ExtraMaxDeviceCoordCacheSize,
- ExtraBoundingRegionGranularity,
- ExtraOpacity,
- ExtraEffectiveOpacity
+ ExtraBoundingRegionGranularity
};
enum AncestorFlag {
@@ -111,8 +112,10 @@ public:
inline QGraphicsItemPrivate()
: z(0),
+ opacity(1.),
scene(0),
parent(0),
+ transformData(0),
index(-1),
depth(0),
acceptedMouseButtons(0x1f),
@@ -126,14 +129,10 @@ public:
isMemberOfGroup(0),
handlesChildEvents(0),
itemDiscovered(0),
- hasTransform(0),
hasCursor(0),
ancestorFlags(0),
cacheMode(0),
hasBoundingRegionGranularity(0),
- flags(0),
- hasOpacity(0),
- hasEffectiveOpacity(0),
isWidget(0),
dirty(0),
dirtyChildren(0),
@@ -141,9 +140,17 @@ public:
dirtyClipPath(1),
emptyClipPath(0),
inSetPosHelper(0),
- allChildrenCombineOpacity(1),
+ needSortChildren(1),
+ allChildrenDirty(0),
+ fullUpdatePending(0),
+ flags(0),
+ dirtyChildrenBoundingRect(1),
+ paintedViewBoundingRectsNeedRepaint(0),
+ dirtySceneTransform(1),
+ geometryChanged(0),
+ inDestructor(0),
+ isObject(0),
globalStackingOrder(-1),
- sceneTransformIndex(-1),
q_ptr(0)
{
}
@@ -156,23 +163,32 @@ public:
void setIsMemberOfGroup(bool enabled);
void remapItemPos(QEvent *event, QGraphicsItem *item);
QPointF genericMapFromScene(const QPointF &pos, const QWidget *viewport) const;
- bool itemIsUntransformable() const;
+ inline bool itemIsUntransformable() const
+ {
+ return (flags & QGraphicsItem::ItemIgnoresTransformations)
+ || (ancestorFlags & AncestorIgnoresTransformations);
+ }
+ void combineTransformToParent(QTransform *x, const QTransform *viewTransform = 0) const;
+ void combineTransformFromParent(QTransform *x, const QTransform *viewTransform = 0) const;
+
// ### Qt 5: Remove. Workaround for reimplementation added after Qt 4.4.
virtual QVariant inputMethodQueryHelper(Qt::InputMethodQuery query) const;
static bool movableAncestorIsSelected(const QGraphicsItem *item);
void setPosHelper(const QPointF &pos);
+ void setTransformHelper(const QTransform &transform);
void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
bool discardUpdateRequest(bool ignoreClipping = false, bool ignoreVisibleBit = false,
bool ignoreDirtyBit = false, bool ignoreOpacity = false) const;
- void updateHelper(const QRectF &rect = QRectF(), bool force = false, bool maybeDirtyClipPath = false);
- void fullUpdateHelper(bool childrenOnly = false, bool maybeDirtyClipPath = false, bool ignoreOpacity = false);
- void updateEffectiveOpacity();
- void resolveEffectiveOpacity(qreal effectiveParentOpacity);
void resolveDepth(int parentDepth);
- void invalidateSceneTransformCache();
+ void addChild(QGraphicsItem *child);
+ void removeChild(QGraphicsItem *child);
+ void setParentItemHelper(QGraphicsItem *parent);
+ void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
+ void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
+ const QRegion &exposedRegion, bool allItems = false) const;
virtual void resolveFont(uint inheritedMask)
{
@@ -224,7 +240,7 @@ public:
}
}
}
-
+
struct ExtraStruct {
ExtraStruct(Extra type, QVariant value)
: type(type), value(value)
@@ -236,8 +252,10 @@ public:
bool operator<(Extra extra) const
{ return type < extra; }
};
+
QList<ExtraStruct> extras;
+ QGraphicsItemCache *maybeExtraItemCache() const;
QGraphicsItemCache *extraItemCache() const;
void removeExtraItemCache();
@@ -261,12 +279,67 @@ public:
void invalidateCachedClipPathRecursively(bool childrenOnly = false, const QRectF &emptyIfOutsideThisRect = QRectF());
void updateCachedClipPathFromSetPosHelper(const QPointF &newPos);
+ void ensureSceneTransformRecursive(QGraphicsItem **topMostDirtyItem);
+
+ inline void invalidateChildrenSceneTransform()
+ {
+ for (int i = 0; i < children.size(); ++i)
+ children.at(i)->d_ptr->dirtySceneTransform = 1;
+ }
+
+ inline qreal calcEffectiveOpacity() const
+ {
+ qreal o = opacity;
+ QGraphicsItem *p = parent;
+ int myFlags = flags;
+ while (p) {
+ int parentFlags = p->d_ptr->flags;
+
+ // If I have a parent, and I don't ignore my parent's opacity, and my
+ // parent propagates to me, then combine my local opacity with my parent's
+ // effective opacity into my effective opacity.
+ if ((myFlags & QGraphicsItem::ItemIgnoresParentOpacity)
+ || (parentFlags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ break;
+ }
+
+ o *= p->d_ptr->opacity;
+ p = p->d_ptr->parent;
+ myFlags = parentFlags;
+ }
+ return o;
+ }
inline bool isFullyTransparent() const
- { return hasEffectiveOpacity && qFuzzyCompare(q_func()->effectiveOpacity() + 1, qreal(1.0)); }
+ {
+ if (opacity < 0.001)
+ return true;
+ if (!parent)
+ return false;
+
+ return calcEffectiveOpacity() < 0.001;
+ }
+
+ inline qreal effectiveOpacity() const {
+ if (!parent || !opacity)
+ return opacity;
+
+ return calcEffectiveOpacity();
+ }
inline bool childrenCombineOpacity() const
- { return allChildrenCombineOpacity || children.isEmpty(); }
+ {
+ if (!children.size())
+ return true;
+ if (flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)
+ return false;
+
+ for (int i = 0; i < children.size(); ++i) {
+ if (children.at(i)->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity)
+ return false;
+ }
+ return true;
+ }
inline bool isClippedAway() const
{ return !dirtyClipPath && q_func()->isClipped() && (emptyClipPath || cachedClipPath.isEmpty()); }
@@ -281,16 +354,25 @@ public:
|| (childrenCombineOpacity() && isFullyTransparent());
}
+ inline QTransform transformToParent() const;
+
QPainterPath cachedClipPath;
+ QRectF childrenBoundingRect;
+ QRectF needsRepaint;
+ QMap<QWidget *, QRect> paintedViewBoundingRects;
QPointF pos;
qreal z;
+ qreal opacity;
QGraphicsScene *scene;
QGraphicsItem *parent;
QList<QGraphicsItem *> children;
+ struct TransformData;
+ TransformData *transformData;
+ QTransform sceneTransform;
int index;
int depth;
- // Packed 32 bytes
+ // Packed 32 bits
quint32 acceptedMouseButtons : 5;
quint32 visible : 1;
quint32 explicitlyHidden : 1;
@@ -302,16 +384,10 @@ public:
quint32 isMemberOfGroup : 1;
quint32 handlesChildEvents : 1;
quint32 itemDiscovered : 1;
- quint32 hasTransform : 1;
quint32 hasCursor : 1;
quint32 ancestorFlags : 3;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
- quint32 flags : 9;
-
- // New 32 bytes
- quint32 hasOpacity : 1;
- quint32 hasEffectiveOpacity : 1;
quint32 isWidget : 1;
quint32 dirty : 1;
quint32 dirtyChildren : 1;
@@ -319,15 +395,79 @@ public:
quint32 dirtyClipPath : 1;
quint32 emptyClipPath : 1;
quint32 inSetPosHelper : 1;
- quint32 allChildrenCombineOpacity : 1;
+ quint32 needSortChildren : 1;
+ quint32 allChildrenDirty : 1;
+ quint32 fullUpdatePending : 1;
+
+ // New 32 bits
+ quint32 flags : 12;
+ quint32 dirtyChildrenBoundingRect : 1;
+ quint32 paintedViewBoundingRectsNeedRepaint : 1;
+ quint32 dirtySceneTransform : 1;
+ quint32 geometryChanged : 1;
+ quint32 inDestructor : 1;
+ quint32 isObject : 1;
+ quint32 unused : 14; // feel free to use
// Optional stacking order
int globalStackingOrder;
- int sceneTransformIndex;
-
QGraphicsItem *q_ptr;
};
+struct QGraphicsItemPrivate::TransformData {
+ QTransform transform;
+ qreal xScale;
+ qreal yScale;
+ qreal xRotation;
+ qreal yRotation;
+ qreal zRotation;
+ qreal horizontalShear;
+ qreal verticalShear;
+ qreal xOrigin;
+ qreal yOrigin;
+ bool onlyTransform;
+
+ TransformData() :
+ xScale(1.0), yScale(1.0), xRotation(0.0), yRotation(0.0), zRotation(0.0),
+ horizontalShear(0.0), verticalShear(0.0), xOrigin(0.0), yOrigin(0.0),
+ onlyTransform(true)
+ {}
+
+ QTransform computedFullTransform(QTransform *postmultiplyTransform = 0) const
+ {
+ if (onlyTransform) {
+ if (!postmultiplyTransform)
+ return transform;
+ QTransform x(transform);
+ x *= *postmultiplyTransform;
+ return x;
+ }
+
+ QTransform x(transform);
+ if (xOrigin != 0 || yOrigin != 0)
+ x *= QTransform::fromTranslate(xOrigin, yOrigin);
+ x.rotate(xRotation, Qt::XAxis);
+ x.rotate(yRotation, Qt::YAxis);
+ x.rotate(zRotation, Qt::ZAxis);
+ x.shear(horizontalShear, verticalShear);
+ x.scale(xScale, yScale);
+ x.translate(-xOrigin, -yOrigin);
+ if (postmultiplyTransform)
+ x *= *postmultiplyTransform;
+ return x;
+ }
+};
+
+/*
+ return the full transform of the item to the parent. This include the position and all the transform data
+*/
+inline QTransform QGraphicsItemPrivate::transformToParent() const
+{
+ QTransform matrix;
+ combineTransformToParent(&matrix);
+ return matrix;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicslayoutitem.cpp b/src/gui/graphicsview/qgraphicslayoutitem.cpp
index c291763..2d4bddb 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem.cpp
+++ b/src/gui/graphicsview/qgraphicslayoutitem.cpp
@@ -108,13 +108,22 @@ static void normalizeHints(qreal &minimum, qreal &preferred, qreal &maximum, qre
\internal
*/
QGraphicsLayoutItemPrivate::QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *par, bool layout)
- : parent(par), isLayout(layout), ownedByLayout(false), graphicsItem(0)
+ : parent(par), userSizeHints(0), isLayout(layout), ownedByLayout(false), graphicsItem(0)
{
}
/*!
\internal
*/
+QGraphicsLayoutItemPrivate::~QGraphicsLayoutItemPrivate()
+{
+ // Remove any lazily allocated data
+ delete[] userSizeHints;
+}
+
+/*!
+ \internal
+*/
void QGraphicsLayoutItemPrivate::init()
{
sizeHintCacheDirty = true;
@@ -132,7 +141,8 @@ QSizeF *QGraphicsLayoutItemPrivate::effectiveSizeHints(const QSizeF &constraint)
for (int i = 0; i < Qt::NSizeHints; ++i) {
cachedSizeHints[i] = constraint;
- combineSize(cachedSizeHints[i], userSizeHints[i]);
+ if (userSizeHints)
+ combineSize(cachedSizeHints[i], userSizeHints[i]);
}
QSizeF &minS = cachedSizeHints[Qt::MinimumSize];
@@ -198,6 +208,58 @@ QGraphicsItem *QGraphicsLayoutItemPrivate::parentItem() const
}
/*!
+ \internal
+
+ Ensures that userSizeHints is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsLayoutItemPrivate::ensureUserSizeHints()
+{
+ if (!userSizeHints)
+ userSizeHints = new QSizeF[Qt::NSizeHints];
+}
+
+/*!
+ \internal
+
+ Sets the user size hint \a which to \a size. Use an invalid size to unset the size hint.
+ */
+void QGraphicsLayoutItemPrivate::setSize(Qt::SizeHint which, const QSizeF &size)
+{
+ Q_Q(QGraphicsLayoutItem);
+
+ if (userSizeHints) {
+ if (size == userSizeHints[which])
+ return;
+ } else if (!size.isValid()) {
+ return;
+ }
+
+ ensureUserSizeHints();
+ userSizeHints[which] = size;
+ q->updateGeometry();
+}
+
+/*!
+ \internal
+
+ Sets the width of the user size hint \a which to \a width.
+ */
+void QGraphicsLayoutItemPrivate::setSizeComponent(
+ Qt::SizeHint which, SizeComponent component, qreal value)
+{
+ Q_Q(QGraphicsLayoutItem);
+ ensureUserSizeHints();
+ qreal &userValue = (component == Width)
+ ? userSizeHints[which].rwidth()
+ : userSizeHints[which].rheight();
+ if (value == userValue)
+ return;
+ userValue = value;
+ q->updateGeometry();
+}
+
+/*!
\class QGraphicsLayoutItem
\brief The QGraphicsLayoutItem class can be inherited to allow your custom
items to be managed by layouts.
@@ -380,12 +442,7 @@ QSizePolicy QGraphicsLayoutItem::sizePolicy() const
*/
void QGraphicsLayoutItem::setMinimumSize(const QSizeF &size)
{
- Q_D(QGraphicsLayoutItem);
- if (size == d->userSizeHints[Qt::MinimumSize])
- return;
-
- d->userSizeHints[Qt::MinimumSize] = size;
- updateGeometry();
+ d_ptr->setSize(Qt::MinimumSize, size);
}
/*!
@@ -415,12 +472,7 @@ QSizeF QGraphicsLayoutItem::minimumSize() const
*/
void QGraphicsLayoutItem::setMinimumWidth(qreal width)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rwidth();
- if (width == userSizeHint)
- return;
- userSizeHint = width;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Width, width);
}
/*!
@@ -430,12 +482,7 @@ void QGraphicsLayoutItem::setMinimumWidth(qreal width)
*/
void QGraphicsLayoutItem::setMinimumHeight(qreal height)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MinimumSize].rheight();
- if (height == userSizeHint)
- return;
- userSizeHint = height;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MinimumSize, d_ptr->Height, height);
}
@@ -449,12 +496,7 @@ void QGraphicsLayoutItem::setMinimumHeight(qreal height)
*/
void QGraphicsLayoutItem::setPreferredSize(const QSizeF &size)
{
- Q_D(QGraphicsLayoutItem);
- if (size == d->userSizeHints[Qt::PreferredSize])
- return;
-
- d->userSizeHints[Qt::PreferredSize] = size;
- updateGeometry();
+ d_ptr->setSize(Qt::PreferredSize, size);
}
/*!
@@ -484,12 +526,7 @@ QSizeF QGraphicsLayoutItem::preferredSize() const
*/
void QGraphicsLayoutItem::setPreferredHeight(qreal height)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rheight();
- if (height == userSizeHint)
- return;
- userSizeHint = height;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Height, height);
}
/*!
@@ -499,12 +536,7 @@ void QGraphicsLayoutItem::setPreferredHeight(qreal height)
*/
void QGraphicsLayoutItem::setPreferredWidth(qreal width)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::PreferredSize].rwidth();
- if (width == userSizeHint)
- return;
- userSizeHint = width;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::PreferredSize, d_ptr->Width, width);
}
/*!
@@ -518,12 +550,7 @@ void QGraphicsLayoutItem::setPreferredWidth(qreal width)
*/
void QGraphicsLayoutItem::setMaximumSize(const QSizeF &size)
{
- Q_D(QGraphicsLayoutItem);
- if (size == d->userSizeHints[Qt::MaximumSize])
- return;
-
- d->userSizeHints[Qt::MaximumSize] = size;
- updateGeometry();
+ d_ptr->setSize(Qt::MaximumSize, size);
}
/*!
@@ -553,12 +580,7 @@ QSizeF QGraphicsLayoutItem::maximumSize() const
*/
void QGraphicsLayoutItem::setMaximumWidth(qreal width)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rwidth();
- if (width == userSizeHint)
- return;
- userSizeHint = width;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Width, width);
}
/*!
@@ -568,12 +590,7 @@ void QGraphicsLayoutItem::setMaximumWidth(qreal width)
*/
void QGraphicsLayoutItem::setMaximumHeight(qreal height)
{
- Q_D(QGraphicsLayoutItem);
- qreal &userSizeHint = d->userSizeHints[Qt::MaximumSize].rheight();
- if (height == userSizeHint)
- return;
- userSizeHint = height;
- updateGeometry();
+ d_ptr->setSizeComponent(Qt::MaximumSize, d_ptr->Height, height);
}
/*!
@@ -731,6 +748,11 @@ QRectF QGraphicsLayoutItem::contentsRect() const
*/
QSizeF QGraphicsLayoutItem::effectiveSizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
+ Q_D(const QGraphicsLayoutItem);
+
+ if (!d->userSizeHints && constraint.isValid())
+ return constraint;
+
// ### should respect size policy???
return d_ptr->effectiveSizeHints(constraint)[which];
}
diff --git a/src/gui/graphicsview/qgraphicslayoutitem_p.h b/src/gui/graphicsview/qgraphicslayoutitem_p.h
index fab0f39..dc044e6 100644
--- a/src/gui/graphicsview/qgraphicslayoutitem_p.h
+++ b/src/gui/graphicsview/qgraphicslayoutitem_p.h
@@ -63,16 +63,20 @@ class Q_AUTOTEST_EXPORT QGraphicsLayoutItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsLayoutItem)
public:
- virtual ~QGraphicsLayoutItemPrivate() {}
+ virtual ~QGraphicsLayoutItemPrivate();
QGraphicsLayoutItemPrivate(QGraphicsLayoutItem *parent, bool isLayout);
void init();
QSizeF *effectiveSizeHints(const QSizeF &constraint) const;
QGraphicsItem *parentItem() const;
+ void ensureUserSizeHints();
+ void setSize(Qt::SizeHint which, const QSizeF &size);
+ enum SizeComponent { Width, Height };
+ void setSizeComponent(Qt::SizeHint which, SizeComponent component, qreal value);
QSizePolicy sizePolicy;
QGraphicsLayoutItem *parent;
- QSizeF userSizeHints[Qt::NSizeHints];
+ QSizeF *userSizeHints;
mutable QSizeF cachedSizeHints[Qt::NSizeHints];
mutable QSizeF cachedConstraint;
diff --git a/src/gui/graphicsview/qgraphicslinearlayout.cpp b/src/gui/graphicsview/qgraphicslinearlayout.cpp
index 6a2d456..2f32950 100644
--- a/src/gui/graphicsview/qgraphicslinearlayout.cpp
+++ b/src/gui/graphicsview/qgraphicslinearlayout.cpp
@@ -178,7 +178,7 @@ QLayoutStyleInfo QGraphicsLinearLayoutPrivate::styleInfo() const
if (!wid)
wid = new QWidget;
QGraphicsItem *item = parentItem();
- QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : qApp->style();
+ QStyle *style = (item && item->isWidget()) ? static_cast<QGraphicsWidget*>(item)->style() : QApplication::style();
return QLayoutStyleInfo(style, wid);
}
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.cpp b/src/gui/graphicsview/qgraphicsproxywidget.cpp
index e660879..a5b11ff 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.cpp
+++ b/src/gui/graphicsview/qgraphicsproxywidget.cpp
@@ -460,7 +460,7 @@ void QGraphicsProxyWidgetPrivate::embedSubWindow(QWidget *subWin)
{
QWExtra *extra;
if (!((extra = subWin->d_func()->extra) && extra->proxyWidget)) {
- QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func());
+ QGraphicsProxyWidget *subProxy = new QGraphicsProxyWidget(q_func(), subWin->windowFlags());
subProxy->d_func()->setWidget_helper(subWin, false);
}
}
@@ -544,6 +544,9 @@ QGraphicsProxyWidget::~QGraphicsProxyWidget()
hidden or disabled after embedding is complete. The class documentation
has a full overview over the shared state.
+ QGraphicsProxyWidget's window flags determine whether the widget, after
+ embedding, will be given window decorations or not.
+
After this function returns, QGraphicsProxyWidget will keep its state
synchronized with that of \a widget whenever possible.
@@ -661,10 +664,6 @@ void QGraphicsProxyWidgetPrivate::setWidget_helper(QWidget *newWidget, bool auto
if (newWidget->testAttribute(Qt::WA_SetCursor))
q->setCursor(widget->cursor());
#endif
- Qt::WFlags flags = newWidget->windowFlags();
- if (newWidget->windowType() == Qt::Window)
- flags &= ~Qt::Window;
- q->setWindowFlags(flags);
q->setEnabled(newWidget->isEnabled());
q->setVisible(newWidget->isVisible());
q->setLayoutDirection(newWidget->layoutDirection());
@@ -977,6 +976,7 @@ void QGraphicsProxyWidget::contextMenuEvent(QGraphicsSceneContextMenuEvent *even
}
#endif // QT_NO_CONTEXTMENU
+#ifndef QT_NO_DRAGANDDROP
/*!
\reimp
*/
@@ -1097,6 +1097,7 @@ void QGraphicsProxyWidget::dropEvent(QGraphicsSceneDragDropEvent *event)
}
#endif
}
+#endif
/*!
\reimp
diff --git a/src/gui/graphicsview/qgraphicsproxywidget.h b/src/gui/graphicsview/qgraphicsproxywidget.h
index f006319..0c874c8 100644
--- a/src/gui/graphicsview/qgraphicsproxywidget.h
+++ b/src/gui/graphicsview/qgraphicsproxywidget.h
@@ -90,10 +90,12 @@ protected:
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
#endif
+#ifndef QT_NO_DRAGANDDROP
void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
void dropEvent(QGraphicsSceneDragDropEvent *event);
+#endif
void hoverEnterEvent(QGraphicsSceneHoverEvent *event);
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 5114351..900fa1a 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -39,7 +39,6 @@
**
****************************************************************************/
-static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
/*!
\class QGraphicsScene
@@ -250,6 +249,8 @@ static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
QT_BEGIN_NAMESPACE
+static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2);
+
static inline bool QRectF_intersects(const QRectF &s, const QRectF &r)
{
qreal xp = s.left();
@@ -333,8 +334,9 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
hasSceneRect(false),
updateAll(false),
calledEmitUpdated(false),
+ processDirtyItemsEmitted(false),
selectionChanging(0),
- dirtyItemResetPending(false),
+ needSortTopLevelItems(true),
regenerateIndex(true),
purgePending(false),
indexTimerId(0),
@@ -351,6 +353,8 @@ QGraphicsScenePrivate::QGraphicsScenePrivate()
dragDropItem(0),
enterWidget(0),
lastDropAction(Qt::IgnoreAction),
+ allItemsIgnoreHoverEvents(true),
+ allItemsUseDefaultCursor(true),
painterStateProtection(true),
sortCacheEnabled(false),
updatingSortCache(false),
@@ -410,7 +414,7 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::estimateItemsInRect(const QRectF &
if (QGraphicsItem *item = unindexedItems.at(i)) {
if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
continue;
- if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0))
+ if (item->d_ptr->visible && !item->d_ptr->isFullyTransparent())
itemsInRect << item;
}
}
@@ -418,7 +422,7 @@ QList<QGraphicsItem *> QGraphicsScenePrivate::estimateItemsInRect(const QRectF &
if (QGraphicsItem *item = indexedItems.at(i)) {
if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)
continue;
- if (item->d_ptr->visible && item->effectiveOpacity() > qreal(0.0))
+ if (item->d_ptr->visible && !item->d_ptr->isFullyTransparent())
itemsInRect << item;
}
}
@@ -596,7 +600,7 @@ void QGraphicsScenePrivate::_q_emitUpdated()
// the optimization that items send updates directly to the views, but it
// needs to happen in order to keep compatibility with the behavior from
// Qt 4.4 and backward.
- if (!views.isEmpty() && (connectedSignals & changedSignalMask)) {
+ if (connectedSignals & changedSignalMask) {
for (int i = 0; i < views.size(); ++i) {
QGraphicsView *view = views.at(i);
if (!view->d_func()->connectedToScene) {
@@ -605,13 +609,13 @@ void QGraphicsScenePrivate::_q_emitUpdated()
views.at(i), SLOT(updateScene(QList<QRectF>)));
}
}
+ } else {
+ updateAll = false;
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->processPendingUpdates();
+ return;
}
- // Ensure all dirty items's current positions are recorded in the list of
- // updated rects.
- for (int i = 0; i < dirtyItems.size(); ++i)
- updatedRects += dirtyItems.at(i)->sceneBoundingRect();
-
// Notify the changes to anybody interested.
QList<QRectF> oldUpdatedRects;
oldUpdatedRects = updateAll ? (QList<QRectF>() << q->sceneRect()) : updatedRects;
@@ -622,6 +626,23 @@ void QGraphicsScenePrivate::_q_emitUpdated()
/*!
\internal
+*/
+void QGraphicsScenePrivate::registerTopLevelItem(QGraphicsItem *item)
+{
+ needSortTopLevelItems = true;
+ topLevelItems.append(item);
+}
+
+/*!
+ \internal
+*/
+void QGraphicsScenePrivate::unregisterTopLevelItem(QGraphicsItem *item)
+{
+ topLevelItems.removeOne(item);
+}
+
+/*!
+ \internal
Updates all items in the pending update list. At this point, the list is
unlikely to contain partially constructed items.
@@ -652,70 +673,102 @@ void QGraphicsScenePrivate::_q_polishItems()
unpolishedItems.clear();
}
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::_q_resetDirtyItems()
+void QGraphicsScenePrivate::_q_processDirtyItems()
{
- for (int i = 0; i < dirtyItems.size(); ++i) {
- QGraphicsItem *item = dirtyItems.at(i);
- item->d_ptr->dirty = 0;
- item->d_ptr->dirtyChildren = 0;
- }
- dirtyItems.clear();
- dirtyItemResetPending = false;
-}
+ processDirtyItemsEmitted = false;
-/*!
- \internal
-*/
-void QGraphicsScenePrivate::resetDirtyItemsLater()
-{
- Q_Q(QGraphicsScene);
- if (dirtyItemResetPending)
+ const bool wasPendingSceneUpdate = calledEmitUpdated;
+ const QRectF oldGrowingItemsBoundingRect = growingItemsBoundingRect;
+ processDirtyItemsRecursive(0);
+ if (!hasSceneRect && oldGrowingItemsBoundingRect != growingItemsBoundingRect)
+ emit q_func()->sceneRectChanged(growingItemsBoundingRect);
+
+ if (wasPendingSceneUpdate)
return;
- // dirtyItems.reserve(indexedItems.size() + unindexedItems.size());
- dirtyItemResetPending = true;
- QMetaObject::invokeMethod(q, "_q_resetDirtyItems", Qt::QueuedConnection);
+
+ for (int i = 0; i < views.size(); ++i)
+ views.at(i)->d_func()->processPendingUpdates();
+
+ if (calledEmitUpdated) {
+ // We did a compatibility QGraphicsScene::update in processDirtyItemsRecursive
+ // and we cannot wait for the control to reach the eventloop before the
+ // changed signal is emitted, so we emit it now.
+ _q_emitUpdated();
+ }
+
+ // Immediately dispatch all pending update requests on the views.
+ for (int i = 0; i < views.size(); ++i) {
+ QWidget *viewport = views.at(i)->d_func()->viewport;
+ if (qt_widget_private(viewport)->paintOnScreen())
+ QCoreApplication::sendPostedEvents(viewport, QEvent::UpdateRequest);
+ else
+ QCoreApplication::sendPostedEvents(viewport->window(), QEvent::UpdateRequest);
+ }
}
/*!
\internal
Schedules an item for removal. This function leaves some stale indexes
- around in the BSP tree; these will be cleaned up the next time someone
- triggers purgeRemovedItems().
+ around in the BSP tree if called from the item's destructor; these will
+ be cleaned up the next time someone triggers purgeRemovedItems().
- Note: This function is called from QGraphicsItem's destructor. \a item is
+ Note: This function might get called from QGraphicsItem's destructor. \a item is
being destroyed, so we cannot call any pure virtual functions on it (such
as boundingRect()). Also, it is unnecessary to update the item's own state
in any way.
-
- ### Refactoring: This function shares much functionality with removeItem()
*/
-void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
+void QGraphicsScenePrivate::removeItemHelper(QGraphicsItem *item)
{
Q_Q(QGraphicsScene);
- // Clear focus on the item to remove any reference in the focusWidget
- // chain.
+ // Clear focus on the item to remove any reference in the focusWidget chain.
item->clearFocus();
-
- int index = item->d_func()->index;
- if (index != -1) {
- // Important: The index is useless until purgeRemovedItems() is
- // called.
- indexedItems[index] = (QGraphicsItem *)0;
- if (!purgePending) {
+ markDirty(item, QRectF(), false, false, false, false, /*removingItemFromScene=*/true);
+
+ if (!item->d_ptr->inDestructor) {
+ // Can potentially call item->boundingRect() (virtual function), that's why
+ // we only can call this function if the item is not in its destructor.
+ removeFromIndex(item);
+ } else if (item->d_ptr->index != -1) {
+ // Important: The index is useless until purgeRemovedItems() is called.
+ indexedItems[item->d_ptr->index] = (QGraphicsItem *)0;
+ if (!purgePending)
purgePending = true;
- q->update();
- }
removedItems << item;
} else {
// Recently added items are purged immediately. unindexedItems() never
// contains stale items.
unindexedItems.removeAll(item);
- q->update();
+ }
+
+ if (!item->d_ptr->inDestructor && item == tabFocusFirst) {
+ QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
+ widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
+ }
+
+ item->d_func()->scene = 0;
+
+ // Remove from parent, or unregister from toplevels.
+ if (QGraphicsItem *parentItem = item->parentItem()) {
+ if (parentItem->scene()) {
+ Q_ASSERT_X(parentItem->scene() == q, "QGraphicsScene::removeItem",
+ "Parent item's scene is different from this item's scene");
+ item->d_ptr->setParentItemHelper(0);
+ }
+ } else {
+ unregisterTopLevelItem(item);
+ }
+
+ if (!item->d_ptr->inDestructor) {
+ // Remove from our item lists.
+ int index = item->d_func()->index;
+ if (index != -1) {
+ freeItemIndexes << index;
+ indexedItems[index] = 0;
+ } else {
+ unindexedItems.removeAll(item);
+ }
}
// Reset the mouse grabber and focus item data.
@@ -735,10 +788,10 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
// Update selected & hovered item bookkeeping
selectedItems.remove(item);
hoverItems.removeAll(item);
- pendingUpdateItems.removeAll(item);
cachedItemsUnderMouse.removeAll(item);
unpolishedItems.removeAll(item);
- dirtyItems.removeAll(item);
+ pendingUpdateItems.removeAll(item);
+ resetDirtyItem(item);
//We remove all references of item from the sceneEventFilter arrays
QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = sceneEventFilters.begin();
@@ -749,24 +802,19 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
++iterator;
}
- // Remove from scene transform cache
- int transformIndex = item->d_func()->sceneTransformIndex;
- if (transformIndex != -1) {
- validTransforms.setBit(transformIndex, 0);
- freeSceneTransformSlots.append(transformIndex);
+ if (!item->d_ptr->inDestructor) {
+ // Remove all children recursively
+ for (int i = 0; i < item->d_ptr->children.size(); ++i)
+ q->removeItem(item->d_ptr->children.at(i));
}
- // Remove all children recursively.
- foreach (QGraphicsItem *child, item->children())
- _q_removeItemLater(child);
-
- // Reset the mouse grabber
+ // Reset the mouse grabber and focus item data.
if (mouseGrabberItems.contains(item))
- ungrabMouse(item, /* item is dying */ true);
+ ungrabMouse(item, /* item is dying */ item->d_ptr->inDestructor);
// Reset the keyboard grabber
if (keyboardGrabberItems.contains(item))
- ungrabKeyboard(item, /* item is dying */ true);
+ ungrabKeyboard(item, /* item is dying */ item->d_ptr->inDestructor);
// Reset the last mouse grabber item
if (item == lastMouseGrabberItem)
@@ -785,8 +833,6 @@ void QGraphicsScenePrivate::_q_removeItemLater(QGraphicsItem *item)
*/
void QGraphicsScenePrivate::purgeRemovedItems()
{
- Q_Q(QGraphicsScene);
-
if (!purgePending && removedItems.isEmpty())
return;
@@ -802,9 +848,6 @@ void QGraphicsScenePrivate::purgeRemovedItems()
freeItemIndexes << i;
}
purgePending = false;
-
- // No locality info for the items; update the whole scene.
- q->update();
}
/*!
@@ -812,13 +855,13 @@ void QGraphicsScenePrivate::purgeRemovedItems()
Starts or restarts the timer used for reindexing unindexed items.
*/
-void QGraphicsScenePrivate::startIndexTimer()
+void QGraphicsScenePrivate::startIndexTimer(int interval)
{
Q_Q(QGraphicsScene);
if (indexTimerId) {
restartIndexTimer = true;
} else {
- indexTimerId = q->startTimer(QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
+ indexTimerId = q->startTimer(interval);
}
}
@@ -880,11 +923,18 @@ void QGraphicsScenePrivate::grabMouse(QGraphicsItem *item, bool implicit)
{
// Append to list of mouse grabber items, and send a mouse grab event.
if (mouseGrabberItems.contains(item)) {
- if (mouseGrabberItems.last() == item)
- qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
- else
+ if (mouseGrabberItems.last() == item) {
+ Q_ASSERT(!implicit);
+ if (!lastMouseGrabberItemHasImplicitMouseGrab) {
+ qWarning("QGraphicsItem::grabMouse: already a mouse grabber");
+ } else {
+ // Upgrade to an explicit mouse grab
+ lastMouseGrabberItemHasImplicitMouseGrab = false;
+ }
+ } else {
qWarning("QGraphicsItem::grabMouse: already blocked by mouse grabber: %p",
mouseGrabberItems.last());
+ }
return;
}
@@ -1036,6 +1086,12 @@ void QGraphicsScenePrivate::clearKeyboardGrabber()
ungrabKeyboard(keyboardGrabberItems.first());
}
+void QGraphicsScenePrivate::enableMouseTrackingOnViews()
+{
+ foreach (QGraphicsView *view, views)
+ view->viewport()->setMouseTracking(true);
+}
+
/*!
Returns all items for the screen position in \a event.
*/
@@ -1294,7 +1350,8 @@ void QGraphicsScenePrivate::mousePressEventHandler(QGraphicsSceneMouseEvent *mou
// check if the item we are sending to are disabled (before we send the event)
bool disabled = !item->isEnabled();
bool isWindow = item->isWindow();
- if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick && item != lastMouseGrabberItem) {
+ if (mouseEvent->type() == QEvent::GraphicsSceneMouseDoubleClick
+ && item != lastMouseGrabberItem && lastMouseGrabberItem) {
// If this item is different from the item that received the last
// mouse event, and mouseEvent is a doubleclick event, then the
// event is converted to a press. Known limitation:
@@ -1367,6 +1424,109 @@ QGraphicsWidget *QGraphicsScenePrivate::windowForItem(const QGraphicsItem *item)
return 0;
}
+void QGraphicsScenePrivate::recursive_items_helper(QGraphicsItem *item, QRectF rect,
+ QList<QGraphicsItem *> *items,
+ const QTransform &parentTransform,
+ const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order,
+ qreal parentOpacity) const
+{
+ // Calculate opacity.
+ qreal opacity;
+ if (item) {
+ if (!item->d_ptr->visible)
+ return;
+ QGraphicsItem *p = item->d_ptr->parent;
+ bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity;
+ bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren));
+ if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) {
+ opacity = parentOpacity * item->opacity();
+ } else {
+ opacity = item->d_ptr->opacity;
+ }
+ if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren))
+ return;
+ } else {
+ opacity = parentOpacity;
+ }
+
+ // Calculate the full transform for this item.
+ QTransform transform = parentTransform;
+ bool keep = false;
+ if (item) {
+ item->d_ptr->combineTransformFromParent(&transform, &viewTransform);
+
+ // ### This does not take the clip into account.
+ QRectF brect = item->boundingRect();
+ _q_adjustRect(&brect);
+
+ keep = true;
+ if (mode == Qt::ContainsItemShape || mode == Qt::ContainsItemBoundingRect)
+ keep = rect.contains(transform.mapRect(brect)) && rect != brect;
+ else
+ keep = rect.intersects(transform.mapRect(brect));
+
+ if (keep && (mode == Qt::ContainsItemShape || mode == Qt::IntersectsItemShape)) {
+ QPainterPath rectPath;
+ rectPath.addRect(rect);
+ keep = itemCollidesWithPath(item, transform.inverted().map(rectPath), mode);
+ }
+ }
+
+ bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape));
+ bool dontProcessItem = !item || !keep;
+ bool dontProcessChildren = item && dontProcessItem && childClip;
+
+ // Find and sort children.
+ QList<QGraphicsItem *> &children = item ? item->d_ptr->children : const_cast<QGraphicsScenePrivate *>(this)->topLevelItems;
+ if (!dontProcessChildren) {
+ if (item && item->d_ptr->needSortChildren) {
+ item->d_ptr->needSortChildren = 0;
+ qStableSort(children.begin(), children.end(), qt_notclosestLeaf);
+ } else if (!item && needSortTopLevelItems) {
+ const_cast<QGraphicsScenePrivate *>(this)->needSortTopLevelItems = false;
+ qStableSort(children.begin(), children.end(), qt_notclosestLeaf);
+ }
+ }
+
+ childClip &= !dontProcessChildren & !children.isEmpty();
+
+ // Clip.
+ if (childClip)
+ rect &= transform.map(item->shape()).controlPointRect();
+
+ // Process children behind
+ int i = 0;
+ if (!dontProcessChildren) {
+ for (i = 0; i < children.size(); ++i) {
+ QGraphicsItem *child = children.at(i);
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ recursive_items_helper(child, rect, items, transform, viewTransform,
+ mode, order, opacity);
+ }
+ }
+
+ // Process item
+ if (!dontProcessItem)
+ items->append(item);
+
+ // Process children in front
+ if (!dontProcessChildren) {
+ for (; i < children.size(); ++i)
+ recursive_items_helper(children.at(i), rect, items, transform, viewTransform,
+ mode, order, opacity);
+ }
+
+ if (!item && order == Qt::AscendingOrder) {
+ int n = items->size();
+ for (int i = 0; i < n / 2; ++i) {
+ QGraphicsItem *tmp = (*items)[n - i - 1];
+ (*items)[n - i - 1] = (*items)[i];
+ (*items)[i] = tmp;
+ }
+ }
+}
QList<QGraphicsItem *> QGraphicsScenePrivate::items_helper(const QPointF &pos) const
{
@@ -1602,7 +1762,7 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items and all their children.
@@ -1642,7 +1802,7 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items and all their children.
@@ -1678,7 +1838,7 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
if ((keep || !(item->flags() & QGraphicsItem::ItemClipsChildrenToShape)) && !item->d_ptr->children.isEmpty()) {
// Recurse into children.
- if (!item->d_ptr->hasTransform || item->transform().type() <= QTransform::TxScale) {
+ if (!item->d_ptr->transformData || item->d_ptr->transformData->computedFullTransform().type() <= QTransform::TxScale) {
// Rect
childItems_helper(items, item, item->mapRectFromParent(rect), mode);
} else {
@@ -1708,7 +1868,7 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items.
@@ -1767,7 +1927,7 @@ void QGraphicsScenePrivate::childItems_helper(QList<QGraphicsItem *> *items,
QList<QGraphicsItem *> &children = parent->d_ptr->children;
for (int i = 0; i < children.size(); ++i) {
QGraphicsItem *item = children.at(i);
- if (item->d_ptr->hasTransform && !item->transform().isInvertible())
+ if (item->d_ptr->transformData && !item->d_ptr->transformData->computedFullTransform().isInvertible())
continue;
// Skip invisible items.
@@ -1831,7 +1991,12 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item
if (f1 != f2) return f2;
qreal z1 = d1->z;
qreal z2 = d2->z;
- return z1 != z2 ? z1 > z2 : item1 > item2;
+ return z1 > z2;
+}
+
+static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ return qt_closestLeaf(item2, item1);
}
/*!
@@ -1996,7 +2161,7 @@ void QGraphicsScenePrivate::setFont_helper(const QFont &font)
*/
void QGraphicsScenePrivate::resolveFont()
{
- QFont naturalFont = qApp->font();
+ QFont naturalFont = QApplication::font();
naturalFont.resolve(0);
QFont resolvedFont = font.resolve(naturalFont);
updateFont(resolvedFont);
@@ -2052,7 +2217,7 @@ void QGraphicsScenePrivate::setPalette_helper(const QPalette &palette)
*/
void QGraphicsScenePrivate::resolvePalette()
{
- QPalette naturalPalette = qApp->palette();
+ QPalette naturalPalette = QApplication::palette();
naturalPalette.resolve(0);
QPalette resolvedPalette = palette.resolve(naturalPalette);
updatePalette(resolvedPalette);
@@ -2211,8 +2376,6 @@ void QGraphicsScene::setSceneRect(const QRectF &rect)
void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source,
Qt::AspectRatioMode aspectRatioMode)
{
- Q_D(QGraphicsScene);
-
// Default source rect = scene rect
QRectF sourceRect = source;
if (sourceRect.isNull())
@@ -2269,36 +2432,8 @@ void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRect
// Generate the style options
QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
- for (int i = 0; i < numItems; ++i) {
- QGraphicsItem *item = itemArray[i];
-
- QStyleOptionGraphicsItem option;
- option.state = QStyle::State_None;
- option.rect = item->boundingRect().toRect();
- if (item->isSelected())
- option.state |= QStyle::State_Selected;
- if (item->isEnabled())
- option.state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option.state |= QStyle::State_HasFocus;
- if (d->hoverItems.contains(item))
- option.state |= QStyle::State_MouseOver;
- if (item == mouseGrabberItem())
- option.state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsView::paintEvent()
- // and QGraphicsView::render() - consider refactoring
- QTransform itemToDeviceTransform = item->deviceTransform(painterTransform);
-
- option.levelOfDetail = qSqrt(itemToDeviceTransform.map(v1).length() * itemToDeviceTransform.map(v2).length());
- option.matrix = itemToDeviceTransform.toAffine(); //### discards perspective
-
- option.exposedRect = item->boundingRect();
- option.exposedRect &= itemToDeviceTransform.inverted().mapRect(targetRect);
-
- styleOptionArray[i] = option;
- }
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
// Render the scene.
drawBackground(painter, sourceRect);
@@ -2474,7 +2609,6 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
return d->items_helper(pos);
}
-
/*!
\fn QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rectangle, Qt::ItemSelectionMode mode) const
@@ -2491,7 +2625,9 @@ QList<QGraphicsItem *> QGraphicsScene::items(const QPointF &pos) const
QList<QGraphicsItem *> QGraphicsScene::items(const QRectF &rect, Qt::ItemSelectionMode mode) const
{
Q_D(const QGraphicsScene);
- return d->items_helper(rect, mode, Qt::AscendingOrder);
+ QList<QGraphicsItem *> itemList;
+ d->recursive_items_helper(0, rect, &itemList, QTransform(), QTransform(), mode, Qt::AscendingOrder);
+ return itemList;
}
/*!
@@ -2742,12 +2878,13 @@ void QGraphicsScene::clear()
}
d->unindexedItems.clear();
qDeleteAll(unindexedParents);
-
d->indexedItems.clear();
d->freeItemIndexes.clear();
d->lastItemCount = 0;
d->bspTree.clear();
d->largestUntransformableItem = QRectF();
+ d->allItemsIgnoreHoverEvents = true;
+ d->allItemsUseDefaultCursor = true;
}
/*!
@@ -2851,7 +2988,6 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
qWarning("QGraphicsScene::addItem: item has already been added to this scene");
return;
}
-
// Remove this item from its existing scene
if (QGraphicsScene *oldScene = item->scene())
oldScene->removeItem(item);
@@ -2890,7 +3026,11 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
// a temporary list and schedule an indexing for later.
d->unindexedItems << item;
item->d_func()->index = -1;
- d->startIndexTimer();
+ d->startIndexTimer(0);
+
+ // Add to list of toplevels if this item is a toplevel.
+ if (!item->d_ptr->parent)
+ d->registerTopLevelItem(item);
// Update the scene's sort cache settings.
item->d_ptr->globalStackingOrder = -1;
@@ -2909,6 +3049,19 @@ void QGraphicsScene::addItem(QGraphicsItem *item)
++d->selectionChanging;
int oldSelectedItemSize = d->selectedItems.size();
+ // Enable mouse tracking if the item accepts hover events or has a cursor set.
+ if (d->allItemsIgnoreHoverEvents && d->itemAcceptsHoverEvents_helper(item)) {
+ d->allItemsIgnoreHoverEvents = false;
+ d->enableMouseTrackingOnViews();
+ }
+#ifndef QT_NO_CURSOR
+ if (d->allItemsUseDefaultCursor && item->hasCursor()) {
+ d->allItemsUseDefaultCursor = false;
+ if (d->allItemsIgnoreHoverEvents) // already enabled otherwise
+ d->enableMouseTrackingOnViews();
+ }
+#endif //QT_NO_CURSOR
+
// Update selection lists
if (item->isSelected())
d->selectedItems << item;
@@ -3226,106 +3379,7 @@ void QGraphicsScene::removeItem(QGraphicsItem *item)
return;
}
- // If the item has focus, remove it (and any focusWidget reference).
- item->clearFocus();
-
- // Clear its background
- item->update();
-
- // Note: This will access item's sceneBoundingRect(), which (as this is
- // C++) is why we cannot call removeItem() from QGraphicsItem's
- // destructor.
- d->removeFromIndex(item);
-
- if (item == d->tabFocusFirst) {
- QGraphicsWidget *widget = static_cast<QGraphicsWidget *>(item);
- widget->d_func()->fixFocusChainBeforeReparenting(0, 0);
- }
- // Set the item's scene ptr to 0.
- item->d_func()->scene = 0;
-
- // Detach the item from its parent.
- if (QGraphicsItem *parentItem = item->parentItem()) {
- if (parentItem->scene()) {
- Q_ASSERT_X(parentItem->scene() == this, "QGraphicsScene::removeItem",
- "Parent item's scene is different from this item's scene");
- item->setParentItem(0);
- }
- }
-
- // Remove from our item lists.
- int index = item->d_func()->index;
- if (index != -1) {
- d->freeItemIndexes << index;
- d->indexedItems[index] = 0;
- } else {
- d->unindexedItems.removeAll(item);
- }
-
- // Remove from scene transform cache
- int transformIndex = item->d_func()->sceneTransformIndex;
- if (transformIndex != -1) {
- d->validTransforms.setBit(transformIndex, 0);
- d->freeSceneTransformSlots.append(transformIndex);
- item->d_func()->sceneTransformIndex = -1;
- }
-
- if (item == d->focusItem)
- d->focusItem = 0;
- if (item == d->lastFocusItem)
- d->lastFocusItem = 0;
- if (item == d->activeWindow) {
- // ### deactivate...
- d->activeWindow = 0;
- }
-
- // Disable selectionChanged() for individual items
- ++d->selectionChanging;
- int oldSelectedItemsSize = d->selectedItems.size();
-
- // Update selected & hovered item bookkeeping
- d->selectedItems.remove(item);
- d->hoverItems.removeAll(item);
- d->pendingUpdateItems.removeAll(item);
- d->cachedItemsUnderMouse.removeAll(item);
- d->unpolishedItems.removeAll(item);
- d->dirtyItems.removeAll(item);
-
- //We remove all references of item from the sceneEventFilter arrays
- QMultiMap<QGraphicsItem*, QGraphicsItem*>::iterator iterator = d->sceneEventFilters.begin();
- while (iterator != d->sceneEventFilters.end()) {
- if (iterator.value() == item || iterator.key() == item)
- iterator = d->sceneEventFilters.erase(iterator);
- else
- ++iterator;
- }
-
-
- //Ensure dirty flag have the correct default value so the next time it will be added it will receive updates
- item->d_func()->dirty = 0;
- item->d_func()->dirtyChildren = 0;
-
- // Remove all children recursively
- foreach (QGraphicsItem *child, item->children())
- removeItem(child);
-
- // Reset the mouse grabber and focus item data.
- if (d->mouseGrabberItems.contains(item))
- d->ungrabMouse(item);
-
- // Reset the keyboard grabber
- if (d->keyboardGrabberItems.contains(item))
- item->ungrabKeyboard();
-
- // Reset the last mouse grabber item
- if (item == d->lastMouseGrabberItem)
- d->lastMouseGrabberItem = 0;
-
- // Reenable selectionChanged() for individual items
- --d->selectionChanging;
-
- if (!d->selectionChanging && d->selectedItems.size() != oldSelectedItemsSize)
- emit selectionChanged();
+ d->removeItemHelper(item);
// Deliver post-change notification
item->itemChange(QGraphicsItem::ItemSceneHasChanged, newSceneVariant);
@@ -3628,7 +3682,7 @@ void QGraphicsScene::update(const QRectF &rect)
}
}
- if (!directUpdates && !d->calledEmitUpdated) {
+ if (!d->calledEmitUpdated) {
d->calledEmitUpdated = true;
QMetaObject::invokeMethod(this, "_q_emitUpdated", Qt::QueuedConnection);
}
@@ -3744,6 +3798,8 @@ bool QGraphicsScene::event(QEvent *event)
// items from inside event handlers, this list can quickly end up
// having stale pointers in it. We need to clear it before dispatching
// events that use it.
+ // ### this should only be cleared if we received a new mouse move event,
+ // which relies on us fixing the replay mechanism in QGraphicsView.
d->cachedItemsUnderMouse.clear();
default:
break;
@@ -3919,10 +3975,10 @@ bool QGraphicsScene::eventFilter(QObject *watched, QEvent *event)
switch (event->type()) {
case QEvent::ApplicationPaletteChange:
- qApp->postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
+ QApplication::postEvent(this, new QEvent(QEvent::ApplicationPaletteChange));
break;
case QEvent::ApplicationFontChange:
- qApp->postEvent(this, new QEvent(QEvent::ApplicationFontChange));
+ QApplication::postEvent(this, new QEvent(QEvent::ApplicationFontChange));
break;
default:
break;
@@ -4209,6 +4265,9 @@ bool QGraphicsScenePrivate::itemAcceptsHoverEvents_helper(const QGraphicsItem *i
*/
bool QGraphicsScenePrivate::dispatchHoverEvent(QGraphicsSceneHoverEvent *hoverEvent)
{
+ if (allItemsIgnoreHoverEvents)
+ return false;
+
// Find the first item that accepts hover events, reusing earlier
// calculated data is possible.
if (cachedItemsUnderMouse.isEmpty()) {
@@ -4608,7 +4667,7 @@ static void _q_paintItem(QGraphicsItem *item, QPainter *painter,
? proxy->widget()->windowOpacity() : 1.0;
const qreal oldPainterOpacity = painter->opacity();
- if (qFuzzyCompare(windowOpacity + 1, qreal(1.0)))
+ if (qFuzzyIsNull(windowOpacity))
return;
// Set new painter opacity.
if (windowOpacity < 1.0)
@@ -4717,8 +4776,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
return;
// Fetch the off-screen transparent buffer and exposed area info.
- QString pixmapKey;
+ QPixmapCache::Key pixmapKey;
QPixmap pix;
+ bool pixmapFound;
QGraphicsItemCache *itemCache = itemd->extraItemCache();
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
if (itemCache->boundingRect != brect.toRect()) {
@@ -4728,17 +4788,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
pixmapKey = itemCache->key;
} else {
- if ((pixmapKey = itemCache->deviceData.value(widget).key).isEmpty()) {
- pixmapKey.sprintf("qgv-%p-%p", item, widget);
- QGraphicsItemCache::DeviceData data;
- data.key = pixmapKey;
- itemCache->deviceData.insert(widget, data);
- }
+ pixmapKey = itemCache->deviceData.value(widget).key;
}
// Find pixmap in cache.
- if (!itemCache->allExposed)
- QPixmapCache::find(pixmapKey, pix);
+ pixmapFound = QPixmapCache::find(pixmapKey, &pix);
// Render using item coordinate cache mode.
if (cacheMode == QGraphicsItem::ItemCoordinateCache) {
@@ -4763,6 +4817,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Redraw any newly exposed areas.
if (itemCache->allExposed || !itemCache->exposed.isEmpty()) {
+
+ //We know that we will modify the pixmap, removing it from the cache
+ //will detach the one we have and avoid a deep copy
+ if (pixmapFound)
+ QPixmapCache::remove(pixmapKey);
+
// Fit the item's bounding rect into the pixmap's coordinates.
QTransform itemToPixmap;
if (fixedCacheSize) {
@@ -4773,7 +4833,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Generate the item's exposedRect and map its list of expose
// rects to device coordinates.
- QStyleOptionGraphicsItem cacheOption = *option;
+ styleOptionTmp = *option;
QRegion pixmapExposed;
QRectF exposedRect;
if (!itemCache->allExposed) {
@@ -4785,14 +4845,14 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
} else {
exposedRect = brect;
}
- cacheOption.exposedRect = exposedRect;
+ styleOptionTmp.exposedRect = exposedRect;
// Render.
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &cacheOption, painterStateProtection);
+ &styleOptionTmp, painterStateProtection);
- // Reinsert this pixmap into the cache.
- QPixmapCache::insert(pixmapKey, pix);
+ // insert this pixmap into the cache.
+ itemCache->key = QPixmapCache::insert(pix);
// Reset expose data.
itemCache->allExposed = false;
@@ -4858,7 +4918,7 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
bool allowPartialCacheExposure = !viewRect.contains(deviceRect);
#else
// Only if deviceRect is 20% taller or wider than the desktop.
- QRect desktopRect = qApp->desktop()->availableGeometry(widget);
+ QRect desktopRect = QApplication::desktop()->availableGeometry(widget);
bool allowPartialCacheExposure = (desktopRect.width() * 1.2 < deviceRect.width()
|| desktopRect.height() * 1.2 < deviceRect.height());
#endif
@@ -4919,6 +4979,11 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
// Check for newly invalidated areas.
if (itemCache->allExposed || !itemCache->exposed.isEmpty() || !scrollExposure.isEmpty()) {
+ //We know that we will modify the pixmap, removing it from the cache
+ //will detach the one we have and avoid a deep copy
+ if (pixmapFound)
+ QPixmapCache::remove(pixmapKey);
+
// Construct an item-to-pixmap transform.
QPointF p = deviceRect.topLeft();
QTransform itemToPixmap = painter->worldTransform();
@@ -4945,12 +5010,12 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
foreach (QRect r, scrollExposure.rects())
br |= pixmapToItem.mapRect(r);
}
- QStyleOptionGraphicsItem cacheOption = *option;
- cacheOption.exposedRect = br.adjusted(-1, -1, 1, 1);
+ styleOptionTmp = *option;
+ styleOptionTmp.exposedRect = br.adjusted(-1, -1, 1, 1);
// Render the exposed areas.
_q_paintIntoCache(&pix, item, pixmapExposed, itemToPixmap, painter->renderHints(),
- &cacheOption, painterStateProtection);
+ &styleOptionTmp, painterStateProtection);
// Reset expose data.
pixModified = true;
@@ -4959,8 +5024,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
if (pixModified) {
- // Reinsert this pixmap into the cache
- QPixmapCache::insert(pixmapKey, pix);
+ // Insert this pixmap into the cache.
+ deviceData->key = QPixmapCache::insert(pix);
}
// Redraw the exposed area using an untransformed painter. This
@@ -4979,6 +5044,397 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
}
+void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter,
+ const QTransform &viewTransform,
+ QRegion *exposedRegion, QWidget *widget,
+ QList<QGraphicsItem *> *topLevelItems,
+ qreal parentOpacity)
+{
+ // Calculate opacity.
+ qreal opacity;
+ bool invisibleButChildIgnoresParentOpacity = false;
+ if (item) {
+ if (!item->d_ptr->visible)
+ return;
+ QGraphicsItem *p = item->d_ptr->parent;
+ bool itemIgnoresParentOpacity = item->d_ptr->flags & QGraphicsItem::ItemIgnoresParentOpacity;
+ bool parentDoesntPropagateOpacity = (p && (p->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren));
+ if (!itemIgnoresParentOpacity && !parentDoesntPropagateOpacity) {
+ opacity = parentOpacity * item->opacity();
+ } else {
+ opacity = item->d_ptr->opacity;
+ }
+ if (opacity == 0.0 && !(item->d_ptr->flags & QGraphicsItem::ItemDoesntPropagateOpacityToChildren)) {
+ invisibleButChildIgnoresParentOpacity = !item->d_ptr->childrenCombineOpacity();
+ if (!invisibleButChildIgnoresParentOpacity)
+ return;
+ }
+ } else {
+ opacity = parentOpacity;
+ }
+
+ // Calculate the full transform for this item.
+ bool wasDirtyParentSceneTransform = false;
+ bool dontDrawItem = true;
+ QTransform transform;
+ if (item) {
+ if (item->d_ptr->itemIsUntransformable()) {
+ transform = item->deviceTransform(viewTransform);
+ } else {
+ if (item->d_ptr->dirtySceneTransform) {
+ item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
+ : QTransform();
+ item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
+ item->d_ptr->dirtySceneTransform = 0;
+ wasDirtyParentSceneTransform = true;
+ }
+ transform = item->d_ptr->sceneTransform;
+ transform *= viewTransform;
+ }
+
+ QRectF brect = item->boundingRect();
+ // ### This does not take the clip into account.
+ _q_adjustRect(&brect);
+ QRect viewBoundingRect = transform.mapRect(brect).toRect();
+ item->d_ptr->paintedViewBoundingRects.insert(widget, viewBoundingRect);
+ viewBoundingRect.adjust(-1, -1, 1, 1);
+ if (exposedRegion)
+ dontDrawItem = !exposedRegion->intersects(viewBoundingRect);
+ else
+ dontDrawItem = viewBoundingRect.isEmpty();
+ }
+
+ // Find and sort children.
+ QList<QGraphicsItem *> tmp;
+ QList<QGraphicsItem *> *children = 0;
+ if (item) {
+ children = &item->d_ptr->children;
+ } else if (topLevelItems) {
+ children = topLevelItems;
+ } else if (indexMethod == QGraphicsScene::NoIndex || !exposedRegion) {
+ children = &this->topLevelItems;
+ } else {
+ QRectF sceneRect = viewTransform.inverted().mapRect(QRectF(exposedRegion->boundingRect().adjusted(-1, -1, 1, 1)));
+ if (!largestUntransformableItem.isEmpty()) {
+ // ### Nuke this when we move the indexing code into a separate
+ // class. All the largestUntransformableItem code should then go
+ // away, and the estimate function should return untransformable
+ // items as well.
+ QRectF untr = largestUntransformableItem;
+ QRectF ltri = viewTransform.inverted().mapRect(untr);
+ ltri.adjust(-untr.width(), -untr.height(), untr.width(), untr.height());
+ sceneRect.adjust(-ltri.width(), -ltri.height(), ltri.width(), ltri.height());
+ }
+ tmp = estimateItemsInRect(sceneRect);
+
+ QList<QGraphicsItem *> tli;
+ for (int i = 0; i < tmp.size(); ++i)
+ tmp.at(i)->topLevelItem()->d_ptr->itemDiscovered = 1;
+
+ // Sort if the toplevel list is unsorted.
+ if (needSortTopLevelItems) {
+ needSortTopLevelItems = false;
+ qStableSort(this->topLevelItems.begin(),
+ this->topLevelItems.end(), qt_notclosestLeaf);
+ }
+
+ for (int i = 0; i < this->topLevelItems.size(); ++i) {
+ // ### Investigate smarter ways. Looping through all top level
+ // items is not optimal. If the BSP tree is to have maximum
+ // effect, it should be possible to sort the subset of items
+ // quickly. We must use this approach for now, as it's the only
+ // current way to keep the stable sorting order (insertion order).
+ QGraphicsItem *item = this->topLevelItems.at(i);
+ if (item->d_ptr->itemDiscovered) {
+ item->d_ptr->itemDiscovered = 0;
+ tli << item;
+ }
+ }
+
+ tmp = tli;
+ children = &tmp;
+ }
+
+ bool childClip = (item && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape));
+ bool dontDrawChildren = item && dontDrawItem && childClip;
+ childClip &= !dontDrawChildren && !children->isEmpty();
+ if (item && ((item->d_ptr->flags & QGraphicsItem::ItemHasNoContents) || invisibleButChildIgnoresParentOpacity))
+ dontDrawItem = true;
+
+ // Clip children.
+ if (childClip) {
+ painter->save();
+ painter->setWorldTransform(transform);
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ }
+
+ if (!dontDrawChildren) {
+ if (item && item->d_ptr->needSortChildren) {
+ item->d_ptr->needSortChildren = 0;
+ qStableSort(children->begin(), children->end(), qt_notclosestLeaf);
+ } else if (!item && needSortTopLevelItems && children != &tmp) {
+ needSortTopLevelItems = false;
+ qStableSort(children->begin(), children->end(), qt_notclosestLeaf);
+ }
+ }
+
+ // Draw children behind
+ int i = 0;
+ if (!dontDrawChildren) {
+ // ### Don't visit children that don't ignore parent opacity if this
+ // item is invisible.
+ for (i = 0; i < children->size(); ++i) {
+ QGraphicsItem *child = children->at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (!(child->d_ptr->flags & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget,
+ 0, opacity);
+ }
+ }
+
+ // Draw item
+ if (!dontDrawItem) {
+ item->d_ptr->initStyleOption(&styleOptionTmp, transform, exposedRegion ? *exposedRegion : QRegion(), exposedRegion == 0);
+
+ bool clipsToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsToShape);
+ bool savePainter = clipsToShape || painterStateProtection;
+ if (savePainter)
+ painter->save();
+ if (!childClip)
+ painter->setWorldTransform(transform);
+ if (clipsToShape)
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ painter->setOpacity(opacity);
+ drawItemHelper(item, painter, &styleOptionTmp, widget, painterStateProtection);
+
+ if (savePainter)
+ painter->restore();
+ }
+
+ // Draw children in front
+ if (!dontDrawChildren) {
+ // ### Don't visit children that don't ignore parent opacity if this
+ // item is invisible.
+ for (; i < children->size(); ++i) {
+ QGraphicsItem *child = children->at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion,
+ widget, 0, opacity);
+ }
+ } else if (wasDirtyParentSceneTransform) {
+ item->d_ptr->invalidateChildrenSceneTransform();
+ }
+
+ // Restore child clip
+ if (childClip)
+ painter->restore();
+}
+
+void QGraphicsScenePrivate::markDirty(QGraphicsItem *item, const QRectF &rect, bool invalidateChildren,
+ bool maybeDirtyClipPath, bool force, bool ignoreOpacity,
+ bool removingItemFromScene)
+{
+ Q_ASSERT(item);
+ if (updateAll)
+ return;
+
+ if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/maybeDirtyClipPath,
+ /*ignoreVisibleBit=*/force,
+ /*ignoreDirtyBit=*/removingItemFromScene || invalidateChildren,
+ /*ignoreOpacity=*/ignoreOpacity)) {
+ return;
+ }
+
+ const bool fullItemUpdate = rect.isNull();
+ if (!fullItemUpdate && rect.isEmpty())
+ return;
+
+ if (!processDirtyItemsEmitted) {
+ QMetaObject::invokeMethod(q_ptr, "_q_processDirtyItems", Qt::QueuedConnection);
+ processDirtyItemsEmitted = true;
+ }
+
+ if (removingItemFromScene) {
+ // Note that this function can be called from the item's destructor, so
+ // do NOT call any virtual functions on it within this block.
+ if ((connectedSignals & changedSignalMask) || views.isEmpty()) {
+ // This block of code is kept for compatibility. Since 4.5, by default
+ // QGraphicsView does not connect the signal and we use the below
+ // method of delivering updates.
+ q_func()->update();
+ return;
+ }
+
+ for (int i = 0; i < views.size(); ++i) {
+ QGraphicsViewPrivate *viewPrivate = views.at(i)->d_func();
+ QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
+ rect.translate(viewPrivate->dirtyScrollOffset);
+ viewPrivate->updateRect(rect);
+ }
+ return;
+ }
+
+ item->d_ptr->dirty = 1;
+ if (fullItemUpdate)
+ item->d_ptr->fullUpdatePending = 1;
+ else if (!item->d_ptr->fullUpdatePending)
+ item->d_ptr->needsRepaint |= rect;
+
+ if (invalidateChildren) {
+ item->d_ptr->allChildrenDirty = 1;
+ item->d_ptr->dirtyChildren = 1;
+ }
+
+ QGraphicsItem *p = item->d_ptr->parent;
+ while (p && !p->d_ptr->dirtyChildren) {
+ p->d_ptr->dirtyChildren = 1;
+ p = p->d_ptr->parent;
+ }
+}
+
+void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren)
+{
+ Q_Q(QGraphicsScene);
+
+ // Calculate the full scene transform for this item.
+ bool wasDirtyParentSceneTransform = false;
+ if (item && item->d_ptr->dirtySceneTransform && !item->d_ptr->itemIsUntransformable()) {
+ item->d_ptr->sceneTransform = item->d_ptr->parent ? item->d_ptr->parent->d_ptr->sceneTransform
+ : QTransform();
+ item->d_ptr->combineTransformFromParent(&item->d_ptr->sceneTransform);
+ item->d_ptr->dirtySceneTransform = 0;
+ wasDirtyParentSceneTransform = true;
+ }
+
+ // Process item.
+ bool wasDirtyParentViewBoundingRects = false;
+ if (item && (item->d_ptr->dirty || item->d_ptr->paintedViewBoundingRectsNeedRepaint)) {
+ const bool useCompatUpdate = views.isEmpty() || (connectedSignals & changedSignalMask);
+ const bool untransformableItem = item->d_ptr->itemIsUntransformable();
+ const QRectF itemBoundingRect = item->boundingRect();
+
+ if (item->d_ptr->geometryChanged) {
+ // Update growingItemsBoundingRect.
+ if (!hasSceneRect) {
+ QRectF itemSceneBoundingRect = item->d_ptr->sceneTransform.mapRect(itemBoundingRect);
+ _q_adjustRect(&itemSceneBoundingRect);
+ growingItemsBoundingRect |= itemSceneBoundingRect;
+ }
+ item->d_ptr->geometryChanged = 0;
+ }
+
+ if (useCompatUpdate && !untransformableItem && qFuzzyIsNull(item->boundingRegionGranularity())) {
+ // This block of code is kept for compatibility. Since 4.5, by default
+ // QGraphicsView does not connect the signal and we use the below
+ // method of delivering updates.
+ q->update(item->d_ptr->sceneTransform.mapRect(itemBoundingRect));
+ } else {
+ QRectF dirtyRect;
+ bool uninitializedDirtyRect = true;
+
+ for (int j = 0; j < views.size(); ++j) {
+ QGraphicsView *view = views.at(j);
+ QGraphicsViewPrivate *viewPrivate = view->d_func();
+ if (viewPrivate->fullUpdatePending)
+ continue;
+ switch (viewPrivate->viewportUpdateMode) {
+ case QGraphicsView::NoViewportUpdate:
+ continue;
+ case QGraphicsView::FullViewportUpdate:
+ view->viewport()->update();
+ viewPrivate->fullUpdatePending = 1;
+ continue;
+ default:
+ break;
+ }
+
+ if (item->d_ptr->paintedViewBoundingRectsNeedRepaint) {
+ wasDirtyParentViewBoundingRects = true;
+ QRect rect = item->d_ptr->paintedViewBoundingRects.value(viewPrivate->viewport);
+ rect.translate(viewPrivate->dirtyScrollOffset);
+ viewPrivate->updateRect(rect);
+ }
+
+ if (!item->d_ptr->dirty)
+ continue;
+
+ if (uninitializedDirtyRect) {
+ dirtyRect = itemBoundingRect;
+ _q_adjustRect(&dirtyRect);
+ if (!item->d_ptr->fullUpdatePending) {
+ _q_adjustRect(&item->d_ptr->needsRepaint);
+ dirtyRect &= item->d_ptr->needsRepaint;
+ }
+ uninitializedDirtyRect = false;
+ }
+
+ if (dirtyRect.isEmpty())
+ continue; // Discard updates outside the bounding rect.
+
+ QTransform deviceTransform = item->d_ptr->sceneTransform;
+ if (view->isTransformed()) {
+ if (!untransformableItem)
+ deviceTransform *= view->viewportTransform();
+ else
+ deviceTransform = item->deviceTransform(view->viewportTransform());
+ }
+ if (item->d_ptr->hasBoundingRegionGranularity)
+ viewPrivate->updateRegion(deviceTransform.map(QRegion(dirtyRect.toRect())));
+ else
+ viewPrivate->updateRect(deviceTransform.mapRect(dirtyRect).toRect());
+ }
+ }
+ }
+
+ // Process root items / children.
+ if (!item || item->d_ptr->dirtyChildren) {
+ QList<QGraphicsItem *> *children = item ? &item->d_ptr->children : &topLevelItems;
+ const bool allChildrenDirty = item && item->d_ptr->allChildrenDirty;
+ if (!dirtyAncestorContainsChildren) {
+ dirtyAncestorContainsChildren = item && item->d_ptr->fullUpdatePending
+ && (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
+ }
+ for (int i = 0; i < children->size(); ++i) {
+ QGraphicsItem *child = children->at(i);
+ if (wasDirtyParentSceneTransform)
+ child->d_ptr->dirtySceneTransform = 1;
+ if (wasDirtyParentViewBoundingRects)
+ child->d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
+
+ if (allChildrenDirty) {
+ child->d_ptr->dirty = 1;
+ child->d_ptr->fullUpdatePending = 1;
+ child->d_ptr->dirtyChildren = 1;
+ child->d_ptr->allChildrenDirty = 1;
+ } else if (!child->d_ptr->dirty && !child->d_ptr->dirtyChildren) {
+ resetDirtyItem(child);
+ continue;
+ }
+
+ if (dirtyAncestorContainsChildren || updateAll) {
+ // No need to process this child's dirty rect, hence reset the dirty state.
+ // However, we have to continue the recursion because it might have a dirty
+ // view bounding rect that needs repaint. We also have to reset the dirty
+ // state of its descendants.
+ child->d_ptr->dirty = 0;
+ child->d_ptr->fullUpdatePending = 0;
+ if (updateAll)
+ child->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ }
+
+ processDirtyItemsRecursive(child, dirtyAncestorContainsChildren);
+ }
+ } else if (wasDirtyParentSceneTransform) {
+ item->d_ptr->invalidateChildrenSceneTransform();
+ }
+
+ if (item)
+ resetDirtyItem(item);
+}
+
/*!
Paints the given \a items using the provided \a painter, after the
background has been drawn, and before the foreground has been
@@ -5010,111 +5466,29 @@ void QGraphicsScene::drawItems(QPainter *painter,
const QStyleOptionGraphicsItem options[], QWidget *widget)
{
Q_D(QGraphicsScene);
-
- // Detect if painter state protection is disabled.
QTransform viewTransform = painter->worldTransform();
- QVarLengthArray<QGraphicsItem *, 16> childClippers;
-
- for (int i = 0; i < numItems; ++i) {
- QGraphicsItem *item = items[i];
- if (!(item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren)) {
- if (!childClippers.isEmpty()) {
- // Item is not clipped to any ancestor: pop all current clippers.
- for (int i = 0; i < childClippers.size(); ++i)
- painter->restore();
- childClippers.clear();
- }
- } else {
- // Item is clipped to an ancestor, which may or may not be in our
- // child clipper list. Let's start by finding the item's closest
- // clipping ancestor.
- QGraphicsItem *clipParent = item->parentItem();
- while (clipParent && !(clipParent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape))
- clipParent = clipParent->parentItem();
-
- // Pop any in-between clippers. If the clipper is unknown, pop
- // them all. ### QVarLengthArray::lastIndexOf().
- int index = -1;
- for (int n = childClippers.size() - 1; n >= 0; --n) {
- if (childClippers[n] == clipParent) {
- index = n;
- break;
- }
- }
- if (index != -1) {
- int toPop = childClippers.size() - index - 1;
- if (toPop > 0) {
- for (int i = 0; i < toPop; ++i)
- painter->restore();
- childClippers.resize(index + 1);
- }
- }
-
- // Sanity check
- if (!childClippers.isEmpty())
- Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
-
- // If the clipper list is empty at this point, but we're still
- // clipped to an ancestor, then we need to build the clip chain
- // ourselves. There is only one case that can produce this issue:
- // This item is stacked behind an ancestor:
- // ItemStacksBehindParent.
- if (childClippers.isEmpty()) {
- Q_ASSERT(clipParent != 0);
- // Build a stack of clippers.
- QVarLengthArray<QGraphicsItem *, 16> clippers;
- QGraphicsItem *p = clipParent;
- do {
- if (p->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape)
- clippers.append(p);
- } while ((p = p->parentItem()) && (p->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren));
-
- // ### This code path can also use the itemTransform
- // optimization, but it's hit very rarely.
- for (int i = clippers.size() - 1; i >= 0; --i) {
- QGraphicsItem *clipper = clippers[i];
- painter->setWorldTransform(clipper->deviceTransform(viewTransform), false);
-
- childClippers.append(clipper);
- painter->save();
- painter->setClipPath(clipper->shape(), Qt::IntersectClip);
- }
- Q_ASSERT(childClippers[childClippers.size() - 1] == clipParent);
- }
- }
-
- // Set up the painter transform
- painter->setWorldTransform(item->deviceTransform(viewTransform), false);
-
- // Save painter
- bool saveState = (d->painterStateProtection || (item->flags() & QGraphicsItem::ItemClipsToShape));
- if (saveState)
- painter->save();
-
- // Set local clip
- if (item->flags() & QGraphicsItem::ItemClipsToShape)
- painter->setClipPath(item->shape(), Qt::IntersectClip);
-
- // Setup opacity
- painter->setOpacity(item->effectiveOpacity());
+ Q_UNUSED(options);
- // Draw the item
- d->drawItemHelper(item, painter, &options[i], widget, d->painterStateProtection);
-
- if (saveState)
- painter->restore();
+ // Determine view, expose and flags.
+ QGraphicsView *view = widget ? qobject_cast<QGraphicsView *>(widget->parentWidget()) : 0;
+ QRegion *expose = 0;
+ if (view)
+ expose = &view->d_func()->exposedRegion;
- if (item->flags() & QGraphicsItem::ItemClipsChildrenToShape) {
- // Clip descendents to this item's shape, and keep the painter
- // saved.
- childClippers.append(item);
- painter->save();
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ // Find all toplevels, they are already sorted.
+ QList<QGraphicsItem *> topLevelItems;
+ for (int i = 0; i < numItems; ++i) {
+ QGraphicsItem *item = items[i]->topLevelItem();
+ if (!item->d_ptr->itemDiscovered) {
+ topLevelItems << item;
+ item->d_ptr->itemDiscovered = 1;
+ d->drawSubtreeRecursive(item, painter, viewTransform, expose, widget);
}
}
- for (int i = 0; i < childClippers.size(); ++i)
- painter->restore();
+ // Reset discovery bits.
+ for (int i = 0; i < topLevelItems.size(); ++i)
+ topLevelItems.at(i)->d_ptr->itemDiscovered = 0;
painter->setWorldTransform(viewTransform);
}
@@ -5226,73 +5600,6 @@ bool QGraphicsScene::focusNextPrevChild(bool next)
*/
/*!
- \internal
-
- This private function is called by QGraphicsItem, which is a friend of
- QGraphicsScene. It is used by QGraphicsScene to record the rectangles that
- need updating. It also launches a single-shot timer to ensure that
- updated() will be emitted later.
-
- The \a item parameter is the item that changed, and \a rect is the
- area of the item that changed given in item coordinates.
-*/
-void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect)
-{
- Q_D(QGraphicsScene);
- // Deliver the actual update.
- if (!d->updateAll) {
- if (d->views.isEmpty() || ((d->connectedSignals & d->changedSignalMask) && !item->d_ptr->itemIsUntransformable()
- && qFuzzyCompare(item->boundingRegionGranularity(), qreal(0.0)))) {
- // This block of code is kept for compatibility. Since 4.5, by default
- // QGraphicsView does not connect the signal and we use the below
- // method of delivering updates.
- update(item->sceneBoundingRect());
- } else {
- // ### Remove _q_adjustedRects().
- QRectF boundingRect(adjustedItemBoundingRect(item));
- if (!rect.isNull()) {
- QRectF adjustedRect(rect);
- _q_adjustRect(&adjustedRect);
- boundingRect &= adjustedRect;
- }
-
- // Update each view directly.
- for (int i = 0; i < d->views.size(); ++i)
- d->views.at(i)->d_func()->itemUpdated(item, boundingRect);
- }
- }
- if (item->d_ptr->dirty) {
- d->dirtyItems << item;
- d->resetDirtyItemsLater();
- }
-
- if (!item->isVisible())
- return; // Hiding an item won't effect the largestUntransformableItem/sceneRect.
-
- // Update d->largestUntransformableItem by mapping this item's bounding
- // rect back to the topmost untransformable item's untransformed
- // coordinate system (which sort of equals the 1:1 coordinate system of an
- // untransformed view).
- if (item->d_ptr->itemIsUntransformable()) {
- QGraphicsItem *parent = item;
- while (parent && (parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorIgnoresTransformations))
- parent = parent->parentItem();
- d->largestUntransformableItem |= item->mapToItem(parent, item->boundingRect()).boundingRect();
- }
-
- // Only track the automatically growing scene rect if the scene has no
- // defined scene rect.
- if (!d->hasSceneRect) {
- QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect;
- QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect());
- _q_adjustRect(&adjustedItemSceneBoundingRect);
- d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect;
- if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect)
- emit sceneRectChanged(d->growingItemsBoundingRect);
- }
-}
-
-/*!
\since 4.4
Returns the scene's style, or the same as QApplication::style() if the
@@ -5304,7 +5611,7 @@ QStyle *QGraphicsScene::style() const
{
Q_D(const QGraphicsScene);
// ### This function, and the use of styles in general, is non-reentrant.
- return d->style ? d->style : qApp->style();
+ return d->style ? d->style : QApplication::style();
}
/*!
@@ -5381,7 +5688,7 @@ QFont QGraphicsScene::font() const
void QGraphicsScene::setFont(const QFont &font)
{
Q_D(QGraphicsScene);
- QFont naturalFont = qApp->font();
+ QFont naturalFont = QApplication::font();
naturalFont.resolve(0);
QFont resolvedFont = font.resolve(naturalFont);
d->setFont_helper(resolvedFont);
@@ -5418,7 +5725,7 @@ QPalette QGraphicsScene::palette() const
void QGraphicsScene::setPalette(const QPalette &palette)
{
Q_D(QGraphicsScene);
- QPalette naturalPalette = qApp->palette();
+ QPalette naturalPalette = QApplication::palette();
naturalPalette.resolve(0);
QPalette resolvedPalette = palette.resolve(naturalPalette);
d->setPalette_helper(resolvedPalette);
diff --git a/src/gui/graphicsview/qgraphicsscene.h b/src/gui/graphicsview/qgraphicsscene.h
index 9802f87..c4c9f9c 100644
--- a/src/gui/graphicsview/qgraphicsscene.h
+++ b/src/gui/graphicsview/qgraphicsscene.h
@@ -271,17 +271,14 @@ Q_SIGNALS:
void selectionChanged();
private:
- void itemUpdated(QGraphicsItem *item, const QRectF &rect);
-
Q_DECLARE_PRIVATE(QGraphicsScene)
Q_DISABLE_COPY(QGraphicsScene)
Q_PRIVATE_SLOT(d_func(), void _q_updateIndex())
Q_PRIVATE_SLOT(d_func(), void _q_emitUpdated())
- Q_PRIVATE_SLOT(d_func(), void _q_removeItemLater(QGraphicsItem *item))
Q_PRIVATE_SLOT(d_func(), void _q_updateLater())
Q_PRIVATE_SLOT(d_func(), void _q_polishItems())
Q_PRIVATE_SLOT(d_func(), void _q_updateSortCache())
- Q_PRIVATE_SLOT(d_func(), void _q_resetDirtyItems())
+ Q_PRIVATE_SLOT(d_func(), void _q_processDirtyItems())
friend class QGraphicsItem;
friend class QGraphicsItemPrivate;
friend class QGraphicsView;
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index befbbd8..11e9b64 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -57,6 +57,7 @@
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
+#include "qgraphicsview.h"
#include "qgraphicsscene_bsp_p.h"
#include "qgraphicsitem_p.h"
@@ -68,6 +69,9 @@
#include <QtGui/qfont.h>
#include <QtGui/qpalette.h>
#include <QtGui/qstyle.h>
+#include <QtGui/qstyleoption.h>
+
+static const int QGRAPHICSSCENE_INDEXTIMER_TIMEOUT = 2000;
QT_BEGIN_NAMESPACE
@@ -104,28 +108,30 @@ public:
QList<QRectF> updatedRects;
bool updateAll;
bool calledEmitUpdated;
+ bool processDirtyItemsEmitted;
QPainterPath selectionArea;
int selectionChanging;
QSet<QGraphicsItem *> selectedItems;
QList<QGraphicsItem *> unindexedItems;
QList<QGraphicsItem *> indexedItems;
- QList<QGraphicsItem *> dirtyItems;
QList<QGraphicsItem *> pendingUpdateItems;
QList<QGraphicsItem *> unpolishedItems;
+ QList<QGraphicsItem *> topLevelItems;
+ bool needSortTopLevelItems;
QMap<QGraphicsItem *, QPointF> movingItemsInitialPositions;
+ void registerTopLevelItem(QGraphicsItem *item);
+ void unregisterTopLevelItem(QGraphicsItem *item);
void _q_updateLater();
void _q_polishItems();
- void _q_resetDirtyItems();
- void resetDirtyItemsLater();
- bool dirtyItemResetPending;
+ void _q_processDirtyItems();
QList<int> freeItemIndexes;
bool regenerateIndex;
bool purgePending;
- void _q_removeItemLater(QGraphicsItem *item);
+ void removeItemHelper(QGraphicsItem *item);
QSet<QGraphicsItem *> removedItems;
void purgeRemovedItems();
@@ -134,7 +140,7 @@ public:
int indexTimerId;
bool restartIndexTimer;
- void startIndexTimer();
+ void startIndexTimer(int interval = QGRAPHICSSCENE_INDEXTIMER_TIMEOUT);
bool stickyFocus;
bool hasFocus;
@@ -165,6 +171,9 @@ public:
Qt::DropAction lastDropAction;
QList<QGraphicsItem *> cachedItemsUnderMouse;
QList<QGraphicsItem *> hoverItems;
+ bool allItemsIgnoreHoverEvents;
+ bool allItemsUseDefaultCursor;
+ void enableMouseTrackingOnViews();
QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownPos;
QMap<Qt::MouseButton, QPointF> mouseGrabberButtonDownScenePos;
QMap<Qt::MouseButton, QPoint> mouseGrabberButtonDownScreenPos;
@@ -197,6 +206,10 @@ public:
void mousePressEventHandler(QGraphicsSceneMouseEvent *mouseEvent);
QGraphicsWidget *windowForItem(const QGraphicsItem *item) const;
+ void recursive_items_helper(QGraphicsItem *item, QRectF rect, QList<QGraphicsItem *> *items,
+ const QTransform &parentTransform, const QTransform &viewTransform,
+ Qt::ItemSelectionMode mode, Qt::SortOrder order, qreal parentOpacity = 1.0) const;
+
QList<QGraphicsItem *> items_helper(const QPointF &pos) const;
QList<QGraphicsItem *> items_helper(const QRectF &rect,
Qt::ItemSelectionMode mode,
@@ -247,6 +260,26 @@ public:
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection);
+ void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform,
+ QRegion *exposedRegion, QWidget *widget,
+ QList<QGraphicsItem *> *topLevelItems = 0, qreal parentOpacity = qreal(1.0));
+ void markDirty(QGraphicsItem *item, const QRectF &rect = QRectF(), bool invalidateChildren = false,
+ bool maybeDirtyClipPath = false, bool force = false, bool ignoreOpacity = false,
+ bool removingItemFromScene = false);
+ void processDirtyItemsRecursive(QGraphicsItem *item, bool dirtyAncestorContainsChildren = false);
+
+ inline void resetDirtyItem(QGraphicsItem *item)
+ {
+ Q_ASSERT(item);
+ item->d_ptr->dirty = 0;
+ item->d_ptr->paintedViewBoundingRectsNeedRepaint = 0;
+ item->d_ptr->geometryChanged = 0;
+ item->d_ptr->dirtyChildren = 0;
+ item->d_ptr->needsRepaint = QRectF();
+ item->d_ptr->allChildrenDirty = 0;
+ item->d_ptr->fullUpdatePending = 0;
+ }
+
QStyle *style;
QFont font;
void setFont_helper(const QFont &font);
@@ -257,9 +290,7 @@ public:
void resolvePalette();
void updatePalette(const QPalette &palette);
- mutable QVector<QTransform> sceneTransformCache;
- mutable QBitArray validTransforms;
- mutable QVector<int> freeSceneTransformSlots;
+ QStyleOptionGraphicsItem styleOptionTmp;
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 96e9a96..a3e2ebe 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -39,8 +39,6 @@
**
****************************************************************************/
-//#define QGRAPHICSVIEW_DEBUG
-
static const int QGRAPHICSVIEW_REGION_RECT_THRESHOLD = 50;
static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime < 2^9
@@ -200,16 +198,7 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
Note that setting a flag usually imposes a side effect, and this effect
can vary between paint devices and platforms.
- \value DontClipPainter QGraphicsView sometimes clips the painter when
- rendering the scene contents. This can generally improve performance
- (e.g., rendering only small parts of a large pixmap), and protects against
- rendering mistakes (e.g., drawing outside bounding rectangles, or outside
- the exposed area). In some situations, however, the painter clip can slow
- down rendering; especially when all painting is restricted to inside
- exposed areas. By enabling this flag, QGraphicsView will completely
- disable its implicit clipping. Note that rendering artifacts from using a
- semi-transparent foreground or background brush can occur if clipping is
- disabled.
+ \value DontClipPainter This value is obsolete and has no effect.
\value DontSavePainterState When rendering, QGraphicsView protects the
painter state (see QPainter::save()) when rendering the background or
@@ -228,6 +217,8 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
minimizing the areas that require redrawing, which improves performance. A
common side effect is that items that do draw with antialiasing can leave
painting traces behind on the scene as they are moved.
+
+ \omitvalue IndirectPainting
*/
/*!
@@ -338,8 +329,6 @@ QGraphicsViewPrivate::QGraphicsViewPrivate()
#endif
lastDragDropEvent(0),
fullUpdatePending(true),
- dirtyRectCount(0),
- updatingLater(false),
updateSceneSlotReimplementedChecked(false)
{
styleOptions.reserve(QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS);
@@ -400,7 +389,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
int left = q_round_bound(viewRect.left());
int right = q_round_bound(viewRect.right() - width);
if (left >= right) {
- q->horizontalScrollBar()->setRange(0, 0);
+ hbar->setRange(0, 0);
switch (alignment & Qt::AlignHorizontal_Mask) {
case Qt::AlignLeft:
@@ -415,9 +404,9 @@ void QGraphicsViewPrivate::recalculateContentSize()
break;
}
} else {
- q->horizontalScrollBar()->setRange(left, right);
- q->horizontalScrollBar()->setPageStep(width);
- q->horizontalScrollBar()->setSingleStep(width / 20);
+ hbar->setRange(left, right);
+ hbar->setPageStep(width);
+ hbar->setSingleStep(width / 20);
leftIndent = 0;
}
@@ -426,7 +415,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
int top = q_round_bound(viewRect.top());
int bottom = q_round_bound(viewRect.bottom() - height);
if (top >= bottom) {
- q->verticalScrollBar()->setRange(0, 0);
+ vbar->setRange(0, 0);
switch (alignment & Qt::AlignVertical_Mask) {
case Qt::AlignTop:
@@ -441,9 +430,9 @@ void QGraphicsViewPrivate::recalculateContentSize()
break;
}
} else {
- q->verticalScrollBar()->setRange(top, bottom);
- q->verticalScrollBar()->setPageStep(height);
- q->verticalScrollBar()->setSingleStep(height / 20);
+ vbar->setRange(top, bottom);
+ vbar->setPageStep(height);
+ vbar->setSingleStep(height / 20);
topIndent = 0;
}
@@ -455,7 +444,7 @@ void QGraphicsViewPrivate::recalculateContentSize()
// scroll instead.
if (oldLeftIndent != leftIndent || oldTopIndent != topIndent) {
dirtyScroll = true;
- q->viewport()->update();
+ updateAll();
} else if (q->isRightToLeft() && !leftIndent) {
// In reverse mode, the horizontal scroll always changes after the content
// size has changed, as the scroll is calculated by summing the min and
@@ -481,7 +470,7 @@ void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
if (q->underMouse()) {
// Last scene pos: lastMouseMoveScenePoint
// Current mouse pos:
- QPointF transformationDiff = q->mapToScene(q->viewport()->rect().center())
+ QPointF transformationDiff = q->mapToScene(viewport->rect().center())
- q->mapToScene(q->mapFromGlobal(QCursor::pos()));
q->centerOn(lastMouseMoveScenePoint + transformationDiff);;
} else {
@@ -503,7 +492,7 @@ void QGraphicsViewPrivate::centerView(QGraphicsView::ViewportAnchor anchor)
void QGraphicsViewPrivate::updateLastCenterPoint()
{
Q_Q(QGraphicsView);
- lastCenterPoint = q->mapToScene(q->viewport()->rect().center());
+ lastCenterPoint = q->mapToScene(viewport->rect().center());
}
/*!
@@ -541,15 +530,15 @@ void QGraphicsViewPrivate::updateScroll()
scrollX = qint64(-leftIndent);
if (q->isRightToLeft()) {
if (!leftIndent) {
- scrollX += q->horizontalScrollBar()->minimum();
- scrollX += q->horizontalScrollBar()->maximum();
- scrollX -= q->horizontalScrollBar()->value();
+ scrollX += hbar->minimum();
+ scrollX += hbar->maximum();
+ scrollX -= hbar->value();
}
} else {
- scrollX += q->horizontalScrollBar()->value();
+ scrollX += hbar->value();
}
- scrollY = qint64(q->verticalScrollBar()->value() - topIndent);
+ scrollY = qint64(vbar->value() - topIndent);
dirtyScroll = false;
}
@@ -589,7 +578,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
return;
QGraphicsSceneMouseEvent mouseEvent(QEvent::GraphicsSceneMouseMove);
- mouseEvent.setWidget(q->viewport());
+ mouseEvent.setWidget(viewport);
mouseEvent.setButtonDownScenePos(mousePressButton, mousePressScenePoint);
mouseEvent.setButtonDownScreenPos(mousePressButton, mousePressScreenPoint);
mouseEvent.setScenePos(q->mapToScene(event->pos()));
@@ -614,6 +603,16 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
}
#ifndef QT_NO_CURSOR
+ // If all the items ignore hover events, we don't look-up any items
+ // in QGraphicsScenePrivate::dispatchHoverEvent, hence the
+ // cachedItemsUnderMouse list will be empty. We therefore do the look-up
+ // for cursor items here if not all items use the default cursor.
+ if (scene->d_func()->allItemsIgnoreHoverEvents && !scene->d_func()->allItemsUseDefaultCursor
+ && scene->d_func()->cachedItemsUnderMouse.isEmpty()) {
+ scene->d_func()->cachedItemsUnderMouse = scene->d_func()->itemsAtPosition(mouseEvent.screenPos(),
+ mouseEvent.scenePos(),
+ mouseEvent.widget());
+ }
// Find the topmost item under the mouse with a cursor.
foreach (QGraphicsItem *item, scene->d_func()->cachedItemsUnderMouse) {
if (item->hasCursor()) {
@@ -626,7 +625,7 @@ void QGraphicsViewPrivate::mouseMoveEventHandler(QMouseEvent *event)
if (hasStoredOriginalCursor) {
// Restore the original viewport cursor.
hasStoredOriginalCursor = false;
- q->viewport()->setCursor(originalCursor);
+ viewport->setCursor(originalCursor);
}
#endif
}
@@ -658,8 +657,6 @@ QRegion QGraphicsViewPrivate::rubberBandRegion(const QWidget *widget, const QRec
#ifndef QT_NO_CURSOR
void QGraphicsViewPrivate::_q_setViewportCursor(const QCursor &cursor)
{
- Q_Q(QGraphicsView);
- QWidget *viewport = q->viewport();
if (!hasStoredOriginalCursor) {
hasStoredOriginalCursor = true;
originalCursor = viewport->cursor();
@@ -685,9 +682,9 @@ void QGraphicsViewPrivate::_q_unsetViewportCursor()
// Restore the original viewport cursor.
hasStoredOriginalCursor = false;
if (dragMode == QGraphicsView::ScrollHandDrag)
- q->viewport()->setCursor(Qt::OpenHandCursor);
+ viewport->setCursor(Qt::OpenHandCursor);
else
- q->viewport()->setCursor(originalCursor);
+ viewport->setCursor(originalCursor);
}
#endif
@@ -726,7 +723,7 @@ void QGraphicsViewPrivate::populateSceneDragDropEvent(QGraphicsSceneDragDropEven
dest->setProposedAction(source->proposedAction());
dest->setDropAction(source->dropAction());
dest->setMimeData(source->mimeData());
- dest->setWidget(q->viewport());
+ dest->setWidget(viewport);
dest->setSource(source->source());
#else
Q_UNUSED(dest)
@@ -749,12 +746,13 @@ QRect QGraphicsViewPrivate::mapToViewRect(const QGraphicsItem *item, const QRect
}
// Translate-only
+ // COMBINE
QPointF offset;
const QGraphicsItem *parentItem = item;
const QGraphicsItemPrivate *itemd;
do {
itemd = parentItem->d_ptr.data();
- if (itemd->hasTransform)
+ if (itemd->transformData)
break;
offset += itemd->pos;
} while ((parentItem = itemd->parent));
@@ -786,7 +784,7 @@ QRegion QGraphicsViewPrivate::mapToViewRegion(const QGraphicsItem *item, const Q
const_cast<QGraphicsViewPrivate *>(this)->updateScroll();
// Accurate bounding region
- QTransform itv = item->sceneTransform() * q->viewportTransform();
+ QTransform itv = item->deviceTransform(q->viewportTransform());
return item->boundingRegion(itv) & itv.mapRect(rect).toAlignedRect();
}
@@ -803,219 +801,90 @@ static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item)
return boundingRect;
}
-/*!
- \internal
-*/
-void QGraphicsViewPrivate::itemUpdated(QGraphicsItem *item, const QRectF &rect)
+void QGraphicsViewPrivate::processPendingUpdates()
{
- if (fullUpdatePending || viewportUpdateMode == QGraphicsView::NoViewportUpdate)
- return;
- if (item->d_ptr->dirty)
- updateLater();
-
- QRectF updateRect = rect;
- if ((item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) || item->d_ptr->children.isEmpty()) {
- updateRect &= adjustedItemBoundingRect(item);
- if (updateRect.isEmpty())
- return;
- }
-
- QGraphicsItem *clipItem = item;
- if (item->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren) {
- // Minimize unnecessary redraw.
- QGraphicsItem *parent = item;
- while ((parent = parent->d_ptr->parent)) {
- if (parent->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape) {
- // Map update rect to the current parent and itersect with its bounding rect.
- updateRect = clipItem->itemTransform(parent).mapRect(updateRect)
- & adjustedItemBoundingRect(parent);
- if (updateRect.isEmpty())
- return;
- clipItem = parent;
- }
-
- if (!(parent->d_ptr->ancestorFlags & QGraphicsItemPrivate::AncestorClipsChildren))
- break;
- }
- }
-
- // Map update rect from clipItem coordinates to view coordinates.
- Q_ASSERT(clipItem);
- if (!item->d_ptr->hasBoundingRegionGranularity)
- this->updateRect(mapToViewRect(clipItem, updateRect) & viewport->rect());
- else
- updateRegion(mapToViewRegion(clipItem, updateRect) & viewport->rect());
-}
-
-void QGraphicsViewPrivate::updateLater()
-{
- Q_Q(QGraphicsView);
- if (updatingLater)
- return;
- updatingLater = true;
- QMetaObject::invokeMethod(q, "_q_updateLaterSlot", Qt::QueuedConnection);
-}
-
-void QGraphicsViewPrivate::_q_updateLaterSlot()
-{
- Q_Q(QGraphicsView);
if (!scene)
return;
- QRect vr = viewport->rect();
- QTransform viewTransform = q->viewportTransform();
- const QList<QGraphicsItem *> &dirtyItems = scene->d_func()->dirtyItems;
- for (int i = 0; i < dirtyItems.size(); ++i) {
- const QGraphicsItem *item = dirtyItems.at(i);
- if (item->d_ptr->discardUpdateRequest(/*ignoreClipping=*/false,
- /*ignoreVisibleBit=*/false,
- /*ignoreDirtyBit=*/true)) {
- continue;
- }
- QTransform x = item->sceneTransform() * viewTransform;
- updateRect(x.mapRect(item->boundingRect()).toAlignedRect() & vr);
+ if (fullUpdatePending) { // We have already called viewport->update()
+ dirtyBoundingRect = QRect();
+ dirtyRegion = QRegion();
+ return;
}
- dirtyRectCount += dirtyRects.size();
-
- bool noUpdate = !fullUpdatePending && viewportUpdateMode == QGraphicsView::FullViewportUpdate;
- if ((dirtyRectCount > 0 || !dirtyBoundingRect.isEmpty()) && !fullUpdatePending && !noUpdate) {
- if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate
- || (viewportUpdateMode == QGraphicsView::SmartViewportUpdate
- && dirtyRectCount >= QGRAPHICSVIEW_REGION_RECT_THRESHOLD)) {
- if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
- viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
- } else {
- viewport->update(dirtyBoundingRect);
- }
- } else {
- // ### Improve this block, which is very slow for complex regions. We
- // need to strike the balance between having an accurate update
- // region, and running fast. The below approach is the simplest way to
- // create a region from a bunch of rects, but we might want to use
- // other approaches; e.g., a grid of a fixed size representing
- // quadrants of the viewport, which we mark as dirty depending on the
- // rectangles in the list. Perhaps this should go into a
- // QRegion::fromRects(rects, how) function.
- QRegion region;
- if (!(optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)) {
- for (int i = 0; i < dirtyRegions.size(); ++i) {
- QVector<QRect> rects = dirtyRegions.at(i).rects();
- for (int j = 0; j < rects.size(); ++j)
- region += rects.at(j).adjusted(-2, -2, 2, 2);
- }
- for (int i = 0; i < dirtyRects.size(); ++i)
- region += dirtyRects.at(i).adjusted(-2, -2, 2, 2);
- } else {
- for (int i = 0; i < dirtyRegions.size(); ++i)
- region += dirtyRegions.at(i);
- for (int i = 0; i < dirtyRects.size(); ++i)
- region += dirtyRects.at(i);
- }
-
- viewport->update(region);
- }
+ if (viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate) {
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ viewport->update(dirtyBoundingRect.adjusted(-1, -1, 1, 1));
+ else
+ viewport->update(dirtyBoundingRect.adjusted(-2, -2, 2, 2));
+ } else {
+ viewport->update(dirtyRegion); // Already adjusted in updateRect/Region.
}
- dirtyRegions.clear();
- dirtyRects.clear();
- dirtyRectCount = 0;
- dirtyBoundingRect = QRect();
- updatingLater = false;
-}
-
-void QGraphicsViewPrivate::updateAll()
-{
- Q_Q(QGraphicsView);
- q->viewport()->update();
- fullUpdatePending = true;
- dirtyRectCount = 0;
dirtyBoundingRect = QRect();
- updatingLater = false;
+ dirtyRegion = QRegion();
}
void QGraphicsViewPrivate::updateRegion(const QRegion &r)
{
- if (r.isEmpty())
+ if (r.isEmpty() || fullUpdatePending)
return;
- Q_Q(QGraphicsView);
-
// Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
- q->viewport()->update();
+ viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
dirtyBoundingRect |= r.boundingRect();
- if (dirtyBoundingRect == q->viewport()->rect()) {
+ if (dirtyBoundingRect.contains(viewport->rect())) {
fullUpdatePending = true;
- q->viewport()->update();
- } else {
- updateLater();
+ viewport->update();
}
break;
- case QGraphicsView::SmartViewportUpdate:
- dirtyBoundingRect |= r.boundingRect();
- if ((dirtyRectCount + r.numRects()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
- dirtyRegions << r;
- dirtyRectCount += r.numRects();
- updateLater();
- break;
+ case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
case QGraphicsView::MinimalViewportUpdate:
- dirtyRegions << r;
- dirtyRectCount += r.numRects();
- updateLater();
+ {
+ const QVector<QRect> &rects = r.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ dirtyRegion += rects.at(i).adjusted(-1, -1, 1, 1);
+ else
+ dirtyRegion += rects.at(i).adjusted(-2, -2, 2, 2);
+ }
break;
+ }
case QGraphicsView::NoViewportUpdate:
// Unreachable
break;
}
-
- // Compress the regions...
- if (dirtyRectCount > QGRAPHICSVIEW_REGION_RECT_THRESHOLD && dirtyRegions.size() > 1) {
- QRegion masterRegion;
- for (int i=0; i<dirtyRegions.size(); ++i) {
- masterRegion |= dirtyRegions.at(i);
- }
- dirtyRectCount = masterRegion.numRects();
- dirtyRegions.clear();
- dirtyRegions << masterRegion;
- }
}
void QGraphicsViewPrivate::updateRect(const QRect &r)
{
- if (r.isEmpty())
+ if (r.isEmpty() || fullUpdatePending)
return;
- Q_Q(QGraphicsView);
-
// Rect intersects viewport - update everything?
switch (viewportUpdateMode) {
case QGraphicsView::FullViewportUpdate:
fullUpdatePending = true;
- q->viewport()->update();
+ viewport->update();
break;
case QGraphicsView::BoundingRectViewportUpdate:
dirtyBoundingRect |= r;
- if (dirtyBoundingRect == q->viewport()->rect()) {
+ if (dirtyBoundingRect.contains(viewport->rect())) {
fullUpdatePending = true;
- q->viewport()->update();
- } else {
- updateLater();
+ viewport->update();
}
break;
- case QGraphicsView::SmartViewportUpdate:
- dirtyBoundingRect |= r;
- if ((dirtyRectCount + dirtyRects.size()) < QGRAPHICSVIEW_REGION_RECT_THRESHOLD)
- dirtyRects << r;
- updateLater();
- break;
+ case QGraphicsView::SmartViewportUpdate: // ### DEPRECATE
case QGraphicsView::MinimalViewportUpdate:
- dirtyRects << r;
- updateLater();
+ if (optimizationFlags & QGraphicsView::DontAdjustForAntialiasing)
+ dirtyRegion += r.adjusted(-1, -1, 1, 1);
+ else
+ dirtyRegion += r.adjusted(-2, -2, 2, 2);
break;
case QGraphicsView::NoViewportUpdate:
// Unreachable
@@ -1061,7 +930,7 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg
// Step 1) If all items are contained within the expose region, then
// return a list of all visible items.
- const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 2, 2))
+ const QRectF exposedRegionSceneBounds = q->mapToScene(exposedRegion.boundingRect().adjusted(-1, -1, 1, 1))
.boundingRect();
if (exposedRegionSceneBounds.contains(scene->d_func()->growingItemsBoundingRect)) {
Q_ASSERT(allItems);
@@ -1117,69 +986,6 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg
return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
}
-void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &itemList,
- QGraphicsItem **itemArray,
- QStyleOptionGraphicsItem *styleOptionArray,
- const QTransform &worldTransform,
- bool allItems,
- const QRegion &exposedRegion) const
-{
- // Two unit vectors.
- QLineF v1(0, 0, 1, 0);
- QLineF v2(0, 0, 0, 1);
- QTransform itemToViewportTransform;
- QRectF brect;
- QTransform reverseMap;
-
- for (int i = 0; i < itemList.size(); ++i) {
- QGraphicsItem *item = itemArray[i] = itemList[i];
-
- QStyleOptionGraphicsItem &option = styleOptionArray[i];
- brect = item->boundingRect();
- option.state = QStyle::State_None;
- option.rect = brect.toRect();
- option.exposedRect = QRectF();
- if (item->d_ptr->selected)
- option.state |= QStyle::State_Selected;
- if (item->d_ptr->enabled)
- option.state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option.state |= QStyle::State_HasFocus;
- if (scene->d_func()->hoverItems.contains(item))
- option.state |= QStyle::State_MouseOver;
- if (item == scene->mouseGrabberItem())
- option.state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsScene::render()
- // and QGraphicsView::render() - consider refactoring
- itemToViewportTransform = item->deviceTransform(worldTransform);
-
- if (itemToViewportTransform.type() <= QTransform::TxTranslate) {
- // Translation and rotation only? The LOD is 1.
- option.levelOfDetail = 1;
- } else {
- // LOD is the transformed area of a 1x1 rectangle.
- option.levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
- }
- option.matrix = itemToViewportTransform.toAffine(); //### discards perspective
-
- if (!allItems) {
- // Determine the item's exposed area
- reverseMap = itemToViewportTransform.inverted();
- foreach (const QRect &rect, exposedRegion.rects()) {
- option.exposedRect |= reverseMap.mapRect(QRectF(rect.adjusted(-1, -1, 1, 1)));
- if (option.exposedRect.contains(brect))
- break;
- }
- option.exposedRect &= brect;
- } else {
- // The whole item is exposed
- option.exposedRect = brect;
- }
- }
-}
-
/*!
Constructs a QGraphicsView. \a parent is passed to QWidget's constructor.
*/
@@ -1289,7 +1095,7 @@ void QGraphicsView::setRenderHints(QPainter::RenderHints hints)
if (hints == d->renderHints)
return;
d->renderHints = hints;
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -1307,7 +1113,7 @@ void QGraphicsView::setRenderHint(QPainter::RenderHint hint, bool enabled)
else
d->renderHints &= ~hint;
if (oldHints != d->renderHints)
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -1594,7 +1400,7 @@ void QGraphicsView::resetCachedContent()
if (d->cacheMode & CacheBackground) {
// Background caching is enabled.
d->mustResizeBackgroundPixmap = true;
- viewport()->update();
+ d->updateAll();
} else if (d->mustResizeBackgroundPixmap) {
// Background caching is disabled.
// Cleanup, free some resources.
@@ -1683,7 +1489,7 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
return;
// Always update the viewport when the scene changes.
- viewport()->update();
+ d->updateAll();
// Remove the previously assigned scene.
if (d->scene) {
@@ -1704,6 +1510,12 @@ void QGraphicsView::setScene(QGraphicsScene *scene)
d->recalculateContentSize();
d->lastCenterPoint = sceneRect().center();
d->keepLastCenterPoint = true;
+ // We are only interested in mouse tracking if items accept
+ // hover events or use non-default cursors.
+ if (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor) {
+ d->viewport->setMouseTracking(true);
+ }
} else {
d->recalculateContentSize();
}
@@ -2145,40 +1957,10 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect
.scale(xratio, yratio)
.translate(-sourceRect.left(), -sourceRect.top());
- // Two unit vectors.
- QLineF v1(0, 0, 1, 0);
- QLineF v2(0, 0, 0, 1);
-
// Generate the style options
QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- QStyleOptionGraphicsItem* option = styleOptionArray;
- for (int i = 0; i < numItems; ++i, ++option) {
- QGraphicsItem *item = itemArray[i];
-
- option->state = QStyle::State_None;
- option->rect = item->boundingRect().toRect();
- if (item->isSelected())
- option->state |= QStyle::State_Selected;
- if (item->isEnabled())
- option->state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option->state |= QStyle::State_HasFocus;
- if (d->scene->d_func()->hoverItems.contains(item))
- option->state |= QStyle::State_MouseOver;
- if (item == d->scene->mouseGrabberItem())
- option->state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsScene::render()
- // and QGraphicsView::paintEvent() - consider refactoring
- QTransform itemToViewportTransform = item->deviceTransform(painterMatrix);
-
- option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
- option->matrix = itemToViewportTransform.toAffine();
-
- option->exposedRect = item->boundingRect();
- option->exposedRect &= itemToViewportTransform.inverted().mapRect(targetRect);
- }
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
painter->save();
@@ -2304,7 +2086,7 @@ QList<QGraphicsItem *> QGraphicsView::items(const QPoint &pos) const
QTransform xinv = viewportTransform().inverted();
return d->scene->items(xinv.mapRect(QRectF(pos.x(), pos.y(), 1, 1)));
}
- return d->scene->items(mapToScene(pos.x(), pos.y(), 2, 2));
+ return d->scene->items(mapToScene(pos.x(), pos.y(), 1, 1));
}
QPainterPath path;
@@ -2466,10 +2248,11 @@ QPolygonF QGraphicsView::mapToScene(const QRect &rect) const
return QPolygonF();
QPointF scrollOffset(d->horizontalScroll(), d->verticalScroll());
- QPointF tl = scrollOffset + rect.topLeft();
- QPointF tr = scrollOffset + rect.topRight();
- QPointF br = scrollOffset + rect.bottomRight();
- QPointF bl = scrollOffset + rect.bottomLeft();
+ QRect r = rect.adjusted(0, 0, 1, 1);
+ QPointF tl = scrollOffset + r.topLeft();
+ QPointF tr = scrollOffset + r.topRight();
+ QPointF br = scrollOffset + r.bottomRight();
+ QPointF bl = scrollOffset + r.bottomLeft();
QPolygonF poly;
poly.resize(4);
@@ -2662,7 +2445,7 @@ void QGraphicsView::setBackgroundBrush(const QBrush &brush)
{
Q_D(QGraphicsView);
d->backgroundBrush = brush;
- viewport()->update();
+ d->updateAll();
if (d->cacheMode & CacheBackground) {
// Invalidate the background pixmap
@@ -2692,7 +2475,7 @@ void QGraphicsView::setForegroundBrush(const QBrush &brush)
{
Q_D(QGraphicsView);
d->foregroundBrush = brush;
- viewport()->update();
+ d->updateAll();
}
/*!
@@ -2713,9 +2496,11 @@ void QGraphicsView::updateScene(const QList<QRectF> &rects)
// Extract and reset dirty scene rect info.
QVector<QRect> dirtyViewportRects;
- for (int i = 0; i < d->dirtyRegions.size(); ++i)
- dirtyViewportRects += d->dirtyRegions.at(i).rects();
- d->dirtyRegions.clear();
+ const QVector<QRect> &dirtyRects = d->dirtyRegion.rects();
+ for (int i = 0; i < dirtyRects.size(); ++i)
+ dirtyViewportRects += dirtyRects.at(i);
+ d->dirtyRegion = QRegion();
+ d->dirtyBoundingRect = QRect();
bool fullUpdate = !d->accelerateScrolling || d->viewportUpdateMode == QGraphicsView::FullViewportUpdate;
bool boundingRectUpdate = (d->viewportUpdateMode == QGraphicsView::BoundingRectViewportUpdate)
@@ -2799,9 +2584,7 @@ void QGraphicsView::setupViewport(QWidget *widget)
const bool isGLWidget = widget->inherits("QGLWidget");
- d->accelerateScrolling = !(isGLWidget
- || widget->testAttribute(Qt::WA_MSWindowsUseDirect3D)
- || qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault));
+ d->accelerateScrolling = !(isGLWidget);
widget->setFocusPolicy(Qt::StrongFocus);
@@ -2810,7 +2593,12 @@ void QGraphicsView::setupViewport(QWidget *widget)
widget->setAutoFillBackground(true);
}
- widget->setMouseTracking(true);
+ // We are only interested in mouse tracking if items
+ // accept hover events or use non-default cursors.
+ if (d->scene && (!d->scene->d_func()->allItemsIgnoreHoverEvents
+ || !d->scene->d_func()->allItemsUseDefaultCursor)) {
+ widget->setMouseTracking(true);
+ }
widget->setAcceptDrops(acceptDrops());
}
@@ -2909,6 +2697,7 @@ bool QGraphicsView::viewportEvent(QEvent *event)
case QEvent::Paint:
// Reset full update
d->fullUpdatePending = false;
+ d->dirtyScrollOffset = QPoint();
if (d->scene) {
// Check if this view reimplements the updateScene slot; if it
// does, we can't do direct update delivery and have to fall back
@@ -3285,7 +3074,7 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
if (d->viewportUpdateMode != FullViewportUpdate)
viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
else
- viewport()->update();
+ d->updateAll();
}
// Stop rubber banding if the user has let go of all buttons (even
@@ -3307,7 +3096,7 @@ void QGraphicsView::mouseMoveEvent(QMouseEvent *event)
if (d->viewportUpdateMode != FullViewportUpdate)
viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
else
- viewport()->update();
+ d->updateAll();
}
// Set the new selection area
QPainterPath selectionArea;
@@ -3350,7 +3139,7 @@ void QGraphicsView::mouseReleaseEvent(QMouseEvent *event)
if (d->viewportUpdateMode != FullViewportUpdate)
viewport()->update(d->rubberBandRegion(viewport(), d->rubberBandRect));
else
- viewport()->update();
+ d->updateAll();
}
d->rubberBanding = false;
d->rubberBandRect = QRect();
@@ -3452,16 +3241,15 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
d->scene->d_func()->painterStateProtection = !(d->optimizationFlags & DontSavePainterState);
// Determine the exposed region
- QRegion exposedRegion = event->region();
+ d->exposedRegion = event->region();
if (!d->accelerateScrolling)
- exposedRegion = viewport()->rect();
+ d->exposedRegion = viewport()->rect();
else if (d->viewportUpdateMode == BoundingRectViewportUpdate)
- exposedRegion = event->rect();
- QRectF exposedSceneRect = mapToScene(exposedRegion.boundingRect().adjusted(0, 0, 1, 1)).boundingRect();
+ d->exposedRegion = event->rect();
+ QRectF exposedSceneRect = mapToScene(d->exposedRegion.boundingRect()).boundingRect();
// Set up the painter
QPainter painter(viewport());
- QTransform original = painter.worldTransform();
#ifndef QT_NO_RUBBERBAND
if (d->rubberBanding && !d->rubberBandRect.isEmpty())
painter.save();
@@ -3472,22 +3260,9 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Set up viewport transform
const QTransform viewTransform = viewportTransform();
- painter.setTransform(viewTransform, true);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- QTime stopWatch;
- stopWatch.start();
- qDebug() << "QGraphicsView::paintEvent(" << exposedRegion << ")";
-#endif
-
- // Find all exposed items
- bool allItems = false;
- QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int exposedTime = stopWatch.elapsed();
-#endif
+ painter.setWorldTransform(viewTransform);
+ // Draw background
if ((d->cacheMode & CacheBackground)
#ifdef Q_WS_X11
&& X11->use_xrender
@@ -3511,15 +3286,15 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
QPainter backgroundPainter(&d->backgroundPixmap);
backgroundPainter.setClipRegion(d->backgroundPixmapExposed, Qt::ReplaceClip);
backgroundPainter.setTransform(viewportTransform());
+ backgroundPainter.setCompositionMode(QPainter::CompositionMode_Source);
drawBackground(&backgroundPainter, exposedSceneRect);
d->backgroundPixmapExposed = QRegion();
}
// Blit the background from the background pixmap
- QTransform oldMatrix = painter.worldTransform();
- painter.setWorldTransform(original);
+ painter.setWorldTransform(QTransform());
painter.drawPixmap(QPoint(), d->backgroundPixmap);
- painter.setWorldTransform(oldMatrix);
+ painter.setWorldTransform(viewTransform);
} else {
if (!(d->optimizationFlags & DontSavePainterState))
painter.save();
@@ -3528,34 +3303,31 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.restore();
}
-#ifdef QGRAPHICSVIEW_DEBUG
- int backgroundTime = stopWatch.elapsed() - exposedTime;
-#endif
-
- // Generate the style options
- QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
- QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(itemList.size());
-
- d->generateStyleOptions(itemList, itemArray, styleOptionArray, viewTransform,
- allItems, exposedRegion);
-
// Items
- drawItems(&painter, itemList.size(), itemArray, styleOptionArray);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime;
-#endif
+ if (!(d->optimizationFlags & IndirectPainting)) {
+ d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, &d->exposedRegion,
+ viewport(), 0);
+ } else {
+ // Find all exposed items
+ bool allItems = false;
+ QList<QGraphicsItem *> itemList = d->findItems(d->exposedRegion, &allItems);
+
+ if (!itemList.isEmpty()) {
+ // Generate the style options.
+ const int numItems = itemList.size();
+ QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
+ QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, d->exposedRegion, allItems);
+ // Draw the items.
+ drawItems(&painter, numItems, itemArray, styleOptionArray);
+ d->freeStyleOptionsArray(styleOptionArray);
+ }
+ }
// Foreground
drawForeground(&painter, exposedSceneRect);
- delete [] itemArray;
- d->freeStyleOptionsArray(styleOptionArray);
-
-#ifdef QGRAPHICSVIEW_DEBUG
- int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;
-#endif
-
#ifndef QT_NO_RUBBERBAND
// Rubberband
if (d->rubberBanding && !d->rubberBandRect.isEmpty()) {
@@ -3577,17 +3349,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
painter.end();
-#ifdef QGRAPHICSVIEW_DEBUG
- qDebug() << "\tItem discovery....... " << exposedTime << "msecs (" << itemList.size() << "items,"
- << (exposedTime > 0 ? (itemList.size() * 1000.0 / exposedTime) : -1) << "/ sec )";
- qDebug() << "\tDrawing background... " << backgroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
- qDebug() << "\tDrawing items........ " << itemsTime << "msecs ("
- << (itemsTime > 0 ? (itemList.size() * 1000.0 / itemsTime) : -1) << "/ sec )";
- qDebug() << "\tDrawing foreground... " << foregroundTime << "msecs (" << exposedRegion.numRects() << "segments )";
- qDebug() << "\tTotal rendering time: " << stopWatch.elapsed() << "msecs ("
- << (stopWatch.elapsed() > 0 ? (1000.0 / stopWatch.elapsed()) : -1.0) << "fps )";
-#endif
-
// Restore painter state protection.
d->scene->d_func()->painterStateProtection = true;
}
@@ -3634,10 +3395,6 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
if (d->viewportUpdateMode != QGraphicsView::NoViewportUpdate) {
if (d->viewportUpdateMode != QGraphicsView::FullViewportUpdate) {
- for (int i = 0; i < d->dirtyRects.size(); ++i)
- d->dirtyRects[i].translate(dx, dy);
- for (int i = 0; i < d->dirtyRegions.size(); ++i)
- d->dirtyRegions[i].translate(dx, dy);
if (d->accelerateScrolling) {
#ifndef QT_NO_RUBBERBAND
// Update new and old rubberband regions
@@ -3647,12 +3404,15 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
viewport()->update(rubberBandRegion);
}
#endif
+ d->dirtyScrollOffset.rx() += dx;
+ d->dirtyScrollOffset.ry() += dy;
+ d->dirtyRegion.translate(dx, dy);
viewport()->scroll(dx, dy);
} else {
- viewport()->update();
+ d->updateAll();
}
} else {
- viewport()->update();
+ d->updateAll();
}
}
@@ -3663,31 +3423,14 @@ void QGraphicsView::scrollContentsBy(int dx, int dy)
&& X11->use_xrender
#endif
) {
- // Invalidate the background pixmap
- d->backgroundPixmapExposed.translate(dx, 0);
- if (dx > 0) {
- d->backgroundPixmapExposed += QRect(0, 0, dx, viewport()->height());
- } else if (dx < 0) {
- d->backgroundPixmapExposed += QRect(viewport()->width() + dx, 0,
- -dx, viewport()->height());
- }
- d->backgroundPixmapExposed.translate(0, dy);
- if (dy > 0) {
- d->backgroundPixmapExposed += QRect(0, 0, viewport()->width(), dy);
- } else if (dy < 0) {
- d->backgroundPixmapExposed += QRect(0, viewport()->height() + dy,
- viewport()->width(), -dy);
- }
-
// Scroll the background pixmap
- if (!d->backgroundPixmap.isNull()) {
- QPixmap tmp = d->backgroundPixmap.copy();
- QBrush bgBrush = viewport()->palette().brush(viewport()->backgroundRole());
- if (!bgBrush.isOpaque())
- d->backgroundPixmap.fill(Qt::transparent);
- QPainter painter(&d->backgroundPixmap);
- painter.drawPixmap(dx, dy, tmp);
- }
+ QRegion exposed;
+ if (!d->backgroundPixmap.isNull())
+ d->backgroundPixmap.scroll(dx, dy, d->backgroundPixmap.rect(), &exposed);
+
+ // Invalidate the background pixmap
+ d->backgroundPixmapExposed.translate(dx, dy);
+ d->backgroundPixmapExposed += exposed;
}
// Always replay on scroll.
@@ -3788,8 +3531,10 @@ void QGraphicsView::drawItems(QPainter *painter, int numItems,
const QStyleOptionGraphicsItem options[])
{
Q_D(QGraphicsView);
- if (d->scene)
- d->scene->drawItems(painter, numItems, items, options, viewport());
+ if (d->scene) {
+ QWidget *widget = painter->device() == viewport() ? viewport() : 0;
+ d->scene->drawItems(painter, numItems, items, options, widget);
+ }
}
/*!
@@ -3818,6 +3563,18 @@ QTransform QGraphicsView::viewportTransform() const
}
/*!
+ Returns true if the view is transformed (i.e., a non-identity transform
+ has been assigned, or the scrollbars are adjusted).
+
+ \sa setTransform(), horizontalScrollBar(), verticalScrollBar()
+*/
+bool QGraphicsView::isTransformed() const
+{
+ Q_D(const QGraphicsView);
+ return !d->identityMatrix || d->horizontalScroll() || d->verticalScroll();
+}
+
+/*!
Sets the view's current transformation matrix to \a matrix.
If \a combine is true, then \a matrix is combined with the current matrix;
@@ -3868,7 +3625,7 @@ void QGraphicsView::setTransform(const QTransform &matrix, bool combine )
d->transforming = false;
// Any matrix operation requires a full update.
- viewport()->update();
+ d->updateAll();
}
/*!
diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h
index e77e45c..387fa01 100644
--- a/src/gui/graphicsview/qgraphicsview.h
+++ b/src/gui/graphicsview/qgraphicsview.h
@@ -110,9 +110,10 @@ public:
};
enum OptimizationFlag {
- DontClipPainter = 0x1,
+ DontClipPainter = 0x1, // obsolete
DontSavePainterState = 0x2,
- DontAdjustForAntialiasing = 0x4
+ DontAdjustForAntialiasing = 0x4,
+ IndirectPainting = 0x8
};
Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag)
@@ -169,6 +170,7 @@ public:
void resetMatrix();
QTransform transform() const;
QTransform viewportTransform() const;
+ bool isTransformed() const;
void setTransform(const QTransform &matrix, bool combine = false);
void resetTransform();
void rotate(qreal angle);
@@ -273,7 +275,6 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_setViewportCursor(const QCursor &))
Q_PRIVATE_SLOT(d_func(), void _q_unsetViewportCursor())
#endif
- Q_PRIVATE_SLOT(d_func(), void _q_updateLaterSlot())
friend class QGraphicsSceneWidget;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index a76279e..a6f0d04 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -63,7 +63,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
+class QGraphicsViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QGraphicsView)
public:
@@ -94,6 +94,7 @@ public:
QPoint mousePressScreenPoint;
QPointF lastMouseMoveScenePoint;
QPoint lastMouseMoveScreenPoint;
+ QPoint dirtyScrollOffset;
Qt::MouseButton mousePressButton;
QTransform matrix;
bool identityMatrix;
@@ -159,28 +160,23 @@ public:
QRect mapToViewRect(const QGraphicsItem *item, const QRectF &rect) const;
QRegion mapToViewRegion(const QGraphicsItem *item, const QRectF &rect) const;
- void itemUpdated(QGraphicsItem *item, const QRectF &rect);
bool fullUpdatePending;
- QList<QRect> dirtyRects;
- QList<QRegion> dirtyRegions;
- int dirtyRectCount;
+ QRegion dirtyRegion;
QRect dirtyBoundingRect;
- void updateLater();
- bool updatingLater;
- void _q_updateLaterSlot();
- void updateAll();
+ void processPendingUpdates();
+ inline void updateAll()
+ {
+ viewport->update();
+ fullUpdatePending = true;
+ dirtyBoundingRect = QRect();
+ dirtyRegion = QRegion();
+ }
void updateRect(const QRect &rect);
void updateRegion(const QRegion &region);
bool updateSceneSlotReimplementedChecked;
+ QRegion exposedRegion;
QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
-
- void generateStyleOptions(const QList<QGraphicsItem *> &itemList,
- QGraphicsItem **itemArray,
- QStyleOptionGraphicsItem *styleOptionArray,
- const QTransform &worldTransform,
- bool allItems,
- const QRegion &exposedRegion) const;
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index aa2b9bf..4e4944c 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -170,46 +170,13 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \property QGraphicsWidget::enabled
- \brief whether the item is enabled or not
-
- This property is declared in QGraphicsItem.
-
- By default, this property is true.
-
- \sa QGraphicsItem::isEnabled(), QGraphicsItem::setEnabled()
-*/
-
-/*!
- \property QGraphicsWidget::visible
- \brief whether the item is visible or not
-
- This property is declared in QGraphicsItem.
-
- By default, this property is true.
-
- \sa QGraphicsItem::isVisible(), QGraphicsItem::setVisible(), show(),
- hide()
-*/
-
-/*!
- \property QGraphicsWidget::opacity
- \brief the opacity of the widget
-*/
-
-/*!
- \property QGraphicsWidget::pos
- \brief the position of the widget
-*/
-
-/*!
Constructs a QGraphicsWidget instance. The optional \a parent argument is
passed to QGraphicsItem's constructor. The optional \a wFlags argument
specifies the widget's window flags (e.g., whether the widget should be a
window, a tool, a popup, etc).
*/
QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
- : QGraphicsItem(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)
+ : QGraphicsObject(*new QGraphicsWidgetPrivate, 0, 0), QGraphicsLayoutItem(0, false)
{
Q_D(QGraphicsWidget);
d->init(parent, wFlags);
@@ -221,7 +188,7 @@ QGraphicsWidget::QGraphicsWidget(QGraphicsItem *parent, Qt::WindowFlags wFlags)
Constructs a new QGraphicsWidget, using \a dd as parent.
*/
QGraphicsWidget::QGraphicsWidget(QGraphicsWidgetPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene, Qt::WindowFlags wFlags)
- : QGraphicsItem(dd, 0, scene), QGraphicsLayoutItem(0, false)
+ : QGraphicsObject(dd, 0, scene), QGraphicsLayoutItem(0, false)
{
Q_D(QGraphicsWidget);
d->init(parent, wFlags);
@@ -459,17 +426,19 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre
{
Q_D(QGraphicsWidget);
- if (left == d->leftMargin
- && top == d->topMargin
- && right == d->rightMargin
- && bottom == d->bottomMargin) {
+ if (!d->margins && left == 0 && top == 0 && right == 0 && bottom == 0)
+ return;
+ d->ensureMargins();
+ if (left == d->margins[d->Left]
+ && top == d->margins[d->Top]
+ && right == d->margins[d->Right]
+ && bottom == d->margins[d->Bottom])
return;
- }
- d->leftMargin = left;
- d->topMargin = top;
- d->rightMargin = right;
- d->bottomMargin = bottom;
+ d->margins[d->Left] = left;
+ d->margins[d->Top] = top;
+ d->margins[d->Right] = right;
+ d->margins[d->Bottom] = bottom;
if (QGraphicsLayout *l = d->layout)
l->invalidate();
@@ -490,14 +459,16 @@ void QGraphicsWidget::setContentsMargins(qreal left, qreal top, qreal right, qre
void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
Q_D(const QGraphicsWidget);
+ if (left || top || right || bottom)
+ d->ensureMargins();
if (left)
- *left = d->leftMargin;
+ *left = d->margins[d->Left];
if (top)
- *top = d->topMargin;
+ *top = d->margins[d->Top];
if (right)
- *right = d->rightMargin;
+ *right = d->margins[d->Right];
if (bottom)
- *bottom = d->bottomMargin;
+ *bottom = d->margins[d->Bottom];
}
/*!
@@ -513,16 +484,23 @@ void QGraphicsWidget::getContentsMargins(qreal *left, qreal *top, qreal *right,
void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right, qreal bottom)
{
Q_D(QGraphicsWidget);
- bool unchanged = left == d->leftWindowFrameMargin && top == d->topWindowFrameMargin
- && right == d->rightWindowFrameMargin && bottom == d->bottomWindowFrameMargin;
+
+ if (!d->windowFrameMargins && left == 0 && top == 0 && right == 0 && bottom == 0)
+ return;
+ d->ensureWindowFrameMargins();
+ bool unchanged =
+ d->windowFrameMargins[d->Left] == left
+ && d->windowFrameMargins[d->Top] == top
+ && d->windowFrameMargins[d->Right] == right
+ && d->windowFrameMargins[d->Bottom] == bottom;
if (d->setWindowFrameMargins && unchanged)
return;
if (!unchanged)
prepareGeometryChange();
- d->leftWindowFrameMargin = left;
- d->topWindowFrameMargin = top;
- d->rightWindowFrameMargin = right;
- d->bottomWindowFrameMargin = bottom;
+ d->windowFrameMargins[d->Left] = left;
+ d->windowFrameMargins[d->Top] = top;
+ d->windowFrameMargins[d->Right] = right;
+ d->windowFrameMargins[d->Bottom] = bottom;
d->setWindowFrameMargins = true;
}
@@ -536,14 +514,16 @@ void QGraphicsWidget::setWindowFrameMargins(qreal left, qreal top, qreal right,
void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
{
Q_D(const QGraphicsWidget);
+ if (left || top || right || bottom)
+ d->ensureWindowFrameMargins();
if (left)
- *left = d->leftWindowFrameMargin;
+ *left = d->windowFrameMargins[d->Left];
if (top)
- *top = d->topWindowFrameMargin;
+ *top = d->windowFrameMargins[d->Top];
if (right)
- *right = d->rightWindowFrameMargin;
+ *right = d->windowFrameMargins[d->Right];
if (bottom)
- *bottom = d->bottomWindowFrameMargin;
+ *bottom = d->windowFrameMargins[d->Bottom];
}
/*!
@@ -577,8 +557,10 @@ void QGraphicsWidget::unsetWindowFrameMargins()
QRectF QGraphicsWidget::windowFrameGeometry() const
{
Q_D(const QGraphicsWidget);
- return geometry().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin,
- d->rightWindowFrameMargin, d->bottomWindowFrameMargin);
+ return d->windowFrameMargins
+ ? geometry().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
+ d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
+ : geometry();
}
/*!
@@ -589,8 +571,10 @@ QRectF QGraphicsWidget::windowFrameGeometry() const
QRectF QGraphicsWidget::windowFrameRect() const
{
Q_D(const QGraphicsWidget);
- return rect().adjusted(-d->leftWindowFrameMargin, -d->topWindowFrameMargin,
- d->rightWindowFrameMargin, d->bottomWindowFrameMargin);
+ return d->windowFrameMargins
+ ? rect().adjusted(-d->windowFrameMargins[d->Left], -d->windowFrameMargins[d->Top],
+ d->windowFrameMargins[d->Right], d->windowFrameMargins[d->Bottom])
+ : rect();
}
/*!
@@ -699,7 +683,10 @@ QSizeF QGraphicsWidget::sizeHint(Qt::SizeHint which, const QSizeF &constraint) c
QSizeF sh;
if (d->layout) {
sh = d->layout->effectiveSizeHint(which, constraint);
- sh += QSizeF(d->leftMargin + d->rightMargin, d->topMargin + d->bottomMargin);
+ if (d->margins) {
+ sh += QSizeF(d->margins[d->Left] + d->margins[d->Right],
+ d->margins[d->Top] + d->margins[d->Bottom]);
+ }
} else {
switch (which) {
case Qt::MinimumSize:
@@ -989,6 +976,9 @@ void QGraphicsWidget::updateGeometry()
ItemParentChange both to deliver \l ParentChange events, and for managing
the focus chain.
+ QGraphicsWidget enables the ItemSendsGeometryChanges flag by default in
+ order to track position changes.
+
\sa propertyChange()
*/
QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &value)
@@ -1039,10 +1029,6 @@ QVariant QGraphicsWidget::itemChange(GraphicsItemChange change, const QVariant &
break;
}
case ItemParentHasChanged: {
- // reset window type on parent change in order to automagically remove decorations etc.
- Qt::WindowFlags wflags = d->windowFlags & ~Qt::WindowType_Mask;
- d->adjustWindowFlags(&wflags);
- setWindowFlags(wflags);
// Deliver ParentChange.
QEvent event(QEvent::ParentChange);
QApplication::sendEvent(this, &event);
@@ -1131,7 +1117,8 @@ bool QGraphicsWidget::windowFrameEvent(QEvent *event)
d->windowFrameMousePressEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
break;
case QEvent::GraphicsSceneMouseMove:
- if (d->grabbedSection != Qt::NoSection) {
+ d->ensureWindowData();
+ if (d->windowData->grabbedSection != Qt::NoSection) {
d->windowFrameMouseMoveEvent(static_cast<QGraphicsSceneMouseEvent *>(event));
event->accept();
}
@@ -1186,7 +1173,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
const qreal cornerMargin = 20;
//### Not sure of this one, it should be the same value for all edges.
- const qreal windowFrameWidth = d->leftWindowFrameMargin;
+ const qreal windowFrameWidth = d->windowFrameMargins
+ ? d->windowFrameMargins[d->Left] : 0;
Qt::WindowFrameSection s = Qt::NoSection;
if (x <= left + cornerMargin) {
@@ -1212,7 +1200,8 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
}
if (s == Qt::NoSection) {
QRectF r1 = r;
- r1.setHeight(d->topWindowFrameMargin);
+ r1.setHeight(d->windowFrameMargins
+ ? d->windowFrameMargins[d->Top] : 0);
if (r1.contains(pos))
s = Qt::TitleBarArea;
}
@@ -1320,7 +1309,8 @@ bool QGraphicsWidget::event(QEvent *event)
case QEvent::GraphicsSceneMouseMove:
case QEvent::GraphicsSceneMouseRelease:
case QEvent::GraphicsSceneMouseDoubleClick:
- if (d->hasDecoration() && d->grabbedSection != Qt::NoSection)
+ d->ensureWindowData();
+ if (d->hasDecoration() && d->windowData->grabbedSection != Qt::NoSection)
return windowFrameEvent(event);
break;
case QEvent::GraphicsSceneHoverEnter:
@@ -1623,6 +1613,7 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
return;
bool wasPopup = (d->windowFlags & Qt::WindowType_Mask) == Qt::Popup;
+ d->adjustWindowFlags(&wFlags);
d->windowFlags = wFlags;
if (!d->setWindowFrameMargins)
unsetWindowFrameMargins();
@@ -1635,6 +1626,11 @@ void QGraphicsWidget::setWindowFlags(Qt::WindowFlags wFlags)
else
d->scene->d_func()->addPopup(this);
}
+
+ if (d->scene && d->scene->d_func()->allItemsIgnoreHoverEvents && d->hasDecoration()) {
+ d->scene->d_func()->allItemsIgnoreHoverEvents = false;
+ d->scene->d_func()->enableMouseTrackingOnViews();
+ }
}
/*!
@@ -1662,17 +1658,19 @@ bool QGraphicsWidget::isActiveWindow() const
This property is only used for windows.
- By default, if no title has been set, this property contains an empty string.
+ By default, if no title has been set, this property contains an
+ empty string.
*/
void QGraphicsWidget::setWindowTitle(const QString &title)
{
Q_D(QGraphicsWidget);
- d->windowTitle = title;
+ d->ensureWindowData();
+ d->windowData->windowTitle = title;
}
QString QGraphicsWidget::windowTitle() const
{
Q_D(const QGraphicsWidget);
- return d->windowTitle;
+ return d->windowData ? d->windowData->windowTitle : QString();
}
/*!
@@ -1724,6 +1722,38 @@ QGraphicsWidget *QGraphicsWidget::focusWidget() const
return d->focusChild;
}
+/*! \property QGraphicsWidget::horizontalShear
+ \brief This property holds the horizontal shear value for the item.
+ */
+
+/*! \property QGraphicsWidget::transformOrigin
+ \brief This property holds the origin point used for transformations
+ in item coordinates.
+ */
+
+/*! \property QGraphicsWidget::verticalShear
+ \brief This property holds the vertical shear value for the item.
+ */
+
+/*! \property QGraphicsWidget::xRotation
+ \brief This property holds the value for rotation around the x axis.
+ */
+
+/*! \property QGraphicsWidget::xScale
+ \brief This property holds the scale factor for the x axis.
+ */
+
+/*! \property QGraphicsWidget::yRotation
+ \brief This property holds the value for rotation around the y axis.
+ */
+
+/*! \property QGraphicsWidget::yScale
+ \brief This property holds the scale factor for the y axis.
+ */
+
+/*! \property QGraphicsWidget::zRotation
+ \brief This property holds the value for rotation around the z axis.
+ */
#ifndef QT_NO_SHORTCUT
/*!
@@ -2110,11 +2140,12 @@ void QGraphicsWidget::paintWindowFrame(QPainter *painter, const QStyleOptionGrap
QStyleOptionTitleBar bar;
bar.QStyleOption::operator=(*option);
d->initStyleOptionTitleBar(&bar); // this clear flags in bar.state
- if (d->buttonMouseOver)
+ d->ensureWindowData();
+ if (d->windowData->buttonMouseOver)
bar.state |= QStyle::State_MouseOver;
else
bar.state &= ~QStyle::State_MouseOver;
- if (d->buttonSunken)
+ if (d->windowData->buttonSunken)
bar.state |= QStyle::State_Sunken;
else
bar.state &= ~QStyle::State_Sunken;
@@ -2269,7 +2300,7 @@ void QGraphicsWidget::dumpFocusChain()
qWarning("Found a focus chain that is not circular, (next == 0)");
break;
}
- qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? "1" : "0") << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);
+ qDebug() << i++ << QString::number(uint(next), 16) << next->className() << next->data(0) << QString::fromAscii("focusItem:%1").arg(next->hasFocus() ? '1' : '0') << QLatin1String("next:") << next->d_func()->focusNext->data(0) << QLatin1String("prev:") << next->d_func()->focusPrev->data(0);
if (visited.contains(next)) {
qWarning("Already visited this node. However, I expected to dump until I found myself.");
break;
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 49de542..0563dcb 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -66,7 +66,7 @@ class QStyleOption;
class QGraphicsWidgetPrivate;
-class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, public QGraphicsLayoutItem
+class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLayoutItem
{
Q_OBJECT
Q_PROPERTY(QPalette palette READ palette WRITE setPalette)
@@ -74,14 +74,17 @@ class Q_GUI_EXPORT QGraphicsWidget : public QObject, public QGraphicsItem, publi
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection)
Q_PROPERTY(QSizeF size READ size WRITE resize)
Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy)
- Q_PROPERTY(bool enabled READ isEnabled WRITE setEnabled)
- Q_PROPERTY(bool visible READ isVisible WRITE setVisible)
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
- Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity)
- Q_PROPERTY(QPointF pos READ pos WRITE setPos)
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry)
-
+ Q_PROPERTY(QPointF transformOrigin READ transformOrigin WRITE setTransformOrigin)
+ Q_PROPERTY(qreal xRotation READ xRotation WRITE setXRotation)
+ Q_PROPERTY(qreal yRotation READ yRotation WRITE setYRotation)
+ Q_PROPERTY(qreal zRotation READ zRotation WRITE setZRotation)
+ Q_PROPERTY(qreal xScale READ xScale WRITE setXScale)
+ Q_PROPERTY(qreal yScale READ yScale WRITE setYScale)
+ Q_PROPERTY(qreal horizontalShear READ horizontalShear WRITE setHorizontalShear)
+ Q_PROPERTY(qreal verticalShear READ verticalShear WRITE setVerticalShear)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
~QGraphicsWidget();
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 789f8da..557b883 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -66,17 +66,20 @@ void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFl
isWidget = 1; // QGraphicsItem::isWidget() returns true.
focusNext = focusPrev = q;
focusPolicy = Qt::NoFocus;
+
+ adjustWindowFlags(&wFlags);
+ windowFlags = wFlags;
+
q->setParentItem(parentItem);
q->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred, QSizePolicy::DefaultType));
q->setGraphicsItem(q);
resolveLayoutDirection();
-
- if (!parentItem)
- adjustWindowFlags(&wFlags);
- windowFlags = wFlags;
q->unsetWindowFrameMargins();
+ q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
+ q->setFlag(QGraphicsItem::ItemSendsGeometryChanges);
}
+
qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
Q_Q(const QGraphicsWidget);
@@ -89,56 +92,57 @@ qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options
return (qreal)height;
}
-void QGraphicsWidgetPrivate::getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const
+/*!
+ \internal
+*/
+QGraphicsWidgetPrivate::~QGraphicsWidgetPrivate()
{
- if (left)
- *left = leftLayoutItemMargin;
- if (top)
- *top = topLayoutItemMargin;
- if (right)
- *right = rightLayoutItemMargin;
- if (bottom)
- *bottom = bottomLayoutItemMargin;
+ // Remove any lazily allocated data
+ delete[] margins;
+ delete[] windowFrameMargins;
+ delete windowData;
}
-void QGraphicsWidgetPrivate::setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom)
-{
- if (leftLayoutItemMargin == left
- && topLayoutItemMargin == top
- && rightLayoutItemMargin == right
- && bottomLayoutItemMargin == bottom)
- return;
+/*!
+ \internal
- Q_Q(QGraphicsWidget);
- leftLayoutItemMargin = left;
- topLayoutItemMargin = top;
- rightLayoutItemMargin = right;
- bottomLayoutItemMargin = bottom;
- q->updateGeometry();
+ Ensures that margins is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureMargins() const
+{
+ if (!margins) {
+ margins = new qreal[4];
+ for (int i = 0; i < 4; ++i)
+ margins[i] = 0;
+ }
}
-void QGraphicsWidgetPrivate::setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt)
+/*!
+ \internal
+
+ Ensures that windowFrameMargins is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureWindowFrameMargins() const
{
- Q_Q(QGraphicsWidget);
- QStyleOption myOpt;
- if (!opt) {
- q->initStyleOption(&myOpt);
- myOpt.rect.setRect(0, 0, 32768, 32768); // arbitrary
- opt = &myOpt;
+ if (!windowFrameMargins) {
+ windowFrameMargins = new qreal[4];
+ for (int i = 0; i < 4; ++i)
+ windowFrameMargins[i] = 0;
}
+}
- QRect liRect = q->style()->subElementRect(element, opt, /* q */ 0);
- if (liRect.isValid()) {
- leftLayoutItemMargin = (opt->rect.left() - liRect.left());
- topLayoutItemMargin = (opt->rect.top() - liRect.top());
- rightLayoutItemMargin = (liRect.right() - opt->rect.right());
- bottomLayoutItemMargin = (liRect.bottom() - opt->rect.bottom());
- } else {
- leftLayoutItemMargin = 0;
- topLayoutItemMargin = 0;
- rightLayoutItemMargin = 0;
- bottomLayoutItemMargin = 0;
- }
+/*!
+ \internal
+
+ Ensures that windowData is allocated.
+ This function must be called before any dereferencing.
+*/
+void QGraphicsWidgetPrivate::ensureWindowData()
+{
+ if (!windowData)
+ windowData = new WindowData;
}
void QGraphicsWidgetPrivate::setPalette_helper(const QPalette &palette)
@@ -297,11 +301,12 @@ QFont QGraphicsWidgetPrivate::naturalWidgetFont() const
void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *option)
{
Q_Q(QGraphicsWidget);
+ ensureWindowData();
q->initStyleOption(option);
option->rect.setHeight(titleBarHeight(*option));
option->titleBarFlags = windowFlags;
option->subControls = QStyle::SC_TitleBarCloseButton | QStyle::SC_TitleBarLabel | QStyle::SC_TitleBarSysMenu;
- option->activeSubControls = hoveredSubControl;
+ option->activeSubControls = windowData->hoveredSubControl;
bool isActive = q->isActiveWindow();
if (isActive) {
option->state |= QStyle::State_Active;
@@ -313,7 +318,8 @@ void QGraphicsWidgetPrivate::initStyleOptionTitleBar(QStyleOptionTitleBar *optio
}
QFont windowTitleFont = QApplication::font("QWorkspaceTitleBar");
QRect textRect = q->style()->subControlRect(QStyle::CC_TitleBar, option, QStyle::SC_TitleBarLabel, 0);
- option->text = QFontMetrics(windowTitleFont).elidedText(windowTitle, Qt::ElideRight, textRect.width());
+ option->text = QFontMetrics(windowTitleFont).elidedText(
+ windowData->windowTitle, Qt::ElideRight, textRect.width());
}
void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
@@ -341,9 +347,10 @@ void QGraphicsWidgetPrivate::adjustWindowFlags(Qt::WindowFlags *flags)
void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{
Q_Q(QGraphicsWidget);
- if (grabbedSection != Qt::NoSection) {
- if (grabbedSection == Qt::TitleBarArea) {
- buttonSunken = false;
+ ensureWindowData();
+ if (windowData->grabbedSection != Qt::NoSection) {
+ if (windowData->grabbedSection == Qt::TitleBarArea) {
+ windowData->buttonSunken = false;
QStyleOptionTitleBar bar;
initStyleOptionTitleBar(&bar);
// make sure that the coordinates (rect and pos) we send to the style are positive.
@@ -351,8 +358,10 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve
bar.rect.moveTo(0,0);
bar.rect.setHeight(q->style()->pixelMetric(QStyle::PM_TitleBarHeight, &bar));
QPointF pos = event->pos();
- pos.rx() += leftWindowFrameMargin;
- pos.ry() += topWindowFrameMargin;
+ if (windowFrameMargins) {
+ pos.rx() += windowFrameMargins[Left];
+ pos.ry() += windowFrameMargins[Top];
+ }
bar.subControls = QStyle::SC_TitleBarCloseButton;
if (q->style()->subControlRect(QStyle::CC_TitleBar, &bar,
QStyle::SC_TitleBarCloseButton,
@@ -361,7 +370,7 @@ void QGraphicsWidgetPrivate::windowFrameMouseReleaseEvent(QGraphicsSceneMouseEve
}
}
if (!(static_cast<QGraphicsSceneMouseEvent *>(event)->buttons()))
- grabbedSection = Qt::NoSection;
+ windowData->grabbedSection = Qt::NoSection;
event->accept();
}
}
@@ -372,35 +381,16 @@ void QGraphicsWidgetPrivate::windowFrameMousePressEvent(QGraphicsSceneMouseEvent
if (event->button() != Qt::LeftButton)
return;
- startGeometry = q->geometry();
- grabbedSection = q->windowFrameSectionAt(event->pos());
- switch (grabbedSection) {
- case Qt::LeftSection:
- case Qt::TopLeftSection:
- mouseDelta = event->pos() - q->rect().topLeft();
- break;
- case Qt::TopSection:
- case Qt::TopRightSection:
- mouseDelta = event->pos() - q->rect().topRight();
- break;
- case Qt::RightSection:
- case Qt::BottomRightSection:
- mouseDelta = event->pos() - q->rect().bottomRight();
- break;
- case Qt::BottomSection:
- case Qt::BottomLeftSection:
- mouseDelta = event->pos() - q->rect().bottomLeft();
- break;
- case Qt::TitleBarArea:
- if (hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
- buttonSunken = true;
- q->update();
- }
- break;
- case Qt::NoSection:
- break;
+ ensureWindowData();
+ windowData->startGeometry = q->geometry();
+ windowData->grabbedSection = q->windowFrameSectionAt(event->pos());
+ ensureWindowData();
+ if (windowData->grabbedSection == Qt::TitleBarArea
+ && windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton) {
+ windowData->buttonSunken = true;
+ q->update();
}
- event->setAccepted(grabbedSection != Qt::NoSection);
+ event->setAccepted(windowData->grabbedSection != Qt::NoSection);
}
static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
@@ -455,7 +445,8 @@ static void _q_boundGeometryToSizeConstraints(const QRectF &startGeometry,
void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Q_Q(QGraphicsWidget);
- if (!(event->buttons() & Qt::LeftButton) || hoveredSubControl != QStyle::SC_TitleBarLabel)
+ ensureWindowData();
+ if (!(event->buttons() & Qt::LeftButton) || windowData->hoveredSubControl != QStyle::SC_TitleBarLabel)
return;
QLineF delta(q->mapFromScene(event->buttonDownScenePos(Qt::LeftButton)), event->pos());
@@ -464,49 +455,56 @@ void QGraphicsWidgetPrivate::windowFrameMouseMoveEvent(QGraphicsSceneMouseEvent
QLineF parentYDelta(q->mapToParent(QPointF(0, delta.p1().y())), q->mapToParent(QPointF(0, delta.p2().y())));
QRectF newGeometry;
- switch (grabbedSection) {
+ switch (windowData->grabbedSection) {
case Qt::LeftSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()),
- startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentXDelta.dx(), parentXDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
break;
case Qt::TopLeftSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()),
- startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentDelta.dx(), parentDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(delta.dx(), delta.dy()));
break;
case Qt::TopSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()),
- startGeometry.size() - QSizeF(0, delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentYDelta.dx(), parentYDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(0, delta.dy()));
break;
case Qt::TopRightSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentYDelta.dx(), parentYDelta.dy()),
- startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentYDelta.dx(), parentYDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(-delta.dx(), delta.dy()));
break;
case Qt::RightSection:
- newGeometry = QRectF(startGeometry.topLeft(),
- startGeometry.size() + QSizeF(delta.dx(), 0));
+ newGeometry = QRectF(windowData->startGeometry.topLeft(),
+ windowData->startGeometry.size() + QSizeF(delta.dx(), 0));
break;
case Qt::BottomRightSection:
- newGeometry = QRectF(startGeometry.topLeft(),
- startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft(),
+ windowData->startGeometry.size() + QSizeF(delta.dx(), delta.dy()));
break;
case Qt::BottomSection:
- newGeometry = QRectF(startGeometry.topLeft(),
- startGeometry.size() + QSizeF(0, delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft(),
+ windowData->startGeometry.size() + QSizeF(0, delta.dy()));
break;
case Qt::BottomLeftSection:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentXDelta.dx(), parentXDelta.dy()),
- startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentXDelta.dx(), parentXDelta.dy()),
+ windowData->startGeometry.size() - QSizeF(delta.dx(), -delta.dy()));
break;
case Qt::TitleBarArea:
- newGeometry = QRectF(startGeometry.topLeft() + QPointF(parentDelta.dx(), parentDelta.dy()),
- startGeometry.size());
+ newGeometry = QRectF(windowData->startGeometry.topLeft()
+ + QPointF(parentDelta.dx(), parentDelta.dy()),
+ windowData->startGeometry.size());
break;
case Qt::NoSection:
break;
}
- if (grabbedSection != Qt::NoSection) {
- _q_boundGeometryToSizeConstraints(startGeometry, &newGeometry, grabbedSection,
+ if (windowData->grabbedSection != Qt::NoSection) {
+ _q_boundGeometryToSizeConstraints(windowData->startGeometry, &newGeometry,
+ windowData->grabbedSection,
q->effectiveSizeHint(Qt::MinimumSize),
q->effectiveSizeHint(Qt::MaximumSize));
q->setGeometry(newGeometry);
@@ -519,21 +517,25 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
if (!hasDecoration())
return;
+ ensureWindowData();
+
if (q->rect().contains(event->pos())) {
- if (buttonMouseOver || hoveredSubControl != QStyle::SC_None)
+ if (windowData->buttonMouseOver || windowData->hoveredSubControl != QStyle::SC_None)
windowFrameHoverLeaveEvent(event);
return;
}
- bool wasMouseOver = buttonMouseOver;
- QRect oldButtonRect = buttonRect;
- buttonRect = QRect();
- buttonMouseOver = false;
+ bool wasMouseOver = windowData->buttonMouseOver;
+ QRect oldButtonRect = windowData->buttonRect;
+ windowData->buttonRect = QRect();
+ windowData->buttonMouseOver = false;
QPointF pos = event->pos();
QStyleOptionTitleBar bar;
// make sure that the coordinates (rect and pos) we send to the style are positive.
- pos.rx() += leftWindowFrameMargin;
- pos.ry() += topWindowFrameMargin;
+ if (windowFrameMargins) {
+ pos.rx() += windowFrameMargins[Left];
+ pos.ry() += windowFrameMargins[Top];
+ }
initStyleOptionTitleBar(&bar);
bar.rect = q->windowFrameRect().toRect();
bar.rect.moveTo(0,0);
@@ -559,14 +561,17 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
cursorShape = Qt::SizeVerCursor;
break;
case Qt::TitleBarArea:
- buttonRect = q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
+ windowData->buttonRect = q->style()->subControlRect(
+ QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarCloseButton, 0);
#ifdef Q_WS_MAC
// On mac we should hover if we are in the 'area' of the buttons
- buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
- buttonRect |= q->style()->subControlRect(QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
+ windowData->buttonRect |= q->style()->subControlRect(
+ QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMinButton, 0);
+ windowData->buttonRect |= q->style()->subControlRect(
+ QStyle::CC_TitleBar, &bar, QStyle::SC_TitleBarMaxButton, 0);
#endif
- if (buttonRect.contains(pos.toPoint()))
- buttonMouseOver = true;
+ if (windowData->buttonRect.contains(pos.toPoint()))
+ windowData->buttonMouseOver = true;
event->ignore();
break;
default:
@@ -578,15 +583,15 @@ void QGraphicsWidgetPrivate::windowFrameHoverMoveEvent(QGraphicsSceneHoverEvent
q->setCursor(cursorShape);
#endif
// update buttons if we hover over them
- hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
- if (hoveredSubControl != QStyle::SC_TitleBarCloseButton)
- hoveredSubControl = QStyle::SC_TitleBarLabel;
+ windowData->hoveredSubControl = q->style()->hitTestComplexControl(QStyle::CC_TitleBar, &bar, pos.toPoint(), 0);
+ if (windowData->hoveredSubControl != QStyle::SC_TitleBarCloseButton)
+ windowData->hoveredSubControl = QStyle::SC_TitleBarLabel;
- if (buttonMouseOver != wasMouseOver) {
+ if (windowData->buttonMouseOver != wasMouseOver) {
if (!oldButtonRect.isNull())
q->update(QRectF(oldButtonRect).translated(q->windowFrameRect().topLeft()));
- if (!buttonRect.isNull())
- q->update(QRectF(buttonRect).translated(q->windowFrameRect().topLeft()));
+ if (!windowData->buttonRect.isNull())
+ q->update(QRectF(windowData->buttonRect).translated(q->windowFrameRect().topLeft()));
}
}
@@ -600,16 +605,19 @@ void QGraphicsWidgetPrivate::windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent
q->unsetCursor();
#endif
+ ensureWindowData();
+
bool needsUpdate = false;
- if (hoveredSubControl == QStyle::SC_TitleBarCloseButton || buttonMouseOver)
+ if (windowData->hoveredSubControl == QStyle::SC_TitleBarCloseButton
+ || windowData->buttonMouseOver)
needsUpdate = true;
// update the hover state (of buttons etc...)
- hoveredSubControl = QStyle::SC_None;
- buttonMouseOver = false;
- buttonRect = QRect();
+ windowData->hoveredSubControl = QStyle::SC_None;
+ windowData->buttonMouseOver = false;
+ windowData->buttonRect = QRect();
if (needsUpdate)
- q->update(buttonRect);
+ q->update(windowData->buttonRect);
}
}
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 53eaa31..f4cdeca 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -68,19 +68,12 @@ class QStyleOptionTitleBar;
#if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW
-class Q_GUI_EXPORT QGraphicsWidgetPrivate : public QGraphicsItemPrivate
+class QGraphicsWidgetPrivate : public QGraphicsItemPrivate
{
Q_DECLARE_PUBLIC(QGraphicsWidget)
public:
QGraphicsWidgetPrivate()
- : leftMargin(0),
- topMargin(0),
- rightMargin(0),
- bottomMargin(0),
- leftLayoutItemMargin(0),
- topLayoutItemMargin(0),
- rightLayoutItemMargin(0),
- bottomLayoutItemMargin(0),
+ : margins(0),
layout(0),
inheritedPaletteResolveMask(0),
inheritedFontResolveMask(0),
@@ -92,40 +85,23 @@ public:
focusPrev(0),
focusChild(0),
windowFlags(0),
- hoveredSubControl(QStyle::SC_None),
- grabbedSection(Qt::NoSection),
- buttonMouseOver(false),
- buttonSunken(false),
+ windowData(0),
setWindowFrameMargins(false),
- leftWindowFrameMargin(0),
- topWindowFrameMargin(0),
- rightWindowFrameMargin(0),
- bottomWindowFrameMargin(0)
+ windowFrameMargins(0)
{ }
+ virtual ~QGraphicsWidgetPrivate();
void init(QGraphicsItem *parentItem, Qt::WindowFlags wFlags);
qreal titleBarHeight(const QStyleOptionTitleBar &options) const;
// Margins
- qreal leftMargin;
- qreal topMargin;
- qreal rightMargin;
- qreal bottomMargin;
- QRectF contentsRect;
-
- // Layout item margins
- void getLayoutItemMargins(qreal *left, qreal *top, qreal *right, qreal *bottom) const;
- void setLayoutItemMargins(qreal left, qreal top, qreal right, qreal bottom);
- void setLayoutItemMargins(QStyle::SubElement element, const QStyleOption *opt = 0);
+ enum {Left, Top, Right, Bottom};
+ mutable qreal *margins;
+ void ensureMargins() const;
void fixFocusChainBeforeReparenting(QGraphicsWidget *newParent, QGraphicsScene *newScene = 0);
void setLayout_helper(QGraphicsLayout *l);
- qreal leftLayoutItemMargin;
- qreal topLayoutItemMargin;
- qreal rightLayoutItemMargin;
- qreal bottomLayoutItemMargin;
-
// Layouts
QGraphicsLayout *layout;
void setLayoutDirection_helper(Qt::LayoutDirection direction);
@@ -208,20 +184,26 @@ public:
// Windows
Qt::WindowFlags windowFlags;
- QString windowTitle;
- QStyle::SubControl hoveredSubControl;
- Qt::WindowFrameSection grabbedSection;
- uint buttonMouseOver : 1;
- uint buttonSunken : 1;
- QPointF mouseDelta; // to compensate for small error when interactively resizing
- QRectF startGeometry;
- QRect buttonRect;
+ struct WindowData {
+ QString windowTitle;
+ QStyle::SubControl hoveredSubControl;
+ Qt::WindowFrameSection grabbedSection;
+ uint buttonMouseOver : 1;
+ uint buttonSunken : 1;
+ QRectF startGeometry;
+ QRect buttonRect;
+ WindowData()
+ : hoveredSubControl(QStyle::SC_None)
+ , grabbedSection(Qt::NoSection)
+ , buttonMouseOver(false)
+ , buttonSunken(false)
+ {}
+ } *windowData;
+ void ensureWindowData();
bool setWindowFrameMargins;
- qreal leftWindowFrameMargin;
- qreal topWindowFrameMargin;
- qreal rightWindowFrameMargin;
- qreal bottomWindowFrameMargin;
+ mutable qreal *windowFrameMargins;
+ void ensureWindowFrameMargins() const;
#ifndef QT_NO_ACTION
QList<QAction *> actions;
diff --git a/src/gui/graphicsview/qgridlayoutengine.cpp b/src/gui/graphicsview/qgridlayoutengine.cpp
index dc5ca21..88712c2 100644
--- a/src/gui/graphicsview/qgridlayoutengine.cpp
+++ b/src/gui/graphicsview/qgridlayoutengine.cpp
@@ -275,7 +275,7 @@ void QGridLayoutRowData::calculateGeometries(int start, int end, qreal targetSiz
if (hasIgnoreFlag) {
factors[i] = (stretch < 0) ? 1.0 : 0.0;
} else {
- factors[i] = (stretch < 0) ? sizes[i] : 0.0;
+ factors[i] = (stretch < 0) ? sizes[i] : 0.0;
}
} else if (stretch == sumStretches) {
factors[i] = 1.0;
@@ -615,7 +615,7 @@ QRectF QGridLayoutItem::geometryWithin(qreal x, qreal y, qreal width, qreal heig
QSizeF size = effectiveMaxSize().boundedTo(QSizeF(cellWidth, cellHeight));
width = size.width();
height = size.height();
-
+
Qt::Alignment align = q_engine->effectiveAlignment(this);
switch (align & Qt::AlignHorizontal_Mask) {
case Qt::AlignHCenter:
@@ -717,7 +717,7 @@ void QGridLayoutItem::dump(int indent) const
void QGridLayoutRowInfo::insertOrRemoveRows(int row, int delta)
{
count += delta;
-
+
insertOrRemoveItems(stretches, row, delta);
insertOrRemoveItems(spacings, row, delta);
insertOrRemoveItems(alignments, row, delta);
@@ -1076,7 +1076,7 @@ QSizeF QGridLayoutEngine::sizeHint(const QLayoutStyleInfo &styleInfo, Qt::SizeHi
break;
}
return QSizeF();
-}
+}
QSizePolicy::ControlTypes QGridLayoutEngine::controlTypes(LayoutSide side) const
{
@@ -1131,9 +1131,9 @@ void QGridLayoutEngine::dump(int indent) const
QString message = QLatin1String("[ ");
for (int column = 0; column < internalGridColumnCount(); ++column) {
message += QString::number(q_items.indexOf(itemAt(row, column))).rightJustified(3);
- message += QLatin1String(" ");
+ message += QLatin1Char(' ');
}
- message += QLatin1String("]");
+ message += QLatin1Char(']');
qDebug("%*s %s", indent, "", qPrintable(message));
}
@@ -1150,16 +1150,16 @@ void QGridLayoutEngine::dump(int indent) const
q_rowData.dump(indent + 2);
qDebug("%*s Geometries output", indent, "");
+ QVector<qreal> *cellPos = &q_yy;
for (int pass = 0; pass < 2; ++pass) {
- QVector<qreal> &cellPos = q_yy;
QString message;
- for (i = 0; i < cellPos.count(); ++i) {
+ for (i = 0; i < cellPos->count(); ++i) {
message += QLatin1String((message.isEmpty() ? "[" : ", "));
- message += QString::number(cellPos.at(i));
+ message += QString::number(cellPos->at(i));
}
- message += QLatin1String("]");
+ message += QLatin1Char(']');
qDebug("%*s %s %s", indent, "", (pass == 0 ? "rows:" : "columns:"), qPrintable(message));
- cellPos = q_xx;
+ cellPos = &q_xx;
}
}
#endif
@@ -1538,5 +1538,5 @@ void QGridLayoutEngine::ensureGeometries(const QLayoutStyleInfo &styleInfo,
}
QT_END_NAMESPACE
-
+
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 30aaa51..4ff3a27 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -19,6 +19,7 @@ win32:include(kernel/win.pri)
embedded:include(embedded/embedded.pri)
#modules
+include(animation/animation.pri)
include(kernel/kernel.pri)
include(image/image.pri)
include(painting/painting.pri)
@@ -31,6 +32,8 @@ include(itemviews/itemviews.pri)
include(inputmethod/inputmethod.pri)
include(graphicsview/graphicsview.pri)
include(util/util.pri)
+include(statemachine/statemachine.pri)
+include(math3d/math3d.pri)
embedded: QT += network
diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri
index b5e3ee5..c15e8b6 100644
--- a/src/gui/image/image.pri
+++ b/src/gui/image/image.pri
@@ -22,6 +22,7 @@ HEADERS += \
image/qpixmap.h \
image/qpixmap_raster_p.h \
image/qpixmapcache.h \
+ image/qpixmapcache_p.h \
image/qpixmapdata_p.h \
image/qpixmapdatafactory_p.h \
image/qpixmapfilter_p.h
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 0799ea7..7e262b1 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -304,6 +304,8 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
QString key = QLatin1String("$qt_icon_")
+ QString::number(pm.cacheKey())
+ QString::number(pe->mode)
+ + QString::number(QApplication::palette().cacheKey())
+ + QLatin1Char('_')
+ QString::number(actualSize.width())
+ QLatin1Char('_')
+ QString::number(actualSize.height())
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 34ad99c..281d8d4 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1702,8 +1702,12 @@ void QImage::setColorTable(const QVector<QRgb> colors)
d->colortable = colors;
d->has_alpha_clut = false;
- for (int i = 0; i < d->colortable.size(); ++i)
- d->has_alpha_clut |= (qAlpha(d->colortable.at(i)) != 255);
+ for (int i = 0; i < d->colortable.size(); ++i) {
+ if (qAlpha(d->colortable.at(i)) != 255) {
+ d->has_alpha_clut = true;
+ break;
+ }
+ }
}
/*!
@@ -4288,6 +4292,11 @@ QImage QImage::mirrored(bool horizontal, bool vertical) const
int h = d->height;
// Create result image, copy colormap
QImage result(d->width, d->height, d->format);
+
+ // check if we ran out of of memory..
+ if (!result.d)
+ return QImage();
+
result.d->colortable = d->colortable;
result.d->has_alpha_clut = d->has_alpha_clut;
@@ -4770,7 +4779,7 @@ QDataStream &operator>>(QDataStream &s, QImage &image)
image = QImageReader(s.device(), 0).read();
return s;
}
-#endif
+#endif // QT_NO_DATASTREAM
#ifdef QT3_SUPPORT
@@ -4860,8 +4869,6 @@ bool QImage::operator==(const QImage & i) const
return false;
if (d->format != Format_RGB32) {
- if (d->colortable != i.d->colortable)
- return false;
if (d->format >= Format_ARGB32) { // all bits defined
const int n = d->width * d->depth / 8;
if (n == d->bytes_per_line && n == i.d->bytes_per_line) {
@@ -4874,11 +4881,13 @@ bool QImage::operator==(const QImage & i) const
}
}
} else {
- int w = width();
- int h = height();
+ const int w = width();
+ const int h = height();
+ const QVector<QRgb> &colortable = d->colortable;
+ const QVector<QRgb> &icolortable = i.d->colortable;
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
- if (pixelIndex(x, y) != i.pixelIndex(x, y))
+ if (colortable[pixelIndex(x, y)] != icolortable[i.pixelIndex(x, y)])
return false;
}
}
diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp
index 33e565c..dc01fe4 100644
--- a/src/gui/image/qnativeimage.cpp
+++ b/src/gui/image/qnativeimage.cpp
@@ -65,7 +65,7 @@ typedef struct {
QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer, QWidget *)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
Q_UNUSED(isTextBuffer);
#endif
BITMAPINFO_MASK bmi;
@@ -78,7 +78,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool is
if (format == QImage::Format_RGB16) {
bmi.bmiHeader.biBitCount = 16;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (isTextBuffer) {
bmi.bmiHeader.biCompression = BI_RGB;
bmi.redMask = 0;
@@ -116,7 +116,7 @@ QNativeImage::QNativeImage(int width, int height, QImage::Format format, bool is
Q_ASSERT(image.paintEngine()->type() == QPaintEngine::Raster);
static_cast<QRasterPaintEngine *>(image.paintEngine())->setDC(hdc);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GdiFlush();
#endif
}
diff --git a/src/gui/image/qnativeimage_p.h b/src/gui/image/qnativeimage_p.h
index 860485a..6402af2 100644
--- a/src/gui/image/qnativeimage_p.h
+++ b/src/gui/image/qnativeimage_p.h
@@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE
class QWidget;
-class Q_GUI_EXPORT QNativeImage
+class QNativeImage
{
public:
QNativeImage(int width, int height, QImage::Format format, bool isTextBuffer = false, QWidget *widget = 0);
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index a16305e..96f2a14 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -1148,6 +1148,7 @@ QPaintEngine *QPicture::paintEngine() const
QPicture stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
/*!
\relates QPicture
@@ -1193,6 +1194,7 @@ QDataStream &operator>>(QDataStream &s, QPicture &r)
r.d_func()->resetFormat();
return s;
}
+#endif // QT_NO_DATASTREAM
#ifndef QT_NO_PICTUREIO
diff --git a/src/gui/image/qpicture.h b/src/gui/image/qpicture.h
index 7de1f79..d28131f 100644
--- a/src/gui/image/qpicture.h
+++ b/src/gui/image/qpicture.h
@@ -184,8 +184,10 @@ private:
QPicture stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QPicture &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPicture &);
+#endif
#endif // QT_NO_PICTURE
diff --git a/src/gui/image/qpicture_p.h b/src/gui/image/qpicture_p.h
index 373ff15..a9c4dd5 100644
--- a/src/gui/image/qpicture_p.h
+++ b/src/gui/image/qpicture_p.h
@@ -69,7 +69,7 @@ class QPaintEngine;
extern const char *qt_mfhdr_tag;
-class Q_GUI_EXPORT QPicturePrivate
+class QPicturePrivate
{
Q_DECLARE_PUBLIC(QPicture)
friend class QPicturePaintEngine;
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index f85e21a..0ab14aa 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -383,6 +383,56 @@ QPixmap QPixmap::copy(const QRect &rect) const
}
/*!
+ \fn QPixmap::scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed)
+
+ This convenience function is equivalent to calling QPixmap::scroll(\a dx,
+ \a dy, QRect(\a x, \a y, \a width, \a height), \a exposed).
+
+ \sa QWidget::scroll(), QGraphicsItem::scroll()
+*/
+
+/*!
+ Scrolls the area \a rect of this pixmap by (\a dx, \a dy). The exposed
+ region is left unchanged. You can optionally pass a pointer to an empty
+ QRegion to get the region that is \a exposed by the scroll operation.
+
+ \snippet doc/src/snippets/code/src_gui_image_qpixmap.cpp 2
+
+ You cannot scroll while there is an active painter on the pixmap.
+
+ \sa QWidget::scroll(), QGraphicsItem::scroll()
+*/
+void QPixmap::scroll(int dx, int dy, const QRect &rect, QRegion *exposed)
+{
+ if (isNull() || (dx == 0 && dy == 0))
+ return;
+ QRect dest = rect & this->rect();
+ QRect src = dest.translated(-dx, -dy) & dest;
+ if (src.isEmpty()) {
+ if (exposed)
+ *exposed += dest;
+ return;
+ }
+
+ detach();
+
+ if (!data->scroll(dx, dy, src)) {
+ // Fallback
+ QPixmap pix = *this;
+ QPainter painter(&pix);
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ painter.drawPixmap(src.translated(dx, dy), *this, src);
+ painter.end();
+ *this = pix;
+ }
+
+ if (exposed) {
+ *exposed += dest;
+ *exposed -= src.translated(dx, dy);
+ }
+}
+
+/*!
Assigns the given \a pixmap to this pixmap and returns a reference
to this pixmap.
@@ -1271,7 +1321,7 @@ QDataStream &operator>>(QDataStream &stream, QPixmap &pixmap)
return stream;
}
-#endif //QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
#ifdef QT3_SUPPORT
Q_GUI_EXPORT void copyBlt(QPixmap *dst, int dx, int dy,
@@ -1313,14 +1363,6 @@ bool QPixmap::isDetached() const
void QPixmap::deref()
{
if (data && !data->ref.deref()) { // Destroy image if last ref
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- if (data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *rData = static_cast<QRasterPixmapData*>(data);
- if (rData->texture)
- rData->texture->Release();
- rData->texture = 0;
- }
-#endif
if (data->is_cached && qt_pixmap_cleanup_hook_64)
qt_pixmap_cleanup_hook_64(cacheKey());
delete data;
@@ -1857,7 +1899,7 @@ int QPixmap::defaultDepth()
return QScreen::instance()->depth();
#elif defined(Q_WS_X11)
return QX11Info::appDepth();
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WINCE)
return QColormap::instance().depth();
#elif defined(Q_WS_WIN)
return 32; // XXX
@@ -1895,12 +1937,6 @@ void QPixmap::detach()
if (id == QPixmapData::RasterClass) {
QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data);
rasterData->image.detach();
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- if (rasterData->texture) {
- rasterData->texture->Release();
- rasterData->texture = 0;
- }
-#endif
}
if (data->is_cached && qt_pixmap_cleanup_hook_64 && data->ref == 1)
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 6c24055..afe7b1c 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -163,6 +163,9 @@ public:
inline QPixmap copy(int x, int y, int width, int height) const;
QPixmap copy(const QRect &rect = QRect()) const;
+ inline void scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed = 0);
+ void scroll(int dx, int dy, const QRect &rect, QRegion *exposed = 0);
+
int serialNumber() const;
qint64 cacheKey() const;
@@ -259,8 +262,6 @@ private:
friend class QWidgetPrivate;
friend class QRasterPaintEngine;
friend class QRasterBuffer;
- friend class QDirect3DPaintEngine;
- friend class QDirect3DPaintEnginePrivate;
friend class QDetachedPixmap;
#if !defined(QT_NO_DATASTREAM)
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPixmap &);
@@ -282,6 +283,11 @@ inline QPixmap QPixmap::copy(int ax, int ay, int awidth, int aheight) const
return copy(QRect(ax, ay, awidth, aheight));
}
+inline void QPixmap::scroll(int dx, int dy, int ax, int ay, int awidth, int aheight, QRegion *exposed)
+{
+ scroll(dx, dy, QRect(ax, ay, awidth, aheight), exposed);
+}
+
inline bool QPixmap::loadFromData(const QByteArray &buf, const char *format,
Qt::ImageConversionFlags flags)
{
diff --git a/src/gui/image/qpixmap_mac.cpp b/src/gui/image/qpixmap_mac.cpp
index 26d9618..973cd78 100644
--- a/src/gui/image/qpixmap_mac.cpp
+++ b/src/gui/image/qpixmap_mac.cpp
@@ -1290,6 +1290,14 @@ void QMacPixmapData::copy(const QPixmapData *data, const QRect &rect)
has_mask = macData->has_mask;
}
+bool QMacPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
/*!
\since 4.2
diff --git a/src/gui/image/qpixmap_mac_p.h b/src/gui/image/qpixmap_mac_p.h
index 75525c4..2b22e6b 100644
--- a/src/gui/image/qpixmap_mac_p.h
+++ b/src/gui/image/qpixmap_mac_p.h
@@ -68,6 +68,7 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
+ bool scroll(int dx, int dy, const QRect &rect);
int metric(QPaintDevice::PaintDeviceMetric metric) const;
void fill(const QColor &color);
diff --git a/src/gui/image/qpixmap_raster.cpp b/src/gui/image/qpixmap_raster.cpp
index 7dfab70..29e4f3f 100644
--- a/src/gui/image/qpixmap_raster.cpp
+++ b/src/gui/image/qpixmap_raster.cpp
@@ -50,12 +50,6 @@
#include <private/qwidget_p.h>
#include <private/qdrawhelper_p.h>
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
-#include <private/qpaintengine_d3d_p.h>
-#include <d3d9.h>
-extern QDirect3DPaintEngine *qt_d3dEngine();
-#endif
-
QT_BEGIN_NAMESPACE
const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
@@ -63,9 +57,6 @@ const uchar qt_pixmap_bit_mask[] = { 0x01, 0x02, 0x04, 0x08,
QRasterPixmapData::QRasterPixmapData(PixelType type)
: QPixmapData(type, RasterClass)
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- , texture(0)
-#endif
{
}
@@ -181,6 +172,16 @@ void QRasterPixmapData::fromImage(const QImage &sourceImage,
setSerialNumber(image.serialNumber());
}
+// from qwindowsurface.cpp
+extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset);
+
+bool QRasterPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ if (!image.isNull())
+ qt_scrollRectInImage(image, rect, QPoint(dx, dy));
+ return true;
+}
+
void QRasterPixmapData::fill(const QColor &color)
{
uint pixel;
@@ -321,25 +322,36 @@ extern int qt_defaultDpiY();
int QRasterPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
{
+ QImageData *d = image.d;
+ if (!d)
+ return 0;
+
// override the image dpi with the screen dpi when rendering to a pixmap
- const int dpmX = qRound(qt_defaultDpiX() * 100 / qreal(2.54));
- const int dpmY = qRound(qt_defaultDpiY() * 100 / qreal(2.54));
switch (metric) {
+ case QPaintDevice::PdmWidth:
+ return d->width;
+ case QPaintDevice::PdmHeight:
+ return d->height;
case QPaintDevice::PdmWidthMM:
- return qRound(image.width() * 1000 / dpmX);
+ return qRound(d->width * 25.4 / qt_defaultDpiX());
case QPaintDevice::PdmHeightMM:
- return qRound(image.height() * 1000 / dpmY);
- case QPaintDevice::PdmDpiX:
- return qRound(dpmX * qreal(0.0254));
- case QPaintDevice::PdmDpiY:
- return qRound(dpmY * qreal(0.0254));
+ return qRound(d->width * 25.4 / qt_defaultDpiY());
+ case QPaintDevice::PdmNumColors:
+ return d->colortable.size();
+ case QPaintDevice::PdmDepth:
+ return d->depth;
+ case QPaintDevice::PdmDpiX: // fall-through
case QPaintDevice::PdmPhysicalDpiX:
- return qRound(dpmX * qreal(0.0254));
+ return qt_defaultDpiX();
+ case QPaintDevice::PdmDpiY: // fall-through
case QPaintDevice::PdmPhysicalDpiY:
- return qRound(dpmY * qreal(0.0254));
+ return qt_defaultDpiY();
default:
- return image.metric(metric);
+ qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric);
+ break;
}
+
+ return 0;
}
QImage* QRasterPixmapData::buffer()
diff --git a/src/gui/image/qpixmap_raster_p.h b/src/gui/image/qpixmap_raster_p.h
index 095f378..9d3bf72 100644
--- a/src/gui/image/qpixmap_raster_p.h
+++ b/src/gui/image/qpixmap_raster_p.h
@@ -58,9 +58,6 @@
#ifdef Q_WS_WIN
# include "qt_windows.h"
-# ifndef QT_NO_DIRECT3D
-# include <d3d9.h>
-# endif
#endif
QT_BEGIN_NAMESPACE
@@ -75,6 +72,7 @@ public:
void fromFile(const QString &filename, Qt::ImageConversionFlags flags);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
void setMask(const QBitmap &mask);
bool hasAlphaChannel() const;
@@ -87,10 +85,6 @@ protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
private:
-#if defined(Q_WS_WIN) && !defined(QT_NO_DIRECT3D)
- friend class QDirect3DPaintEnginePrivate;
- IDirect3DTexture9 *texture;
-#endif
friend class QPixmap;
friend class QBitmap;
friend class QDetachedPixmap;
diff --git a/src/gui/image/qpixmap_win.cpp b/src/gui/image/qpixmap_win.cpp
index 6a8b38a..ac02f97 100644
--- a/src/gui/image/qpixmap_win.cpp
+++ b/src/gui/image/qpixmap_win.cpp
@@ -59,7 +59,7 @@
#include "qdebug.h"
#include "qt_windows.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include <winbase.h>
#include "qguifunctions_wince.h"
extern bool qt_wince_is_high_dpi();
@@ -80,7 +80,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
if (w < 0) w = r.right - r.left;
if (h < 0) h = r.bottom - r.top;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (qt_wince_is_pocket_pc()) {
QWidget *widget = QWidget::find(winId);
if (qobject_cast<QDesktopWidget *>(widget)) {
@@ -101,7 +101,7 @@ QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
// copy data
HDC window_dc = GetDC(winId);
BitBlt(bitmap_dc, 0, 0, w, h, window_dc, x, y, SRCCOPY
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
| CAPTUREBLT
#endif
);
@@ -243,7 +243,7 @@ QPixmap QPixmap::fromWinHBITMAP(HBITMAP bitmap, HBitmapFormat format)
}
#ifdef Q_WS_WIN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
static QImage qt_fromWinHBITMAP(HDC hdc, HBITMAP bitmap, int w, int h)
{
@@ -347,7 +347,7 @@ QPixmap convertHIconToPixmap( const HICON icon)
DeleteDC(hdc);
return QPixmap::fromImage(image);
}
-#else //ifndef Q_OS_WINCE
+#else //ifndef Q_WS_WINCE
QPixmap convertHIconToPixmap( const HICON icon, bool large)
{
HDC screenDevice = GetDC(0);
@@ -412,7 +412,7 @@ QPixmap convertHIconToPixmap( const HICON icon, bool large)
DeleteDC(hdc);
return QPixmap::fromImage(image);
}
-#endif //ifndef Q_OS_WINCE
+#endif //ifndef Q_WS_WINCE
QPixmap loadIconFromShell32( int resourceId, int size )
{
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index d2e8d84..a0ae01f 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -2177,6 +2177,16 @@ void QX11PixmapData::copy(const QPixmapData *data, const QRect &rect)
}
}
+bool QX11PixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ GC gc = XCreateGC(X11->display, hd, 0, 0);
+ XCopyArea(X11->display, hd, hd, gc,
+ rect.left(), rect.top(), rect.width(), rect.height(),
+ rect.left() + dx, rect.top() + dy);
+ XFreeGC(X11->display, gc);
+ return true;
+}
+
#if !defined(QT_NO_XRENDER)
void QX11PixmapData::convertToARGB32(bool preserveContents)
{
diff --git a/src/gui/image/qpixmap_x11_p.h b/src/gui/image/qpixmap_x11_p.h
index 980b10e..c526402 100644
--- a/src/gui/image/qpixmap_x11_p.h
+++ b/src/gui/image/qpixmap_x11_p.h
@@ -74,6 +74,7 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image, Qt::ImageConversionFlags flags);
void copy(const QPixmapData *data, const QRect &rect);
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
QBitmap mask() const;
diff --git a/src/gui/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 4f71e09..59c8ce7 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -40,13 +40,9 @@
****************************************************************************/
#include "qpixmapcache.h"
-#include "qcache.h"
#include "qobject.h"
#include "qdebug.h"
-
-#include "qpaintengine.h"
-#include <private/qimage_p.h>
-#include <private/qpixmap_raster_p.h>
+#include "qpixmapcache_p.h"
QT_BEGIN_NAMESPACE
@@ -68,15 +64,20 @@ QT_BEGIN_NAMESPACE
access the global pixmap cache. It creates an internal QCache
object for caching the pixmaps.
- The cache associates a pixmap with a string (key). If two pixmaps
- are inserted into the cache using equal keys, then the last pixmap
- will hide the first pixmap. The QHash and QCache classes do
+ The cache associates a pixmap with a string as a key or with a QPixmapCache::Key.
+ The QPixmapCache::Key is faster than using strings as key. The string API is
+ very convenient for complex keys but the QPixmapCache::Key API will be very efficient
+ and convenient for a 1 object <-> 1 pixmap mapping (then you can store the key as
+ a member).
+ If two pixmaps are inserted into the cache using equal keys, then the
+ last pixmap will hide the first pixmap. The QHash and QCache classes do
exactly the same.
The cache becomes full when the total size of all pixmaps in the
- cache exceeds cacheLimit(). The initial cache limit is 1024 KB (1
- MB); it is changed with setCacheLimit(). A pixmap takes roughly
- (\e{width} * \e{height} * \e{depth})/8 bytes of memory.
+ cache exceeds cacheLimit(). The initial cache limit is
+ 2048 KB(2 MB) for Embedded, 10240 KB (10
+ MB) for Desktops; it is changed with setCacheLimit().
+ A pixmap takes roughly (\e{width} * \e{height} * \e{depth})/8 bytes of memory.
The \e{Qt Quarterly} article
\l{http://doc.trolltech.com/qq/qq12-qpixmapcache.html}{Optimizing
@@ -88,58 +89,128 @@ QT_BEGIN_NAMESPACE
#if defined(Q_OS_SYMBIAN)
static int cache_limit = 1024; // 1048 KB cache limit for symbian
-#elif defined(Q_WS_QWS) || defined(Q_OS_WINCE)
+#elif defined(Q_WS_QWS) || defined(Q_WS_WINCE)
static int cache_limit = 2048; // 2048 KB cache limit for embedded
#else
static int cache_limit = 10240; // 10 MB cache limit for desktop
#endif
-// XXX: hw: is this a general concept we need to abstract?
-class QDetachedPixmap : public QPixmap
+/*!
+ Constructs an empty Key object.
+*/
+QPixmapCache::Key::Key() : d(0)
{
-public:
- QDetachedPixmap(const QPixmap &pix) : QPixmap(pix)
- {
- if (data && data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data);
- if (!d->image.isNull() && d->image.d->paintEngine
- && !d->image.d->paintEngine->isActive())
- {
- delete d->image.d->paintEngine;
- d->image.d->paintEngine = 0;
- }
- }
+}
+
+/*!
+ \internal
+ Constructs a copy of \a other.
+*/
+QPixmapCache::Key::Key(const Key &other)
+{
+ if (other.d)
+ ++(other.d->ref);
+ d = other.d;
+}
+
+/*!
+ Destructor; called immediately before the object is deleted.
+*/
+QPixmapCache::Key::~Key()
+{
+ if (d && --(d->ref) == 0)
+ delete d;
+}
+
+/*!
+ \internal
+
+ Returns true if this key is the same as the given \a key.
+*/
+bool QPixmapCache::Key::operator ==(const Key &key) const
+{
+ return (d == key.d);
+}
+
+/*!
+ \fn bool QPixmapCache::Key::operator !=(const Key &key) const
+ \internal
+*/
+
+/*!
+ \internal
+*/
+QPixmapCache::Key &QPixmapCache::Key::operator =(const Key &other)
+{
+ if (d != other.d) {
+ if (other.d)
+ ++(other.d->ref);
+ if (d && --(d->ref) == 0)
+ delete d;
+ d = other.d;
}
-};
+ return *this;
+}
-class QPMCache : public QObject, public QCache<qint64, QDetachedPixmap>
+class QPMCache : public QObject, public QCache<QPixmapCache::Key, QDetachedPixmap>
{
Q_OBJECT
public:
- QPMCache()
- : QObject(0),
- QCache<qint64, QDetachedPixmap>(cache_limit * 1024),
- theid(0), ps(0), t(false) { }
- ~QPMCache() { }
+ QPMCache();
+ ~QPMCache();
void timerEvent(QTimerEvent *);
bool insert(const QString& key, const QPixmap &pixmap, int cost);
+ QPixmapCache::Key insert(const QPixmap &pixmap, int cost);
+ bool replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost);
bool remove(const QString &key);
+ bool remove(const QPixmapCache::Key &key);
+
+ void resizeKeyArray(int size);
+ QPixmapCache::Key createKey();
+ void releaseKey(const QPixmapCache::Key &key);
+ void clear();
QPixmap *object(const QString &key) const;
+ QPixmap *object(const QPixmapCache::Key &key) const;
+
+ static inline QPixmapCache::KeyData *get(const QPixmapCache::Key &key)
+ {return key.d;}
+
+ static QPixmapCache::KeyData* getKeyData(QPixmapCache::Key *key);
private:
- QHash<QString, qint64> cacheKeys;
+ int *keyArray;
int theid;
int ps;
+ int keyArraySize;
+ int freeKey;
+ QHash<QString, QPixmapCache::Key> cacheKeys;
bool t;
};
+
QT_BEGIN_INCLUDE_NAMESPACE
#include "qpixmapcache.moc"
QT_END_INCLUDE_NAMESPACE
+uint qHash(const QPixmapCache::Key &k)
+{
+ return qHash(QPMCache::get(k)->key);
+}
+
+QPMCache::QPMCache()
+ : QObject(0),
+ QCache<QPixmapCache::Key, QDetachedPixmap>(cache_limit * 1024),
+ keyArray(0), theid(0), ps(0), keyArraySize(0), freeKey(0), t(false)
+{
+}
+QPMCache::~QPMCache()
+{
+ free(keyArray);
+}
+
/*
- This is supposed to cut the cache size down by about 80-90% in a
+ This is supposed to cut the cache size down by about 25% in a
minute once the application becomes idle, to let any inserted pixmap
remain in the cache for some time before it becomes a candidate for
cleaning-up, and to not cut down the size of the cache while the
@@ -148,23 +219,28 @@ QT_END_INCLUDE_NAMESPACE
When the last pixmap has been deleted from the cache, kill the
timer so Qt won't keep the CPU from going into sleep mode.
*/
-
void QPMCache::timerEvent(QTimerEvent *)
{
int mc = maxCost();
bool nt = totalCost() == ps;
+ QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QDetachedPixmap>::keys();
setMaxCost(nt ? totalCost() * 3 / 4 : totalCost() -1);
setMaxCost(mc);
ps = totalCost();
- QHash<QString, qint64>::iterator it = cacheKeys.begin();
+ QHash<QString, QPixmapCache::Key>::iterator it = cacheKeys.begin();
while (it != cacheKeys.end()) {
if (!contains(it.value())) {
+ releaseKey(it.value());
it = cacheKeys.erase(it);
} else {
++it;
}
}
+ for (int i = 0; i < keys.size(); ++i) {
+ if (!contains(keys.at(i)))
+ releaseKey(keys.at(i));
+ }
if (!size()) {
killTimer(theid);
@@ -178,38 +254,156 @@ void QPMCache::timerEvent(QTimerEvent *)
QPixmap *QPMCache::object(const QString &key) const
{
- return QCache<qint64, QDetachedPixmap>::object(cacheKeys.value(key, -1));
+ QPixmapCache::Key cacheKey = cacheKeys.value(key);
+ if (!cacheKey.d || !cacheKey.d->isValid) {
+ const_cast<QPMCache *>(this)->cacheKeys.remove(key);
+ return 0;
+ }
+ QPixmap *ptr = QCache<QPixmapCache::Key, QDetachedPixmap>::object(cacheKey);
+ //We didn't find the pixmap in the cache, the key is not valid anymore
+ if (!ptr) {
+ const_cast<QPMCache *>(this)->cacheKeys.remove(key);
+ const_cast<QPMCache *>(this)->releaseKey(cacheKey);
+ }
+ return ptr;
}
+QPixmap *QPMCache::object(const QPixmapCache::Key &key) const
+{
+ Q_ASSERT(key.d->isValid);
+ QPixmap *ptr = QCache<QPixmapCache::Key, QDetachedPixmap>::object(key);
+ //We didn't find the pixmap in the cache, the key is not valid anymore
+ if (!ptr)
+ const_cast<QPMCache *>(this)->releaseKey(key);
+ return ptr;
+}
bool QPMCache::insert(const QString& key, const QPixmap &pixmap, int cost)
{
- qint64 cacheKey = pixmap.cacheKey();
- if (QCache<qint64, QDetachedPixmap>::object(cacheKey)) {
+ QPixmapCache::Key cacheKey;
+ QPixmapCache::Key oldCacheKey = cacheKeys.value(key);
+ //If for the same key we add already a pixmap we should delete it
+ if (oldCacheKey.d) {
+ QCache<QPixmapCache::Key, QDetachedPixmap>::remove(oldCacheKey);
+ cacheKey = oldCacheKey;
+ } else {
+ cacheKey = createKey();
+ }
+
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
+ if (success) {
cacheKeys.insert(key, cacheKey);
- return true;
+ if (!theid) {
+ theid = startTimer(30000);
+ t = false;
+ }
+ } else {
+ //Insertion failed we released the new allocated key
+ releaseKey(cacheKey);
}
- qint64 oldCacheKey = cacheKeys.value(key, -1);
- //If for the same key we add already a pixmap we should delete it
- if (oldCacheKey != -1)
- QCache<qint64, QDetachedPixmap>::remove(oldCacheKey);
+ return success;
+}
- bool success = QCache<qint64, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
+QPixmapCache::Key QPMCache::insert(const QPixmap &pixmap, int cost)
+{
+ QPixmapCache::Key cacheKey = createKey();
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(cacheKey, new QDetachedPixmap(pixmap), cost);
if (success) {
- cacheKeys.insert(key, cacheKey);
if (!theid) {
theid = startTimer(30000);
t = false;
}
+ } else {
+ //Insertion failed we released the key and return an invalid one
+ releaseKey(cacheKey);
+ }
+ return cacheKey;
+}
+
+bool QPMCache::replace(const QPixmapCache::Key &key, const QPixmap &pixmap, int cost)
+{
+ Q_ASSERT(key.d->isValid);
+ //If for the same key we add already a pixmap we should delete it
+ QCache<QPixmapCache::Key, QDetachedPixmap>::remove(key);
+
+ bool success = QCache<QPixmapCache::Key, QDetachedPixmap>::insert(key, new QDetachedPixmap(pixmap), cost);
+ if (success && !theid) {
+ theid = startTimer(30000);
+ t = false;
}
return success;
}
bool QPMCache::remove(const QString &key)
{
- qint64 cacheKey = cacheKeys.value(key, -1);
+ QPixmapCache::Key cacheKey = cacheKeys.value(key);
+ //The key was not in the cache
+ if (!cacheKey.d)
+ return false;
cacheKeys.remove(key);
- return QCache<qint64, QDetachedPixmap>::remove(cacheKey);
+ releaseKey(cacheKey);
+ return QCache<QPixmapCache::Key, QDetachedPixmap>::remove(cacheKey);
+}
+
+bool QPMCache::remove(const QPixmapCache::Key &key)
+{
+ bool result = QCache<QPixmapCache::Key, QDetachedPixmap>::remove(key);
+ //We release the key after we removed it from the cache
+ releaseKey(key);
+ return result;
+}
+
+void QPMCache::resizeKeyArray(int size)
+{
+ if (size <= keyArraySize || size == 0)
+ return;
+ keyArray = reinterpret_cast<int *>(realloc(keyArray, size * sizeof(int)));
+ for (int i = keyArraySize; i != size; ++i)
+ keyArray[i] = i + 1;
+ keyArraySize = size;
+}
+
+QPixmapCache::Key QPMCache::createKey()
+{
+ if (freeKey == keyArraySize)
+ resizeKeyArray(keyArraySize ? keyArraySize << 1 : 2);
+ int id = freeKey;
+ freeKey = keyArray[id];
+ QPixmapCache::Key key;
+ QPixmapCache::KeyData *d = QPMCache::getKeyData(&key);
+ d->key = ++id;
+ return key;
+}
+
+void QPMCache::releaseKey(const QPixmapCache::Key &key)
+{
+ if (key.d->key > keyArraySize || key.d->key <= 0)
+ return;
+ key.d->key--;
+ keyArray[key.d->key] = freeKey;
+ freeKey = key.d->key;
+ key.d->isValid = false;
+ key.d->key = 0;
+}
+
+void QPMCache::clear()
+{
+ free(keyArray);
+ keyArray = 0;
+ freeKey = 0;
+ keyArraySize = 0;
+ //Mark all keys as invalid
+ QList<QPixmapCache::Key> keys = QCache<QPixmapCache::Key, QDetachedPixmap>::keys();
+ for (int i = 0; i < keys.size(); ++i)
+ keys.at(i).d->isValid = false;
+ QCache<QPixmapCache::Key, QDetachedPixmap>::clear();
+}
+
+QPixmapCache::KeyData* QPMCache::getKeyData(QPixmapCache::Key *key)
+{
+ if (!key->d)
+ key->d = new QPixmapCache::KeyData;
+ return key->d;
}
Q_GLOBAL_STATIC(QPMCache, pm_cache)
@@ -224,7 +418,7 @@ Q_GLOBAL_STATIC(QPMCache, pm_cache)
\warning If valid, you should copy the pixmap immediately (this is
fast). Subsequent insertions into the cache could cause the
pointer to become invalid. For this reason, we recommend you use
- find(const QString&, QPixmap&) instead.
+ bool find(const QString&, QPixmap*) instead.
Example:
\snippet doc/src/snippets/code/src_gui_image_qpixmapcache.cpp 0
@@ -237,25 +431,57 @@ QPixmap *QPixmapCache::find(const QString &key)
/*!
+ \obsolete
+
+ Use bool find(const QString&, QPixmap*) instead.
+*/
+
+bool QPixmapCache::find(const QString &key, QPixmap& pixmap)
+{
+ return find(key, &pixmap);
+}
+
+/*!
Looks for a cached pixmap associated with the \a key in the cache.
- If the pixmap is found, the function sets \a pm to that pixmap and
- returns true; otherwise it leaves \a pm alone and returns false.
+ If the pixmap is found, the function sets \a pixmap to that pixmap and
+ returns true; otherwise it leaves \a pixmap alone and returns false.
+
+ \since 4.6
Example:
\snippet doc/src/snippets/code/src_gui_image_qpixmapcache.cpp 1
*/
-bool QPixmapCache::find(const QString &key, QPixmap& pm)
+bool QPixmapCache::find(const QString &key, QPixmap* pixmap)
{
QPixmap *ptr = pm_cache()->object(key);
- if (ptr)
- pm = *ptr;
+ if (ptr && pixmap)
+ *pixmap = *ptr;
return ptr != 0;
}
+/*!
+ Looks for a cached pixmap associated with the \a key in the cache.
+ If the pixmap is found, the function sets \a pixmap to that pixmap and
+ returns true; otherwise it leaves \a pixmap alone and returns false. If
+ the pixmap is not found, it means that the \a key is not valid anymore,
+ so it will be released for the next insertion.
+
+ \since 4.6
+*/
+bool QPixmapCache::find(const Key &key, QPixmap* pixmap)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return false;
+ QPixmap *ptr = pm_cache()->object(key);
+ if (ptr && pixmap)
+ *pixmap = *ptr;
+ return ptr != 0;
+}
/*!
- Inserts a copy of the pixmap \a pm associated with the \a key into
+ Inserts a copy of the pixmap \a pixmap associated with the \a key into
the cache.
All pixmaps inserted by the Qt library have a key starting with
@@ -274,9 +500,46 @@ bool QPixmapCache::find(const QString &key, QPixmap& pm)
\sa setCacheLimit()
*/
-bool QPixmapCache::insert(const QString &key, const QPixmap &pm)
+bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
{
- return pm_cache()->insert(key, pm, pm.width() * pm.height() * pm.depth() / 8);
+ return pm_cache()->insert(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+}
+
+/*!
+ Inserts a copy of the pixmap \a pixmap into
+ the cache and return you the key.
+
+ When a pixmap is inserted and the cache is about to exceed its
+ limit, it removes pixmaps until there is enough room for the
+ pixmap to be inserted.
+
+ The oldest pixmaps (least recently accessed in the cache) are
+ deleted when more space is needed.
+
+ \sa setCacheLimit(), replace()
+
+ \since 4.6
+*/
+QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
+{
+ return pm_cache()->insert(pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
+}
+
+/*!
+ Replace the pixmap associated to the \a key into
+ the cache. It return true if the pixmap \a pixmap has been correctly
+ inserted into the cache false otherwise.
+
+ \sa setCacheLimit(), insert()
+
+ \since 4.6
+*/
+bool QPixmapCache::replace(const Key &key, const QPixmap &pixmap)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return false;
+ return pm_cache()->replace(key, pixmap, pixmap.width() * pixmap.height() * pixmap.depth() / 8);
}
/*!
@@ -316,6 +579,19 @@ void QPixmapCache::remove(const QString &key)
pm_cache()->remove(key);
}
+/*!
+ Removes the pixmap associated with \a key from the cache and release
+ the key for a future insertion.
+
+ \since 4.6
+*/
+void QPixmapCache::remove(const Key &key)
+{
+ //The key is not valid anymore, a flush happened before probably
+ if (!key.d || !key.d->isValid)
+ return;
+ pm_cache()->remove(key);
+}
/*!
Removes all pixmaps from the cache.
diff --git a/src/gui/image/qpixmapcache.h b/src/gui/image/qpixmapcache.h
index 2750a88..ae64310 100644
--- a/src/gui/image/qpixmapcache.h
+++ b/src/gui/image/qpixmapcache.h
@@ -53,12 +53,35 @@ QT_MODULE(Gui)
class Q_GUI_EXPORT QPixmapCache
{
public:
+ class KeyData;
+ class Key
+ {
+ public:
+ Key();
+ Key(const Key &other);
+ ~Key();
+ bool operator ==(const Key &key) const;
+ inline bool operator !=(const Key &key) const
+ { return !operator==(key); }
+ Key &operator =(const Key &other);
+
+ private:
+ KeyData *d;
+ friend class QPMCache;
+ friend class QPixmapCache;
+ };
+
static int cacheLimit();
static void setCacheLimit(int);
static QPixmap *find(const QString &key);
- static bool find(const QString &key, QPixmap&);
- static bool insert(const QString &key, const QPixmap&);
+ static bool find(const QString &key, QPixmap &pixmap);
+ static bool find(const QString &key, QPixmap *pixmap);
+ static bool find(const Key &key, QPixmap *pixmap);
+ static bool insert(const QString &key, const QPixmap &pixmap);
+ static Key insert(const QPixmap &pixmap);
+ static bool replace(const Key &key, const QPixmap &pixmap);
static void remove(const QString &key);
+ static void remove(const Key &key);
static void clear();
};
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
new file mode 100644
index 0000000..a35e0d2
--- /dev/null
+++ b/src/gui/image/qpixmapcache_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPIXMAPCACHE_P_H
+#define QPIXMAPCACHE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header
+// file may change from version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qpixmapcache.h"
+#include "qpaintengine.h"
+#include <private/qimage_p.h>
+#include <private/qpixmap_raster_p.h>
+#include "qcache.h"
+
+QT_BEGIN_NAMESPACE
+
+uint qHash(const QPixmapCache::Key &k);
+
+class QPixmapCache::KeyData
+{
+public:
+ KeyData() : isValid(true), key(0), ref(1) {}
+ KeyData(const KeyData &other)
+ : isValid(other.isValid), key(other.key), ref(1) {}
+ ~KeyData() {}
+
+ bool isValid;
+ int key;
+ int ref;
+};
+
+// XXX: hw: is this a general concept we need to abstract?
+class QDetachedPixmap : public QPixmap
+{
+public:
+ QDetachedPixmap(const QPixmap &pix) : QPixmap(pix)
+ {
+ if (data && data->classId() == QPixmapData::RasterClass) {
+ QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data);
+ if (!d->image.isNull() && d->image.d->paintEngine
+ && !d->image.d->paintEngine->isActive())
+ {
+ delete d->image.d->paintEngine;
+ d->image.d->paintEngine = 0;
+ }
+ }
+ }
+};
+
+QT_END_NAMESPACE
+
+#endif // QPIXMAPCACHE_P_H
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 3d88f4b..245a866 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -73,6 +73,14 @@ void QPixmapData::copy(const QPixmapData *data, const QRect &rect)
fromImage(data->toImage().copy(rect), Qt::AutoColor);
}
+bool QPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
void QPixmapData::setMask(const QBitmap &mask)
{
if (mask.size().isEmpty()) {
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 7296426..27bc70d 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -78,6 +78,7 @@ public:
virtual void fromFile(const QString &filename, const char *format,
Qt::ImageConversionFlags flags);
virtual void copy(const QPixmapData *data, const QRect &rect);
+ virtual bool scroll(int dx, int dy, const QRect &rect);
virtual int metric(QPaintDevice::PaintDeviceMetric metric) const = 0;
virtual void fill(const QColor &color) = 0;
@@ -121,7 +122,7 @@ private:
};
#ifdef Q_WS_WIN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
QPixmap convertHIconToPixmap( const HICON icon);
#else
QPixmap convertHIconToPixmap( const HICON icon, bool large = false);
diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp
index 03d62d3..1254c40 100644
--- a/src/gui/image/qpixmapdatafactory.cpp
+++ b/src/gui/image/qpixmapdatafactory.cpp
@@ -84,7 +84,7 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type)
#endif
}
-Q_GLOBAL_STATIC(QSimplePixmapDataFactory, factory);
+Q_GLOBAL_STATIC(QSimplePixmapDataFactory, factory)
#endif // !defined(Q_WS_QWS)
diff --git a/src/gui/image/qpixmapdatafactory_p.h b/src/gui/image/qpixmapdatafactory_p.h
index 65e3f11..9604346 100644
--- a/src/gui/image/qpixmapdatafactory_p.h
+++ b/src/gui/image/qpixmapdatafactory_p.h
@@ -65,7 +65,7 @@ QT_MODULE(Gui)
class QPixmapData;
-class Q_GUI_EXPORT QPixmapDataFactory
+class QPixmapDataFactory
{
public:
static QPixmapDataFactory* instance(int screen = 0);
diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp
index 8631c8c..4e6adc0 100644
--- a/src/gui/image/qpixmapfilter.cpp
+++ b/src/gui/image/qpixmapfilter.cpp
@@ -401,6 +401,7 @@ static void convolute(
}
yk++;
}
+ delete[] fixedKernel;
}
/*!
diff --git a/src/gui/image/qxpmhandler.cpp b/src/gui/image/qxpmhandler.cpp
index 90bd2ab..f4062ad 100644
--- a/src/gui/image/qxpmhandler.cpp
+++ b/src/gui/image/qxpmhandler.cpp
@@ -1146,7 +1146,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
QTextStream s(device);
s << "/* XPM */" << endl
<< "static char *" << fbname(fileName) << "[]={" << endl
- << "\"" << w << " " << h << " " << ncolors << " " << cpp << "\"";
+ << '\"' << w << ' ' << h << ' ' << ncolors << ' ' << cpp << '\"';
// write palette
QMap<QRgb, int>::Iterator c = colorMap.begin();
@@ -1162,7 +1162,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
qGreen(color),
qBlue(color));
++c;
- s << "," << endl << line;
+ s << ',' << endl << line;
}
// write pixels, limit to 4 characters per pixel
@@ -1184,7 +1184,7 @@ static bool write_xpm_image(const QImage &sourceImage, QIODevice *device, const
}
}
}
- s << "," << endl << "\"" << line << "\"";
+ s << ',' << endl << '\"' << line << '\"';
}
s << "};" << endl;
return (s.status() == QTextStream::Ok);
diff --git a/src/gui/inputmethod/qinputcontext.cpp b/src/gui/inputmethod/qinputcontext.cpp
index 00a9225..a0b2a54 100644
--- a/src/gui/inputmethod/qinputcontext.cpp
+++ b/src/gui/inputmethod/qinputcontext.cpp
@@ -274,7 +274,7 @@ void QInputContext::sendEvent(const QInputMethodEvent &event)
return;
QInputMethodEvent e(event);
- qApp->sendEvent(focus, &e);
+ QApplication::sendEvent(focus, &e);
}
@@ -420,7 +420,7 @@ QList<QAction *> QInputContext::actions()
QTextFormat QInputContext::standardFormat(StandardFormat s) const
{
QWidget *focus = focusWidget();
- const QPalette &pal = focus ? focus->palette() : qApp->palette();
+ const QPalette &pal = focus ? focus->palette() : QApplication::palette();
QTextCharFormat fmt;
QColor bg;
diff --git a/src/gui/inputmethod/qinputcontext_p.h b/src/gui/inputmethod/qinputcontext_p.h
index 8c1b8de..a5e3d91 100644
--- a/src/gui/inputmethod/qinputcontext_p.h
+++ b/src/gui/inputmethod/qinputcontext_p.h
@@ -84,10 +84,6 @@ public:
{}
QWidget *focusWidget;
-
-#if defined(Q_WS_WIN) || defined(Q_WS_QWS)
- static void updateImeStatus(QWidget *w, bool hasFocus);
-#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qmacinputcontext_mac.cpp b/src/gui/inputmethod/qmacinputcontext_mac.cpp
index f0e7ea9..86385fa 100644
--- a/src/gui/inputmethod/qmacinputcontext_mac.cpp
+++ b/src/gui/inputmethod/qmacinputcontext_mac.cpp
@@ -45,6 +45,7 @@
#include "qtextformat.h"
#include <qdebug.h>
#include <private/qapplication_p.h>
+#include <private/qkeymapper_p.h>
QT_BEGIN_NAMESPACE
@@ -63,7 +64,8 @@ static QTextFormat qt_mac_compose_format()
}
QMacInputContext::QMacInputContext(QObject *parent)
- : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0)
+ : QInputContext(parent), composing(false), recursionGuard(false), textDocument(0),
+ keydownEvent(0)
{
// createTextDocument();
}
@@ -183,6 +185,16 @@ QMacInputContext::cleanup()
#endif
}
+void QMacInputContext::setLastKeydownEvent(EventRef event)
+{
+ EventRef tmpEvent = keydownEvent;
+ keydownEvent = event;
+ if (keydownEvent)
+ RetainEvent(keydownEvent);
+ if (tmpEvent)
+ ReleaseEvent(tmpEvent);
+}
+
OSStatus
QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void *)
{
@@ -335,6 +347,12 @@ QMacInputContext::globalEventProcessor(EventHandlerCallRef, EventRef event, void
GetEventParameter(key_ev, kEventParamKeyMacCharCodes, typeChar, 0, sizeof(chr), 0, &chr);
if(!chr || chr >= 128 || (text.length() > 0 && (text.length() > 1 || text.at(0) != QLatin1Char(chr))))
handled_event = !widget->testAttribute(Qt::WA_InputMethodEnabled);
+ QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
+ if (context && context->lastKeydownEvent()) {
+ qt_keymapper_private()->translateKeyEvent(widget, 0, context->lastKeydownEvent(),
+ 0, false);
+ context->setLastKeydownEvent(0);
+ }
}
break; }
default:
diff --git a/src/gui/inputmethod/qmacinputcontext_p.h b/src/gui/inputmethod/qmacinputcontext_p.h
index f708040..c3f245a 100644
--- a/src/gui/inputmethod/qmacinputcontext_p.h
+++ b/src/gui/inputmethod/qmacinputcontext_p.h
@@ -78,6 +78,10 @@ public:
static OSStatus globalEventProcessor(EventHandlerCallRef, EventRef, void *);
static void initialize();
static void cleanup();
+
+ EventRef lastKeydownEvent() { return keydownEvent; }
+ void setLastKeydownEvent(EventRef);
+
protected:
void mouseHandler(int pos, QMouseEvent *);
private:
@@ -85,6 +89,7 @@ private:
bool recursionGuard;
TSMDocumentID textDocument;
QString currentText;
+ EventRef keydownEvent;
};
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qwininputcontext_p.h b/src/gui/inputmethod/qwininputcontext_p.h
index 38d7e32..c6ad19e 100644
--- a/src/gui/inputmethod/qwininputcontext_p.h
+++ b/src/gui/inputmethod/qwininputcontext_p.h
@@ -83,6 +83,7 @@ public:
static void TranslateMessage(const MSG *msg);
static LRESULT DefWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
+ static void updateImeStatus(QWidget *w, bool hasFocus);
static void enablePopupChild(QWidget *w, bool e);
static void enable(QWidget *w, bool e);
diff --git a/src/gui/inputmethod/qwininputcontext_win.cpp b/src/gui/inputmethod/qwininputcontext_win.cpp
index d670f5a..11ee2f2 100644
--- a/src/gui/inputmethod/qwininputcontext_win.cpp
+++ b/src/gui/inputmethod/qwininputcontext_win.cpp
@@ -59,7 +59,7 @@
#include "qdebug.h"
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
extern void qt_wince_show_SIP(bool show); // defined in qguifunctions_wince.cpp
#endif
@@ -237,7 +237,7 @@ QWinInputContext::QWinInputContext(QObject *parent)
aimmpump->Start();
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
QSysInfo::WinVersion ver = QSysInfo::windowsVersion();
if (ver & QSysInfo::WV_NT_based && ver >= QSysInfo::WV_VISTA) {
// Since the IsValidLanguageGroup/IsValidLocale functions always return true on
@@ -349,7 +349,7 @@ static LONG getCompositionString(HIMC himc, DWORD dwIndex, LPVOID lpbuf, DWORD d
if(QSysInfo::WindowsVersion != QSysInfo::WV_95) {
len = ImmGetCompositionStringW(himc, dwIndex, lpbuf, dBufLen);
}
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
else {
len = ImmGetCompositionStringA(himc, dwIndex, lpbuf, dBufLen);
if (unicode)
@@ -539,7 +539,7 @@ bool QWinInputContext::endComposition()
}
if (!fw)
- fw = qApp->focusWidget();
+ fw = QApplication::focusWidget();
if (fw) {
QInputMethodEvent e;
@@ -637,7 +637,7 @@ bool QWinInputContext::composition(LPARAM lParam)
// bogus event
return true;
- QWidget *fw = qApp->focusWidget();
+ QWidget *fw = QApplication::focusWidget();
if (fw) {
Q_ASSERT(fw->testAttribute(Qt::WA_WState_Created));
HIMC imc = getContext(fw->effectiveWinId());
@@ -738,7 +738,7 @@ inline void enableIme(QWidget *w, bool value)
// enable ime
if (defaultContext)
ImmAssociateContext(w->effectiveWinId(), defaultContext);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qApp->autoSipEnabled())
qt_wince_show_SIP(true);
#endif
@@ -747,7 +747,7 @@ inline void enableIme(QWidget *w, bool value)
HIMC oldimc = ImmAssociateContext(w->effectiveWinId(), 0);
if (!defaultContext)
defaultContext = oldimc;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qApp->autoSipEnabled())
qt_wince_show_SIP(false);
#endif
@@ -755,7 +755,7 @@ inline void enableIme(QWidget *w, bool value)
}
-void QInputContextPrivate::updateImeStatus(QWidget *w, bool hasFocus)
+void QWinInputContext::updateImeStatus(QWidget *w, bool hasFocus)
{
if (!w)
return;
@@ -829,6 +829,15 @@ void QWinInputContext::enable(QWidget *w, bool e)
void QWinInputContext::setFocusWidget(QWidget *w)
{
+ QWidget *oldFocus = focusWidget();
+ if (oldFocus == w)
+ return;
+ if (w) {
+ QWinInputContext::updateImeStatus(w, true);
+ } else {
+ if (oldFocus)
+ QWinInputContext::updateImeStatus(oldFocus , false);
+ }
QInputContext::setFocusWidget(w);
update();
}
diff --git a/src/gui/inputmethod/qwsinputcontext_p.h b/src/gui/inputmethod/qwsinputcontext_p.h
index 20811da..835cb3f 100644
--- a/src/gui/inputmethod/qwsinputcontext_p.h
+++ b/src/gui/inputmethod/qwsinputcontext_p.h
@@ -87,6 +87,7 @@ public:
static bool translateIMEvent(QWidget *w, const QWSIMEvent *e);
static bool translateIMQueryEvent(QWidget *w, const QWSIMQueryEvent *e);
static bool translateIMInitEvent(const QWSIMInitEvent *e);
+ static void updateImeStatus(QWidget *w, bool hasFocus);
};
QT_END_NAMESPACE
diff --git a/src/gui/inputmethod/qwsinputcontext_qws.cpp b/src/gui/inputmethod/qwsinputcontext_qws.cpp
index 46ac13d..6180c48 100644
--- a/src/gui/inputmethod/qwsinputcontext_qws.cpp
+++ b/src/gui/inputmethod/qwsinputcontext_qws.cpp
@@ -73,10 +73,17 @@ void QWSInputContext::reset()
void QWSInputContext::setFocusWidget( QWidget *w )
{
- QWidget *oldFocus = focusWidget();
+ QWidget *oldFocus = focusWidget();
if (oldFocus == w)
return;
+ if (w) {
+ QWSInputContext::updateImeStatus(w, true);
+ } else {
+ if (oldFocus)
+ QWSInputContext::updateImeStatus(oldFocus, false);
+ }
+
if (oldFocus) {
QWidget *tlw = oldFocus->window();
int winid = tlw->internalWinId();
@@ -224,7 +231,7 @@ bool QWSInputContext::translateIMEvent(QWidget *w, const QWSIMEvent *e)
Q_GUI_EXPORT void (*qt_qws_inputMethodStatusChanged)(QWidget*) = 0;
-void QInputContextPrivate::updateImeStatus(QWidget *w, bool hasFocus)
+void QWSInputContext::updateImeStatus(QWidget *w, bool hasFocus)
{
Q_UNUSED(hasFocus);
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index 60ea15b..c1eccd5 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -438,7 +438,8 @@ void QXIMInputContext::create_xim()
// server (like SCIM) has been launched without
// requiring the user to manually switch focus.
if (focusWidget->testAttribute(Qt::WA_InputMethodEnabled)
- && focusWidget->testAttribute(Qt::WA_WState_Created))
+ && focusWidget->testAttribute(Qt::WA_WState_Created)
+ && focusWidget->isEnabled())
setFocusWidget(focusWidget);
}
// following code fragment is not required for immodule
diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp
index 2576724..3e85b67 100644
--- a/src/gui/itemviews/qabstractitemview.cpp
+++ b/src/gui/itemviews/qabstractitemview.cpp
@@ -109,16 +109,16 @@ void QAbstractItemViewPrivate::init()
Q_Q(QAbstractItemView);
q->setItemDelegate(new QStyledItemDelegate(q));
- q->verticalScrollBar()->setRange(0, 0);
- q->horizontalScrollBar()->setRange(0, 0);
+ vbar->setRange(0, 0);
+ hbar->setRange(0, 0);
- QObject::connect(q->verticalScrollBar(), SIGNAL(actionTriggered(int)),
+ QObject::connect(vbar, SIGNAL(actionTriggered(int)),
q, SLOT(verticalScrollbarAction(int)));
- QObject::connect(q->horizontalScrollBar(), SIGNAL(actionTriggered(int)),
+ QObject::connect(hbar, SIGNAL(actionTriggered(int)),
q, SLOT(horizontalScrollbarAction(int)));
- QObject::connect(q->verticalScrollBar(), SIGNAL(valueChanged(int)),
+ QObject::connect(vbar, SIGNAL(valueChanged(int)),
q, SLOT(verticalScrollbarValueChanged(int)));
- QObject::connect(q->horizontalScrollBar(), SIGNAL(valueChanged(int)),
+ QObject::connect(hbar, SIGNAL(valueChanged(int)),
q, SLOT(horizontalScrollbarValueChanged(int)));
viewport->setBackgroundRole(QPalette::Base);
@@ -1427,10 +1427,10 @@ bool QAbstractItemView::viewportEvent(QEvent *event)
case QEvent::HoverEnter: {
QHoverEvent *he = static_cast<QHoverEvent*>(event);
d->hover = indexAt(he->pos());
- d->viewport->update(visualRect(d->hover));
+ update(d->hover);
break; }
case QEvent::HoverLeave: {
- d->viewport->update(visualRect(d->hover)); // update old
+ update(d->hover); // update old
d->hover = QModelIndex();
break; }
case QEvent::HoverMove: {
@@ -1643,7 +1643,7 @@ void QAbstractItemView::mouseReleaseEvent(QMouseEvent *event)
if (d->isIndexValid(index)
&& d->isIndexEnabled(index)
&& d->sendDelegateEvent(index, event))
- d->viewport->update(visualRect(index));
+ update(index);
return;
}
@@ -2169,11 +2169,12 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
}
#endif
bool modified = (event->modifiers() & (Qt::ControlModifier | Qt::AltModifier | Qt::MetaModifier));
- if (!event->text().isEmpty() && !modified) {
- if (!edit(currentIndex(), AnyKeyPressed, event))
- keyboardSearch(event->text());
+ if (!event->text().isEmpty() && !modified && !edit(currentIndex(), AnyKeyPressed, event)) {
+ keyboardSearch(event->text());
+ event->accept();
+ } else {
+ event->ignore();
}
- event->ignore();
break; }
}
}
@@ -2329,7 +2330,7 @@ bool QAbstractItemView::edit(const QModelIndex &index, EditTrigger trigger, QEve
}
if (d->sendDelegateEvent(index, event)) {
- d->viewport->update(visualRect(index));
+ update(index);
return true;
}
@@ -2401,8 +2402,8 @@ void QAbstractItemView::updateEditorGeometries()
//we release the editor outside of the loop because it might change the focus and try
//to change the d->editors list.
- foreach(QWidget *editor, editorsToRelease) {
- d->releaseEditor(editor);
+ for (int i = 0; i < editorsToRelease.count(); ++i) {
+ d->releaseEditor(editorsToRelease.at(i));
}
}
@@ -2848,9 +2849,9 @@ void QAbstractItemView::setIndexWidget(const QModelIndex &index, QWidget *widget
d->persistent.insert(widget);
d->addEditor(index, widget, true);
widget->show();
+ dataChanged(index, index); // update the geometry
if (!d->delayedPendingLayout)
widget->setGeometry(visualRect(index));
- dataChanged(index, index); // update the geometry
}
}
@@ -2930,7 +2931,7 @@ void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelInde
}
if (isVisible() && !d->delayedPendingLayout) {
// otherwise the items will be update later anyway
- d->viewport->update(visualRect(topLeft));
+ update(topLeft);
}
return;
}
@@ -3135,9 +3136,7 @@ void QAbstractItemView::selectionChanged(const QItemSelection &selected,
{
Q_D(QAbstractItemView);
if (isVisible() && updatesEnabled()) {
- d->setDirtyRegion(visualRegionForSelection(deselected));
- d->setDirtyRegion(visualRegionForSelection(selected));
- d->updateDirtyRegion();
+ d->viewport->update(visualRegionForSelection(deselected) | visualRegionForSelection(selected));
}
}
@@ -3165,16 +3164,15 @@ void QAbstractItemView::currentChanged(const QModelIndex &current, const QModelI
closeEditor(editor, QAbstractItemDelegate::NoHint);
}
if (isVisible()) {
- d->setDirtyRegion(visualRect(previous));
- d->updateDirtyRegion();
+ update(previous);
}
}
+
if (current.isValid() && !d->autoScrollTimer.isActive()) {
if (isVisible()) {
if (d->autoScroll)
scrollTo(current);
- d->setDirtyRegion(visualRect(current));
- d->updateDirtyRegion();
+ update(current);
edit(current, CurrentChanged, 0);
if (current.row() == (d->model->rowCount(d->root) - 1))
d->_q_fetchMore();
@@ -3790,7 +3788,7 @@ void QAbstractItemViewPrivate::clearOrRemove()
void QAbstractItemViewPrivate::checkPersistentEditorFocus()
{
Q_Q(QAbstractItemView);
- if (QWidget *widget = qApp->focusWidget()) {
+ if (QWidget *widget = QApplication::focusWidget()) {
if (persistent.contains(widget)) {
//a persistent editor has gained the focus
QModelIndex index = indexForEditor(widget);
diff --git a/src/gui/itemviews/qabstractitemview_p.h b/src/gui/itemviews/qabstractitemview_p.h
index c4bf4db..1d2a233 100644
--- a/src/gui/itemviews/qabstractitemview_p.h
+++ b/src/gui/itemviews/qabstractitemview_p.h
@@ -99,7 +99,7 @@ public:
QVariant data(const QModelIndex &, int) const { return QVariant(); }
};
-class Q_GUI_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate
+class Q_AUTOTEST_EXPORT QAbstractItemViewPrivate : public QAbstractScrollAreaPrivate
{
Q_DECLARE_PUBLIC(QAbstractItemView)
diff --git a/src/gui/itemviews/qcolumnview.cpp b/src/gui/itemviews/qcolumnview.cpp
index 4fb08bb..16ae8e9 100644
--- a/src/gui/itemviews/qcolumnview.cpp
+++ b/src/gui/itemviews/qcolumnview.cpp
@@ -108,9 +108,9 @@ void QColumnViewPrivate::initialize()
{
Q_Q(QColumnView);
q->setTextElideMode(Qt::ElideMiddle);
- q->connect(&currentAnimation, SIGNAL(frameChanged(int)),
- q->horizontalScrollBar(), SLOT(setValue(int)));
- q->connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
+ QObject::connect(&currentAnimation, SIGNAL(frameChanged(int)),
+ hbar, SLOT(setValue(int)));
+ QObject::connect(&currentAnimation, SIGNAL(finished()), q, SLOT(_q_changeCurrentColumn()));
delete itemDelegate;
q->setItemDelegate(new QColumnViewDelegate(q));
}
@@ -421,23 +421,23 @@ void QColumnViewPrivate::updateScrollbars()
horizontalLength = (columns.first()->x() + columns.first()->width()) - columns.last()->x();
}
- QSize viewportSize = q->viewport()->size();
- if (horizontalLength < viewportSize.width() && q->horizontalScrollBar()->value() == 0) {
- q->horizontalScrollBar()->setRange(0, 0);
+ QSize viewportSize = viewport->size();
+ if (horizontalLength < viewportSize.width() && hbar->value() == 0) {
+ hbar->setRange(0, 0);
} else {
int visibleLength = qMin(horizontalLength + q->horizontalOffset(), viewportSize.width());
int hiddenLength = horizontalLength - visibleLength;
- if (hiddenLength != q->horizontalScrollBar()->maximum())
- q->horizontalScrollBar()->setRange(0, hiddenLength);
+ if (hiddenLength != hbar->maximum())
+ hbar->setRange(0, hiddenLength);
}
if (!columns.isEmpty()) {
int pageStepSize = columns.at(0)->width();
- if (pageStepSize != q->horizontalScrollBar()->pageStep())
- q->horizontalScrollBar()->setPageStep(pageStepSize);
+ if (pageStepSize != hbar->pageStep())
+ hbar->setPageStep(pageStepSize);
}
- bool visible = (q->horizontalScrollBar()->maximum() > 0);
- if (visible != q->horizontalScrollBar()->isVisible())
- q->horizontalScrollBar()->setVisible(visible);
+ bool visible = (hbar->maximum() > 0);
+ if (visible != hbar->isVisible())
+ hbar->setVisible(visible);
}
/*!
@@ -696,7 +696,7 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
q, SIGNAL(pressed(const QModelIndex &)));
view->setFocusPolicy(Qt::NoFocus);
- view->setParent(q->viewport());
+ view->setParent(viewport);
Q_ASSERT(view);
// Setup corner grip
@@ -707,13 +707,13 @@ QAbstractItemView *QColumnViewPrivate::createColumn(const QModelIndex &index, bo
}
if (columnSizes.count() > columns.count()) {
- view->setGeometry(0, 0, columnSizes.at(columns.count()), q->viewport()->height());
+ view->setGeometry(0, 0, columnSizes.at(columns.count()), viewport->height());
} else {
int initialWidth = view->sizeHint().width();
if (q->isRightToLeft())
- view->setGeometry(q->viewport()->width() - initialWidth, 0, initialWidth, q->viewport()->height());
+ view->setGeometry(viewport->width() - initialWidth, 0, initialWidth, viewport->height());
else
- view->setGeometry(0, 0, initialWidth, q->viewport()->height());
+ view->setGeometry(0, 0, initialWidth, viewport->height());
columnSizes.resize(qMax(columnSizes.count(), columns.count() + 1));
columnSizes[columns.count()] = initialWidth;
}
@@ -1056,11 +1056,11 @@ void QColumnViewPrivate::doLayout()
if (!model || columns.isEmpty())
return;
- int viewportHeight = q->viewport()->height();
+ int viewportHeight = viewport->height();
int x = columns.at(0)->x();
if (q->isRightToLeft()) {
- x = q->viewport()->width() + q->horizontalOffset();
+ x = viewport->width() + q->horizontalOffset();
for (int i = 0; i < columns.size(); ++i) {
QAbstractItemView *view = columns.at(i);
x -= view->width();
@@ -1116,7 +1116,7 @@ void QColumnViewDelegate::paint(QPainter *painter,
// Draw >
if (index.model()->hasChildren(index)) {
const QWidget *view = opt.widget;
- QStyle *style = view ? view->style() : qApp->style();
+ QStyle *style = view ? view->style() : QApplication::style();
style->drawPrimitive(QStyle::PE_IndicatorColumnViewArrow, &opt, painter, view);
}
}
diff --git a/src/gui/itemviews/qdirmodel.cpp b/src/gui/itemviews/qdirmodel.cpp
index a82ffd9..2596e8c 100644
--- a/src/gui/itemviews/qdirmodel.cpp
+++ b/src/gui/itemviews/qdirmodel.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_DIRMODEL
#include <qstack.h>
#include <qfile.h>
+#include <qfilesystemmodel.h>
#include <qurl.h>
#include <qmime.h>
#include <qpair.h>
@@ -1340,14 +1341,14 @@ QString QDirModelPrivate::size(const QModelIndex &index) const
const quint64 tb = 1024 * gb;
quint64 bytes = n->info.size();
if (bytes >= tb)
- return QLocale().toString(bytes / tb) + QString::fromLatin1(" TB");
+ return QFileSystemModel::tr("%1 TB").arg(QLocale().toString(qreal(bytes) / tb, 'f', 3));
if (bytes >= gb)
- return QLocale().toString(bytes / gb) + QString::fromLatin1(" GB");
+ return QFileSystemModel::tr("%1 GB").arg(QLocale().toString(qreal(bytes) / gb, 'f', 2));
if (bytes >= mb)
- return QLocale().toString(bytes / mb) + QString::fromLatin1(" MB");
+ return QFileSystemModel::tr("%1 MB").arg(QLocale().toString(qreal(bytes) / mb, 'f', 1));
if (bytes >= kb)
- return QLocale().toString(bytes / kb) + QString::fromLatin1(" KB");
- return QLocale().toString(bytes) + QString::fromLatin1(" bytes");
+ return QFileSystemModel::tr("%1 KB").arg(QLocale().toString(bytes / kb));
+ return QFileSystemModel::tr("%1 bytes").arg(QLocale().toString(bytes));
}
QString QDirModelPrivate::type(const QModelIndex &index) const
diff --git a/src/gui/itemviews/qfileiconprovider.cpp b/src/gui/itemviews/qfileiconprovider.cpp
index af4d42a..9a97c2a 100644
--- a/src/gui/itemviews/qfileiconprovider.cpp
+++ b/src/gui/itemviews/qfileiconprovider.cpp
@@ -214,8 +214,7 @@ QIcon QFileIconProvider::icon(IconType type) const
QIcon QFileIconProviderPrivate::getWinIcon(const QFileInfo &fileInfo) const
{
QIcon retIcon;
- QString fileExtension = fileInfo.suffix().toUpper();
- fileExtension.prepend( QLatin1String(".") );
+ const QString fileExtension = QLatin1Char('.') + fileInfo.suffix().toUpper();
QString key;
if (fileInfo.isFile() && !fileInfo.isExecutable() && !fileInfo.isSymLink())
@@ -355,7 +354,7 @@ QIcon QFileIconProvider::icon(const QFileInfo &info) const
return icon;
#endif
if (info.isRoot())
-#if defined (Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined (Q_WS_WIN) && !defined(Q_WS_WINCE)
{
uint type = DRIVE_UNKNOWN;
QT_WA({ type = GetDriveTypeW((wchar_t *)info.absoluteFilePath().utf16()); },
@@ -415,26 +414,22 @@ QString QFileIconProvider::type(const QFileInfo &info) const
}
if (info.isDir())
- return QApplication::translate("QFileDialog",
#ifdef Q_WS_WIN
- "File Folder", "Match Windows Explorer"
+ return QApplication::translate("QFileDialog", "File Folder", "Match Windows Explorer");
#else
- "Folder", "All other platforms"
+ return QApplication::translate("QFileDialog", "Folder", "All other platforms");
#endif
- );
// Windows - "File Folder"
// OS X - "Folder"
// Konqueror - "Folder"
// Nautilus - "folder"
if (info.isSymLink())
- return QApplication::translate("QFileDialog",
#ifdef Q_OS_MAC
- "Alias", "Mac OS X Finder"
+ return QApplication::translate("QFileDialog", "Alias", "Mac OS X Finder");
#else
- "Shortcut", "All other platforms"
+ return QApplication::translate("QFileDialog", "Shortcut", "All other platforms");
#endif
- );
// OS X - "Alias"
// Windows - "Shortcut"
// Konqueror - "Folder" or "TXT File" i.e. what it is pointing to
diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp
index f888f5f..b437119 100644
--- a/src/gui/itemviews/qheaderview.cpp
+++ b/src/gui/itemviews/qheaderview.cpp
@@ -62,9 +62,11 @@
#ifndef QT_NO_DATASTREAM
#include <qdatastream.h>
+#endif
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &out, const QHeaderViewPrivate::SectionSpan &span)
{
span.write(out);
@@ -76,7 +78,7 @@ QDataStream &operator>>(QDataStream &in, QHeaderViewPrivate::SectionSpan &span)
span.read(in);
return in;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
@@ -1151,7 +1153,8 @@ void QHeaderView::setResizeMode(ResizeMode mode)
\overload
Sets the constraints on how the section specified by \a logicalIndex in
- the header can be resized to those described by the given \a mode.
+ the header can be resized to those described by the given \a mode. The logical
+ index should exist at the time this function is called.
\note This setting will be ignored for the last section if the stretchLastSection
property is set to true. This is the default for the horizontal headers provided
@@ -1195,7 +1198,7 @@ QHeaderView::ResizeMode QHeaderView::resizeMode(int logicalIndex) const
Q_D(const QHeaderView);
int visual = visualIndex(logicalIndex);
Q_ASSERT(visual != -1);
- return d->visualIndexResizeMode(visual);
+ return d->headerSectionResizeMode(visual);
}
/*!
@@ -1234,7 +1237,7 @@ void QHeaderView::setSortIndicatorShown(bool show)
if (sortIndicatorSection() < 0 || sortIndicatorSection() > count())
return;
- if (d->visualIndexResizeMode(sortIndicatorSection()) == ResizeToContents)
+ if (d->headerSectionResizeMode(sortIndicatorSection()) == ResizeToContents)
resizeSections();
d->viewport->update();
@@ -1535,7 +1538,7 @@ bool QHeaderView::restoreState(const QByteArray &state)
}
return false;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
\reimp
@@ -1969,20 +1972,19 @@ void QHeaderView::currentChanged(const QModelIndex &current, const QModelIndex &
if (d->orientation == Qt::Horizontal && current.column() != old.column()) {
if (old.isValid() && old.parent() == d->root)
- d->setDirtyRegion(QRect(sectionViewportPosition(old.column()), 0,
+ d->viewport->update(QRect(sectionViewportPosition(old.column()), 0,
sectionSize(old.column()), d->viewport->height()));
if (current.isValid() && current.parent() == d->root)
- d->setDirtyRegion(QRect(sectionViewportPosition(current.column()), 0,
+ d->viewport->update(QRect(sectionViewportPosition(current.column()), 0,
sectionSize(current.column()), d->viewport->height()));
} else if (d->orientation == Qt::Vertical && current.row() != old.row()) {
if (old.isValid() && old.parent() == d->root)
- d->setDirtyRegion(QRect(0, sectionViewportPosition(old.row()),
+ d->viewport->update(QRect(0, sectionViewportPosition(old.row()),
d->viewport->width(), sectionSize(old.row())));
if (current.isValid() && current.parent() == d->root)
- d->setDirtyRegion(QRect(0, sectionViewportPosition(current.row()),
+ d->viewport->update(QRect(0, sectionViewportPosition(current.row()),
d->viewport->width(), sectionSize(current.row())));
}
- d->updateDirtyRegion();
}
@@ -2936,22 +2938,25 @@ int QHeaderViewPrivate::lastVisibleVisualIndex() const
void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool useGlobalMode)
{
Q_Q(QHeaderView);
+ //stop the timer in case it is delayed
+ delayedResize.stop();
executePostedLayout();
if (sectionCount == 0)
return;
+
+ if (resizeRecursionBlock)
+ return;
+ resizeRecursionBlock = true;
+
invalidateCachedSizeHint();
+ const int lastVisibleSection = lastVisibleVisualIndex();
+
// find stretchLastSection if we have it
int stretchSection = -1;
- if (stretchLastSection && !useGlobalMode) {
- for (int i = sectionCount - 1; i >= 0; --i) {
- if (!isVisualIndexHidden(i)) {
- stretchSection = i;
- break;
- }
- }
- }
+ if (stretchLastSection && !useGlobalMode)
+ stretchSection = lastVisibleVisualIndex();
// count up the number of strected sections and how much space left for them
int lengthToStrech = (orientation == Qt::Horizontal ? viewport->width() : viewport->height());
@@ -2965,7 +2970,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
if (useGlobalMode && (i != stretchSection))
resizeMode = globalMode;
else
- resizeMode = (i == stretchSection ? QHeaderView::Stretch : visualIndexResizeMode(i));
+ resizeMode = (i == stretchSection ? QHeaderView::Stretch : headerSectionResizeMode(i));
if (resizeMode == QHeaderView::Stretch) {
++numberOfStretchedSections;
@@ -2997,7 +3002,6 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
int spanStartSection = 0;
int previousSectionLength = 0;
- const int lastVisibleSection = lastVisibleVisualIndex();
QHeaderView::ResizeMode previousSectionResizeMode = QHeaderView::Interactive;
@@ -3016,7 +3020,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
else
resizeMode = (i == stretchSection
? QHeaderView::Stretch
- : visualIndexResizeMode(i));
+ : newSectionResizeMode);
if (resizeMode == QHeaderView::Stretch && stretchSectionLength != -1) {
if (i == lastVisibleSection)
newSectionLength = qMax(stretchSectionLength, lastSectionSize);
@@ -3053,7 +3057,7 @@ void QHeaderViewPrivate::resizeSections(QHeaderView::ResizeMode globalMode, bool
(sectionCount - spanStartSection) * previousSectionLength,
previousSectionResizeMode);
//Q_ASSERT(headerLength() == length);
-
+ resizeRecursionBlock = false;
viewport->update();
}
@@ -3470,11 +3474,10 @@ void QHeaderViewPrivate::setGlobalHeaderResizeMode(QHeaderView::ResizeMode mode)
int QHeaderViewPrivate::viewSectionSizeHint(int logical) const
{
- Q_Q(const QHeaderView);
- if (QAbstractItemView *parent = qobject_cast<QAbstractItemView*>(q->parent())) {
+ if (QAbstractItemView *view = qobject_cast<QAbstractItemView*>(parent)) {
return (orientation == Qt::Horizontal
- ? parent->sizeHintForColumn(logical)
- : parent->sizeHintForRow(logical));
+ ? view->sizeHintForColumn(logical)
+ : view->sizeHintForRow(logical));
}
return 0;
}
@@ -3570,9 +3573,9 @@ bool QHeaderViewPrivate::read(QDataStream &in)
return true;
}
-QT_END_NAMESPACE
+#endif // QT_NO_DATASTREAM
-#endif // QT_NO_DATASTREAEM
+QT_END_NAMESPACE
#endif // QT_NO_ITEMVIEWS
diff --git a/src/gui/itemviews/qheaderview_p.h b/src/gui/itemviews/qheaderview_p.h
index 2889f08..cfb1c3e 100644
--- a/src/gui/itemviews/qheaderview_p.h
+++ b/src/gui/itemviews/qheaderview_p.h
@@ -90,6 +90,7 @@ public:
highlightSelected(false),
stretchLastSection(false),
cascadingResizing(false),
+ resizeRecursionBlock(false),
stretchSections(0),
contentsSections(0),
minimumSectionSize(-1),
@@ -169,10 +170,6 @@ public:
if (!sectionHidden.isEmpty()) sectionHidden.setBit(visual, hidden);
}
- inline QHeaderView::ResizeMode visualIndexResizeMode(int visual) const {
- return headerSectionResizeMode(visual);
- }
-
inline bool hasAutoResizeSections() const {
return stretchSections || stretchLastSection || contentsSections;
}
@@ -210,7 +207,7 @@ public:
}
inline bool sectionIsCascadable(int visual) const {
- return visualIndexResizeMode(visual) == QHeaderView::Interactive;
+ return headerSectionResizeMode(visual) == QHeaderView::Interactive;
}
inline int modelSectionCount() const {
@@ -230,7 +227,6 @@ public:
inline void executePostedResize() const {
if (delayedResize.isActive() && state == NoState) {
- delayedResize.stop();
const_cast<QHeaderView*>(q_func())->resizeSections();
}
}
@@ -274,6 +270,7 @@ public:
bool highlightSelected;
bool stretchLastSection;
bool cascadingResizing;
+ bool resizeRecursionBlock;
int stretchSections;
int contentsSections;
int defaultSectionSize;
diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp
index 8baefdf..696b8fa 100644
--- a/src/gui/itemviews/qitemselectionmodel.cpp
+++ b/src/gui/itemviews/qitemselectionmodel.cpp
@@ -1553,7 +1553,7 @@ QDebug operator<<(QDebug dbg, const QItemSelectionRange &range)
{
#ifndef Q_BROKEN_DEBUG_STREAM
dbg.nospace() << "QItemSelectionRange(" << range.topLeft()
- << "," << range.bottomRight() << ")";
+ << ',' << range.bottomRight() << ')';
return dbg.space();
#else
qWarning("This compiler doesn't support streaming QItemSelectionRange to QDebug");
diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp
index 48f53a0..fe7916c 100644
--- a/src/gui/itemviews/qlistview.cpp
+++ b/src/gui/itemviews/qlistview.cpp
@@ -588,7 +588,7 @@ void QListView::scrollTo(const QModelIndex &index, ScrollHint hint)
const QRect rect = visualRect(index);
if (hint == EnsureVisible && d->viewport->rect().contains(rect)) {
- d->setDirtyRegion(rect);
+ d->viewport->update(rect);
return;
}
@@ -610,7 +610,7 @@ int QListViewPrivate::horizontalScrollToValue(const QModelIndex &index, const QR
const bool rightOf = q->isRightToLeft()
? rect.right() > area.right()
: (rect.right() > area.right()) && (rect.left() > area.left());
- int horizontalValue = q->horizontalScrollBar()->value();
+ int horizontalValue = hbar->value();
// ScrollPerItem
if (q->horizontalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
@@ -652,10 +652,10 @@ int QListViewPrivate::verticalScrollToValue(const QModelIndex &index, const QRec
const bool above = (hint == QListView::EnsureVisible && rect.top() < area.top());
const bool below = (hint == QListView::EnsureVisible && rect.bottom() > area.bottom());
- int verticalValue = q->verticalScrollBar()->value();
+ int verticalValue = vbar->value();
// ScrollPerItem
- if (q->verticalScrollMode() == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
+ if (verticalScrollMode == QAbstractItemView::ScrollPerItem && viewMode == QListView::ListMode) {
const QListViewItem item = indexToListViewItem(index);
const QRect rect = q->visualRect(index);
verticalValue = staticListView->verticalPerItemValue(itemIndex(item),
@@ -755,7 +755,7 @@ void QListView::scrollContentsBy(int dx, int dy)
// update the dragged items
if (d->viewMode == IconMode) // ### move to dynamic class
if (!d->dynamicListView->draggedItems.isEmpty())
- d->setDirtyRegion(d->dynamicListView->draggedItemsRect().translated(dx, dy));
+ d->viewport->update(d->dynamicListView->draggedItemsRect().translated(dx, dy));
}
/*!
@@ -835,7 +835,7 @@ void QListView::mouseMoveEvent(QMouseEvent *e)
&& d->selectionMode != NoSelection) {
QRect rect(d->pressedPosition, e->pos() + QPoint(horizontalOffset(), verticalOffset()));
rect = rect.normalized();
- d->setDirtyRegion(d->mapToViewport(rect.united(d->elasticBand), d->viewMode == QListView::ListMode));
+ d->viewport->update(d->mapToViewport(rect.united(d->elasticBand), d->viewMode == QListView::ListMode));
d->elasticBand = rect;
}
}
@@ -849,7 +849,7 @@ void QListView::mouseReleaseEvent(QMouseEvent *e)
QAbstractItemView::mouseReleaseEvent(e);
// #### move this implementation into a dynamic class
if (d->showElasticBand && d->elasticBand.isValid()) {
- d->setDirtyRegion(d->mapToViewport(d->elasticBand, d->viewMode == QListView::ListMode));
+ d->viewport->update(d->mapToViewport(d->elasticBand, d->viewMode == QListView::ListMode));
d->elasticBand = QRect();
}
}
@@ -914,11 +914,11 @@ void QListView::dragMoveEvent(QDragMoveEvent *e)
if (d->canDecode(e)) {
// get old dragged items rect
QRect itemsRect = d->dynamicListView->itemsRect(d->dynamicListView->draggedItems);
- d->setDirtyRegion(itemsRect.translated(d->dynamicListView->draggedItemsDelta()));
+ d->viewport->update(itemsRect.translated(d->dynamicListView->draggedItemsDelta()));
// update position
d->dynamicListView->draggedItemsPos = e->pos();
// get new items rect
- d->setDirtyRegion(itemsRect.translated(d->dynamicListView->draggedItemsDelta()));
+ d->viewport->update(itemsRect.translated(d->dynamicListView->draggedItemsDelta()));
// set the item under the cursor to current
QModelIndex index;
if (d->movement == Snap) {
@@ -1007,12 +1007,12 @@ void QListView::internalDrop(QDropEvent *event)
for (int i = 0; i < indexes.count(); ++i) {
QModelIndex index = indexes.at(i);
QRect rect = rectForIndex(index);
- d->setDirtyRegion(d->mapToViewport(rect, d->viewMode == QListView::ListMode));
+ d->viewport->update(d->mapToViewport(rect, d->viewMode == QListView::ListMode));
QPoint dest = rect.topLeft() + delta;
if (isRightToLeft())
dest.setX(d->flipX(dest.x()) - rect.width());
d->dynamicListView->moveItem(index.row(), dest);
- d->setDirtyRegion(visualRect(index));
+ update(index);
}
stopAutoScroll();
d->dynamicListView->draggedItems.clear();
@@ -1100,14 +1100,8 @@ void QListView::paintEvent(QPaintEvent *e)
QPainter painter(d->viewport);
QRect area = e->rect();
- QVector<QModelIndex> toBeRendered;
-// QVector<QRect> rects = e->region().rects();
-// for (int i = 0; i < rects.size(); ++i) {
-// d->intersectingSet(rects.at(i).translated(horizontalOffset(), verticalOffset()));
-// toBeRendered += d->intersectVector;
-// }
d->intersectingSet(e->rect().translated(horizontalOffset(), verticalOffset()), false);
- toBeRendered = d->intersectVector;
+ const QVector<QModelIndex> toBeRendered = d->intersectVector;
const QModelIndex current = currentIndex();
const QModelIndex hover = d->hover;
@@ -1455,9 +1449,9 @@ void QListView::setPositionForIndex(const QPoint &position, const QModelIndex &i
if (index.row() >= d->dynamicListView->items.count())
return;
const QSize oldContents = d->contentsSize();
- d->setDirtyRegion(visualRect(index)); // update old position
+ update(index); // update old position
d->dynamicListView->moveItem(index.row(), position);
- d->setDirtyRegion(visualRect(index)); // update new position
+ update(index); // update new position
if (d->contentsSize() != oldContents)
updateGeometries(); // update the scroll bars
@@ -1608,6 +1602,10 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
if (!selection.at(i).isValid())
continue;
QModelIndex parent = selection.at(i).topLeft().parent();
+ //we only display the children of the root in a listview
+ //we're not interested in the other model indexes
+ if (parent != d->root)
+ continue;
int t = selection.at(i).topLeft().row();
int b = selection.at(i).bottomRight().row();
if (d->viewMode == IconMode || d->isWrapping()) { // in non-static mode, we have to go through all selected items
@@ -1616,8 +1614,8 @@ QRegion QListView::visualRegionForSelection(const QItemSelection &selection) con
} else { // in static mode, we can optimize a bit
while (t <= b && d->isHidden(t)) ++t;
while (b >= t && d->isHidden(b)) --b;
- const QModelIndex top = d->model->index(t, c, d->root);
- const QModelIndex bottom = d->model->index(b, c, d->root);
+ const QModelIndex top = d->model->index(t, c, parent);
+ const QModelIndex bottom = d->model->index(b, c, parent);
QRect rect(visualRect(top).topLeft(),
visualRect(bottom).bottomRight());
selectionRegion += QRegion(rect);
@@ -1969,10 +1967,16 @@ void QListViewPrivate::prepareItemsLayout()
int frameAroundContents = 0;
if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents))
frameAroundContents = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth) * 2;
- int verticalMargin = vbarpolicy==Qt::ScrollBarAlwaysOff ? 0 :
- q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->verticalScrollBar()) + frameAroundContents;
- int horizontalMargin = hbarpolicy==Qt::ScrollBarAlwaysOff ? 0 :
- q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, q->horizontalScrollBar()) + frameAroundContents;
+
+ // maximumViewportSize() already takes scrollbar into account if policy is
+ // Qt::ScrollBarAlwaysOn but scrollbar extent must be deduced if policy
+ // is Qt::ScrollBarAsNeeded
+ int verticalMargin = vbarpolicy==Qt::ScrollBarAsNeeded
+ ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, vbar) + frameAroundContents
+ : 0;
+ int horizontalMargin = hbarpolicy==Qt::ScrollBarAsNeeded
+ ? q->style()->pixelMetric(QStyle::PM_ScrollBarExtent, 0, hbar) + frameAroundContents
+ : 0;
layoutBounds.adjust(0, 0, -verticalMargin, -horizontalMargin);
diff --git a/src/gui/itemviews/qlistview_p.h b/src/gui/itemviews/qlistview_p.h
index 4568d8c..6514496 100644
--- a/src/gui/itemviews/qlistview_p.h
+++ b/src/gui/itemviews/qlistview_p.h
@@ -84,7 +84,7 @@ public:
inline bool operator!=(const QListViewItem &other) const
{ return !(*this == other); }
inline bool isValid() const
- { return (x > -1) && (y > -1) && (w > 0) && (h > 0) && (indexHint > -1); }
+ { return rect().isValid() && (indexHint > -1); }
inline void invalidate()
{ x = -1; y = -1; w = 0; h = 0; }
inline void resize(const QSize &size)
diff --git a/src/gui/itemviews/qlistwidget.cpp b/src/gui/itemviews/qlistwidget.cpp
index bf3b43c..51861b3 100644
--- a/src/gui/itemviews/qlistwidget.cpp
+++ b/src/gui/itemviews/qlistwidget.cpp
@@ -687,7 +687,10 @@ QVariant QListWidgetItem::data(int role) const
*/
bool QListWidgetItem::operator<(const QListWidgetItem &other) const
{
- return text() < other.text();
+ const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
+ if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2))
+ return v1.toDouble() < v2.toDouble();
+ return v1.toString() < v2.toString();
}
#ifndef QT_NO_DATASTREAM
@@ -711,6 +714,7 @@ void QListWidgetItem::write(QDataStream &out) const
{
out << d->values;
}
+#endif // QT_NO_DATASTREAM
/*!
\since 4.1
@@ -745,6 +749,8 @@ QListWidgetItem &QListWidgetItem::operator=(const QListWidgetItem &other)
return *this;
}
+#ifndef QT_NO_DATASTREAM
+
/*!
\relates QListWidgetItem
@@ -1014,51 +1020,51 @@ void QListWidgetPrivate::setup()
QObject::connect(q, SIGNAL(activated(QModelIndex)),
q, SLOT(_q_emitItemActivated(QModelIndex)));
QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_emitItemChanged(QModelIndex)));
QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_emitCurrentItemChanged(QModelIndex,QModelIndex)));
QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
q, SIGNAL(itemSelectionChanged()));
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
+ QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
}
void QListWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemPressed(model()->at(index.row()));
+ emit q->itemPressed(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemClicked(model()->at(index.row()));
+ emit q->itemClicked(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemDoubleClicked(model()->at(index.row()));
+ emit q->itemDoubleClicked(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemActivated(model()->at(index.row()));
+ emit q->itemActivated(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemEntered(model()->at(index.row()));
+ emit q->itemEntered(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
{
Q_Q(QListWidget);
- emit q->itemChanged(model()->at(index.row()));
+ emit q->itemChanged(listModel()->at(index.row()));
}
void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
@@ -1066,8 +1072,8 @@ void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
{
Q_Q(QListWidget);
QPersistentModelIndex persistentCurrent = current;
- QListWidgetItem *currentItem = model()->at(persistentCurrent.row());
- emit q->currentItemChanged(currentItem, model()->at(previous.row()));
+ QListWidgetItem *currentItem = listModel()->at(persistentCurrent.row());
+ emit q->currentItemChanged(currentItem, listModel()->at(previous.row()));
//persistentCurrent is invalid if something changed the model in response
//to the currentItemChanged signal emission and the item was removed
@@ -1082,14 +1088,14 @@ void QListWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
void QListWidgetPrivate::_q_sort()
{
if (sortingEnabled)
- model()->sort(0, sortOrder);
+ model->sort(0, sortOrder);
}
void QListWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid())
- model()->ensureSorted(topLeft.column(), sortOrder,
+ listModel()->ensureSorted(topLeft.column(), sortOrder,
topLeft.row(), bottomRight.row());
}
@@ -1302,9 +1308,9 @@ QListWidget::~QListWidget()
QListWidgetItem *QListWidget::item(int row) const
{
Q_D(const QListWidget);
- if (row < 0 || row >= d->model()->rowCount())
+ if (row < 0 || row >= d->model->rowCount())
return 0;
- return d->model()->at(row);
+ return d->listModel()->at(row);
}
/*!
@@ -1316,7 +1322,7 @@ QListWidgetItem *QListWidget::item(int row) const
int QListWidget::row(const QListWidgetItem *item) const
{
Q_D(const QListWidget);
- return d->model()->index(const_cast<QListWidgetItem*>(item)).row();
+ return d->listModel()->index(const_cast<QListWidgetItem*>(item)).row();
}
@@ -1330,7 +1336,7 @@ void QListWidget::insertItem(int row, QListWidgetItem *item)
{
Q_D(QListWidget);
if (item && !item->view)
- d->model()->insert(row, item);
+ d->listModel()->insert(row, item);
}
/*!
@@ -1343,7 +1349,7 @@ void QListWidget::insertItem(int row, QListWidgetItem *item)
void QListWidget::insertItem(int row, const QString &label)
{
Q_D(QListWidget);
- d->model()->insert(row, new QListWidgetItem(label));
+ d->listModel()->insert(row, new QListWidgetItem(label));
}
/*!
@@ -1356,7 +1362,7 @@ void QListWidget::insertItem(int row, const QString &label)
void QListWidget::insertItems(int row, const QStringList &labels)
{
Q_D(QListWidget);
- d->model()->insert(row, labels);
+ d->listModel()->insert(row, labels);
}
/*!
@@ -1372,9 +1378,9 @@ void QListWidget::insertItems(int row, const QStringList &labels)
QListWidgetItem *QListWidget::takeItem(int row)
{
Q_D(QListWidget);
- if (row < 0 || row >= d->model()->rowCount())
+ if (row < 0 || row >= d->model->rowCount())
return 0;
- return d->model()->take(row);
+ return d->listModel()->take(row);
}
/*!
@@ -1385,7 +1391,7 @@ QListWidgetItem *QListWidget::takeItem(int row)
int QListWidget::count() const
{
Q_D(const QListWidget);
- return d->model()->rowCount();
+ return d->model->rowCount();
}
/*!
@@ -1394,7 +1400,7 @@ int QListWidget::count() const
QListWidgetItem *QListWidget::currentItem() const
{
Q_D(const QListWidget);
- return d->model()->at(currentIndex().row());
+ return d->listModel()->at(currentIndex().row());
}
@@ -1432,7 +1438,7 @@ int QListWidget::currentRow() const
void QListWidget::setCurrentRow(int row)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(row);
+ QModelIndex index = d->listModel()->index(row);
if (d->selectionMode == SingleSelection)
selectionModel()->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
else if (d->selectionMode == NoSelection)
@@ -1449,7 +1455,7 @@ void QListWidget::setCurrentRow(int row)
void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags command)
{
Q_D(QListWidget);
- d->selectionModel->setCurrentIndex(d->model()->index(row), command);
+ d->selectionModel->setCurrentIndex(d->listModel()->index(row), command);
}
/*!
@@ -1458,7 +1464,7 @@ void QListWidget::setCurrentRow(int row, QItemSelectionModel::SelectionFlags com
QListWidgetItem *QListWidget::itemAt(const QPoint &p) const
{
Q_D(const QListWidget);
- return d->model()->at(indexAt(p).row());
+ return d->listModel()->at(indexAt(p).row());
}
@@ -1476,7 +1482,7 @@ QListWidgetItem *QListWidget::itemAt(const QPoint &p) const
QRect QListWidget::visualItemRect(const QListWidgetItem *item) const
{
Q_D(const QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
return visualRect(index);
}
@@ -1487,7 +1493,7 @@ void QListWidget::sortItems(Qt::SortOrder order)
{
Q_D(QListWidget);
d->sortOrder = order;
- d->model()->sort(0, order);
+ d->listModel()->sort(0, order);
}
/*!
@@ -1526,7 +1532,7 @@ Qt::SortOrder QListWidget::sortOrder() const
void QListWidget::editItem(QListWidgetItem *item)
{
Q_D(QListWidget);
- edit(d->model()->index(item));
+ edit(d->listModel()->index(item));
}
/*!
@@ -1537,7 +1543,7 @@ void QListWidget::editItem(QListWidgetItem *item)
void QListWidget::openPersistentEditor(QListWidgetItem *item)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
QAbstractItemView::openPersistentEditor(index);
}
@@ -1549,7 +1555,7 @@ void QListWidget::openPersistentEditor(QListWidgetItem *item)
void QListWidget::closePersistentEditor(QListWidgetItem *item)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
QAbstractItemView::closePersistentEditor(index);
}
@@ -1561,7 +1567,7 @@ void QListWidget::closePersistentEditor(QListWidgetItem *item)
QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
{
Q_D(const QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
return QAbstractItemView::indexWidget(index);
}
@@ -1579,7 +1585,7 @@ QWidget *QListWidget::itemWidget(QListWidgetItem *item) const
void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->listModel()->index(item);
QAbstractItemView::setIndexWidget(index, widget);
}
@@ -1593,7 +1599,7 @@ void QListWidget::setItemWidget(QListWidgetItem *item, QWidget *widget)
bool QListWidget::isItemSelected(const QListWidgetItem *item) const
{
Q_D(const QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
return selectionModel()->isSelected(index);
}
@@ -1608,7 +1614,7 @@ bool QListWidget::isItemSelected(const QListWidgetItem *item) const
void QListWidget::setItemSelected(const QListWidgetItem *item, bool select)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
if (d->selectionMode == SingleSelection) {
selectionModel()->select(index, select
@@ -1632,7 +1638,7 @@ QList<QListWidgetItem*> QListWidget::selectedItems() const
QModelIndexList indexes = selectionModel()->selectedIndexes();
QList<QListWidgetItem*> items;
for (int i = 0; i < indexes.count(); ++i)
- items.append(d->model()->at(indexes.at(i).row()));
+ items.append(d->listModel()->at(indexes.at(i).row()));
return items;
}
@@ -1643,11 +1649,11 @@ QList<QListWidgetItem*> QListWidget::selectedItems() const
QList<QListWidgetItem*> QListWidget::findItems(const QString &text, Qt::MatchFlags flags) const
{
Q_D(const QListWidget);
- QModelIndexList indexes = d->model()->match(model()->index(0, 0, QModelIndex()),
+ QModelIndexList indexes = d->listModel()->match(model()->index(0, 0, QModelIndex()),
Qt::DisplayRole, text, -1, flags);
QList<QListWidgetItem*> items;
for (int i = 0; i < indexes.size(); ++i)
- items.append(d->model()->at(indexes.at(i).row()));
+ items.append(d->listModel()->at(indexes.at(i).row()));
return items;
}
@@ -1684,7 +1690,7 @@ void QListWidget::setItemHidden(const QListWidgetItem *item, bool hide)
void QListWidget::scrollToItem(const QListWidgetItem *item, QAbstractItemView::ScrollHint hint)
{
Q_D(QListWidget);
- QModelIndex index = d->model()->index(const_cast<QListWidgetItem*>(item));
+ QModelIndex index = d->listModel()->index(const_cast<QListWidgetItem*>(item));
QListView::scrollTo(index, hint);
}
@@ -1697,7 +1703,7 @@ void QListWidget::clear()
{
Q_D(QListWidget);
selectionModel()->clear();
- d->model()->clear();
+ d->listModel()->clear();
}
/*!
@@ -1708,7 +1714,7 @@ void QListWidget::clear()
*/
QStringList QListWidget::mimeTypes() const
{
- return d_func()->model()->QAbstractListModel::mimeTypes();
+ return d_func()->listModel()->QAbstractListModel::mimeTypes();
}
/*!
@@ -1721,7 +1727,7 @@ QStringList QListWidget::mimeTypes() const
*/
QMimeData *QListWidget::mimeData(const QList<QListWidgetItem*>) const
{
- return d_func()->model()->internalMimeData();
+ return d_func()->listModel()->internalMimeData();
}
#ifndef QT_NO_DRAGANDDROP
@@ -1744,7 +1750,7 @@ bool QListWidget::dropMimeData(int index, const QMimeData *data, Qt::DropAction
row = -1;
column = -1;
}
- return d_func()->model()->QAbstractListModel::dropMimeData(data, action , row, column, idx);
+ return d_func()->listModel()->QAbstractListModel::dropMimeData(data, action , row, column, idx);
}
/*! \reimp */
@@ -1803,7 +1809,7 @@ void QListWidget::dropEvent(QDropEvent *event) {
Qt::DropActions QListWidget::supportedDropActions() const
{
Q_D(const QListWidget);
- return d->model()->QAbstractListModel::supportedDropActions() | Qt::MoveAction;
+ return d->listModel()->QAbstractListModel::supportedDropActions() | Qt::MoveAction;
}
#endif // QT_NO_DRAGANDDROP
@@ -1827,7 +1833,7 @@ QList<QListWidgetItem*> QListWidget::items(const QMimeData *data) const
QModelIndex QListWidget::indexFromItem(QListWidgetItem *item) const
{
Q_D(const QListWidget);
- return d->model()->index(item);
+ return d->listModel()->index(item);
}
/*!
@@ -1838,7 +1844,7 @@ QListWidgetItem *QListWidget::itemFromIndex(const QModelIndex &index) const
{
Q_D(const QListWidget);
if (d->isIndexValid(index))
- return d->model()->at(index.row());
+ return d->listModel()->at(index.row());
return 0;
}
diff --git a/src/gui/itemviews/qlistwidget_p.h b/src/gui/itemviews/qlistwidget_p.h
index 8556047..6887d9d 100644
--- a/src/gui/itemviews/qlistwidget_p.h
+++ b/src/gui/itemviews/qlistwidget_p.h
@@ -143,7 +143,7 @@ class QListWidgetPrivate : public QListViewPrivate
Q_DECLARE_PUBLIC(QListWidget)
public:
QListWidgetPrivate() : QListViewPrivate(), sortOrder(Qt::AscendingOrder), sortingEnabled(false) {}
- inline QListModel *model() const { return qobject_cast<QListModel*>(q_func()->model()); }
+ inline QListModel *listModel() const { return qobject_cast<QListModel*>(model); }
void setup();
void _q_emitItemPressed(const QModelIndex &index);
void _q_emitItemClicked(const QModelIndex &index);
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index 92dfd19..4021c83 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -56,6 +56,15 @@ QT_BEGIN_NAMESPACE
typedef QList<QPair<QModelIndex, QPersistentModelIndex> > QModelIndexPairList;
+static inline QSet<int> qVectorToSet(const QVector<int> &vector)
+{
+ QSet<int> set;
+ set.reserve(vector.size());
+ for(int i=0; i < vector.size(); ++i)
+ set << vector.at(i);
+ return set;
+}
+
class QSortFilterProxyModelLessThan
{
public:
@@ -224,8 +233,8 @@ public:
QModelIndexPairList store_persistent_indexes();
void update_persistent_indexes(const QModelIndexPairList &source_indexes);
- void filter_changed();
- void handle_filter_changed(
+ void filter_changed(const QModelIndex &source_parent = QModelIndex());
+ QSet<int> handle_filter_changed(
QVector<int> &source_to_proxy, QVector<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient);
@@ -875,8 +884,8 @@ void QSortFilterProxyModelPrivate::proxy_item_range(
{
proxy_low = INT_MAX;
proxy_high = INT_MIN;
- foreach (int source_item, source_items) {
- int proxy_item = source_to_proxy.at(source_item);
+ for (int i = 0; i < source_items.count(); ++i) {
+ int proxy_item = source_to_proxy.at(source_items.at(i));
Q_ASSERT(proxy_item != -1);
if (proxy_item < proxy_low)
proxy_low = proxy_item;
@@ -937,34 +946,47 @@ void QSortFilterProxyModelPrivate::update_persistent_indexes(
q->changePersistentIndexList(from, to);
}
+
/*!
\internal
Updates the proxy model (adds/removes rows) based on the
new filter.
*/
-void QSortFilterProxyModelPrivate::filter_changed()
+void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_parent)
{
- QMap<QModelIndex, Mapping *>::const_iterator it;
- for (it = source_index_mapping.constBegin(); it != source_index_mapping.constEnd(); ++it) {
- QModelIndex source_parent = it.key();
- Mapping *m = it.value();
- handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical);
- handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal);
+ IndexMap::const_iterator it = source_index_mapping.constFind(source_parent);
+ if (it == source_index_mapping.constEnd())
+ return;
+ Mapping *m = it.value();
+ QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical);
+ QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal);
+ QVector<QModelIndex>::iterator it2 = m->mapped_children.end();
+ while (it2 != m->mapped_children.begin()) {
+ --it2;
+ const QModelIndex source_child_index = *it2;
+ if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) {
+ it2 = m->mapped_children.erase(it2);
+ remove_from_mapping(source_child_index);
+ } else {
+ filter_changed(source_child_index);
+ }
}
}
/*!
\internal
+ returns the removed items indexes
*/
-void QSortFilterProxyModelPrivate::handle_filter_changed(
+QSet<int> QSortFilterProxyModelPrivate::handle_filter_changed(
QVector<int> &source_to_proxy, QVector<int> &proxy_to_source,
const QModelIndex &source_parent, Qt::Orientation orient)
{
Q_Q(QSortFilterProxyModel);
// Figure out which mapped items to remove
QVector<int> source_items_remove;
- foreach (int source_item, proxy_to_source) {
+ for (int i = 0; i < proxy_to_source.count(); ++i) {
+ const int source_item = proxy_to_source.at(i);
if ((orient == Qt::Vertical)
? !q->filterAcceptsRow(source_item, source_parent)
: !q->filterAcceptsColumn(source_item, source_parent)) {
@@ -994,6 +1016,7 @@ void QSortFilterProxyModelPrivate::handle_filter_changed(
insert_source_items(source_to_proxy, proxy_to_source,
source_items_insert, source_parent, orient);
}
+ return qVectorToSet(source_items_remove);
}
void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &source_top_left,
@@ -1044,15 +1067,14 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
if (!source_rows_remove.isEmpty()) {
remove_source_items(m->proxy_rows, m->source_rows,
source_rows_remove, source_parent, Qt::Vertical);
- QSet<int> source_rows_remove_set = source_rows_remove.toList().toSet();
- QVector<QModelIndex>::iterator it = m->mapped_children.begin();
- while (it != m->mapped_children.end()) {
+ QSet<int> source_rows_remove_set = qVectorToSet(source_rows_remove);
+ QVector<QModelIndex>::iterator it = m->mapped_children.end();
+ while (it != m->mapped_children.begin()) {
+ --it;
const QModelIndex source_child_index = *it;
if (source_rows_remove_set.contains(source_child_index.row())) {
it = m->mapped_children.erase(it);
remove_from_mapping(source_child_index);
- } else {
- ++it;
}
}
}
diff --git a/src/gui/itemviews/qstandarditemmodel.cpp b/src/gui/itemviews/qstandarditemmodel.cpp
index 4ec00bb..675a5b3 100644
--- a/src/gui/itemviews/qstandarditemmodel.cpp
+++ b/src/gui/itemviews/qstandarditemmodel.cpp
@@ -1740,18 +1740,21 @@ QList<QStandardItem*> QStandardItem::takeRow(int row)
Q_D(QStandardItem);
if ((row < 0) || (row >= rowCount()))
return QList<QStandardItem*>();
+ if (d->model)
+ d->model->d_func()->rowsAboutToBeRemoved(this, row, row);
QList<QStandardItem*> items;
int index = d->childIndex(row, 0);
- for (int column = 0; column < d->columnCount(); ++column) {
- QStandardItem *ch = d->children.at(index);
- if (ch) {
+ int col_count = d->columnCount();
+ for (int column = 0; column < col_count; ++column) {
+ QStandardItem *ch = d->children.at(index + column);
+ if (ch)
ch->d_func()->setParentAndModel(0, 0);
- d->children.replace(index, 0);
- }
items.append(ch);
- ++index;
}
- removeRow(row);
+ d->children.remove(index, col_count);
+ d->rows--;
+ if (d->model)
+ d->model->d_func()->rowsRemoved(this, row, 1);
return items;
}
@@ -1767,18 +1770,21 @@ QList<QStandardItem*> QStandardItem::takeColumn(int column)
Q_D(QStandardItem);
if ((column < 0) || (column >= columnCount()))
return QList<QStandardItem*>();
+ if (d->model)
+ d->model->d_func()->columnsAboutToBeRemoved(this, column, column);
QList<QStandardItem*> items;
- int index = d->childIndex(0, column);
- for (int row = 0; row < d->rowCount(); ++row) {
+
+ for (int row = d->rowCount() - 1; row >= 0; --row) {
+ int index = d->childIndex(row, column);
QStandardItem *ch = d->children.at(index);
- if (ch) {
+ if (ch)
ch->d_func()->setParentAndModel(0, 0);
- d->children.replace(index, 0);
- }
- items.append(ch);
- index += d->columnCount();
+ d->children.remove(index);
+ items.prepend(ch);
}
- removeColumn(column);
+ d->columns--;
+ if (d->model)
+ d->model->d_func()->columnsRemoved(this, column, 1);
return items;
}
@@ -1936,7 +1942,7 @@ QDataStream &operator<<(QDataStream &out, const QStandardItem &item)
return out;
}
-#endif // !QT_NO_DATASTREAM
+#endif // QT_NO_DATASTREAM
/*!
\class QStandardItemModel
@@ -2905,8 +2911,8 @@ QMimeData *QStandardItemModel::mimeData(const QModelIndexList &indexes) const
QStack<QStandardItem*> stack;
itemsSet.reserve(indexes.count());
stack.reserve(indexes.count());
- foreach (const QModelIndex &index, indexes) {
- QStandardItem *item = itemFromIndex(index);
+ for (int i = 0; i < indexes.count(); ++i) {
+ QStandardItem *item = itemFromIndex(indexes.at(i));
itemsSet << item;
stack.push(item);
}
diff --git a/src/gui/itemviews/qtableview.cpp b/src/gui/itemviews/qtableview.cpp
index 2902768..454b1f5 100644
--- a/src/gui/itemviews/qtableview.cpp
+++ b/src/gui/itemviews/qtableview.cpp
@@ -59,6 +59,138 @@
QT_BEGIN_NAMESPACE
+/** \internal
+ Add a span to the collection. the collection takes the ownership.
+ */
+void QSpanCollection::addSpan(QSpanCollection::Span *span)
+{
+ spans.append(span);
+ Index::iterator it_y = index.lowerBound(-span->top());
+ if (it_y == index.end() || it_y.key() != -span->top()) {
+ //there is no spans that starts with the row in the index, so create a sublist for it.
+ SubIndex sub_index;
+ if (it_y != index.end()) {
+ //the previouslist is the list of spans that sarts _before_ the row of the span.
+ // and which may intersect this row.
+ const SubIndex previousList = it_y.value();
+ foreach(Span *s, previousList) {
+ //If a subspans intersect the row, we need to split it into subspans
+ if(s->bottom() >= span->top())
+ sub_index.insert(-s->left(), s);
+ }
+ }
+ it_y = index.insert(-span->top(), sub_index);
+ //we will insert span to *it_y in the later loop
+ }
+
+ //insert the span as supspan in all the lists that intesects the span
+ while(-it_y.key() <= span->bottom()) {
+ (*it_y).insert(-span->left(), span);
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+}
+
+
+/** \internal
+* Has to be called after the height and width of a span is changed.
+*
+* old_height is the height before the change
+*
+* if the size of the span is now 0x0 the span will be deleted.
+*/
+void QSpanCollection::updateSpan(QSpanCollection::Span *span, int old_height)
+{
+ if (old_height < span->height()) {
+ //add the span as subspan in all the lists that intersect the new covered columns
+ Index::iterator it_y = index.lowerBound(-(span->top() + old_height - 1));
+ Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
+ while (-it_y.key() <= span->bottom()) {
+ (*it_y).insert(-span->left(), span);
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+ } else if (old_height > span->height()) {
+ //remove the span from all the subspans lists that intersect the columns not covered anymore
+ Index::iterator it_y = index.lowerBound(-span->bottom());
+ Q_ASSERT(it_y != index.end()); //it_y must exist since the span is in the list
+ while (-it_y.key() <= span->top() + old_height -1) {
+ if(-it_y.key() != span->bottom()) {
+ (*it_y).remove(-span->left());
+ if (it_y->isEmpty()) {
+ it_y = index.erase(it_y) - 1;
+ }
+ }
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+ }
+
+ if (span->width() == 0 && span->height() == 0) {
+ spans.removeOne(span);
+ delete span;
+ }
+}
+
+/** \internal
+ * \return a spans that spans over cell x,y (column,row) or 0 if there is none.
+ */
+QSpanCollection::Span *QSpanCollection::spanAt(int x, int y) const
+{
+ Index::const_iterator it_y = index.lowerBound(-y);
+ if (it_y == index.end())
+ return 0;
+ SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
+ if (it_x == (*it_y).end())
+ return 0;
+ Span *span = *it_x;
+ if (span->right() >= x && span->bottom() >= y)
+ return span;
+ return 0;
+}
+
+
+/** \internal
+* remove and deletes all spans inside the collection
+*/
+void QSpanCollection::clear()
+{
+ qDeleteAll(spans);
+ index.clear();
+ spans.clear();
+}
+
+/** \internal
+ * return a list to all the spans that spans over cells in the given rectangle
+ */
+QList<QSpanCollection::Span *> QSpanCollection::spansInRect(int x, int y, int w, int h) const
+{
+ QSet<Span *> list;
+ Index::const_iterator it_y = index.lowerBound(-y);
+ if(it_y == index.end())
+ --it_y;
+ while(-it_y.key() <= y + h) {
+ SubIndex::const_iterator it_x = (*it_y).lowerBound(-x);
+ if (it_x == (*it_y).end())
+ --it_x;
+ while(-it_x.key() <= x + w) {
+ Span *s = *it_x;
+ if (s->bottom() >= y && s->right() >= x)
+ list << s;
+ if (it_x == (*it_y).begin())
+ break;
+ --it_x;
+ }
+ if(it_y == index.begin())
+ break;
+ --it_y;
+ }
+ return list.toList();
+}
+
class QTableCornerButton : public QAbstractButton
{
Q_OBJECT
@@ -149,35 +281,40 @@ void QTableViewPrivate::trimHiddenSelections(QItemSelectionRange *range) const
*/
void QTableViewPrivate::setSpan(int row, int column, int rowSpan, int columnSpan)
{
- if (row < 0 || column < 0 || rowSpan < 0 || columnSpan < 0)
+ if (row < 0 || column < 0 || rowSpan <= 0 || columnSpan <= 0) {
+ qWarning() << "QTableView::setSpan: invalid span given: (" << row << ',' << column << ',' << rowSpan << ',' << columnSpan << ')';
return;
- Span sp(row, column, rowSpan, columnSpan);
- QList<Span>::iterator it;
- for (it = spans.begin(); it != spans.end(); ++it) {
- if (((*it).top() == sp.top()) && ((*it).left() == sp.left())) {
- if ((sp.height() == 1) && (sp.width() == 1))
- spans.erase(it); // "Implicit" span (1, 1), no need to store it
- else
- *it = sp; // Replace
+ }
+ QSpanCollection::Span *sp = spans.spanAt(column, row);
+ if (sp) {
+ if (sp->top() != row || sp->left() != column) {
+ qWarning() << "QTableView::setSpan: span cannot overlap";
return;
}
+ if (rowSpan == 1 && columnSpan == 1) {
+ rowSpan = columnSpan = 0;
+ }
+ const int old_height = sp->height();
+ sp->m_bottom = row + rowSpan - 1;
+ sp->m_right = column + columnSpan - 1;
+ spans.updateSpan(sp, old_height);
+ return;
}
- spans.append(sp);
+ sp = new QSpanCollection::Span(row, column, rowSpan, columnSpan);
+ spans.addSpan(sp);
}
/*!
\internal
Gets the span information for the cell at (\a row, \a column).
*/
-QTableViewPrivate::Span QTableViewPrivate::span(int row, int column) const
+QSpanCollection::Span QTableViewPrivate::span(int row, int column) const
{
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
- if (isInSpan(row, column, span))
- return span;
- }
- return Span(row, column, 1, 1);
+ QSpanCollection::Span *sp = spans.spanAt(column, row);
+ if (sp)
+ return *sp;
+
+ return QSpanCollection::Span(row, column, 1, 1);
}
/*!
@@ -233,67 +370,9 @@ bool QTableViewPrivate::spanContainsSection(const QHeaderView *header, int logic
/*!
\internal
- Returns true if one or more spans intersect column \a column.
-*/
-bool QTableViewPrivate::spansIntersectColumn(int column) const
-{
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
- if (spanContainsColumn(column, span.left(), span.width()))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
- Returns true if one or more spans intersect row \a row.
-*/
-bool QTableViewPrivate::spansIntersectRow(int row) const
-{
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
- if (spanContainsRow(row, span.top(), span.height()))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
- Returns true if one or more spans intersect one or more columns.
-*/
-bool QTableViewPrivate::spansIntersectColumns(const QList<int> &columns) const
-{
- QList<int>::const_iterator it;
- for (it = columns.constBegin(); it != columns.constEnd(); ++it) {
- if (spansIntersectColumn(*it))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
- Returns true if one or more spans intersect one or more rows.
-*/
-bool QTableViewPrivate::spansIntersectRows(const QList<int> &rows) const
-{
- QList<int>::const_iterator it;
- for (it = rows.constBegin(); it != rows.constEnd(); ++it) {
- if (spansIntersectRow(*it))
- return true;
- }
- return false;
-}
-
-/*!
- \internal
Returns the visual rect for the given \a span.
*/
-QRect QTableViewPrivate::visualSpanRect(const Span &span) const
+QRect QTableViewPrivate::visualSpanRect(const QSpanCollection::Span &span) const
{
Q_Q(const QTableView);
// vertical
@@ -319,42 +398,54 @@ QRect QTableViewPrivate::visualSpanRect(const Span &span) const
preparation for the main drawing loop.
\a drawn is a QBitArray of visualRowCountxvisualCoulumnCount which say if particular cell has been drawn
*/
-void QTableViewPrivate::drawAndClipSpans(const QRect &area, QPainter *painter,
+void QTableViewPrivate::drawAndClipSpans(const QRegion &area, QPainter *painter,
const QStyleOptionViewItemV4 &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn)
{
bool alternateBase = false;
QRegion region = viewport->rect();
- QList<Span>::const_iterator it;
- for (it = spans.constBegin(); it != spans.constEnd(); ++it) {
- Span span = *it;
+ QList<QSpanCollection::Span *> visibleSpans;
+ bool sectionMoved = verticalHeader->sectionsMoved() || horizontalHeader->sectionsMoved();
+
+ if (!sectionMoved) {
+ visibleSpans = spans.spansInRect(logicalColumn(firstVisualColumn), logicalRow(firstVisualRow),
+ lastVisualColumn - firstVisualColumn + 1, lastVisualRow - firstVisualRow + 1);
+ } else {
+ QSet<QSpanCollection::Span *> set;
+ for(int x = firstVisualColumn; x <= lastVisualColumn; x++)
+ for(int y = firstVisualRow; y <= lastVisualRow; y++)
+ set.insert(spans.spanAt(x,y));
+ set.remove(0);
+ visibleSpans = set.toList();
+ }
- int row = span.top();
- int col = span.left();
+ foreach (QSpanCollection::Span *span, visibleSpans) {
+ int row = span->top();
+ int col = span->left();
if (isHidden(row, col))
continue;
QModelIndex index = model->index(row, col, root);
if (!index.isValid())
continue;
- QRect rect = visualSpanRect(span);
+ QRect rect = visualSpanRect(*span);
rect.translate(scrollDelayOffset);
- if (!rect.intersects(area))
+ if (!area.intersects(rect))
continue;
QStyleOptionViewItemV4 opt = option;
opt.rect = rect;
- alternateBase = alternatingColors && (span.top() & 1);
+ alternateBase = alternatingColors && (span->top() & 1);
if (alternateBase)
opt.features |= QStyleOptionViewItemV2::Alternate;
else
opt.features &= ~QStyleOptionViewItemV2::Alternate;
drawCell(painter, opt, index);
region -= rect;
- for (int r = span.top(); r <= span.bottom(); ++r) {
+ for (int r = span->top(); r <= span->bottom(); ++r) {
const int vr = visualRow(r);
if (vr < firstVisualRow || vr > lastVisualRow)
continue;
- for (int c = span.left(); c <= span.right(); ++c) {
+ for (int c = span->left(); c <= span->right(); ++c) {
const int vc = visualColumn(c);
if (vc < firstVisualColumn || vc > lastVisualColumn)
continue;
@@ -753,7 +844,8 @@ void QTableView::paintEvent(QPaintEvent *event)
uint x = horizontalHeader->length() - horizontalHeader->offset() - (rightToLeft ? 0 : 1);
uint y = verticalHeader->length() - verticalHeader->offset() - 1;
- QVector<QRect> rects = event->region().rects();
+ const QRegion region = event->region().translated(offset);
+ const QVector<QRect> rects = region.rects();
//firstVisualRow is the visual index of the first visible row. lastVisualRow is the visual index of the last visible Row.
//same goes for ...VisualColumn
@@ -773,9 +865,13 @@ void QTableView::paintEvent(QPaintEvent *event)
QBitArray drawn((lastVisualRow - firstVisualRow + 1) * (lastVisualColumn - firstVisualColumn + 1));
+ if (d->hasSpans()) {
+ d->drawAndClipSpans(region, &painter, option, &drawn,
+ firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
+ }
+
for (int i = 0; i < rects.size(); ++i) {
QRect dirtyArea = rects.at(i);
- dirtyArea.translate(offset);
dirtyArea.setBottom(qMin(dirtyArea.bottom(), int(y)));
if (rightToLeft) {
dirtyArea.setLeft(qMax(dirtyArea.left(), d->viewport->width() - int(x)));
@@ -783,10 +879,6 @@ void QTableView::paintEvent(QPaintEvent *event)
dirtyArea.setRight(qMin(dirtyArea.right(), int(x)));
}
- if (d->hasSpans())
- d->drawAndClipSpans(dirtyArea, &painter, option, &drawn,
- firstVisualRow, lastVisualRow, firstVisualColumn, lastVisualColumn);
-
// get the horizontal start and end visual sections
int left = horizontalHeader->visualIndexAt(dirtyArea.left());
int right = horizontalHeader->visualIndexAt(dirtyArea.right());
@@ -913,7 +1005,7 @@ QModelIndex QTableView::indexAt(const QPoint &pos) const
int c = columnAt(pos.x());
if (r >= 0 && c >= 0) {
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(r, c);
+ QSpanCollection::Span span = d->span(r, c);
r = span.top();
c = span.left();
}
@@ -1011,14 +1103,14 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
--visualRow;
if (d->hasSpans()) {
int row = d->logicalRow(visualRow);
- QTableViewPrivate::Span span = d->span(row, current.column());
+ QSpanCollection::Span span = d->span(row, current.column());
visualRow = d->visualRow(span.top());
visualColumn = d->visualColumn(span.left());
}
break;
case MoveDown:
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(current.row(), current.column());
+ QSpanCollection::Span span = d->span(current.row(), current.column());
visualRow = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
}
#ifdef QT_KEYPAD_NAVIGATION
@@ -1030,7 +1122,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
++visualRow;
if (d->hasSpans()) {
int row = d->logicalRow(visualRow);
- QTableViewPrivate::Span span = d->span(row, current.column());
+ QSpanCollection::Span span = d->span(row, current.column());
visualColumn = d->visualColumn(span.left());
}
break;
@@ -1058,7 +1150,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
--visualColumn;
if (d->hasSpans()) {
int column = d->logicalColumn(visualColumn);
- QTableViewPrivate::Span span = d->span(current.row(), column);
+ QSpanCollection::Span span = d->span(current.row(), column);
visualRow = d->visualRow(span.top());
visualColumn = d->visualColumn(span.left());
}
@@ -1078,7 +1170,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
} // else MoveRight
case MoveRight:
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(current.row(), current.column());
+ QSpanCollection::Span span = d->span(current.row(), current.column());
visualColumn = d->visualColumn(d->columnSpanEndLogical(span.left(), span.width()));
}
++visualColumn;
@@ -1086,7 +1178,7 @@ QModelIndex QTableView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifi
++visualColumn;
if (d->hasSpans()) {
int column = d->logicalColumn(visualColumn);
- QTableViewPrivate::Span span = d->span(current.row(), column);
+ QSpanCollection::Span span = d->span(current.row(), column);
visualRow = d->visualRow(span.top());
}
break;
@@ -1161,9 +1253,8 @@ void QTableView::setSelection(const QRect &rect, QItemSelectionModel::SelectionF
int right = qMax(d->visualColumn(tl.column()), d->visualColumn(br.column()));
do {
expanded = false;
- QList<QTableViewPrivate::Span>::const_iterator it;
- for (it = d->spans.constBegin(); it != d->spans.constEnd(); ++it) {
- QTableViewPrivate::Span span = *it;
+ foreach (QSpanCollection::Span *it, d->spans.spans) {
+ const QSpanCollection::Span &span = *it;
int t = d->visualRow(span.top());
int l = d->visualColumn(span.left());
int b = d->visualRow(d->rowSpanEndLogical(span.top(), span.height()));
@@ -1253,7 +1344,7 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
bool verticalMoved = verticalHeader()->sectionsMoved();
bool horizontalMoved = horizontalHeader()->sectionsMoved();
- if ((verticalMoved && horizontalMoved) || d->hasSpans()) {
+ if ((verticalMoved && horizontalMoved) || (d->hasSpans() && (verticalMoved || horizontalMoved))) {
for (int i = 0; i < selection.count(); ++i) {
QItemSelectionRange range = selection.at(i);
if (range.parent() != d->root || !range.isValid())
@@ -1296,9 +1387,19 @@ QRegion QTableView::visualRegionForSelection(const QItemSelection &selection) co
if (range.parent() != d->root || !range.isValid())
continue;
d->trimHiddenSelections(&range);
- QRect tl = visualRect(range.topLeft());
- QRect br = visualRect(range.bottomRight());
- selectionRegion += QRegion(tl|br);
+
+ const int rtop = rowViewportPosition(range.top());
+ const int rbottom = rowViewportPosition(range.bottom()) + rowHeight(range.bottom());
+ const int rleft = columnViewportPosition(range.left());
+ const int rright = columnViewportPosition(range.right()) + columnWidth(range.right());
+ selectionRegion += QRect(QPoint(rleft, rtop), QPoint(rright, rbottom));
+ if (d->hasSpans()) {
+ foreach (QSpanCollection::Span *s,
+ d->spans.spansInRect(range.left(), range.top(), range.width(), range.height())) {
+ if (range.contains(s->top(), s->left(), range.parent()))
+ selectionRegion += d->visualSpanRect(*s);
+ }
+ }
}
}
@@ -1743,14 +1844,14 @@ void QTableView::setSortingEnabled(bool enable)
disconnect(horizontalHeader(), SIGNAL(sectionPressed(int)),
this, SLOT(selectColumn(int)));
connect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(sortByColumn(int)));
+ this, SLOT(sortByColumn(int)), Qt::UniqueConnection);
sortByColumn(horizontalHeader()->sortIndicatorSection(),
horizontalHeader()->sortIndicatorOrder());
} else {
connect(d->horizontalHeader, SIGNAL(sectionEntered(int)),
- this, SLOT(_q_selectColumn(int)));
+ this, SLOT(_q_selectColumn(int)), Qt::UniqueConnection);
connect(horizontalHeader(), SIGNAL(sectionPressed(int)),
- this, SLOT(selectColumn(int)));
+ this, SLOT(selectColumn(int)), Qt::UniqueConnection);
disconnect(horizontalHeader(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
this, SLOT(sortByColumn(int)));
}
@@ -1874,7 +1975,7 @@ QRect QTableView::visualRect(const QModelIndex &index) const
d->executePostedLayout();
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(index.row(), index.column());
+ QSpanCollection::Span span = d->span(index.row(), index.column());
return d->visualSpanRect(span);
}
@@ -1903,7 +2004,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
|| isIndexHidden(index))
return;
- QTableViewPrivate::Span span;
+ QSpanCollection::Span span;
if (d->hasSpans())
span = d->span(index.row(), index.column());
@@ -2010,7 +2111,7 @@ void QTableView::scrollTo(const QModelIndex &index, ScrollHint hint)
}
}
- d->setDirtyRegion(visualRect(index));
+ update(index);
}
/*!
@@ -2058,7 +2159,7 @@ void QTableView::timerEvent(QTimerEvent *event)
QRect rect;
int viewportHeight = d->viewport->height();
int viewportWidth = d->viewport->width();
- if (d->hasSpans() && d->spansIntersectColumns(d->columnsToUpdate)) {
+ if (d->hasSpans()) {
rect = QRect(0, 0, viewportWidth, viewportHeight);
} else {
for (int i = d->columnsToUpdate.size()-1; i >= 0; --i) {
@@ -2083,7 +2184,7 @@ void QTableView::timerEvent(QTimerEvent *event)
int viewportHeight = d->viewport->height();
int viewportWidth = d->viewport->width();
int top;
- if (d->hasSpans() && d->spansIntersectRows(d->rowsToUpdate)) {
+ if (d->hasSpans()) {
top = 0;
} else {
top = viewportHeight;
@@ -2114,7 +2215,7 @@ void QTableView::rowMoved(int, int oldIndex, int newIndex)
updateGeometries();
int logicalOldIndex = d->verticalHeader->logicalIndex(oldIndex);
int logicalNewIndex = d->verticalHeader->logicalIndex(newIndex);
- if (d->hasSpans() && (d->spansIntersectRow(logicalOldIndex) || d->spansIntersectRow(logicalNewIndex))) {
+ if (d->hasSpans()) {
d->viewport->update();
} else {
int oldTop = rowViewportPosition(logicalOldIndex);
@@ -2142,7 +2243,7 @@ void QTableView::columnMoved(int, int oldIndex, int newIndex)
updateGeometries();
int logicalOldIndex = d->horizontalHeader->logicalIndex(oldIndex);
int logicalNewIndex = d->horizontalHeader->logicalIndex(newIndex);
- if (d->hasSpans() && (d->spansIntersectColumn(logicalOldIndex) || d->spansIntersectColumn(logicalNewIndex))) {
+ if (d->hasSpans()) {
d->viewport->update();
} else {
int oldLeft = columnViewportPosition(logicalOldIndex);
@@ -2325,7 +2426,7 @@ bool QTableView::isIndexHidden(const QModelIndex &index) const
if (isRowHidden(index.row()) || isColumnHidden(index.column()))
return true;
if (d->hasSpans()) {
- QTableViewPrivate::Span span = d->span(index.row(), index.column());
+ QSpanCollection::Span span = d->span(index.row(), index.column());
return !((span.top() == index.row()) && (span.left() == index.column()));
}
return false;
diff --git a/src/gui/itemviews/qtableview_p.h b/src/gui/itemviews/qtableview_p.h
index b08eabd..3f3dd36 100644
--- a/src/gui/itemviews/qtableview_p.h
+++ b/src/gui/itemviews/qtableview_p.h
@@ -53,12 +53,69 @@
// We mean it.
//
+#include <QtCore/QList>
+#include <QtCore/QMap>
+#include <QtCore/QSet>
+#include <QtCore/QDebug>
#include "private/qabstractitemview_p.h"
#ifndef QT_NO_TABLEVIEW
QT_BEGIN_NAMESPACE
+/** \internal
+*
+* This is a list of span with a binary index to look up quickly a span at a certain index.
+*
+* The index is a map of map.
+* spans are mentaly divided into sub spans so that the start of any subspans doesn't overlap
+* with any other subspans. There is no real representation of the subspans.
+* The key of the first map is the row where the subspan starts, the value of the first map is
+* a list (map) of all subspans that starts at the same row. It is indexed with its row
+*/
+class QSpanCollection
+{
+public:
+ struct Span
+ {
+ int m_top;
+ int m_left;
+ int m_bottom;
+ int m_right;
+ Span()
+ : m_top(-1), m_left(-1), m_bottom(-1), m_right(-1) { }
+ Span(int row, int column, int rowCount, int columnCount)
+ : m_top(row), m_left(column), m_bottom(row+rowCount-1), m_right(column+columnCount-1) { }
+ inline int top() const { return m_top; }
+ inline int left() const { return m_left; }
+ inline int bottom() const { return m_bottom; }
+ inline int right() const { return m_right; }
+ inline int height() const { return m_bottom - m_top + 1; }
+ inline int width() const { return m_right - m_left + 1; }
+ };
+
+ ~QSpanCollection()
+ {
+ qDeleteAll(spans);
+ }
+
+ void addSpan(Span *span);
+ void updateSpan(Span *span, int old_height);
+ Span *spanAt(int x, int y) const;
+ void clear();
+ QList<Span *> spansInRect(int x, int y, int w, int h) const;
+
+ QList<Span *> spans; //lists of all spans
+private:
+ //the indexes are negative so the QMap::lowerBound do what i need.
+ typedef QMap<int, Span *> SubIndex;
+ typedef QMap<int, SubIndex> Index;
+ Index index;
+};
+
+Q_DECLARE_TYPEINFO ( QSpanCollection::Span, Q_MOVABLE_TYPE);
+
+
class QTableViewPrivate : public QAbstractItemViewPrivate
{
Q_DECLARE_PUBLIC(QTableView)
@@ -98,11 +155,7 @@ public:
int sectionSpanEndLogical(const QHeaderView *header, int logical, int span) const;
int sectionSpanSize(const QHeaderView *header, int logical, int span) const;
bool spanContainsSection(const QHeaderView *header, int logical, int spanLogical, int span) const;
- bool spansIntersectColumn(int column) const;
- bool spansIntersectRow(int row) const;
- bool spansIntersectColumns(const QList<int> &columns) const;
- bool spansIntersectRows(const QList<int> &rows) const;
- void drawAndClipSpans(const QRect &area, QPainter *painter,
+ void drawAndClipSpans(const QRegion &area, QPainter *painter,
const QStyleOptionViewItemV4 &option, QBitArray *drawn,
int firstVisualRow, int lastVisualRow, int firstVisualColumn, int lastVisualColumn);
void drawCell(QPainter *painter, const QStyleOptionViewItemV4 &option, const QModelIndex &index);
@@ -121,27 +174,10 @@ public:
bool sortingEnabled;
bool geometryRecursionBlock;
- struct Span
- {
- int m_top;
- int m_left;
- int m_bottom;
- int m_right;
- Span()
- : m_top(-1), m_left(-1), m_bottom(-1), m_right(-1) { }
- Span(int row, int column, int rowCount, int columnCount)
- : m_top(row), m_left(column), m_bottom(row+rowCount-1), m_right(column+columnCount-1) { }
- inline int top() const { return m_top; }
- inline int left() const { return m_left; }
- inline int bottom() const { return m_bottom; }
- inline int right() const { return m_right; }
- inline int height() const { return m_bottom - m_top + 1; }
- inline int width() const { return m_right - m_left + 1; }
- };
- QList<Span> spans;
+ QSpanCollection spans;
void setSpan(int row, int column, int rowSpan, int columnSpan);
- Span span(int row, int column) const;
+ QSpanCollection::Span span(int row, int column) const;
inline int rowSpan(int row, int column) const {
return span(row, column).height();
}
@@ -149,17 +185,7 @@ public:
return span(row, column).width();
}
inline bool hasSpans() const {
- return !spans.isEmpty();
- }
- inline bool spanContainsRow(int row, int spanRow, int span) const {
- return spanContainsSection(verticalHeader, row, spanRow, span);
- }
- inline bool spanContainsColumn(int column, int spanColumn, int span) const {
- return spanContainsSection(horizontalHeader, column, spanColumn, span);
- }
- inline bool isInSpan(int row, int column, const Span &span) const {
- return spanContainsRow(row, span.top(), span.height())
- && spanContainsColumn(column, span.left(), span.width());
+ return !spans.spans.isEmpty();
}
inline int rowSpanHeight(int row, int span) const {
return sectionSpanSize(verticalHeader, row, span);
@@ -194,7 +220,7 @@ public:
return isColumnHidden(c) || !isCellEnabled(r, c);
}
- QRect visualSpanRect(const Span &span) const;
+ QRect visualSpanRect(const QSpanCollection::Span &span) const;
void _q_selectRow(int row);
void _q_selectColumn(int column);
diff --git a/src/gui/itemviews/qtablewidget.cpp b/src/gui/itemviews/qtablewidget.cpp
index e88301e..6645376 100644
--- a/src/gui/itemviews/qtablewidget.cpp
+++ b/src/gui/itemviews/qtablewidget.cpp
@@ -530,24 +530,6 @@ void QTableModel::sort(int column, Qt::SortOrder order)
emit layoutChanged();
}
-bool QTableModel::canConvertToDouble(const QVariant &value)
-{
- switch (value.type()) {
- case QVariant::Bool:
- case QVariant::Int:
- case QVariant::UInt:
- case QVariant::LongLong:
- case QVariant::ULongLong:
- case QVariant::Double:
- case QVariant::Char:
- return true;
- default:
- return false;
- }
- return false;
-}
-
-
/*
\internal
@@ -1410,7 +1392,7 @@ QVariant QTableWidgetItem::data(int role) const
bool QTableWidgetItem::operator<(const QTableWidgetItem &other) const
{
const QVariant v1 = data(Qt::DisplayRole), v2 = other.data(Qt::DisplayRole);
- if (QTableModel::canConvertToDouble(v1) && QTableModel::canConvertToDouble(v2))
+ if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2))
return v1.toDouble() < v2.toDouble();
return v1.toString() < v2.toString();
}
@@ -1588,7 +1570,7 @@ void QTableWidgetPrivate::setup()
QObject::connect(q, SIGNAL(activated(QModelIndex)), q, SLOT(_q_emitItemActivated(QModelIndex)));
QObject::connect(q, SIGNAL(entered(QModelIndex)), q, SLOT(_q_emitItemEntered(QModelIndex)));
// model signals
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_emitItemChanged(QModelIndex)));
// selection signals
QObject::connect(q->selectionModel(), SIGNAL(currentChanged(QModelIndex,QModelIndex)),
@@ -1596,15 +1578,15 @@ void QTableWidgetPrivate::setup()
QObject::connect(q->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
q, SIGNAL(itemSelectionChanged()));
// sorting
- QObject::connect(model(), SIGNAL(dataChanged(QModelIndex,QModelIndex)),
+ QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
q, SLOT(_q_dataChanged(QModelIndex,QModelIndex)));
- QObject::connect(model(), SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
+ QObject::connect(model, SIGNAL(columnsRemoved(QModelIndex,int,int)), q, SLOT(_q_sort()));
}
void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemPressed(item);
emit q->cellPressed(index.row(), index.column());
}
@@ -1612,7 +1594,7 @@ void QTableWidgetPrivate::_q_emitItemPressed(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemClicked(item);
emit q->cellClicked(index.row(), index.column());
}
@@ -1620,7 +1602,7 @@ void QTableWidgetPrivate::_q_emitItemClicked(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemDoubleClicked(item);
emit q->cellDoubleClicked(index.row(), index.column());
}
@@ -1628,7 +1610,7 @@ void QTableWidgetPrivate::_q_emitItemDoubleClicked(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemActivated(item);
emit q->cellActivated(index.row(), index.column());
}
@@ -1636,7 +1618,7 @@ void QTableWidgetPrivate::_q_emitItemActivated(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemEntered(item);
emit q->cellEntered(index.row(), index.column());
}
@@ -1644,7 +1626,7 @@ void QTableWidgetPrivate::_q_emitItemEntered(const QModelIndex &index)
void QTableWidgetPrivate::_q_emitItemChanged(const QModelIndex &index)
{
Q_Q(QTableWidget);
- if (QTableWidgetItem *item = model()->item(index))
+ if (QTableWidgetItem *item = tableModel()->item(index))
emit q->itemChanged(item);
emit q->cellChanged(index.row(), index.column());
}
@@ -1653,8 +1635,8 @@ void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
const QModelIndex &previous)
{
Q_Q(QTableWidget);
- QTableWidgetItem *currentItem = model()->item(current);
- QTableWidgetItem *previousItem = model()->item(previous);
+ QTableWidgetItem *currentItem = tableModel()->item(current);
+ QTableWidgetItem *previousItem = tableModel()->item(previous);
if (currentItem || previousItem)
emit q->currentItemChanged(currentItem, previousItem);
emit q->currentCellChanged(current.row(), current.column(), previous.row(), previous.column());
@@ -1662,23 +1644,21 @@ void QTableWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
void QTableWidgetPrivate::_q_sort()
{
- Q_Q(QTableWidget);
if (sortingEnabled) {
- int column = q->horizontalHeader()->sortIndicatorSection();
- Qt::SortOrder order = q->horizontalHeader()->sortIndicatorOrder();
- model()->sort(column, order);
+ int column = horizontalHeader->sortIndicatorSection();
+ Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
+ model->sort(column, order);
}
}
void QTableWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
- Q_Q(QTableWidget);
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()) {
- int column = q->horizontalHeader()->sortIndicatorSection();
+ int column = horizontalHeader->sortIndicatorSection();
if (column >= topLeft.column() && column <= bottomRight.column()) {
- Qt::SortOrder order = q->horizontalHeader()->sortIndicatorOrder();
- model()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
+ Qt::SortOrder order = horizontalHeader->sortIndicatorOrder();
+ tableModel()->ensureSorted(column, order, topLeft.row(), bottomRight.row());
}
}
}
@@ -1882,7 +1862,7 @@ QTableWidget::~QTableWidget()
void QTableWidget::setRowCount(int rows)
{
Q_D(QTableWidget);
- d->model()->setRowCount(rows);
+ d->tableModel()->setRowCount(rows);
}
/*!
@@ -1892,7 +1872,7 @@ void QTableWidget::setRowCount(int rows)
int QTableWidget::rowCount() const
{
Q_D(const QTableWidget);
- return d->model()->rowCount();
+ return d->model->rowCount();
}
/*!
@@ -1905,7 +1885,7 @@ int QTableWidget::rowCount() const
void QTableWidget::setColumnCount(int columns)
{
Q_D(QTableWidget);
- d->model()->setColumnCount(columns);
+ d->tableModel()->setColumnCount(columns);
}
/*!
@@ -1915,7 +1895,7 @@ void QTableWidget::setColumnCount(int columns)
int QTableWidget::columnCount() const
{
Q_D(const QTableWidget);
- return d->model()->columnCount();
+ return d->model->columnCount();
}
/*!
@@ -1924,7 +1904,7 @@ int QTableWidget::columnCount() const
int QTableWidget::row(const QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- return d->model()->index(item).row();
+ return d->tableModel()->index(item).row();
}
/*!
@@ -1933,7 +1913,7 @@ int QTableWidget::row(const QTableWidgetItem *item) const
int QTableWidget::column(const QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- return d->model()->index(item).column();
+ return d->tableModel()->index(item).column();
}
@@ -1946,7 +1926,7 @@ int QTableWidget::column(const QTableWidgetItem *item) const
QTableWidgetItem *QTableWidget::item(int row, int column) const
{
Q_D(const QTableWidget);
- return d->model()->item(row, column);
+ return d->tableModel()->item(row, column);
}
/*!
@@ -1975,7 +1955,7 @@ void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
qWarning("QTableWidget: cannot insert an item that is already owned by another QTableWidget");
} else {
item->view = this;
- d->model()->setItem(row, column, item);
+ d->tableModel()->setItem(row, column, item);
}
} else {
delete takeItem(row, column);
@@ -1988,7 +1968,7 @@ void QTableWidget::setItem(int row, int column, QTableWidgetItem *item)
QTableWidgetItem *QTableWidget::takeItem(int row, int column)
{
Q_D(QTableWidget);
- QTableWidgetItem *item = d->model()->takeItem(row, column);
+ QTableWidgetItem *item = d->tableModel()->takeItem(row, column);
if (item)
item->view = 0;
return item;
@@ -2000,7 +1980,7 @@ QTableWidgetItem *QTableWidget::takeItem(int row, int column)
QTableWidgetItem *QTableWidget::verticalHeaderItem(int row) const
{
Q_D(const QTableWidget);
- return d->model()->verticalHeaderItem(row);
+ return d->tableModel()->verticalHeaderItem(row);
}
/*!
@@ -2011,7 +1991,7 @@ void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
Q_D(QTableWidget);
if (item) {
item->view = this;
- d->model()->setVerticalHeaderItem(row, item);
+ d->tableModel()->setVerticalHeaderItem(row, item);
} else {
delete takeVerticalHeaderItem(row);
}
@@ -2024,7 +2004,7 @@ void QTableWidget::setVerticalHeaderItem(int row, QTableWidgetItem *item)
QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
{
Q_D(QTableWidget);
- QTableWidgetItem *itm = d->model()->takeVerticalHeaderItem(row);
+ QTableWidgetItem *itm = d->tableModel()->takeVerticalHeaderItem(row);
if (itm)
itm->view = 0;
return itm;
@@ -2037,7 +2017,7 @@ QTableWidgetItem *QTableWidget::takeVerticalHeaderItem(int row)
QTableWidgetItem *QTableWidget::horizontalHeaderItem(int column) const
{
Q_D(const QTableWidget);
- return d->model()->horizontalHeaderItem(column);
+ return d->tableModel()->horizontalHeaderItem(column);
}
/*!
@@ -2048,7 +2028,7 @@ void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
Q_D(QTableWidget);
if (item) {
item->view = this;
- d->model()->setHorizontalHeaderItem(column, item);
+ d->tableModel()->setHorizontalHeaderItem(column, item);
} else {
delete takeHorizontalHeaderItem(column);
}
@@ -2061,7 +2041,7 @@ void QTableWidget::setHorizontalHeaderItem(int column, QTableWidgetItem *item)
QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
{
Q_D(QTableWidget);
- QTableWidgetItem *itm = d->model()->takeHorizontalHeaderItem(column);
+ QTableWidgetItem *itm = d->tableModel()->takeHorizontalHeaderItem(column);
if (itm)
itm->view = 0;
return itm;
@@ -2073,7 +2053,7 @@ QTableWidgetItem *QTableWidget::takeHorizontalHeaderItem(int column)
void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
{
Q_D(QTableWidget);
- QTableModel *model = d->model();
+ QTableModel *model = d->tableModel();
QTableWidgetItem *item = 0;
for (int i = 0; i < model->rowCount() && i < labels.count(); ++i) {
item = model->verticalHeaderItem(i);
@@ -2091,7 +2071,7 @@ void QTableWidget::setVerticalHeaderLabels(const QStringList &labels)
void QTableWidget::setHorizontalHeaderLabels(const QStringList &labels)
{
Q_D(QTableWidget);
- QTableModel *model = d->model();
+ QTableModel *model = d->tableModel();
QTableWidgetItem *item = 0;
for (int i = 0; i < model->columnCount() && i < labels.count(); ++i) {
item = model->horizontalHeaderItem(i);
@@ -2131,7 +2111,7 @@ int QTableWidget::currentColumn() const
QTableWidgetItem *QTableWidget::currentItem() const
{
Q_D(const QTableWidget);
- return d->model()->item(currentIndex());
+ return d->tableModel()->item(currentIndex());
}
/*!
@@ -2145,7 +2125,7 @@ QTableWidgetItem *QTableWidget::currentItem() const
void QTableWidget::setCurrentItem(QTableWidgetItem *item)
{
Q_D(QTableWidget);
- setCurrentIndex(d->model()->index(item));
+ setCurrentIndex(d->tableModel()->index(item));
}
/*!
@@ -2158,7 +2138,7 @@ void QTableWidget::setCurrentItem(QTableWidgetItem *item)
void QTableWidget::setCurrentItem(QTableWidgetItem *item, QItemSelectionModel::SelectionFlags command)
{
Q_D(QTableWidget);
- d->selectionModel->setCurrentIndex(d->model()->index(item), command);
+ d->selectionModel->setCurrentIndex(d->tableModel()->index(item), command);
}
/*!
@@ -2197,7 +2177,7 @@ void QTableWidget::setCurrentCell(int row, int column, QItemSelectionModel::Sele
void QTableWidget::sortItems(int column, Qt::SortOrder order)
{
Q_D(QTableWidget);
- d->model()->sort(column, order);
+ d->model->sort(column, order);
horizontalHeader()->setSortIndicator(column, order);
}
@@ -2226,7 +2206,7 @@ void QTableWidget::editItem(QTableWidgetItem *item)
Q_D(QTableWidget);
if (!item)
return;
- edit(d->model()->index(item));
+ edit(d->tableModel()->index(item));
}
/*!
@@ -2239,7 +2219,7 @@ void QTableWidget::openPersistentEditor(QTableWidgetItem *item)
Q_D(QTableWidget);
if (!item)
return;
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
QAbstractItemView::openPersistentEditor(index);
}
@@ -2253,7 +2233,7 @@ void QTableWidget::closePersistentEditor(QTableWidgetItem *item)
Q_D(QTableWidget);
if (!item)
return;
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
QAbstractItemView::closePersistentEditor(index);
}
@@ -2303,7 +2283,7 @@ void QTableWidget::setCellWidget(int row, int column, QWidget *widget)
bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
return selectionModel()->isSelected(index);
}
@@ -2317,7 +2297,7 @@ bool QTableWidget::isItemSelected(const QTableWidgetItem *item) const
void QTableWidget::setItemSelected(const QTableWidgetItem *item, bool select)
{
Q_D(QTableWidget);
- QModelIndex index = d->model()->index(item);
+ QModelIndex index = d->tableModel()->index(item);
selectionModel()->select(index, select ? QItemSelectionModel::Select : QItemSelectionModel::Deselect);
}
@@ -2374,7 +2354,7 @@ QList<QTableWidgetItem*> QTableWidget::selectedItems()
QModelIndex index = indexes.at(i);
if (isIndexHidden(index))
continue;
- QTableWidgetItem *item = d->model()->item(index);
+ QTableWidgetItem *item = d->tableModel()->item(index);
if (item)
items.append(item);
}
@@ -2390,11 +2370,11 @@ QList<QTableWidgetItem*> QTableWidget::findItems(const QString &text, Qt::MatchF
Q_D(const QTableWidget);
QModelIndexList indexes;
for (int column = 0; column < columnCount(); ++column)
- indexes += d->model()->match(model()->index(0, column, QModelIndex()),
+ indexes += d->model->match(model()->index(0, column, QModelIndex()),
Qt::DisplayRole, text, -1, flags);
QList<QTableWidgetItem*> items;
for (int i = 0; i < indexes.size(); ++i)
- items.append(d->model()->item(indexes.at(i)));
+ items.append(d->tableModel()->item(indexes.at(i)));
return items;
}
@@ -2428,7 +2408,7 @@ int QTableWidget::visualColumn(int logicalColumn) const
QTableWidgetItem *QTableWidget::itemAt(const QPoint &p) const
{
Q_D(const QTableWidget);
- return d->model()->item(indexAt(p));
+ return d->tableModel()->item(indexAt(p));
}
/*!
@@ -2439,7 +2419,7 @@ QRect QTableWidget::visualItemRect(const QTableWidgetItem *item) const
Q_D(const QTableWidget);
if (!item)
return QRect();
- QModelIndex index = d->model()->index(const_cast<QTableWidgetItem*>(item));
+ QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
Q_ASSERT(index.isValid());
return visualRect(index);
}
@@ -2455,7 +2435,7 @@ void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView:
Q_D(QTableWidget);
if (!item)
return;
- QModelIndex index = d->model()->index(const_cast<QTableWidgetItem*>(item));
+ QModelIndex index = d->tableModel()->index(const_cast<QTableWidgetItem*>(item));
Q_ASSERT(index.isValid());
QTableView::scrollTo(index, hint);
}
@@ -2468,7 +2448,7 @@ void QTableWidget::scrollToItem(const QTableWidgetItem *item, QAbstractItemView:
const QTableWidgetItem *QTableWidget::itemPrototype() const
{
Q_D(const QTableWidget);
- return d->model()->itemPrototype();
+ return d->tableModel()->itemPrototype();
}
/*!
@@ -2487,7 +2467,7 @@ const QTableWidgetItem *QTableWidget::itemPrototype() const
void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
{
Q_D(QTableWidget);
- d->model()->setItemPrototype(item);
+ d->tableModel()->setItemPrototype(item);
}
/*!
@@ -2496,7 +2476,7 @@ void QTableWidget::setItemPrototype(const QTableWidgetItem *item)
void QTableWidget::insertRow(int row)
{
Q_D(QTableWidget);
- d->model()->insertRows(row);
+ d->tableModel()->insertRows(row);
}
/*!
@@ -2505,7 +2485,7 @@ void QTableWidget::insertRow(int row)
void QTableWidget::insertColumn(int column)
{
Q_D(QTableWidget);
- d->model()->insertColumns(column);
+ d->tableModel()->insertColumns(column);
}
/*!
@@ -2514,7 +2494,7 @@ void QTableWidget::insertColumn(int column)
void QTableWidget::removeRow(int row)
{
Q_D(QTableWidget);
- d->model()->removeRows(row);
+ d->tableModel()->removeRows(row);
}
/*!
@@ -2523,7 +2503,7 @@ void QTableWidget::removeRow(int row)
void QTableWidget::removeColumn(int column)
{
Q_D(QTableWidget);
- d->model()->removeColumns(column);
+ d->tableModel()->removeColumns(column);
}
/*!
@@ -2536,7 +2516,7 @@ void QTableWidget::clear()
{
Q_D(QTableWidget);
selectionModel()->clear();
- d->model()->clear();
+ d->tableModel()->clear();
}
/*!
@@ -2550,7 +2530,7 @@ void QTableWidget::clearContents()
{
Q_D(QTableWidget);
selectionModel()->clear();
- d->model()->clearContents();
+ d->tableModel()->clearContents();
}
/*!
@@ -2561,7 +2541,7 @@ void QTableWidget::clearContents()
*/
QStringList QTableWidget::mimeTypes() const
{
- return d_func()->model()->QAbstractTableModel::mimeTypes();
+ return d_func()->tableModel()->QAbstractTableModel::mimeTypes();
}
/*!
@@ -2574,7 +2554,7 @@ QStringList QTableWidget::mimeTypes() const
*/
QMimeData *QTableWidget::mimeData(const QList<QTableWidgetItem*>) const
{
- return d_func()->model()->internalMimeData();
+ return d_func()->tableModel()->internalMimeData();
}
/*!
@@ -2596,7 +2576,7 @@ bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::
column = -1;
}
#endif
- return d_func()->model()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
+ return d_func()->tableModel()->QAbstractTableModel::dropMimeData(data, action , row, column, idx);
}
/*!
@@ -2606,7 +2586,7 @@ bool QTableWidget::dropMimeData(int row, int column, const QMimeData *data, Qt::
*/
Qt::DropActions QTableWidget::supportedDropActions() const
{
- return d_func()->model()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
+ return d_func()->tableModel()->QAbstractTableModel::supportedDropActions() | Qt::MoveAction;
}
/*!
@@ -2630,7 +2610,7 @@ QList<QTableWidgetItem*> QTableWidget::items(const QMimeData *data) const
QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
{
Q_D(const QTableWidget);
- return d->model()->index(item);
+ return d->tableModel()->index(item);
}
/*!
@@ -2640,7 +2620,7 @@ QModelIndex QTableWidget::indexFromItem(QTableWidgetItem *item) const
QTableWidgetItem *QTableWidget::itemFromIndex(const QModelIndex &index) const
{
Q_D(const QTableWidget);
- return d->model()->item(index);
+ return d->tableModel()->item(index);
}
/*!
diff --git a/src/gui/itemviews/qtablewidget_p.h b/src/gui/itemviews/qtablewidget_p.h
index 2e1dab6..2acaf9b 100644
--- a/src/gui/itemviews/qtablewidget_p.h
+++ b/src/gui/itemviews/qtablewidget_p.h
@@ -144,7 +144,6 @@ public:
const QPair<QTableWidgetItem*,int> &right);
static bool itemGreaterThan(const QPair<QTableWidgetItem*,int> &left,
const QPair<QTableWidgetItem*,int> &right);
- static bool canConvertToDouble(const QVariant &value);
void ensureSorted(int column, Qt::SortOrder order, int start, int end);
QVector<QTableWidgetItem*> columnItems(int column) const;
@@ -190,7 +189,7 @@ class QTableWidgetPrivate : public QTableViewPrivate
Q_DECLARE_PUBLIC(QTableWidget)
public:
QTableWidgetPrivate() : QTableViewPrivate() {}
- inline QTableModel *model() const { return qobject_cast<QTableModel*>(q_func()->model()); }
+ inline QTableModel *tableModel() const { return qobject_cast<QTableModel*>(model); }
void setup();
// view signals
diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp
index 1070648..ecbd683 100644
--- a/src/gui/itemviews/qtreeview.cpp
+++ b/src/gui/itemviews/qtreeview.cpp
@@ -238,11 +238,6 @@ void QTreeView::setModel(QAbstractItemModel *model)
connect(d->model, SIGNAL(rowsRemoved(QModelIndex,int,int)),
this, SLOT(rowsRemoved(QModelIndex,int,int)));
- connect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int)));
- connect(d->model, SIGNAL(columnsRemoved(QModelIndex,int,int)),
- this, SLOT(_q_columnsRemoved(QModelIndex,int,int)));
-
connect(d->model, SIGNAL(modelAboutToBeReset()), SLOT(_q_modelAboutToBeReset()));
if (d->sortingEnabled)
@@ -680,10 +675,9 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto
// refresh the height cache here; we don't really lose anything by getting the size hint,
// since QAbstractItemView::dataChanged() will get the visualRect for the items anyway
- QModelIndex top = topLeft.sibling(topLeft.row(), 0);
- int topViewIndex = d->viewIndex(top);
+ int topViewIndex = d->viewIndex(topLeft);
if (topViewIndex == 0)
- d->defaultItemHeight = indexRowSizeHint(top);
+ d->defaultItemHeight = indexRowSizeHint(topLeft);
bool sizeChanged = false;
if (topViewIndex != -1) {
if (topLeft == bottomRight) {
@@ -691,8 +685,7 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto
d->invalidateHeightCache(topViewIndex);
sizeChanged = (oldHeight != d->itemHeight(topViewIndex));
} else {
- QModelIndex bottom = bottomRight.sibling(bottomRight.row(), 0);
- int bottomViewIndex = d->viewIndex(bottom);
+ int bottomViewIndex = d->viewIndex(bottomRight);
for (int i = topViewIndex; i <= bottomViewIndex; ++i) {
int oldHeight = d->itemHeight(i);
d->invalidateHeightCache(i);
@@ -853,7 +846,7 @@ void QTreeView::setSortingEnabled(bool enable)
// because otherwise it will not call sort on the model.
sortByColumn(header()->sortIndicatorSection(), header()->sortIndicatorOrder());
connect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
- this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)));
+ this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)), Qt::UniqueConnection);
} else {
disconnect(header(), SIGNAL(sortIndicatorChanged(int,Qt::SortOrder)),
this, SLOT(_q_sortIndicatorChanged(int, Qt::SortOrder)));
@@ -1142,7 +1135,7 @@ void QTreeView::scrollTo(const QModelIndex &index, ScrollHint hint)
if (rect.isEmpty()) {
// nothing to do
} else if (hint == EnsureVisible && area.contains(rect)) {
- d->setDirtyRegion(rect);
+ d->viewport->update(rect);
// nothing to do
} else {
bool above = (hint == EnsureVisible
@@ -1326,7 +1319,7 @@ bool QTreeViewPrivate::expandOrCollapseItemAtPos(const QPoint &pos)
expand(i, true);
if (!isAnimating()) {
q->updateGeometries();
- q->viewport()->update();
+ viewport->update();
}
return true;
}
@@ -1548,7 +1541,7 @@ void QTreeView::drawRow(QPainter *painter, const QStyleOptionViewItem &option,
? logicalIndexBeforeLeft
: logicalIndices.at(currentLogicalSection - 1);
if (columnCount == 1 || (nextLogicalSection == 0 && prevLogicalSection == -1)
- || (headerSection == 0 && nextLogicalSection == -1))
+ || (headerSection == 0 && nextLogicalSection == -1) || spanning)
opt.viewItemPosition = QStyleOptionViewItemV4::OnlyOne;
else if (headerSection == 0 || (nextLogicalSection != 0 && prevLogicalSection == -1))
opt.viewItemPosition = QStyleOptionViewItemV4::Beginning;
@@ -1817,10 +1810,10 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
if (i == -1)
return; // user clicked outside the items
- const QModelIndex &index = d->viewItems.at(i).index;
+ const QPersistentModelIndex firstColumnIndex = d->viewItems.at(i).index;
int column = d->header->logicalIndexAt(event->x());
- QPersistentModelIndex persistent = index.sibling(index.row(), column);
+ QPersistentModelIndex persistent = firstColumnIndex.sibling(firstColumnIndex.row(), column);
if (d->pressedIndex != persistent) {
mousePressEvent(event);
@@ -1843,10 +1836,10 @@ void QTreeView::mouseDoubleClickEvent(QMouseEvent *event)
if (d->itemsExpandable
&& d->expandsOnDoubleClick
&& d->hasVisibleChildren(persistent)) {
- if (!((i < d->viewItems.count()) && (d->viewItems.at(i).index == persistent))) {
+ if (!((i < d->viewItems.count()) && (d->viewItems.at(i).index == firstColumnIndex))) {
// find the new index of the item
for (i = 0; i < d->viewItems.count(); ++i) {
- if (d->viewItems.at(i).index == persistent)
+ if (d->viewItems.at(i).index == firstColumnIndex)
break;
}
if (i == d->viewItems.count())
@@ -2074,7 +2067,8 @@ QModelIndex QTreeView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifie
const bool useTopIndex = (cursorAction == MoveUp || cursorAction == MovePrevious);
int index = useTopIndex ? INT_MAX : INT_MIN;
const QItemSelection selection = d->selectionModel->selection();
- foreach (const QItemSelectionRange &range, selection) {
+ for (int i = 0; i < selection.count(); ++i) {
+ const QItemSelectionRange &range = selection.at(i);
int candidate = d->viewIndex(useTopIndex ? range.topLeft() : range.bottomRight());
if (candidate >= 0)
index = useTopIndex ? qMin(index, candidate) : qMax(index, candidate);
@@ -2424,14 +2418,10 @@ void QTreeView::rowsInserted(const QModelIndex &parent, int start, int end)
? d->viewItems.count()
: d->viewItems.at(parentItem).total) - 1;
- int firstColumn = 0;
- while (isColumnHidden(firstColumn) && firstColumn < header()->count() - 1)
- ++firstColumn;
-
const int delta = end - start + 1;
QVector<QTreeViewItem> insertedItems(delta);
for (int i = 0; i < delta; ++i) {
- insertedItems[i].index = d->model->index(i + start, firstColumn, parent);
+ insertedItems[i].index = d->model->index(i + start, 0, parent);
insertedItems[i].level = childLevel;
}
if (d->viewItems.isEmpty())
@@ -2614,7 +2604,7 @@ void QTreeView::expandAll()
d->viewItems[i].expanded = true;
d->layout(i);
QModelIndex idx = d->viewItems.at(i).index;
- d->expandedIndexes.insert(idx.sibling(idx.row(), 0));
+ d->expandedIndexes.insert(idx);
}
updateGeometries();
d->viewport->update();
@@ -3077,16 +3067,16 @@ void QTreeViewPrivate::_q_modelAboutToBeReset()
void QTreeViewPrivate::_q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end)
{
- Q_UNUSED(parent);
if (start <= 0 && 0 <= end)
viewItems.clear();
+ QAbstractItemViewPrivate::_q_columnsAboutToBeRemoved(parent, start, end);
}
void QTreeViewPrivate::_q_columnsRemoved(const QModelIndex &parent, int start, int end)
{
- Q_UNUSED(parent);
if (start <= 0 && 0 <= end)
doDelayedItemsLayout();
+ QAbstractItemViewPrivate::_q_columnsRemoved(parent, start, end);
}
void QTreeViewPrivate::layout(int i)
@@ -3094,10 +3084,6 @@ void QTreeViewPrivate::layout(int i)
Q_Q(QTreeView);
QModelIndex current;
QModelIndex parent = (i < 0) ? (QModelIndex)root : modelIndex(i);
- // modelIndex() will return an index that don't have a parent if column 0 is hidden,
- // so we must make sure that parent points to the actual parent that has children.
- if (parent != root)
- parent = model->index(parent.row(), 0, parent.parent());
if (i>=0 && !parent.isValid()) {
//modelIndex() should never return something invalid for the real items.
@@ -3132,13 +3118,9 @@ void QTreeViewPrivate::layout(int i)
int last = 0;
int children = 0;
- int firstColumn = 0;
- while (header->isSectionHidden(firstColumn) && firstColumn < header->count())
- ++firstColumn;
-
for (int j = first; j < first + count; ++j) {
- current = model->index(j - first, firstColumn, parent);
- if (isRowHidden(current.sibling(current.row(), 0))) {
+ current = model->index(j - first, 0, parent);
+ if (isRowHidden(current)) {
++hidden;
last = j - hidden + children;
} else {
@@ -3219,19 +3201,18 @@ int QTreeViewPrivate::itemHeight(int item) const
*/
int QTreeViewPrivate::coordinateForItem(int item) const
{
- Q_Q(const QTreeView);
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights)
- return (item * defaultItemHeight) - q->verticalScrollBar()->value();
+ return (item * defaultItemHeight) - vbar->value();
// ### optimize (spans or caching)
int y = 0;
for (int i = 0; i < viewItems.count(); ++i) {
if (i == item)
- return y - q->verticalScrollBar()->value();
+ return y - vbar->value();
y += itemHeight(i);
}
} else { // ScrollPerItem
- int topViewItemIndex = q->verticalScrollBar()->value();
+ int topViewItemIndex = vbar->value();
if (uniformRowHeights)
return defaultItemHeight * (item - topViewItemIndex);
if (item >= topViewItemIndex) {
@@ -3271,7 +3252,6 @@ int QTreeViewPrivate::coordinateForItem(int item) const
*/
int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
{
- Q_Q(const QTreeView);
const int itemCount = viewItems.count();
if (itemCount == 0)
return -1;
@@ -3279,19 +3259,19 @@ int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
return -1;
if (verticalScrollMode == QAbstractItemView::ScrollPerPixel) {
if (uniformRowHeights) {
- const int viewItemIndex = (coordinate + q->verticalScrollBar()->value()) / defaultItemHeight;
+ const int viewItemIndex = (coordinate + vbar->value()) / defaultItemHeight;
return ((viewItemIndex >= itemCount || viewItemIndex < 0) ? -1 : viewItemIndex);
}
// ### optimize
int viewItemCoordinate = 0;
- const int contentsCoordinate = coordinate + q->verticalScrollBar()->value();
+ const int contentsCoordinate = coordinate + vbar->value();
for (int viewItemIndex = 0; viewItemIndex < viewItems.count(); ++viewItemIndex) {
viewItemCoordinate += itemHeight(viewItemIndex);
if (viewItemCoordinate >= contentsCoordinate)
return (viewItemIndex >= itemCount ? -1 : viewItemIndex);
}
} else { // ScrollPerItem
- int topViewItemIndex = q->verticalScrollBar()->value();
+ int topViewItemIndex = vbar->value();
if (uniformRowHeights) {
if (coordinate < 0)
coordinate -= defaultItemHeight - 1;
@@ -3321,15 +3301,11 @@ int QTreeViewPrivate::itemAtCoordinate(int coordinate) const
int QTreeViewPrivate::viewIndex(const QModelIndex &_index) const
{
- Q_Q(const QTreeView);
if (!_index.isValid() || viewItems.isEmpty())
return -1;
const int totalCount = viewItems.count();
- int firstColumn = 0;
- while (q->isColumnHidden(firstColumn) && firstColumn < header->count())
- ++firstColumn;
- const QModelIndex index = _index.sibling(_index.row(), firstColumn);
+ const QModelIndex index = _index.sibling(_index.row(), 0);
// A quick check near the last item to see if we are just incrementing
@@ -3387,8 +3363,7 @@ QModelIndex QTreeViewPrivate::modelIndex(int i, int column) const
int QTreeViewPrivate::firstVisibleItem(int *offset) const
{
- Q_Q(const QTreeView);
- const int value = q->verticalScrollBar()->value();
+ const int value = vbar->value();
if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
if (offset)
*offset = 0;
@@ -3465,9 +3440,9 @@ void QTreeViewPrivate::updateScrollBars()
if (verticalScrollMode == QAbstractItemView::ScrollPerItem) {
if (!viewItems.isEmpty())
itemsInViewport = qMax(1, itemsInViewport);
- q->verticalScrollBar()->setRange(0, viewItems.count() - itemsInViewport);
- q->verticalScrollBar()->setPageStep(itemsInViewport);
- q->verticalScrollBar()->setSingleStep(1);
+ vbar->setRange(0, viewItems.count() - itemsInViewport);
+ vbar->setPageStep(itemsInViewport);
+ vbar->setSingleStep(1);
} else { // scroll per pixel
int contentsHeight = 0;
if (uniformRowHeights) {
@@ -3476,9 +3451,9 @@ void QTreeViewPrivate::updateScrollBars()
for (int i = 0; i < viewItems.count(); ++i)
contentsHeight += itemHeight(i);
}
- q->verticalScrollBar()->setRange(0, contentsHeight - viewportSize.height());
- q->verticalScrollBar()->setPageStep(viewportSize.height());
- q->verticalScrollBar()->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
+ vbar->setRange(0, contentsHeight - viewportSize.height());
+ vbar->setPageStep(viewportSize.height());
+ vbar->setSingleStep(qMax(viewportSize.height() / (itemsInViewport + 1), 2));
}
const int columnCount = header->count();
@@ -3494,23 +3469,23 @@ void QTreeViewPrivate::updateScrollBars()
if (columnCount > 0)
columnsInViewport = qMax(1, columnsInViewport);
if (horizontalScrollMode == QAbstractItemView::ScrollPerItem) {
- q->horizontalScrollBar()->setRange(0, columnCount - columnsInViewport);
- q->horizontalScrollBar()->setPageStep(columnsInViewport);
- q->horizontalScrollBar()->setSingleStep(1);
+ hbar->setRange(0, columnCount - columnsInViewport);
+ hbar->setPageStep(columnsInViewport);
+ hbar->setSingleStep(1);
} else { // scroll per pixel
const int horizontalLength = header->length();
const QSize maxSize = q->maximumViewportSize();
- if (maxSize.width() >= horizontalLength && q->verticalScrollBar()->maximum() <= 0)
+ if (maxSize.width() >= horizontalLength && vbar->maximum() <= 0)
viewportSize = maxSize;
- q->horizontalScrollBar()->setPageStep(viewportSize.width());
- q->horizontalScrollBar()->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
- q->horizontalScrollBar()->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
+ hbar->setPageStep(viewportSize.width());
+ hbar->setRange(0, qMax(horizontalLength - viewportSize.width(), 0));
+ hbar->setSingleStep(qMax(viewportSize.width() / (columnsInViewport + 1), 2));
}
}
int QTreeViewPrivate::itemDecorationAt(const QPoint &pos) const
{
- const_cast<QTreeView *>(q_func())->executeDelayedItemsLayout();
+ executePostedLayout();
int x = pos.x();
int column = header->logicalIndexAt(x);
if (column != 0)
@@ -3576,7 +3551,8 @@ QList<QPair<int, int> > QTreeViewPrivate::columnRanges(const QModelIndex &topInd
QPair<int, int> current;
current.first = -2; // -1 is not enough because -1+1 = 0
current.second = -2;
- foreach (int logicalColumn, logicalIndexes) {
+ for(int i = 0; i < logicalIndexes.count(); ++i) {
+ const int logicalColumn = logicalIndexes.at(i);
if (current.second + 1 != logicalColumn) {
if (current.first != -2) {
//let's save the current one
diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp
index 0f2a27c..709c7b9 100644
--- a/src/gui/itemviews/qtreewidget.cpp
+++ b/src/gui/itemviews/qtreewidget.cpp
@@ -577,7 +577,7 @@ void QTreeModel::sort(int column, Qt::SortOrder order)
if (column < 0 || column >= columnCount())
return;
- //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
+ //layoutAboutToBeChanged and layoutChanged will be called by sortChildren
rootItem->sortChildren(column, order, true);
}
@@ -1787,7 +1787,11 @@ QVariant QTreeWidgetItem::data(int column, int role) const
bool QTreeWidgetItem::operator<(const QTreeWidgetItem &other) const
{
int column = view ? view->sortColumn() : 0;
- return text(column) < other.text(column);
+ const QVariant v1 = data(column, Qt::DisplayRole);
+ const QVariant v2 = other.data(column, Qt::DisplayRole);
+ if (QAbstractItemModelPrivate::canConvertToDouble(v1) && QAbstractItemModelPrivate::canConvertToDouble(v2))
+ return v1.toDouble() < v2.toDouble();
+ return v1.toString() < v2.toString();
}
#ifndef QT_NO_DATASTREAM
@@ -1827,6 +1831,7 @@ void QTreeWidgetItem::write(QDataStream &out) const
{
out << values << d->display;
}
+#endif // QT_NO_DATASTREAM
/*!
\since 4.1
@@ -1863,8 +1868,6 @@ QTreeWidgetItem &QTreeWidgetItem::operator=(const QTreeWidgetItem &other)
return *this;
}
-#endif // QT_NO_DATASTREAM
-
/*!
Appends the \a child item to the list of children.
@@ -2075,7 +2078,7 @@ void QTreeWidgetItemPrivate::sortChildren(int column, Qt::SortOrder order, bool
if (climb) {
QList<QTreeWidgetItem*>::iterator it = q->children.begin();
for (; it != q->children.end(); ++it) {
- //here we call the private object's method to avoid emitting
+ //here we call the private object's method to avoid emitting
//the layoutAboutToBeChanged and layoutChanged signals
(*it)->d->sortChildren(column, order, climb);
}
@@ -2277,11 +2280,10 @@ void QTreeWidgetPrivate::_q_emitCurrentItemChanged(const QModelIndex &current,
void QTreeWidgetPrivate::_q_sort()
{
- Q_Q(QTreeWidget);
if (sortingEnabled) {
- int column = q->header()->sortIndicatorSection();
- Qt::SortOrder order = q->header()->sortIndicatorOrder();
- model()->sort(column, order);
+ int column = header->sortIndicatorSection();
+ Qt::SortOrder order = header->sortIndicatorOrder();
+ treeModel()->sort(column, order);
}
}
@@ -2290,7 +2292,7 @@ void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, con
Q_Q(QTreeWidget);
QModelIndexList indices = selected.indexes();
int i;
- QTreeModel *m = model();
+ QTreeModel *m = treeModel();
for (i = 0; i < indices.count(); ++i) {
QTreeWidgetItem *item = m->item(indices.at(i));
item->d->selected = true;
@@ -2308,13 +2310,12 @@ void QTreeWidgetPrivate::_q_selectionChanged(const QItemSelection &selected, con
void QTreeWidgetPrivate::_q_dataChanged(const QModelIndex &topLeft,
const QModelIndex &bottomRight)
{
- Q_Q(QTreeWidget);
if (sortingEnabled && topLeft.isValid() && bottomRight.isValid()
- && !model()->sortPendingTimer.isActive()) {
- int column = q->header()->sortIndicatorSection();
+ && !treeModel()->sortPendingTimer.isActive()) {
+ int column = header->sortIndicatorSection();
if (column >= topLeft.column() && column <= bottomRight.column()) {
- Qt::SortOrder order = q->header()->sortIndicatorOrder();
- model()->ensureSorted(column, order, topLeft.row(),
+ Qt::SortOrder order = header->sortIndicatorOrder();
+ treeModel()->ensureSorted(column, order, topLeft.row(),
bottomRight.row(), topLeft.parent());
}
}
@@ -2542,7 +2543,7 @@ QTreeWidget::~QTreeWidget()
int QTreeWidget::columnCount() const
{
Q_D(const QTreeWidget);
- return d->model()->columnCount();
+ return d->model->columnCount();
}
/*
@@ -2554,7 +2555,7 @@ void QTreeWidget::setColumnCount(int columns)
Q_D(QTreeWidget);
if (columns < 0)
return;
- d->model()->setColumnCount(columns);
+ d->treeModel()->setColumnCount(columns);
}
/*!
@@ -2571,7 +2572,7 @@ void QTreeWidget::setColumnCount(int columns)
QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
{
Q_D(const QTreeWidget);
- return d->model()->rootItem;
+ return d->treeModel()->rootItem;
}
/*!
@@ -2584,7 +2585,7 @@ QTreeWidgetItem *QTreeWidget::invisibleRootItem() const
QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
{
Q_D(const QTreeWidget);
- return d->model()->rootItem->child(index);
+ return d->treeModel()->rootItem->child(index);
}
/*!
@@ -2599,7 +2600,7 @@ QTreeWidgetItem *QTreeWidget::topLevelItem(int index) const
int QTreeWidget::topLevelItemCount() const
{
Q_D(const QTreeWidget);
- return d->model()->rootItem->childCount();
+ return d->treeModel()->rootItem->childCount();
}
/*!
@@ -2613,7 +2614,7 @@ int QTreeWidget::topLevelItemCount() const
void QTreeWidget::insertTopLevelItem(int index, QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- d->model()->rootItem->insertChild(index, item);
+ d->treeModel()->rootItem->insertChild(index, item);
}
/*!
@@ -2638,7 +2639,7 @@ void QTreeWidget::addTopLevelItem(QTreeWidgetItem *item)
QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
{
Q_D(QTreeWidget);
- return d->model()->rootItem->takeChild(index);
+ return d->treeModel()->rootItem->takeChild(index);
}
/*!
@@ -2647,8 +2648,8 @@ QTreeWidgetItem *QTreeWidget::takeTopLevelItem(int index)
int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- d->model()->executePendingSort();
- return d->model()->rootItem->children.indexOf(item);
+ d->treeModel()->executePendingSort();
+ return d->treeModel()->rootItem->children.indexOf(item);
}
/*!
@@ -2660,8 +2661,8 @@ int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item)
int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- d->model()->executePendingSort();
- return d->model()->rootItem->children.indexOf(item);
+ d->treeModel()->executePendingSort();
+ return d->treeModel()->rootItem->children.indexOf(item);
}
/*!
@@ -2676,7 +2677,7 @@ int QTreeWidget::indexOfTopLevelItem(QTreeWidgetItem *item) const
void QTreeWidget::insertTopLevelItems(int index, const QList<QTreeWidgetItem*> &items)
{
Q_D(QTreeWidget);
- d->model()->rootItem->insertChildren(index, items);
+ d->treeModel()->rootItem->insertChildren(index, items);
}
/*!
@@ -2698,7 +2699,7 @@ void QTreeWidget::addTopLevelItems(const QList<QTreeWidgetItem*> &items)
QTreeWidgetItem *QTreeWidget::headerItem() const
{
Q_D(const QTreeWidget);
- return d->model()->headerItem;
+ return d->treeModel()->headerItem;
}
/*!
@@ -2719,16 +2720,16 @@ void QTreeWidget::setHeaderItem(QTreeWidgetItem *item)
int oldCount = columnCount();
if (oldCount < item->columnCount())
- d->model()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount());
+ d->treeModel()->beginInsertColumns(QModelIndex(), oldCount, item->columnCount());
else
- d->model()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount);
- delete d->model()->headerItem;
- d->model()->headerItem = item;
+ d->treeModel()->beginRemoveColumns(QModelIndex(), item->columnCount(), oldCount);
+ delete d->treeModel()->headerItem;
+ d->treeModel()->headerItem = item;
if (oldCount < item->columnCount())
- d->model()->endInsertColumns();
+ d->treeModel()->endInsertColumns();
else
- d->model()->endRemoveColumns();
- d->model()->headerDataChanged(Qt::Horizontal, 0, oldCount);
+ d->treeModel()->endRemoveColumns();
+ d->treeModel()->headerDataChanged(Qt::Horizontal, 0, oldCount);
}
@@ -2745,8 +2746,7 @@ void QTreeWidget::setHeaderLabels(const QStringList &labels)
Q_D(QTreeWidget);
if (columnCount() < labels.count())
setColumnCount(labels.count());
- QTreeModel *model = d->model();
- QTreeWidgetItem *item = model->headerItem;
+ QTreeWidgetItem *item = d->treeModel()->headerItem;
for (int i = 0; i < labels.count(); ++i)
item->setText(i, labels.at(i));
}
@@ -2874,7 +2874,7 @@ void QTreeWidget::sortItems(int column, Qt::SortOrder order)
{
Q_D(QTreeWidget);
header()->setSortIndicator(column, order);
- d->model()->sort(column, order);
+ d->model->sort(column, order);
}
/*!
@@ -3041,7 +3041,7 @@ QList<QTreeWidgetItem*> QTreeWidget::selectedItems() const
QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFlags flags, int column) const
{
Q_D(const QTreeWidget);
- QModelIndexList indexes = d->model()->match(model()->index(0, column, QModelIndex()),
+ QModelIndexList indexes = d->model->match(model()->index(0, column, QModelIndex()),
Qt::DisplayRole, text, -1, flags);
QList<QTreeWidgetItem*> items;
for (int i = 0; i < indexes.size(); ++i)
@@ -3059,11 +3059,11 @@ QList<QTreeWidgetItem*> QTreeWidget::findItems(const QString &text, Qt::MatchFla
bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return header()->isHidden();
if (d->hiddenIndexes.isEmpty())
return false;
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
return d->isRowHidden(d->index(item));
}
@@ -3079,7 +3079,7 @@ bool QTreeWidget::isItemHidden(const QTreeWidgetItem *item) const
void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
{
Q_D(QTreeWidget);
- if (item == d->model()->headerItem) {
+ if (item == d->treeModel()->headerItem) {
header()->setHidden(hide);
} else {
const QModelIndex index = d->index(item);
@@ -3099,7 +3099,7 @@ void QTreeWidget::setItemHidden(const QTreeWidgetItem *item, bool hide)
bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
return isExpanded(d->index(item));
}
@@ -3116,7 +3116,7 @@ bool QTreeWidget::isItemExpanded(const QTreeWidgetItem *item) const
void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
{
Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
setExpanded(d->index(item), expand);
}
@@ -3131,7 +3131,7 @@ void QTreeWidget::setItemExpanded(const QTreeWidgetItem *item, bool expand)
bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return false; // We can't set the header items to spanning
const QModelIndex index = d->index(item);
return isFirstColumnSpanned(index.row(), index.parent());
@@ -3148,7 +3148,7 @@ bool QTreeWidget::isFirstItemColumnSpanned(const QTreeWidgetItem *item) const
void QTreeWidget::setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool span)
{
Q_D(QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return; // We can't set header items to spanning
const QModelIndex index = d->index(item);
setFirstColumnSpanned(index.row(), index.parent(), span);
@@ -3162,7 +3162,7 @@ void QTreeWidget::setFirstItemColumnSpanned(const QTreeWidgetItem *item, bool sp
QTreeWidgetItem *QTreeWidget::itemAbove(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return 0;
const QModelIndex index = d->index(item);
const QModelIndex above = indexAbove(index);
@@ -3177,7 +3177,7 @@ QTreeWidgetItem *QTreeWidget::itemAbove(const QTreeWidgetItem *item) const
QTreeWidgetItem *QTreeWidget::itemBelow(const QTreeWidgetItem *item) const
{
Q_D(const QTreeWidget);
- if (item == d->model()->headerItem)
+ if (item == d->treeModel()->headerItem)
return 0;
const QModelIndex index = d->index(item);
const QModelIndex below = indexBelow(index);
@@ -3217,7 +3217,7 @@ void QTreeWidget::scrollToItem(const QTreeWidgetItem *item, QAbstractItemView::S
void QTreeWidget::expandItem(const QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
expand(d->index(item));
}
@@ -3230,7 +3230,7 @@ void QTreeWidget::expandItem(const QTreeWidgetItem *item)
void QTreeWidget::collapseItem(const QTreeWidgetItem *item)
{
Q_D(QTreeWidget);
- QTreeModel::SkipSorting skipSorting(d->model());
+ QTreeModel::SkipSorting skipSorting(d->treeModel());
collapse(d->index(item));
}
@@ -3247,7 +3247,7 @@ void QTreeWidget::clear()
{
Q_D(QTreeWidget);
selectionModel()->clear();
- d->model()->clear();
+ d->treeModel()->clear();
}
/*!
@@ -3272,7 +3272,7 @@ QStringList QTreeWidget::mimeTypes() const
QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem*> items) const
{
Q_D(const QTreeWidget);
- if (d->model()->cachedIndexes.isEmpty()) {
+ if (d->treeModel()->cachedIndexes.isEmpty()) {
QList<QModelIndex> indexes;
for (int i = 0; i < items.count(); ++i) {
QTreeWidgetItem *item = items.at(i);
@@ -3280,9 +3280,9 @@ QMimeData *QTreeWidget::mimeData(const QList<QTreeWidgetItem*> items) const
indexes << indexFromItem(item, c);
}
}
- return model()->QAbstractItemModel::mimeData(indexes);
+ return d->model->QAbstractItemModel::mimeData(indexes);
}
- return d->model()->internalMimeData();
+ return d->treeModel()->internalMimeData();
}
/*!
@@ -3426,7 +3426,7 @@ bool QTreeWidget::event(QEvent *e)
{
Q_D(QTreeWidget);
if (e->type() == QEvent::Polish)
- d->model()->executePendingSort();
+ d->treeModel()->executePendingSort();
return QTreeView::event(e);
}
diff --git a/src/gui/itemviews/qtreewidget_p.h b/src/gui/itemviews/qtreewidget_p.h
index a089cf5..fb0ee11 100644
--- a/src/gui/itemviews/qtreewidget_p.h
+++ b/src/gui/itemviews/qtreewidget_p.h
@@ -219,12 +219,11 @@ class QTreeWidgetPrivate : public QTreeViewPrivate
Q_DECLARE_PUBLIC(QTreeWidget)
public:
QTreeWidgetPrivate() : QTreeViewPrivate(), explicitSortColumn(-1) {}
- inline QTreeModel *model() const
- { return qobject_cast<QTreeModel*>(q_func()->model()); }
+ inline QTreeModel *treeModel() const { return qobject_cast<QTreeModel*>(model); }
inline QModelIndex index(const QTreeWidgetItem *item, int column = 0) const
- { return model()->index(item, column); }
+ { return treeModel()->index(item, column); }
inline QTreeWidgetItem *item(const QModelIndex &index) const
- { return model()->item(index); }
+ { return treeModel()->item(index); }
void _q_emitItemPressed(const QModelIndex &index);
void _q_emitItemClicked(const QModelIndex &index);
void _q_emitItemDoubleClicked(const QModelIndex &index);
diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri
index 8f0692b..8e3b6cb 100644
--- a/src/gui/kernel/kernel.pri
+++ b/src/gui/kernel/kernel.pri
@@ -214,7 +214,7 @@ embedded {
MENU_NIB.path = Resources
MENU_NIB.version = Versions
QMAKE_BUNDLE_DATA += MENU_NIB
- RESOURCES += mac/maccursors.qrc
+ RESOURCES += mac/macresources.qrc
LIBS += -framework AppKit
}
diff --git a/src/gui/kernel/qaction.cpp b/src/gui/kernel/qaction.cpp
index b1db8d6..9dedc9d 100644
--- a/src/gui/kernel/qaction.cpp
+++ b/src/gui/kernel/qaction.cpp
@@ -76,7 +76,7 @@ static QString qt_strippedText(QString s)
s.remove(i-1,1);
}
return s.trimmed();
-};
+}
QActionPrivate::QActionPrivate() : group(0), enabled(1), forceDisabled(0),
@@ -137,25 +137,31 @@ void QActionPrivate::redoGrab(QShortcutMap &map)
void QActionPrivate::redoGrabAlternate(QShortcutMap &map)
{
Q_Q(QAction);
- foreach (int id, alternateShortcutIds)
- if (id)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
map.removeShortcut(id, q);
+ }
alternateShortcutIds.clear();
if (alternateShortcuts.isEmpty())
return;
- foreach (const QKeySequence& alternate, alternateShortcuts) {
+ for(int i = 0; i < alternateShortcuts.count(); ++i) {
+ const QKeySequence& alternate = alternateShortcuts.at(i);
if (!alternate.isEmpty())
alternateShortcutIds.append(map.addShortcut(q, alternate, shortcutContext));
else
alternateShortcutIds.append(0);
}
if (!enabled) {
- foreach (int id, alternateShortcutIds)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
map.setShortcutEnabled(false, id, q);
+ }
}
if (!autorepeat) {
- foreach (int id, alternateShortcutIds)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ const int id = alternateShortcutIds.at(i);
map.setShortcutAutoRepeat(false, id, q);
+ }
}
}
@@ -164,9 +170,10 @@ void QActionPrivate::setShortcutEnabled(bool enable, QShortcutMap &map)
Q_Q(QAction);
if (shortcutId)
map.setShortcutEnabled(enable, shortcutId, q);
- foreach (int id, alternateShortcutIds)
- if (id)
+ for(int i = 0; i < alternateShortcutIds.count(); ++i) {
+ if (const int id = alternateShortcutIds.at(i))
map.setShortcutEnabled(enable, id, q);
+ }
}
#endif // QT_NO_SHORTCUT
@@ -616,8 +623,10 @@ QAction::~QAction()
#ifndef QT_NO_SHORTCUT
if (d->shortcutId && qApp) {
qApp->d_func()->shortcutMap.removeShortcut(d->shortcutId, this);
- foreach (int id, d->alternateShortcutIds)
+ for(int i = 0; i < d->alternateShortcutIds.count(); ++i) {
+ const int id = d->alternateShortcutIds.at(i);
qApp->d_func()->shortcutMap.removeShortcut(id, this);
+ }
}
#endif
}
@@ -1152,6 +1161,8 @@ void QAction::activate(ActionEvent event)
// the checked action of an exclusive group cannot be unchecked
if (d->checked && (d->group && d->group->isExclusive()
&& d->group->checkedAction() == this)) {
+ if (guard)
+ emit triggered(true);
QMetaObject::removeGuard(&guard);
return;
}
@@ -1395,7 +1406,7 @@ QAction::SoftKeyRole QAction::softKeyRole() const
void QAction::setIconVisibleInMenu(bool visible)
{
Q_D(QAction);
- if (visible != (bool)d->iconVisibleInMenu) {
+ if (d->iconVisibleInMenu == -1 || visible != bool(d->iconVisibleInMenu)) {
int oldValue = d->iconVisibleInMenu;
d->iconVisibleInMenu = visible;
// Only send data changed if we really need to.
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index aa6d21e..64009d4 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -92,7 +92,7 @@
#include "qapplication.h"
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qdatetime.h"
#include "qguifunctions_wince.h"
extern bool qt_wince_is_smartphone(); //qguifunctions_wince.cpp
@@ -104,15 +104,12 @@ extern bool qt_wince_is_pocket_pc(); //qguifunctions_wince.cpp
static void initResources()
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_INIT_RESOURCE(qstyle_wince);
#else
Q_INIT_RESOURCE(qstyle);
#endif
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- Q_INIT_RESOURCE(qpaintengine_d3d);
-#endif
Q_INIT_RESOURCE(qmessagebox);
#if !defined(QT_NO_PRINTDIALOG)
Q_INIT_RESOURCE(qprintdialog);
@@ -133,7 +130,7 @@ QInputContext *QApplicationPrivate::inputContext;
bool QApplicationPrivate::quitOnLastWindowClosed = true;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
int QApplicationPrivate::autoMaximizeThreshold = -1;
bool QApplicationPrivate::autoSipEnabled = false;
#else
@@ -399,6 +396,7 @@ Qt::MouseButtons QApplicationPrivate::mouse_buttons = Qt::NoButton;
Qt::KeyboardModifiers QApplicationPrivate::modifier_buttons = Qt::NoModifier;
QStyle *QApplicationPrivate::app_style = 0; // default application style
+QString QApplicationPrivate::styleOverride; // style override
#ifndef QT_NO_STYLE_STYLESHEET
QString QApplicationPrivate::styleSheet; // default application stylesheet
@@ -413,7 +411,7 @@ QPalette *QApplicationPrivate::set_pal = 0; // default palette set by pro
QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system
QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization
-Q_GLOBAL_STATIC(QMutex, applicationFontMutex);
+Q_GLOBAL_STATIC(QMutex, applicationFontMutex)
QFont *QApplicationPrivate::app_font = 0; // default application font
QFont *QApplicationPrivate::sys_font = 0; // default system font
QFont *QApplicationPrivate::set_font = 0; // default font set by programmer
@@ -453,7 +451,7 @@ bool QApplicationPrivate::animate_toolbox = false;
bool QApplicationPrivate::widgetCount = false;
bool QApplicationPrivate::auto_sip_on_mouse_focus = false;
QString* QApplicationPrivate::styleOverride = 0;
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
bool QApplicationPrivate::inSizeMove = false;
#endif
#ifdef QT_KEYPAD_NAVIGATION
@@ -509,8 +507,6 @@ QWidgetList * qt_modal_stack=0; // stack of modal widgets
*/
void QApplicationPrivate::process_cmdline()
{
- Q_Q(QApplication);
- Q_UNUSED(q);// only static members being used.
// process platform-indep command line
if (!qt_is_gui_used || !argc)
return;
@@ -555,7 +551,7 @@ void QApplicationPrivate::process_cmdline()
#endif
} else if (qstrcmp(arg, "-reverse") == 0) {
force_reverse = true;
- q->setLayoutDirection(Qt::RightToLeft);
+ QApplication::setLayoutDirection(Qt::RightToLeft);
} else if (qstrcmp(arg, "-widgetcount") == 0) {
widgetCount = true;
} else if (arg == "-graphicssystem" && i < argc-1) {
@@ -568,9 +564,7 @@ void QApplicationPrivate::process_cmdline()
delete app_style;
app_style = 0;
}
- if (!styleOverride)
- styleOverride = new QString;
- *styleOverride = s;
+ styleOverride = s;
}
}
@@ -635,13 +629,6 @@ void QApplicationPrivate::process_cmdline()
and QPixmaps. Available options are \c{raster} and \c{opengl}.
\endlist
- The Windows version of Qt supports an additional command line option, if
- Direct3D support has been compiled into Qt:
- \list
- \o -direct3d will make the Direct3D paint engine the default widget
- paint engine in Qt. \bold {This functionality is experimental.}
- \endlist
-
The X11 version of Qt supports some traditional X11 command line options:
\list
\o -display \e display, sets the X display (default is $DISPLAY).
@@ -863,6 +850,11 @@ void QApplicationPrivate::initialize()
// trigger registering of QVariant's GUI types
extern int qRegisterGuiVariant();
qRegisterGuiVariant();
+#ifndef QT_NO_STATEMACHINE
+ // trigger registering of QStateMachine's GUI types
+ extern int qRegisterGuiStateMachine();
+ qRegisterGuiStateMachine();
+#endif
is_app_running = true; // no longer starting up
@@ -881,7 +873,7 @@ void QApplicationPrivate::initialize()
q->setAttribute(Qt::AA_NativeWindows);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#ifdef QT_AUTO_MAXIMIZE_THRESHOLD
autoMaximizeThreshold = QT_AUTO_MAXIMIZE_THRESHOLD;
#else
@@ -890,7 +882,7 @@ void QApplicationPrivate::initialize()
else
autoMaximizeThreshold = -1;
#endif //QT_AUTO_MAXIMIZE_THRESHOLD
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
// Set up which span functions should be used in raster engine...
qInitDrawhelperAsm();
@@ -1086,6 +1078,11 @@ QApplication::~QApplication()
QApplicationPrivate::widgetCount = false;
QApplicationPrivate::auto_sip_on_mouse_focus = false;
+#ifndef QT_NO_STATEMACHINE
+ // trigger unregistering of QStateMachine's GUI types
+ extern int qUnregisterGuiStateMachine();
+ qUnregisterGuiStateMachine();
+#endif
// trigger unregistering of QVariant's GUI types
extern int qUnregisterGuiVariant();
qUnregisterGuiVariant();
@@ -1248,7 +1245,7 @@ bool QApplication::compressEvent(QEvent *event, QObject *receiver, QPostEventLis
The default is platform dependent.
*/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void QApplication::setAutoMaximizeThreshold(const int threshold)
{
QApplicationPrivate::autoMaximizeThreshold = threshold;
@@ -1310,46 +1307,14 @@ QStyle *QApplication::style()
return 0;
}
-#if defined(Q_WS_X11)
- if(!QApplicationPrivate::styleOverride)
- QApplicationPrivate::x11_initialize_style(); // run-time search for default style
-#endif
if (!QApplicationPrivate::app_style) {
// Compile-time search for default style
//
QString style;
- if (QApplicationPrivate::styleOverride) {
- style = *QApplicationPrivate::styleOverride;
- delete QApplicationPrivate::styleOverride;
- QApplicationPrivate::styleOverride = 0;
- } else {
-#if defined(Q_WS_WIN) && defined(Q_OS_WINCE)
- if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
- style = QLatin1String("WindowsMobile");
- else
- style = QLatin1String("WindowsCE");
-
-#elif defined(Q_WS_WIN)
- if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
- && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
- style = QLatin1String("WindowsVista");
- else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
- && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
- style = QLatin1String("WindowsXP");
- else
- style = QLatin1String("Windows"); // default styles for Windows
-#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
- style = QLatin1String("CDE"); // default style for X11 on Solaris
-#elif defined(Q_WS_S60)
- style = QLatin1String("S60"); // default style for S60
-#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
- style = QLatin1String("SGI"); // default style for X11 on IRIX
-#elif defined(Q_WS_X11) || defined(Q_WS_QWS)
- style = QLatin1String("Plastique"); // default style for X11 and small devices
-#elif defined(Q_WS_MAC)
- style = QLatin1String("Macintosh"); // default style for all Mac's
-#endif
- }
+ if (!QApplicationPrivate::styleOverride.isEmpty())
+ style = QApplicationPrivate::styleOverride;
+ else
+ style = QApplicationPrivate::desktopStyleKey();
QStyle *&app_style = QApplicationPrivate::app_style;
app_style = QStyleFactory::create(style);
@@ -1437,9 +1402,8 @@ void QApplication::setStyle(QStyle *style)
} else
#endif // QT_NO_STYLE_STYLESHEET
QApplicationPrivate::app_style = style;
-
QApplicationPrivate::app_style->setParent(qApp); // take ownership
-
+
// take care of possible palette requirements of certain gui
// styles. Do it before polishing the application since the style
// might call QApplication::setPalette() itself
@@ -1961,6 +1925,42 @@ void QApplicationPrivate::setSystemFont(const QFont &font)
QApplication::setFont(*sys_font);
}
+/*! \internal
+*/
+QString QApplicationPrivate::desktopStyleKey()
+{
+QString desktopstyle;
+#if defined(Q_WS_WIN) && defined(Q_WS_WINCE)
+ if (qt_wince_is_smartphone() || qt_wince_is_pocket_pc())
+ desktopstyle = QLatin1String("WindowsMobile");
+ else
+ desktopstyle = QLatin1String("WindowsCE");
+
+#elif defined(Q_WS_WIN)
+ if ((QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ desktopstyle = QLatin1String("WindowsVista");
+ else if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
+ && QSysInfo::WindowsVersion < QSysInfo::WV_NT_based))
+ desktopstyle = QLatin1String("WindowsXP");
+ else
+ desktopstyle = QLatin1String("Windows"); // default styles for Windows
+#elif defined(Q_WS_X11) && defined(Q_OS_SOLARIS)
+ desktopstyle = QLatin1String("CDE"); // default style for X11 on Solaris
+#elif defined(Q_WS_S60)
+ style = QLatin1String("S60");
+#elif defined(Q_WS_X11) && defined(Q_OS_IRIX)
+ desktopstyle = QLatin1String("SGI"); // default style for X11 on IRIX
+#elif defined(Q_WS_QWS)
+ desktopstyle = QLatin1String("Plastique"); // default style for X11 and small devices
+#elif defined(Q_WS_X11)
+ desktopstyle = QApplicationPrivate::x11_desktop_style(); // default runtime dependant style for X11
+#elif defined(Q_WS_MAC)
+ desktopstyle = QLatin1String("Macintosh"); // default style for all Mac's
+#endif
+ return desktopstyle;
+}
+
/*!
\property QApplication::windowIcon
\brief the default window icon
@@ -2122,8 +2122,9 @@ void QApplicationPrivate::setFocusWidget(QWidget *focus, Qt::FocusReason reason)
if(focus && QApplicationPrivate::focus_widget == focus) {
if (focus->testAttribute(Qt::WA_InputMethodEnabled)) {
QInputContext *qic = focus->inputContext();
- if (qic && focus_widget->testAttribute(Qt::WA_WState_Created))
- qic->setFocusWidget( focus_widget );
+ if (qic && focus->testAttribute(Qt::WA_WState_Created)
+ && focus->isEnabled())
+ qic->setFocusWidget(focus);
}
QFocusEvent in(QEvent::FocusIn, reason);
QPointer<QWidget> that = focus;
@@ -2609,14 +2610,14 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
QEvent leaveEvent(QEvent::Leave);
for (int i = 0; i < leaveList.size(); ++i) {
w = leaveList.at(i);
- if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+ if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
if (leaveAfterRelease == w)
leaveAfterRelease = 0;
#endif
QApplication::sendEvent(w, &leaveEvent);
if (w->testAttribute(Qt::WA_Hover) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
Q_ASSERT(instance());
QHoverEvent he(QEvent::HoverLeave, QPoint(-1, -1), w->mapFromGlobal(QApplicationPrivate::instance()->hoverGlobalPos));
qApp->d_func()->notify_helper(w, &he);
@@ -2627,10 +2628,10 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) {
QEvent enterEvent(QEvent::Enter);
for (int i = 0; i < enterList.size(); ++i) {
w = enterList.at(i);
- if (!qApp->activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
+ if (!QApplication::activeModalWidget() || QApplicationPrivate::tryModalHelper(w, 0)) {
QApplication::sendEvent(w, &enterEvent);
if (w->testAttribute(Qt::WA_Hover) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
QHoverEvent he(QEvent::HoverEnter, w->mapFromGlobal(posEnter), QPoint(-1, -1));
qApp->d_func()->notify_helper(w, &he);
}
@@ -2704,7 +2705,7 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
widget = widget->window();
if (!modalState())
return false;
- if (qApp->activePopupWidget() == widget)
+ if (QApplication::activePopupWidget() == widget)
return false;
for (int i = 0; i < qt_modal_stack->size(); ++i) {
@@ -2793,7 +2794,7 @@ bool QApplicationPrivate::isBlockedByModal(QWidget *widget)
void QApplicationPrivate::enterModal(QWidget *widget)
{
QSet<QWidget*> blocked;
- QList<QWidget*> windows = qApp->topLevelWidgets();
+ QList<QWidget*> windows = QApplication::topLevelWidgets();
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
if (window->windowType() != Qt::Tool && isBlockedByModal(window))
@@ -2802,7 +2803,7 @@ void QApplicationPrivate::enterModal(QWidget *widget)
enterModal_sys(widget);
- windows = qApp->topLevelWidgets();
+ windows = QApplication::topLevelWidgets();
QEvent e(QEvent::WindowBlocked);
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
@@ -2816,7 +2817,7 @@ void QApplicationPrivate::enterModal(QWidget *widget)
void QApplicationPrivate::leaveModal(QWidget *widget)
{
QSet<QWidget*> blocked;
- QList<QWidget*> windows = qApp->topLevelWidgets();
+ QList<QWidget*> windows = QApplication::topLevelWidgets();
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
if (window->windowType() != Qt::Tool && isBlockedByModal(window))
@@ -2825,7 +2826,7 @@ void QApplicationPrivate::leaveModal(QWidget *widget)
leaveModal_sys(widget);
- windows = qApp->topLevelWidgets();
+ windows = QApplication::topLevelWidgets();
QEvent e(QEvent::WindowUnblocked);
for (int i = 0; i < windows.count(); ++i) {
QWidget *window = windows.at(i);
@@ -2848,7 +2849,7 @@ bool QApplicationPrivate::tryModalHelper(QWidget *widget, QWidget **rettop)
*rettop = top;
// the active popup widget always gets the input event
- if (qApp->activePopupWidget())
+ if (QApplication::activePopupWidget())
return true;
#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
@@ -2914,7 +2915,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event,
QPointer<QWidget> receiverGuard = receiver;
QPointer<QWidget> nativeGuard = nativeWidget;
QPointer<QWidget> alienGuard = alienWidget;
- QPointer<QWidget> activePopupWidget = qApp->activePopupWidget();
+ QPointer<QWidget> activePopupWidget = QApplication::activePopupWidget();
const bool graphicsWidget = nativeWidget->testAttribute(Qt::WA_DontShowOnScreen);
@@ -3562,7 +3563,7 @@ void QApplication::changeOverrideCursor(const QCursor &cursor)
It is necessary to call this function to start event handling. The main
event loop receives events from the window system and dispatches these to
the application widgets.
-
+
Generally, no user interaction can take place before calling exec(). As a
special case, modal widgets like QMessageBox can be used before calling
exec(), because modal widgets call exec() to start a local event loop.
@@ -3632,10 +3633,12 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
#if !defined(QT_NO_WHEELEVENT) || !defined(QT_NO_TABLETEVENT)
else if (
# ifndef QT_NO_WHEELEVENT
- e->type() == QEvent::Wheel ||
+ e->type() == QEvent::Wheel
+# else
+ false
# endif
# ifndef QT_NO_TABLETEVENT
- e->type() == QEvent::TabletMove
+ || e->type() == QEvent::TabletMove
|| e->type() == QEvent::TabletPress
|| e->type() == QEvent::TabletRelease
# endif
@@ -3851,7 +3854,7 @@ bool QApplication::notify(QObject *receiver, QEvent *e)
QPoint diff = relpos - w->mapFromGlobal(d->hoverGlobalPos);
while (w) {
if (w->testAttribute(Qt::WA_Hover) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == w->window())) {
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == w->window())) {
QHoverEvent he(QEvent::HoverMove, relpos, relpos - diff);
d->notify_helper(w, &he);
}
@@ -4121,10 +4124,10 @@ bool QApplicationPrivate::notify_helper(QObject *receiver, QEvent * e)
if (receiver->isWidgetType()) {
QWidget *widget = static_cast<QWidget *>(receiver);
-#if !defined(Q_OS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
+#if !defined(Q_WS_WINCE) || (defined(GWES_ICONCURS) && !defined(QT_NO_CURSOR))
// toggle HasMouse widget state on enter and leave
if ((e->type() == QEvent::Enter || e->type() == QEvent::DragEnter) &&
- (!qApp->activePopupWidget() || qApp->activePopupWidget() == widget->window()))
+ (!QApplication::activePopupWidget() || QApplication::activePopupWidget() == widget->window()))
widget->setAttribute(Qt::WA_UnderMouse, true);
else if (e->type() == QEvent::Leave || e->type() == QEvent::DragLeave)
widget->setAttribute(Qt::WA_UnderMouse, false);
@@ -4654,9 +4657,9 @@ void QSessionManager::requestPhase2()
\oldcode
app.setWinStyleHighlightColor(color);
\newcode
- QPalette palette(qApp->palette());
+ QPalette palette(QApplication::palette());
palette.setColor(QPalette::Highlight, color);
- qApp->setPalette(palette);
+ QApplication::setPalette(palette);
\endcode
*/
@@ -4675,7 +4678,7 @@ void QSessionManager::requestPhase2()
/*!
\fn const QColor &QApplication::winStyleHighlightColor()
- Use qApp->palette().color(QPalette::Active, QPalette::Highlight) instead.
+ Use QApplication::palette().color(QPalette::Active, QPalette::Highlight) instead.
*/
/*!
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index e1b8b26..32bfcf5 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -109,7 +109,7 @@ class Q_GUI_EXPORT QApplication : public QCoreApplication
#ifndef QT_NO_STYLE_STYLESHEET
Q_PROPERTY(QString styleSheet READ styleSheet WRITE setStyleSheet)
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_PROPERTY(int autoMaximizeThreshold READ autoMaximizeThreshold WRITE setAutoMaximizeThreshold)
#endif
Q_PROPERTY(bool autoSipEnabled READ autoSipEnabled WRITE setAutoSipEnabled)
@@ -293,7 +293,7 @@ public Q_SLOTS:
#ifndef QT_NO_STYLE_STYLESHEET
void setStyleSheet(const QString& sheet);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void setAutoMaximizeThreshold(const int threshold);
int autoMaximizeThreshold() const;
#endif
diff --git a/src/gui/kernel/qapplication_mac.mm b/src/gui/kernel/qapplication_mac.mm
index 69302ec..6a592e4 100644
--- a/src/gui/kernel/qapplication_mac.mm
+++ b/src/gui/kernel/qapplication_mac.mm
@@ -154,6 +154,10 @@
#define kThemeBrushAlternatePrimaryHighlightColor -5
#endif
+#define kCMDeviceUnregisteredNotification CFSTR("CMDeviceUnregisteredNotification")
+#define kCMDefaultDeviceNotification CFSTR("CMDefaultDeviceNotification")
+#define kCMDeviceProfilesNotification CFSTR("CMDeviceProfilesNotification")
+#define kCMDefaultDeviceProfileNotification CFSTR("CMDefaultDeviceProfileNotification")
QT_BEGIN_NAMESPACE
@@ -1040,11 +1044,29 @@ void qt_release_app_proc_handler()
#endif
}
+void qt_color_profile_changed(CFNotificationCenterRef, void *, CFStringRef, const void *,
+ CFDictionaryRef)
+{
+ QCoreGraphicsPaintEngine::cleanUpMacColorSpaces();
+}
/* platform specific implementations */
void qt_init(QApplicationPrivate *priv, int)
{
if (qt_is_gui_used) {
CGDisplayRegisterReconfigurationCallback(qt_mac_display_change_callbk, 0);
+ CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDeviceUnregisteredNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDefaultDeviceNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDeviceProfilesNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+ CFNotificationCenterAddObserver(center, qApp, qt_color_profile_changed,
+ kCMDefaultDeviceProfileNotification, 0,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
ProcessSerialNumber psn;
if (GetCurrentProcess(&psn) == noErr) {
// Jambi needs to transform itself since most people aren't "used"
@@ -1196,10 +1218,6 @@ void qt_init(QApplicationPrivate *priv, int)
[qtMenuLoader release];
}
#endif
- if (QApplication::testAttribute(Qt::AA_MacPluginApplication)) {
- extern void qt_mac_set_native_menubar(bool);
- qt_mac_set_native_menubar(false);
- }
// Register for Carbon tablet proximity events on the event monitor target.
// This means that we should receive proximity events even when we aren't the active application.
if (!tablet_proximity_handler) {
@@ -1228,6 +1246,12 @@ void qt_release_apple_event_handler()
void qt_cleanup()
{
CGDisplayRemoveReconfigurationCallback(qt_mac_display_change_callbk, 0);
+ CFNotificationCenterRef center = CFNotificationCenterGetDistributedCenter();
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceUnregisteredNotification, 0);
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceNotification, 0);
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDeviceProfilesNotification, 0);
+ CFNotificationCenterRemoveObserver(center, qApp, kCMDefaultDeviceProfileNotification, 0);
+
#ifndef QT_MAC_USE_COCOA
qt_release_app_proc_handler();
if (app_proc_handlerUPP) {
@@ -1642,15 +1666,6 @@ QApplicationPrivate::globalEventProcessor(EventHandlerCallRef er, EventRef event
bool inNonClientArea = false;
GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0,
sizeof(where), 0, &where);
- if(ekind == kEventMouseMoved && qt_mac_app_fullscreen &&
- QApplication::desktop()->screenNumber(QPoint(where.h, where.v)) ==
- QApplication::desktop()->primaryScreen()) {
- if(where.v <= 0)
- ShowMenuBar();
- else if(qt_mac_window_at(where.h, where.v, 0) != inMenuBar)
- HideMenuBar();
- }
-
#if defined(DEBUG_MOUSE_MAPS)
const char *edesc = 0;
switch(ekind) {
diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h
index 35a532a..3377a4d 100644
--- a/src/gui/kernel/qapplication_p.h
+++ b/src/gui/kernel/qapplication_p.h
@@ -211,6 +211,7 @@ public:
#if defined(Q_WS_X11)
#ifndef QT_NO_SETTINGS
static QString kdeHome();
+ static QString x11_desktop_style();
static bool x11_apply_settings();
#endif
static void reset_instance_pointer();
@@ -220,10 +221,11 @@ public:
#endif
static bool quitOnLastWindowClosed;
static void emitLastWindowClosed();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
static int autoMaximizeThreshold;
#endif
static bool autoSipEnabled;
+ static QString desktopStyleKey();
static QGraphicsSystem *graphicsSystem()
#if !defined(Q_WS_QWS)
@@ -359,7 +361,7 @@ public:
#ifdef Q_WS_MAC
static bool native_modal_dialog_active;
#endif
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
static bool inSizeMove;
#endif
@@ -394,7 +396,7 @@ public:
static QApplicationPrivate *instance() { return self; }
- static QString *styleOverride;
+ static QString styleOverride;
static int app_compile_version;
diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp
index aeebde4..936768d 100644
--- a/src/gui/kernel/qapplication_qws.cpp
+++ b/src/gui/kernel/qapplication_qws.cpp
@@ -196,15 +196,15 @@ QString qws_dataDir()
static QString result;
if (!result.isEmpty())
return result;
- QByteArray dataDir = QString(QLatin1String("/tmp/qtembedded-%1")).arg(qws_display_id).toLocal8Bit();
- if (mkdir(dataDir, 0700)) {
+ QByteArray dataDir = QString::fromLatin1("/tmp/qtembedded-%1").arg(qws_display_id).toLocal8Bit();
+ if (QT_MKDIR(dataDir, 0700)) {
if (errno != EEXIST) {
qFatal("Cannot create Qt for Embedded Linux data directory: %s", dataDir.constData());
}
}
- struct stat buf;
- if (lstat(dataDir, &buf))
+ QT_STATBUF buf;
+ if (QT_LSTAT(dataDir, &buf))
qFatal("stat failed for Qt for Embedded Linux data directory: %s", dataDir.constData());
if (!S_ISDIR(buf.st_mode))
@@ -217,7 +217,7 @@ QString qws_dataDir()
if ((buf.st_mode & 0677) != 0600)
qFatal("Qt for Embedded Linux data directory has incorrect permissions: %s", dataDir.constData());
#endif
- dataDir += "/";
+ dataDir += '/';
result = QString::fromLocal8Bit(dataDir);
return result;
@@ -226,7 +226,7 @@ QString qws_dataDir()
// Get the filename of the pipe Qt for Embedded Linux uses for server/client comms
Q_GUI_EXPORT QString qws_qtePipeFilename()
{
- return (qws_dataDir() + QString(QLatin1String(QTE_PIPE)).arg(qws_display_id));
+ return (qws_dataDir() + QString::fromLatin1(QTE_PIPE).arg(qws_display_id));
}
static void setMaxWindowRect(const QRect &rect)
@@ -2018,8 +2018,8 @@ bool QApplicationPrivate::qws_apply_settings()
// read new QStyle
QString stylename = settings.value(QLatin1String("style")).toString();
if (QCoreApplication::startingUp()) {
- if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
- QApplicationPrivate::styleOverride = new QString(stylename);
+ if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
+ QApplicationPrivate::styleOverride = stylename;
} else {
QApplication::setStyle(stylename);
}
@@ -2287,7 +2287,8 @@ void qt_init(QApplicationPrivate *priv, int type)
qt_appType = QApplication::Type(type);
qws_single_process = true;
QWSServer::startup(flags);
- setenv("QWS_DISPLAY", qws_display_spec.constData(), 0);
+ if (!display) // if not already set
+ qputenv("QWS_DISPLAY", qws_display_spec);
}
if(qt_is_gui_used) {
diff --git a/src/gui/kernel/qapplication_win.cpp b/src/gui/kernel/qapplication_win.cpp
index 239ee14..f449141 100644
--- a/src/gui/kernel/qapplication_win.cpp
+++ b/src/gui/kernel/qapplication_win.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
#include "qmenubar.h"
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wince.cpp
@@ -48,7 +48,7 @@ extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.c
extern bool qt_wince_is_pocket_pc(); //defined in qguifunctions_wince.cpp
extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.cpp
#endif
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
#include <windowsm.h>
#include <tpcshell.h>
#endif
@@ -106,7 +106,7 @@ extern void qt_wince_hide_taskbar(HWND hwnd); //defined in qguifunctions_wince.c
#include <winuser.h>
#if !defined(WINABLEAPI)
-# if defined(Q_OS_WINCE)
+# if defined(Q_WS_WINCE)
# include <bldver.h>
# endif
# include <winable.h>
@@ -155,7 +155,7 @@ static PtrFlashWindowEx pFlashWindowEx = 0;
QT_BEGIN_NAMESPACE
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#ifndef SHRG_RETURNCMD
struct SHRGINFO {
DWORD cbSize;
@@ -266,7 +266,7 @@ Q_CORE_EXPORT bool winPostMessage(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPa
#define MK_XBUTTON2 0x0040
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#define GET_KEYSTATE_WPARAM(wParam) (LOWORD(wParam))
#endif
@@ -376,11 +376,6 @@ QRgb qt_colorref2qrgb(COLORREF col)
Internal variables and functions
*****************************************************************************/
-extern Q_CORE_EXPORT char theAppName[];
-extern Q_CORE_EXPORT char appFileName[];
-extern Q_CORE_EXPORT HINSTANCE appInst; // handle to app instance
-extern Q_CORE_EXPORT HINSTANCE appPrevInst; // handle to prev app instance
-extern Q_CORE_EXPORT int appCmdShow; // main window show command
static HWND curWin = 0; // current window
static HDC displayDC = 0; // display device context
@@ -497,7 +492,7 @@ static void qt_set_windows_color_resources()
pal.setColor(QPalette::HighlightedText,
QColor(qt_colorref2qrgb(GetSysColor(COLOR_HIGHLIGHTTEXT))));
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
// ### hardcoded until I find out how to get it from the system settings.
pal.setColor(QPalette::LinkVisited, pal.highlight().color().dark(150));
pal.setColor(QPalette::Link, pal.highlight().color().light(130));
@@ -573,7 +568,7 @@ static void qt_set_windows_color_resources()
static void qt_set_windows_font_resources()
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
QFont menuFont;
QFont messageFont;
QFont statusFont;
@@ -625,11 +620,18 @@ static void qt_set_windows_font_resources()
smallerFont.setPointSize(systemFont.pointSize()-1);
QApplication::setFont(smallerFont, "QTabBar");
}
-#endif// Q_OS_WINCE
+#endif// Q_WS_WINCE
}
static void qt_win_read_cleartype_settings()
{
+#ifdef Q_OS_WINCE
+ UINT result;
+ BOOL ok;
+ ok = SystemParametersInfo(SPI_GETFONTSMOOTHING, 0, &result, 0);
+ if (ok)
+ qt_cleartype_enabled = result;
+#else
QT_WA({
UINT result;
BOOL ok;
@@ -643,6 +645,7 @@ static void qt_win_read_cleartype_settings()
if (ok)
qt_cleartype_enabled = (result == FE_FONTSMOOTHINGCLEARTYPE);
});
+#endif
}
@@ -745,9 +748,6 @@ void qt_init(QApplicationPrivate *priv, int)
appNoGrab = !appNoGrab;
else
#endif // QT_DEBUG
- if (qstrcmp(argv[i], "-direct3d") == 0)
- QApplication::setAttribute(Qt::AA_MSWindowsUseDirect3DByDefault);
- else
argv[j++] = argv[i];
}
if(j < priv->argc) {
@@ -755,21 +755,12 @@ void qt_init(QApplicationPrivate *priv, int)
priv->argc = j;
}
- // Get the application name/instance if qWinMain() was not invoked
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// No message boxes but important ones
SetErrorMode(SetErrorMode(0) | SEM_FAILCRITICALERRORS|SEM_NOOPENFILEERRORBOX);
#endif
- if (appInst == 0) {
- QT_WA({
- appInst = GetModuleHandle(0);
- }, {
- appInst = GetModuleHandleA(0);
- });
- }
-
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// Initialize OLE/COM
// S_OK means success and S_FALSE means that it has already
// been initialized
@@ -781,7 +772,7 @@ void qt_init(QApplicationPrivate *priv, int)
#endif
// Misc. initialization
-#if defined(QT_DEBUG) && !defined(Q_OS_WINCE)
+#if defined(QT_DEBUG) && !defined(Q_WS_WINCE)
GdiSetBatchLimit(1);
#endif
@@ -793,9 +784,9 @@ void qt_init(QApplicationPrivate *priv, int)
#ifndef QT_NO_CURSOR
QCursorData::initialize();
#endif
- qApp->setObjectName(QLatin1String(theAppName));
+ qApp->setObjectName(priv->appName());
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
// default font
HFONT hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
QFont f(QLatin1String("MS Sans Serif"),8);
@@ -815,7 +806,7 @@ void qt_init(QApplicationPrivate *priv, int)
&& f.family() == QLatin1String("MS Shell Dlg"))
f.setFamily(QLatin1String("MS Shell Dlg 2"));
QApplicationPrivate::setSystemFont(f);
-#else //Q_OS_WINCE
+#else //Q_WS_WINCE
LOGFONT lf;
HGDIOBJ stockFont = GetStockObject(SYSTEM_FONT);
int result = 0;
@@ -823,7 +814,7 @@ void qt_init(QApplicationPrivate *priv, int)
QFont font = qt_LOGFONTtoQFont(lf, true);
if (result)
QApplicationPrivate::setSystemFont(font);
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
// QFont::locale_init(); ### Uncomment when it does something on Windows
@@ -880,7 +871,7 @@ void qt_cleanup()
delete QApplicationPrivate::inputContext;
QApplicationPrivate::inputContext = 0;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// Deinitialize OLE/COM
OleUninitialize();
#endif
@@ -891,12 +882,6 @@ void qt_cleanup()
Platform specific global and internal functions
*****************************************************************************/
-Q_GUI_EXPORT int qWinAppCmdShow() // get main window show command
-{
- return appCmdShow;
-}
-
-
Q_GUI_EXPORT HDC qt_win_display_dc() // get display DC
{
Q_ASSERT(qApp && qApp->thread() == QThread::currentThread());
@@ -928,7 +913,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (flags & Qt::MSWindowsOwnDC) {
cname = QLatin1String("QWidgetOwnDC");
style = CS_DBLCLKS;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
style |= CS_OWNDC;
#endif
icon = true;
@@ -943,14 +928,14 @@ const QString qt_reg_winclass(QWidget *w) // register window class
} else {
cname = QLatin1String("QTool");
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
style |= CS_SAVEBITS;
#endif
icon = false;
} else if (type == Qt::Popup) {
cname = QLatin1String("QPopup");
style = CS_DBLCLKS;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
style |= CS_SAVEBITS;
#endif
if ((QSysInfo::WindowsVersion >= QSysInfo::WV_XP
@@ -963,7 +948,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
icon = true;
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// force CS_OWNDC when the GL graphics system is
// used as the default renderer
if (qt_win_owndc_required)
@@ -978,8 +963,8 @@ const QString qt_reg_winclass(QWidget *w) // register window class
wchar_t uniqueAppID[256];
GetModuleFileNameW(0, uniqueAppID, 255);
cname = QString::number(RegisterWindowMessageW(
- (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QString(QString::fromLatin1("\\")),
- QString(QString::fromLatin1("_"))).utf16()));
+ (const wchar_t *) QString::fromUtf16((const ushort *)uniqueAppID).toLower().replace(QLatin1Char('\\'),
+ QLatin1Char('_')).utf16()));
#endif
// since multiple Qt versions can be used in one process
@@ -992,11 +977,11 @@ const QString qt_reg_winclass(QWidget *w) // register window class
if (classExists == -1) {
QT_WA({
WNDCLASS wcinfo;
- classExists = GetClassInfo((HINSTANCE)qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo);
+ classExists = GetClassInfo(qWinAppInst(), (TCHAR*)cname.utf16(), &wcinfo);
classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
}, {
WNDCLASSA wcinfo;
- classExists = GetClassInfoA((HINSTANCE)qWinAppInst(), cname.toLatin1(), &wcinfo);
+ classExists = GetClassInfoA(qWinAppInst(), cname.toLatin1(), &wcinfo);
classExists = classExists && wcinfo.lpfnWndProc != QtWndProc;
});
}
@@ -1008,7 +993,7 @@ const QString qt_reg_winclass(QWidget *w) // register window class
return cname;
ATOM atom;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
HBRUSH bgBrush = (HBRUSH)GetSysColorBrush(COLOR_WINDOW);
QT_WA({
WNDCLASS wc;
@@ -1016,9 +1001,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class
wc.lpfnWndProc = (WNDPROC)QtWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
+ wc.hInstance = qWinAppInst();
if (icon) {
- wc.hIcon = LoadIcon(appInst, L"IDI_ICON1");
+ wc.hIcon = LoadIcon(qWinAppInst(), L"IDI_ICON1");
if (!wc.hIcon)
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
} else {
@@ -1035,9 +1020,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class
wc.lpfnWndProc = (WNDPROC)QtWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
+ wc.hInstance = qWinAppInst();
if (icon) {
- wc.hIcon = LoadIconA(appInst, (char*)"IDI_ICON1");
+ wc.hIcon = LoadIconA(qWinAppInst(), (char*)"IDI_ICON1");
if (!wc.hIcon)
wc.hIcon = LoadIconA(0, (char*)IDI_APPLICATION);
} else {
@@ -1056,9 +1041,9 @@ const QString qt_reg_winclass(QWidget *w) // register window class
wc.lpfnWndProc = (WNDPROC)QtWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
+ wc.hInstance = qWinAppInst();
if (icon) {
- wc.hIcon = LoadIcon(appInst, L"IDI_ICON1");
+ wc.hIcon = LoadIcon(qWinAppInst(), L"IDI_ICON1");
// if (!wc.hIcon)
// wc.hIcon = LoadIcon(0, IDI_APPLICATION);
} else {
@@ -1092,9 +1077,9 @@ static void unregWinClasses()
QHash<QString, int>::ConstIterator it = hash->constBegin();
while (it != hash->constEnd()) {
QT_WA({
- UnregisterClass((TCHAR*)it.key().utf16(), (HINSTANCE)qWinAppInst());
+ UnregisterClass((TCHAR*)it.key().utf16(), qWinAppInst());
} , {
- UnregisterClassA(it.key().toLatin1(), (HINSTANCE)qWinAppInst());
+ UnregisterClassA(it.key().toLatin1(), qWinAppInst());
});
++it;
}
@@ -1129,7 +1114,7 @@ void qWinRequestConfig(WId id, int req, int x, int y, int w, int h)
configRequests->append(r); // store request in queue
}
-Q_GUI_EXPORT void qWinProcessConfigRequests() // perform requests in queue
+static void qWinProcessConfigRequests() // perform requests in queue
{
if (!configRequests)
return;
@@ -1381,7 +1366,7 @@ void QApplication::winFocus(QWidget *widget, bool gotFocus)
&& (QApplicationPrivate::active_window->windowType() == Qt::Dialog)) {
// raise the entire application, not just the dialog
QWidget* mw = QApplicationPrivate::active_window;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
while(mw->parentWidget() && (mw->windowType() == Qt::Dialog))
mw = mw->parentWidget()->window();
if (mw->testAttribute(Qt::WA_WState_Created) && mw != QApplicationPrivate::active_window)
@@ -1431,8 +1416,9 @@ static bool qt_is_translatable_mouse_event(UINT message)
return (message >= WM_MOUSEFIRST && message <= WM_MOUSELAST ||
message >= WM_XBUTTONDOWN && message <= WM_XBUTTONDBLCLK)
&& message != WM_MOUSEWHEEL
+ && message != WM_MOUSEHWHEEL
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| message >= WM_NCMOUSEMOVE && message <= WM_NCMBUTTONDBLCLK
#endif
;
@@ -1472,7 +1458,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
msg.pt.y = GET_Y_LPARAM(lParam);
// If it's a non-client-area message the coords are screen coords, otherwise they are
// client coords.
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (message < WM_NCMOUSEMOVE || message > WM_NCMBUTTONDBLCLK)
#endif
ClientToScreen(msg.hwnd, &msg.pt);
@@ -1502,7 +1488,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (imeParentWnd && QApplication::activePopupWidget()
&& (message == WM_MBUTTONDOWN || message == WM_XBUTTONDOWN
|| message == WM_LBUTTONDOWN || message == WM_RBUTTONDOWN
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| message == WM_NCMBUTTONDOWN || message == WM_NCLBUTTONDOWN
|| message == WM_NCRBUTTONDOWN)) {
#else
@@ -1512,7 +1498,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
switch (message) {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_QUERYENDSESSION: {
if (sm_smActive) // bogus message from windows
RETURN(true);
@@ -1540,13 +1526,13 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
int index = QApplication::staticMetaObject.indexOfSignal("aboutToQuit()");
qApp->qt_metacall(QMetaObject::InvokeMetaMethod, index,0);
// since the process will be killed immediately quit() has no real effect
- qApp->quit();
+ QApplication::quit();
}
RETURN(0);
}
case WM_DISPLAYCHANGE:
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
break;
if (qt_desktopWidget) {
qt_desktopWidget->move(GetSystemMetrics(76), GetSystemMetrics(77));
@@ -1563,7 +1549,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#endif
case WM_SETTINGCHANGE:
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// CE SIP hide/show
if (wParam == SPI_SETSIPINFO) {
QResizeEvent re(QSize(0, 0), QSize(0, 0)); // Calculated by QDesktopWidget
@@ -1572,7 +1558,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
#endif
// ignore spurious XP message when user logs in again after locking
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
break;
if (QApplication::desktopSettingsAware() && wParam != SPI_SETWORKAREA) {
widget = (QETWidget*)QWidget::find(hwnd);
@@ -1595,7 +1581,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (wParam == SPI_SETFONTSMOOTHINGTYPE) {
qt_win_read_cleartype_settings();
- foreach (QWidget *w, qApp->topLevelWidgets()) {
+ foreach (QWidget *w, QApplication::topLevelWidgets()) {
if (!w->isVisible())
continue;
((QETWidget *) w)->forceUpdate();
@@ -1604,7 +1590,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
case WM_SYSCOLORCHANGE:
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
break;
if (QApplication::desktopSettingsAware()) {
widget = (QETWidget*)QWidget::find(hwnd);
@@ -1656,7 +1642,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
RETURN(res);
if (qt_is_translatable_mouse_event(message)) {
- if (qApp->activePopupWidget() != 0) { // in popup mode
+ if (QApplication::activePopupWidget() != 0) { // in popup mode
POINT curPos = msg.pt;
QWidget* w = QApplication::widgetAt(curPos.x, curPos.y);
if (w)
@@ -1665,10 +1651,10 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
if (!qt_tabletChokeMouse) {
result = widget->translateMouseEvent(msg); // mouse event
-#if defined(Q_OS_WINCE) && !defined(QT_NO_CONTEXTMENU)
- if (message == WM_LBUTTONDOWN && widget != qApp->activePopupWidget()) {
+#if defined(Q_WS_WINCE) && !defined(QT_NO_CONTEXTMENU)
+ if (message == WM_LBUTTONDOWN && widget != QApplication::activePopupWidget()) {
QWidget* alienWidget = widget;
- if ((alienWidget != qApp->activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) {
+ if ((alienWidget != QApplication::activePopupWidget()) && (alienWidget->contextMenuPolicy() != Qt::PreventContextMenu)) {
QPoint pos(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam));
QPoint globalPos(msg.pt.x, msg.pt.y);
// In case we are using Alien, then the widget to
@@ -1687,8 +1673,8 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
shrg.dwFlags = SHRG_RETURNCMD | SHRG_NOANIMATION;
resolveAygLibs();
if (ptrRecognizeGesture && (ptrRecognizeGesture(&shrg) == GN_CONTEXTMENU)) {
- if (qApp->activePopupWidget())
- qApp->activePopupWidget()->close();
+ if (QApplication::activePopupWidget())
+ QApplication::activePopupWidget()->close();
QContextMenuEvent e(QContextMenuEvent::Mouse, pos, globalPos);
result = qt_sendSpontaneousEvent(alienWidget, &e);
}
@@ -1766,7 +1752,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
widget = (QETWidget*)QApplication::activePopupWidget()->focusWidget()
? (QETWidget*)QApplication::activePopupWidget()->focusWidget()
: (QETWidget*)QApplication::activePopupWidget();
- else if (qApp->focusWidget())
+ else if (QApplication::focusWidget())
widget = (QETWidget*)QApplication::focusWidget();
else if (!widget || widget->internalWinId() == GetFocus()) // We faked the message to go to exactly that widget.
widget = (QETWidget*)widget->window();
@@ -1781,6 +1767,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
case WM_MOUSEWHEEL:
+ case WM_MOUSEHWHEEL:
result = widget->translateWheelEvent(msg);
break;
@@ -1888,8 +1875,8 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
QWidget *g = QWidget::keyboardGrabber();
if (g)
widget = (QETWidget*)g;
- else if (qApp->focusWidget())
- widget = (QETWidget*)qApp->focusWidget();
+ else if (QApplication::focusWidget())
+ widget = (QETWidget*)QApplication::focusWidget();
else
widget = (QETWidget*)widget->window();
if (widget->isEnabled()) {
@@ -1911,7 +1898,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_NCHITTEST:
if (widget->isWindow()) {
QPoint pos = widget->mapFromGlobal(QPoint(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)));
@@ -1930,7 +1917,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#endif
case WM_SYSCOMMAND: {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
bool window_state_change = false;
Qt::WindowStates oldstate = Qt::WindowStates(widget->dataPtr()->window_state);
// MSDN:In WM_SYSCOMMAND messages, the four low-order bits of the wParam parameter are
@@ -1958,7 +1945,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
QHideEvent e;
qt_sendSpontaneousEvent(widget, &e);
widget->hideChildren(true);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = widget->windowIconText();
if (!title.isEmpty())
widget->setWindowTitle_helper(title);
@@ -1981,7 +1968,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
widget->showChildren(true);
QShowEvent e;
qt_sendSpontaneousEvent(widget, &e);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = widget->windowTitle();
if (!title.isEmpty())
widget->setWindowTitle_helper(title);
@@ -2004,7 +1991,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
case WM_SETTINGCHANGE:
- if ( qApp->type() == QApplication::Tty )
+ if ( QApplication::type() == QApplication::Tty )
break;
if (!msg.wParam) {
@@ -2017,7 +2004,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
}
else if (msg.wParam == SPI_SETICONTITLELOGFONT) {
- if (qApp->desktopSettingsAware()) {
+ if (QApplication::desktopSettingsAware()) {
widget = (QETWidget*)QWidget::find(hwnd);
if (widget && !widget->parentWidget()) {
qt_set_windows_font_resources();
@@ -2031,7 +2018,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = widget->translatePaintEvent(msg);
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_ENTERSIZEMOVE:
autoCaptureWnd = hwnd;
QApplicationPrivate::inSizeMove = true;
@@ -2060,7 +2047,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
case WM_ACTIVATE:
- if ( qApp->type() == QApplication::Tty )
+ if ( QApplication::type() == QApplication::Tty )
break;
if (ptrWTOverlap && ptrWTEnable) {
@@ -2086,9 +2073,13 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
// WM_ACTIVATEAPP handles the "true" false case, as this is only when the application
// loses focus. Doing it here would result in the widget getting focus to not know
// where it got it from; it would simply get a 0 value as the old focus widget.
+#ifndef Q_WS_WINCE_WM
if (!(widget->windowState() & Qt::WindowMinimized)) {
// Ignore the activate message send by WindowsXP to a minimized window
-#ifdef Q_OS_WINCE_WM
+#else
+ {
+ if (widget->windowState() & Qt::WindowMinimized)
+ widget->dataPtr()->window_state &= ~Qt::WindowMinimized;
if (widget->windowState() & Qt::WindowFullScreen)
qt_wince_hide_taskbar(widget->winId());
#endif
@@ -2115,7 +2106,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_MOUSEACTIVATE:
if (widget->window()->windowType() == Qt::Tool) {
QWidget *w = widget;
@@ -2204,7 +2195,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
result = false;
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_WINDOWPOSCHANGING:
{
result = false;
@@ -2285,12 +2276,12 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
QWidget *fw = QWidget::keyboardGrabber();
if (!fw) {
- if (qApp->activePopupWidget())
- fw = (qApp->activePopupWidget()->focusWidget()
- ? qApp->activePopupWidget()->focusWidget()
- : qApp->activePopupWidget());
- else if (qApp->focusWidget())
- fw = qApp->focusWidget();
+ if (QApplication::activePopupWidget())
+ fw = (QApplication::activePopupWidget()->focusWidget()
+ ? QApplication::activePopupWidget()->focusWidget()
+ : QApplication::activePopupWidget());
+ else if (QApplication::focusWidget())
+ fw = QApplication::focusWidget();
else if (widget)
fw = widget->window();
}
@@ -2307,7 +2298,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_IME_STARTCOMPOSITION:
case WM_IME_ENDCOMPOSITION:
case WM_IME_COMPOSITION: {
- QWidget *fw = qApp->focusWidget();
+ QWidget *fw = QApplication::focusWidget();
QWinInputContext *im = fw ? qobject_cast<QWinInputContext *>(fw->inputContext()) : 0;
if (fw && im) {
if(message == WM_IME_STARTCOMPOSITION)
@@ -2320,7 +2311,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
break;
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_CHANGECBCHAIN:
case WM_DRAWCLIPBOARD:
#endif
@@ -2340,7 +2331,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_GETOBJECT:
{
// Ignoring all requests while starting up
- if (qApp->startingUp() || qApp->closingDown() || (DWORD)lParam != OBJID_CLIENT) {
+ if (QApplication::startingUp() || QApplication::closingDown() || (DWORD)lParam != OBJID_CLIENT) {
result = false;
break;
}
@@ -2427,7 +2418,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
#endif // QT_NO_TABLETEVENT
}
break;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
case WM_SETFOCUS: {
HIMC hC;
hC = ImmGetContext(hwnd);
@@ -2440,7 +2431,7 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
case WM_KILLFOCUS:
if (!QWidget::find((HWND)wParam)) { // we don't get focus, so unset it now
if (!widget->hasFocus()) // work around Windows bug after minimizing/restoring
- widget = (QETWidget*)qApp->focusWidget();
+ widget = (QETWidget*)QApplication::focusWidget();
HWND focus = ::GetFocus();
//if there is a current widget and the new widget belongs to the same toplevel window
//or if the current widget was embedded into non-qt window (i.e. we won't get WM_ACTIVATEAPP)
@@ -2459,21 +2450,21 @@ LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam
}
break;
case WM_THEMECHANGED:
- if ((widget->windowType() == Qt::Desktop) || !qApp || qApp->closingDown()
- || qApp->type() == QApplication::Tty)
+ if ((widget->windowType() == Qt::Desktop) || !qApp || QApplication::closingDown()
+ || QApplication::type() == QApplication::Tty)
break;
if (widget->testAttribute(Qt::WA_WState_Polished))
- qApp->style()->unpolish(widget);
+ QApplication::style()->unpolish(widget);
if (widget->testAttribute(Qt::WA_WState_Polished))
- qApp->style()->polish(widget);
- widget->repolishStyle(*qApp->style());
+ QApplication::style()->polish(widget);
+ widget->repolishStyle(*QApplication::style());
if (widget->isVisible())
widget->update();
break;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
case WM_INPUTLANGCHANGE: {
char info[7];
if (!GetLocaleInfoA(MAKELCID(lParam, SORT_DEFAULT), LOCALE_IDEFAULTANSICODEPAGE, info, 6)) {
@@ -2671,19 +2662,20 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret)
int type = msg->message;
bool block_event = false;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (type != WM_NCHITTEST)
#endif
if ((type >= WM_MOUSEFIRST && type <= WM_MOUSELAST) ||
type == WM_MOUSEWHEEL || type == (int)WM95_MOUSEWHEEL ||
+ type == WM_MOUSEHWHEEL ||
type == WM_MOUSELEAVE ||
(type >= WM_KEYFIRST && type <= WM_KEYLAST)
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| type == WM_NCMOUSEMOVE
#endif
) {
if (type == WM_MOUSEMOVE
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
|| type == WM_NCMOUSEMOVE
#endif
) {
@@ -2701,7 +2693,7 @@ bool qt_try_modal(QWidget *widget, MSG *msg, int& ret)
} else if (type == WM_CLOSE) {
block_event = true;
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
else if (type == WM_MOUSEACTIVATE || type == WM_NCLBUTTONDOWN){
if (!top->isActiveWindow()) {
top->activateWindow();
@@ -2756,9 +2748,9 @@ void QApplicationPrivate::openPopup(QWidget *popup)
if (popup->focusWidget()) {
popup->focusWidget()->setFocus(Qt::PopupFocusReason);
} else if (QApplicationPrivate::popupWidgets->count() == 1) { // this was the first popup
- if (QWidget *fw = q_func()->focusWidget()) {
+ if (QWidget *fw = QApplication::focusWidget()) {
QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason);
- q_func()->sendEvent(fw, &e);
+ QApplication::sendEvent(fw, &e);
}
}
}
@@ -2785,13 +2777,13 @@ void QApplicationPrivate::closePopup(QWidget *popup)
if (!qt_nograb()) // grabbing not disabled
releaseAutoCapture();
QWidget *fw = QApplicationPrivate::active_window ? QApplicationPrivate::active_window->focusWidget()
- : q_func()->focusWidget();
+ : QApplication::focusWidget();
if (fw) {
- if (fw != q_func()->focusWidget()) {
+ if (fw != QApplication::focusWidget()) {
fw->setFocus(Qt::PopupFocusReason);
} else {
QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason);
- q_func()->sendEvent(fw, &e);
+ QApplication::sendEvent(fw, &e);
}
}
} else {
@@ -2859,7 +2851,7 @@ static const ushort mouseTbl[] = {
WM_XBUTTONUP, QEvent::MouseButtonRelease, Qt::XButton1,
WM_XBUTTONDBLCLK, QEvent::MouseButtonDblClick, Qt::XButton1,
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
WM_NCMOUSEMOVE, QEvent::NonClientAreaMouseMove, 0,
WM_NCLBUTTONDOWN, QEvent::NonClientAreaMouseButtonPress, Qt::LeftButton,
WM_NCLBUTTONUP, QEvent::NonClientAreaMouseButtonRelease, Qt::LeftButton,
@@ -3055,7 +3047,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
HWND id = effectiveWinId();
QWidget *mouseGrabber = QWidget::mouseGrabber();
- QWidget *activePopupWidget = qApp->activePopupWidget();
+ QWidget *activePopupWidget = QApplication::activePopupWidget();
if (mouseGrabber) {
if (!activePopupWidget || (activePopupWidget == this && !rect().contains(widgetPos)))
id = mouseGrabber->effectiveWinId();
@@ -3148,7 +3140,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
return false;
replayPopupMouseEvent = false;
- QWidget* activePopupWidget = qApp->activePopupWidget();
+ QWidget* activePopupWidget = QApplication::activePopupWidget();
QWidget *target = activePopupWidget;
const QPoint globalPos(gpos.x, gpos.y);
@@ -3176,10 +3168,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
if (popupButtonFocus) {
target = popupButtonFocus;
} else if (popupChild) {
- // forward mouse events to the popup child. mouse move events
- // are only forwarded to popup children that enable mouse tracking.
- if (type != QEvent::MouseMove || popupChild->hasMouseTracking())
- target = popupChild;
+ target = popupChild;
}
pos = target->mapFromGlobal(globalPos);
@@ -3209,7 +3198,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
}
if (type == QEvent::MouseButtonPress
- && qApp->activePopupWidget() != activePopupWidget
+ && QApplication::activePopupWidget() != activePopupWidget
&& replayPopupMouseEvent) {
// the popup dissappeared. Replay the event
QWidget* w = QApplication::widgetAt(gpos.x, gpos.y);
@@ -3226,7 +3215,7 @@ bool QETWidget::translateMouseEvent(const MSG &msg)
winPostMessage(hwndTarget, msg.message, msg.wParam, lParam);
}
} else if (type == QEvent::MouseButtonRelease && button == Qt::RightButton
- && qApp->activePopupWidget() == activePopupWidget) {
+ && QApplication::activePopupWidget() == activePopupWidget) {
// popup still alive and received right-button-release
#if !defined(QT_NO_CONTEXTMENU)
QContextMenuEvent e2(QContextMenuEvent::Mouse, pos, globalPos,
@@ -3290,12 +3279,12 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
state = translateButtonState(GET_KEYSTATE_WPARAM(msg.wParam), 0, 0);
int delta;
- if (msg.message == WM_MOUSEWHEEL)
+ if (msg.message == WM_MOUSEWHEEL || msg.message == WM_MOUSEHWHEEL)
delta = (short) HIWORD (msg.wParam);
else
delta = (int) msg.wParam;
- Qt::Orientation orient = (state&Qt::AltModifier
+ Qt::Orientation orient = (msg.message == WM_MOUSEHWHEEL || state&Qt::AltModifier
#if 0
// disabled for now - Trenton's one-wheel mouse makes trouble...
// "delta" for usual wheels is +-120. +-240 seems to indicate
@@ -3309,6 +3298,13 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
#endif
) ? Qt::Horizontal : Qt::Vertical;
+ // according to the MSDN documentation on WM_MOUSEHWHEEL:
+ // a positive value indicates that the wheel was rotated to the right;
+ // a negative value indicates that the wheel was rotated to the left.
+ // Qt defines this value as the exact opposite, so we have to flip the value!
+ if (msg.message == WM_MOUSEHWHEEL)
+ delta = -delta;
+
QPoint globalPos;
globalPos.rx() = (short)LOWORD (msg.lParam);
@@ -3329,7 +3325,7 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
// send the event to the widget or its ancestors
{
- QWidget* popup = qApp->activePopupWidget();
+ QWidget* popup = QApplication::activePopupWidget();
if (popup && w->window() != popup)
popup->close();
#ifndef QT_NO_WHEELEVENT
@@ -3345,8 +3341,8 @@ bool QETWidget::translateWheelEvent(const MSG &msg)
}
// send the event to the widget that has the focus or its ancestors, if different
- if (w != qApp->focusWidget() && (w = qApp->focusWidget())) {
- QWidget* popup = qApp->activePopupWidget();
+ if (w != QApplication::focusWidget() && (w = QApplication::focusWidget())) {
+ QWidget* popup = QApplication::activePopupWidget();
if (popup && w->window() != popup)
popup->close();
#ifndef QT_NO_WHEELEVENT
@@ -3661,7 +3657,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
WORD b = HIWORD(msg.lParam);
QSize oldSize = size();
QSize newSize(a, b);
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (isFullScreen() && (oldSize.width() == newSize.height()) && (oldSize.height() == newSize.width()))
qt_wince_hide_taskbar(internalWinId());
#endif
@@ -3673,7 +3669,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
// Capture SIZE_MINIMIZED without preceding WM_SYSCOMMAND
// (like Windows+M)
if (msg.wParam == SIZE_MINIMIZED && !isMinimized()) {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = windowIconText();
if (!title.isEmpty())
d_func()->setWindowTitle_helper(title);
@@ -3685,7 +3681,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
hideChildren(true);
}
} else if (msg.wParam != SIZE_MINIMIZED && isMinimized()) {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
const QString title = windowTitle();
if (!title.isEmpty())
d_func()->setWindowTitle_helper(title);
@@ -3731,7 +3727,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
QPoint oldPos = geometry().topLeft();
QPoint newCPos(a, b);
// Ignore silly Windows move event to wild pos after iconify.
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
if (!IsIconic(internalWinId()) && newCPos != oldPos) {
#endif
cr.moveTopLeft(newCPos);
@@ -3743,7 +3739,7 @@ bool QETWidget::translateConfigEvent(const MSG &msg)
QMoveEvent * e = new QMoveEvent(newCPos, oldPos);
QApplication::postEvent(this, e);
}
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
}
#endif
}
@@ -3785,7 +3781,7 @@ int QApplication::cursorFlashTime()
void QApplication::setDoubleClickInterval(int ms)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
SetDoubleClickTime(ms);
#endif
QApplicationPrivate::mouse_double_click_time = ms;
diff --git a/src/gui/kernel/qapplication_x11.cpp b/src/gui/kernel/qapplication_x11.cpp
index 12155f0..7387fb0 100644
--- a/src/gui/kernel/qapplication_x11.cpp
+++ b/src/gui/kernel/qapplication_x11.cpp
@@ -128,6 +128,10 @@ extern "C" {
#include <private/qbackingstore_p.h>
+#if defined(Q_OS_BSD4) || _POSIX_VERSION+0 < 200112L
+# define QT_NO_UNSETENV
+#endif
+
QT_BEGIN_NAMESPACE
//#define X_NOT_BROKEN
@@ -157,6 +161,8 @@ static const char * x11_atomnames = {
"WM_TAKE_FOCUS\0"
"_NET_WM_PING\0"
"_NET_WM_CONTEXT_HELP\0"
+ "_NET_WM_SYNC_REQUEST\0"
+ "_NET_WM_SYNC_REQUEST_COUNTER\0"
// ICCCM window state
"WM_STATE\0"
@@ -294,6 +300,10 @@ static const char * x11_atomnames = {
// XEMBED
"_XEMBED\0"
"_XEMBED_INFO\0"
+
+ "Wacom Stylus\0"
+ "Wacom Cursor\0"
+ "Wacom Eraser\0"
};
Q_GUI_EXPORT QX11Data *qt_x11Data = 0;
@@ -504,6 +514,7 @@ static Bool qt_xfixes_scanner(Display*, XEvent *event, XPointer arg)
class QETWidget : public QWidget // event translator widget
{
public:
+ QWidgetPrivate* d_func() { return QWidget::d_func(); }
bool translateMouseEvent(const XEvent *);
void translatePaintEvent(const XEvent *);
bool translateConfigEvent(const XEvent *);
@@ -714,6 +725,44 @@ static int qt_xio_errhandler(Display *)
}
#endif
+#ifndef QT_NO_XSYNC
+struct qt_sync_request_event_data
+{
+ WId window;
+};
+
+#if defined(Q_C_CALLBACKS)
+extern "C" {
+#endif
+
+static Bool qt_sync_request_scanner(Display*, XEvent *event, XPointer arg)
+{
+ qt_sync_request_event_data *data =
+ reinterpret_cast<qt_sync_request_event_data*>(arg);
+ if (event->type == ClientMessage &&
+ event->xany.window == data->window &&
+ event->xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)event->xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST)) {
+ QWidget *w = QWidget::find(event->xany.window);
+ if (QTLWExtra *tlw = ((QETWidget*)w)->d_func()->maybeTopData()) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+#if defined(Q_C_CALLBACKS)
+}
+#endif
+#endif // QT_NO_XSYNC
static void qt_x11_create_intern_atoms()
{
@@ -754,6 +803,14 @@ Q_GUI_EXPORT void qt_x11_apply_settings_in_all_apps()
PropModeReplace, (unsigned char *)stamp.data(), stamp.size());
}
+static int kdeSessionVersion()
+{
+ static int kdeVersion = 0;
+ if (!kdeVersion)
+ kdeVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
+ return kdeVersion;
+}
+
/*! \internal
Gets the current KDE 3 or 4 home path
*/
@@ -763,10 +820,9 @@ QString QApplicationPrivate::kdeHome()
if (kdeHomePath.isEmpty()) {
kdeHomePath = QString::fromLocal8Bit(qgetenv("KDEHOME"));
if (kdeHomePath.isEmpty()) {
- int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
QDir homeDir(QDir::homePath());
QString kdeConfDir(QLatin1String("/.kde"));
- if (4 == kdeSessionVersion && homeDir.exists(QLatin1String(".kde4")))
+ if (4 == kdeSessionVersion() && homeDir.exists(QLatin1String(".kde4")))
kdeConfDir = QLatin1String("/.kde4");
kdeHomePath = QDir::homePath() + kdeConfDir;
}
@@ -835,13 +891,11 @@ bool QApplicationPrivate::x11_apply_settings()
QApplicationPrivate::setSystemPalette(pal);
}
- int kdeSessionVersion = QString::fromLocal8Bit(qgetenv("KDE_SESSION_VERSION")).toInt();
-
if (!appFont) {
QFont font(QApplication::font());
QString fontDescription;
// Override Qt font if KDE4 settings can be used
- if (4 == kdeSessionVersion) {
+ if (4 == kdeSessionVersion()) {
QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
fontDescription = kdeSettings.value(QLatin1String("font")).toString();
if (fontDescription.isEmpty()) {
@@ -871,29 +925,16 @@ bool QApplicationPrivate::x11_apply_settings()
// read new QStyle
QString stylename = settings.value(QLatin1String("style")).toString();
- if (stylename.isEmpty() && !QApplicationPrivate::styleOverride && X11->use_xrender) {
- QStringList availableStyles = QStyleFactory::keys();
- // Override Qt style if KDE4 settings can be used
- if (4 == kdeSessionVersion) {
- QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
- QString kde4Style = kdeSettings.value(QLatin1String("widgetStyle"),
- QLatin1String("Oxygen")).toString();
- foreach (const QString &style, availableStyles) {
- if (style.toLower() == kde4Style.toLower())
- stylename = kde4Style;
- }
- // Set QGtkStyle for GNOME
- } else if (X11->desktopEnvironment == DE_GNOME) {
- QString gtkStyleKey = QString::fromLatin1("GTK+");
- if (availableStyles.contains(gtkStyleKey))
- stylename = gtkStyleKey;
- }
+
+
+ if (stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull() && X11->use_xrender) {
+ stylename = x11_desktop_style();
}
static QString currentStyleName = stylename;
if (QCoreApplication::startingUp()) {
- if (!stylename.isEmpty() && !QApplicationPrivate::styleOverride)
- QApplicationPrivate::styleOverride = new QString(stylename);
+ if (!stylename.isEmpty() && QApplicationPrivate::styleOverride.isNull())
+ QApplicationPrivate::styleOverride = stylename;
} else {
if (currentStyleName != stylename) {
currentStyleName = stylename;
@@ -1579,6 +1620,7 @@ static PtrWacomConfigOpenDevice ptrWacomConfigOpenDevice = 0;
static PtrWacomConfigGetRawParam ptrWacomConfigGetRawParam = 0;
static PtrWacomConfigCloseDevice ptrWacomConfigCloseDevice = 0;
static PtrWacomConfigTerm ptrWacomConfigTerm = 0;
+Q_GLOBAL_STATIC(QByteArray, wacomDeviceName)
#endif
#endif
@@ -1719,7 +1761,7 @@ void qt_init(QApplicationPrivate *priv, int,
X11->pattern_fills[i].screen = -1;
#endif
- X11->startupId = X11->originalStartupId = 0;
+ X11->startupId = X11->originalStartupId = X11->startupIdString = 0;
int argc = priv->argc;
char **argv = priv->argv;
@@ -2057,14 +2099,6 @@ void qt_init(QApplicationPrivate *priv, int,
X11->xfixes_major = major;
}
}
- if (X11->use_xfixes && X11->ptrXFixesSelectSelectionInput) {
- const unsigned long eventMask =
- XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask;
- X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(0),
- XA_PRIMARY, eventMask);
- X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(0),
- ATOM(CLIPBOARD), eventMask);
- }
#endif // QT_NO_XFIXES
#ifndef QT_NO_XCURSOR
@@ -2085,6 +2119,13 @@ void qt_init(QApplicationPrivate *priv, int,
#endif // QT_RUNTIME_XCURSOR
#endif // QT_NO_XCURSOR
+#ifndef QT_NO_XSYNC
+ int xsync_evbase, xsync_errbase;
+ int major, minor;
+ if (XSyncQueryExtension(X11->display, &xsync_evbase, &xsync_errbase))
+ XSyncInitialize(X11->display, &major, &minor);
+#endif // QT_NO_XSYNC
+
#ifndef QT_NO_XINERAMA
#ifdef QT_RUNTIME_XINERAMA
X11->ptrXineramaQueryExtension = 0;
@@ -2356,13 +2397,6 @@ void qt_init(QApplicationPrivate *priv, int,
XAxisInfoPtr a;
XDevice *dev = 0;
-#if !defined(Q_OS_IRIX)
- // XFree86 divides a stylus and eraser into 2 devices, so we must do for both...
- const QString XFREENAMESTYLUS = QLatin1String("stylus");
- const QString XFREENAMEPEN = QLatin1String("pen");
- const QString XFREENAMEERASER = QLatin1String("eraser");
-#endif
-
if (X11->ptrXListInputDevices) {
devices = X11->ptrXListInputDevices(X11->display, &ndev);
if (!devices)
@@ -2377,18 +2411,19 @@ void qt_init(QApplicationPrivate *priv, int,
gotStylus = false;
gotEraser = false;
- QString devName = QString::fromLocal8Bit(devs->name).toLower();
#if defined(Q_OS_IRIX)
+ QString devName = QString::fromLocal8Bit(devs->name).toLower();
if (devName == QLatin1String(WACOM_NAME)) {
deviceType = QTabletEvent::Stylus;
gotStylus = true;
}
#else
- if (devName.startsWith(XFREENAMEPEN)
- || devName.startsWith(XFREENAMESTYLUS)) {
+ if (devs->type == ATOM(XWacomStylus)) {
deviceType = QTabletEvent::Stylus;
+ if (wacomDeviceName()->isEmpty())
+ wacomDeviceName()->append(devs->name);
gotStylus = true;
- } else if (devName.startsWith(XFREENAMEERASER)) {
+ } else if (devs->type == ATOM(XWacomEraser)) {
deviceType = QTabletEvent::XFreeEraser;
gotEraser = true;
}
@@ -2525,9 +2560,16 @@ void qt_init(QApplicationPrivate *priv, int,
X11->startupId = getenv("DESKTOP_STARTUP_ID");
X11->originalStartupId = X11->startupId;
- static char desktop_startup_id[] = "DESKTOP_STARTUP_ID=";
- putenv(desktop_startup_id);
-
+ if (X11->startupId) {
+#ifndef QT_NO_UNSETENV
+ unsetenv("DESKTOP_STARTUP_ID");
+#else
+ // it's a small memory leak, however we won't crash if Qt is
+ // unloaded and someones tries to use the envoriment.
+ X11->startupIdString = strdup("DESKTOP_STARTUP_ID=");
+ putenv(X11->startupIdString);
+#endif
+ }
} else {
// read some non-GUI settings when not using the X server...
@@ -2586,31 +2628,49 @@ void qt_init(QApplicationPrivate *priv, int,
/*!
\internal
*/
-void QApplicationPrivate::x11_initialize_style()
+QString QApplicationPrivate::x11_desktop_style()
{
- if (QApplicationPrivate::app_style)
- return;
+ QString stylename;
+ QStringList availableStyles = QStyleFactory::keys();
+ // Override Qt style if KDE4 settings can be used
+ if (4 == kdeSessionVersion()) {
+ QSettings kdeSettings(kdeHome() + QLatin1String("/share/config/kdeglobals"), QSettings::IniFormat);
+ QString kde4Style = kdeSettings.value(QLatin1String("widgetStyle"),
+ QLatin1String("Oxygen")).toString();
+ foreach (const QString &style, availableStyles) {
+ if (style.toLower() == kde4Style.toLower())
+ stylename = kde4Style;
+ }
+ // Set QGtkStyle for GNOME
+ } else if (X11->desktopEnvironment == DE_GNOME) {
+ QString gtkStyleKey = QString::fromLatin1("GTK+");
+ if (availableStyles.contains(gtkStyleKey))
+ stylename = gtkStyleKey;
+ }
- switch(X11->desktopEnvironment) {
+ if (stylename.isEmpty()) {
+ switch(X11->desktopEnvironment) {
case DE_KDE:
if (X11->use_xrender)
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("plastique"));
+ stylename = QLatin1String("plastique");
else
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
+ stylename = QLatin1String("windows");
break;
case DE_GNOME:
if (X11->use_xrender)
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cleanlooks"));
+ stylename = QLatin1String("cleanlooks");
else
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("windows"));
+ stylename = QLatin1String("windows");
break;
case DE_CDE:
- QApplicationPrivate::app_style = QStyleFactory::create(QLatin1String("cde"));
+ stylename = QLatin1String("cde");
break;
default:
// Don't do anything
break;
+ }
}
+ return stylename;
}
void QApplicationPrivate::initializeWidgetPaletteHash()
@@ -2641,9 +2701,14 @@ void qt_cleanup()
#endif
}
- // restore original value back. This is also done in QWidgetPrivate::show_sys.
- if (X11->originalStartupId)
+#ifdef QT_NO_UNSETENV
+ // restore original value back.
+ if (X11->originalStartupId && X11->startupIdString) {
putenv(X11->originalStartupId);
+ free(X11->startupIdString);
+ X11->startupIdString = 0;
+ }
+#endif
#ifndef QT_NO_XRENDER
for (int i = 0; i < X11->solid_fill_count; ++i) {
@@ -2979,7 +3044,7 @@ QWidget *QApplication::topLevelAt(const QPoint &p)
void QApplication::syncX()
{
if (X11->display)
- XSync(X11->display, False); // don't discard events
+ XSync(X11->display, False); // don't discard events
}
@@ -3117,6 +3182,19 @@ int QApplication::x11ClientMessage(QWidget* w, XEvent* event, bool passive_only)
XSendEvent(event->xclient.display, event->xclient.window,
False, SubstructureNotifyMask|SubstructureRedirectMask, event);
}
+#ifndef QT_NO_XSYNC
+ } else if (a == ATOM(_NET_WM_SYNC_REQUEST)) {
+ const ulong timestamp = (const ulong) event->xclient.data.l[1];
+ if (timestamp > X11->time)
+ X11->time = timestamp;
+ if (QTLWExtra *tlw = w->d_func()->maybeTopData()) {
+ if (timestamp == CurrentTime || timestamp > tlw->syncRequestTimestamp) {
+ tlw->syncRequestTimestamp = timestamp;
+ tlw->newCounterValueLo = event->xclient.data.l[2];
+ tlw->newCounterValueHi = event->xclient.data.l[3];
+ }
+ }
+#endif
}
} else if (event->xclient.message_type == ATOM(_QT_SCROLL_DONE)) {
widget->translateScrollDoneEvent(event);
@@ -4145,7 +4223,9 @@ bool QETWidget::translateMouseEvent(const XEvent *event)
|| ((nextEvent.type == EnterNotify || nextEvent.type == LeaveNotify)
&& qt_button_down == this)
|| (nextEvent.type == ClientMessage
- && nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE))) {
+ && (nextEvent.xclient.message_type == ATOM(_QT_SCROLL_DONE) ||
+ (nextEvent.xclient.message_type == ATOM(WM_PROTOCOLS) &&
+ (Atom)nextEvent.xclient.data.l[0] == ATOM(_NET_WM_SYNC_REQUEST))))) {
qApp->x11ProcessEvent(&nextEvent);
continue;
} else if (nextEvent.type != MotionNotify ||
@@ -4484,8 +4564,7 @@ void fetchWacomToolId(int &deviceType, qint64 &serialId)
WACOMCONFIG *config = ptrWacomConfigInit(X11->display, 0);
if (config == 0)
return;
- const char *name = "stylus"; // TODO get this from the X config instead (users may have called it differently)
- WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, name);
+ WACOMDEVICE *device = ptrWacomConfigOpenDevice (config, wacomDeviceName()->constData());
if (device == 0)
return;
unsigned keys[1];
@@ -5202,6 +5281,14 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
otherEvent.xconfigure.border_width;
}
}
+#ifndef QT_NO_XSYNC
+ qt_sync_request_event_data sync_event;
+ sync_event.window = internalWinId();
+ for (XEvent ev;;) {
+ if (!XCheckIfEvent(X11->display, &ev, &qt_sync_request_scanner, (XPointer)&sync_event))
+ break;
+ }
+#endif // QT_NO_XSYNC
}
QRect cr (geometry());
@@ -5287,6 +5374,20 @@ bool QETWidget::translateConfigEvent(const XEvent *event)
if (d->extra && d->extra->topextra)
d->extra->topextra->inTopLevelResize = false;
}
+#ifndef QT_NO_XSYNC
+ if (QTLWExtra *tlwExtra = d->maybeTopData()) {
+ if (tlwExtra->newCounterValueLo != 0 || tlwExtra->newCounterValueHi != 0) {
+ XSyncValue value;
+ XSyncIntsToValue(&value,
+ tlwExtra->newCounterValueLo,
+ tlwExtra->newCounterValueHi);
+
+ XSyncSetCounter(X11->display, tlwExtra->syncUpdateCounter, value);
+ tlwExtra->newCounterValueHi = 0;
+ tlwExtra->newCounterValueLo = 0;
+ }
+ }
+#endif
return true;
}
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index bab3449..96e9580 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -50,6 +50,7 @@
#include "qvariant.h"
#include "qbuffer.h"
#include "qimage.h"
+#include "qtextcodec.h"
QT_BEGIN_NAMESPACE
@@ -276,11 +277,12 @@ QClipboard::~QClipboard()
*/
QString QClipboard::text(QString &subtype, Mode mode) const
{
- const QMimeData *data = mimeData(mode);
+ const QMimeData *const data = mimeData(mode);
if (!data)
return QString();
+
+ const QStringList formats = data->formats();
if (subtype.isEmpty()) {
- QStringList formats = data->formats();
if (formats.contains(QLatin1String("text/plain")))
subtype = QLatin1String("plain");
else {
@@ -289,13 +291,21 @@ QString QClipboard::text(QString &subtype, Mode mode) const
subtype = formats.at(i).mid(5);
break;
}
+ if (subtype.isEmpty())
+ return QString();
}
- }
- if (subtype.isEmpty())
+ } else if (!formats.contains(QLatin1String("text/") + subtype)) {
return QString();
- if (subtype == QLatin1String("plain"))
- return data->text();
- return QString::fromUtf8(data->data(QLatin1String("text/") + subtype));
+ }
+
+ const QByteArray rawData = data->data(QLatin1String("text/") + subtype);
+
+ QTextCodec* codec = QTextCodec::codecForMib(106); // utf-8 is default
+ if (subtype == QLatin1String("html"))
+ codec = QTextCodec::codecForHtml(rawData, codec);
+ else
+ codec = QTextCodec::codecForUtfText(rawData, codec);
+ return codec->toUnicode(rawData);
}
/*!
diff --git a/src/gui/kernel/qclipboard_x11.cpp b/src/gui/kernel/qclipboard_x11.cpp
index 089cc43..b85e024 100644
--- a/src/gui/kernel/qclipboard_x11.cpp
+++ b/src/gui/kernel/qclipboard_x11.cpp
@@ -428,6 +428,20 @@ QClipboard::QClipboard(QObject *parent)
// XFixesSelectionNotify events when someone changes the
// clipboard.
(void)QApplication::desktop();
+
+#ifndef QT_NO_XFIXES
+ if (X11->use_xfixes && X11->ptrXFixesSelectSelectionInput) {
+ const unsigned long eventMask =
+ XFixesSetSelectionOwnerNotifyMask | XFixesSelectionWindowDestroyNotifyMask | XFixesSelectionClientCloseNotifyMask;
+ for (int i = 0; i < X11->screenCount; ++i) {
+ X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(i),
+ XA_PRIMARY, eventMask);
+ X11->ptrXFixesSelectSelectionInput(X11->display, QX11Info::appRootWindow(i),
+ ATOM(CLIPBOARD), eventMask);
+ }
+ }
+#endif // QT_NO_XFIXES
+
if (X11->time == CurrentTime) {
// send a dummy event to myself to get the timestamp from X11.
qt_init_timestamp_data data;
@@ -786,7 +800,7 @@ static Atom send_selection(QClipboardData *d, Atom target, Window window, Atom p
QByteArray data;
QByteArray fmt = X11->xdndAtomToString(target);
- if (fmt.isEmpty() || !QInternalMimeData::hasFormatHelper(QString::fromAscii(fmt), d->source())) { // Not a MIME type we have
+ if (fmt.isEmpty()) { // Not a MIME type we have
DEBUG("QClipboard: send_selection(): converting to type '%s' is not supported", fmt.data());
return XNone;
}
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index f1a7f39..838f751 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -196,6 +196,7 @@ extern "C" {
if (self) {
[self finishInitWithQWidget:widget widgetPrivate:widgetprivate];
}
+ composingText = new QString();
composing = false;
sendKeyEvents = true;
currentCustomTypes = 0;
@@ -419,6 +420,7 @@ extern "C" {
- (void)dealloc
{
+ delete composingText;
[[NSNotificationCenter defaultCenter] removeObserver:self];
delete currentCustomTypes;
[self unregisterDraggedTypes];
@@ -1009,7 +1011,7 @@ extern "C" {
- (void) insertText:(id)aString
{
- if (composing) {
+ if ([aString length]) {
// Send the commit string to the widget.
QString commitText;
if ([aString isKindOfClass:[NSAttributedString class]]) {
@@ -1023,6 +1025,7 @@ extern "C" {
e.setCommitString(commitText);
qt_sendSpontaneousEvent(qwidget, &e);
}
+ composingText->clear();
}
- (void) setMarkedText:(id)aString selectedRange:(NSRange)selRange
@@ -1076,12 +1079,21 @@ extern "C" {
attrs<<QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
0, composingLength, format);
}
+ *composingText = qtText;
QInputMethodEvent e(qtText, attrs);
qt_sendSpontaneousEvent(qwidget, &e);
+ if (!composingLength)
+ composing = false;
}
- (void) unmarkText
{
+ if (composing) {
+ QInputMethodEvent e;
+ e.setCommitString(*composingText);
+ qt_sendSpontaneousEvent(qwidget, &e);
+ }
+ composingText->clear();
composing = false;
}
diff --git a/src/gui/kernel/qcocoaview_mac_p.h b/src/gui/kernel/qcocoaview_mac_p.h
index 527b1a6..be4501f3 100644
--- a/src/gui/kernel/qcocoaview_mac_p.h
+++ b/src/gui/kernel/qcocoaview_mac_p.h
@@ -84,6 +84,7 @@ Q_GUI_EXPORT
bool composing;
int composingLength;
bool sendKeyEvents;
+ QString *composingText;
QStringList *currentCustomTypes;
}
- (id)initWithQWidget:(QWidget *)widget widgetPrivate:(QWidgetPrivate *)widgetprivate;
diff --git a/src/gui/kernel/qcursor.cpp b/src/gui/kernel/qcursor.cpp
index 21a4287..e5056a4 100644
--- a/src/gui/kernel/qcursor.cpp
+++ b/src/gui/kernel/qcursor.cpp
@@ -403,7 +403,7 @@ void QCursorData::initialize()
QCursor::QCursor()
{
if (!QCursorData::initialized) {
- if (qApp->startingUp()) {
+ if (QApplication::startingUp()) {
d = 0;
return;
}
diff --git a/src/gui/kernel/qcursor_win.cpp b/src/gui/kernel/qcursor_win.cpp
index 85d5a11..a475882 100644
--- a/src/gui/kernel/qcursor_win.cpp
+++ b/src/gui/kernel/qcursor_win.cpp
@@ -66,7 +66,7 @@ QCursorData::~QCursorData()
{
delete bm;
delete bmm;
-#if !defined(Q_OS_WINCE) || defined(GWES_ICONCURS)
+#if !defined(Q_WS_WINCE) || defined(GWES_ICONCURS)
if (hcurs)
DestroyCursor(hcurs);
#endif
@@ -129,7 +129,7 @@ extern HBITMAP qt_createIconMask(const QBitmap &bitmap);
static HCURSOR create32BitCursor(const QPixmap &pixmap, int hx, int hy)
{
HCURSOR cur = 0;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QBitmap mask = pixmap.mask();
if (mask.isNull()) {
mask = QBitmap(pixmap.size());
@@ -407,7 +407,7 @@ void QCursorData::update()
}
int n = qMax(1, bbits.width() / 8);
int h = bbits.height();
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
uchar* xBits = new uchar[h * n];
uchar* xMask = new uchar[h * n];
int x = 0;
@@ -430,7 +430,7 @@ void QCursorData::update()
xBits, xMask);
delete [] xBits;
delete [] xMask;
-#elif defined(GWES_ICONCURS) // Q_OS_WINCE
+#elif defined(GWES_ICONCURS) // Q_WS_WINCE
// Windows CE only supports fixed cursor size.
int sysW = GetSystemMetrics(SM_CXCURSOR);
int sysH = GetSystemMetrics(SM_CYCURSOR);
diff --git a/src/gui/kernel/qdesktopwidget_win.cpp b/src/gui/kernel/qdesktopwidget_win.cpp
index 725e985..b9e2e1e 100644
--- a/src/gui/kernel/qdesktopwidget_win.cpp
+++ b/src/gui/kernel/qdesktopwidget_win.cpp
@@ -45,7 +45,7 @@
#include "qlibrary.h"
#include <qvector.h>
#include <limits.h>
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include <sipapi.h>
#endif
#include "qwidget_p.h"
@@ -92,7 +92,7 @@ QVector<QRect> *QDesktopWidgetPrivate::rects = 0;
QVector<QRect> *QDesktopWidgetPrivate::workrects = 0;
static int screen_number = 0;
int QDesktopWidgetPrivate::refcount = 0;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
// Use SIP information, if available
// SipGetInfo is not supported by SSDK (no definition!).
static inline void qt_get_sip_info(QRect &rect)
@@ -208,7 +208,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
SystemParametersInfo(SPI_GETWORKAREA, 0, &r, 0);
QRect qr = QRect(QPoint(r.left, r.top), QPoint(r.right - 1, r.bottom - 1));
-#if defined(Q_OS_WINCE_WM)
+#if defined(Q_WS_WINCE_WM)
qt_get_sip_info(qr);
#endif
@@ -222,7 +222,7 @@ void QDesktopWidgetPrivate::init(QDesktopWidget *that)
enumDisplayMonitors(0, 0, enumCallback, 0);
enumDisplayMonitors = 0;
getMonitorInfo = 0;
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
}
QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
@@ -303,7 +303,7 @@ QWidget *QDesktopWidget::screen(int /* screen */)
const QRect QDesktopWidget::availableGeometry(int screen) const
{
Q_D(const QDesktopWidget);
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
for(int i=0; i < d->workrects->size(); ++i)
qt_get_sip_info((*d->workrects)[i]);
#endif
@@ -385,7 +385,7 @@ void QDesktopWidget::resizeEvent(QResizeEvent *)
QDesktopWidgetPrivate::cleanup();
QDesktopWidgetPrivate::init(this);
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
for(int i=0; i < d->workrects->size(); ++i)
qt_get_sip_info((*d->workrects)[i]);
#endif
diff --git a/src/gui/kernel/qdnd.cpp b/src/gui/kernel/qdnd.cpp
index a5092a0..e83a2ae 100644
--- a/src/gui/kernel/qdnd.cpp
+++ b/src/gui/kernel/qdnd.cpp
@@ -368,7 +368,7 @@ QDragManager::~QDragManager()
QDragManager *QDragManager::self()
{
- if (!instance && qApp && !qApp->closingDown())
+ if (!instance && !QApplication::closingDown())
instance = new QDragManager;
return instance;
}
diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h
index 7a0cb7a..9871658 100644
--- a/src/gui/kernel/qdnd_p.h
+++ b/src/gui/kernel/qdnd_p.h
@@ -202,7 +202,7 @@ public:
#endif
};
-class Q_GUI_EXPORT QDragManager: public QObject {
+class QDragManager: public QObject {
Q_OBJECT
QDragManager();
diff --git a/src/gui/kernel/qdnd_win.cpp b/src/gui/kernel/qdnd_win.cpp
index 8bf5c84..b8c65e8 100644
--- a/src/gui/kernel/qdnd_win.cpp
+++ b/src/gui/kernel/qdnd_win.cpp
@@ -549,7 +549,7 @@ QOleDropSource::QueryContinueDrag(BOOL fEscapePressed, DWORD grfKeyState)
return ResultFromScode(DRAGDROP_S_DROP);
}
#endif
- qApp->processEvents();
+ QApplication::processEvents();
return NOERROR;
}
}
diff --git a/src/gui/kernel/qdnd_x11.cpp b/src/gui/kernel/qdnd_x11.cpp
index 4c9c73c..9b2305d 100644
--- a/src/gui/kernel/qdnd_x11.cpp
+++ b/src/gui/kernel/qdnd_x11.cpp
@@ -542,6 +542,8 @@ bool QX11Data::xdndMimeDataForAtom(Atom a, QMimeData *mimeData, QByteArray *data
dm->xdndMimeTransferedPixmapIndex =
(dm->xdndMimeTransferedPixmapIndex + 1) % 2;
}
+ } else {
+ DEBUG("QClipboard: xdndMimeDataForAtom(): converting to type '%s' is not supported", qPrintable(atomName));
}
}
return data;
@@ -622,28 +624,12 @@ QVariant QX11Data::xdndMimeConvertToFormat(Atom a, const QByteArray &data, const
if (format == QLatin1String("image/ppm")) {
if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) {
Pixmap xpm = *((Pixmap*)data.data());
- Display *dpy = display;
- Window r;
- int x,y;
- uint w,h,bw,d;
if (!xpm)
return QByteArray();
- XGetGeometry(dpy,xpm, &r,&x,&y,&w,&h,&bw,&d);
+ QPixmap qpm = QPixmap::fromX11Pixmap(xpm);
QImageWriter imageWriter;
- GC gc = XCreateGC(dpy, xpm, 0, 0);
- QImage imageToWrite;
- if (d == 1) {
- QBitmap qbm(w,h);
- XCopyArea(dpy,xpm,qbm.handle(),gc,0,0,w,h,0,0);
- imageWriter.setFormat("PBMRAW");
- imageToWrite = qbm.toImage();
- } else {
- QPixmap qpm(w,h);
- XCopyArea(dpy,xpm,qpm.handle(),gc,0,0,w,h,0,0);
- imageWriter.setFormat("PPMRAW");
- imageToWrite = qpm.toImage();
- }
- XFreeGC(dpy,gc);
+ imageWriter.setFormat("PPMRAW");
+ QImage imageToWrite = qpm.toImage();
QBuffer buf;
buf.open(QIODevice::WriteOnly);
imageWriter.setDevice(&buf);
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index ba85eea..99677e2 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -861,6 +861,17 @@ bool QKeyEvent::matches(QKeySequence::StandardKey matchKey) const
uint searchkey = (modifiers() | key()) & ~(Qt::KeypadModifier); //The keypad modifier should not make a difference
uint platform = QApplicationPrivate::currentPlatform();
+#ifdef Q_WS_MAC
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ uint oldSearchKey = searchkey;
+ searchkey &= ~(Qt::ControlModifier | Qt::MetaModifier);
+ if (oldSearchKey & Qt::ControlModifier)
+ searchkey |= Qt::MetaModifier;
+ if (oldSearchKey & Qt::MetaModifier)
+ searchkey |= Qt::ControlModifier;
+ }
+#endif
+
uint N = QKeySequencePrivate::numberOfKeyBindings;
int first = 0;
int last = N - 1;
@@ -3081,7 +3092,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
<< ", " << me->button()
<< ", " << hex << (int)me->buttons()
<< ", " << hex << (int)me->modifiers()
- << ")";
+ << ')';
}
return dbg.space();
@@ -3102,7 +3113,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
#ifndef QT_NO_WHEELEVENT
case QEvent::Wheel:
dbg.nospace() << "QWheelEvent(" << static_cast<const QWheelEvent *>(e)->delta()
- << ")";
+ << ')';
return dbg.space();
#endif
case QEvent::KeyPress:
@@ -3128,7 +3139,7 @@ QDebug operator<<(QDebug dbg, const QEvent *e) {
<< ", \"" << ke->text()
<< "\", " << ke->isAutoRepeat()
<< ", " << ke->count()
- << ")";
+ << ')';
}
return dbg.space();
case QEvent::FocusIn:
diff --git a/src/gui/kernel/qevent_p.h b/src/gui/kernel/qevent_p.h
index cc94aad..8e762d6 100644
--- a/src/gui/kernel/qevent_p.h
+++ b/src/gui/kernel/qevent_p.h
@@ -58,7 +58,7 @@ QT_BEGIN_NAMESPACE
//
// ### Qt 5: remove
-class Q_GUI_EXPORT QKeyEventEx : public QKeyEvent
+class QKeyEventEx : public QKeyEvent
{
public:
QKeyEventEx(Type type, int key, Qt::KeyboardModifiers modifiers,
@@ -76,7 +76,7 @@ protected:
};
// ### Qt 5: remove
-class Q_GUI_EXPORT QMouseEventEx : public QMouseEvent
+class QMouseEventEx : public QMouseEvent
{
public:
QMouseEventEx(Type type, const QPointF &pos, const QPoint &globalPos,
diff --git a/src/gui/kernel/qformlayout.cpp b/src/gui/kernel/qformlayout.cpp
index e2d6108..a665c89 100644
--- a/src/gui/kernel/qformlayout.cpp
+++ b/src/gui/kernel/qformlayout.cpp
@@ -689,12 +689,16 @@ void QFormLayoutPrivate::setupVerticalLayoutData(int width)
// are split.
maxLabelWidth = 0;
if (!wrapAllRows) {
+ int maxFieldMinWidth = 0; //the maximum minimum size of the field
for (int i = 0; i < rr; ++i) {
const QFormLayoutItem *label = m_matrix(i, 0);
const QFormLayoutItem *field = m_matrix(i, 1);
- if (label && (label->sizeHint.width() + (field ? field->minSize.width() : 0) <= width))
+ if (label && field && label->sideBySide)
maxLabelWidth = qMax(maxLabelWidth, label->sizeHint.width());
+ if (field)
+ maxFieldMinWidth = qMax(maxFieldMinWidth, field->minSize.width() + field->sbsHSpace);
}
+ maxLabelWidth = qMin(maxLabelWidth, width - maxFieldMinWidth);
} else {
maxLabelWidth = width;
}
diff --git a/src/gui/kernel/qkeymapper.cpp b/src/gui/kernel/qkeymapper.cpp
index 535d009..503a33b 100644
--- a/src/gui/kernel/qkeymapper.cpp
+++ b/src/gui/kernel/qkeymapper.cpp
@@ -116,6 +116,4 @@ QKeyMapperPrivate *qt_keymapper_private()
return QKeyMapper::instance()->d_func();
}
-Q_GUI_EXPORT QList<int> qt_keymapper_possibleKeys(QKeyEvent *e) { return QKeyMapper::instance()->possibleKeys(e); }
-
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qkeymapper_mac.cpp b/src/gui/kernel/qkeymapper_mac.cpp
index 1a0fb08..01b2c13 100644
--- a/src/gui/kernel/qkeymapper_mac.cpp
+++ b/src/gui/kernel/qkeymapper_mac.cpp
@@ -48,6 +48,7 @@
#include <qinputcontext.h>
#include <private/qkeymapper_p.h>
#include <private/qapplication_p.h>
+#include <private/qmacinputcontext_p.h>
QT_BEGIN_NAMESPACE
@@ -160,6 +161,14 @@ Qt::KeyboardModifiers qt_mac_get_modifiers(int keys)
ret |= Qt::KeyboardModifier(qt_mac_modifier_symbols[i].qt_code);
}
}
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ Qt::KeyboardModifiers oldModifiers = ret;
+ ret &= ~(Qt::MetaModifier | Qt::ControlModifier);
+ if (oldModifiers & Qt::ControlModifier)
+ ret |= Qt::MetaModifier;
+ if (oldModifiers & Qt::MetaModifier)
+ ret |= Qt::ControlModifier;
+ }
return ret;
}
static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
@@ -176,6 +185,15 @@ static int qt_mac_get_mac_modifiers(Qt::KeyboardModifiers keys)
ret |= qt_mac_modifier_symbols[i].mac_code;
}
}
+
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ int oldModifiers = ret;
+ ret &= ~(controlKeyBit | cmdKeyBit);
+ if (oldModifiers & controlKeyBit)
+ ret |= cmdKeyBit;
+ if (oldModifiers & cmdKeyBit)
+ ret |= controlKeyBit;
+ }
return ret;
}
void qt_mac_send_modifiers_changed(quint32 modifiers, QObject *object)
@@ -480,7 +498,8 @@ static bool translateKeyEventInternal(EventHandlerCallRef er, EventRef keyEvent,
#ifdef QT_MAC_USE_COCOA
if (outHandled) {
qt_mac_eat_unicode_key = false;
- CallNextEventHandler(er, keyEvent);
+ if (er)
+ CallNextEventHandler(er, keyEvent);
*outHandled = qt_mac_eat_unicode_key;
}
#endif
@@ -692,8 +711,14 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
return true;
}
- if (qApp->inputContext() && qApp->inputContext()->isComposing())
+ if (qApp->inputContext() && qApp->inputContext()->isComposing()) {
+ if (ekind == kEventRawKeyDown) {
+ QMacInputContext *context = qobject_cast<QMacInputContext*>(qApp->inputContext());
+ if (context)
+ context->setLastKeydownEvent(event);
+ }
return false;
+ }
//get modifiers
Qt::KeyboardModifiers modifiers;
int qtKey;
@@ -721,7 +746,8 @@ bool QKeyMapperPrivate::translateKeyEvent(QWidget *widget, EventHandlerCallRef e
//is it of use to text services? If so we won't bother
//with a QKeyEvent.
qt_mac_eat_unicode_key = false;
- CallNextEventHandler(er, event);
+ if (er)
+ CallNextEventHandler(er, event);
extern bool qt_mac_menubar_is_open();
if (qt_mac_eat_unicode_key || qt_mac_menubar_is_open()) {
return true;
diff --git a/src/gui/kernel/qkeysequence.cpp b/src/gui/kernel/qkeysequence.cpp
index 3bcf9e3..ee45969 100644
--- a/src/gui/kernel/qkeysequence.cpp
+++ b/src/gui/kernel/qkeysequence.cpp
@@ -105,20 +105,39 @@ static bool operator<(int key, const MacSpecialKey &entry)
static const MacSpecialKey * const MacSpecialKeyEntriesEnd = entries + NumEntries;
-static QChar macSymbolForQtKey(int key)
+QChar qt_macSymbolForQtKey(int key)
{
const MacSpecialKey *i = qBinaryFind(entries, MacSpecialKeyEntriesEnd, key);
if (i == MacSpecialKeyEntriesEnd)
return QChar();
- return QChar(i->macSymbol);
+ ushort macSymbol = i->macSymbol;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)
+ && (macSymbol == kControlUnicode || macSymbol == kCommandUnicode)) {
+ if (macSymbol == kControlUnicode)
+ macSymbol = kCommandUnicode;
+ else
+ macSymbol = kControlUnicode;
+ }
+
+ return QChar(macSymbol);
}
static int qtkeyForMacSymbol(const QChar ch)
{
+ const ushort unicode = ch.unicode();
for (int i = 0; i < NumEntries; ++i) {
const MacSpecialKey &entry = entries[i];
- if (entry.macSymbol == ch.unicode())
- return entry.key;
+ if (entry.macSymbol == unicode) {
+ int key = entry.key;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)
+ && (unicode == kControlUnicode || unicode == kCommandUnicode)) {
+ if (unicode == kControlUnicode)
+ key = Qt::Key_Control;
+ else
+ key = Qt::Key_Meta;
+ }
+ return key;
+ }
}
return -1;
}
@@ -126,7 +145,7 @@ static int qtkeyForMacSymbol(const QChar ch)
#else
static bool qt_sequence_no_mnemonics = false;
#endif
-void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; }
+void Q_AUTOTEST_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemonics = !b; }
/*!
\class QKeySequence
@@ -213,12 +232,14 @@ void Q_GUI_EXPORT qt_set_sequence_auto_mnemonic(bool b) { qt_sequence_no_mnemoni
\row \i Open \i Ctrl+O \i Ctrl+O \i Ctrl+O \i Ctrl+O
\row \i Close \i Ctrl+F4, Ctrl+W \i Ctrl+W, Ctrl+F4 \i Ctrl+W \i Ctrl+W
\row \i Save \i Ctrl+S \i Ctrl+S \i Ctrl+S \i Ctrl+S
+ \row \i Quit \i \i Ctrl+Q \i Qtrl+Q \i Qtrl+Q
\row \i SaveAs \i \i Ctrl+Shift+S \i \i Ctrl+Shift+S
\row \i New \i Ctrl+N \i Ctrl+N \i Ctrl+N \i Ctrl+N
\row \i Delete \i Del \i Del, Meta+D \i Del, Ctrl+D \i Del, Ctrl+D
\row \i Cut \i Ctrl+X, Shift+Del \i Ctrl+X \i Ctrl+X, F20, Shift+Del \i Ctrl+X, F20, Shift+Del
\row \i Copy \i Ctrl+C, Ctrl+Ins \i Ctrl+C \i Ctrl+C, F16, Ctrl+Ins \i Ctrl+C, F16, Ctrl+Ins
\row \i Paste \i Ctrl+V, Shift+Ins \i Ctrl+V \i Ctrl+V, F18, Shift+Ins \i Ctrl+V, F18, Shift+Ins
+ \row \i Preferences \i \i Ctrl+, \i \i
\row \i Undo \i Ctrl+Z, Alt+Backspace \i Ctrl+Z \i Ctrl+Z, F14 \i Ctrl+Z, F14
\row \i Redo \i Ctrl+Y, Shift+Ctrl+Z, Alt+Shift+Backspace \i Ctrl+Shift+Z, Ctrl+Y \i Ctrl+Shift+Z \i Ctrl+Shift+Z
\row \i Back \i Alt+Left, Backspace \i Ctrl+[ \i Alt+Left \i Alt+Left
@@ -521,6 +542,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::FindPrevious, 1, Qt::SHIFT | Qt::Key_F3, QApplicationPrivate::KB_Win},
{QKeySequence::ZoomIn, 1, Qt::CTRL | Qt::Key_Plus, QApplicationPrivate::KB_All},
{QKeySequence::NextChild, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_KDE},
+ {QKeySequence::Preferences, 0, Qt::CTRL | Qt::Key_Comma, QApplicationPrivate::KB_Mac},
{QKeySequence::ZoomOut, 1, Qt::CTRL | Qt::Key_Minus, QApplicationPrivate::KB_All},
{QKeySequence::PreviousChild, 0, Qt::CTRL | Qt::Key_Period, QApplicationPrivate::KB_KDE},
{QKeySequence::HelpContents, 1, Qt::CTRL | Qt::Key_Question, QApplicationPrivate::KB_Mac},
@@ -538,6 +560,7 @@ const QKeyBinding QKeySequencePrivate::keyBindings[] = {
{QKeySequence::New, 1, Qt::CTRL | Qt::Key_N, QApplicationPrivate::KB_All},
{QKeySequence::Open, 1, Qt::CTRL | Qt::Key_O, QApplicationPrivate::KB_All},
{QKeySequence::Print, 1, Qt::CTRL | Qt::Key_P, QApplicationPrivate::KB_All},
+ {QKeySequence::Quit, 0, Qt::CTRL | Qt::Key_Q, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_KDE | QApplicationPrivate::KB_Mac},
{QKeySequence::Refresh, 1, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_Gnome | QApplicationPrivate::KB_Mac},
{QKeySequence::Replace, 0, Qt::CTRL | Qt::Key_R, QApplicationPrivate::KB_KDE},
{QKeySequence::Save, 1, Qt::CTRL | Qt::Key_S, QApplicationPrivate::KB_All},
@@ -669,12 +692,14 @@ const uint QKeySequencePrivate::numberOfKeyBindings = sizeof(QKeySequencePrivate
\value NextChild Navigate to next tab or child window.
\value Open Open document.
\value Paste Paste.
+ \value Preferences Open the preferences dialog.
\value PreviousChild Navigate to previous tab or child window.
\value Print Print document.
+ \value Quit Quit the application.
\value Redo Redo.
\value Refresh Refresh or reload current document.
\value Replace Find and replace.
- \value SaveAs Save document after prompting the user for a file name.
+ \value SaveAs Save document after prompting the user for a file name.
\value Save Save document.
\value SelectAll Select all text.
\value SelectEndOfBlock Extend selection to the end of a text block. This shortcut is only used on OS X.
@@ -780,6 +805,21 @@ QKeySequence::QKeySequence(const QKeySequence& keysequence)
d->ref.ref();
}
+#ifdef Q_WS_MAC
+static inline int maybeSwapShortcut(int shortcut)
+{
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ uint oldshortcut = shortcut;
+ shortcut &= ~(Qt::CTRL | Qt::META);
+ if (oldshortcut & Qt::CTRL)
+ shortcut |= Qt::META;
+ if (oldshortcut & Qt::META)
+ shortcut |= Qt::CTRL;
+ }
+ return shortcut;
+}
+#endif
+
/*!
\since 4.2
@@ -796,10 +836,16 @@ QList<QKeySequence> QKeySequence::keyBindings(StandardKey key)
for (uint i = 0; i < QKeySequencePrivate::numberOfKeyBindings ; ++i) {
QKeyBinding keyBinding = QKeySequencePrivate::keyBindings[i];
if (keyBinding.standardKey == key && (keyBinding.platform & platform)) {
- if (keyBinding.priority > 0)
- list.prepend(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut));
- else
- list.append(QKeySequence(QKeySequencePrivate::keyBindings[i].shortcut));
+ uint shortcut =
+#ifdef Q_WS_MAC
+ maybeSwapShortcut(QKeySequencePrivate::keyBindings[i].shortcut);
+#else
+ QKeySequencePrivate::keyBindings[i].shortcut;
+#endif
+ if (keyBinding.priority > 0)
+ list.prepend(QKeySequence(shortcut));
+ else
+ list.append(QKeySequence(shortcut));
}
}
return list;
@@ -967,9 +1013,16 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
gmodifs = globalModifs();
if (gmodifs->isEmpty()) {
#ifdef Q_WS_MAC
- *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode));
+ const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
+ if (dontSwap)
+ *gmodifs << QModifKeyName(Qt::META, QChar(kCommandUnicode));
+ else
+ *gmodifs << QModifKeyName(Qt::CTRL, QChar(kCommandUnicode));
*gmodifs << QModifKeyName(Qt::ALT, QChar(kOptionUnicode));
- *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode));
+ if (dontSwap)
+ *gmodifs << QModifKeyName(Qt::CTRL, QChar(kControlUnicode));
+ else
+ *gmodifs << QModifKeyName(Qt::META, QChar(kControlUnicode));
*gmodifs << QModifKeyName(Qt::SHIFT, QChar(kShiftUnicode));
#endif
*gmodifs << QModifKeyName(Qt::CTRL, QLatin1String("ctrl+"))
@@ -1067,8 +1120,6 @@ int QKeySequencePrivate::decodeString(const QString &str, QKeySequence::Sequence
if (found)
break;
}
-#ifdef Q_WS_MAC
-#endif
}
return ret;
}
@@ -1097,15 +1148,30 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat
QString s;
#if defined(Q_WS_MAC)
if (nativeText) {
- // On MAC the order is Meta, Alt, Shift, Control.
- if ((key & Qt::META) == Qt::META)
- s += macSymbolForQtKey(Qt::Key_Meta);
- if ((key & Qt::ALT) == Qt::ALT)
- s += macSymbolForQtKey(Qt::Key_Alt);
- if ((key & Qt::SHIFT) == Qt::SHIFT)
- s += macSymbolForQtKey(Qt::Key_Shift);
- if ((key & Qt::CTRL) == Qt::CTRL)
- s += macSymbolForQtKey(Qt::Key_Control);
+ // On Mac OS X the order (by default) is Meta, Alt, Shift, Control.
+ // If the AA_MacDontSwapCtrlAndMeta is enabled, then the order
+ // is Ctrl, Alt, Shift, Meta. The macSymbolForQtKey does this swap
+ // for us, which means that we have to adjust our order here.
+ // The upshot is a lot more infrastructure to keep the number of
+ // if tests down and the code relatively clean.
+ static const int ModifierOrder[] = { Qt::META, Qt::ALT, Qt::SHIFT, Qt::CTRL, 0 };
+ static const int QtKeyOrder[] = { Qt::Key_Meta, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Control, 0 };
+ static const int DontSwapModifierOrder[] = { Qt::CTRL, Qt::ALT, Qt::SHIFT, Qt::META, 0 };
+ static const int DontSwapQtKeyOrder[] = { Qt::Key_Control, Qt::Key_Alt, Qt::Key_Shift, Qt::Key_Meta, 0 };
+ const int *modifierOrder;
+ const int *qtkeyOrder;
+ if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) {
+ modifierOrder = DontSwapModifierOrder;
+ qtkeyOrder = DontSwapQtKeyOrder;
+ } else {
+ modifierOrder = ModifierOrder;
+ qtkeyOrder = QtKeyOrder;
+ }
+
+ for (int i = 0; modifierOrder[i] != 0; ++i) {
+ if (key & modifierOrder[i])
+ s += qt_macSymbolForQtKey(qtkeyOrder[i]);
+ }
} else
#endif
{
@@ -1138,7 +1204,7 @@ QString QKeySequencePrivate::encodeString(int key, QKeySequence::SequenceFormat
int i=0;
#if defined(Q_WS_MAC)
if (nativeText) {
- QChar ch = macSymbolForQtKey(key);
+ QChar ch = qt_macSymbolForQtKey(key);
if (!ch.isNull())
p = ch;
else
diff --git a/src/gui/kernel/qkeysequence.h b/src/gui/kernel/qkeysequence.h
index 1c4776f..f78e34a 100644
--- a/src/gui/kernel/qkeysequence.h
+++ b/src/gui/kernel/qkeysequence.h
@@ -136,7 +136,9 @@ public:
DeleteEndOfLine,
InsertParagraphSeparator,
InsertLineSeparator,
- SaveAs
+ SaveAs,
+ Preferences,
+ Quit
};
QKeySequence();
diff --git a/src/gui/kernel/qlayout.cpp b/src/gui/kernel/qlayout.cpp
index d8d8234..2d4ff18 100644
--- a/src/gui/kernel/qlayout.cpp
+++ b/src/gui/kernel/qlayout.cpp
@@ -1593,8 +1593,6 @@ QDataStream &operator>>(QDataStream &stream, QSizePolicy &policy)
{
return stream >> policy.data;
}
-
-#endif
-
+#endif // QT_NO_DATASTREAM
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qlayoutengine.cpp b/src/gui/kernel/qlayoutengine.cpp
index fbaa388..3673f08 100644
--- a/src/gui/kernel/qlayoutengine.cpp
+++ b/src/gui/kernel/qlayoutengine.cpp
@@ -329,7 +329,7 @@ void qGeomCalc(QVector<QLayoutStruct> &chain, int start, int count,
qDebug() << "qGeomCalc" << "start" << start << "count" << count << "pos" << pos
<< "space" << space << "spacer" << spacer;
for (i = start; i < start + count; ++i) {
- qDebug() << i << ":" << chain[i].minimumSize << chain[i].smartSizeHint()
+ qDebug() << i << ':' << chain[i].minimumSize << chain[i].smartSizeHint()
<< chain[i].maximumSize << "stretch" << chain[i].stretch
<< "empty" << chain[i].empty << "expansive" << chain[i].expansive
<< "spacing" << chain[i].spacing;
diff --git a/src/gui/kernel/qlayoutitem.cpp b/src/gui/kernel/qlayoutitem.cpp
index 0fd73b8..c70ab2d 100644
--- a/src/gui/kernel/qlayoutitem.cpp
+++ b/src/gui/kernel/qlayoutitem.cpp
@@ -54,7 +54,8 @@ QT_BEGIN_NAMESPACE
inline static QRect fromLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
{
- return priv->fromOrToLayoutItemRect(rect, -1);
+ return rect.adjusted(priv->leftLayoutItemMargin, priv->topLayoutItemMargin,
+ -priv->rightLayoutItemMargin, -priv->bottomLayoutItemMargin);
}
inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
@@ -64,7 +65,8 @@ inline static QSize fromLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
inline static QRect toLayoutItemRect(QWidgetPrivate *priv, const QRect &rect)
{
- return priv->fromOrToLayoutItemRect(rect, +1);
+ return rect.adjusted(-priv->leftLayoutItemMargin, -priv->topLayoutItemMargin,
+ priv->rightLayoutItemMargin, priv->bottomLayoutItemMargin);
}
inline static QSize toLayoutItemSize(QWidgetPrivate *priv, const QSize &size)
diff --git a/src/gui/kernel/qmime_mac.cpp b/src/gui/kernel/qmime_mac.cpp
index cf1d747..9cb8b61 100644
--- a/src/gui/kernel/qmime_mac.cpp
+++ b/src/gui/kernel/qmime_mac.cpp
@@ -127,32 +127,44 @@ CFStringRef qt_mac_mime_typeUTI = CFSTR("com.pasteboard.trolltech.marker");
/*!
\class QMacPasteboardMime
- \brief The QMacPasteboardMime class maps open-standard MIME to Mac flavors.
+ \brief The QMacPasteboardMime class converts between a MIME type and a
+ \l{http://developer.apple.com/macosx/uniformtypeidentifiers.html}{Uniform
+ Type Identifier (UTI)} format.
\since 4.2
\ingroup io
\ingroup draganddrop
\ingroup misc
- Qt's drag and drop support and clipboard facilities use the MIME
- standard. On X11, this maps trivially to the Xdnd protocol, but on
- Mac although some applications use MIME types to describe clipboard
- formats, others use arbitrary non-standardized naming conventions,
- or unnamed built-in Mac formats.
+ Qt's drag and drop and clipboard facilities use the MIME
+ standard. On X11, this maps trivially to the Xdnd protocol. On
+ Mac, although some applications use MIME to describe clipboard
+ contents, it is more common to use Apple's UTI format.
- By instantiating subclasses of QMacPasteboardMime that provide conversions
- between Mac flavors and MIME formats, you can convert proprietary
- clipboard formats to MIME formats.
+ QMacPasteboardMime's role is to bridge the gap between MIME and UTI;
+ By subclasses this class, one can extend Qt's drag and drop
+ and clipboard handling to convert to and from unsupported, or proprietary, UTI formats.
- Qt has predefined support for the following Mac flavors:
+ A subclass of QMacPasteboardMime will automatically be registered, and active, upon instantiation.
+
+ Qt has predefined support for the following UTIs:
\list
- \i kScrapFlavorTypeUnicode - converted to "text/plain;charset=ISO-10646-UCS-2"
- \i kScrapFlavorTypeText - converted to "text/plain;charset=system" or "text/plain"
- \i kScrapFlavorTypePicture - converted to "application/x-qt-image"
- \i typeFileURL - converted to "text/uri-list"
+ \i public.utf8-plain-text - converts to "text/plain"
+ \i public.utf16-plain-text - converts to "text/plain"
+ \i public.html - converts to "text/html"
+ \i public.url - converts to "text/uri-list"
+ \i public.file-url - converts to "text/uri-list"
+ \i public.tiff - converts to "application/x-qt-image"
+ \i com.apple.traditional-mac-plain-text - converts to "text/plain"
+ \i com.apple.pict - converts to "application/x-qt-image"
\endlist
- You can check if a MIME type is convertible using canConvert() and
- can perform conversions with convertToMime() and convertFromMime().
+ When working with MIME data, Qt will interate through all instances of QMacPasteboardMime to
+ find an instance that can convert to, or from, a specific MIME type. It will do this by calling
+ canConvert() on each instance, starting with (and choosing) the last created instance first.
+ The actual conversions will be done by using convertToMime() and convertFromMime().
+
+ \note The API uses the term "flavor" in some cases. This is for backwards
+ compatibility reasons, and should now be understood as UTIs.
*/
/*! \enum QMacPasteboardMime::QMacPasteboardMimeType
@@ -206,7 +218,7 @@ QString QMacPasteboardMimeAny::flavorFor(const QString &mime)
if(mime == QLatin1String("application/x-qt-mime-type-name"))
return QString();
QString ret = QLatin1String("com.trolltech.anymime.") + mime;
- return ret.replace(QLatin1String("/"), QLatin1String("--"));
+ return ret.replace(QLatin1Char('/'), QLatin1String("--"));
}
QString QMacPasteboardMimeAny::mimeFor(QString flav)
@@ -382,7 +394,7 @@ QString QMacPasteboardMimeUnicodeText::flavorFor(const QString &mime)
int i = mime.indexOf(QLatin1String("charset="));
if (i >= 0) {
QString cs(mime.mid(i+8).toLower());
- i = cs.indexOf(QLatin1String(";"));
+ i = cs.indexOf(QLatin1Char(';'));
if (i>=0)
cs = cs.left(i);
if (cs == QLatin1String("system"))
@@ -841,6 +853,80 @@ QList<QByteArray> QMacPasteboardMimeFileUri::convertFromMime(const QString &mime
return ret;
}
+class QMacPasteboardMimeUrl : public QMacPasteboardMime {
+public:
+ QMacPasteboardMimeUrl() : QMacPasteboardMime(MIME_ALL) { }
+ QString convertorName();
+
+ QString flavorFor(const QString &mime);
+ QString mimeFor(QString flav);
+ bool canConvert(const QString &mime, QString flav);
+ QVariant convertToMime(const QString &mime, QList<QByteArray> data, QString flav);
+ QList<QByteArray> convertFromMime(const QString &mime, QVariant data, QString flav);
+};
+
+QString QMacPasteboardMimeUrl::convertorName()
+{
+ return QLatin1String("URL");
+}
+
+QString QMacPasteboardMimeUrl::flavorFor(const QString &mime)
+{
+ if(mime.startsWith(QLatin1String("text/uri-list")))
+ return QLatin1String("public.url");
+ return QString();
+}
+
+QString QMacPasteboardMimeUrl::mimeFor(QString flav)
+{
+ if(flav == QLatin1String("public.url"))
+ return QLatin1String("text/uri-list");
+ return QString();
+}
+
+bool QMacPasteboardMimeUrl::canConvert(const QString &mime, QString flav)
+{
+ return flav == QLatin1String("public.url")
+ && mime == QLatin1String("text/uri-list");
+}
+
+QVariant QMacPasteboardMimeUrl::convertToMime(const QString &mime, QList<QByteArray> data, QString flav)
+{
+ if(!canConvert(mime, flav))
+ return QVariant();
+
+ QList<QVariant> ret;
+ for (int i=0; i<data.size(); ++i) {
+ QUrl url = QUrl::fromEncoded(data.at(i));
+ if (url.host().toLower() == QLatin1String("localhost"))
+ url.setHost(QString());
+ url.setPath(url.path().normalized(QString::NormalizationForm_C));
+ ret.append(url);
+ }
+ return QVariant(ret);
+}
+
+QList<QByteArray> QMacPasteboardMimeUrl::convertFromMime(const QString &mime, QVariant data, QString flav)
+{
+ QList<QByteArray> ret;
+ if (!canConvert(mime, flav))
+ return ret;
+
+ QList<QVariant> urls = data.toList();
+ for(int i=0; i<urls.size(); ++i) {
+ QUrl url = urls.at(i).toUrl();
+ if (url.scheme().isEmpty())
+ url.setScheme(QLatin1String("file"));
+ if (url.scheme().toLower() == QLatin1String("file")) {
+ if (url.host().isEmpty())
+ url.setHost(QLatin1String("localhost"));
+ url.setPath(url.path().normalized(QString::NormalizationForm_D));
+ }
+ ret.append(url.toEncoded());
+ }
+ return ret;
+}
+
#ifdef QT3_SUPPORT
class QMacPasteboardMimeQt3Any : public QMacPasteboardMime {
private:
@@ -1043,6 +1129,7 @@ void QMacPasteboardMime::initialize()
new QMacPasteboardMimePlainText;
new QMacPasteboardMimeHTMLText;
new QMacPasteboardMimeFileUri;
+ new QMacPasteboardMimeUrl;
new QMacPasteboardMimeTypeName;
//make sure our "non-standard" types are always last! --Sam
new QMacPasteboardMimeAny;
diff --git a/src/gui/kernel/qmime_win.cpp b/src/gui/kernel/qmime_win.cpp
index cd0aae6..ad2dec1 100644
--- a/src/gui/kernel/qmime_win.cpp
+++ b/src/gui/kernel/qmime_win.cpp
@@ -852,7 +852,7 @@ QVariant QWindowsMimeHtml::convertToMime(const QString &mime, IDataObject *pData
if (end > start && start > 0) {
html = "<!--StartFragment-->" + html.mid(start, end - start);
html += "<!--EndFragment-->";
- html.replace("\r", "");
+ html.replace('\r', "");
result = QString::fromUtf8(html);
}
}
@@ -1262,16 +1262,16 @@ QVector<FORMATETC> QLastResortMimes::formatsForMime(const QString &mimeType, con
}
return formatetcs;
}
-static const char *x_qt_windows_mime = "application/x-qt-windows-mime;value=\"";
+static const char x_qt_windows_mime[] = "application/x-qt-windows-mime;value=\"";
-bool isCustomMimeType(const QString &mimeType)
+static bool isCustomMimeType(const QString &mimeType)
{
return mimeType.startsWith(QLatin1String(x_qt_windows_mime), Qt::CaseInsensitive);
}
-QString customMimeType(const QString &mimeType)
+static QString customMimeType(const QString &mimeType)
{
- int len = QString(QLatin1String(x_qt_windows_mime)).length();
+ int len = sizeof(x_qt_windows_mime) - 1;
int n = mimeType.lastIndexOf(QLatin1Char('\"'))-len;
return mimeType.mid(len, n);
}
diff --git a/src/gui/kernel/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 6541510..18a2142 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -125,7 +125,7 @@ QDataStream &operator>>(QDataStream &s, QColorGroup &g)
{
return qt_stream_in_qcolorgroup(s, g);
}
-#endif
+#endif // QT_NO_DATASTREAM
/*!
Constructs a palette with the specified \a active, \a disabled and
@@ -158,7 +158,7 @@ void QPalette::setColorGroup(ColorGroup cg, const QColorGroup &g)
g.brush(LinkVisited), g.brush(ToolTipBase), g.brush(ToolTipText));
}
-#endif
+#endif // QT3_SUPPORT
/*!
\fn const QColor &QPalette::color(ColorRole role) const
diff --git a/src/gui/kernel/qshortcut.cpp b/src/gui/kernel/qshortcut.cpp
index 50b6e59..bced833 100644
--- a/src/gui/kernel/qshortcut.cpp
+++ b/src/gui/kernel/qshortcut.cpp
@@ -163,7 +163,6 @@ public:
void QShortcutPrivate::redoGrab(QShortcutMap &map)
{
Q_Q(QShortcut);
- QWidget *parent = q->parentWidget();
if (!parent) {
qWarning("QShortcut: No widget parent defined");
return;
diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp
index 7a19252..72f7732 100644
--- a/src/gui/kernel/qshortcutmap.cpp
+++ b/src/gui/kernel/qshortcutmap.cpp
@@ -61,8 +61,6 @@
QT_BEGIN_NAMESPACE
-extern bool qt_mac_no_native_menubar; // qmenu_mac.cpp
-
// To enable verbose output uncomment below
//#define DEBUG_QSHORTCUTMAP
@@ -111,7 +109,7 @@ QDebug &operator<<(QDebug &dbg, const QShortcutEntry *se) {
dbg.nospace()
<< "QShortcutEntry(" << se->keyseq
<< "), id(" << se->id << "), enabled(" << se->enabled << "), autorepeat(" << se->autorepeat
- << "), owner(" << se->owner << ")";
+ << "), owner(" << se->owner << ')';
return dbg.space();
}
#endif // QT_NO_DEBUGSTREAM
@@ -627,13 +625,13 @@ QKeySequence::SequenceMatch QShortcutMap::matches(const QKeySequence &seq1,
bool QShortcutMap::correctContext(const QShortcutEntry &item) const {
Q_ASSERT_X(item.owner, "QShortcutMap", "Shortcut has no owner. Illegal map state!");
- QWidget *active_window = qApp->activeWindow();
+ QWidget *active_window = QApplication::activeWindow();
// popups do not become the active window,
// so we fake it here to get the correct context
// for the shortcut system.
- if (qApp->activePopupWidget())
- active_window = qApp->activePopupWidget();
+ if (QApplication::activePopupWidget())
+ active_window = QApplication::activePopupWidget();
if (!active_window)
return false;
@@ -657,7 +655,7 @@ bool QShortcutMap::correctWidgetContext(Qt::ShortcutContext context, QWidget *w,
{
bool visible = w->isVisible();
#ifdef Q_WS_MAC
- if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w))
+ if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
visible = true;
#endif
@@ -720,7 +718,7 @@ bool QShortcutMap::correctGraphicsWidgetContext(Qt::ShortcutContext context, QGr
{
bool visible = w->isVisible();
#ifdef Q_WS_MAC
- if (!qt_mac_no_native_menubar && qobject_cast<QMenuBar *>(w))
+ if (!qApp->testAttribute(Qt::AA_DontUseNativeMenuBar) && qobject_cast<QMenuBar *>(w))
visible = true;
#endif
@@ -875,7 +873,7 @@ void QShortcutMap::dispatchEvent(QKeyEvent *e)
qDebug().nospace()
<< "QShortcutMap::dispatchEvent(): Sending QShortcutEvent(\""
<< (QString)next->keyseq << "\", " << next->id << ", "
- << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ")";
+ << (bool)(enabledShortcuts>1) << ") to object(" << next->owner << ')';
#endif
QShortcutEvent se(next->keyseq, next->id, enabledShortcuts>1);
QApplication::sendEvent(const_cast<QObject *>(next->owner), &se);
diff --git a/src/gui/kernel/qsizepolicy.h b/src/gui/kernel/qsizepolicy.h
index 652fda1..32b3b4f 100644
--- a/src/gui/kernel/qsizepolicy.h
+++ b/src/gui/kernel/qsizepolicy.h
@@ -203,9 +203,11 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
+#ifndef QT_NO_DATASTREAM
// implemented in qlayout.cpp
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QSizePolicy &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QSizePolicy &);
+#endif
inline void QSizePolicy::transpose() {
Policy hData = horizontalPolicy();
diff --git a/src/gui/kernel/qsound_qws.cpp b/src/gui/kernel/qsound_qws.cpp
index e83935f..661544f 100644
--- a/src/gui/kernel/qsound_qws.cpp
+++ b/src/gui/kernel/qsound_qws.cpp
@@ -279,7 +279,7 @@ QAuBucketQWS::QAuBucketQWS( QAuServerQWS *server, QSound *sound, QObject* parent
sound->setObjectName( m_id.toString() );
- m_channel = new QCopChannel(QString( QLatin1String("QPE/QSound/") ).append( m_id ), this );
+ m_channel = new QCopChannel(QLatin1String("QPE/QSound/") + m_id ), this );
connect( m_channel, SIGNAL(received(QString,QByteArray)),
this, SLOT(processMessage(QString,QByteArray)) );
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index 9165836..554e9d5 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -88,6 +88,52 @@
QT_BEGIN_NAMESPACE
+Q_GLOBAL_STATIC(QMacWindowFader, macwindowFader);
+
+QMacWindowFader::QMacWindowFader()
+ : m_duration(0.250)
+{
+}
+
+QMacWindowFader *QMacWindowFader::currentFader()
+{
+ return macwindowFader();
+}
+
+void QMacWindowFader::registerWindowToFade(QWidget *window)
+{
+ m_windowsToFade.append(window);
+}
+
+void QMacWindowFader::performFade()
+{
+ const QWidgetList myWidgetsToFade = m_windowsToFade;
+ const int widgetCount = myWidgetsToFade.count();
+#if QT_MAC_USE_COCOA
+ QMacCocoaAutoReleasePool pool;
+ [NSAnimationContext beginGrouping];
+ [[NSAnimationContext currentContext] setDuration:NSTimeInterval(m_duration)];
+#endif
+
+ for (int i = 0; i < widgetCount; ++i) {
+ QWidget *widget = m_windowsToFade.at(i);
+ OSWindowRef window = qt_mac_window_for(widget);
+#if QT_MAC_USE_COCOA
+ [[window animator] setAlphaValue:0.0];
+ QTimer::singleShot(qRound(m_duration * 1000), widget, SLOT(hide()));
+#else
+ TransitionWindowOptions options = {0, m_duration, 0, 0};
+ TransitionWindowWithOptions(window, kWindowFadeTransitionEffect, kWindowHideTransitionAction,
+ 0, 1, &options);
+#endif
+ }
+#if QT_MAC_USE_COCOA
+ [NSAnimationContext endGrouping];
+#endif
+ m_duration = 0.250;
+ m_windowsToFade.clear();
+}
+
extern bool qt_sendSpontaneousEvent(QObject *receiver, QEvent *event); // qapplication.cpp;
extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QWidget * mac_mouse_grabber;
@@ -95,29 +141,26 @@ extern QWidget * mac_mouse_grabber;
void macWindowFade(void * /*OSWindowRef*/ window, float durationSeconds)
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
- if( wnd ) {
+ if (wnd) {
+ QWidget *widget;
#if QT_MAC_USE_COCOA
- QMacCocoaAutoReleasePool pool;
- [NSAnimationContext beginGrouping];
- [[wnd animator] setAlphaValue:0.0];
- if (durationSeconds > 0) {
- [[NSAnimationContext currentContext] setDuration:NSTimeInterval(durationSeconds)];
- } else {
- durationSeconds = [[NSAnimationContext currentContext] duration];
- }
- [NSAnimationContext endGrouping];
- QTimer::singleShot(qRound(durationSeconds * 1000), [wnd QT_MANGLE_NAMESPACE(qt_qwidget)], SLOT(hide()));
+ widget = [wnd QT_MANGLE_NAMESPACE(qt_qwidget)];
#else
- if (durationSeconds <= 0)
- durationSeconds = 0.15;
- TransitionWindowOptions options = {0, durationSeconds, 0, 0};
- TransitionWindowWithOptions(wnd, kWindowFadeTransitionEffect, kWindowHideTransitionAction, 0, 1, &options);
+ const UInt32 kWidgetCreatorQt = kEventClassQt;
+ enum {
+ kWidgetPropertyQWidget = 'QWId' //QWidget *
+ };
+ if (GetWindowProperty(static_cast<WindowRef>(window), kWidgetCreatorQt, kWidgetPropertyQWidget, sizeof(widget), 0, &widget) != noErr)
+ widget = 0;
#endif
- }
+ if (widget) {
+ QMacWindowFader::currentFader()->setFadeDuration(durationSeconds);
+ QMacWindowFader::currentFader()->registerWindowToFade(widget);
+ QMacWindowFader::currentFader()->performFade();
+ }
+ }
}
-
-
bool macWindowIsTextured( void * /*OSWindowRef*/ window )
{
OSWindowRef wnd = static_cast<OSWindowRef>(window);
diff --git a/src/gui/kernel/qt_mac_p.h b/src/gui/kernel/qt_mac_p.h
index ca995dc..3b0f546 100644
--- a/src/gui/kernel/qt_mac_p.h
+++ b/src/gui/kernel/qt_mac_p.h
@@ -120,6 +120,21 @@ public:
}
};
+// Class for chaining to gether a bunch of fades. It pretty much is only used for qmenu fading.
+class QMacWindowFader
+{
+ QWidgetList m_windowsToFade;
+ float m_duration;
+ Q_DISABLE_COPY(QMacWindowFader)
+public:
+ QMacWindowFader(); // PLEASE DON'T CALL THIS.
+ static QMacWindowFader *currentFader();
+ void registerWindowToFade(QWidget *window);
+ void setFadeDuration(float durationInSecs) { m_duration = durationInSecs; }
+ float fadeDuration() const { return m_duration; }
+ void performFade();
+};
+
class Q_GUI_EXPORT QMacCocoaAutoReleasePool
{
private:
diff --git a/src/gui/kernel/qt_x11_p.h b/src/gui/kernel/qt_x11_p.h
index 563b7e9..b480f34 100644
--- a/src/gui/kernel/qt_x11_p.h
+++ b/src/gui/kernel/qt_x11_p.h
@@ -154,6 +154,10 @@ extern "C" {
# include <X11/extensions/Xrender.h>
#endif // QT_NO_XRENDER
+#ifndef QT_NO_XSYNC
+# include "X11/extensions/sync.h"
+#endif
+
// #define QT_NO_XKB
#ifndef QT_NO_XKB
# include <X11/XKBlib.h>
@@ -503,6 +507,7 @@ struct QX11Data
char *startupId;
char *originalStartupId;
+ char *startupIdString;
DesktopEnvironment desktopEnvironment;
@@ -514,6 +519,8 @@ struct QX11Data
WM_TAKE_FOCUS,
_NET_WM_PING,
_NET_WM_CONTEXT_HELP,
+ _NET_WM_SYNC_REQUEST,
+ _NET_WM_SYNC_REQUEST_COUNTER,
// ICCCM window state
WM_STATE,
@@ -652,6 +659,10 @@ struct QX11Data
_XEMBED,
_XEMBED_INFO,
+ XWacomStylus,
+ XWacomCursor,
+ XWacomEraser,
+
NPredefinedAtoms,
_QT_SETTINGS_TIMESTAMP = NPredefinedAtoms,
diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp
index 15a3dd2..2f97e7b 100644
--- a/src/gui/kernel/qtooltip.cpp
+++ b/src/gui/kernel/qtooltip.cpp
@@ -126,14 +126,15 @@ public:
bool eventFilter(QObject *, QEvent *);
- QBasicTimer hideTimer;
+ QBasicTimer hideTimer, expireTimer;
+
bool fadingOut;
void reuseTip(const QString &text);
void hideTip();
void hideTipImmediately();
void setTipRect(QWidget *w, const QRect &r);
- void restartHideTimer();
+ void restartExpireTimer();
bool tipChanged(const QPoint &pos, const QString &text, QObject *o);
void placeTip(const QPoint &pos, QWidget *w);
@@ -190,16 +191,17 @@ QTipLabel::QTipLabel(const QString &text, QWidget *w)
reuseTip(text);
}
-void QTipLabel::restartHideTimer()
+void QTipLabel::restartExpireTimer()
{
int time = 10000 + 40 * qMax(0, text().length()-100);
- hideTimer.start(time, this);
+ expireTimer.start(time, this);
+ hideTimer.stop();
}
void QTipLabel::reuseTip(const QString &text)
{
#ifndef QT_NO_STYLE_STYLESHEET
- if (styleSheetParent) {
+ if (styleSheetParent){
disconnect(styleSheetParent, SIGNAL(destroyed()),
QTipLabel::instance, SLOT(styleSheetParentDestroyed()));
styleSheetParent = 0;
@@ -213,7 +215,7 @@ void QTipLabel::reuseTip(const QString &text)
if (fm.descent() == 2 && fm.ascent() >= 11)
++extra.rheight();
resize(sizeHint() + extra);
- restartHideTimer();
+ restartExpireTimer();
}
void QTipLabel::paintEvent(QPaintEvent *ev)
@@ -257,7 +259,8 @@ QTipLabel::~QTipLabel()
void QTipLabel::hideTip()
{
- hideTimer.start(300, this);
+ if (!hideTimer.isActive())
+ hideTimer.start(300, this);
}
void QTipLabel::hideTipImmediately()
@@ -278,8 +281,10 @@ void QTipLabel::setTipRect(QWidget *w, const QRect &r)
void QTipLabel::timerEvent(QTimerEvent *e)
{
- if (e->timerId() == hideTimer.timerId()){
+ if (e->timerId() == hideTimer.timerId()
+ || e->timerId() == expireTimer.timerId()){
hideTimer.stop();
+ expireTimer.stop();
#if defined(Q_WS_MAC) && !defined(QT_NO_EFFECTS)
if (QApplication::isEffectEnabled(Qt::UI_FadeTooltip)){
// Fade out tip on mac (makes it invisible).
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 8d2569e..efd90f6 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -171,41 +171,49 @@ static inline bool bypassGraphicsProxyWidget(QWidget *p)
extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); // qapplication.cpp
extern QDesktopWidget *qt_desktopWidget; // qapplication.cpp
-QWidgetPrivate::QWidgetPrivate(int version) :
- QObjectPrivate(version), extra(0),
- focus_next(0), focus_prev(0), focus_child(0)
- ,layout(0), widgetItem(0)
- ,leftmargin(0), topmargin(0), rightmargin(0), bottommargin(0)
- ,leftLayoutItemMargin(0), topLayoutItemMargin(0), rightLayoutItemMargin(0)
- ,bottomLayoutItemMargin(0)
- ,fg_role(QPalette::NoRole)
- ,bg_role(QPalette::NoRole)
- ,hd(0)
- ,dirty(0)
- ,needsFlush(0)
- ,dirtyOpaqueChildren(1)
- ,isOpaque(0)
- ,inDirtyList(0)
- ,isScrolled(0)
- ,isMoved(0)
- ,usesDoubleBufferedGLContext(0)
-#ifdef Q_WS_WIN
- ,noPaintOnScreen(0)
-#endif
- ,inheritedFontResolveMask(0)
- ,inheritedPaletteResolveMask(0)
+QWidgetPrivate::QWidgetPrivate(int version)
+ : QObjectPrivate(version)
+ , extra(0)
+ , focus_next(0)
+ , focus_prev(0)
+ , focus_child(0)
+ , layout(0)
+ , needsFlush(0)
+ , redirectDev(0)
+ , widgetItem(0)
+ , extraPaintEngine(0)
+ , polished(0)
+ , inheritedFontResolveMask(0)
+ , inheritedPaletteResolveMask(0)
+ , leftmargin(0)
+ , topmargin(0)
+ , rightmargin(0)
+ , bottommargin(0)
+ , leftLayoutItemMargin(0)
+ , topLayoutItemMargin(0)
+ , rightLayoutItemMargin(0)
+ , bottomLayoutItemMargin(0)
+ , hd(0)
+ , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
+ , fg_role(QPalette::NoRole)
+ , bg_role(QPalette::NoRole)
+ , dirtyOpaqueChildren(1)
+ , isOpaque(0)
+ , inDirtyList(0)
+ , isScrolled(0)
+ , isMoved(0)
+ , usesDoubleBufferedGLContext(0)
#if defined(Q_WS_X11)
- ,picture(0)
-#endif
-#ifdef Q_WS_MAC
- ,needWindowChange(0)
- ,isGLWidget(0)
+ , picture(0)
+#elif defined(Q_WS_WIN)
+ , noPaintOnScreen(0)
+#elif defined(Q_WS_MAC)
+ , needWindowChange(0)
+ , isGLWidget(0)
+ , window_event(0)
+ , qd_hd(0)
#endif
- ,imHints(Qt::ImhNone)
- ,polished(0)
-
- , size_policy(QSizePolicy::Preferred, QSizePolicy::Preferred)
- , redirectDev(0)
+ ,imHints(Qt::ImhNone)
{
if (!qApp) {
qFatal("QWidget: Must construct a QApplication before a QPaintDevice");
@@ -1091,7 +1099,7 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
if (customize)
; // don't modify window flags if the user explicitely set them.
else if (type == Qt::Dialog || type == Qt::Sheet)
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowContextHelpButtonHint | Qt::WindowCloseButtonHint;
#else
flags |= Qt::WindowTitleHint | Qt::WindowSystemMenuHint | Qt::WindowCloseButtonHint;
@@ -1107,7 +1115,7 @@ void QWidgetPrivate::adjustFlags(Qt::WindowFlags &flags, QWidget *w)
void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
{
Q_Q(QWidget);
- if (qApp->type() == QApplication::Tty)
+ if (QApplication::type() == QApplication::Tty)
qFatal("QWidget: Cannot create a QWidget when no GUI is being used");
Q_ASSERT(uncreatedWidgets);
@@ -1122,7 +1130,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
q->data = &data;
#ifndef QT_NO_THREAD
- if (!q->parent()) {
+ if (!parent) {
Q_ASSERT_X(q->thread() == qApp->thread(), "QWidget",
"Widgets must be created in the GUI thread.");
}
@@ -1158,7 +1166,7 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f)
if (f & Qt::MSWindowsOwnDC)
q->setAttribute(Qt::WA_NativeWindow);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
data.window_state_internal = 0;
#endif
@@ -1400,7 +1408,7 @@ QWidget::~QWidget()
#ifdef QT3_SUPPORT
if (QApplicationPrivate::main_widget == this) { // reset main widget
QApplicationPrivate::main_widget = 0;
- qApp->quit();
+ QApplication::quit();
}
#endif
@@ -1409,7 +1417,7 @@ QWidget::~QWidget()
d->setDirtyOpaqueRegion();
if (isWindow() && isVisible() && internalWinId())
- hide();
+ d->close_helper(QWidgetPrivate::CloseNoEvent);
#if defined(Q_WS_WIN) || defined(Q_WS_X11)
else if (!internalWinId() && isVisible())
qApp->d_func()->sendSyntheticEnterLeave(this);
@@ -1476,36 +1484,26 @@ void QWidgetPrivate::createTLExtra()
createExtra();
if (!extra->topextra) {
QTLWExtra* x = extra->topextra = new QTLWExtra;
+ x->icon = 0;
+ x->iconPixmap = 0;
+ x->backingStore = 0;
x->windowSurface = 0;
+ x->sharedPainter = 0;
+ x->incw = x->inch = 0;
+ x->basew = x->baseh = 0;
+ x->frameStrut.setCoords(0, 0, 0, 0);
+ x->normalGeometry = QRect(0,0,-1,-1);
+ x->savedFlags = 0;
x->opacity = 255;
x->posFromMove = false;
x->sizeAdjusted = false;
x->inTopLevelResize = false;
x->inRepaint = false;
- x->backingStore = 0;
- x->icon = 0;
- x->iconPixmap = 0;
- x->frameStrut.setCoords(0, 0, 0, 0);
- x->incw = x->inch = 0;
- x->basew = x->baseh = 0;
- x->normalGeometry = QRect(0,0,-1,-1);
-#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_MAC)
x->embedded = 0;
-#endif
-#if defined(Q_WS_X11)
- x->parentWinId = 0;
- x->spont_unmapped = 0;
- x->dnd = 0;
-#endif
- x->savedFlags = 0;
-#if defined(Q_WS_QWS) && !defined(QT_NO_QWS_MANAGER)
- x->qwsManager = 0;
-#endif
- x->sharedPainter = 0;
createTLSysExtra();
#ifdef QWIDGET_EXTRA_DEBUG
- static int count = 0;
- qDebug() << "tlextra" << ++count;
+ static int count = 0;
+ qDebug() << "tlextra" << ++count;
#endif
}
}
@@ -1519,27 +1517,28 @@ void QWidgetPrivate::createExtra()
{
if (!extra) { // if not exists
extra = new QWExtra;
- extra->minw = extra->minh = 0;
- extra->maxw = extra->maxh = QWIDGETSIZE_MAX;
+ extra->glContext = 0;
+ extra->topextra = 0;
+ extra->proxyWidget = 0;
+#ifndef QT_NO_CURSOR
+ extra->curs = 0;
+#endif
+ extra->minw = 0;
+ extra->minh = 0;
+ extra->maxw = QWIDGETSIZE_MAX;
+ extra->maxh = QWIDGETSIZE_MAX;
+ extra->customDpiX = 0;
+ extra->customDpiY = 0;
extra->explicitMinSize = 0;
extra->explicitMaxSize = 0;
extra->autoFillBackground = 0;
extra->nativeChildrenForced = 0;
extra->inRenderWithPainter = 0;
extra->hasMask = 0;
-#ifndef QT_NO_CURSOR
- extra->curs = 0;
-#endif
- extra->style = 0;
- extra->topextra = 0;
- extra->proxyWidget = 0;
- extra->glContext = 0;
- extra->customDpiX = 0;
- extra->customDpiY = 0;
createSysExtra();
#ifdef QWIDGET_EXTRA_DEBUG
- static int count = 0;
- qDebug() << "extra" << ++count;
+ static int count = 0;
+ qDebug() << "extra" << ++count;
#endif
}
}
@@ -1580,45 +1579,6 @@ void QWidgetPrivate::deleteExtra()
}
/*
- Returns true if the background is inherited; otherwise returns
- false.
-
- Mainly used in the paintOnScreen case.
-*/
-
-bool QWidgetPrivate::isBackgroundInherited() const
-{
- Q_Q(const QWidget);
-
- // windows do not inherit their background
- if (q->isWindow() || q->windowType() == Qt::SubWindow)
- return false;
-
- if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
- return false;
-
- const QPalette &pal = q->palette();
- QPalette::ColorRole bg = q->backgroundRole();
- QBrush brush = pal.brush(bg);
-
- // non opaque brushes leaves us no choice, we must inherit
- if (!q->autoFillBackground() || !brush.isOpaque())
- return true;
-
- if (brush.style() == Qt::SolidPattern) {
- // the background is just a solid color. If there is no
- // propagated contents, then we claim as performance
- // optimization that it was not inheritet. This is the normal
- // case in standard Windows or Motif style.
- const QWidget *w = q->parentWidget();
- if (!w->d_func()->isBackgroundInherited())
- return false;
- }
-
- return true;
-}
-
-/*
Returns true if there are widgets above this which overlap with
\a rect, which is in parent's coordinate system (same as crect).
*/
@@ -1964,24 +1924,6 @@ void QWidgetPrivate::clipToEffectiveMask(QRegion &region) const
}
}
-bool QWidgetPrivate::hasBackground() const
-{
- Q_Q(const QWidget);
- if (!q->isWindow() && q->parentWidget() && q->parentWidget()->testAttribute(Qt::WA_PaintOnScreen))
- return true;
- if (q->testAttribute(Qt::WA_PaintOnScreen))
- return true;
- if (!q->testAttribute(Qt::WA_OpaquePaintEvent) && !q->testAttribute(Qt::WA_NoSystemBackground)) {
- const QPalette &pal = q->palette();
- QPalette::ColorRole bg = q->backgroundRole();
- QBrush bgBrush = pal.brush(bg);
- return (bgBrush.style() != Qt::NoBrush &&
- ((q->isWindow() || q->windowType() == Qt::SubWindow)
- || (QPalette::ColorRole(bg_role) != QPalette::NoRole || (pal.resolve() & (1<<bg)))));
- }
- return false;
-}
-
bool QWidgetPrivate::paintOnScreen() const
{
#if defined(Q_WS_QWS)
@@ -2170,8 +2112,8 @@ void QWidgetPrivate::deactivateWidgetCleanup()
{
Q_Q(QWidget);
// If this was the active application window, reset it
- if (qApp->activeWindow() == q)
- qApp->setActiveWindow(0);
+ if (QApplication::activeWindow() == q)
+ QApplication::setActiveWindow(0);
// If the is the active mouse press widget, reset it
if (q == qt_button_down)
qt_button_down = 0;
@@ -2372,7 +2314,7 @@ QStyle *QWidget::style() const
if (d->extra && d->extra->style)
return d->extra->style;
- return qApp->style();
+ return QApplication::style();
}
/*!
@@ -3048,10 +2990,15 @@ void QWidgetPrivate::setEnabled_helper(bool enable)
#if defined(Q_WS_MAC)
setEnabled_helper_sys(enable);
#endif
-#if defined (Q_WS_WIN)
- if (q->hasFocus())
- QInputContextPrivate::updateImeStatus(q, true);
-#endif
+ if (q->testAttribute(Qt::WA_InputMethodEnabled) && q->hasFocus()) {
+ QInputContext *qic = inputContext();
+ if (enable) {
+ qic->setFocusWidget(q);
+ } else {
+ qic->reset();
+ qic->setFocusWidget(0);
+ }
+ }
QEvent e(QEvent::EnabledChange);
QApplication::sendEvent(q, &e);
#ifdef QT3_SUPPORT
@@ -4288,7 +4235,7 @@ const QPalette &QWidget::palette() const
if (!isEnabled()) {
data->pal.setCurrentColorGroup(QPalette::Disabled);
} else if ((!isVisible() || isActiveWindow())
-#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_OS_WIN) && !defined(Q_WS_WINCE)
&& !QApplicationPrivate::isBlockedByModal(const_cast<QWidget *>(this))
#endif
) {
@@ -4876,7 +4823,7 @@ void QWidget::render(QPainter *painter, const QPoint &targetOffset,
}
const qreal opacity = painter->opacity();
- if (qFuzzyCompare(opacity + 1, qreal(1.0)))
+ if (qFuzzyIsNull(opacity))
return; // Fully transparent.
Q_D(QWidget);
@@ -5131,7 +5078,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
QPoint scrollAreaOffset;
#ifndef QT_NO_SCROLLAREA
- QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(q->parent());
+ QAbstractScrollArea *scrollArea = qobject_cast<QAbstractScrollArea *>(parent);
if (scrollArea && scrollArea->viewport() == q) {
QObjectData *scrollPrivate = static_cast<QWidget *>(scrollArea)->d_ptr.data();
QAbstractScrollAreaPrivate *priv = static_cast<QAbstractScrollAreaPrivate *>(scrollPrivate);
@@ -5374,7 +5321,7 @@ static QString constructWindowTitleFromFilePath(const QString &filePath)
#ifndef Q_WS_MAC
QString appName = QApplication::applicationName();
if (!appName.isEmpty())
- windowTitle += QLatin1String(" ") + QChar(0x2014) + QLatin1String(" ") + appName;
+ windowTitle += QLatin1Char(' ') + QChar(0x2014) + QLatin1Char(' ') + appName;
#endif
return windowTitle;
}
@@ -5438,7 +5385,7 @@ QString qt_setWindowTitle_helperHelper(const QString &title, const QWidget *widg
&& widget->style()->styleHint(QStyle::SH_TitleBar_ModifyNotification, 0, widget))
cap.replace(lastIndex, 3, QWidget::tr("*"));
else
- cap.replace(lastIndex, 3, QLatin1String(""));
+ cap.remove(lastIndex, 3);
}
index = cap.indexOf(placeHolder, index);
@@ -5510,7 +5457,7 @@ QIcon QWidget::windowIcon() const
return *d->extra->topextra->icon;
w = w->parentWidget();
}
- return qApp->windowIcon();
+ return QApplication::windowIcon();
}
void QWidgetPrivate::setWindowIcon_helper()
@@ -5773,8 +5720,8 @@ bool QWidget::hasFocus() const
called from focusOutEvent() or focusInEvent(), you may get an
infinite recursion.
- \sa hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
- setFocusPolicy(), QApplication::focusWidget(), grabKeyboard(),
+ \sa focus(), hasFocus(), clearFocus(), focusInEvent(), focusOutEvent(),
+ setFocusPolicy(), focusWidget(), QApplication::focusWidget(), grabKeyboard(),
grabMouse(), {Keyboard Focus}
*/
@@ -5996,6 +5943,8 @@ QWidget *QWidget::focusWidget() const
/*!
Returns the next widget in this widget's focus chain.
+
+ \sa previousInFocusChain()
*/
QWidget *QWidget::nextInFocusChain() const
{
@@ -6003,6 +5952,18 @@ QWidget *QWidget::nextInFocusChain() const
}
/*!
+ Returns the previous widget in this widget's focus chain.
+
+ \sa nextInFocusChain()
+
+ \since 4.6
+*/
+QWidget *QWidget::previousInFocusChain() const
+{
+ return const_cast<QWidget *>(d_func()->focus_prev);
+}
+
+/*!
\property QWidget::isActiveWindow
\brief whether this widget's window is the active window
@@ -6020,7 +5981,7 @@ QWidget *QWidget::nextInFocusChain() const
bool QWidget::isActiveWindow() const
{
QWidget *tlw = window();
- if(tlw == qApp->activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
+ if(tlw == QApplication::activeWindow() || (isVisible() && (tlw->windowType() == Qt::Popup)))
return true;
#ifndef QT_NO_GRAPHICSVIEW
@@ -6041,7 +6002,7 @@ bool QWidget::isActiveWindow() const
!tlw->isModal() &&
(!tlw->parentWidget() || tlw->parentWidget()->isActiveWindow()))
return true;
- QWidget *w = qApp->activeWindow();
+ QWidget *w = QApplication::activeWindow();
while(w && tlw->windowType() == Qt::Tool &&
!w->isModal() && w->parentWidget()) {
w = w->parentWidget()->window();
@@ -6240,14 +6201,6 @@ int QWidgetPrivate::pointToRect(const QPoint &p, const QRect &r)
return dx + dy;
}
-QRect QWidgetPrivate::fromOrToLayoutItemRect(const QRect &rect, int sign) const
-{
- QRect r = rect;
- r.adjust(-sign * leftLayoutItemMargin, -sign * topLayoutItemMargin,
- +sign * rightLayoutItemMargin, +sign * bottomLayoutItemMargin);
- return r;
-}
-
/*!
\property QWidget::frameSize
\brief the size of the widget including any window frame
@@ -7219,7 +7172,7 @@ bool QWidgetPrivate::close_helper(CloseMode mode)
#ifdef QT3_SUPPORT
if (isMain)
- qApp->quit();
+ QApplication::quit();
#endif
// Attempt to close the application only if this widget has the
// WA_QuitOnClose flag set set and has a non-visible parent
@@ -7402,10 +7355,10 @@ QSize QWidgetPrivate::adjustedSize() const
if (q->isWindow()) {
Qt::Orientations exp;
- if (QLayout *l = q->layout()) {
- if (l->hasHeightForWidth())
- s.setHeight(l->totalHeightForWidth(s.width()));
- exp = l->expandingDirections();
+ if (layout) {
+ if (layout->hasHeightForWidth())
+ s.setHeight(layout->totalHeightForWidth(s.width()));
+ exp = layout->expandingDirections();
} else
{
if (q->sizePolicy().hasHeightForWidth())
@@ -7421,7 +7374,7 @@ QSize QWidgetPrivate::adjustedSize() const
#else // all others
QRect screen = QApplication::desktop()->screenGeometry(q->pos());
#endif
-#if defined (Q_OS_WINCE) || defined (Q_OS_SYMBIAN)
+#if defined (Q_WS_WINCE) || defined (Q_OS_SYMBIAN)
s.setWidth(qMin(s.width(), screen.width()));
s.setHeight(qMin(s.height(), screen.height()));
#else
@@ -7729,17 +7682,11 @@ bool QWidget::event(QEvent *event)
}
break;
case QEvent::FocusIn:
-#if defined(Q_WS_WIN)
- QInputContextPrivate::updateImeStatus(this, true);
-#endif
d->setSoftKeys_sys(softKeys());
focusInEvent((QFocusEvent*)event);
break;
case QEvent::FocusOut:
-#if defined(Q_WS_WIN)
- QInputContextPrivate::updateImeStatus(this, false);
-#endif
focusOutEvent((QFocusEvent*)event);
break;
@@ -7929,7 +7876,7 @@ bool QWidget::event(QEvent *event)
QList<QObject*> childList = d->children;
for (int i = 0; i < childList.size(); ++i) {
QObject *o = childList.at(i);
- if (o != qApp->activeModalWidget()) {
+ if (o != QApplication::activeModalWidget()) {
if (qobject_cast<QWidget *>(o) && static_cast<QWidget *>(o)->isWindow()) {
// do not forward the event to child windows,
// QApplication does this for us
@@ -8152,9 +8099,9 @@ void QWidget::mousePressEvent(QMouseEvent *event)
if ((windowType() == Qt::Popup)) {
event->accept();
QWidget* w;
- while ((w = qApp->activePopupWidget()) && w != this){
+ while ((w = QApplication::activePopupWidget()) && w != this){
w->close();
- if (qApp->activePopupWidget() == w) // widget does not want to dissappear
+ if (QApplication::activePopupWidget() == w) // widget does not want to dissappear
w->hide(); // hide at least
}
if (!rect().contains(event->pos())){
@@ -9392,11 +9339,12 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
d->resolveLayoutDirection();
d->resolveLocale();
- // Note: GL widgets under Windows will always need a ParentChange
- // event to handle recreation/rebinding of the GL context, hence
- // the (f & Qt::MSWindowsOwnDC) clause
+ // Note: GL widgets under WGL or EGL will always need a ParentChange
+ // event to handle recreation/rebinding of the GL context, hence the
+ // (f & Qt::MSWindowsOwnDC) clause (which is set on QGLWidgets on all
+ // platforms).
if (newParent
-#ifdef Q_WS_WIN
+#if defined(Q_WS_WIN) || defined(QT_OPENGL_ES)
|| (f & Qt::MSWindowsOwnDC)
#endif
) {
@@ -9942,27 +9890,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
QEvent e(QEvent::MouseTrackingChange);
QApplication::sendEvent(this, &e);
break; }
-#if !defined(QT_NO_DIRECT3D) && defined(Q_WS_WIN)
- case Qt::WA_MSWindowsUseDirect3D:
- if (!qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)) {
- if (on) {
- if (!d->extra)
- d->createExtra();
- d->extra->had_auto_fill_bg = d->extra->autoFillBackground;
- d->extra->had_no_system_bg = testAttribute(Qt::WA_NoSystemBackground);
- d->extra->had_paint_on_screen = testAttribute(Qt::WA_PaintOnScreen);
- // enforce the opaque widget state D3D needs
- d->extra->autoFillBackground = true;
- setAttribute(Qt::WA_PaintOnScreen);
- setAttribute(Qt::WA_NoSystemBackground);
- } else if (d->extra) {
- d->extra->autoFillBackground = d->extra->had_auto_fill_bg;
- setAttribute(Qt::WA_PaintOnScreen, d->extra->had_paint_on_screen);
- setAttribute(Qt::WA_NoSystemBackground, d->extra->had_no_system_bg);
- }
- }
- break;
-#endif
case Qt::WA_NativeWindow: {
QInputContext *ic = 0;
if (on && !internalWinId() && testAttribute(Qt::WA_InputMethodEnabled) && hasFocus()) {
@@ -9974,7 +9901,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
parentWidget()->d_func()->enforceNativeChildren();
if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
d->createWinId();
- if (ic)
+ if (ic && isEnabled())
ic->setFocusWidget(this);
break;
}
@@ -10005,10 +9932,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
#endif
break;
case Qt::WA_InputMethodEnabled: {
-#if defined(Q_WS_WIN) || (defined(Q_WS_QWS) && !defined(QT_NO_QWS_INPUTMETHODS))
- if (hasFocus())
- QInputContextPrivate::updateImeStatus(this, true);
-#endif
QInputContext *ic = d->ic;
if (!ic) {
// implicitly create input context only if we have a focus
@@ -10016,7 +9939,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
ic = d->inputContext();
}
if (ic) {
- if (on && hasFocus() && ic->focusWidget() != this) {
+ if (on && hasFocus() && ic->focusWidget() != this && isEnabled()) {
ic->setFocusWidget(this);
} else if (!on && ic->focusWidget() == this) {
ic->reset();
diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h
index 1edd466..cd56149 100644
--- a/src/gui/kernel/qwidget.h
+++ b/src/gui/kernel/qwidget.h
@@ -130,7 +130,7 @@ public:
int alloc_region_index;
// int alloc_region_revision;
#endif
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
uint window_state_internal : 4;
#endif
QRect wrect;
@@ -470,7 +470,7 @@ public Q_SLOTS:
virtual void setVisible(bool visible);
inline void setHidden(bool hidden) { setVisible(!hidden); }
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
inline void show() { setVisible(true); }
#else
void show();
@@ -540,6 +540,7 @@ public:
QWidget *focusWidget() const;
QWidget *nextInFocusChain() const;
+ QWidget *previousInFocusChain() const;
// drag and drop
bool acceptDrops() const;
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index e2197c6..63105b3 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -390,21 +390,15 @@ QWidget *qt_mac_find_window(OSWindowRef window)
inline static void qt_mac_set_fullscreen_mode(bool b)
{
- extern bool qt_mac_app_fullscreen; //qapplication_mac.cpp
+ extern bool qt_mac_app_fullscreen; //qapplication_mac.mm
if(qt_mac_app_fullscreen == b)
return;
qt_mac_app_fullscreen = b;
-#if QT_MAC_USE_COCOA
- if(b)
- SetSystemUIMode(kUIModeAllHidden, kUIOptionAutoShowMenuBar);
- else
+ if (b) {
+ SetSystemUIMode(kUIModeAllSuppressed, 0);
+ } else {
SetSystemUIMode(kUIModeNormal, 0);
-#else
- if(b)
- HideMenuBar();
- else
- ShowMenuBar();
-#endif
+ }
}
Q_GUI_EXPORT OSViewRef qt_mac_nativeview_for(const QWidget *w)
@@ -734,6 +728,7 @@ static OSWindowRef qt_mac_create_window(QWidget *, WindowClass wclass, WindowAtt
static EventTypeSpec window_events[] = {
{ kEventClassWindow, kEventWindowClose },
{ kEventClassWindow, kEventWindowExpanded },
+ { kEventClassWindow, kEventWindowHidden },
{ kEventClassWindow, kEventWindowZoomed },
{ kEventClassWindow, kEventWindowCollapsed },
{ kEventClassWindow, kEventWindowToolbarSwitchMode },
@@ -993,6 +988,19 @@ OSStatus QWidgetPrivate::qt_window_event(EventHandlerCallRef er, EventRef event,
}
}
}
+ } else if (ekind == kEventWindowHidden) {
+ // Make sure that we also hide any visible sheets on our window.
+ // Cocoa does the right thing for us.
+ const QObjectList children = widget->children();
+ const int childCount = children.count();
+ for (int i = 0; i < childCount; ++i) {
+ QObject *obj = children.at(i);
+ if (obj->isWidgetType()) {
+ QWidget *widget = static_cast<QWidget *>(obj);
+ if (qt_mac_is_macsheet(widget) && widget->isVisible())
+ widget->hide();
+ }
+ }
} else {
handled_event = false;
}
@@ -1595,24 +1603,6 @@ bool QWidgetPrivate::qt_create_root_win()
return true;
}
-bool QWidgetPrivate::qt_recreate_root_win()
-{
- if(!qt_root_win) //sanity check
- return false;
- //store old
- OSWindowRef old_root_win = qt_root_win;
- //recreate
- qt_root_win = 0;
- qt_create_root_win();
- //cleanup old window
-#ifdef QT_MAC_USE_COCOA
- [old_root_win release];
-#else
- CFRelease(old_root_win);
-#endif
- return true;
-}
-
bool QWidgetPrivate::qt_widget_rgn(QWidget *widget, short wcode, RgnHandle rgn, bool force = false)
{
bool ret = false;
@@ -4440,11 +4430,13 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+ extra->topextra->resizer = 0;
+ extra->topextra->isSetGeometry = 0;
+ extra->topextra->isMove = 0;
+ extra->topextra->wattr = 0;
extra->topextra->wclass = 0;
extra->topextra->group = 0;
extra->topextra->windowIcon = 0;
- extra->topextra->resizer = 0;
- extra->topextra->isSetGeometry = 0;
extra->topextra->savedWindowAttributesFromMaximized = 0;
}
@@ -4519,14 +4511,6 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
#endif
}
-extern "C" {
- typedef struct CGSConnection *CGSConnectionRef;
- typedef struct CGSWindow *CGSWindowRef;
- extern OSStatus CGSSetWindowAlpha(CGSConnectionRef, CGSWindowRef, float);
- extern CGSWindowRef GetNativeWindowFromWindowRef(WindowRef);
- extern CGSConnectionRef _CGSDefaultConnection();
-}
-
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
{
Q_Q(QWidget);
@@ -4539,12 +4523,11 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
if (!q->testAttribute(Qt::WA_WState_Created))
return;
-#if QT_MAC_USE_COCOA
OSWindowRef oswindow = qt_mac_window_for(q);
+#if QT_MAC_USE_COCOA
[oswindow setAlphaValue:level];
#else
- CGSSetWindowAlpha(_CGSDefaultConnection(),
- GetNativeWindowFromWindowRef(qt_mac_window_for(q)), level);
+ SetWindowAlpha(oswindow, level);
#endif
}
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 084439c..527e331 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -109,97 +109,101 @@ class QWidgetItemV2;
class QStyle;
struct QTLWExtra {
+ // *************************** Cross-platform variables *****************************
+
+ // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
+ QIcon *icon; // widget icon
+ QPixmap *iconPixmap;
+ QWidgetBackingStore *backingStore;
+ QWindowSurface *windowSurface;
+ QPainter *sharedPainter;
+
+ // Implicit pointers (shared_null).
QString caption; // widget caption
QString iconText; // widget icon text
QString role; // widget role
QString filePath; // widget file path
- QIcon *icon; // widget icon
- QPixmap *iconPixmap;
+
+ // Other variables.
short incw, inch; // size increments
+ short basew, baseh; // base sizes
// frame strut, don't use these directly, use QWidgetPrivate::frameStrut() instead.
QRect frameStrut;
+ QRect normalGeometry; // used by showMin/maximized/FullScreen
+ Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
+
+ // *************************** Cross-platform bit fields ****************************
uint opacity : 8;
uint posFromMove : 1;
uint sizeAdjusted : 1;
uint inTopLevelResize : 1;
uint inRepaint : 1;
- QWidgetBackingStore *backingStore;
-#if defined(Q_WS_WIN)
- ulong savedFlags; // Save window flags while showing fullscreen
- uint embedded : 1; // window is embedded in another application
-#else
- Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen
-#endif
- short basew, baseh; // base sizes
-#if defined(Q_WS_X11)
- WId parentWinId; // parent window Id (valid after reparenting)
- uint embedded : 1; // window is embedded in another Qt application
+ uint embedded : 1;
+
+ // *************************** Platform specific values (bit fields first) **********
+#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
uint spont_unmapped: 1; // window was spontaneously unmapped
uint dnd : 1; // DND properties installed
uint validWMState : 1; // is WM_STATE valid?
uint waitingForMapNotify : 1; // show() has been called, haven't got the MapNotify yet
+ WId parentWinId; // parent window Id (valid after reparenting)
WId userTimeWindow; // window id that contains user-time timestamp when WM supports a _NET_WM_USER_TIME_WINDOW atom
QPoint fullScreenOffset;
+#ifndef QT_NO_XSYNC
+ WId syncUpdateCounter;
+ ulong syncRequestTimestamp;
+ qint32 newCounterValueHi;
+ quint32 newCounterValueLo;
#endif
-#if defined(Q_WS_MAC)
+#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ HICON winIconBig; // internal big Windows icon
+ HICON winIconSmall; // internal small Windows icon
+#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
+ uint resizer : 4;
+ uint isSetGeometry : 1;
+ uint isMove : 1;
quint32 wattr;
quint32 wclass;
WindowGroupRef group;
IconRef windowIcon; // the current window icon, if set with setWindowIcon_sys.
quint32 savedWindowAttributesFromMaximized; // Saved attributes from when the calling updateMaximizeButton_sys()
- uint resizer : 4;
- uint isSetGeometry : 1;
- uint isMove : 1;
- uint embedded : 1;
+#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
+#ifndef QT_NO_QWS_MANAGER
+ QWSManager *qwsManager;
#endif
-#if defined(Q_WS_S60)
+#elif defined(Q_WS_S60) // <--------------------------------------------------------- SYMBIAN
uint activated : 1; // RWindowBase::Activated has been called
RDrawableWindow *rwindow;
#endif
-#if defined(Q_WS_QWS) && !defined (QT_NO_QWS_MANAGER)
- QWSManager *qwsManager;
-#endif
-#if defined(Q_WS_WIN)
- HICON winIconBig; // internal big Windows icon
- HICON winIconSmall; // internal small Windows icon
-#endif
- QRect normalGeometry; // used by showMin/maximized/FullScreen
- QWindowSurface *windowSurface;
- QPainter *sharedPainter;
};
struct QWExtra {
- qint32 minw, minh; // minimum size
- qint32 maxw, maxh; // maximum size
- QPointer<QWidget> focus_proxy;
-#ifndef QT_NO_CURSOR
- QCursor *curs;
-#endif
+ // *************************** Cross-platform variables *****************************
+
+ // Regular pointers (keep them together to avoid gaps on 64 bits architectures).
+ void *glContext; // if the widget is hijacked by QGLWindowSurface
QTLWExtra *topextra; // only useful for TLWs
QGraphicsProxyWidget *proxyWidget; // if the widget is embedded
- void *glContext; // if the widget is hijacked by QGLWindowSurface
-#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
- QOleDropTarget *dropTarget; // drop target
- QList<QPointer<QWidget> > oleDropWidgets;
-#endif
-#if defined(Q_WS_X11)
- WId xDndProxy; // XDND forwarding to embedded windows
+#ifndef QT_NO_CURSOR
+ QCursor *curs;
#endif
+ QPointer<QStyle> style;
+ QPointer<QWidget> focus_proxy;
+
+ // Implicit pointers (shared_empty/shared_null).
QRegion mask; // widget mask
+ QString styleSheet;
+
+ // Other variables.
+ qint32 minw;
+ qint32 minh; // minimum size
+ qint32 maxw;
+ qint32 maxh; // maximum size
+ quint16 customDpiX;
+ quint16 customDpiY;
QSize staticContentsSize;
-//bit flags at the end to improve packing
-#if defined(Q_WS_WIN)
- uint shown_mode : 8; // widget show mode
-#ifndef QT_NO_DIRECT3D
- uint had_paint_on_screen : 1;
- uint had_no_system_bg : 1;
- uint had_auto_fill_bg : 1;
-#endif
-#endif
-#if defined(Q_WS_X11)
- uint compress_events : 1;
-#endif
+ // *************************** Cross-platform bit fields ****************************
uint explicitMinSize : 2;
uint explicitMaxSize : 2;
uint autoFillBackground : 1;
@@ -207,16 +211,22 @@ struct QWExtra {
uint inRenderWithPainter : 1;
uint hasMask : 1;
- QPointer<QStyle> style;
- QString styleSheet;
-
- quint16 customDpiX;
- quint16 customDpiY;
-#if defined(Q_WS_MAC) && defined(QT_MAC_USE_COCOA)
+ // *************************** Platform specific values (bit fields first) **********
+#if defined(Q_WS_WIN) // <----------------------------------------------------------- WIN
+#ifndef QT_NO_DRAGANDDROP
+ QOleDropTarget *dropTarget; // drop target
+ QList<QPointer<QWidget> > oleDropWidgets;
+#endif
+#elif defined(Q_WS_X11) // <--------------------------------------------------------- X11
+ uint compress_events : 1;
+ WId xDndProxy; // XDND forwarding to embedded windows
+#elif defined(Q_WS_MAC) // <------------------------------------------------------ MAC
+#ifdef QT_MAC_USE_COCOA
// Cocoa Mask stuff
QImage maskBits;
CGImageRef imageMask;
#endif
+#endif
};
class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
@@ -224,6 +234,24 @@ class Q_GUI_EXPORT QWidgetPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QWidget)
public:
+ // *************************** Cross-platform ***************************************
+ enum DrawWidgetFlags {
+ DrawAsRoot = 0x01,
+ DrawPaintOnScreen = 0x02,
+ DrawRecursive = 0x04,
+ DrawInvisible = 0x08,
+ DontSubtractOpaqueChildren = 0x10,
+ DontSetCompositionMode = 0x20,
+ DontDrawOpaqueChildren = 0x40
+ };
+
+ enum CloseMode {
+ CloseNoEvent,
+ CloseWithEvent,
+ CloseWithSpontaneousEvent
+ };
+
+ // Functions.
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
~QWidgetPrivate();
@@ -234,10 +262,6 @@ public:
QPainter *sharedPainter() const;
void setSharedPainter(QPainter *painter);
QWidgetBackingStore *maybeBackingStore() const;
-#ifdef Q_WS_QWS
- void setMaxWindowState_helper();
- void setFullScreenSize_helper();
-#endif
void init(QWidget *desktopWidget, Qt::WindowFlags f);
void create_sys(WId window, bool initializeWindow, bool destroyOldWindow);
void createRecursively();
@@ -258,24 +282,6 @@ public:
QPalette naturalWidgetPalette(uint inheritedMask) const;
void setMask_sys(const QRegion &);
-#ifdef Q_WS_WIN
- bool shouldShowMaximizeButton();
- void winUpdateIsOpaque();
-#endif
-
-#ifdef Q_WS_MAC
- void macUpdateSizeAttribute();
- void macUpdateHideOnSuspend();
- void macUpdateOpaqueSizeGrip();
- void macUpdateIgnoreMouseEvents();
- void macUpdateMetalAttribute();
- void macUpdateIsOpaque();
- void setEnabled_helper_sys(bool enable);
- bool isRealWindow() const;
- void adjustWithinMaxAndMinSize(int &w, int &h);
- void applyMaxAndMinSizeOnWindow();
-#endif
-
#ifdef Q_WS_S60
void s60UpdateIsOpaque();
#endif
@@ -304,20 +310,9 @@ public:
void setStyle_helper(QStyle *newStyle, bool propagate, bool metalHack = false);
void inheritStyle();
- bool isBackgroundInherited() const;
-
void setUpdatesEnabled_helper(bool );
void paintBackground(QPainter *, const QRegion &, const QPoint & = QPoint(), int flags = DrawAsRoot) const;
- enum DrawWidgetFlags {
- DrawAsRoot = 0x01,
- DrawPaintOnScreen = 0x02,
- DrawRecursive = 0x04,
- DrawInvisible = 0x08,
- DontSubtractOpaqueChildren = 0x10,
- DontSetCompositionMode = 0x20,
- DontDrawOpaqueChildren = 0x40
- };
bool isAboutToShow() const;
QRegion prepareToRender(const QRegion &region, QWidget::RenderFlags renderFlags);
void render_helper(QPainter *painter, const QPoint &targetOffset, const QRegion &sourceRegion,
@@ -340,10 +335,6 @@ public:
QWindowSurface *createDefaultWindowSurface();
QWindowSurface *createDefaultWindowSurface_sys();
void repaint_sys(const QRegion &rgn);
-#ifdef Q_WS_MAC
- void update_sys(const QRect &rect);
- void update_sys(const QRegion &rgn);
-#endif
QRect clipRect() const;
QRegion clipRegion() const;
@@ -354,42 +345,20 @@ public:
void updateIsOpaque();
void setOpaque(bool opaque);
void updateIsTranslucent();
- bool hasBackground() const;
bool paintOnScreen() const;
QRegion getOpaqueRegion() const;
const QRegion &getOpaqueChildren() const;
void setDirtyOpaqueRegion();
- QRegion opaqueChildren;
-
- enum CloseMode {
- CloseNoEvent,
- CloseWithEvent,
- CloseWithSpontaneousEvent
- };
bool close_helper(CloseMode mode);
- bool compositeEvent(QEvent *e);
void setWindowIcon_helper();
void setWindowIcon_sys(bool forceReset = false);
void setWindowOpacity_sys(qreal opacity);
-
void adjustQuitOnCloseAttribute();
-#if defined(Q_WS_X11)
- void setWindowRole();
- void sendStartupMessage(const char *message) const;
- void setNetWmWindowTypes();
- void x11UpdateIsOpaque();
-#endif
-
-#if defined (Q_WS_WIN) || defined (Q_WS_S60)
- void reparentChildren();
-#endif
-
void scrollChildren(int dx, int dy);
-
void moveRect(const QRect &, int dx, int dy);
void scrollRect(const QRect &, int dx, int dy);
void invalidateBuffer_resizeHelper(const QPoint &oldPos, const QSize &oldSize);
@@ -403,7 +372,6 @@ public:
void reparentFocusWidgets(QWidget *oldtlw);
static int pointToRect(const QPoint &p, const QRect &r);
- QRect fromOrToLayoutItemRect(const QRect &rect, int sign) const;
void setWinId(WId);
void showChildren(bool spontaneous);
@@ -413,9 +381,6 @@ public:
void scroll_sys(int dx, int dy, const QRect &r);
void deactivateWidgetCleanup();
void setGeometry_sys(int, int, int, int, bool);
-#ifdef Q_WS_MAC
- void setGeometry_sys_helper(int, int, int, int, bool);
-#endif
void sendPendingMoveAndResizeEvents(bool recursive = false, bool disableUpdates = false);
void activateChildLayoutsRecursively();
void show_recursive();
@@ -427,10 +392,6 @@ public:
void setEnabled_helper(bool);
void registerDropSite(bool);
-#if defined(Q_WS_WIN) && !defined(QT_NO_DRAGANDDROP)
- QOleDropTarget *registerOleDnd(QWidget *widget);
- void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
-#endif
static void adjustFlags(Qt::WindowFlags &flags, QWidget *w = 0);
void updateFrameStrut();
@@ -440,32 +401,11 @@ public:
void setWindowIconText_helper(const QString &cap);
void setWindowTitle_sys(const QString &cap);
-#ifdef Q_OS_WIN
- void grabMouseWhileInWindow();
-#endif
-
#ifndef QT_NO_CURSOR
void setCursor_sys(const QCursor &cursor);
void unsetCursor_sys();
#endif
-#ifdef Q_WS_MAC
- void setWindowModified_sys(bool b);
- void updateMaximizeButton_sys();
- void setWindowFilePath_sys(const QString &filePath);
- void createWindow_sys();
- void recreateMacWindow();
-#ifndef QT_MAC_USE_COCOA
- void initWindowPtr();
- void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
-#else
- void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
- void syncCocoaMask();
- void finishCocoaMaskSetup();
-#endif
- void determineWindowClass();
- void transferChildren();
-#endif
void setWindowTitle_helper(const QString &cap);
void setWindowFilePath_helper(const QString &filePath);
@@ -481,60 +421,91 @@ public:
QInputContext *inputContext() const;
-#if defined(Q_WS_QWS)
- void moveSurface(QWindowSurface *surface, const QPoint &offset);
+ void setModal_sys();
- QRegion localRequestedRegion() const;
- QRegion localAllocatedRegion() const;
+ inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
+ {
+ Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
+ redirectDev = replacement;
+ redirectOffset = offset;
+ }
- void blitToScreen(const QRegion &globalrgn);
-#ifndef QT_NO_CURSOR
- void updateCursor() const;
-#endif
+ inline QPaintDevice *redirected(QPoint *offset) const
+ {
+ if (offset)
+ *offset = redirectDev ? redirectOffset : QPoint();
+ return redirectDev;
+ }
- QScreen* getScreen() const;
+ inline void restoreRedirected()
+ { redirectDev = 0; }
- friend class QWSManager;
- friend class QWSManagerPrivate;
- friend class QDecoration;
-#endif
+ inline void enforceNativeChildren()
+ {
+ if (!extra)
+ createExtra();
- static int instanceCounter; // Current number of widget instances
- static int maxInstances; // Maximum number of widget instances
+ if (extra->nativeChildrenForced)
+ return;
+ extra->nativeChildrenForced = 1;
-#ifdef QT_KEYPAD_NAVIGATION
- static QPointer<QWidget> editingWidget;
-#endif
+ for (int i = 0; i < children.size(); ++i) {
+ if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
+ child->setAttribute(Qt::WA_NativeWindow);
+ }
+ }
- QWidgetData data;
+ inline bool nativeChildrenForced() const
+ {
+ return extra ? extra->nativeChildrenForced : false;
+ }
+
+ QSize adjustedSize() const;
+
+#ifndef Q_WS_QWS // Almost cross-platform :-)
+ void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());
+
+ inline QPoint mapToWS(const QPoint &p) const
+ { return p - data.wrect.topLeft(); }
+
+ inline QPoint mapFromWS(const QPoint &p) const
+ { return p + data.wrect.topLeft(); }
+
+ inline QRect mapToWS(const QRect &r) const
+ { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; }
+ inline QRect mapFromWS(const QRect &r) const
+ { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+#endif
+
+ // Variables.
+ // Regular pointers (keep them together to avoid gaps on 64 bit architectures).
QWExtra *extra;
QWidget *focus_next;
QWidget *focus_prev;
QWidget *focus_child;
-#ifndef QT_NO_ACTION
- QList<QAction*> actions;
-#endif
QList<QAction*> softKeys;
QLayout *layout;
+ QRegion *needsFlush;
+ QPaintDevice *redirectDev;
QWidgetItemV2 *widgetItem;
-#if !defined(QT_NO_IM)
- QPointer<QInputContext> ic;
-#endif
+ QPaintEngine *extraPaintEngine;
+ mutable const QMetaObject *polished;
// All widgets are initially added into the uncreatedWidgets set. Once
// they receive a window id they are removed and added to the mapper
static QWidgetMapper *mapper;
static QWidgetSet *uncreatedWidgets;
+#if !defined(QT_NO_IM)
+ QPointer<QInputContext> ic;
+ Qt::InputMethodHints imHints;
+#endif
+#ifdef QT_KEYPAD_NAVIGATION
+ static QPointer<QWidget> editingWidget;
+#endif
- short leftmargin, topmargin, rightmargin, bottommargin;
-
- signed char leftLayoutItemMargin;
- signed char topLayoutItemMargin;
- signed char rightLayoutItemMargin;
- signed char bottomLayoutItemMargin;
-
- // ### TODO: reorganize private/extra/topextra to save memory
- QPointer<QWidget> compositeChildGrab;
+ // Implicit pointers (shared_null/shared_empty).
+ QRegion opaqueChildren;
+ QRegion dirty;
#ifndef QT_NO_TOOLTIP
QString toolTip;
#endif
@@ -544,14 +515,37 @@ public:
#ifndef QT_NO_WHATSTHIS
QString whatsThis;
#endif
- QString accessibleName, accessibleDescription;
+#ifndef QT_NO_ACCESSIBILITY
+ QString accessibleName;
+ QString accessibleDescription;
+#endif
+ // Other variables.
+ uint inheritedFontResolveMask;
+ uint inheritedPaletteResolveMask;
+ short leftmargin;
+ short topmargin;
+ short rightmargin;
+ short bottommargin;
+ signed char leftLayoutItemMargin;
+ signed char topLayoutItemMargin;
+ signed char rightLayoutItemMargin;
+ signed char bottomLayoutItemMargin;
+ static int instanceCounter; // Current number of widget instances
+ static int maxInstances; // Maximum number of widget instances
+ Qt::HANDLE hd;
+ QWidgetData data;
+ QSizePolicy size_policy;
+ QLocale locale;
+ QPoint redirectOffset;
+#ifndef QT_NO_ACTION
+ QList<QAction*> actions;
+#endif
+
+ // Bit fields.
+ uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
QPalette::ColorRole fg_role : 8;
QPalette::ColorRole bg_role : 8;
- uint high_attributes[3]; // the low ones are in QWidget::widget_attributes
- Qt::HANDLE hd;
- QRegion dirty;
- QRegion *needsFlush;
uint dirtyOpaqueChildren : 1;
uint isOpaque : 1;
uint inDirtyList : 1;
@@ -559,35 +553,33 @@ public:
uint isMoved : 1;
uint usesDoubleBufferedGLContext : 1;
-#ifdef Q_WS_WIN
- uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
-#endif
-
- uint inheritedFontResolveMask;
- uint inheritedPaletteResolveMask;
-#if defined(Q_WS_X11)
+ // *************************** Platform specific ************************************
+#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
QX11Info xinfo;
Qt::HANDLE picture;
+ static QWidget *mouseGrabber;
+ static QWidget *keyboardGrabber;
+
+ void setWindowRole();
+ void sendStartupMessage(const char *message) const;
+ void setNetWmWindowTypes();
+ void x11UpdateIsOpaque();
+ bool isBackgroundInherited() const;
+#elif defined(Q_WS_WIN) // <--------------------------------------------------------- WIN
+ uint noPaintOnScreen : 1; // see qwidget_win.cpp ::paintEngine()
+
+ bool shouldShowMaximizeButton();
+ void winUpdateIsOpaque();
+ void reparentChildren();
+#ifndef QT_NO_DRAGANDDROP
+ QOleDropTarget *registerOleDnd(QWidget *widget);
+ void unregisterOleDnd(QWidget *widget, QOleDropTarget *target);
#endif
-#if defined(Q_WS_MAC)
- enum PaintChildrenOPs {
- PC_None = 0x00,
- PC_Now = 0x01,
- PC_NoPaint = 0x04,
- PC_Later = 0x10
- };
- EventHandlerRef window_event;
- bool qt_mac_dnd_event(uint, DragRef);
- void toggleDrawers(bool);
- //mac event functions
- static bool qt_create_root_win();
- static void qt_clean_root_win();
- static bool qt_recreate_root_win();
- static bool qt_mac_update_sizer(QWidget *, int up = 0);
- static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
- static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
- static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
- static bool qt_widget_shape(QWidget *, short, HIMutableShapeRef, bool);
+ void grabMouseWhileInWindow();
+#elif defined(Q_WS_MAC) // <--------------------------------------------------------- MAC
+ // This is new stuff
+ uint needWindowChange : 1;
+ uint isGLWidget : 1;
// Each wiget keeps a list of all its child and grandchild OpenGL widgets.
// This list is used to update the gl context whenever a parent and a granparent
@@ -600,97 +592,73 @@ public:
QWidget * widget;
QWidget * lastUpdateWidget;
};
- QList<GlWidgetInfo> glWidgets;
// dirtyOnWidget contains the areas in the widget that needs to be repained,
// in the same way as dirtyOnScreen does for the window. Areas are added in
// dirtyWidget_sys and cleared in the paint event. In scroll_sys we then use
// this information repaint invalid areas when widgets are scrolled.
QRegion dirtyOnWidget;
+ EventHandlerRef window_event;
+ QList<GlWidgetInfo> glWidgets;
//these are here just for code compat (HIViews)
Qt::HANDLE qd_hd;
- // This is new stuff
- uint needWindowChange : 1;
- uint isGLWidget : 1;
-#endif
-
- Qt::InputMethodHints imHints;
-
-#if defined(Q_WS_X11) || defined (Q_WS_WIN) || defined(Q_WS_MAC) || defined(Q_WS_S60)
-#ifdef Q_WS_MAC
- void setWSGeometry(bool dontShow=false, const QRect &oldRect = QRect());
+ void macUpdateSizeAttribute();
+ void macUpdateHideOnSuspend();
+ void macUpdateOpaqueSizeGrip();
+ void macUpdateIgnoreMouseEvents();
+ void macUpdateMetalAttribute();
+ void macUpdateIsOpaque();
+ void setEnabled_helper_sys(bool enable);
+ bool isRealWindow() const;
+ void adjustWithinMaxAndMinSize(int &w, int &h);
+ void applyMaxAndMinSizeOnWindow();
+ void update_sys(const QRect &rect);
+ void update_sys(const QRegion &rgn);
+ void setGeometry_sys_helper(int, int, int, int, bool);
+ void setWindowModified_sys(bool b);
+ void updateMaximizeButton_sys();
+ void setWindowFilePath_sys(const QString &filePath);
+ void createWindow_sys();
+ void recreateMacWindow();
+#ifndef QT_MAC_USE_COCOA
+ void initWindowPtr();
+ void finishCreateWindow_sys_Carbon(OSWindowRef windowRef);
#else
- void setWSGeometry(bool dontShow=false);
+ void finishCreateWindow_sys_Cocoa(void * /*NSWindow * */ windowRef);
+ void syncCocoaMask();
+ void finishCocoaMaskSetup();
#endif
+ void determineWindowClass();
+ void transferChildren();
+ bool qt_mac_dnd_event(uint, DragRef);
+ void toggleDrawers(bool);
+ //mac event functions
+ static bool qt_create_root_win();
+ static void qt_clean_root_win();
+ static bool qt_mac_update_sizer(QWidget *, int up = 0);
+ static OSStatus qt_window_event(EventHandlerCallRef er, EventRef event, void *);
+ static OSStatus qt_widget_event(EventHandlerCallRef er, EventRef event, void *);
+ static bool qt_widget_rgn(QWidget *, short, RgnHandle, bool);
+#elif defined(Q_WS_QWS) // <--------------------------------------------------------- QWS
+ void setMaxWindowState_helper();
+ void setFullScreenSize_helper();
+ void moveSurface(QWindowSurface *surface, const QPoint &offset);
+ QRegion localRequestedRegion() const;
+ QRegion localAllocatedRegion() const;
- inline QPoint mapToWS(const QPoint &p) const
- { return p - data.wrect.topLeft(); }
-
- inline QPoint mapFromWS(const QPoint &p) const
- { return p + data.wrect.topLeft(); }
-
- inline QRect mapToWS(const QRect &r) const
- { QRect rr(r); rr.translate(-data.wrect.topLeft()); return rr; }
-
- inline QRect mapFromWS(const QRect &r) const
- { QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+ friend class QWSManager;
+ friend class QWSManagerPrivate;
+ friend class QDecoration;
+#ifndef QT_NO_CURSOR
+ void updateCursor() const;
#endif
-
- QPaintEngine *extraPaintEngine;
-
- mutable const QMetaObject *polished;
-
- void setModal_sys();
- QSizePolicy size_policy;
- QLocale locale;
-
-#if defined(Q_WS_X11) || defined(Q_WS_S60)
+ QScreen* getScreen() const;
+#elif defined(Q_WS_S60) // <--------------------------------------------------------- SYMBIAN
static QWidget *mouseGrabber;
static QWidget *keyboardGrabber;
#endif
- QPaintDevice *redirectDev;
- QPoint redirectOffset;
-
- inline void setRedirected(QPaintDevice *replacement, const QPoint &offset)
- {
- Q_ASSERT(q_func()->testAttribute(Qt::WA_WState_InPaintEvent));
- redirectDev = replacement;
- redirectOffset = offset;
- }
-
- inline QPaintDevice *redirected(QPoint *offset) const
- {
- if (offset)
- *offset = redirectDev ? redirectOffset : QPoint();
- return redirectDev;
- }
-
- inline void restoreRedirected()
- { redirectDev = 0; }
-
- inline void enforceNativeChildren()
- {
- if (!extra)
- createExtra();
-
- if (extra->nativeChildrenForced)
- return;
- extra->nativeChildrenForced = 1;
-
- for (int i = 0; i < children.size(); ++i) {
- if (QWidget *child = qobject_cast<QWidget *>(children.at(i)))
- child->setAttribute(Qt::WA_NativeWindow);
- }
- }
-
- inline bool nativeChildrenForced() const
- {
- return extra ? extra->nativeChildrenForced : false;
- }
-
- QSize adjustedSize() const;
};
diff --git a/src/gui/kernel/qwidget_qws.cpp b/src/gui/kernel/qwidget_qws.cpp
index 0073d3f..40fce4a 100644
--- a/src/gui/kernel/qwidget_qws.cpp
+++ b/src/gui/kernel/qwidget_qws.cpp
@@ -565,20 +565,6 @@ void QWidget::activateWindow()
}
}
-/*
- Should we require that q is a toplevel window ???
-
- Used by QWSManager
- */
-void QWidgetPrivate::blitToScreen(const QRegion &globalrgn)
-{
- Q_Q(QWidget);
- QWidget *win = q->window();
- QBrush bgBrush = win->palette().brush(win->backgroundRole());
- bool opaque = bgBrush.style() == Qt::NoBrush || bgBrush.isOpaque();
- QWidget::qwsDisplay()->repaintRegion(win->data->winid, win->windowFlags(), opaque, globalrgn);
-}
-
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
@@ -1038,6 +1024,9 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+#ifndef QT_NO_QWS_MANAGER
+ extra->topextra->qwsManager = 0;
+#endif
}
void QWidgetPrivate::deleteTLSysExtra()
diff --git a/src/gui/kernel/qwidget_win.cpp b/src/gui/kernel/qwidget_win.cpp
index ffbb341..6ad2548 100644
--- a/src/gui/kernel/qwidget_win.cpp
+++ b/src/gui/kernel/qwidget_win.cpp
@@ -56,19 +56,13 @@
#include "private/qbackingstore_p.h"
#include "private/qwindowsurface_raster_p.h"
-#ifndef QT_NO_DIRECT3D
-#include "private/qpaintengine_d3d_p.h"
-#include "private/qwindowsurface_d3d_p.h"
-#endif
-
-
#include <qdebug.h>
#include <private/qapplication_p.h>
#include <private/qwininputcontext_p.h>
#include <private/qpaintengine_raster_p.h>
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
QT_USE_NAMESPACE
extern void qt_wince_maximize(QWidget *widget); //defined in qguifunctions_wince.cpp
@@ -257,7 +251,7 @@ extern "C" LRESULT CALLBACK QtWndProc(HWND, UINT, WPARAM, LPARAM);
QWidget member functions
*****************************************************************************/
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow)
{
Q_Q(QWidget);
@@ -546,7 +540,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
}
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
@@ -574,7 +568,7 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if (destroyWindow && !(windowType() == Qt::Desktop) && internalWinId()) {
DestroyWindow(internalWinId());
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (destroyWindow && (windowType() == Qt::Desktop) && !GetDesktopWindow()) {
DestroyWindow(internalWinId());
}
@@ -681,7 +675,7 @@ void QWidgetPrivate::setParent_sys(QWidget *parent, Qt::WindowFlags f)
EnableMenuItem(systemMenu, SC_CLOSE, MF_BYCOMMAND|MF_GRAYED);
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// Show borderless toplevel windows in tasklist & NavBar
if (!parent) {
QString txt = q->windowTitle().isEmpty()?qAppName():q->windowTitle();
@@ -877,12 +871,12 @@ QCursor *qt_grab_cursor()
}
// The procedure does nothing, but is required for mousegrabbing to work
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
LRESULT CALLBACK qJournalRecordProc(int nCode, WPARAM wParam, LPARAM lParam)
{
return CallNextHookEx(journalRec, nCode, wParam, lParam);
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
/* Works only as long as pointer is inside the application's window,
which is good enough for QDockWidget.
@@ -905,7 +899,7 @@ void QWidgetPrivate::grabMouseWhileInWindow()
}
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidget::grabMouse()
{
if (!qt_nograb()) {
@@ -982,7 +976,7 @@ void QWidget::activateWindow()
SetForegroundWindow(window()->internalWinId());
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidget::setWindowState(Qt::WindowStates newstate)
{
Q_D(QWidget);
@@ -1031,18 +1025,18 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
if (newstate & Qt::WindowFullScreen) {
if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
d->topData()->normalGeometry = geometry();
- d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE);
+ d->topData()->savedFlags = Qt::WindowFlags(GetWindowLongA(internalWinId(), GWL_STYLE));
#ifndef Q_FLATTEN_EXPOSE
UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
#else
UINT style = WS_POPUP;
#endif
- if (d->topData()->savedFlags & WS_SYSMENU)
+ if (ulong(d->topData()->savedFlags) & WS_SYSMENU)
style |= WS_SYSMENU;
if (isVisible())
style |= WS_VISIBLE;
SetWindowLongA(internalWinId(), GWL_STYLE, style);
- QRect r = qApp->desktop()->screenGeometry(this);
+ QRect r = QApplication::desktop()->screenGeometry(this);
UINT swpf = SWP_FRAMECHANGED;
if (newstate & Qt::WindowActive)
swpf |= SWP_NOACTIVATE;
@@ -1084,7 +1078,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
QWindowStateChangeEvent e(oldstate);
QApplication::sendEvent(this, &e);
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
/*
@@ -1097,7 +1091,7 @@ void QWidgetPrivate::hide_sys()
Q_Q(QWidget);
deactivateWidgetCleanup();
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (!qt_wince_is_mobile() && q->isFullScreen()) {
HWND handle = FindWindow(L"HHTaskBar", L"");
if (handle) {
@@ -1126,7 +1120,7 @@ void QWidgetPrivate::hide_sys()
\internal
Platform-specific part of QWidget::show().
*/
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidgetPrivate::show_sys()
{
Q_Q(QWidget);
@@ -1194,7 +1188,7 @@ void QWidgetPrivate::show_sys()
invalidateBuffer(q->rect());
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
void QWidgetPrivate::setFocus_sys()
{
@@ -1240,7 +1234,7 @@ void QWidgetPrivate::stackUnder_sys(QWidget* w)
(In all comments below: s/X/Windows/g)
*/
-void QWidgetPrivate::setWSGeometry(bool dontShow)
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
@@ -1452,7 +1446,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove)
show_sys();
} else if (!q->testAttribute(Qt::WA_DontShowOnScreen)) {
q->setAttribute(Qt::WA_OutsideWSRange, false);
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
// If the window is hidden and in maximized state or minimized, instead of moving the
// window, set the normal position of the window.
WINDOWPLACEMENT wndpl;
@@ -1571,7 +1565,7 @@ bool QWidgetPrivate::shouldShowMaximizeButton()
void QWidgetPrivate::winUpdateIsOpaque()
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
Q_Q(QWidget);
if (!q->isWindow() || !q->testAttribute(Qt::WA_TranslucentBackground))
@@ -1592,7 +1586,7 @@ void QWidgetPrivate::winUpdateIsOpaque()
void QWidgetPrivate::setConstraints_sys()
{
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
Q_Q(QWidget);
if (q->isWindow() && q->testAttribute(Qt::WA_WState_Created)) {
int style = GetWindowLongA(q->internalWinId(), GWL_STYLE);
@@ -1710,28 +1704,24 @@ int QWidget::metric(PaintDeviceMetric m) const
return val;
}
-#ifndef Q_OS_WINCE
void QWidgetPrivate::createSysExtra()
{
#ifndef QT_NO_DRAGANDDROP
extra->dropTarget = 0;
#endif
-#ifndef QT_NO_DIRECT3D
- extra->had_auto_fill_bg = 0;
- extra->had_paint_on_screen = 0;
- extra->had_no_system_bg = 0;
-#endif
}
+#ifndef Q_WS_WINCE
void QWidgetPrivate::deleteSysExtra()
{
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
void QWidgetPrivate::createTLSysExtra()
{
- extra->topextra->winIconSmall = 0;
+ extra->topextra->savedFlags = 0;
extra->topextra->winIconBig = 0;
+ extra->topextra->winIconSmall = 0;
}
void QWidgetPrivate::deleteTLSysExtra()
@@ -1855,7 +1845,8 @@ void QWidgetPrivate::setMask_sys(const QRegion &region)
OffsetRgn(wr, offset.x(), offset.y());
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
- SetWindowRgn(data.winid, wr, true);
+ if (!SetWindowRgn(data.winid, wr, true))
+ DeleteObject(wr);
}
void QWidgetPrivate::updateFrameStrut()
@@ -1877,7 +1868,7 @@ void QWidgetPrivate::updateFrameStrut()
GetWindowLongA(q->internalWinId(), GWL_EXSTYLE));
uint style = QT_WA_INLINE(GetWindowLongW(q->internalWinId(), GWL_STYLE),
GetWindowLongA(q->internalWinId(), GWL_STYLE));
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (AdjustWindowRectEx(&rect, style & ~(WS_OVERLAPPED), FALSE, exstyle)) {
#else
if (AdjustWindowRectEx(&rect, style, FALSE, exstyle)) {
@@ -1887,7 +1878,7 @@ void QWidgetPrivate::updateFrameStrut()
}
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
void QWidgetPrivate::setWindowOpacity_sys(qreal level)
{
Q_Q(QWidget);
@@ -1922,7 +1913,7 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
}
(*ptrSetLayeredWindowAttributes)(q->internalWinId(), 0, (int)(level * 255), Q_LWA_ALPHA);
}
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
// class QGlobalRasterPaintEngine: public QRasterPaintEngine
// {
@@ -1931,22 +1922,6 @@ void QWidgetPrivate::setWindowOpacity_sys(qreal level)
// };
// Q_GLOBAL_STATIC(QGlobalRasterPaintEngine, globalRasterPaintEngine)
-#ifndef QT_NO_DIRECT3D
-static void cleanup_d3d_engine();
-Q_GLOBAL_STATIC_WITH_INITIALIZER(QDirect3DPaintEngine, _qt_d3dEngine,
- {
- qAddPostRoutine(cleanup_d3d_engine);
- })
-static void cleanup_d3d_engine()
-{
- _qt_d3dEngine()->cleanup();
-}
-QDirect3DPaintEngine* qt_d3dEngine()
-{
- return _qt_d3dEngine();
-}
-#endif
-
#ifndef QT_NO_DIRECTDRAW
static uchar *qt_primary_surface_bits;
@@ -2002,8 +1977,8 @@ public:
// in
QOnScreenRasterPaintEngine()
: QRasterPaintEngine(new QImage(qt_primary_surface_bits,
- qApp->desktop()->width(),
- qApp->desktop()->height(),
+ QApplication::desktop()->width(),
+ QApplication::desktop()->height(),
qt_primary_surface_stride,
qt_primary_surface_format))
{
@@ -2059,19 +2034,6 @@ void qt_win_initialize_directdraw() { }
QPaintEngine *QWidget::paintEngine() const
{
-#ifndef QT_NO_DIRECT3D
- if ((qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault)
- || testAttribute(Qt::WA_MSWindowsUseDirect3D))
- && qt_d3dEngine()->hasDirect3DSupport())
- {
- QDirect3DPaintEngine *engine = qt_d3dEngine();
- if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault))
- engine->setFlushOnEnd(false);
- else
- engine->setFlushOnEnd(true);
- return engine;
- }
-#endif
#ifndef QT_NO_DIRECTDRAW
QOnScreenRasterPaintEngine *pe = onScreenPaintEngine();
pe->widget = this;
@@ -2100,13 +2062,6 @@ QPaintEngine *QWidget::paintEngine() const
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys()
{
Q_Q(QWidget);
-#ifndef QT_NO_DIRECT3D
- extern QDirect3DPaintEngine *qt_d3dEngine();
- if (qApp->testAttribute(Qt::AA_MSWindowsUseDirect3DByDefault) && (q->windowOpacity() == 1.0f)
- && qt_d3dEngine()->hasDirect3DSupport()) {
- return new QD3DWindowSurface(q);
- }
-#endif
return new QRasterWindowSurface(q);
}
@@ -2119,6 +2074,6 @@ void QWidgetPrivate::setModal_sys()
QT_END_NAMESPACE
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
# include "qwidget_wince.cpp"
#endif
diff --git a/src/gui/kernel/qwidget_wince.cpp b/src/gui/kernel/qwidget_wince.cpp
index bb9681e..435fd31 100644
--- a/src/gui/kernel/qwidget_wince.cpp
+++ b/src/gui/kernel/qwidget_wince.cpp
@@ -39,7 +39,7 @@
**
****************************************************************************/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
@@ -211,7 +211,7 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
style |= WS_SYSMENU;
if (flags & Qt::WindowContextHelpButtonHint)
exsty |= WS_EX_CONTEXTHELP;
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
if (shouldShowMaximizeButton())
@@ -414,7 +414,7 @@ void QWidgetPrivate::show_sys() {
int sm = SW_SHOW;
bool fakedMaximize = false;
if (q->isWindow()) {
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
if (q->isMinimized()) {
sm = SW_SHOWMINIMIZED;
} else if (q->isMaximized()) {
@@ -450,7 +450,7 @@ void QWidgetPrivate::show_sys() {
if (q->isMaximized() && q->isWindow())
qt_wince_maximize(q);
-#ifndef Q_OS_WINCE_WM
+#ifndef Q_WS_WINCE_WM
if (!qt_wince_is_mobile() && q->isFullScreen()) {
HWND handle = FindWindow(L"HHTaskBar", L"");
if (handle) {
@@ -535,7 +535,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
if (newstate & Qt::WindowFullScreen) {
if (d->topData()->normalGeometry.width() < 0 && !(oldstate & Qt::WindowMaximized))
d->topData()->normalGeometry = geometry();
- d->topData()->savedFlags = GetWindowLongA(internalWinId(), GWL_STYLE);
+ d->topData()->savedFlags = (Qt::WindowFlags) GetWindowLongA(internalWinId(), GWL_STYLE);
UINT style = WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_POPUP;
if (isVisible())
style |= WS_VISIBLE;
@@ -583,7 +583,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
}
if ((newstate & Qt::WindowMaximized) && !(newstate & Qt::WindowFullScreen)) {
QRect r = d->topData()->normalGeometry;
-#ifdef Q_OS_WINCE_WM
+#ifdef Q_WS_WINCE_WM
if (!inherits("QDialog") && !inherits("QMdiArea") && !isVisible()) {
d->data.crect.setRect(0, 0, -1, -1);
}
@@ -598,13 +598,6 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
QApplication::sendEvent(this, &e);
}
-
-void QWidgetPrivate::createSysExtra() {
-#ifndef QT_NO_DRAGANDDROP
- extra->dropTarget = 0;
-#endif
-}
-
void QWidgetPrivate::deleteSysExtra()
{
Q_Q(QWidget);
@@ -704,4 +697,4 @@ void QWidget::show()
QT_END_NAMESPACE
-#endif Q_OS_WINCE
+#endif // Q_WS_WINCE
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 6250fb77..8159f8e 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -754,11 +754,14 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO
qBound(1, data.crect.width(), XCOORD_MAX),
qBound(1, data.crect.height(), XCOORD_MAX));
XStoreName(dpy, id, appName.data());
- Atom protocols[4];
+ Atom protocols[5];
int n = 0;
protocols[n++] = ATOM(WM_DELETE_WINDOW); // support del window protocol
protocols[n++] = ATOM(WM_TAKE_FOCUS); // support take focus window protocol
protocols[n++] = ATOM(_NET_WM_PING); // support _NET_WM_PING protocol
+#ifndef QT_NO_XSYNC
+ protocols[n++] = ATOM(_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol
+#endif // QT_NO_XSYNC
if (flags & Qt::WindowContextHelpButtonHint)
protocols[n++] = ATOM(_NET_WM_CONTEXT_HELP);
XSetWMProtocols(dpy, id, protocols, n);
@@ -893,19 +896,70 @@ void QWidgetPrivate::x11UpdateIsOpaque()
int screen = xinfo.screen();
if (topLevel && X11->use_xrender
&& X11->argbVisuals[screen] && xinfo.depth() != 32) {
- // recreate widget
- QPoint pos = q->pos();
- bool visible = q->isVisible();
- if (visible)
- q->hide();
- q->setParent(q->parentWidget(), q->windowFlags());
- q->move(pos);
- if (visible)
- q->show();
+
+ if (q->inherits("QGLWidget")) {
+ // We send QGLWidgets a ParentChange event which causes them to
+ // recreate their GL context, which in turn causes them to choose
+ // their visual again. Now that WA_TranslucentBackground is set,
+ // QGLContext::chooseVisual will select an ARGB visual.
+ QEvent e(QEvent::ParentChange);
+ QApplication::sendEvent(q, &e);
+ }
+ else {
+ // For regular widgets, reparent them with their parent which
+ // also triggers a recreation of the native window
+ QPoint pos = q->pos();
+ bool visible = q->isVisible();
+ if (visible)
+ q->hide();
+
+ q->setParent(q->parentWidget(), q->windowFlags());
+ q->move(pos);
+ if (visible)
+ q->show();
+ }
}
#endif
}
+/*
+ Returns true if the background is inherited; otherwise returns
+ false.
+
+ Mainly used in the paintOnScreen case.
+*/
+bool QWidgetPrivate::isBackgroundInherited() const
+{
+ Q_Q(const QWidget);
+
+ // windows do not inherit their background
+ if (q->isWindow() || q->windowType() == Qt::SubWindow)
+ return false;
+
+ if (q->testAttribute(Qt::WA_NoSystemBackground) || q->testAttribute(Qt::WA_OpaquePaintEvent))
+ return false;
+
+ const QPalette &pal = q->palette();
+ QPalette::ColorRole bg = q->backgroundRole();
+ QBrush brush = pal.brush(bg);
+
+ // non opaque brushes leaves us no choice, we must inherit
+ if (!q->autoFillBackground() || !brush.isOpaque())
+ return true;
+
+ if (brush.style() == Qt::SolidPattern) {
+ // the background is just a solid color. If there is no
+ // propagated contents, then we claim as performance
+ // optimization that it was not inheritet. This is the normal
+ // case in standard Windows or Motif style.
+ const QWidget *w = q->parentWidget();
+ if (!w->d_func()->isBackgroundInherited())
+ return false;
+ }
+
+ return true;
+}
+
void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
{
Q_D(QWidget);
@@ -1308,17 +1362,10 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
// already been set
return;
- XWMHints *h = 0;
- if (q->internalWinId())
- h = XGetWMHints(X11->display, q->internalWinId());
- XWMHints wm_hints;
- if (!h) {
- memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
- h = &wm_hints;
- }
-
// preparing images to set the _NET_WM_ICON property
QIcon icon = q->windowIcon();
+ QVector<long> icon_data;
+ Qt::HANDLE pixmap_handle = 0;
if (!icon.isNull()) {
QList<QSize> availableSizes = icon.availableSizes();
if(availableSizes.isEmpty()) {
@@ -1328,7 +1375,6 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
availableSizes.push_back(QSize(64,64));
availableSizes.push_back(QSize(128,128));
}
- QVector<long> icon_data;
for(int i = 0; i < availableSizes.size(); ++i) {
QSize size = availableSizes.at(i);
QPixmap pixmap = icon.pixmap(size);
@@ -1350,11 +1396,6 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
}
}
if (!icon_data.isEmpty()) {
- if (q->internalWinId()) {
- XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
- PropModeReplace, (unsigned char *) icon_data.data(),
- icon_data.size());
- }
extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
/*
if the app is running on an unknown desktop, or it is not
@@ -1368,22 +1409,44 @@ void QWidgetPrivate::setWindowIcon_sys(bool forceReset)
// unknown DE or non-default visual/colormap, use 1bpp bitmap
if (!forceReset || !topData->iconPixmap)
topData->iconPixmap = new QBitmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
- h->icon_pixmap = topData->iconPixmap->handle();
+ pixmap_handle = topData->iconPixmap->handle();
} else {
// default depth, use a normal pixmap (even though this
// violates the ICCCM), since this works on all DEs known to Qt
if (!forceReset || !topData->iconPixmap)
topData->iconPixmap = new QPixmap(qt_toX11Pixmap(icon.pixmap(QSize(64,64))));
- h->icon_pixmap = static_cast<QX11PixmapData*>(topData->iconPixmap->data)->x11ConvertToDefaultDepth();
+ pixmap_handle = static_cast<QX11PixmapData*>(topData->iconPixmap->data)->x11ConvertToDefaultDepth();
}
- h->flags |= IconPixmapHint;
- } else {
- h->flags &= ~(IconPixmapHint | IconMaskHint);
}
}
- if (q->internalWinId())
- XSetWMHints(X11->display, q->internalWinId(), h);
+ if (!q->internalWinId())
+ return;
+
+ if (!icon_data.isEmpty()) {
+ XChangeProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON), XA_CARDINAL, 32,
+ PropModeReplace, (unsigned char *) icon_data.data(),
+ icon_data.size());
+ } else {
+ XDeleteProperty(X11->display, q->internalWinId(), ATOM(_NET_WM_ICON));
+ }
+
+ XWMHints *h = XGetWMHints(X11->display, q->internalWinId());
+ XWMHints wm_hints;
+ if (!h) {
+ memset(&wm_hints, 0, sizeof(wm_hints)); // make valgrind happy
+ h = &wm_hints;
+ }
+
+ if (pixmap_handle) {
+ h->icon_pixmap = pixmap_handle;
+ h->flags |= IconPixmapHint;
+ } else {
+ h->icon_pixmap = 0;
+ h->flags &= ~(IconPixmapHint | IconMaskHint);
+ }
+
+ XSetWMHints(X11->display, q->internalWinId(), h);
if (h != &wm_hints)
XFree((char *)h);
}
@@ -1817,6 +1880,23 @@ void QWidgetPrivate::show_sys()
if (setUserTime)
qt_net_update_user_time(q, userTime);
+#ifndef QT_NO_XSYNC
+ if (!topData()->syncUpdateCounter) {
+ XSyncValue value;
+ XSyncIntToValue(&value, 0);
+ topData()->syncUpdateCounter = XSyncCreateCounter(X11->display, value);
+
+ XChangeProperty(X11->display, q->internalWinId(),
+ ATOM(_NET_WM_SYNC_REQUEST_COUNTER),
+ XA_CARDINAL,
+ 32, PropModeReplace,
+ (uchar *) &topData()->syncUpdateCounter, 1);
+
+ topData()->newCounterValueHi = 0;
+ topData()->newCounterValueLo = 0;
+ }
+#endif
+
if (!topData()->embedded
&& (topData()->validWMState || topData()->waitingForMapNotify)
&& !q->isMinimized()) {
@@ -2151,7 +2231,7 @@ static void do_size_hints(QWidget* widget, QWExtra *x)
parentWRect is the geometry of the parent's X rect, measured in
parent's coord sys
*/
-void QWidgetPrivate::setWSGeometry(bool dontShow)
+void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &)
{
Q_Q(QWidget);
Q_ASSERT(q->testAttribute(Qt::WA_WState_Created));
@@ -2611,8 +2691,8 @@ int QWidget::metric(PaintDeviceMetric m) const
void QWidgetPrivate::createSysExtra()
{
- extra->xDndProxy = 0;
extra->compress_events = true;
+ extra->xDndProxy = 0;
}
void QWidgetPrivate::deleteSysExtra()
@@ -2621,9 +2701,18 @@ void QWidgetPrivate::deleteSysExtra()
void QWidgetPrivate::createTLSysExtra()
{
+ extra->topextra->spont_unmapped = 0;
+ extra->topextra->dnd = 0;
extra->topextra->validWMState = 0;
extra->topextra->waitingForMapNotify = 0;
+ extra->topextra->parentWinId = 0;
extra->topextra->userTimeWindow = 0;
+#ifndef QT_NO_XSYNC
+ extra->topextra->syncUpdateCounter = 0;
+ extra->topextra->syncRequestTimestamp = 0;
+ extra->topextra->newCounterValueHi = 0;
+ extra->topextra->newCounterValueLo = 0;
+#endif
}
void QWidgetPrivate::deleteTLSysExtra()
diff --git a/src/gui/kernel/qwidgetaction.cpp b/src/gui/kernel/qwidgetaction.cpp
index efdde5e..cd12029 100644
--- a/src/gui/kernel/qwidgetaction.cpp
+++ b/src/gui/kernel/qwidgetaction.cpp
@@ -228,8 +228,8 @@ bool QWidgetAction::event(QEvent *event)
if (event->type() == QEvent::ActionChanged) {
if (d->defaultWidget)
d->defaultWidget->setEnabled(isEnabled());
- foreach (QWidget *w, d->createdWidgets)
- w->setEnabled(isEnabled());
+ for (int i = 0; i < d->createdWidgets.count(); ++i)
+ d->createdWidgets.at(i)->setEnabled(isEnabled());
}
return QAction::event(event);
}
diff --git a/src/gui/kernel/qwindowdefs_win.h b/src/gui/kernel/qwindowdefs_win.h
index 3899c23..a24afd4 100644
--- a/src/gui/kernel/qwindowdefs_win.h
+++ b/src/gui/kernel/qwindowdefs_win.h
@@ -122,7 +122,7 @@ QT_BEGIN_NAMESPACE
Q_CORE_EXPORT HINSTANCE qWinAppInst();
Q_CORE_EXPORT HINSTANCE qWinAppPrevInst();
-Q_GUI_EXPORT int qWinAppCmdShow();
+Q_CORE_EXPORT int qWinAppCmdShow();
Q_GUI_EXPORT HDC qt_win_display_dc();
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qx11embed_x11.cpp b/src/gui/kernel/qx11embed_x11.cpp
index 6329135..ae93efe 100644
--- a/src/gui/kernel/qx11embed_x11.cpp
+++ b/src/gui/kernel/qx11embed_x11.cpp
@@ -1297,9 +1297,6 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
// focus is set to our focus proxy. We want to intercept all
// keypresses.
if (o == window() && d->client) {
- if (!d->isEmbedded() && d->activeContainer == this)
- d->moveInputToProxy();
-
if (d->clientIsXEmbed) {
sendXEmbedMessage(d->client, x11Info().display(), XEMBED_WINDOW_ACTIVATE);
} else {
@@ -1307,6 +1304,8 @@ bool QX11EmbedContainer::eventFilter(QObject *o, QEvent *event)
if (hasFocus())
XSetInputFocus(x11Info().display(), d->client, XRevertToParent, x11Time());
}
+ if (!d->isEmbedded())
+ d->moveInputToProxy();
}
break;
case QEvent::WindowDeactivate:
@@ -1729,10 +1728,10 @@ void QX11EmbedContainerPrivate::acceptClient(WId window)
checkGrab();
if (q->hasFocus()) {
XSetInputFocus(q->x11Info().display(), client, XRevertToParent, x11Time());
- } else {
- if (!isEmbedded())
- moveInputToProxy();
}
+ } else {
+ if (!isEmbedded())
+ moveInputToProxy();
}
emit q->clientIsEmbedded();
@@ -1749,11 +1748,9 @@ void QX11EmbedContainerPrivate::acceptClient(WId window)
void QX11EmbedContainerPrivate::moveInputToProxy()
{
Q_Q(QX11EmbedContainer);
- WId focus;
- int revert_to;
- XGetInputFocus(q->x11Info().display(), &focus, &revert_to);
- if (focus != focusProxy->internalWinId())
- XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, x11Time());
+ // Following Owen Taylor's advice from the XEmbed specification to
+ // always use CurrentTime when no explicit user action is involved.
+ XSetInputFocus(q->x11Info().display(), focusProxy->internalWinId(), XRevertToParent, CurrentTime);
}
/*! \internal
diff --git a/src/gui/mac/images/leopard-unified-toolbar-on.png b/src/gui/mac/images/leopard-unified-toolbar-on.png
new file mode 100644
index 0000000..6716597
--- /dev/null
+++ b/src/gui/mac/images/leopard-unified-toolbar-on.png
Binary files differ
diff --git a/src/gui/mac/maccursors.qrc b/src/gui/mac/macresources.qrc
index d80a63b..9696002 100644
--- a/src/gui/mac/maccursors.qrc
+++ b/src/gui/mac/macresources.qrc
@@ -6,4 +6,7 @@
<file>images/waitcursor.png</file>
<file>images/pluscursor.png</file>
</qresource>
+<qresource prefix="/trolltech/mac/style">
+<file>images/leopard-unified-toolbar-on.png</file>
+</qresource>
</RCC>
diff --git a/src/gui/math3d/math3d.pri b/src/gui/math3d/math3d.pri
new file mode 100644
index 0000000..e4dd53a
--- /dev/null
+++ b/src/gui/math3d/math3d.pri
@@ -0,0 +1,15 @@
+HEADERS += \
+ math3d/qgenericmatrix.h \
+ math3d/qmatrix4x4.h \
+ math3d/qquaternion.h \
+ math3d/qvector2d.h \
+ math3d/qvector3d.h \
+ math3d/qvector4d.h
+
+SOURCES += \
+ math3d/qgenericmatrix.cpp \
+ math3d/qmatrix4x4.cpp \
+ math3d/qquaternion.cpp \
+ math3d/qvector2d.cpp \
+ math3d/qvector3d.cpp \
+ math3d/qvector4d.cpp
diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp
new file mode 100644
index 0000000..19a0f6e
--- /dev/null
+++ b/src/gui/math3d/qgenericmatrix.cpp
@@ -0,0 +1,251 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericmatrix.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGenericMatrix
+ \brief The QGenericMatrix class is a template class that represents a NxM transformation matrix with N columns and M rows.
+ \since 4.6
+
+ The QGenericMatrix template has four parameters:
+
+ \table
+ \row \i N \i Number of columns.
+ \row \i M \i Number of rows.
+ \row \i T \i Element type that is visible to users of the class.
+ \row \i InnerT \i Element type that is used inside the class.
+ \endtable
+
+ Normally T and InnerT are the same type; e.g. float or double.
+ But they can be different if the user wants to store elements
+ internally in a fixed-point format for the underlying hardware.
+
+ \sa QMatrix4x4, QFixedPt
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix()
+
+ Constructs a NxM identity matrix.
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix(const T *values)
+
+ Constructs a matrix from the given N * M floating-point \a values.
+ The contents of the array \a values is assumed to be in
+ row-major order.
+
+ \sa toValueArray()
+*/
+
+/*!
+ \fn T QGenericMatrix::operator()(int row, int column) const
+
+ Returns the element at position (\a row, \a column) in this matrix.
+*/
+
+/*!
+ \fn InnerT& QGenericMatrix::operator()(int row, int column)
+
+ Returns a reference to the element at position (\a row, \a column)
+ in this matrix so that the element can be assigned to.
+*/
+
+/*!
+ \fn bool QGenericMatrix::isIdentity() const
+
+ Returns true if this matrix is the identity; false otherwise.
+
+ \sa setIdentity()
+*/
+
+/*!
+ \fn void QGenericMatrix::setIdentity()
+
+ Sets this matrix to the identity.
+
+ \sa isIdentity()
+*/
+
+/*!
+ \fn void QGenericMatrix::fill(T value)
+
+ Fills all elements of this matrix with \a value.
+*/
+
+/*!
+ \fn QGenericMatrix<M, N> QGenericMatrix::transposed() const
+
+ Returns this matrix, transposed about its diagonal.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator+=(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Adds the contents of \a other to this matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator-=(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Subtracts the contents of \a other from this matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator*=(T factor)
+
+ Multiplies all elements of this matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator/=(T divisor)
+
+ Divides all elements of this matrix by \a divisor.
+*/
+
+/*!
+ \fn bool QGenericMatrix::operator==(const QGenericMatrix<N, M, T, InnerT>& other) const
+
+ Returns true if this matrix is identical to \a other; false otherwise.
+*/
+
+/*!
+ \fn bool QGenericMatrix::operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const
+
+ Returns true if this matrix is not identical to \a other; false otherwise.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator+(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the sum of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the difference of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QGenericMatrix<M1, M2, T, InnerT> operator*(const QGenericMatrix<N, M2, T, InnerT>& m1, const QGenericMatrix<M1, N, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the product of the NxM2 matrix \a m1 and the M1xN matrix \a m2
+ to produce a M1xM2 matrix result.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& matrix)
+ \overload
+ \relates QGenericMatrix
+
+ Returns the negation of \a matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator*(T factor, const QGenericMatrix<N, M, T, InnerT>& matrix)
+ \relates QGenericMatrix
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator*(const QGenericMatrix<N, M, T, InnerT>& matrix, T factor)
+ \relates QGenericMatrix
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator/(const QGenericMatrix<N, M, T, InnerT>& matrix, T divisor)
+ \relates QGenericMatrix
+
+ Returns the result of dividing all elements of \a matrix by \a divisor.
+*/
+
+/*!
+ \fn void QGenericMatrix::toValueArray(T *values)
+
+ Retrieves the N * M items in this matrix and writes them to \a values
+ in row-major order.
+*/
+
+/*!
+ \fn InnerT *QGenericMatrix::data()
+
+ Returns a pointer to the raw data of this matrix. This is intended
+ for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const InnerT *QGenericMatrix::data() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const InnerT *QGenericMatrix::constData() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa data()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
new file mode 100644
index 0000000..330ded2
--- /dev/null
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGENERICMATRIX_H
+#define QGENERICMATRIX_H
+
+#include <QtCore/qmetatype.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+template <int N, int M, typename T, typename InnerT = T>
+class QGenericMatrix
+{
+public:
+ QGenericMatrix();
+ QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other);
+ explicit QGenericMatrix(const T *values);
+
+ T operator()(int row, int column) const;
+ InnerT& operator()(int row, int column);
+
+ bool isIdentity() const;
+ void setIdentity();
+
+ void fill(T value);
+
+ QGenericMatrix<M, N, T, InnerT> transposed() const;
+
+ QGenericMatrix<N, M, T, InnerT>& operator+=(const QGenericMatrix<N, M, T, InnerT>& other);
+ QGenericMatrix<N, M, T, InnerT>& operator-=(const QGenericMatrix<N, M, T, InnerT>& other);
+ QGenericMatrix<N, M, T, InnerT>& operator*=(T factor);
+ QGenericMatrix<N, M, T, InnerT>& operator/=(T divisor);
+ bool operator==(const QGenericMatrix<N, M, T, InnerT>& other) const;
+ bool operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const;
+
+ void toValueArray(T *values);
+
+ InnerT *data() { return m[0]; }
+ const InnerT *data() const { return m[0]; }
+ const InnerT *constData() const { return m[0]; }
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator+(const QGenericMatrix<NN, MM, TT, ITT>& m1, const QGenericMatrix<NN, MM, TT, ITT>& m2);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator-(const QGenericMatrix<NN, MM, TT, ITT>& m1, const QGenericMatrix<NN, MM, TT, ITT>& m2);
+ template<int NN, int M1, int M2, typename TT, typename ITT>
+ friend QGenericMatrix<M1, M2, TT, ITT> operator*(const QGenericMatrix<NN, M2, TT, ITT>& m1, const QGenericMatrix<M1, NN, TT, ITT>& m2);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator-(const QGenericMatrix<NN, MM, TT, ITT>& matrix);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator*(TT factor, const QGenericMatrix<NN, MM, TT, ITT>& matrix);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator*(const QGenericMatrix<NN, MM, TT, ITT>& matrix, TT factor);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator/(const QGenericMatrix<NN, MM, TT, ITT>& matrix, TT divisor);
+
+private:
+#endif
+ InnerT m[N][M]; // Column-major order to match OpenGL.
+
+ QGenericMatrix(int) {} // Construct without initializing identity matrix.
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template <int NN, int MM, typename TT, typename ITT>
+ friend class QGenericMatrix;
+#endif
+};
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix()
+{
+ setIdentity();
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ qMemCopy(m, other.m, sizeof(m));
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix(const T *values)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = values[row * N + col];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE T QGenericMatrix<N, M, T, InnerT>::operator()(int row, int column) const
+{
+ Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
+ return T(m[column][row]);
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE InnerT& QGenericMatrix<N, M, T, InnerT>::operator()(int row, int column)
+{
+ Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
+ return m[column][row];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::isIdentity() const
+{
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (row == col) {
+ if (m[col][row] != 1.0f)
+ return false;
+ } else {
+ if (m[col][row] != 0.0f)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::setIdentity()
+{
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (row == col)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::fill(T value)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = value;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<M, N, T, InnerT> QGenericMatrix<N, M, T, InnerT>::transposed() const
+{
+ QGenericMatrix<M, N, T, InnerT> result(1);
+ for (int row = 0; row < M; ++row)
+ for (int col = 0; col < N; ++col)
+ result.m[row][col] = m[col][row];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator+=(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] += other.m[0][index];
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator-=(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] -= other.m[0][index];
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator*=(T factor)
+{
+ InnerT f(factor);
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] *= f;
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::operator==(const QGenericMatrix<N, M, T, InnerT>& other) const
+{
+ for (int index = 0; index < N * M; ++index) {
+ if (m[0][index] != other.m[0][index])
+ return false;
+ }
+ return true;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const
+{
+ for (int index = 0; index < N * M; ++index) {
+ if (m[0][index] != other.m[0][index])
+ return true;
+ }
+ return false;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator/=(T divisor)
+{
+ InnerT d(divisor);
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] /= d;
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator+(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = m1.m[0][index] + m2.m[0][index];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = m1.m[0][index] - m2.m[0][index];
+ return result;
+}
+
+template <int N, int M1, int M2, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<M1, M2, T, InnerT> operator*(const QGenericMatrix<N, M2, T, InnerT>& m1, const QGenericMatrix<M1, N, T, InnerT>& m2)
+{
+ QGenericMatrix<M1, M2, T, InnerT> result(1);
+ for (int row = 0; row < M2; ++row) {
+ for (int col = 0; col < M1; ++col) {
+ InnerT sum(0.0f);
+ for (int j = 0; j < N; ++j)
+ sum += m1.m[j][row] * m2.m[col][j];
+ result.m[col][row] = sum;
+ }
+ }
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& matrix)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = -matrix.m[0][index];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator*(T factor, const QGenericMatrix<N, M, T, InnerT>& matrix)
+{
+ InnerT f(factor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] * f;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator*(const QGenericMatrix<N, M, T, InnerT>& matrix, T factor)
+{
+ InnerT f(factor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] * f;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator/(const QGenericMatrix<N, M, T, InnerT>& matrix, T divisor)
+{
+ InnerT d(divisor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] / d;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::toValueArray(T *values)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ values[row * N + col] = T(m[col][row]);
+}
+
+// Define aliases for the useful variants of QGenericMatrix.
+typedef QGenericMatrix<2, 2, qreal, float> QMatrix2x2;
+typedef QGenericMatrix<2, 3, qreal, float> QMatrix2x3;
+typedef QGenericMatrix<2, 4, qreal, float> QMatrix2x4;
+typedef QGenericMatrix<3, 2, qreal, float> QMatrix3x2;
+typedef QGenericMatrix<3, 3, qreal, float> QMatrix3x3;
+typedef QGenericMatrix<3, 4, qreal, float> QMatrix3x4;
+typedef QGenericMatrix<4, 2, qreal, float> QMatrix4x2;
+typedef QGenericMatrix<4, 3, qreal, float> QMatrix4x3;
+
+#ifndef QT_NO_DEBUG_STREAM
+
+template <int N, int M, typename T, typename InnerT>
+QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T, InnerT> &m)
+{
+ dbg.nospace() << "QGenericMatrix<" << N << ", " << M
+ << ", " << QTypeInfo<T>::name() << ", " << QTypeInfo<InnerT>::name()
+ << ">(" << endl << qSetFieldWidth(10);
+ for (int row = 0; row < M; ++row) {
+ for (int col = 0; col < N; ++col)
+ dbg << m(row, col);
+ dbg << endl;
+ }
+ dbg << qSetFieldWidth(0) << ')';
+ return dbg.space();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMatrix2x2)
+Q_DECLARE_METATYPE(QMatrix2x3)
+Q_DECLARE_METATYPE(QMatrix2x4)
+Q_DECLARE_METATYPE(QMatrix3x2)
+Q_DECLARE_METATYPE(QMatrix3x3)
+Q_DECLARE_METATYPE(QMatrix3x4)
+Q_DECLARE_METATYPE(QMatrix4x2)
+Q_DECLARE_METATYPE(QMatrix4x3)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
new file mode 100644
index 0000000..a69b9df
--- /dev/null
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -0,0 +1,1808 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmatrix4x4.h"
+#include <QtCore/qmath.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_MATRIX4X4
+
+/*!
+ \class QMatrix4x4
+ \brief The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
+ \since 4.6
+
+ The matrix elements are stored internally using the most efficient
+ numeric representation for the underlying hardware: floating-point
+ or fixed-point.
+
+ \sa QVector3D, QGenericMatrix
+*/
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4()
+
+ Constructs an identity matrix.
+*/
+
+/*!
+ Constructs a matrix from the given 16 floating-point \a values.
+ The contents of the array \a values is assumed to be in
+ row-major order.
+
+ If the matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toValueArray(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const qreal *values)
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ m[col][row] = values[row * 4 + col];
+ flagBits = General;
+}
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14, qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44)
+
+ Constructs a matrix from the 16 elements \a m11, \a m12, \a m13, \a m14,
+ \a m21, \a m22, \a m23, \a m24, \a m31, \a m32, \a m33, \a m34,
+ \a m41, \a m42, \a m43, and \a m44. The elements are specified in
+ row-major order.
+
+ If the matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa inferSpecialType()
+*/
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix)
+
+ Constructs a 4x4 matrix from the left-most 4 columns and top-most
+ 4 rows of \a matrix. If \a matrix has less than 4 columns or rows,
+ the remaining elements are filled with elements from the identity
+ matrix.
+
+ \sa toGenericMatrix(), qGenericMatrixToMatrix4x4()
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, qreal, float> QMatrix4x4::toGenericMatrix() const
+
+ Constructs a NxM generic matrix from the left-most N columns and
+ top-most M rows of this 4x4 matrix. If N or M is greater than 4,
+ then the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixFromMatrix4x4()
+*/
+
+#endif
+
+/*!
+ \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix)
+ \relates QMatrix4x4
+
+ Returns a 4x4 matrix constructed from the left-most 4 columns and
+ top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
+ or rows, the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixFromMatrix4x4()
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, qreal, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns a NxM generic matrix constructed from the left-most N columns
+ and top-most M rows of \a matrix. If N or M is greater than 4,
+ then the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix()
+*/
+
+/*!
+ \internal
+*/
+QMatrix4x4::QMatrix4x4(const float *values, int cols, int rows)
+{
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col < cols && row < rows)
+ m[col][row] = values[col * rows + row];
+ else if (col == row)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+ flagBits = General;
+}
+
+/*!
+ Constructs a 4x4 matrix from a conventional Qt 2D affine
+ transformation \a matrix.
+
+ If \a matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toAffine(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const QMatrix& matrix)
+{
+ m[0][0] = matrix.m11();
+ m[0][1] = matrix.m12();
+ m[0][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][0] = matrix.m21();
+ m[1][1] = matrix.m22();
+ m[1][2] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = matrix.dx();
+ m[3][1] = matrix.dy();
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ flagBits = General;
+}
+
+/*!
+ Constructs a 4x4 matrix from the conventional Qt 2D
+ transformation matrix \a transform.
+
+ If \a transform has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toTransform(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const QTransform& transform)
+{
+ m[0][0] = transform.m11();
+ m[0][1] = transform.m12();
+ m[0][2] = 0.0f;
+ m[0][3] = transform.m13();
+ m[1][0] = transform.m21();
+ m[1][1] = transform.m22();
+ m[1][2] = 0.0f;
+ m[1][3] = transform.m23();
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = transform.dx();
+ m[3][1] = transform.dy();
+ m[3][2] = 0.0f;
+ m[3][3] = transform.m33();
+ flagBits = General;
+}
+
+/*!
+ \fn qreal QMatrix4x4::operator()(int row, int column) const
+
+ Returns the element at position (\a row, \a column) in this matrix.
+
+ \sa column(), row()
+*/
+
+/*!
+ \fn float& QMatrix4x4::operator()(int row, int column)
+
+ Returns a reference to the element at position (\a row, \a column)
+ in this matrix so that the element can be assigned to.
+
+ \sa inferSpecialType(), setColumn(), setRow()
+*/
+
+/*!
+ \fn QVector4D QMatrix4x4::column(int index) const
+
+ Returns the elements of column \a index as a 4D vector.
+
+ \sa setColumn(), row()
+*/
+
+/*!
+ \fn void QMatrix4x4::setColumn(int index, const QVector4D& value)
+
+ Sets the elements of column \a index to the components of \a value.
+
+ \sa column(), setRow()
+*/
+
+/*!
+ \fn QVector4D QMatrix4x4::row(int index) const
+
+ Returns the elements of row \a index as a 4D vector.
+
+ \sa setRow(), column()
+*/
+
+/*!
+ \fn void QMatrix4x4::setRow(int index, const QVector4D& value)
+
+ Sets the elements of row \a index to the components of \a value.
+
+ \sa row(), setColumn()
+*/
+
+/*!
+ \fn bool QMatrix4x4::isIdentity() const
+
+ Returns true if this matrix is the identity; false otherwise.
+
+ \sa setIdentity()
+*/
+
+/*!
+ \fn void QMatrix4x4::setIdentity()
+
+ Sets this matrix to the identity.
+
+ \sa isIdentity()
+*/
+
+/*!
+ \fn void QMatrix4x4::fill(qreal value)
+
+ Fills all elements of this matrx with \a value.
+*/
+
+// The 4x4 matrix inverse algorithm is based on that described at:
+// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
+// Some optimization has been done to avoid making copies of 3x3
+// sub-matrices, to do calculations in fixed-point where required,
+// and to unroll the loops.
+
+// Calculate the determinant of a 3x3 sub-matrix.
+// | A B C |
+// M = | D E F | det(M) = A * (EI - HF) - B * (DI - GF) + C * (DH - GE)
+// | G H I |
+static inline float matrixDet3
+ (const float m[4][4], int col0, int col1, int col2,
+ int row0, int row1, int row2)
+{
+ return m[col0][row0] *
+ (m[col1][row1] * m[col2][row2] -
+ m[col1][row2] * m[col2][row1]) -
+ m[col1][row0] *
+ (m[col0][row1] * m[col2][row2] -
+ m[col0][row2] * m[col2][row1]) +
+ m[col2][row0] *
+ (m[col0][row1] * m[col1][row2] -
+ m[col0][row2] * m[col1][row1]);
+}
+
+// Calculate the determinant of a 4x4 matrix.
+static inline float matrixDet4(const float m[4][4])
+{
+ float det;
+ det = m[0][0] * matrixDet3(m, 1, 2, 3, 1, 2, 3);
+ det -= m[1][0] * matrixDet3(m, 0, 2, 3, 1, 2, 3);
+ det += m[2][0] * matrixDet3(m, 0, 1, 3, 1, 2, 3);
+ det -= m[3][0] * matrixDet3(m, 0, 1, 2, 1, 2, 3);
+ return det;
+}
+
+/*!
+ Returns the determinant of this matrix.
+*/
+qreal QMatrix4x4::determinant() const
+{
+ return qreal(matrixDet4(m));
+}
+
+/*!
+ Returns the inverse of this matrix. Returns the identity if
+ this matrix cannot be inverted; i.e. determinant() is zero.
+ If \a invertible is not null, then true will be written to
+ that location if the matrix can be inverted; false otherwise.
+
+ If the matrix is recognized as the identity or an orthonormal
+ matrix, then this function will quickly invert the matrix
+ using optimized routines.
+
+ \sa determinant(), normalMatrix()
+*/
+QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
+{
+ // Handle some of the easy cases first.
+ if (flagBits == Identity) {
+ if (invertible)
+ *invertible = true;
+ return QMatrix4x4();
+ } else if (flagBits == Translation) {
+ QMatrix4x4 inv;
+ inv.m[3][0] = -m[3][0];
+ inv.m[3][1] = -m[3][1];
+ inv.m[3][2] = -m[3][2];
+ inv.flagBits = Translation;
+ if (invertible)
+ *invertible = true;
+ return inv;
+ } else if (flagBits == Rotation || flagBits == (Rotation | Translation)) {
+ if (invertible)
+ *invertible = true;
+ return orthonormalInverse();
+ }
+
+ QMatrix4x4 inv(1); // The "1" says to not load the identity.
+
+ float det = matrixDet4(m);
+ if (det == 0.0f) {
+ if (invertible)
+ *invertible = false;
+ return QMatrix4x4();
+ }
+ det = 1.0f / det;
+
+ inv.m[0][0] = matrixDet3(m, 1, 2, 3, 1, 2, 3) * det;
+ inv.m[0][1] = -matrixDet3(m, 0, 2, 3, 1, 2, 3) * det;
+ inv.m[0][2] = matrixDet3(m, 0, 1, 3, 1, 2, 3) * det;
+ inv.m[0][3] = -matrixDet3(m, 0, 1, 2, 1, 2, 3) * det;
+ inv.m[1][0] = -matrixDet3(m, 1, 2, 3, 0, 2, 3) * det;
+ inv.m[1][1] = matrixDet3(m, 0, 2, 3, 0, 2, 3) * det;
+ inv.m[1][2] = -matrixDet3(m, 0, 1, 3, 0, 2, 3) * det;
+ inv.m[1][3] = matrixDet3(m, 0, 1, 2, 0, 2, 3) * det;
+ inv.m[2][0] = matrixDet3(m, 1, 2, 3, 0, 1, 3) * det;
+ inv.m[2][1] = -matrixDet3(m, 0, 2, 3, 0, 1, 3) * det;
+ inv.m[2][2] = matrixDet3(m, 0, 1, 3, 0, 1, 3) * det;
+ inv.m[2][3] = -matrixDet3(m, 0, 1, 2, 0, 1, 3) * det;
+ inv.m[3][0] = -matrixDet3(m, 1, 2, 3, 0, 1, 2) * det;
+ inv.m[3][1] = matrixDet3(m, 0, 2, 3, 0, 1, 2) * det;
+ inv.m[3][2] = -matrixDet3(m, 0, 1, 3, 0, 1, 2) * det;
+ inv.m[3][3] = matrixDet3(m, 0, 1, 2, 0, 1, 2) * det;
+
+ if (invertible)
+ *invertible = true;
+ return inv;
+}
+
+/*!
+ Returns the normal matrix corresponding to this 4x4 transformation.
+ The normal matrix is the transpose of the inverse of the top-left
+ 3x3 part of this 4x4 matrix. If the 3x3 sub-matrix is not invertible,
+ this function returns the identity.
+
+ \sa inverted()
+*/
+QMatrix3x3 QMatrix4x4::normalMatrix() const
+{
+ QMatrix3x3 inv;
+
+ // Handle the simple cases first.
+ if (flagBits == Identity || flagBits == Translation) {
+ return inv;
+ } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
+ if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
+ return inv;
+ inv.data()[0] = 1.0f / m[0][0];
+ inv.data()[4] = 1.0f / m[1][1];
+ inv.data()[8] = 1.0f / m[2][2];
+ return inv;
+ }
+
+ float det = matrixDet3(m, 0, 1, 2, 0, 1, 2);
+ if (det == 0.0f)
+ return inv;
+ det = 1.0f / det;
+
+ float *invm = inv.data();
+
+ // Invert and transpose in a single step.
+ invm[0 + 0 * 3] = (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * det;
+ invm[1 + 0 * 3] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * det;
+ invm[2 + 0 * 3] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * det;
+ invm[0 + 1 * 3] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * det;
+ invm[1 + 1 * 3] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * det;
+ invm[2 + 1 * 3] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * det;
+ invm[0 + 2 * 3] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * det;
+ invm[1 + 2 * 3] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * det;
+ invm[2 + 2 * 3] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * det;
+
+ return inv;
+}
+
+/*!
+ Returns this matrix, transposed about its diagonal.
+*/
+QMatrix4x4 QMatrix4x4::transposed() const
+{
+ QMatrix4x4 result(1); // The "1" says to not load the identity.
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ result.m[col][row] = m[row][col];
+ }
+ }
+ return result;
+}
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
+
+ Adds the contents of \a other to this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
+
+ Subtracts the contents of \a other from this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
+
+ Multiplies the contents of \a other by this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
+ \overload
+
+ Multiplies all elements of this matrix by \a factor.
+*/
+
+/*!
+ \overload
+
+ Divides all elements of this matrix by \a divisor.
+*/
+QMatrix4x4& QMatrix4x4::operator/=(qreal divisor)
+{
+ m[0][0] /= divisor;
+ m[0][1] /= divisor;
+ m[0][2] /= divisor;
+ m[0][3] /= divisor;
+ m[1][0] /= divisor;
+ m[1][1] /= divisor;
+ m[1][2] /= divisor;
+ m[1][3] /= divisor;
+ m[2][0] /= divisor;
+ m[2][1] /= divisor;
+ m[2][2] /= divisor;
+ m[2][3] /= divisor;
+ m[3][0] /= divisor;
+ m[3][1] /= divisor;
+ m[3][2] /= divisor;
+ m[3][3] /= divisor;
+ flagBits = General;
+ return *this;
+}
+
+/*!
+ \fn bool QMatrix4x4::operator==(const QMatrix4x4& other) const
+
+ Returns true if this matrix is identical to \a other; false otherwise.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
+
+ Returns true if this matrix is not identical to \a other; false otherwise.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the sum of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the difference of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the product of \a m1 and \a m2.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied post-vector.
+*/
+
+/*!
+ \fn QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied pre-vector.
+*/
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied post-vector.
+*/
+
+/*!
+ \fn QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied pre-vector.
+*/
+
+#endif
+
+/*!
+ \fn QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied post-point.
+*/
+
+/*!
+ \fn QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied post-point.
+*/
+
+/*!
+ \fn QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied pre-point.
+*/
+
+/*!
+ \fn QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied pre-point.
+*/
+
+/*!
+ \fn QMatrix4x4 operator-(const QMatrix4x4& matrix)
+ \overload
+ \relates QMatrix4x4
+
+ Returns the negation of \a matrix.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
+ \relates QMatrix4x4
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \relates QMatrix4x4
+
+ Returns the result of dividing all elements of \a matrix by \a divisor.
+*/
+QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor)
+{
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ m.m[0][0] = matrix.m[0][0] / divisor;
+ m.m[0][1] = matrix.m[0][1] / divisor;
+ m.m[0][2] = matrix.m[0][2] / divisor;
+ m.m[0][3] = matrix.m[0][3] / divisor;
+ m.m[1][0] = matrix.m[1][0] / divisor;
+ m.m[1][1] = matrix.m[1][1] / divisor;
+ m.m[1][2] = matrix.m[1][2] / divisor;
+ m.m[1][3] = matrix.m[1][3] / divisor;
+ m.m[2][0] = matrix.m[2][0] / divisor;
+ m.m[2][1] = matrix.m[2][1] / divisor;
+ m.m[2][2] = matrix.m[2][2] / divisor;
+ m.m[2][3] = matrix.m[2][3] / divisor;
+ m.m[3][0] = matrix.m[3][0] / divisor;
+ m.m[3][1] = matrix.m[3][1] / divisor;
+ m.m[3][2] = matrix.m[3][2] / divisor;
+ m.m[3][3] = matrix.m[3][3] / divisor;
+ return m;
+}
+
+/*!
+ \fn bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns true if \a m1 and \a m2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiplies this matrix by another that scales coordinates by
+ the components of \a vector. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector)
+{
+ float vx = vector.xp;
+ float vy = vector.yp;
+ float vz = vector.zp;
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ m[2][2] *= vz;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ m[2][0] *= vz;
+ m[2][1] *= vz;
+ m[2][2] *= vz;
+ m[2][3] *= vz;
+ flagBits = General;
+ }
+ return *this;
+}
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ components \a x, and \a y. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y)
+{
+ float vx(x);
+ float vy(y);
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ components \a x, \a y, and \a z. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y, qreal z)
+{
+ float vx(x);
+ float vy(y);
+ float vz(z);
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ m[2][2] *= vz;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ m[2][0] *= vz;
+ m[2][1] *= vz;
+ m[2][2] *= vz;
+ m[2][3] *= vz;
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ given \a factor. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal factor)
+{
+ if (flagBits == Identity) {
+ m[0][0] = factor;
+ m[1][1] = factor;
+ m[2][2] = factor;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= factor;
+ m[1][1] *= factor;
+ m[2][2] *= factor;
+ } else if (flagBits == Translation) {
+ m[0][0] = factor;
+ m[1][1] = factor;
+ m[2][2] = factor;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= factor;
+ m[0][1] *= factor;
+ m[0][2] *= factor;
+ m[0][3] *= factor;
+ m[1][0] *= factor;
+ m[1][1] *= factor;
+ m[1][2] *= factor;
+ m[1][3] *= factor;
+ m[2][0] *= factor;
+ m[2][1] *= factor;
+ m[2][2] *= factor;
+ m[2][3] *= factor;
+ flagBits = General;
+ }
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+/*!
+ Multiplies this matrix by another that translates coordinates by
+ the components of \a vector. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector)
+{
+ float vx = vector.xp;
+ float vy = vector.yp;
+ float vz = vector.zp;
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ m[3][2] = vz;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ m[3][2] += vz;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = m[2][2] * vz;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ m[3][2] += m[2][2] * vz;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that translates coordinates
+ by the components \a x, and \a y. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y)
+{
+ float vx(x);
+ float vy(y);
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = 0.;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that translates coordinates
+ by the components \a x, \a y, and \a z. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y, qreal z)
+{
+ float vx(x);
+ float vy(y);
+ float vz(z);
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ m[3][2] = vz;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ m[3][2] += vz;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = m[2][2] * vz;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ m[3][2] += m[2][2] * vz;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiples this matrix by another that rotates coordinates through
+ \a angle degrees about \a vector. Returns this matrix.
+
+ \sa scale(), translate()
+*/
+QMatrix4x4& QMatrix4x4::rotate(qreal angle, const QVector3D& vector)
+{
+ return rotate(angle, vector.x(), vector.y(), vector.z());
+}
+
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that rotates coordinates through
+ \a angle degrees about the vector (\a x, \a y, \a z). Returns this matrix.
+
+ \sa scale(), translate()
+*/
+QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
+{
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ qreal a = angle * M_PI / 180.0f;
+ qreal c = qCos(a);
+ qreal s = qSin(a);
+ qreal ic;
+ bool quick = false;
+ if (x == 0.0f) {
+ if (y == 0.0f) {
+ if (z != 0.0f) {
+ // Rotate around the Z axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[1][1] = c;
+ if (z < 0.0f) {
+ m.m[1][0] = s;
+ m.m[0][1] = -s;
+ } else {
+ m.m[1][0] = -s;
+ m.m[0][1] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (z == 0.0f) {
+ // Rotate around the Y axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[2][2] = c;
+ if (y < 0.0f) {
+ m.m[2][0] = -s;
+ m.m[0][2] = s;
+ } else {
+ m.m[2][0] = s;
+ m.m[0][2] = -s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (y == 0.0f && z == 0.0f) {
+ // Rotate around the X axis.
+ m.setIdentity();
+ m.m[1][1] = c;
+ m.m[2][2] = c;
+ if (x < 0.0f) {
+ m.m[2][1] = s;
+ m.m[1][2] = -s;
+ } else {
+ m.m[2][1] = -s;
+ m.m[1][2] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ if (!quick) {
+ qreal len = x * x + y * y + z * z;
+ if (!qFuzzyIsNull(len - 1.0f) && !qFuzzyIsNull(len)) {
+ len = qSqrt(len);
+ x /= len;
+ y /= len;
+ z /= len;
+ }
+ ic = 1.0f - c;
+ m.m[0][0] = x * x * ic + c;
+ m.m[1][0] = x * y * ic - z * s;
+ m.m[2][0] = x * z * ic + y * s;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = y * x * ic + z * s;
+ m.m[1][1] = y * y * ic + c;
+ m.m[2][1] = y * z * ic - x * s;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = x * z * ic - y * s;
+ m.m[1][2] = y * z * ic + x * s;
+ m.m[2][2] = z * z * ic + c;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ }
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Multiples this matrix by another that rotates coordinates according
+ to a specified \a quaternion. The \a quaternion is assumed to have
+ been normalized. Returns this matrix.
+
+ \sa scale(), translate(), QQuaternion
+*/
+QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
+ QMatrix4x4 m(1);
+ float xx = quaternion.xp * quaternion.xp;
+ float xy = quaternion.xp * quaternion.yp;
+ float xz = quaternion.xp * quaternion.zp;
+ float xw = quaternion.xp * quaternion.wp;
+ float yy = quaternion.yp * quaternion.yp;
+ float yz = quaternion.yp * quaternion.zp;
+ float yw = quaternion.yp * quaternion.wp;
+ float zz = quaternion.zp * quaternion.zp;
+ float zw = quaternion.zp * quaternion.wp;
+ m.m[0][0] = 1.0f - 2 * (yy + zz);
+ m.m[1][0] = 2 * (xy - zw);
+ m.m[2][0] = 2 * (xz + yw);
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 2 * (xy + zw);
+ m.m[1][1] = 1.0f - 2 * (xx + zz);
+ m.m[2][1] = 2 * (yz - xw);
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 2 * (xz - yw);
+ m.m[1][2] = 2 * (yz + xw);
+ m.m[2][2] = 1.0f - 2 * (xx + yy);
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with boundaries specified by \a rect.
+ The near and far clipping planes will be -1 and 1 respectively.
+ Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(const QRect& rect)
+{
+ // Note: rect.right() and rect.bottom() subtract 1 in QRect,
+ // which gives the location of a pixel within the rectangle,
+ // instead of the extent of the rectangle. We want the extent.
+ // QRectF expresses the extent properly.
+ return ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with boundaries specified by \a rect.
+ The near and far clipping planes will be -1 and 1 respectively.
+ Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(const QRectF& rect)
+{
+ return ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
+}
+
+/*!
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with lower-left corner (\a left, \a bottom),
+ upper-right corner (\a right, \a top), and the specified \a nearPlane
+ and \a farPlane clipping planes. Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (left == right || bottom == top || nearPlane == farPlane)
+ return *this;
+
+ // Construct the projection.
+ qreal width = right - left;
+ qreal invheight = top - bottom;
+ qreal clip = farPlane - nearPlane;
+#ifndef QT_NO_VECTOR3D
+ if (clip == 2.0f && (nearPlane + farPlane) == 0.0f) {
+ // We can express this projection as a translate and scale
+ // which will be more efficient to modify with further
+ // transformations than producing a "General" matrix.
+ translate(QVector3D
+ (-(left + right) / width,
+ -(top + bottom) / invheight,
+ 0.0f, 1));
+ scale(QVector3D
+ (2.0f / width,
+ 2.0f / invheight,
+ -1.0f, 1));
+ return *this;
+ }
+#endif
+ QMatrix4x4 m(1);
+ m.m[0][0] = 2.0f / width;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = 0.0f;
+ m.m[3][0] = -(left + right) / width;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = 2.0f / invheight;
+ m.m[2][1] = 0.0f;
+ m.m[3][1] = -(top + bottom) / invheight;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = -2.0f / clip;
+ m.m[3][2] = -(nearPlane + farPlane) / clip;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+/*!
+ Multiplies this matrix by another that applies a perspective
+ frustum projection for a window with lower-left corner (\a left, \a bottom),
+ upper-right corner (\a right, \a top), and the specified \a nearPlane
+ and \a farPlane clipping planes. Returns this matrix.
+
+ \sa ortho(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (left == right || bottom == top || nearPlane == farPlane)
+ return *this;
+
+ // Construct the projection.
+ QMatrix4x4 m(1);
+ qreal width = right - left;
+ qreal invheight = top - bottom;
+ qreal clip = farPlane - nearPlane;
+ m.m[0][0] = 2.0f * nearPlane / width;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = (left + right) / width;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = 2.0f * nearPlane / invheight;
+ m.m[2][1] = (top + bottom) / invheight;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = -(nearPlane + farPlane) / clip;
+ m.m[3][2] = -2.0f * nearPlane * farPlane / clip;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = -1.0f;
+ m.m[3][3] = 0.0f;
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+/*!
+ Multiplies this matrix by another that applies a perspective
+ projection. The field of view will be \a angle degrees within
+ a window with a given \a aspect ratio. The projection will
+ have the specified \a nearPlane and \a farPlane clipping planes.
+ Returns this matrix.
+
+ \sa ortho(), frustum()
+*/
+QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (nearPlane == farPlane || aspect == 0.0f)
+ return *this;
+
+ // Construct the projection.
+ QMatrix4x4 m(1);
+ qreal radians = (angle / 2.0f) * M_PI / 180.0f;
+ qreal sine = qSin(radians);
+ if (sine == 0.0f)
+ return *this;
+ qreal cotan = qCos(radians) / sine;
+ qreal clip = farPlane - nearPlane;
+ m.m[0][0] = cotan / aspect;
+ m.m[1][0] = 0.0f;
+ m.m[2][0] = 0.0f;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 0.0f;
+ m.m[1][1] = cotan;
+ m.m[2][1] = 0.0f;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 0.0f;
+ m.m[1][2] = 0.0f;
+ m.m[2][2] = -(nearPlane + farPlane) / clip;
+ m.m[3][2] = -(2.0f * nearPlane * farPlane) / clip;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = -1.0f;
+ m.m[3][3] = 0.0f;
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiplies this matrix by another that applies an \a eye position
+ transformation. The \a center value indicates the center of the
+ view that the \a eye is looking at. The \a up value indicates
+ which direction should be considered up with respect to the \a eye.
+ Returns this matrix.
+*/
+QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
+{
+ QVector3D forward = (center - eye).normalized();
+ QVector3D side = QVector3D::crossProduct(forward, up).normalized();
+ QVector3D upVector = QVector3D::crossProduct(side, forward);
+
+ QMatrix4x4 m(1);
+
+ m.m[0][0] = side.xp;
+ m.m[1][0] = side.yp;
+ m.m[2][0] = side.zp;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = upVector.xp;
+ m.m[1][1] = upVector.yp;
+ m.m[2][1] = upVector.zp;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = -forward.xp;
+ m.m[1][2] = -forward.yp;
+ m.m[2][2] = -forward.zp;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+
+ *this *= m;
+ return translate(-eye);
+}
+
+#endif
+
+/*!
+ Flips between right-handed and left-handed coordinate systems
+ by multiplying the y and z co-ordinates by -1. This is normally
+ used to create a left-handed orthographic view without scaling
+ the viewport as ortho() does. Returns this matrix.
+
+ \sa ortho()
+*/
+QMatrix4x4& QMatrix4x4::flipCoordinates()
+{
+ if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[1][1] = -m[1][1];
+ m[2][2] = -m[2][2];
+ } else if (flagBits == Translation) {
+ m[1][1] = -m[1][1];
+ m[2][2] = -m[2][2];
+ flagBits |= Scale;
+ } else if (flagBits == Identity) {
+ m[1][1] = -1.0f;
+ m[2][2] = -1.0f;
+ flagBits = Scale;
+ } else {
+ m[1][0] = -m[1][0];
+ m[1][1] = -m[1][1];
+ m[1][2] = -m[1][2];
+ m[1][3] = -m[1][3];
+ m[2][0] = -m[2][0];
+ m[2][1] = -m[2][1];
+ m[2][2] = -m[2][2];
+ m[2][3] = -m[2][3];
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ Retrieves the 16 items in this matrix and writes them to \a values
+ in row-major order.
+*/
+void QMatrix4x4::toValueArray(qreal *values) const
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ values[row * 4 + col] = qreal(m[col][row]);
+}
+
+/*!
+ Returns the conventional Qt 2D affine transformation matrix that
+ corresponds to this matrix. It is assumed that this matrix
+ only contains 2D affine transformation elements.
+
+ \sa toTransform()
+*/
+QMatrix QMatrix4x4::toAffine() const
+{
+ return QMatrix(qreal(m[0][0]), qreal(m[0][1]),
+ qreal(m[1][0]), qreal(m[1][1]),
+ qreal(m[3][0]), qreal(m[3][1]));
+}
+
+/*!
+ Returns the conventional Qt 2D transformation matrix that
+ corresponds to this matrix. It is assumed that this matrix
+ only contains 2D transformation elements.
+
+ \sa toAffine()
+*/
+QTransform QMatrix4x4::toTransform() const
+{
+ return QTransform(qreal(m[0][0]), qreal(m[0][1]), qreal(m[0][3]),
+ qreal(m[1][0]), qreal(m[1][1]), qreal(m[1][3]),
+ qreal(m[3][0]), qreal(m[3][1]), qreal(m[3][3]));
+}
+
+/*!
+ \fn QPoint QMatrix4x4::map(const QPoint& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+/*!
+ \fn QPointF QMatrix4x4::map(const QPointF& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QVector3D QMatrix4x4::map(const QVector3D& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QVector4D QMatrix4x4::map(const QVector4D& point) const;
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#endif
+
+/*!
+ Maps \a rect by multiplying this matrix by the corners
+ of \a rect and then forming a new rectangle from the results.
+ The returned rectangle will be an ordinary 2D rectangle
+ with sides parallel to the horizontal and vertical axes.
+
+ \sa map()
+*/
+QRect QMatrix4x4::mapRect(const QRect& rect) const
+{
+ if (flagBits == (Translation | Scale) || flagBits == Scale) {
+ qreal x = rect.x() * m[0][0] + m[3][0];
+ qreal y = rect.y() * m[1][1] + m[3][1];
+ qreal w = rect.width() * m[0][0];
+ qreal h = rect.height() * m[1][1];
+ if (w < 0) {
+ w = -w;
+ x -= w;
+ }
+ if (h < 0) {
+ h = -h;
+ y -= h;
+ }
+ return QRect(qRound(x), qRound(y), qRound(w), qRound(h));
+ } else if (flagBits == Translation) {
+ return QRect(qRound(rect.x() + m[3][0]),
+ qRound(rect.y() + m[3][1]),
+ rect.width(), rect.height());
+ }
+
+ QPoint tl = map(rect.topLeft());
+ QPoint tr = map(QPoint(rect.x() + rect.width(), rect.y()));
+ QPoint bl = map(QPoint(rect.x(), rect.y() + rect.height()));
+ QPoint br = map(QPoint(rect.x() + rect.width(),
+ rect.y() + rect.height()));
+
+ int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRect(xmin, ymin, xmax - xmin, ymax - ymin);
+}
+
+/*!
+ Maps \a rect by multiplying this matrix by the corners
+ of \a rect and then forming a new rectangle from the results.
+ The returned rectangle will be an ordinary 2D rectangle
+ with sides parallel to the horizontal and vertical axes.
+
+ \sa map()
+*/
+QRectF QMatrix4x4::mapRect(const QRectF& rect) const
+{
+ if (flagBits == (Translation | Scale) || flagBits == Scale) {
+ qreal x = rect.x() * m[0][0] + m[3][0];
+ qreal y = rect.y() * m[1][1] + m[3][1];
+ qreal w = rect.width() * m[0][0];
+ qreal h = rect.height() * m[1][1];
+ if (w < 0) {
+ w = -w;
+ x -= w;
+ }
+ if (h < 0) {
+ h = -h;
+ y -= h;
+ }
+ return QRectF(x, y, w, h);
+ } else if (flagBits == Translation) {
+ return rect.translated(m[3][0], m[3][1]);
+ }
+
+ QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
+ QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
+
+ qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
+}
+
+/*!
+ \fn float *QMatrix4x4::data()
+
+ Returns a pointer to the raw data of this matrix. This is intended
+ for use with raw GL functions.
+
+ \sa constData(), inferSpecialType()
+*/
+
+/*!
+ \fn const float *QMatrix4x4::data() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const float *QMatrix4x4::constData() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is intended for use with raw GL functions.
+
+ \sa data()
+*/
+
+// Helper routine for inverting orthonormal matrices that consist
+// of just rotations and translations.
+QMatrix4x4 QMatrix4x4::orthonormalInverse() const
+{
+ QMatrix4x4 result(1); // The '1' says not to load identity
+
+ result.m[0][0] = m[0][0];
+ result.m[1][0] = m[0][1];
+ result.m[2][0] = m[0][2];
+
+ result.m[0][1] = m[1][0];
+ result.m[1][1] = m[1][1];
+ result.m[2][1] = m[1][2];
+
+ result.m[0][2] = m[2][0];
+ result.m[1][2] = m[2][1];
+ result.m[2][2] = m[2][2];
+
+ result.m[0][3] = 0.0f;
+ result.m[1][3] = 0.0f;
+ result.m[2][3] = 0.0f;
+
+ result.m[3][0] = -(result.m[0][0] * m[3][0] + result.m[1][0] * m[3][1] + result.m[2][0] * m[3][2]);
+ result.m[3][1] = -(result.m[0][1] * m[3][0] + result.m[1][1] * m[3][1] + result.m[2][1] * m[3][2]);
+ result.m[3][2] = -(result.m[0][2] * m[3][0] + result.m[1][2] * m[3][1] + result.m[2][2] * m[3][2]);
+ result.m[3][3] = 1.0f;
+
+ return result;
+}
+
+#ifndef QT_NO_VECTOR3D
+/*!
+ Decomposes the current rotation matrix into an \a axis of rotation plus
+ an \a angle. The result can be used to construct an equivalent rotation
+ matrix using glRotate(). It is assumed that the homogenous coordinate
+ is 1.0. The returned vector is guaranteed to be normalized.
+
+ \code
+ qreal angle;
+ QVector3D axis;
+
+ matrix.extractAxisAngle(angle, axis);
+ glRotate(angle, axis[0], axis[1], axis[2]);
+ \endcode
+
+ \sa rotate()
+*/
+void QMatrix4x4::extractAxisRotation(qreal &angle, QVector3D &axis) const
+{
+ // Orientation is dependent on the upper 3x3 matrix; subtract the
+ // homogeneous scaling element from the trace of the 4x4 matrix
+ float tr = m[0][0] + m[1][1] + m[2][2];
+ qreal cosa = qreal(0.5f * (tr - 1.0f));
+ angle = acos(cosa) * 180.0f / M_PI;
+
+ // Any axis will work if r is zero (means no rotation)
+ if (qFuzzyIsNull(angle)) {
+ axis.setX(1.0f);
+ axis.setY(0.0f);
+ axis.setZ(0.0f);
+ return;
+ }
+
+ if (angle < 180.0f) {
+ axis.xp = m[1][2] - m[2][1];
+ axis.yp = m[2][0] - m[0][2];
+ axis.zp = m[0][1] - m[1][0];
+ axis.normalize();
+ return;
+ }
+
+ // rads == PI
+ float tmp;
+
+ // r00 is maximum
+ if ((m[0][0] >= m[2][2]) && (m[0][0] >= m[1][1])) {
+ axis.xp = 0.5f * qSqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f);
+ tmp = 0.5f / axis.x();
+ axis.yp = m[1][0] * tmp;
+ axis.zp = m[2][0] * tmp;
+ }
+
+ // r11 is maximum
+ if ((m[1][1] >= m[2][2]) && (m[1][1] >= m[0][0])) {
+ axis.yp = 0.5f * qSqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f);
+ tmp = 0.5f / axis.y();
+ axis.xp = tmp * m[1][0];
+ axis.zp = tmp * m[2][1];
+ }
+
+ // r22 is maximum
+ if ((m[2][2] >= m[1][1]) && (m[2][2] >= m[0][0])) {
+ axis.zp = 0.5f * qSqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
+ tmp = 0.5f / axis.z();
+ axis.xp = m[2][0]*tmp;
+ axis.yp = m[2][1]*tmp;
+ }
+}
+
+/*!
+ If this is an orthonormal transformation matrix (e.g. only rotations and
+ translations have been applied to the matrix, no scaling, or shearing)
+ then the world translational component can be obtained by calling this function.
+
+ This is most useful for camera matrices, where the negation of this vector
+ is effectively the camera world coordinates.
+*/
+QVector3D QMatrix4x4::extractTranslation() const
+{
+ return QVector3D
+ (m[0][0] * m[3][0] + m[0][1] * m[3][1] + m[0][2] * m[3][2],
+ m[1][0] * m[3][0] + m[1][1] * m[3][1] + m[1][2] * m[3][2],
+ m[2][0] * m[3][0] + m[2][1] * m[3][1] + m[2][2] * m[3][2], 1);
+}
+#endif
+
+/*!
+ Infers the special type of this matrix from its current elements.
+
+ Some operations such as translate(), scale(), and rotate() can be
+ performed more efficiently if the matrix being modified is already
+ known to be the identity, a previous translate(), a previous
+ scale(), etc.
+
+ Normally the QMatrix4x4 class keeps track of this special type internally
+ as operations are performed. However, if the matrix is modified
+ directly with operator()() or data(), then QMatrix4x4 will lose track of
+ the special type and will revert to the safest but least efficient
+ operations thereafter.
+
+ By calling inferSpecialType() after directly modifying the matrix,
+ the programmer can force QMatrix4x4 to recover the special type if
+ the elements appear to conform to one of the known optimized types.
+
+ \sa operator()(), data(), translate()
+*/
+void QMatrix4x4::inferSpecialType()
+{
+ // If the last element is not 1, then it can never be special.
+ if (m[3][3] != 1.0f) {
+ flagBits = General;
+ return;
+ }
+
+ // If the upper three elements m12, m13, and m21 are not all zero,
+ // or the lower elements below the diagonal are not all zero, then
+ // the matrix can never be special.
+ if (m[1][0] != 0.0f || m[2][0] != 0.0f || m[2][1] != 0.0f) {
+ flagBits = General;
+ return;
+ }
+ if (m[0][1] != 0.0f || m[0][2] != 0.0f || m[0][3] != 0.0f ||
+ m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][3] != 0.0f) {
+ flagBits = General;
+ return;
+ }
+
+ // Determine what we have in the remaining regions of the matrix.
+ bool identityAlongDiagonal
+ = (m[0][0] == 1.0f && m[1][1] == 1.0f && m[2][2] == 1.0f);
+ bool translationPresent
+ = (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f);
+
+ // Now determine the special matrix type.
+ if (translationPresent && identityAlongDiagonal)
+ flagBits = Translation;
+ else if (translationPresent)
+ flagBits = (Translation | Scale);
+ else if (identityAlongDiagonal)
+ flagBits = Identity;
+ else
+ flagBits = Scale;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
+{
+ // Create a string that represents the matrix type.
+ QByteArray bits;
+ if ((m.flagBits & QMatrix4x4::Identity) != 0)
+ bits += "Identity,";
+ if ((m.flagBits & QMatrix4x4::General) != 0)
+ bits += "General,";
+ if ((m.flagBits & QMatrix4x4::Translation) != 0)
+ bits += "Translation,";
+ if ((m.flagBits & QMatrix4x4::Scale) != 0)
+ bits += "Scale,";
+ if ((m.flagBits & QMatrix4x4::Rotation) != 0)
+ bits += "Rotation,";
+ if (bits.size() > 0)
+ bits = bits.left(bits.size() - 1);
+
+ // Output in row-major order because it is more human-readable.
+ dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl
+ << qSetFieldWidth(10)
+ << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl
+ << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl
+ << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
+ << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
+ << qSetFieldWidth(0) << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
new file mode 100644
index 0000000..da1bcba
--- /dev/null
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -0,0 +1,998 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATRIX4X4_H
+#define QMATRIX4X4_H
+
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+#include <QtGui/qgenericmatrix.h>
+#include <QtCore/qrect.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_MATRIX4X4
+
+class QMatrix;
+class QTransform;
+
+class Q_GUI_EXPORT QMatrix4x4
+{
+public:
+ inline QMatrix4x4() { setIdentity(); }
+ explicit QMatrix4x4(const qreal *values);
+ inline QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14,
+ qreal m21, qreal m22, qreal m23, qreal m24,
+ qreal m31, qreal m32, qreal m33, qreal m34,
+ qreal m41, qreal m42, qreal m43, qreal m44);
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int N, int M>
+ explicit QMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix);
+#endif
+ QMatrix4x4(const float *values, int cols, int rows);
+ QMatrix4x4(const QTransform& transform);
+ QMatrix4x4(const QMatrix& matrix);
+
+ inline qreal operator()(int row, int column) const;
+ inline float& operator()(int row, int column);
+
+ inline QVector4D column(int index) const;
+ inline void setColumn(int index, const QVector4D& value);
+
+ inline QVector4D row(int index) const;
+ inline void setRow(int index, const QVector4D& value);
+
+ inline bool isIdentity() const;
+ inline void setIdentity();
+
+ inline void fill(qreal value);
+
+ qreal determinant() const;
+ QMatrix4x4 inverted(bool *invertible = 0) const;
+ QMatrix4x4 transposed() const;
+ QMatrix3x3 normalMatrix() const;
+
+ inline QMatrix4x4& operator+=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator-=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator*=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator*=(qreal factor);
+ QMatrix4x4& operator/=(qreal divisor);
+ inline bool operator==(const QMatrix4x4& other) const;
+ inline bool operator!=(const QMatrix4x4& other) const;
+
+ friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
+ friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
+ friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
+#ifndef QT_NO_VECTOR3D
+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
+#endif
+#ifndef QT_NO_VECTOR4D
+ friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
+ friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
+#endif
+ friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
+ friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
+ friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
+ friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
+ friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
+ friend QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix);
+ friend QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor);
+ friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
+
+#ifndef QT_NO_VECTOR3D
+ QMatrix4x4& scale(const QVector3D& vector);
+ QMatrix4x4& translate(const QVector3D& vector);
+ QMatrix4x4& rotate(qreal angle, const QVector3D& vector);
+#endif
+ QMatrix4x4& scale(qreal x, qreal y);
+ QMatrix4x4& scale(qreal x, qreal y, qreal z);
+ QMatrix4x4& scale(qreal factor);
+ QMatrix4x4& translate(qreal x, qreal y);
+ QMatrix4x4& translate(qreal x, qreal y, qreal z);
+ QMatrix4x4& rotate(qreal angle, qreal x, qreal y, qreal z = 0.0f);
+#ifndef QT_NO_QUATERNION
+ QMatrix4x4& rotate(const QQuaternion& quaternion);
+#endif
+
+#ifndef QT_NO_VECTOR3D
+ void extractAxisRotation(qreal &angle, QVector3D &axis) const;
+ QVector3D extractTranslation() const;
+#endif
+
+ QMatrix4x4& ortho(const QRect& rect);
+ QMatrix4x4& ortho(const QRectF& rect);
+ QMatrix4x4& ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
+ QMatrix4x4& frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
+ QMatrix4x4& perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane);
+#ifndef QT_NO_VECTOR3D
+ QMatrix4x4& lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
+#endif
+ QMatrix4x4& flipCoordinates();
+
+ void toValueArray(qreal *values) const;
+
+ QMatrix toAffine() const;
+ QTransform toTransform() const;
+
+ QPoint map(const QPoint& point) const;
+ QPointF map(const QPointF& point) const;
+#ifndef QT_NO_VECTOR3D
+ QVector3D map(const QVector3D& point) const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D map(const QVector4D& point) const;
+#endif
+ QRect mapRect(const QRect& rect) const;
+ QRectF mapRect(const QRectF& rect) const;
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int N, int M>
+ QGenericMatrix<N, M, qreal, float> toGenericMatrix() const;
+#endif
+
+ inline float *data();
+ inline const float *data() const { return m[0]; }
+ inline const float *constData() const { return m[0]; }
+
+ void inferSpecialType();
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
+#endif
+
+private:
+ float m[4][4]; // Column-major order to match OpenGL.
+ int flagBits; // Flag bits from the enum below.
+
+ enum {
+ Identity = 0x0001, // Identity matrix
+ General = 0x0002, // General matrix, unknown contents
+ Translation = 0x0004, // Contains a simple translation
+ Scale = 0x0008, // Contains a simple scale
+ Rotation = 0x0010 // Contains a simple rotation
+ };
+
+ // Construct without initializing identity matrix.
+ QMatrix4x4(int) { flagBits = General; }
+
+ QMatrix4x4 orthonormalInverse() const;
+};
+
+inline QMatrix4x4::QMatrix4x4
+ (qreal m11, qreal m12, qreal m13, qreal m14,
+ qreal m21, qreal m22, qreal m23, qreal m24,
+ qreal m31, qreal m32, qreal m33, qreal m34,
+ qreal m41, qreal m42, qreal m43, qreal m44)
+{
+ m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
+ m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
+ m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
+ m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
+ flagBits = General;
+}
+
+#if !defined(QT_NO_MEMBER_TEMPLATES)
+
+template <int N, int M>
+Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
+ (const QGenericMatrix<N, M, qreal, float>& matrix)
+{
+ const float *values = matrix.constData();
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col < N && row < M)
+ m[col][row] = values[col * M + row];
+ else if (col == row)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+ flagBits = General;
+}
+
+template <int N, int M>
+QGenericMatrix<N, M, qreal, float> QMatrix4x4::toGenericMatrix() const
+{
+ QGenericMatrix<N, M, qreal, float> result;
+ float *values = result.data();
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (col < 4 && row < 4)
+ values[col * M + row] = m[col][row];
+ else if (col == row)
+ values[col * M + row] = 1.0f;
+ else
+ values[col * M + row] = 0.0f;
+ }
+ }
+ return result;
+}
+
+#endif
+
+inline qreal QMatrix4x4::operator()(int row, int column) const
+{
+ Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
+ return qreal(m[column][row]);
+}
+
+inline float& QMatrix4x4::operator()(int row, int column)
+{
+ Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
+ flagBits = General;
+ return m[column][row];
+}
+
+inline QVector4D QMatrix4x4::column(int index) const
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3], 1);
+}
+
+inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ m[index][0] = value.xp;
+ m[index][1] = value.yp;
+ m[index][2] = value.zp;
+ m[index][3] = value.wp;
+ flagBits = General;
+}
+
+inline QVector4D QMatrix4x4::row(int index) const
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index], 1);
+}
+
+inline void QMatrix4x4::setRow(int index, const QVector4D& value)
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ m[0][index] = value.xp;
+ m[1][index] = value.yp;
+ m[2][index] = value.zp;
+ m[3][index] = value.wp;
+ flagBits = General;
+}
+
+Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
+
+inline bool QMatrix4x4::isIdentity() const
+{
+ if (flagBits == Identity)
+ return true;
+ if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
+ return false;
+ if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
+ return false;
+ if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
+ return false;
+ if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
+ return false;
+ if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
+ return false;
+ return (m[3][3] == 1.0f);
+}
+
+inline void QMatrix4x4::setIdentity()
+{
+ m[0][0] = 1.0f;
+ m[0][1] = 0.0f;
+ m[0][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][0] = 0.0f;
+ m[1][1] = 1.0f;
+ m[1][2] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = 0.0f;
+ m[3][1] = 0.0f;
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ flagBits = Identity;
+}
+
+inline void QMatrix4x4::fill(qreal value)
+{
+ m[0][0] = value;
+ m[0][1] = value;
+ m[0][2] = value;
+ m[0][3] = value;
+ m[1][0] = value;
+ m[1][1] = value;
+ m[1][2] = value;
+ m[1][3] = value;
+ m[2][0] = value;
+ m[2][1] = value;
+ m[2][2] = value;
+ m[2][3] = value;
+ m[3][0] = value;
+ m[3][1] = value;
+ m[3][2] = value;
+ m[3][3] = value;
+ flagBits = General;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
+{
+ m[0][0] += other.m[0][0];
+ m[0][1] += other.m[0][1];
+ m[0][2] += other.m[0][2];
+ m[0][3] += other.m[0][3];
+ m[1][0] += other.m[1][0];
+ m[1][1] += other.m[1][1];
+ m[1][2] += other.m[1][2];
+ m[1][3] += other.m[1][3];
+ m[2][0] += other.m[2][0];
+ m[2][1] += other.m[2][1];
+ m[2][2] += other.m[2][2];
+ m[2][3] += other.m[2][3];
+ m[3][0] += other.m[3][0];
+ m[3][1] += other.m[3][1];
+ m[3][2] += other.m[3][2];
+ m[3][3] += other.m[3][3];
+ flagBits = General;
+ return *this;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
+{
+ m[0][0] -= other.m[0][0];
+ m[0][1] -= other.m[0][1];
+ m[0][2] -= other.m[0][2];
+ m[0][3] -= other.m[0][3];
+ m[1][0] -= other.m[1][0];
+ m[1][1] -= other.m[1][1];
+ m[1][2] -= other.m[1][2];
+ m[1][3] -= other.m[1][3];
+ m[2][0] -= other.m[2][0];
+ m[2][1] -= other.m[2][1];
+ m[2][2] -= other.m[2][2];
+ m[2][3] -= other.m[2][3];
+ m[3][0] -= other.m[3][0];
+ m[3][1] -= other.m[3][1];
+ m[3][2] -= other.m[3][2];
+ m[3][3] -= other.m[3][3];
+ flagBits = General;
+ return *this;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
+{
+ if (flagBits == Identity) {
+ *this = other;
+ return *this;
+ } else if (other.flagBits == Identity) {
+ return *this;
+ } else {
+ *this = *this * other;
+ return *this;
+ }
+}
+
+inline QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
+{
+ m[0][0] *= factor;
+ m[0][1] *= factor;
+ m[0][2] *= factor;
+ m[0][3] *= factor;
+ m[1][0] *= factor;
+ m[1][1] *= factor;
+ m[1][2] *= factor;
+ m[1][3] *= factor;
+ m[2][0] *= factor;
+ m[2][1] *= factor;
+ m[2][2] *= factor;
+ m[2][3] *= factor;
+ m[3][0] *= factor;
+ m[3][1] *= factor;
+ m[3][2] *= factor;
+ m[3][3] *= factor;
+ flagBits = General;
+ return *this;
+}
+
+inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
+{
+ return m[0][0] == other.m[0][0] &&
+ m[0][1] == other.m[0][1] &&
+ m[0][2] == other.m[0][2] &&
+ m[0][3] == other.m[0][3] &&
+ m[1][0] == other.m[1][0] &&
+ m[1][1] == other.m[1][1] &&
+ m[1][2] == other.m[1][2] &&
+ m[1][3] == other.m[1][3] &&
+ m[2][0] == other.m[2][0] &&
+ m[2][1] == other.m[2][1] &&
+ m[2][2] == other.m[2][2] &&
+ m[2][3] == other.m[2][3] &&
+ m[3][0] == other.m[3][0] &&
+ m[3][1] == other.m[3][1] &&
+ m[3][2] == other.m[3][2] &&
+ m[3][3] == other.m[3][3];
+}
+
+inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
+{
+ return m[0][0] != other.m[0][0] ||
+ m[0][1] != other.m[0][1] ||
+ m[0][2] != other.m[0][2] ||
+ m[0][3] != other.m[0][3] ||
+ m[1][0] != other.m[1][0] ||
+ m[1][1] != other.m[1][1] ||
+ m[1][2] != other.m[1][2] ||
+ m[1][3] != other.m[1][3] ||
+ m[2][0] != other.m[2][0] ||
+ m[2][1] != other.m[2][1] ||
+ m[2][2] != other.m[2][2] ||
+ m[2][3] != other.m[2][3] ||
+ m[3][0] != other.m[3][0] ||
+ m[3][1] != other.m[3][1] ||
+ m[3][2] != other.m[3][2] ||
+ m[3][3] != other.m[3][3];
+}
+
+inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] + m2.m[0][0];
+ m.m[0][1] = m1.m[0][1] + m2.m[0][1];
+ m.m[0][2] = m1.m[0][2] + m2.m[0][2];
+ m.m[0][3] = m1.m[0][3] + m2.m[0][3];
+ m.m[1][0] = m1.m[1][0] + m2.m[1][0];
+ m.m[1][1] = m1.m[1][1] + m2.m[1][1];
+ m.m[1][2] = m1.m[1][2] + m2.m[1][2];
+ m.m[1][3] = m1.m[1][3] + m2.m[1][3];
+ m.m[2][0] = m1.m[2][0] + m2.m[2][0];
+ m.m[2][1] = m1.m[2][1] + m2.m[2][1];
+ m.m[2][2] = m1.m[2][2] + m2.m[2][2];
+ m.m[2][3] = m1.m[2][3] + m2.m[2][3];
+ m.m[3][0] = m1.m[3][0] + m2.m[3][0];
+ m.m[3][1] = m1.m[3][1] + m2.m[3][1];
+ m.m[3][2] = m1.m[3][2] + m2.m[3][2];
+ m.m[3][3] = m1.m[3][3] + m2.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] - m2.m[0][0];
+ m.m[0][1] = m1.m[0][1] - m2.m[0][1];
+ m.m[0][2] = m1.m[0][2] - m2.m[0][2];
+ m.m[0][3] = m1.m[0][3] - m2.m[0][3];
+ m.m[1][0] = m1.m[1][0] - m2.m[1][0];
+ m.m[1][1] = m1.m[1][1] - m2.m[1][1];
+ m.m[1][2] = m1.m[1][2] - m2.m[1][2];
+ m.m[1][3] = m1.m[1][3] - m2.m[1][3];
+ m.m[2][0] = m1.m[2][0] - m2.m[2][0];
+ m.m[2][1] = m1.m[2][1] - m2.m[2][1];
+ m.m[2][2] = m1.m[2][2] - m2.m[2][2];
+ m.m[2][3] = m1.m[2][3] - m2.m[2][3];
+ m.m[3][0] = m1.m[3][0] - m2.m[3][0];
+ m.m[3][1] = m1.m[3][1] - m2.m[3][1];
+ m.m[3][2] = m1.m[3][2] - m2.m[3][2];
+ m.m[3][3] = m1.m[3][3] - m2.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ if (m1.flagBits == QMatrix4x4::Identity)
+ return m2;
+ else if (m2.flagBits == QMatrix4x4::Identity)
+ return m1;
+
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] * m2.m[0][0] +
+ m1.m[1][0] * m2.m[0][1] +
+ m1.m[2][0] * m2.m[0][2] +
+ m1.m[3][0] * m2.m[0][3];
+ m.m[0][1] = m1.m[0][1] * m2.m[0][0] +
+ m1.m[1][1] * m2.m[0][1] +
+ m1.m[2][1] * m2.m[0][2] +
+ m1.m[3][1] * m2.m[0][3];
+ m.m[0][2] = m1.m[0][2] * m2.m[0][0] +
+ m1.m[1][2] * m2.m[0][1] +
+ m1.m[2][2] * m2.m[0][2] +
+ m1.m[3][2] * m2.m[0][3];
+ m.m[0][3] = m1.m[0][3] * m2.m[0][0] +
+ m1.m[1][3] * m2.m[0][1] +
+ m1.m[2][3] * m2.m[0][2] +
+ m1.m[3][3] * m2.m[0][3];
+ m.m[1][0] = m1.m[0][0] * m2.m[1][0] +
+ m1.m[1][0] * m2.m[1][1] +
+ m1.m[2][0] * m2.m[1][2] +
+ m1.m[3][0] * m2.m[1][3];
+ m.m[1][1] = m1.m[0][1] * m2.m[1][0] +
+ m1.m[1][1] * m2.m[1][1] +
+ m1.m[2][1] * m2.m[1][2] +
+ m1.m[3][1] * m2.m[1][3];
+ m.m[1][2] = m1.m[0][2] * m2.m[1][0] +
+ m1.m[1][2] * m2.m[1][1] +
+ m1.m[2][2] * m2.m[1][2] +
+ m1.m[3][2] * m2.m[1][3];
+ m.m[1][3] = m1.m[0][3] * m2.m[1][0] +
+ m1.m[1][3] * m2.m[1][1] +
+ m1.m[2][3] * m2.m[1][2] +
+ m1.m[3][3] * m2.m[1][3];
+ m.m[2][0] = m1.m[0][0] * m2.m[2][0] +
+ m1.m[1][0] * m2.m[2][1] +
+ m1.m[2][0] * m2.m[2][2] +
+ m1.m[3][0] * m2.m[2][3];
+ m.m[2][1] = m1.m[0][1] * m2.m[2][0] +
+ m1.m[1][1] * m2.m[2][1] +
+ m1.m[2][1] * m2.m[2][2] +
+ m1.m[3][1] * m2.m[2][3];
+ m.m[2][2] = m1.m[0][2] * m2.m[2][0] +
+ m1.m[1][2] * m2.m[2][1] +
+ m1.m[2][2] * m2.m[2][2] +
+ m1.m[3][2] * m2.m[2][3];
+ m.m[2][3] = m1.m[0][3] * m2.m[2][0] +
+ m1.m[1][3] * m2.m[2][1] +
+ m1.m[2][3] * m2.m[2][2] +
+ m1.m[3][3] * m2.m[2][3];
+ m.m[3][0] = m1.m[0][0] * m2.m[3][0] +
+ m1.m[1][0] * m2.m[3][1] +
+ m1.m[2][0] * m2.m[3][2] +
+ m1.m[3][0] * m2.m[3][3];
+ m.m[3][1] = m1.m[0][1] * m2.m[3][0] +
+ m1.m[1][1] * m2.m[3][1] +
+ m1.m[2][1] * m2.m[3][2] +
+ m1.m[3][1] * m2.m[3][3];
+ m.m[3][2] = m1.m[0][2] * m2.m[3][0] +
+ m1.m[1][2] * m2.m[3][1] +
+ m1.m[2][2] * m2.m[3][2] +
+ m1.m[3][2] * m2.m[3][3];
+ m.m[3][3] = m1.m[0][3] * m2.m[3][0] +
+ m1.m[1][3] * m2.m[3][1] +
+ m1.m[2][3] * m2.m[3][2] +
+ m1.m[3][3] * m2.m[3][3];
+ return m;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
+{
+ float x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[0][1] +
+ vector.zp * matrix.m[0][2] +
+ matrix.m[0][3];
+ y = vector.xp * matrix.m[1][0] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[1][2] +
+ matrix.m[1][3];
+ z = vector.xp * matrix.m[2][0] +
+ vector.yp * matrix.m[2][1] +
+ vector.zp * matrix.m[2][2] +
+ matrix.m[2][3];
+ w = vector.xp * matrix.m[3][0] +
+ vector.yp * matrix.m[3][1] +
+ vector.zp * matrix.m[3][2] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QVector3D(x, y, z, 1);
+ else
+ return QVector3D(x / w, y / w, z / w, 1);
+}
+
+inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
+{
+ float x, y, z, w;
+ if (matrix.flagBits == QMatrix4x4::Identity) {
+ return vector;
+ } else if (matrix.flagBits == QMatrix4x4::Translation) {
+ return QVector3D(vector.xp + matrix.m[3][0],
+ vector.yp + matrix.m[3][1],
+ vector.zp + matrix.m[3][2], 1);
+ } else if (matrix.flagBits ==
+ (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
+ return QVector3D(vector.xp * matrix.m[0][0] + matrix.m[3][0],
+ vector.yp * matrix.m[1][1] + matrix.m[3][1],
+ vector.zp * matrix.m[2][2] + matrix.m[3][2], 1);
+ } else if (matrix.flagBits == QMatrix4x4::Scale) {
+ return QVector3D(vector.xp * matrix.m[0][0],
+ vector.yp * matrix.m[1][1],
+ vector.zp * matrix.m[2][2], 1);
+ } else {
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[1][0] +
+ vector.zp * matrix.m[2][0] +
+ matrix.m[3][0];
+ y = vector.xp * matrix.m[0][1] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[2][1] +
+ matrix.m[3][1];
+ z = vector.xp * matrix.m[0][2] +
+ vector.yp * matrix.m[1][2] +
+ vector.zp * matrix.m[2][2] +
+ matrix.m[3][2];
+ w = vector.xp * matrix.m[0][3] +
+ vector.yp * matrix.m[1][3] +
+ vector.zp * matrix.m[2][3] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QVector3D(x, y, z, 1);
+ else
+ return QVector3D(x / w, y / w, z / w, 1);
+ }
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
+{
+ float x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[0][1] +
+ vector.zp * matrix.m[0][2] +
+ vector.wp * matrix.m[0][3];
+ y = vector.xp * matrix.m[1][0] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[1][2] +
+ vector.wp * matrix.m[1][3];
+ z = vector.xp * matrix.m[2][0] +
+ vector.yp * matrix.m[2][1] +
+ vector.zp * matrix.m[2][2] +
+ vector.wp * matrix.m[2][3];
+ w = vector.xp * matrix.m[3][0] +
+ vector.yp * matrix.m[3][1] +
+ vector.zp * matrix.m[3][2] +
+ vector.wp * matrix.m[3][3];
+ return QVector4D(x, y, z, w, 1);
+}
+
+inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
+{
+ float x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[1][0] +
+ vector.zp * matrix.m[2][0] +
+ vector.wp * matrix.m[3][0];
+ y = vector.xp * matrix.m[0][1] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[2][1] +
+ vector.wp * matrix.m[3][1];
+ z = vector.xp * matrix.m[0][2] +
+ vector.yp * matrix.m[1][2] +
+ vector.zp * matrix.m[2][2] +
+ vector.wp * matrix.m[3][2];
+ w = vector.xp * matrix.m[0][3] +
+ vector.yp * matrix.m[1][3] +
+ vector.zp * matrix.m[2][3] +
+ vector.wp * matrix.m[3][3];
+ return QVector4D(x, y, z, w, 1);
+}
+
+#endif
+
+inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[0][1] +
+ matrix.m[0][3];
+ y = xin * matrix.m[1][0] +
+ yin * matrix.m[1][1] +
+ matrix.m[1][3];
+ w = xin * matrix.m[3][0] +
+ yin * matrix.m[3][1] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QPoint(qRound(x), qRound(y));
+ else
+ return QPoint(qRound(x / w), qRound(y / w));
+}
+
+inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[0][1] +
+ matrix.m[0][3];
+ y = xin * matrix.m[1][0] +
+ yin * matrix.m[1][1] +
+ matrix.m[1][3];
+ w = xin * matrix.m[3][0] +
+ yin * matrix.m[3][1] +
+ matrix.m[3][3];
+ if (w == 1.0f) {
+ return QPointF(qreal(x), qreal(y));
+ } else {
+ return QPointF(qreal(x / w), qreal(y / w));
+ }
+}
+
+inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ if (matrix.flagBits == QMatrix4x4::Identity) {
+ return point;
+ } else if (matrix.flagBits == QMatrix4x4::Translation) {
+ return QPoint(qRound(xin + matrix.m[3][0]),
+ qRound(yin + matrix.m[3][1]));
+ } else if (matrix.flagBits ==
+ (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
+ return QPoint(qRound(xin * matrix.m[0][0] + matrix.m[3][0]),
+ qRound(yin * matrix.m[1][1] + matrix.m[3][1]));
+ } else if (matrix.flagBits == QMatrix4x4::Scale) {
+ return QPoint(qRound(xin * matrix.m[0][0]),
+ qRound(yin * matrix.m[1][1]));
+ } else {
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[1][0] +
+ matrix.m[3][0];
+ y = xin * matrix.m[0][1] +
+ yin * matrix.m[1][1] +
+ matrix.m[3][1];
+ w = xin * matrix.m[0][3] +
+ yin * matrix.m[1][3] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QPoint(qRound(x), qRound(y));
+ else
+ return QPoint(qRound(x / w), qRound(y / w));
+ }
+}
+
+inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
+{
+ float xin, yin;
+ float x, y, w;
+ xin = point.x();
+ yin = point.y();
+ if (matrix.flagBits == QMatrix4x4::Identity) {
+ return point;
+ } else if (matrix.flagBits == QMatrix4x4::Translation) {
+ return QPointF(xin + matrix.m[3][0],
+ yin + matrix.m[3][1]);
+ } else if (matrix.flagBits ==
+ (QMatrix4x4::Translation | QMatrix4x4::Scale)) {
+ return QPointF(xin * matrix.m[0][0] + matrix.m[3][0],
+ yin * matrix.m[1][1] + matrix.m[3][1]);
+ } else if (matrix.flagBits == QMatrix4x4::Scale) {
+ return QPointF(xin * matrix.m[0][0],
+ yin * matrix.m[1][1]);
+ } else {
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[1][0] +
+ matrix.m[3][0];
+ y = xin * matrix.m[0][1] +
+ yin * matrix.m[1][1] +
+ matrix.m[3][1];
+ w = xin * matrix.m[0][3] +
+ yin * matrix.m[1][3] +
+ matrix.m[3][3];
+ if (w == 1.0f) {
+ return QPointF(qreal(x), qreal(y));
+ } else {
+ return QPointF(qreal(x / w), qreal(y / w));
+ }
+ }
+}
+
+inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = -matrix.m[0][0];
+ m.m[0][1] = -matrix.m[0][1];
+ m.m[0][2] = -matrix.m[0][2];
+ m.m[0][3] = -matrix.m[0][3];
+ m.m[1][0] = -matrix.m[1][0];
+ m.m[1][1] = -matrix.m[1][1];
+ m.m[1][2] = -matrix.m[1][2];
+ m.m[1][3] = -matrix.m[1][3];
+ m.m[2][0] = -matrix.m[2][0];
+ m.m[2][1] = -matrix.m[2][1];
+ m.m[2][2] = -matrix.m[2][2];
+ m.m[2][3] = -matrix.m[2][3];
+ m.m[3][0] = -matrix.m[3][0];
+ m.m[3][1] = -matrix.m[3][1];
+ m.m[3][2] = -matrix.m[3][2];
+ m.m[3][3] = -matrix.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = matrix.m[0][0] * factor;
+ m.m[0][1] = matrix.m[0][1] * factor;
+ m.m[0][2] = matrix.m[0][2] * factor;
+ m.m[0][3] = matrix.m[0][3] * factor;
+ m.m[1][0] = matrix.m[1][0] * factor;
+ m.m[1][1] = matrix.m[1][1] * factor;
+ m.m[1][2] = matrix.m[1][2] * factor;
+ m.m[1][3] = matrix.m[1][3] * factor;
+ m.m[2][0] = matrix.m[2][0] * factor;
+ m.m[2][1] = matrix.m[2][1] * factor;
+ m.m[2][2] = matrix.m[2][2] * factor;
+ m.m[2][3] = matrix.m[2][3] * factor;
+ m.m[3][0] = matrix.m[3][0] * factor;
+ m.m[3][1] = matrix.m[3][1] * factor;
+ m.m[3][2] = matrix.m[3][2] * factor;
+ m.m[3][3] = matrix.m[3][3] * factor;
+ return m;
+}
+
+inline QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = matrix.m[0][0] * factor;
+ m.m[0][1] = matrix.m[0][1] * factor;
+ m.m[0][2] = matrix.m[0][2] * factor;
+ m.m[0][3] = matrix.m[0][3] * factor;
+ m.m[1][0] = matrix.m[1][0] * factor;
+ m.m[1][1] = matrix.m[1][1] * factor;
+ m.m[1][2] = matrix.m[1][2] * factor;
+ m.m[1][3] = matrix.m[1][3] * factor;
+ m.m[2][0] = matrix.m[2][0] * factor;
+ m.m[2][1] = matrix.m[2][1] * factor;
+ m.m[2][2] = matrix.m[2][2] * factor;
+ m.m[2][3] = matrix.m[2][3] * factor;
+ m.m[3][0] = matrix.m[3][0] * factor;
+ m.m[3][1] = matrix.m[3][1] * factor;
+ m.m[3][2] = matrix.m[3][2] * factor;
+ m.m[3][3] = matrix.m[3][3] * factor;
+ return m;
+}
+
+inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
+ qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
+ qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
+ qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
+ qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
+ qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
+ qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
+ qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
+ qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
+ qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
+ qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
+ qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
+ qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
+ qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
+ qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
+ qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
+}
+
+inline QPoint QMatrix4x4::map(const QPoint& point) const
+{
+ return *this * point;
+}
+
+inline QPointF QMatrix4x4::map(const QPointF& point) const
+{
+ return *this * point;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QVector3D QMatrix4x4::map(const QVector3D& point) const
+{
+ return *this * point;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+inline QVector4D QMatrix4x4::map(const QVector4D& point) const
+{
+ return *this * point;
+}
+
+#endif
+
+inline float *QMatrix4x4::data()
+{
+ // We have to assume that the caller will modify the matrix elements,
+ // so we flip it over to "General" mode.
+ flagBits = General;
+ return m[0];
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
+#endif
+
+template <int N, int M>
+QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, float>& matrix)
+{
+ return QMatrix4x4(matrix.constData(), N, M);
+}
+
+template <int N, int M>
+QGenericMatrix<N, M, qreal, float> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+{
+ QGenericMatrix<N, M, qreal, float> result;
+ const float *m = matrix.constData();
+ float *values = result.data();
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (col < 4 && row < 4)
+ values[col * M + row] = m[col * 4 + row];
+ else if (col == row)
+ values[col * M + row] = 1.0f;
+ else
+ values[col * M + row] = 0.0f;
+ }
+ }
+ return result;
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_MATRIX4X4
+Q_DECLARE_METATYPE(QMatrix4x4)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
new file mode 100644
index 0000000..03f626a
--- /dev/null
+++ b/src/gui/math3d/qquaternion.cpp
@@ -0,0 +1,584 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qquaternion.h"
+#include <QtCore/qmath.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QUATERNION
+
+/*!
+ \class QQuaternion
+ \brief The QQuaternion class represents a quaternion consisting of a vector and scalar.
+ \since 4.6
+
+ Quaternions are used to represent rotations in 3D space, and
+ consist of a 3D rotation axis specified by the x, y, and z
+ coordinates, and a scalar representing the rotation angle.
+
+ The components of a quaternion are stored internally using the most
+ efficient representation for the GL rendering engine, which will be
+ either floating-point or fixed-point.
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion()
+
+ Constructs an identity quaternion, i.e. with coordinates (1, 0, 0, 0).
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos)
+
+ Constructs a quaternion with the vector (\a xpos, \a ypos, \a zpos)
+ and \a scalar.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QQuaternion::QQuaternion(qreal scalar, const QVector3D& vector)
+
+ Constructs a quaternion vector from the specified \a vector and
+ \a scalar.
+
+ \sa vector(), scalar()
+*/
+
+/*!
+ \fn QVector3D QQuaternion::vector() const
+
+ Returns the vector component of this quaternion.
+
+ \sa setVector(), scalar()
+*/
+
+/*!
+ \fn void QQuaternion::setVector(const QVector3D& vector)
+
+ Sets the vector component of this quaternion to \a vector.
+
+ \sa vector(), setScalar()
+*/
+
+#endif
+
+/*!
+ \fn void QQuaternion::setVector(qreal x, qreal y, qreal z)
+
+ Sets the vector component of this quaternion to (\a x, \a y, \a z).
+
+ \sa vector(), setScalar()
+*/
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QQuaternion::QQuaternion(const QVector4D& vector)
+
+ Constructs a quaternion from the components of \a vector.
+*/
+
+/*!
+ \fn QVector4D QQuaternion::toVector4D() const
+
+ Returns this quaternion as a 4D vector.
+*/
+
+#endif
+
+/*!
+ \fn bool QQuaternion::isNull() const
+
+ Returns true if the x, y, z, and scalar components of this
+ quaternion are set to 0.0; otherwise returns false.
+*/
+
+/*!
+ \fn bool QQuaternion::isIdentity() const
+
+ Returns true if the x, y, and z components of this
+ quaternion are set to 0.0, and the scalar component is set
+ to 1.0; otherwise returns false.
+*/
+
+/*!
+ \fn qreal QQuaternion::x() const
+
+ Returns the x coordinate of this quaternion's vector.
+
+ \sa setX(), y(), z(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::y() const
+
+ Returns the y coordinate of this quaternion's vector.
+
+ \sa setY(), x(), z(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::z() const
+
+ Returns the z coordinate of this quaternion's vector.
+
+ \sa setZ(), x(), y(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::scalar() const
+
+ Returns the scalar component of this quaternion.
+
+ \sa setScalar(), x(), y(), z()
+*/
+
+/*!
+ \fn void QQuaternion::setX(qreal x)
+
+ Sets the x coordinate of this quaternion's vector to the given
+ \a x coordinate.
+
+ \sa x(), setY(), setZ(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setY(qreal y)
+
+ Sets the y coordinate of this quaternion's vector to the given
+ \a y coordinate.
+
+ \sa y(), setX(), setZ(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setZ(qreal z)
+
+ Sets the z coordinate of this quaternion's vector to the given
+ \a z coordinate.
+
+ \sa z(), setX(), setY(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setScalar(qreal scalar)
+
+ Sets the scalar component of this quaternion to \a scalar.
+
+ \sa scalar(), setX(), setY(), setZ()
+*/
+
+/*!
+ Returns the length of the quaternion. This is also called the "norm".
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QQuaternion::length() const
+{
+ return qSqrt(xp * xp + yp * yp + zp * zp + wp * wp);
+}
+
+/*!
+ Returns the squared length of the quaternion.
+
+ \sa length()
+*/
+qreal QQuaternion::lengthSquared() const
+{
+ return xp * xp + yp * yp + zp * zp + wp * wp;
+}
+
+/*!
+ Returns the normalized unit form of this quaternion.
+
+ If this quaternion is null, then a null quaternion is returned.
+ If the length of the quaternion is very close to 1, then the quaternion
+ will be returned as-is. Otherwise the normalized form of the
+ quaternion of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QQuaternion QQuaternion::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+/*!
+ Normalizes the currect quaternion in place. Nothing happens if this
+ is a null quaternion or the length of the quaternion is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QQuaternion::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+ wp /= len;
+}
+
+/*!
+ \fn QQuaternion QQuaternion::conjugate() const
+
+ Returns the conjugate of this quaternion, which is
+ (-x, -y, -z, scalar).
+*/
+
+/*!
+ Rotates \a vector with this quaternion to produce a new vector
+ in 3D space. The following code:
+
+ \code
+ QVector3D result = q.rotateVector(vector);
+ \endcode
+
+ is equivalent to the following:
+
+ \code
+ QVector3D result = (q * QQuaternion(0, vector) * q.conjugate()).vector();
+ \endcode
+*/
+QVector3D QQuaternion::rotateVector(const QVector3D& vector) const
+{
+ return (*this * QQuaternion(0, vector) * conjugate()).vector();
+}
+
+/*!
+ \fn QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+
+ Adds the given \a quaternion to this quaternion and returns a reference to
+ this quaternion.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+
+ Subtracts the given \a quaternion from this quaternion and returns a
+ reference to this quaternion.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator*=(qreal factor)
+
+ Multiplies this quaternion's components by the given \a factor, and
+ returns a reference to this quaternion.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+
+ Multiplies this quaternion by \a quaternion and returns a reference
+ to this quaternion.
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator/=(qreal divisor)
+
+ Divides this quaternion's components by the given \a divisor, and
+ returns a reference to this quaternion.
+
+ \sa operator*=()
+*/
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Creates a normalized quaternion that corresponds to rotating through
+ \a angle degrees about the specified 3D \a axis.
+*/
+QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, qreal angle)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
+ // We normalize the result just in case the values are close
+ // to zero, as suggested in the above FAQ.
+ qreal a = (angle / 2.0f) * M_PI / 180.0f;
+ qreal s = qSin(a);
+ qreal c = qCos(a);
+ QVector3D ax = axis.normalized();
+ return QQuaternion(c, ax.xp * s, ax.yp * s, ax.zp * s, 1).normalized();
+}
+
+#endif
+
+/*!
+ Creates a normalized quaternion that corresponds to rotating through
+ \a angle degrees about the 3D axis (\a x, \a y, \a z).
+*/
+QQuaternion QQuaternion::fromAxisAndAngle
+ (qreal x, qreal y, qreal z, qreal angle)
+{
+ float xp = x;
+ float yp = y;
+ float zp = z;
+ qreal length = qSqrt(xp * xp + yp * yp + zp * zp);
+ if (!qIsNull(length)) {
+ xp /= length;
+ yp /= length;
+ zp /= length;
+ }
+ qreal a = (angle / 2.0f) * M_PI / 180.0f;
+ qreal s = qSin(a);
+ qreal c = qCos(a);
+ return QQuaternion(c, xp * s, yp * s, zp * s, 1).normalized();
+}
+
+/*!
+ \fn bool operator==(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 is equal to \a q2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 is not equal to \a q2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns a QQuaternion object that is the sum of the given quaternions,
+ \a q1 and \a q2; each component is added separately.
+
+ \sa QQuaternion::operator+=()
+*/
+
+/*!
+ \fn const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns a QQuaternion object that is formed by subtracting
+ \a q2 from \a q1; each component is subtracted separately.
+
+ \sa QQuaternion::operator-=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(qreal factor, const QQuaternion &quaternion)
+ \relates QQuaternion
+
+ Returns a copy of the given \a quaternion, multiplied by the
+ given \a factor.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(const QQuaternion &quaternion, qreal factor)
+ \relates QQuaternion
+
+ Returns a copy of the given \a quaternion, multiplied by the
+ given \a factor.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+ \relates QQuaternion
+
+ Multiplies \a q1 and \a q2 using quaternion multiplication.
+ The result corresponds to applying both of the rotations specified
+ by \a q1 and \a q2.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator-(const QQuaternion &quaternion)
+ \relates QQuaternion
+ \overload
+
+ Returns a QQuaternion object that is formed by changing the sign of
+ all three components of the given \a quaternion.
+
+ Equivalent to \c {QQuaternion(0,0,0,0) - quaternion}.
+*/
+
+/*!
+ \fn const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor)
+ \relates QQuaternion
+
+ Returns the QQuaternion object formed by dividing all components of
+ the given \a quaternion by the given \a divisor.
+
+ \sa QQuaternion::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 and \a q2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+/*!
+ Interpolates along the shortest spherical path between the
+ rotational positions \a q1 and \a q2. The value \a t should
+ be between 0 and 1, indicating the spherical distance to travel
+ between \a q1 and \a q2.
+
+ If \a t is less than or equal to 0, then \a q1 will be returned.
+ If \a t is greater than or equal to 1, then \a q2 will be returned.
+
+ \sa nlerp()
+*/
+QQuaternion QQuaternion::slerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t)
+{
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ // Determine the angle between the two quaternions.
+ QQuaternion q2b;
+ qreal dot;
+ dot = q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp;
+ if (dot >= 0.0f) {
+ q2b = q2;
+ } else {
+ q2b = -q2;
+ dot = -dot;
+ }
+
+ // Get the scale factors. If they are too small,
+ // then revert to simple linear interpolation.
+ qreal factor1 = 1.0f - t;
+ qreal factor2 = t;
+ if ((1.0f - dot) > 0.0000001) {
+ qreal angle = qreal(qAcos(dot));
+ qreal sinOfAngle = qreal(qSin(angle));
+ if (sinOfAngle > 0.0000001) {
+ factor1 = qreal(qSin((1.0f - t) * angle)) / sinOfAngle;
+ factor2 = qreal(qSin(t * angle)) / sinOfAngle;
+ }
+ }
+
+ // Construct the result quaternion.
+ return q1 * factor1 + q2b * factor2;
+}
+
+/*!
+ Interpolates along the shortest linear path between the rotational
+ positions \a q1 and \a q2. The value \a t should be between 0 and 1,
+ indicating the distance to travel between \a q1 and \a q2.
+ The result will be normalized().
+
+ If \a t is less than or equal to 0, then \a q1 will be returned.
+ If \a t is greater than or equal to 1, then \a q2 will be returned.
+
+ The nlerp() function is typically faster than slerp() and will
+ give approximate results to spherical interpolation that are
+ good enough for some applications.
+
+ \sa slerp()
+*/
+QQuaternion QQuaternion::nlerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t)
+{
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ // Determine the angle between the two quaternions.
+ QQuaternion q2b;
+ qreal dot;
+ dot = q1.xp * q2.xp + q1.yp * q2.yp + q1.zp * q2.zp + q1.wp * q2.wp;
+ if (dot >= 0.0f)
+ q2b = q2;
+ else
+ q2b = -q2;
+
+ // Perform the linear interpolation.
+ return (q1 * (1.0f - t) + q2b * t).normalized();
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QQuaternion &q)
+{
+ dbg.nospace() << "QQuaternion(scalar:" << q.scalar()
+ << ", vector:(" << q.x() << ", "
+ << q.y() << ", " << q.z() << "))";
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
new file mode 100644
index 0000000..b17cf73
--- /dev/null
+++ b/src/gui/math3d/qquaternion.h
@@ -0,0 +1,337 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUATERNION_H
+#define QQUATERNION_H
+
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QUATERNION
+
+class QMatrix4x4;
+
+class Q_GUI_EXPORT QQuaternion
+{
+public:
+ QQuaternion();
+ QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos);
+#ifndef QT_NO_VECTOR3D
+ QQuaternion(qreal scalar, const QVector3D& vector);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QQuaternion(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+ bool isIdentity() const;
+
+#ifndef QT_NO_VECTOR3D
+ QVector3D vector() const;
+ void setVector(const QVector3D& vector);
+#endif
+ void setVector(qreal x, qreal y, qreal z);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ qreal scalar() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+ void setScalar(qreal scalar);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QQuaternion normalized() const;
+ void normalize();
+
+ QQuaternion conjugate() const;
+
+ QVector3D rotateVector(const QVector3D& vector) const;
+
+ QQuaternion &operator+=(const QQuaternion &quaternion);
+ QQuaternion &operator-=(const QQuaternion &quaternion);
+ QQuaternion &operator*=(qreal factor);
+ QQuaternion &operator*=(const QQuaternion &quaternion);
+ QQuaternion &operator/=(qreal divisor);
+
+ friend inline bool operator==(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator*(qreal factor, const QQuaternion &quaternion);
+ friend inline const QQuaternion operator*(const QQuaternion &quaternion, qreal factor);
+ friend inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2);
+ friend inline const QQuaternion operator-(const QQuaternion &quaternion);
+ friend inline const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2);
+
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+#ifndef QT_NO_VECTOR3D
+ static QQuaternion fromAxisAndAngle(const QVector3D& axis, qreal angle);
+#endif
+ static QQuaternion fromAxisAndAngle
+ (qreal x, qreal y, qreal z, qreal angle);
+
+ static QQuaternion slerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t);
+ static QQuaternion nlerp
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t);
+
+private:
+ float wp, xp, yp, zp;
+
+ friend class QMatrix4x4;
+
+ QQuaternion(float scalar, float xpos, float ypos, float zpos, int dummy);
+};
+
+inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
+
+inline QQuaternion::QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+
+inline QQuaternion::QQuaternion(float scalar, float xpos, float ypos, float zpos, int) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+inline bool QQuaternion::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+}
+
+inline bool QQuaternion::isIdentity() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && wp == 1.0f;
+}
+
+inline qreal QQuaternion::x() const { return qreal(xp); }
+inline qreal QQuaternion::y() const { return qreal(yp); }
+inline qreal QQuaternion::z() const { return qreal(zp); }
+inline qreal QQuaternion::scalar() const { return qreal(wp); }
+
+inline void QQuaternion::setX(qreal x) { xp = x; }
+inline void QQuaternion::setY(qreal y) { yp = y; }
+inline void QQuaternion::setZ(qreal z) { zp = z; }
+inline void QQuaternion::setScalar(qreal scalar) { wp = scalar; }
+
+inline QQuaternion QQuaternion::conjugate() const
+{
+ return QQuaternion(wp, -xp, -yp, -zp, 1);
+}
+
+inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+{
+ xp += quaternion.xp;
+ yp += quaternion.yp;
+ zp += quaternion.zp;
+ wp += quaternion.wp;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+{
+ xp -= quaternion.xp;
+ yp -= quaternion.yp;
+ zp -= quaternion.zp;
+ wp -= quaternion.wp;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ zp *= factor;
+ wp *= factor;
+ return *this;
+}
+
+inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q53
+ float x = q1.wp * q2.xp +
+ q1.xp * q2.wp +
+ q1.yp * q2.zp -
+ q1.zp * q2.yp;
+ float y = q1.wp * q2.yp +
+ q1.yp * q2.wp +
+ q1.zp * q2.xp -
+ q1.xp * q2.zp;
+ float z = q1.wp * q2.zp +
+ q1.zp * q2.wp +
+ q1.xp * q2.yp -
+ q1.yp * q2.xp;
+ float w = q1.wp * q2.wp -
+ q1.xp * q2.xp -
+ q1.yp * q2.yp -
+ q1.zp * q2.zp;
+ return QQuaternion(w, x, y, z, 1);
+}
+
+inline QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+{
+ *this = *this * quaternion;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ zp /= divisor;
+ wp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return q1.xp == q2.xp && q1.yp == q2.yp && q1.zp == q2.zp && q1.wp == q2.wp;
+}
+
+inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return q1.xp != q2.xp || q1.yp != q2.yp || q1.zp != q2.zp || q1.wp != q2.wp;
+}
+
+inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return QQuaternion(q1.wp + q2.wp, q1.xp + q2.xp, q1.yp + q2.yp, q1.zp + q2.zp, 1);
+}
+
+inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return QQuaternion(q1.wp - q2.wp, q1.xp - q2.xp, q1.yp - q2.yp, q1.zp - q2.zp, 1);
+}
+
+inline const QQuaternion operator*(qreal factor, const QQuaternion &quaternion)
+{
+ return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor, 1);
+}
+
+inline const QQuaternion operator*(const QQuaternion &quaternion, qreal factor)
+{
+ return QQuaternion(quaternion.wp * factor, quaternion.xp * factor, quaternion.yp * factor, quaternion.zp * factor, 1);
+}
+
+inline const QQuaternion operator-(const QQuaternion &quaternion)
+{
+ return QQuaternion(-quaternion.wp, -quaternion.xp, -quaternion.yp, -quaternion.zp, 1);
+}
+
+inline const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor)
+{
+ return QQuaternion(quaternion.wp / divisor, quaternion.xp / divisor, quaternion.yp / divisor, quaternion.zp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+{
+ return qFuzzyCompare(q1.xp, q2.xp) &&
+ qFuzzyCompare(q1.yp, q2.yp) &&
+ qFuzzyCompare(q1.zp, q2.zp) &&
+ qFuzzyCompare(q1.wp, q2.wp);
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QQuaternion::QQuaternion(qreal scalar, const QVector3D& vector)
+ : wp(scalar), xp(vector.xp), yp(vector.yp), zp(vector.zp) {}
+
+inline void QQuaternion::setVector(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+}
+
+inline QVector3D QQuaternion::vector() const
+{
+ return QVector3D(xp, yp, zp, 1);
+}
+
+#endif
+
+inline void QQuaternion::setVector(qreal x, qreal y, qreal z)
+{
+ xp = x;
+ yp = y;
+ zp = z;
+}
+
+#ifndef QT_NO_VECTOR4D
+
+inline QQuaternion::QQuaternion(const QVector4D& vector)
+ : wp(vector.wp), xp(vector.xp), yp(vector.yp), zp(vector.zp) {}
+
+inline QVector4D QQuaternion::toVector4D() const
+{
+ return QVector4D(xp, yp, zp, wp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QQuaternion &q);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_QUATERNION
+Q_DECLARE_METATYPE(QQuaternion)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp
new file mode 100644
index 0000000..df2519d
--- /dev/null
+++ b/src/gui/math3d/qvector2d.cpp
@@ -0,0 +1,417 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector2d.h"
+#include "qvector3d.h"
+#include "qvector4d.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ \class QVector2D
+ \brief The QVector2D class represents a vector or vertex in 2D space.
+ \since 4.6
+
+ The QVector2D class can also be used to represent vertices in 2D space.
+ We therefore do not need to provide a separate vertex class.
+
+ The coordinates are stored internally using the most efficient
+ representation for the GL rendering engine, which will be either
+ floating-point or fixed-point.
+*/
+
+/*!
+ \fn QVector2D::QVector2D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(qreal xpos, qreal ypos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point.
+*/
+
+/*!
+ \fn QVector2D::QVector2D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Constructs a vector with x and y coordinates from a 3D \a vector.
+ The z coordinate of \a vector is dropped.
+
+ \sa toVector3D()
+*/
+QVector2D::QVector2D(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Constructs a vector with x and y coordinates from a 3D \a vector.
+ The z and w coordinates of \a vector are dropped.
+
+ \sa toVector4D()
+*/
+QVector2D::QVector2D(const QVector4D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+}
+
+#endif
+
+/*!
+ \fn bool QVector2D::isNull() const
+
+ Returns true if the x and y coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector2D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y()
+*/
+
+/*!
+ \fn qreal QVector2D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x()
+*/
+
+/*!
+ \fn void QVector2D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY()
+*/
+
+/*!
+ \fn void QVector2D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector2D::length() const
+{
+ return qSqrt(xp * xp + yp * yp);
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector2D::lengthSquared() const
+{
+ return xp * xp + yp * yp;
+}
+
+/*!
+ Returns the normalized unit vector form of this vector.
+
+ If this vector is null, then a null vector is returned. If the length
+ of the vector is very close to 1, then the vector will be returned as-is.
+ Otherwise the normalized form of the vector of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QVector2D QVector2D::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QVector2D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector or the length of the vector is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QVector2D::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+}
+
+/*!
+ \fn QVector2D &QVector2D::operator+=(const QVector2D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator-=(const QVector2D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator*=(const QVector2D &vector)
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector2D::dotProduct(const QVector2D& v1, const QVector2D& v2)
+{
+ return v1.xp * v2.xp + v1.yp * v2.yp;
+}
+
+/*!
+ \fn bool operator==(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns a QVector2D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector2D::operator+=()
+*/
+
+/*!
+ \fn const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns a QVector2D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector2D::operator-=()
+*/
+
+/*!
+ \fn const QVector2D operator*(qreal factor, const QVector2D &vector)
+ \relates QVector2D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector2D::operator*=()
+*/
+
+/*!
+ \fn const QVector2D operator*(const QVector2D &vector, qreal factor)
+ \relates QVector2D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector2D::operator*=()
+*/
+
+/*!
+ \fn const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Multiplies the components of \a v1 by the corresponding
+ components in \a v2.
+*/
+
+/*!
+ \fn const QVector2D operator-(const QVector2D &vector)
+ \relates QVector2D
+ \overload
+
+ Returns a QVector2D object that is formed by changing the sign of
+ the components of the given \a vector.
+
+ Equivalent to \c {QVector2D(0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector2D operator/(const QVector2D &vector, qreal divisor)
+ \relates QVector2D
+
+ Returns the QVector2D object formed by dividing all three components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector2D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
+ \relates QVector2D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Returns the 3D form of this 2D vector, with the z coordinate set to zero.
+
+ \sa toVector4D(), toPoint()
+*/
+QVector3D QVector2D::toVector3D() const
+{
+ return QVector3D(xp, yp, 0.0f, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Returns the 4D form of this 2D vector, with the z and w coordinates set to zero.
+
+ \sa toVector3D(), toPoint()
+*/
+QVector4D QVector2D::toVector4D() const
+{
+ return QVector4D(xp, yp, 0.0f, 0.0f, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector2D::toPoint() const
+
+ Returns the QPoint form of this 2D vector.
+
+ \sa toPointF(), toVector3D()
+*/
+
+/*!
+ \fn QPointF QVector2D::toPointF() const
+
+ Returns the QPointF form of this 2D vector.
+
+ \sa toPoint(), toVector3D()
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector2D &vector)
+{
+ dbg.nospace() << "QVector2D(" << vector.x() << ", " << vector.y() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
new file mode 100644
index 0000000..2be0a11
--- /dev/null
+++ b/src/gui/math3d/qvector2d.h
@@ -0,0 +1,256 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR2D_H
+#define QVECTOR2D_H
+
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QVector3D;
+class QVector4D;
+
+#ifndef QT_NO_VECTOR2D
+
+class Q_GUI_EXPORT QVector2D
+{
+public:
+ QVector2D();
+ QVector2D(qreal xpos, qreal ypos);
+ explicit QVector2D(const QPoint& point);
+ explicit QVector2D(const QPointF& point);
+#ifndef QT_NO_VECTOR3D
+ explicit QVector2D(const QVector3D& vector);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QVector2D(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector2D normalized() const;
+ void normalize();
+
+ QVector2D &operator+=(const QVector2D &vector);
+ QVector2D &operator-=(const QVector2D &vector);
+ QVector2D &operator*=(qreal factor);
+ QVector2D &operator*=(const QVector2D &vector);
+ QVector2D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector2D& v1, const QVector2D& v2);
+
+ friend inline bool operator==(const QVector2D &v1, const QVector2D &v2);
+ friend inline bool operator!=(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator*(qreal factor, const QVector2D &vector);
+ friend inline const QVector2D operator*(const QVector2D &vector, qreal factor);
+ friend inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator-(const QVector2D &vector);
+ friend inline const QVector2D operator/(const QVector2D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2);
+
+#ifndef QT_NO_VECTOR3D
+ QVector3D toVector3D() const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+private:
+ float xp, yp;
+
+ QVector2D(float xpos, float ypos, int dummy);
+
+ friend class QVector3D;
+ friend class QVector4D;
+};
+
+inline QVector2D::QVector2D() : xp(0.0f), yp(0.0f) {}
+
+inline QVector2D::QVector2D(float xpos, float ypos, int) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(qreal xpos, qreal ypos) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(const QPoint& point) : xp(point.x()), yp(point.y()) {}
+
+inline QVector2D::QVector2D(const QPointF& point) : xp(point.x()), yp(point.y()) {}
+
+inline bool QVector2D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp);
+}
+
+inline qreal QVector2D::x() const { return qreal(xp); }
+inline qreal QVector2D::y() const { return qreal(yp); }
+
+inline void QVector2D::setX(qreal x) { xp = x; }
+inline void QVector2D::setY(qreal y) { yp = y; }
+
+inline QVector2D &QVector2D::operator+=(const QVector2D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator-=(const QVector2D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator*=(const QVector2D &vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QVector2D &v1, const QVector2D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp;
+}
+
+inline bool operator!=(const QVector2D &v1, const QVector2D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp;
+}
+
+inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp + v2.xp, v1.yp + v2.yp, 1);
+}
+
+inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp - v2.xp, v1.yp - v2.yp, 1);
+}
+
+inline const QVector2D operator*(qreal factor, const QVector2D &vector)
+{
+ return QVector2D(vector.xp * factor, vector.yp * factor, 1);
+}
+
+inline const QVector2D operator*(const QVector2D &vector, qreal factor)
+{
+ return QVector2D(vector.xp * factor, vector.yp * factor, 1);
+}
+
+inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp * v2.xp, v1.yp * v2.yp, 1);
+}
+
+inline const QVector2D operator-(const QVector2D &vector)
+{
+ return QVector2D(-vector.xp, -vector.yp, 1);
+}
+
+inline const QVector2D operator/(const QVector2D &vector, qreal divisor)
+{
+ return QVector2D(vector.xp / divisor, vector.yp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) && qFuzzyCompare(v1.yp, v2.yp);
+}
+
+inline QPoint QVector2D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector2D::toPointF() const
+{
+ return QPointF(qreal(xp), qreal(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector2D &vector);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VECTOR2D
+Q_DECLARE_METATYPE(QVector2D)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp
new file mode 100644
index 0000000..a5f5c5b
--- /dev/null
+++ b/src/gui/math3d/qvector3d.cpp
@@ -0,0 +1,565 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector3d.h"
+#include "qvector2d.h"
+#include "qvector4d.h"
+#include <QtCore/qmath.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \class QVector3D
+ \brief The QVector3D class represents a vector or vertex in 3D space.
+ \since 4.6
+
+ Vectors are one of the main building blocks of 3D representation and
+ drawing. They consist of three coordinates, traditionally called
+ x, y, and z.
+
+ The QVector3D class can also be used to represent vertices in 3D space.
+ We therefore do not need to provide a separate vertex class.
+
+ The coordinates are stored internally using the most efficient
+ representation for the GL rendering engine, which will be either
+ floating-point or fixed-point.
+*/
+
+/*!
+ \fn QVector3D::QVector3D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and a
+ z coordinate of 0.
+*/
+
+/*!
+ \fn QVector3D::QVector3D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and a
+ z coordinate of 0.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Constructs a 3D vector from the specified 2D \a vector. The z
+ coordinate is set to zero.
+
+ \sa toVector2D()
+*/
+QVector3D::QVector3D(const QVector2D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = 0.0f;
+}
+
+/*!
+ Constructs a 3D vector from the specified 2D \a vector. The z
+ coordinate is set to \a zpos.
+
+ \sa toVector2D()
+*/
+QVector3D::QVector3D(const QVector2D& vector, qreal zpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = zpos;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Constructs a 3D vector from the specified 4D \a vector. The w
+ coordinate is dropped.
+
+ \sa toVector4D()
+*/
+QVector3D::QVector3D(const QVector4D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+}
+
+#endif
+
+/*!
+ \fn bool QVector3D::isNull() const
+
+ Returns true if the x, y, and z coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector3D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y(), z()
+*/
+
+/*!
+ \fn qreal QVector3D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x(), z()
+*/
+
+/*!
+ \fn qreal QVector3D::z() const
+
+ Returns the z coordinate of this point.
+
+ \sa setZ(), x(), y()
+*/
+
+/*!
+ \fn void QVector3D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY(), setZ()
+*/
+
+/*!
+ \fn void QVector3D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX(), setZ()
+*/
+
+/*!
+ \fn void QVector3D::setZ(qreal z)
+
+ Sets the z coordinate of this point to the given \a z coordinate.
+
+ \sa z(), setX(), setY()
+*/
+
+/*!
+ Returns the normalized unit vector form of this vector.
+
+ If this vector is null, then a null vector is returned. If the length
+ of the vector is very close to 1, then the vector will be returned as-is.
+ Otherwise the normalized form of the vector of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QVector3D QVector3D::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QVector3D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector or the length of the vector is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QVector3D::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+}
+
+/*!
+ \fn QVector3D &QVector3D::operator+=(const QVector3D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator-=(const QVector3D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator*=(const QVector3D& vector)
+ \overload
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+
+ Note: this is not the same as the crossProduct() of this
+ vector and \a vector.
+
+ \sa crossProduct()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
+{
+ return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp;
+}
+
+/*!
+ Returns the cross-product of vectors \a v1 and \a v2, which corresponds
+ to the normal vector of a plane defined by \a v1 and \a v2.
+
+ \sa normal()
+*/
+QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
+{
+ return QVector3D(v1.yp * v2.zp - v1.zp * v2.yp,
+ v1.zp * v2.xp - v1.xp * v2.zp,
+ v1.xp * v2.yp - v1.yp * v2.xp, 1);
+}
+
+/*!
+ Returns the normal vector of a plane defined by vectors \a v1 and \a v2,
+ normalized to be a unit vector.
+
+ Use crossProduct() to compute the cross-product of \a v1 and \a v2 if you
+ do not need the result to be normalized to a unit vector.
+
+ \sa crossProduct(), distanceToPlane()
+*/
+QVector3D QVector3D::normal(const QVector3D& v1, const QVector3D& v2)
+{
+ return crossProduct(v1, v2).normalized();
+}
+
+/*!
+ \overload
+
+ Returns the normal vector of a plane defined by vectors
+ \a v2 - \a v1 and \a v3 - \a v1, normalized to be a unit vector.
+
+ Use crossProduct() to compute the cross-product of \a v2 - \a v1 and
+ \a v3 - \a v1 if you do not need the result to be normalized to a
+ unit vector.
+
+ \sa crossProduct(), distanceToPlane()
+*/
+QVector3D QVector3D::normal
+ (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3)
+{
+ return crossProduct((v2 - v1), (v3 - v1)).normalized();
+}
+
+/*!
+ Returns the distance from this vertex to a plane defined by
+ the vertex \a plane and a \a normal unit vector. The \a normal
+ parameter is assumed to have been normalized to a unit vector.
+
+ The return value will be negative if the vertex is below the plane,
+ or zero if it is on the plane.
+
+ \sa normal(), distanceToLine()
+*/
+qreal QVector3D::distanceToPlane
+ (const QVector3D& plane, const QVector3D& normal) const
+{
+ return dotProduct(*this - plane, normal);
+}
+
+/*!
+ \overload
+
+ Returns the distance from this vertex a plane defined by
+ the vertices \a plane1, \a plane2 and \a plane3.
+
+ The return value will be negative if the vertex is below the plane,
+ or zero if it is on the plane.
+
+ The two vectors that define the plane are \a plane2 - \a plane1
+ and \a plane3 - \a plane1.
+
+ \sa normal(), distanceToLine()
+*/
+qreal QVector3D::distanceToPlane
+ (const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const
+{
+ QVector3D n = normal(plane2 - plane1, plane3 - plane1);
+ return dotProduct(*this - plane1, n);
+}
+
+/*!
+ Returns the distance that this vertex is from a line defined
+ by \a point and the unit vector \a direction.
+
+ If \a direction is a null vector, then it does not define a line.
+ In that case, the distance from \a point to this vertex is returned.
+
+ \sa distanceToPlane()
+*/
+qreal QVector3D::distanceToLine
+ (const QVector3D& point, const QVector3D& direction) const
+{
+ if (direction.isNull())
+ return (*this - point).length();
+ QVector3D p = point + dotProduct(*this - point, direction) * direction;
+ return (*this - p).length();
+}
+
+/*!
+ \fn bool operator==(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns a QVector3D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector3D::operator+=()
+*/
+
+/*!
+ \fn const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns a QVector3D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector3D::operator-=()
+*/
+
+/*!
+ \fn const QVector3D operator*(qreal factor, const QVector3D &vector)
+ \relates QVector3D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector3D::operator*=()
+*/
+
+/*!
+ \fn const QVector3D operator*(const QVector3D &vector, qreal factor)
+ \relates QVector3D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector3D::operator*=()
+*/
+
+/*!
+ \fn const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
+ \relates QVector3D
+
+ Multiplies the components of \a v1 by the corresponding components in \a v2.
+
+ Note: this is not the same as the crossProduct() of \a v1 and \a v2.
+
+ \sa QVector3D::crossProduct()
+*/
+
+/*!
+ \fn const QVector3D operator-(const QVector3D &vector)
+ \relates QVector3D
+ \overload
+
+ Returns a QVector3D object that is formed by changing the sign of
+ all three components of the given \a vector.
+
+ Equivalent to \c {QVector3D(0,0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector3D operator/(const QVector3D &vector, qreal divisor)
+ \relates QVector3D
+
+ Returns the QVector3D object formed by dividing all three components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector3D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
+ \relates QVector3D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Returns the 2D vector form of this 3D vector, dropping the z coordinate.
+
+ \sa toVector4D(), toPoint()
+*/
+QVector2D QVector3D::toVector2D() const
+{
+ return QVector2D(xp, yp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Returns the 4D form of this 3D vector, with the w coordinate set to zero.
+
+ \sa toVector2D(), toPoint()
+*/
+QVector4D QVector3D::toVector4D() const
+{
+ return QVector4D(xp, yp, zp, 0.0f, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector3D::toPoint() const
+
+ Returns the QPoint form of this 3D vector.
+
+ \sa toPointF(), toVector2D()
+*/
+
+/*!
+ \fn QPointF QVector3D::toPointF() const
+
+ Returns the QPointF form of this 3D vector.
+
+ \sa toPoint(), toVector2D()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector3D::length() const
+{
+ return qSqrt(xp * xp + yp * yp + zp * zp);
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector3D::lengthSquared() const
+{
+ return xp * xp + yp * yp + zp * zp;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector3D &vector)
+{
+ dbg.nospace() << "QVector3D("
+ << vector.x() << ", " << vector.y() << ", " << vector.z() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
new file mode 100644
index 0000000..480667a
--- /dev/null
+++ b/src/gui/math3d/qvector3d.h
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR3D_H
+#define QVECTOR3D_H
+
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QMatrix4x4;
+class QVector2D;
+class QVector4D;
+class QQuaternion;
+
+#ifndef QT_NO_VECTOR3D
+
+class Q_GUI_EXPORT QVector3D
+{
+public:
+ QVector3D();
+ QVector3D(qreal xpos, qreal ypos, qreal zpos);
+ explicit QVector3D(const QPoint& point);
+ explicit QVector3D(const QPointF& point);
+#ifndef QT_NO_VECTOR2D
+ QVector3D(const QVector2D& vector);
+ QVector3D(const QVector2D& vector, qreal zpos);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QVector3D(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector3D normalized() const;
+ void normalize();
+
+ QVector3D &operator+=(const QVector3D &vector);
+ QVector3D &operator-=(const QVector3D &vector);
+ QVector3D &operator*=(qreal factor);
+ QVector3D &operator*=(const QVector3D& vector);
+ QVector3D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D crossProduct(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D normal(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D normal
+ (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3);
+
+ qreal distanceToPlane(const QVector3D& plane, const QVector3D& normal) const;
+ qreal distanceToPlane(const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const;
+ qreal distanceToLine(const QVector3D& point, const QVector3D& direction) const;
+
+ friend inline bool operator==(const QVector3D &v1, const QVector3D &v2);
+ friend inline bool operator!=(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator*(qreal factor, const QVector3D &vector);
+ friend inline const QVector3D operator*(const QVector3D &vector, qreal factor);
+ friend const QVector3D operator*(const QVector3D &v1, const QVector3D& v2);
+ friend inline const QVector3D operator-(const QVector3D &vector);
+ friend inline const QVector3D operator/(const QVector3D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2);
+
+#ifndef QT_NO_VECTOR2D
+ QVector2D toVector2D() const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+private:
+ float xp, yp, zp;
+
+ QVector3D(float xpos, float ypos, float zpos, int dummy);
+
+ friend class QVector2D;
+ friend class QVector4D;
+ friend class QQuaternion;
+ friend class QMatrix4x4;
+#ifndef QT_NO_MATRIX4X4
+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
+#endif
+};
+
+inline QVector3D::QVector3D() : xp(0.0f), yp(0.0f), zp(0.0f) {}
+
+inline QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(float xpos, float ypos, float zpos, int) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+
+inline QVector3D::QVector3D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+
+inline bool QVector3D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
+}
+
+inline qreal QVector3D::x() const { return qreal(xp); }
+inline qreal QVector3D::y() const { return qreal(yp); }
+inline qreal QVector3D::z() const { return qreal(zp); }
+
+inline void QVector3D::setX(qreal x) { xp = x; }
+inline void QVector3D::setY(qreal y) { yp = y; }
+inline void QVector3D::setZ(qreal z) { zp = z; }
+
+inline QVector3D &QVector3D::operator+=(const QVector3D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ zp += vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator-=(const QVector3D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ zp -= vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ zp *= factor;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator*=(const QVector3D& vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ zp *= vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ zp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QVector3D &v1, const QVector3D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp;
+}
+
+inline bool operator!=(const QVector3D &v1, const QVector3D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp;
+}
+
+inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
+{
+ return QVector3D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, 1);
+}
+
+inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
+{
+ return QVector3D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, 1);
+}
+
+inline const QVector3D operator*(qreal factor, const QVector3D &vector)
+{
+ return QVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor, 1);
+}
+
+inline const QVector3D operator*(const QVector3D &vector, qreal factor)
+{
+ return QVector3D(vector.xp * factor, vector.yp * factor, vector.zp * factor, 1);
+}
+
+inline const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
+{
+ return QVector3D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, 1);
+}
+
+inline const QVector3D operator-(const QVector3D &vector)
+{
+ return QVector3D(-vector.xp, -vector.yp, -vector.zp, 1);
+}
+
+inline const QVector3D operator/(const QVector3D &vector, qreal divisor)
+{
+ return QVector3D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) &&
+ qFuzzyCompare(v1.yp, v2.yp) &&
+ qFuzzyCompare(v1.zp, v2.zp);
+}
+
+inline QPoint QVector3D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector3D::toPointF() const
+{
+ return QPointF(qreal(xp), qreal(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector3D &vector);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VECTOR3D
+Q_DECLARE_METATYPE(QVector3D)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp
new file mode 100644
index 0000000..c5124e2
--- /dev/null
+++ b/src/gui/math3d/qvector4d.cpp
@@ -0,0 +1,518 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector4d.h"
+#include "qvector3d.h"
+#include "qvector2d.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \class QVector4D
+ \brief The QVector4D class represents a vector or vertex in 4D space.
+ \since 4.6
+
+ The QVector4D class can also be used to represent vertices in 4D space.
+ We therefore do not need to provide a separate vertex class.
+
+ The coordinates are stored internally using the most efficient
+ representation for the GL rendering engine, which will be either
+ floating-point or fixed-point.
+
+ \sa QQuaternion, QVector2D, QVector3D
+*/
+
+/*!
+ \fn QVector4D::QVector4D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0, 0).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos, \a wpos).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and
+ z and w coordinates of 0.
+*/
+
+/*!
+ \fn QVector4D::QVector4D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and
+ z and w coordinates of 0.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Constructs a 4D vector from the specified 2D \a vector. The z
+ and w coordinates are set to zero.
+
+ \sa toVector2D()
+*/
+QVector4D::QVector4D(const QVector2D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = 0.0f;
+ wp = 0.0f;
+}
+
+/*!
+ Constructs a 4D vector from the specified 2D \a vector. The z
+ and w coordinates are set to \a zpos and \a wpos respectively.
+
+ \sa toVector2D()
+*/
+QVector4D::QVector4D(const QVector2D& vector, qreal zpos, qreal wpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = zpos;
+ wp = wpos;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Constructs a 4D vector from the specified 3D \a vector. The w
+ coordinate is set to zero.
+
+ \sa toVector3D()
+*/
+QVector4D::QVector4D(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+ wp = 0.0f;
+}
+
+/*!
+ Constructs a 4D vector from the specified 3D \a vector. The w
+ coordinate is set to \a wpos.
+
+ \sa toVector3D()
+*/
+QVector4D::QVector4D(const QVector3D& vector, qreal wpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+ wp = wpos;
+}
+
+#endif
+
+/*!
+ \fn bool QVector4D::isNull() const
+
+ Returns true if the x, y, z, and w coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector4D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y(), z(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x(), z(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::z() const
+
+ Returns the z coordinate of this point.
+
+ \sa setZ(), x(), y(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::w() const
+
+ Returns the w coordinate of this point.
+
+ \sa setW(), x(), y(), z()
+*/
+
+/*!
+ \fn void QVector4D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY(), setZ(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX(), setZ(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setZ(qreal z)
+
+ Sets the z coordinate of this point to the given \a z coordinate.
+
+ \sa z(), setX(), setY(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setW(qreal w)
+
+ Sets the w coordinate of this point to the given \a w coordinate.
+
+ \sa w(), setX(), setY(), setZ()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector4D::length() const
+{
+ return qSqrt(xp * xp + yp * yp + zp * zp + wp * wp);
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector4D::lengthSquared() const
+{
+ return xp * xp + yp * yp + zp * zp + wp * wp;
+}
+
+/*!
+ Returns the normalized unit vector form of this vector.
+
+ If this vector is null, then a null vector is returned. If the length
+ of the vector is very close to 1, then the vector will be returned as-is.
+ Otherwise the normalized form of the vector of length 1 will be returned.
+
+ \sa length(), normalize()
+*/
+QVector4D QVector4D::normalized() const
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f))
+ return *this;
+ else if (!qFuzzyIsNull(len))
+ return *this / qSqrt(len);
+ else
+ return QVector4D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector or the length of the vector is very close to 1.
+
+ \sa length(), normalized()
+*/
+void QVector4D::normalize()
+{
+ qreal len = lengthSquared();
+ if (qFuzzyIsNull(len - 1.0f) || qFuzzyIsNull(len))
+ return;
+
+ len = qSqrt(len);
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+ wp /= len;
+}
+
+/*!
+ \fn QVector4D &QVector4D::operator+=(const QVector4D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator-=(const QVector4D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator*=(const QVector4D &vector)
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
+{
+ return v1.xp * v2.xp + v1.yp * v2.yp + v1.zp * v2.zp + v1.wp * v2.wp;
+}
+
+/*!
+ \fn bool operator==(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns a QVector4D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector4D::operator+=()
+*/
+
+/*!
+ \fn const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns a QVector4D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector4D::operator-=()
+*/
+
+/*!
+ \fn const QVector4D operator*(qreal factor, const QVector4D &vector)
+ \relates QVector4D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator*(const QVector4D &vector, qreal factor)
+ \relates QVector4D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
+ \relates QVector4D
+
+ Returns the vector consisting of the multiplication of the
+ components from \a v1 and \a v2.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator-(const QVector4D &vector)
+ \relates QVector4D
+ \overload
+
+ Returns a QVector4D object that is formed by changing the sign of
+ all three components of the given \a vector.
+
+ Equivalent to \c {QVector4D(0,0,0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector4D operator/(const QVector4D &vector, qreal divisor)
+ \relates QVector4D
+
+ Returns the QVector4D object formed by dividing all four components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector4D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
+ \relates QVector4D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Returns the 2D vector form of this 4D vector, dropping the z and w coordinates.
+
+ \sa toVector2DAffine(), toVector3D(), toPoint()
+*/
+QVector2D QVector4D::toVector2D() const
+{
+ return QVector2D(xp, yp, 1);
+}
+
+/*!
+ Returns the 2D vector form of this 4D vector, dividing the x and y
+ coordinates by the w coordinate and dropping the z coordinate.
+ Returns a null vector if w is zero.
+
+ \sa toVector2D(), toVector3DAffine(), toPoint()
+*/
+QVector2D QVector4D::toVector2DAffine() const
+{
+ if (qIsNull(wp))
+ return QVector2D();
+ return QVector2D(xp / wp, yp / wp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Returns the 3D vector form of this 4D vector, dropping the w coordinate.
+
+ \sa toVector3DAffine(), toVector2D(), toPoint()
+*/
+QVector3D QVector4D::toVector3D() const
+{
+ return QVector3D(xp, yp, zp, 1);
+}
+
+/*!
+ Returns the 3D vector form of this 4D vector, dividing the x, y, and
+ z coordinates by the w coordinate. Returns a null vector if w is zero.
+
+ \sa toVector3D(), toVector2DAffine(), toPoint()
+*/
+QVector3D QVector4D::toVector3DAffine() const
+{
+ if (qIsNull(wp))
+ return QVector3D();
+ return QVector3D(xp / wp, yp / wp, zp / wp, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector4D::toPoint() const
+
+ Returns the QPoint form of this 4D vector.
+
+ \sa toPointF(), toVector2D()
+*/
+
+/*!
+ \fn QPointF QVector4D::toPointF() const
+
+ Returns the QPointF form of this 4D vector.
+
+ \sa toPoint(), toVector2D()
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector4D &vector)
+{
+ dbg.nospace() << "QVector4D("
+ << vector.x() << ", " << vector.y() << ", "
+ << vector.z() << ", " << vector.w() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
new file mode 100644
index 0000000..e38f4e5
--- /dev/null
+++ b/src/gui/math3d/qvector4d.h
@@ -0,0 +1,289 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR4D_H
+#define QVECTOR4D_H
+
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QMatrix4x4;
+class QVector2D;
+class QVector3D;
+class QQuaternion;
+
+#ifndef QT_NO_VECTOR4D
+
+class Q_GUI_EXPORT QVector4D
+{
+public:
+ QVector4D();
+ QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos);
+ explicit QVector4D(const QPoint& point);
+ explicit QVector4D(const QPointF& point);
+#ifndef QT_NO_VECTOR2D
+ QVector4D(const QVector2D& vector);
+ QVector4D(const QVector2D& vector, qreal zpos, qreal wpos);
+#endif
+#ifndef QT_NO_VECTOR3D
+ QVector4D(const QVector3D& vector);
+ QVector4D(const QVector3D& vector, qreal wpos);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ qreal w() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+ void setW(qreal w);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector4D normalized() const;
+ void normalize();
+
+ QVector4D &operator+=(const QVector4D &vector);
+ QVector4D &operator-=(const QVector4D &vector);
+ QVector4D &operator*=(qreal factor);
+ QVector4D &operator*=(const QVector4D &vector);
+ QVector4D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector4D& v1, const QVector4D& v2);
+
+ friend inline bool operator==(const QVector4D &v1, const QVector4D &v2);
+ friend inline bool operator!=(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator*(qreal factor, const QVector4D &vector);
+ friend inline const QVector4D operator*(const QVector4D &vector, qreal factor);
+ friend inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2);
+ friend inline const QVector4D operator-(const QVector4D &vector);
+ friend inline const QVector4D operator/(const QVector4D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2);
+
+#ifndef QT_NO_VECTOR2D
+ QVector2D toVector2D() const;
+ QVector2D toVector2DAffine() const;
+#endif
+#ifndef QT_NO_VECTOR3D
+ QVector3D toVector3D() const;
+ QVector3D toVector3DAffine() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+private:
+ float xp, yp, zp, wp;
+
+ QVector4D(float xpos, float ypos, float zpos, float wpos, int dummy);
+
+ friend class QVector2D;
+ friend class QVector3D;
+ friend class QQuaternion;
+ friend class QMatrix4x4;
+#ifndef QT_NO_MATRIX4X4
+ friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
+ friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
+#endif
+};
+
+inline QVector4D::QVector4D() : xp(0.0f), yp(0.0f), zp(0.0f), wp(0.0f) {}
+
+inline QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(float xpos, float ypos, float zpos, float wpos, int) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+
+inline QVector4D::QVector4D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+
+inline bool QVector4D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+}
+
+inline qreal QVector4D::x() const { return qreal(xp); }
+inline qreal QVector4D::y() const { return qreal(yp); }
+inline qreal QVector4D::z() const { return qreal(zp); }
+inline qreal QVector4D::w() const { return qreal(wp); }
+
+inline void QVector4D::setX(qreal x) { xp = x; }
+inline void QVector4D::setY(qreal y) { yp = y; }
+inline void QVector4D::setZ(qreal z) { zp = z; }
+inline void QVector4D::setW(qreal w) { wp = w; }
+
+inline QVector4D &QVector4D::operator+=(const QVector4D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ zp += vector.zp;
+ wp += vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator-=(const QVector4D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ zp -= vector.zp;
+ wp -= vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator*=(qreal factor)
+{
+ xp *= factor;
+ yp *= factor;
+ zp *= factor;
+ wp *= factor;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator*=(const QVector4D &vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ zp *= vector.zp;
+ wp *= vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator/=(qreal divisor)
+{
+ xp /= divisor;
+ yp /= divisor;
+ zp /= divisor;
+ wp /= divisor;
+ return *this;
+}
+
+inline bool operator==(const QVector4D &v1, const QVector4D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp && v1.wp == v2.wp;
+}
+
+inline bool operator!=(const QVector4D &v1, const QVector4D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp || v1.wp != v2.wp;
+}
+
+inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
+{
+ return QVector4D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, v1.wp + v2.wp, 1);
+}
+
+inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
+{
+ return QVector4D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, v1.wp - v2.wp, 1);
+}
+
+inline const QVector4D operator*(qreal factor, const QVector4D &vector)
+{
+ return QVector4D(vector.xp * factor, vector.yp * factor, vector.zp * factor, vector.wp * factor, 1);
+}
+
+inline const QVector4D operator*(const QVector4D &vector, qreal factor)
+{
+ return QVector4D(vector.xp * factor, vector.yp * factor, vector.zp * factor, vector.wp * factor, 1);
+}
+
+inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
+{
+ return QVector4D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, v1.wp * v2.wp, 1);
+}
+
+inline const QVector4D operator-(const QVector4D &vector)
+{
+ return QVector4D(-vector.xp, -vector.yp, -vector.zp, -vector.wp, 1);
+}
+
+inline const QVector4D operator/(const QVector4D &vector, qreal divisor)
+{
+ return QVector4D(vector.xp / divisor, vector.yp / divisor, vector.zp / divisor, vector.wp / divisor, 1);
+}
+
+inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) &&
+ qFuzzyCompare(v1.yp, v2.yp) &&
+ qFuzzyCompare(v1.zp, v2.zp) &&
+ qFuzzyCompare(v1.wp, v2.wp);
+}
+
+inline QPoint QVector4D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector4D::toPointF() const
+{
+ return QPointF(qreal(xp), qreal(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector4D &vector);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VECTOR4D
+Q_DECLARE_METATYPE(QVector4D)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index 693e506..d153215 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -104,12 +104,6 @@ win32 {
painting/qprinterinfo_win.cpp \
painting/qregion_win.cpp
!win32-borland:!wince*:LIBS += -lmsimg32
- contains(QT_CONFIG, direct3d) {
- HEADERS += painting/qpaintengine_d3d_p.h
- SOURCES += painting/qpaintengine_d3d.cpp
- RESOURCES += painting/qpaintengine_d3d.qrc
- LIBS += -ldxguid
- }
}
embedded {
@@ -370,10 +364,6 @@ embedded {
SOURCES += painting/qwindowsurface_qws.cpp
}
-win32:contains(QT_CONFIG, direct3d) {
- HEADERS += painting/qwindowsurface_d3d_p.h
- SOURCES += painting/qwindowsurface_d3d.cpp
-}
symbian {
HEADERS += painting/qwindowsurface_s60_p.h
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 0a3a8dd..25dab4c 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -758,7 +758,7 @@ void QWidgetBackingStore::paintWindowDecoration()
engine->setSystemClip(decorationRegion.translated(tlwOffset));
QPainter painter(windowSurface->paintDevice());
- painter.setFont(qApp->font());
+ painter.setFont(QApplication::font());
painter.translate(tlwOffset);
const int numDirty = managerPrivate->dirtyRegions.size();
@@ -1347,7 +1347,7 @@ void QWidgetBackingStore::flush(QWidget *widget, QWindowSurface *surface)
static inline bool discardInvalidateBufferRequest(QWidget *widget, QTLWExtra *tlwExtra)
{
Q_ASSERT(widget);
- if (qApp && qApp->closingDown())
+ if (QApplication::closingDown())
return true;
if (!tlwExtra || tlwExtra->inTopLevelResize || !tlwExtra->backingStore)
diff --git a/src/gui/painting/qbezier.cpp b/src/gui/painting/qbezier.cpp
index 8317dd8..6a206ee 100644
--- a/src/gui/painting/qbezier.cpp
+++ b/src/gui/painting/qbezier.cpp
@@ -127,13 +127,13 @@ static inline void flattenBezierWithoutInflections(QBezier &bez,
qreal dy = bez.y2 - bez.y1;
qreal normalized = qSqrt(dx * dx + dy * dy);
- if (qFuzzyCompare(normalized + 1, 1))
+ if (qFuzzyIsNull(normalized))
break;
qreal d = qAbs(dx * (bez.y3 - bez.y2) - dy * (bez.x3 - bez.x2));
qreal t = qSqrt(4. / 3. * normalized * flatness / d);
- if (t > 1 || qFuzzyCompare(t, (qreal)1.))
+ if (t > 1 || qFuzzyIsNull(t - (qreal)1.))
break;
bez.parameterSplitLeft(t, &left);
p->append(bez.pt1());
@@ -144,19 +144,19 @@ static inline void flattenBezierWithoutInflections(QBezier &bez,
static inline int quadraticRoots(qreal a, qreal b, qreal c,
qreal *x1, qreal *x2)
{
- if (qFuzzyCompare(a + 1, 1)) {
- if (qFuzzyCompare(b + 1, 1))
+ if (qFuzzyIsNull(a)) {
+ if (qFuzzyIsNull(b))
return 0;
*x1 = *x2 = (-c / b);
return 1;
} else {
const qreal det = b * b - 4 * a * c;
- if (qFuzzyCompare(det + 1, 1)) {
+ if (qFuzzyIsNull(det)) {
*x1 = *x2 = -b / (2 * a);
return 1;
}
if (det > 0) {
- if (qFuzzyCompare(b + 1, 1)) {
+ if (qFuzzyIsNull(b)) {
*x2 = qSqrt(-c / a);
*x1 = -(*x2);
return 2;
@@ -187,7 +187,7 @@ static inline bool findInflections(qreal a, qreal b, qreal c,
*t1 = r2;
*t2 = r1;
}
- if (!qFuzzyCompare(a + 1, 1))
+ if (!qFuzzyIsNull(a))
*tCups = 0.5 * (-b / a);
else
*tCups = 2;
@@ -243,7 +243,7 @@ void QBezier::addToPolygonMixed(QPolygonF *polygon) const
qreal b = 6 * (ay * cx - ax * cy);
qreal c = 2 * (by * cx - bx * cy);
- if ((qFuzzyCompare(a + 1, 1) && qFuzzyCompare(b + 1, 1)) ||
+ if ((qFuzzyIsNull(a) && qFuzzyIsNull(b)) ||
(b * b - 4 * a *c) < 0) {
QBezier bez(*this);
flattenBezierWithoutInflections(bez, polygon);
@@ -447,7 +447,7 @@ static ShiftResult shift(const QBezier *orig, QBezier *shifted, qreal offset, qr
qreal r = 1.0 + prev_normal.x() * next_normal.x()
+ prev_normal.y() * next_normal.y();
- if (qFuzzyCompare(r + 1, 1)) {
+ if (qFuzzyIsNull(r)) {
points_shifted[i] = points[i] + offset * prev_normal;
} else {
qreal k = offset / r;
@@ -477,12 +477,12 @@ static bool addCircle(const QBezier *b, qreal offset, QBezier *o)
normals[0] = QPointF(b->y2 - b->y1, b->x1 - b->x2);
qreal dist = qSqrt(normals[0].x()*normals[0].x() + normals[0].y()*normals[0].y());
- if (qFuzzyCompare(dist + 1, 1))
+ if (qFuzzyIsNull(dist))
return false;
normals[0] /= dist;
normals[2] = QPointF(b->y4 - b->y3, b->x3 - b->x4);
dist = qSqrt(normals[2].x()*normals[2].x() + normals[2].y()*normals[2].y());
- if (qFuzzyCompare(dist + 1, 1))
+ if (qFuzzyIsNull(dist))
return false;
normals[2] /= dist;
@@ -673,10 +673,10 @@ static int IntersectBB(const QBezier &a, const QBezier &b)
#ifdef QDEBUG_BEZIER
static QDebug operator<<(QDebug dbg, const QBezier &bz)
{
- dbg <<"["<<bz.x1<<", "<<bz.y1<<"], "
- <<"["<<bz.x2<<", "<<bz.y2<<"], "
- <<"["<<bz.x3<<", "<<bz.y3<<"], "
- <<"["<<bz.x4<<", "<<bz.y4<<"]";
+ dbg << '[' << bz.x1<< ", " << bz.y1 << "], "
+ << '[' << bz.x2 <<", " << bz.y2 << "], "
+ << '[' << bz.x3 <<", " << bz.y3 << "], "
+ << '[' << bz.x4 <<", " << bz.y4 << ']';
return dbg;
}
#endif
@@ -1022,7 +1022,7 @@ int QBezier::stationaryYPoints(qreal &t0, qreal &t1) const
QList<qreal> result;
- if (qFuzzyCompare(reciprocal + 1, 1)) {
+ if (qFuzzyIsNull(reciprocal)) {
t0 = -b / (2 * a);
return 1;
} else if (reciprocal > 0) {
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 93f11e1..4bdaf0b 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -104,6 +104,37 @@ struct Blend_RGB16_on_RGB16_ConstAlpha {
quint32 m_ialpha;
};
+struct Blend_ARGB24_on_RGB16_SourceAlpha {
+ inline void write(quint16 *dst, const qargb8565 &src) {
+ const uint alpha = src.alpha();
+ if (alpha) {
+ quint16 s = src.rawValue16();
+ if (alpha < 255)
+ s += BYTE_MUL_RGB16(*dst, 255 - alpha);
+ *dst = s;
+ }
+ }
+};
+
+struct Blend_ARGB24_on_RGB16_SourceAndConstAlpha {
+ inline Blend_ARGB24_on_RGB16_SourceAndConstAlpha(quint32 alpha) {
+ m_alpha = (alpha * 255) >> 8;
+ }
+
+ inline void write(quint16 *dst, qargb8565 src) {
+ src = src.byte_mul(src.alpha(m_alpha));
+ const uint alpha = src.alpha();
+ if (alpha) {
+ quint16 s = src.rawValue16();
+ if (alpha < 255)
+ s += BYTE_MUL_RGB16(*dst, 255 - alpha);
+ *dst = s;
+ }
+ }
+
+ quint32 m_alpha;
+};
+
struct Blend_ARGB32_on_RGB16_SourceAlpha {
inline void write(quint16 *dst, quint32 src) {
const quint8 alpha = qAlpha(src);
@@ -237,6 +268,32 @@ void qt_scale_image_rgb16_on_rgb16(uchar *destPixels, int dbpl,
}
}
+void qt_scale_image_argb24_on_rgb16(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ const QRectF &targetRect,
+ const QRectF &sourceRect,
+ const QRect &clip,
+ int const_alpha)
+{
+#ifdef QT_DEBUG_DRAW
+ printf("qt_scale_argb24_on_rgb16: dst=(%p, %d), src=(%p, %d), target=(%d, %d), [%d x %d], src=(%d, %d) [%d x %d] alpha=%d\n",
+ destPixels, dbpl, srcPixels, sbpl,
+ targetRect.x(), targetRect.y(), targetRect.width(), targetRect.height(),
+ sourceRect.x(), sourceRect.y(), sourceRect.width(), sourceRect.height(),
+ const_alpha);
+#endif
+ if (const_alpha == 256) {
+ Blend_ARGB24_on_RGB16_SourceAlpha noAlpha;
+ qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl,
+ targetRect, sourceRect, clip, noAlpha);
+ } else {
+ Blend_ARGB24_on_RGB16_SourceAndConstAlpha constAlpha(const_alpha);
+ qt_scale_image_16bit<qargb8565>(destPixels, dbpl, srcPixels, sbpl,
+ targetRect, sourceRect, clip, constAlpha);
+ }
+}
+
+
void qt_scale_image_argb32_on_rgb16(uchar *destPixels, int dbpl,
const uchar *srcPixels, int sbpl,
const QRectF &targetRect,
@@ -513,11 +570,10 @@ static void qt_blend_argb32_on_argb32(uchar *destPixels, int dbpl,
for (int y=0; y<h; ++y) {
for (int x=0; x<w; ++x) {
uint s = src[x];
- if ((s & 0xff000000) == 0xff000000)
+ if (s >= 0xff000000)
dst[x] = s;
- else {
+ else if (s != 0)
dst[x] = s + BYTE_MUL(dst[x], qAlpha(~s));
- }
}
dst = (quint32 *)(((uchar *) dst) + dbpl);
src = (const quint32 *)(((const uchar *) src) + sbpl);
@@ -875,7 +931,7 @@ SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] =
0, // Format_ARGB32,
qt_scale_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
qt_scale_image_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
+ qt_scale_image_argb24_on_rgb16, // Format_ARGB8565_Premultiplied,
0, // Format_RGB666,
0, // Format_ARGB6666_Premultiplied,
0, // Format_RGB555,
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index c22791a..8e4cc68 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -217,7 +217,7 @@ struct QTexturedBrushData : public QBrushData
// returns true if the brush has a pixmap (or bitmap) set as the
// brush texture, false otherwise
-bool qHasPixmapTexture(const QBrush& brush)
+bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush)
{
if (brush.style() != Qt::TexturePattern)
return false;
@@ -863,7 +863,9 @@ bool QBrush::isOpaque() const
return false;
return true;
} else if (d->style == Qt::TexturePattern) {
- return !texture().hasAlpha();
+ return qHasPixmapTexture(*this)
+ ? !texture().hasAlphaChannel() && !texture().isQBitmap()
+ : !textureImage().hasAlphaChannel();
}
return false;
diff --git a/src/gui/painting/qbrush.h b/src/gui/painting/qbrush.h
index b3aa04d..2e82246 100644
--- a/src/gui/painting/qbrush.h
+++ b/src/gui/painting/qbrush.h
@@ -125,7 +125,7 @@ private:
friend class QRasterPaintEnginePrivate;
friend struct QSpanData;
friend class QPainter;
- friend bool qHasPixmapTexture(const QBrush& brush);
+ friend bool Q_GUI_EXPORT qHasPixmapTexture(const QBrush& brush);
void detach(Qt::BrushStyle newStyle);
void init(const QColor &color, Qt::BrushStyle bs);
QScopedCustomPointer<QBrushData, QBrushDataPointerHandler> d;
diff --git a/src/gui/painting/qcolor.cpp b/src/gui/painting/qcolor.cpp
index c50004e..fa833db 100644
--- a/src/gui/painting/qcolor.cpp
+++ b/src/gui/painting/qcolor.cpp
@@ -1387,7 +1387,7 @@ QColor QColor::toHsv() const
const qreal min = Q_MIN_3(r, g, b);
const qreal delta = max - min;
color.ct.ahsv.value = qRound(max * USHRT_MAX);
- if (qFuzzyCompare(delta + 1, 1)) {
+ if (qFuzzyIsNull(delta)) {
// achromatic case, hue is undefined
color.ct.ahsv.hue = USHRT_MAX;
color.ct.ahsv.saturation = 0;
@@ -1441,7 +1441,7 @@ QColor QColor::toCmyk() const
// cmy -> cmyk
const qreal k = qMin(c, qMin(m, y));
- if (!qFuzzyCompare(k,1)) {
+ if (!qFuzzyIsNull(k - 1)) {
c = (c - k) / (1.0 - k);
m = (m - k) / (1.0 - k);
y = (y - k) / (1.0 - k);
@@ -2022,12 +2022,12 @@ QDebug operator<<(QDebug dbg, const QColor &c)
if (!c.isValid())
dbg.nospace() << "QColor(Invalid)";
else if (c.spec() == QColor::Rgb)
- dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ")";
+ dbg.nospace() << "QColor(ARGB " << c.alphaF() << ", " << c.redF() << ", " << c.greenF() << ", " << c.blueF() << ')';
else if (c.spec() == QColor::Hsv)
- dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ")";
+ dbg.nospace() << "QColor(AHSV " << c.alphaF() << ", " << c.hueF() << ", " << c.saturationF() << ", " << c.valueF() << ')';
else if (c.spec() == QColor::Cmyk)
dbg.nospace() << "QColor(ACMYK " << c.alphaF() << ", " << c.cyanF() << ", " << c.magentaF() << ", " << c.yellowF() << ", "
- << c.blackF()<< ")";
+ << c.blackF()<< ')';
return dbg.space();
#else
@@ -2116,9 +2116,7 @@ QDataStream &operator>>(QDataStream &stream, QColor &color)
return stream;
}
-#endif
-
-
+#endif // QT_NO_DATASTREAM
/*****************************************************************************
diff --git a/src/gui/painting/qcolor_p.cpp b/src/gui/painting/qcolor_p.cpp
index 5bdbee4..fb6d10c 100644
--- a/src/gui/painting/qcolor_p.cpp
+++ b/src/gui/painting/qcolor_p.cpp
@@ -49,7 +49,7 @@
#include "qrgb.h"
#include "qstringlist.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
#endif
QT_BEGIN_NAMESPACE
diff --git a/src/gui/painting/qcolormap_win.cpp b/src/gui/painting/qcolormap_win.cpp
index 7d36582..9ca2521 100644
--- a/src/gui/painting/qcolormap_win.cpp
+++ b/src/gui/painting/qcolormap_win.cpp
@@ -44,7 +44,7 @@
#include "qvector.h"
#include "qt_windows.h"
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
#endif
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 0b5e5bb..23fc1b1 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -160,46 +160,9 @@ static uint * QT_FASTCALL destFetchRGB16(uint *buffer, QRasterBuffer *rasterBuff
return buffer;
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-template <typename EnumType, int value>
-class QEnumToType
-{
-public:
- inline EnumType operator()() const
- {
- return EnumType(value);
- }
-};
-template <QImage::Format format>
-class QImageFormatToType
-{
-public:
- inline QImage::Format operator()() const
- {
- return format;
- }
-};
-// Would have used QEnumToType instead of creating a specialized version for QImageFormatToType,
-// but that causes internal compiler error on VC6
-#define Q_TEMPLATE_IMAGEFORMAT_FIX(format) , const QImageFormatToType<format> &imageFormatType
-#define Q_TEMPLATE_IMAGEFORMAT_CALL(format) , QImageFormatToType<format>()
-#define Q_TEMPLATE_ENUM_FIX(Type, Value) , const QEnumToType<Type, Value> &enumTemplateType
-#define Q_TEMPLATE_ENUM_CALL(Type, Value) , QEnumToType<Type, Value>()
-#define Q_TEMPLATE_FIX(Type) , const QTypeInfo<Type> &templateType
-#define Q_TEMPLATE_CALL(Type) , QTypeInfo<Type>()
-#else
-#define Q_TEMPLATE_IMAGEFORMAT_FIX(format)
-#define Q_TEMPLATE_IMAGEFORMAT_CALL(format)
-#define Q_TEMPLATE_ENUM_FIX(Type, Value)
-#define Q_TEMPLATE_ENUM_CALL(Type, Value)
-#define Q_TEMPLATE_FIX(Type)
-#define Q_TEMPLATE_CALL(Type)
-#endif
-
template <class DST>
Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuffer *rasterBuffer,
- int x, int y, int length
- Q_TEMPLATE_FIX(DST))
+ int x, int y, int length)
{
const DST *src = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x;
quint32 *dest = reinterpret_cast<quint32*>(buffer);
@@ -208,28 +171,7 @@ Q_STATIC_TEMPLATE_FUNCTION uint * QT_FASTCALL destFetch(uint *buffer, QRasterBuf
return buffer;
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-#define DEST_FETCH_DECL(DST) \
- static uint * QT_FASTCALL destFetch_##DST(uint *buffer, \
- QRasterBuffer *rasterBuffer, \
- int x, int y, int length) \
- { \
- return destFetch<DST>(buffer, rasterBuffer, x, y, length Q_TEMPLATE_CALL(DST)); \
- }
-
-DEST_FETCH_DECL(qargb8565)
-DEST_FETCH_DECL(qrgb666)
-DEST_FETCH_DECL(qargb6666)
-DEST_FETCH_DECL(qrgb555)
-DEST_FETCH_DECL(qrgb888)
-DEST_FETCH_DECL(qargb8555)
-DEST_FETCH_DECL(qrgb444)
-DEST_FETCH_DECL(qargb4444)
-#undef DEST_FETCH_DECL
-# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch_##Arg
-#else // !VC6 && !VC2002
# define SPANFUNC_POINTER_DESTFETCH(Arg) destFetch<Arg>
-#endif
static const DestFetchProc destFetchProc[QImage::NImageFormats] =
{
@@ -369,8 +311,7 @@ static void QT_FASTCALL destStoreRGB16(QRasterBuffer *rasterBuffer, int x, int y
template <class DST>
Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffer,
int x, int y,
- const uint *buffer, int length
- Q_TEMPLATE_FIX(DST))
+ const uint *buffer, int length)
{
DST *dest = reinterpret_cast<DST*>(rasterBuffer->scanLine(y)) + x;
const quint32p *src = reinterpret_cast<const quint32p*>(buffer);
@@ -378,28 +319,7 @@ Q_STATIC_TEMPLATE_FUNCTION void QT_FASTCALL destStore(QRasterBuffer *rasterBuffe
*dest++ = DST(*src++);
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-# define DEST_STORE_DECL(DST) \
- static void QT_FASTCALL destStore_##DST(QRasterBuffer *rasterBuffer, \
- int x, int y, \
- const uint *buffer, int length) \
- { \
- destStore<DST>(rasterBuffer, x, y, buffer, length Q_TEMPLATE_CALL(DST)); \
- }
-
-DEST_STORE_DECL(qargb8565)
-DEST_STORE_DECL(qrgb555)
-DEST_STORE_DECL(qrgb666)
-DEST_STORE_DECL(qargb6666)
-DEST_STORE_DECL(qargb8555)
-DEST_STORE_DECL(qrgb888)
-DEST_STORE_DECL(qrgb444)
-DEST_STORE_DECL(qargb4444)
-# undef DEST_FETCH_DECL
-# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore_##DEST
-#else // !VC6 && !VC2002
# define SPANFUNC_POINTER_DESTSTORE(DEST) destStore<DEST>
-#endif
static const DestStoreProc destStoreProc[QImage::NImageFormats] =
{
@@ -428,10 +348,8 @@ static const DestStoreProc destStoreProc[QImage::NImageFormats] =
We need 5 fetch methods per surface type:
untransformed
- transformed
- transformed tiled
- transformed bilinear
- transformed bilinear tiled
+ transformed (tiled and not tiled)
+ transformed bilinear (tiled and not tiled)
We don't need bounds checks for untransformed, but we need them for the other ones.
@@ -439,14 +357,12 @@ static const DestStoreProc destStoreProc[QImage::NImageFormats] =
*/
template <QImage::Format format>
-Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(format));
+Q_STATIC_TEMPLATE_FUNCTION uint QT_FASTCALL qt_fetchPixel(const uchar *scanLine, int x, const QVector<QRgb> *rgb);
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine,
- int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_Mono))
+ int x, const QVector<QRgb> *rgb)
{
bool pixel = scanLine[x>>3] & (0x80 >> (x & 7));
if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0));
@@ -456,8 +372,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_Mono>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine,
- int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_MonoLSB))
+ int x, const QVector<QRgb> *rgb)
{
bool pixel = scanLine[x>>3] & (0x1 << (x & 7));
if (rgb) return PREMUL(rgb->at(pixel ? 1 : 0));
@@ -467,8 +382,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_MonoLSB>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine,
- int x, const QVector<QRgb> *rgb
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_Indexed8))
+ int x, const QVector<QRgb> *rgb)
{
return PREMUL(rgb->at(scanLine[x]));
}
@@ -476,8 +390,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_Indexed8>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine,
- int x, const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32))
+ int x, const QVector<QRgb> *)
{
return PREMUL(((const uint *)scanLine)[x]);
}
@@ -485,8 +398,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32>(const uchar *scanLine,
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar *scanLine,
- int x, const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32_Premultiplied))
+ int x, const QVector<QRgb> *)
{
return ((const uint *)scanLine)[x];
}
@@ -494,8 +406,7 @@ uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB32_Premultiplied>(const uchar
template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB16>(const uchar *scanLine,
- int x, const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB16))
+ int x, const QVector<QRgb> *)
{
return qConvertRgb16To32(((const ushort *)scanLine)[x]);
}
@@ -504,8 +415,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8565_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB8565_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb8565 color = reinterpret_cast<const qargb8565*>(scanLine)[x];
return qt_colorConvert<quint32, qargb8565>(color, 0);
@@ -515,8 +425,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB666>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB666))
+ const QVector<QRgb> *)
{
const qrgb666 color = reinterpret_cast<const qrgb666*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb666>(color, 0);
@@ -526,8 +435,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB6666_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB6666_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb6666 color = reinterpret_cast<const qargb6666*>(scanLine)[x];
return qt_colorConvert<quint32, qargb6666>(color, 0);
@@ -537,8 +445,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB555>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB555))
+ const QVector<QRgb> *)
{
const qrgb555 color = reinterpret_cast<const qrgb555*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb555>(color, 0);
@@ -548,8 +455,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB8555_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB8555_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb8555 color = reinterpret_cast<const qargb8555*>(scanLine)[x];
return qt_colorConvert<quint32, qargb8555>(color, 0);
@@ -559,8 +465,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB888>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB888))
+ const QVector<QRgb> *)
{
const qrgb888 color = reinterpret_cast<const qrgb888*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb888>(color, 0);
@@ -570,8 +475,7 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_RGB444>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_RGB444))
+ const QVector<QRgb> *)
{
const qrgb444 color = reinterpret_cast<const qrgb444*>(scanLine)[x];
return qt_colorConvert<quint32, qrgb444>(color, 0);
@@ -581,47 +485,24 @@ template<>
Q_STATIC_TEMPLATE_SPECIALIZATION
uint QT_FASTCALL qt_fetchPixel<QImage::Format_ARGB4444_Premultiplied>(const uchar *scanLine,
int x,
- const QVector<QRgb> *
- Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB4444_Premultiplied))
+ const QVector<QRgb> *)
{
const qargb4444 color = reinterpret_cast<const qargb4444*>(scanLine)[x];
return qt_colorConvert<quint32, qargb4444>(color, 0);
}
-typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *);
-
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-
-// explicit template instantiations needed to compile with VC6 and VC2002
-
-#define SPANFUNC_INSTANTIATION_FETCHPIXEL(Arg) \
- static inline uint fetchPixel_##Arg(const uchar * scanLine, int x, const QVector<QRgb> * rgb) \
-{ \
- return qt_fetchPixel<QImage::Arg>(scanLine, x, rgb Q_TEMPLATE_IMAGEFORMAT_CALL(QImage::Arg)); \
+template<>
+Q_STATIC_TEMPLATE_SPECIALIZATION
+uint QT_FASTCALL qt_fetchPixel<QImage::Format_Invalid>(const uchar *,
+ int ,
+ const QVector<QRgb> *)
+{
+ return 0;
}
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_Mono);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_MonoLSB);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_Indexed8);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB32_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB32);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB16);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB8565_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB666);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB6666_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB555);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB8555_Premultiplied);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB888);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_RGB444);
-SPANFUNC_INSTANTIATION_FETCHPIXEL(Format_ARGB4444_Premultiplied);
-
-#undef SPANFUNC_INSTANTIATION_FETCHPIXEL
-
-#define SPANFUNC_POINTER_FETCHPIXEL(Arg) fetchPixel_##Arg
+typedef uint (QT_FASTCALL *FetchPixelProc)(const uchar *scanLine, int x, const QVector<QRgb> *);
-#else // !VC6 && !VC2002
-# define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg>
-#endif
+#define SPANFUNC_POINTER_FETCHPIXEL(Arg) qt_fetchPixel<QImage::Arg>
static const FetchPixelProc fetchPixelProc[QImage::NImageFormats] =
@@ -656,11 +537,11 @@ enum TextureBlendType {
template <QImage::Format format>
Q_STATIC_TEMPLATE_FUNCTION const uint * QT_FASTCALL qt_fetchUntransformed(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length Q_TEMPLATE_IMAGEFORMAT_FIX(format))
+ int y, int x, int length)
{
const uchar *scanLine = data->texture.scanLine(y);
for (int i = 0; i < length; ++i)
- buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable Q_TEMPLATE_IMAGEFORMAT_CALL(format));
+ buffer[i] = qt_fetchPixel<format>(scanLine, x + i, data->texture.colorTable);
return buffer;
}
@@ -668,13 +549,15 @@ template <>
Q_STATIC_TEMPLATE_SPECIALIZATION const uint * QT_FASTCALL
qt_fetchUntransformed<QImage::Format_ARGB32_Premultiplied>(uint *, const Operator *,
const QSpanData *data,
- int y, int x, int Q_TEMPLATE_IMAGEFORMAT_FIX(QImage::Format_ARGB32_Premultiplied))
+ int y, int x, int)
{
const uchar *scanLine = data->texture.scanLine(y);
return ((const uint *)scanLine) + x;
}
-static const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data,
+template<TextureBlendType blendType> /* either BlendTransformed or BlendTransformedTiled */
+Q_STATIC_TEMPLATE_FUNCTION
+const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *, const QSpanData *data,
int y, int x, int length)
{
FetchPixelProc fetch = fetchPixelProc[data->texture.format];
@@ -701,84 +584,23 @@ static const uint * QT_FASTCALL fetchTransformed(uint *buffer, const Operator *,
int px = fx >> 16;
int py = fy >> 16;
- bool out = (px < 0) || (px >= image_width)
- || (py < 0) || (py >= image_height);
+ if (blendType == BlendTransformedTiled) {
+ px %= image_width;
+ py %= image_height;
+ if (px < 0) px += image_width;
+ if (py < 0) py += image_height;
- const uchar *scanLine = data->texture.scanLine(py);
- *b = out ? uint(0) : fetch(scanLine, px, data->texture.colorTable);
- fx += fdx;
- fy += fdy;
- ++b;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
- qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
- qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
- qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
-
- while (b < end) {
- const qreal iw = fw == 0 ? 1 : 1 / fw;
- const qreal tx = fx * iw;
- const qreal ty = fy * iw;
- const int px = int(tx) - (tx < 0);
- const int py = int(ty) - (ty < 0);
-
- bool out = (px < 0) || (px >= image_width)
- || (py < 0) || (py >= image_height);
-
- const uchar *scanLine = data->texture.scanLine(py);
- *b = out ? uint(0) : fetch(scanLine, px, data->texture.colorTable);
- fx += fdx;
- fy += fdy;
- fw += fdw;
- //force increment to avoid /0
- if (!fw) {
- fw += fdw;
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ } else {
+ if ((px < 0) || (px >= image_width)
+ || (py < 0) || (py >= image_height)) {
+ *b = uint(0);
+ } else {
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ }
}
- ++b;
- }
- }
-
- return buffer;
-}
-
-static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
-{
- FetchPixelProc fetch = fetchPixelProc[data->texture.format];
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- const qreal cx = x + 0.5;
- const qreal cy = y + 0.5;
-
- const uint *end = buffer + length;
- uint *b = buffer;
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- int fx = int((data->m21 * cy
- + data->m11 * cx + data->dx) * fixed_scale);
- int fy = int((data->m22 * cy
- + data->m12 * cx + data->dy) * fixed_scale);
-
- while (b < end) {
- int px = fx >> 16;
- int py = fy >> 16;
-
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
-
- const uchar *scanLine = data->texture.scanLine(py);
- *b = fetch(scanLine, px, data->texture.colorTable);
fx += fdx;
fy += fdy;
++b;
@@ -799,13 +621,23 @@ static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operat
int px = int(tx) - (tx < 0);
int py = int(ty) - (ty < 0);
- px %= image_width;
- py %= image_height;
- if (px < 0) px += image_width;
- if (py < 0) py += image_height;
+ if (blendType == BlendTransformedTiled) {
+ px %= image_width;
+ py %= image_height;
+ if (px < 0) px += image_width;
+ if (py < 0) py += image_height;
- const uchar *scanLine = data->texture.scanLine(py);
- *b = fetch(scanLine, px, data->texture.colorTable);
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ } else {
+ if ((px < 0) || (px >= image_width)
+ || (py < 0) || (py >= image_height)) {
+ *b = uint(0);
+ } else {
+ const uchar *scanLine = data->texture.scanLine(py);
+ *b = fetch(scanLine, px, data->texture.colorTable);
+ }
+ }
fx += fdx;
fy += fdy;
fw += fdw;
@@ -820,10 +652,12 @@ static const uint * QT_FASTCALL fetchTransformedTiled(uint *buffer, const Operat
return buffer;
}
-static const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
+template<TextureBlendType blendType, QImage::Format format> /* blendType = BlendTransformedBilinear or BlendTransformedBilinearTiled */
+Q_STATIC_TEMPLATE_FUNCTION
+const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Operator *, const QSpanData *data,
+ int y, int x, int length)
{
- FetchPixelProc fetch = fetchPixelProc[data->texture.format];
+ FetchPixelProc fetch = (format != QImage::Format_Invalid) ? FetchPixelProc(qt_fetchPixel<format>) : fetchPixelProc[data->texture.format];
int image_width = data->texture.width;
int image_height = data->texture.height;
@@ -856,130 +690,27 @@ static const uint * QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Ope
int idistx = 256 - distx;
int idisty = 256 - disty;
- x1 = qBound(0, x1, image_width - 1);
- x2 = qBound(0, x2, image_width - 1);
- y1 = qBound(0, y1, image_height - 1);
- y2 = qBound(0, y2, image_height - 1);
-
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
- uint tl = fetch(s1, x1, data->texture.colorTable);
- uint tr = fetch(s1, x2, data->texture.colorTable);
- uint bl = fetch(s2, x1, data->texture.colorTable);
- uint br = fetch(s2, x2, data->texture.colorTable);
-
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
-
- fx += fdx;
- fy += fdy;
- ++b;
- }
- } else {
- const qreal fdx = data->m11;
- const qreal fdy = data->m12;
- const qreal fdw = data->m13;
-
- qreal fx = data->m21 * cy + data->m11 * cx + data->dx;
- qreal fy = data->m22 * cy + data->m12 * cx + data->dy;
- qreal fw = data->m23 * cy + data->m13 * cx + data->m33;
-
- while (b < end) {
- const qreal iw = fw == 0 ? 1 : 1 / fw;
- const qreal px = fx * iw - 0.5;
- const qreal py = fy * iw - 0.5;
-
- int x1 = int(px) - (px < 0);
- int x2 = x1 + 1;
- int y1 = int(py) - (py < 0);
- int y2 = y1 + 1;
-
- int distx = int((px - x1) * 256);
- int disty = int((py - y1) * 256);
- int idistx = 256 - distx;
- int idisty = 256 - disty;
-
- x1 = qBound(0, x1, image_width - 1);
- x2 = qBound(0, x2, image_width - 1);
- y1 = qBound(0, y1, image_height - 1);
- y2 = qBound(0, y2, image_height - 1);
-
- const uchar *s1 = data->texture.scanLine(y1);
- const uchar *s2 = data->texture.scanLine(y2);
-
- uint tl = fetch(s1, x1, data->texture.colorTable);
- uint tr = fetch(s1, x2, data->texture.colorTable);
- uint bl = fetch(s2, x1, data->texture.colorTable);
- uint br = fetch(s2, x2, data->texture.colorTable);
-
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- *b = INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
-
- fx += fdx;
- fy += fdy;
- fw += fdw;
- //force increment to avoid /0
- if (!fw) {
- fw += fdw;
+ if (blendType == BlendTransformedBilinearTiled) {
+ x1 %= image_width;
+ x2 %= image_width;
+ y1 %= image_height;
+ y2 %= image_height;
+
+ if (x1 < 0) x1 += image_width;
+ if (x2 < 0) x2 += image_width;
+ if (y1 < 0) y1 += image_height;
+ if (y2 < 0) y2 += image_height;
+
+ Q_ASSERT(x1 >= 0 && x1 < image_width);
+ Q_ASSERT(x2 >= 0 && x2 < image_width);
+ Q_ASSERT(y1 >= 0 && y1 < image_height);
+ Q_ASSERT(y2 >= 0 && y2 < image_height);
+ } else {
+ x1 = qBound(0, x1, image_width - 1);
+ x2 = qBound(0, x2, image_width - 1);
+ y1 = qBound(0, y1, image_height - 1);
+ y2 = qBound(0, y2, image_height - 1);
}
- ++b;
- }
- }
-
- return buffer;
-}
-
-static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, const Operator *, const QSpanData *data,
- int y, int x, int length)
-{
- FetchPixelProc fetch = fetchPixelProc[data->texture.format];
-
- int image_width = data->texture.width;
- int image_height = data->texture.height;
-
- const qreal cx = x + 0.5;
- const qreal cy = y + 0.5;
-
- const uint *end = buffer + length;
- uint *b = buffer;
- if (data->fast_matrix) {
- // The increment pr x in the scanline
- int fdx = (int)(data->m11 * fixed_scale);
- int fdy = (int)(data->m12 * fixed_scale);
-
- int fx = int((data->m21 * cy + data->m11 * cx + data->dx) * fixed_scale);
- int fy = int((data->m22 * cy + data->m12 * cx + data->dy) * fixed_scale);
-
- fx -= half_point;
- fy -= half_point;
- while (b < end) {
- int x1 = (fx >> 16);
- int x2 = x1 + 1;
- int y1 = (fy >> 16);
- int y2 = y1 + 1;
-
- int distx = ((fx - (x1 << 16)) >> 8);
- int disty = ((fy - (y1 << 16)) >> 8);
- int idistx = 256 - distx;
- int idisty = 256 - disty;
-
- x1 %= image_width;
- x2 %= image_width;
- y1 %= image_height;
- y2 %= image_height;
-
- if (x1 < 0) x1 += image_width;
- if (x2 < 0) x2 += image_width;
- if (y1 < 0) y1 += image_height;
- if (y2 < 0) y2 += image_height;
-
- Q_ASSERT(x1 >= 0 && x1 < image_width);
- Q_ASSERT(x2 >= 0 && x2 < image_width);
- Q_ASSERT(y1 >= 0 && y1 < image_height);
- Q_ASSERT(y2 >= 0 && y2 < image_height);
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -1021,20 +752,27 @@ static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, cons
int idistx = 256 - distx;
int idisty = 256 - disty;
- x1 %= image_width;
- x2 %= image_width;
- y1 %= image_height;
- y2 %= image_height;
-
- if (x1 < 0) x1 += image_width;
- if (x2 < 0) x2 += image_width;
- if (y1 < 0) y1 += image_height;
- if (y2 < 0) y2 += image_height;
-
- Q_ASSERT(x1 >= 0 && x1 < image_width);
- Q_ASSERT(x2 >= 0 && x2 < image_width);
- Q_ASSERT(y1 >= 0 && y1 < image_height);
- Q_ASSERT(y2 >= 0 && y2 < image_height);
+ if (blendType == BlendTransformedBilinearTiled) {
+ x1 %= image_width;
+ x2 %= image_width;
+ y1 %= image_height;
+ y2 %= image_height;
+
+ if (x1 < 0) x1 += image_width;
+ if (x2 < 0) x2 += image_width;
+ if (y1 < 0) y1 += image_height;
+ if (y2 < 0) y2 += image_height;
+
+ Q_ASSERT(x1 >= 0 && x1 < image_width);
+ Q_ASSERT(x2 >= 0 && x2 < image_width);
+ Q_ASSERT(y1 >= 0 && y1 < image_height);
+ Q_ASSERT(y2 >= 0 && y2 < image_height);
+ } else {
+ x1 = qBound(0, x1, image_width - 1);
+ x2 = qBound(0, x2, image_width - 1);
+ y1 = qBound(0, y1, image_height - 1);
+ y2 = qBound(0, y2, image_height - 1);
+ }
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
@@ -1062,39 +800,7 @@ static const uint * QT_FASTCALL fetchTransformedBilinearTiled(uint *buffer, cons
return buffer;
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-
-// explicit template instantiations needed to compile with VC6 and VC2002
-
-#define SPANFUNC_POINTER_FETCHUNTRANSFORMED(Arg) \
- const uint *qt_fetchUntransformed_##Arg(uint *buffer, const Operator *op, const QSpanData *data, \
- int y, int x, int length) \
-{ \
- return qt_fetchUntransformed<QImage::Arg>(buffer, op, data, y, x, length Q_TEMPLATE_IMAGEFORMAT_CALL(QImage::Arg)); \
-}
-
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_Mono);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_MonoLSB);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_Indexed8);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB32_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB32);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB16);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB8565_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB666);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB6666_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB555);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB8555_Premultiplied);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB888);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_RGB444);
-SPANFUNC_POINTER_FETCHUNTRANSFORMED(Format_ARGB4444_Premultiplied);
-
-#undef SPANFUNC_POINTER_FETCHUNTRANSFORMED
-
-#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed_##Arg
-
-#else // !VC6 && !VC2002
-# define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg>
-#endif
+#define SPANFUNC_POINTER_FETCHHUNTRANSFORMED(Arg) qt_fetchUntransformed<QImage::Arg>
static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
// Untransformed
@@ -1138,75 +844,75 @@ static const SourceFetchProc sourceFetch[NBlendTypes][QImage::NImageFormats] = {
// Transformed
{
0, // Invalid
- fetchTransformed, // Mono
- fetchTransformed, // MonoLsb
- fetchTransformed, // Indexed8
- fetchTransformed, // RGB32
- fetchTransformed, // ARGB32
- fetchTransformed, // ARGB32_Premultiplied
- fetchTransformed, // RGB16
- fetchTransformed, // ARGB8565_Premultiplied
- fetchTransformed, // RGB666
- fetchTransformed, // ARGB6666_Premultiplied
- fetchTransformed, // RGB555
- fetchTransformed, // ARGB8555_Premultiplied
- fetchTransformed, // RGB888
- fetchTransformed, // RGB444
- fetchTransformed, // ARGB4444_Premultiplied
+ fetchTransformed<BlendTransformed>, // Mono
+ fetchTransformed<BlendTransformed>, // MonoLsb
+ fetchTransformed<BlendTransformed>, // Indexed8
+ fetchTransformed<BlendTransformed>, // RGB32
+ fetchTransformed<BlendTransformed>, // ARGB32
+ fetchTransformed<BlendTransformed>, // ARGB32_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB16
+ fetchTransformed<BlendTransformed>, // ARGB8565_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB666
+ fetchTransformed<BlendTransformed>, // ARGB6666_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB555
+ fetchTransformed<BlendTransformed>, // ARGB8555_Premultiplied
+ fetchTransformed<BlendTransformed>, // RGB888
+ fetchTransformed<BlendTransformed>, // RGB444
+ fetchTransformed<BlendTransformed>, // ARGB4444_Premultiplied
},
{
0, // TransformedTiled
- fetchTransformedTiled, // Mono
- fetchTransformedTiled, // MonoLsb
- fetchTransformedTiled, // Indexed8
- fetchTransformedTiled, // RGB32
- fetchTransformedTiled, // ARGB32
- fetchTransformedTiled, // ARGB32_Premultiplied
- fetchTransformedTiled, // RGB16
- fetchTransformedTiled, // ARGB8565_Premultiplied
- fetchTransformedTiled, // RGB666
- fetchTransformedTiled, // ARGB6666_Premultiplied
- fetchTransformedTiled, // RGB555
- fetchTransformedTiled, // ARGB8555_Premultiplied
- fetchTransformedTiled, // RGB888
- fetchTransformedTiled, // RGB444
- fetchTransformedTiled, // ARGB4444_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // Mono
+ fetchTransformed<BlendTransformedTiled>, // MonoLsb
+ fetchTransformed<BlendTransformedTiled>, // Indexed8
+ fetchTransformed<BlendTransformedTiled>, // RGB32
+ fetchTransformed<BlendTransformedTiled>, // ARGB32
+ fetchTransformed<BlendTransformedTiled>, // ARGB32_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB16
+ fetchTransformed<BlendTransformedTiled>, // ARGB8565_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB666
+ fetchTransformed<BlendTransformedTiled>, // ARGB6666_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB555
+ fetchTransformed<BlendTransformedTiled>, // ARGB8555_Premultiplied
+ fetchTransformed<BlendTransformedTiled>, // RGB888
+ fetchTransformed<BlendTransformedTiled>, // RGB444
+ fetchTransformed<BlendTransformedTiled>, // ARGB4444_Premultiplied
},
{
0, // Bilinear
- fetchTransformedBilinear, // Mono
- fetchTransformedBilinear, // MonoLsb
- fetchTransformedBilinear, // Indexed8
- fetchTransformedBilinear, // RGB32
- fetchTransformedBilinear, // ARGB32
- fetchTransformedBilinear, // ARGB32_Premultiplied
- fetchTransformedBilinear, // RGB16
- fetchTransformedBilinear, // ARGB8565_Premultiplied
- fetchTransformedBilinear, // RGB666
- fetchTransformedBilinear, // ARGB6666_Premultiplied
- fetchTransformedBilinear, // RGB555
- fetchTransformedBilinear, // ARGB8555_Premultiplied
- fetchTransformedBilinear, // RGB888
- fetchTransformedBilinear, // RGB444
- fetchTransformedBilinear // ARGB4444_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Mono
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // MonoLsb
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // Indexed8
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // RGB32
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32>, // ARGB32
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB16
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8565_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB666
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB6666_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB555
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // ARGB8555_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB888
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid>, // RGB444
+ fetchTransformedBilinear<BlendTransformedBilinear, QImage::Format_Invalid> // ARGB4444_Premultiplied
},
{
0, // BilinearTiled
- fetchTransformedBilinearTiled, // Mono
- fetchTransformedBilinearTiled, // MonoLsb
- fetchTransformedBilinearTiled, // Indexed8
- fetchTransformedBilinearTiled, // RGB32
- fetchTransformedBilinearTiled, // ARGB32
- fetchTransformedBilinearTiled, // ARGB32_Premultiplied
- fetchTransformedBilinearTiled, // RGB16
- fetchTransformedBilinearTiled, // ARGB8565_Premultiplied
- fetchTransformedBilinearTiled, // RGB666
- fetchTransformedBilinearTiled, // ARGB6666_Premultiplied
- fetchTransformedBilinearTiled, // RGB555
- fetchTransformedBilinearTiled, // ARGB8555_Premultiplied
- fetchTransformedBilinearTiled, // RGB888
- fetchTransformedBilinearTiled, // RGB444
- fetchTransformedBilinearTiled // ARGB4444_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Mono
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // MonoLsb
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // Indexed8
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // RGB32
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32>, // ARGB32
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_ARGB32_Premultiplied>, // ARGB32_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB16
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8565_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB666
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB6666_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB555
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // ARGB8555_Premultiplied
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB888
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid>, // RGB444
+ fetchTransformedBilinear<BlendTransformedBilinearTiled, QImage::Format_Invalid> // ARGB4444_Premultiplied
},
};
@@ -3371,8 +3077,7 @@ static void blend_color_argb(int count, const QSpan *spans, void *userData)
}
template <class T>
-Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_FIX(T))
+Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
Operator op = getOperator(data, spans, count);
@@ -3418,28 +3123,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendColor(int count, const QSpan *spans, void *
blend_color_generic(count, spans, userData);
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-#define BLEND_COLOR_DECL(DST) \
- static void blendColor_##DST(int count, \
- const QSpan *spans, \
- void *userData) \
- { \
- blendColor<DST>(count, spans, userData Q_TEMPLATE_CALL(DST)); \
- }
-
-BLEND_COLOR_DECL(qargb8565)
-BLEND_COLOR_DECL(qrgb666)
-BLEND_COLOR_DECL(qargb6666)
-BLEND_COLOR_DECL(qrgb555)
-BLEND_COLOR_DECL(qargb8555)
-BLEND_COLOR_DECL(qrgb888)
-BLEND_COLOR_DECL(qrgb444)
-BLEND_COLOR_DECL(qargb4444)
-#undef DEST_FETCH_DECL
-#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor_##DST
-#else // !VC6 && !VC2002
-# define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST>
-#endif
+#define SPANFUNC_POINTER_BLENDCOLOR(DST) blendColor<DST>
static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
{
@@ -3517,45 +3201,117 @@ static void blend_color_rgb16(int count, const QSpan *spans, void *userData)
blend_color_generic(count, spans, userData);
}
-template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+template <typename T>
+void handleSpans(int count, const QSpan *spans, const QSpanData *data, T &handler)
{
- QSpanData *data = reinterpret_cast<QSpanData *>(userData);
-
- uint buffer[buffer_size];
- uint src_buffer[buffer_size];
- Operator op = getOperator(data, spans, count);
-
uint const_alpha = 256;
if (data->type == QSpanData::Texture)
const_alpha = data->texture.const_alpha;
- while (count--) {
+ int coverage = 0;
+ while (count) {
int x = spans->x;
- int length = spans->len;
- const int coverage = (spans->coverage * const_alpha) >> 8;
+ const int y = spans->y;
+ int right = x + spans->len;
+
+ // compute length of adjacent spans
+ for (int i = 1; i < count && spans[i].y == y && spans[i].x == right; ++i)
+ right += spans[i].len;
+ int length = right - x;
+
while (length) {
int l = qMin(buffer_size, length);
- const uint *src = op.src_fetch(src_buffer, &op, data, spans->y, x, l);
- if (spanMethod == RegularSpans) {
- uint *dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, spans->y, l) : buffer;
- op.func(dest, src, l, coverage);
- if (op.dest_store)
- op.dest_store(data->rasterBuffer, x, spans->y, dest, l);
- } else {
- drawBufferSpan(data, src, l, x, spans->y, l, coverage);
- }
- x += l;
length -= l;
+
+ int process_length = l;
+ int process_x = x;
+
+ const uint *src = handler.fetch(process_x, y, process_length);
+ int offset = 0;
+ while (l > 0) {
+ if (x == spans->x) // new span?
+ coverage = (spans->coverage * const_alpha) >> 8;
+
+ int right = spans->x + spans->len;
+ int len = qMin(l, right - x);
+
+ handler.process(x, y, len, coverage, src, offset);
+
+ l -= len;
+ x += len;
+ offset += len;
+
+ if (x == right) { // done with current span?
+ ++spans;
+ --count;
+ }
+ }
+ handler.store(process_x, y, process_length);
}
- ++spans;
}
}
+struct QBlendBase
+{
+ QBlendBase(QSpanData *d, Operator o)
+ : data(d)
+ , op(o)
+ , dest(0)
+ {
+ }
+
+ QSpanData *data;
+ Operator op;
+
+ uint *dest;
+
+ uint buffer[buffer_size];
+ uint src_buffer[buffer_size];
+};
+
+template <SpanMethod spanMethod>
+class BlendSrcGeneric : public QBlendBase
+{
+public:
+ BlendSrcGeneric(QSpanData *d, Operator o)
+ : QBlendBase(d, o)
+ {
+ }
+
+ const uint *fetch(int x, int y, int len)
+ {
+ if (spanMethod == RegularSpans)
+ dest = op.dest_fetch ? op.dest_fetch(buffer, data->rasterBuffer, x, y, len) : buffer;
+
+ return op.src_fetch(src_buffer, &op, data, y, x, len);
+ }
+
+ void process(int x, int y, int len, int coverage, const uint *src, int offset)
+ {
+ if (spanMethod == RegularSpans)
+ op.func(dest + offset, src + offset, len, coverage);
+ else
+ drawBufferSpan(data, src + offset, len, x, y, len, coverage);
+ }
+
+ void store(int x, int y, int len)
+ {
+ if (spanMethod == RegularSpans && op.dest_store) {
+ op.dest_store(data->rasterBuffer, x, y, dest, len);
+ }
+ }
+};
+
+template <SpanMethod spanMethod>
+Q_STATIC_TEMPLATE_FUNCTION void blend_src_generic(int count, const QSpan *spans, void *userData)
+{
+ QSpanData *data = reinterpret_cast<QSpanData *>(userData);
+ BlendSrcGeneric<spanMethod> blend(data, getOperator(data, spans, count));
+ handleSpans(count, spans, data, blend);
+}
+
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -3606,13 +3362,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_generic(int count, const QSp
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_untransformed_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_untransformed_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_untransformed_generic<spanMethod>(count, spans, userData);
return;
}
@@ -4858,8 +4613,7 @@ void QT_FASTCALL blendUntransformed(int count, const QSpan *spans, void *userDat
if (mode != QPainter::CompositionMode_SourceOver &&
mode != QPainter::CompositionMode_Source)
{
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -4921,8 +4675,7 @@ static void blend_untransformed_rgb888(int count, const QSpan *spans,
blendUntransformed<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb6666(int count, const QSpan *spans,
@@ -4937,8 +4690,7 @@ static void blend_untransformed_argb6666(int count, const QSpan *spans,
blendUntransformed<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb666(int count, const QSpan *spans,
@@ -4953,8 +4705,7 @@ static void blend_untransformed_rgb666(int count, const QSpan *spans,
blendUntransformed<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb8565(int count, const QSpan *spans,
@@ -4969,8 +4720,7 @@ static void blend_untransformed_argb8565(int count, const QSpan *spans,
blendUntransformed<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb565(int count, const QSpan *spans,
@@ -4985,8 +4735,7 @@ static void blend_untransformed_rgb565(int count, const QSpan *spans,
blendUntransformed<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb8555(int count, const QSpan *spans,
@@ -5001,8 +4750,7 @@ static void blend_untransformed_argb8555(int count, const QSpan *spans,
blendUntransformed<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb555(int count, const QSpan *spans,
@@ -5017,8 +4765,7 @@ static void blend_untransformed_rgb555(int count, const QSpan *spans,
blendUntransformed<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_argb4444(int count, const QSpan *spans,
@@ -5033,8 +4780,7 @@ static void blend_untransformed_argb4444(int count, const QSpan *spans,
blendUntransformed<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
static void blend_untransformed_rgb444(int count, const QSpan *spans,
@@ -5049,13 +4795,11 @@ static void blend_untransformed_rgb444(int count, const QSpan *spans,
blendUntransformed<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_untransformed_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_untransformed_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
@@ -5109,13 +4853,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_generic(int count, const QSpan *span
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_tiled_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_tiled_generic<spanMethod>(count, spans, userData);
return;
}
@@ -5171,8 +4914,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTiled(int count, const QSpan *spans, void *
if (mode != QPainter::CompositionMode_SourceOver &&
mode != QPainter::CompositionMode_Source)
{
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -5242,8 +4984,7 @@ static void blend_tiled_rgb888(int count, const QSpan *spans, void *userData)
blendTiled<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData)
@@ -5257,8 +4998,7 @@ static void blend_tiled_argb6666(int count, const QSpan *spans, void *userData)
blendTiled<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData)
@@ -5272,8 +5012,7 @@ static void blend_tiled_rgb666(int count, const QSpan *spans, void *userData)
blendTiled<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData)
@@ -5287,8 +5026,7 @@ static void blend_tiled_argb8565(int count, const QSpan *spans, void *userData)
blendTiled<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
@@ -5302,8 +5040,7 @@ static void blend_tiled_rgb565(int count, const QSpan *spans, void *userData)
blendTiled<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData)
@@ -5317,8 +5054,7 @@ static void blend_tiled_argb8555(int count, const QSpan *spans, void *userData)
blendTiled<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData)
@@ -5332,8 +5068,7 @@ static void blend_tiled_rgb555(int count, const QSpan *spans, void *userData)
blendTiled<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData)
@@ -5347,8 +5082,7 @@ static void blend_tiled_argb4444(int count, const QSpan *spans, void *userData)
blendTiled<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData)
@@ -5362,19 +5096,17 @@ static void blend_tiled_rgb444(int count, const QSpan *spans, void *userData)
blendTiled<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_tiled_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_tiled_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -5553,8 +5285,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedBilinear(int count, const QSpan
if (mode != QPainter::CompositionMode_SourceOver) {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -5757,8 +5488,7 @@ static void blend_transformed_bilinear_rgb888(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, void *userData)
@@ -5772,8 +5502,7 @@ static void blend_transformed_bilinear_argb6666(int count, const QSpan *spans, v
blendTransformedBilinear<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, void *userData)
@@ -5787,8 +5516,7 @@ static void blend_transformed_bilinear_rgb666(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, void *userData)
@@ -5802,8 +5530,7 @@ static void blend_transformed_bilinear_argb8565(int count, const QSpan *spans, v
blendTransformedBilinear<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
@@ -5818,8 +5545,7 @@ static void blend_transformed_bilinear_rgb565(int count, const QSpan *spans,
blendTransformedBilinear<qrgb565, qargb8565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, void *userData)
@@ -5833,8 +5559,7 @@ static void blend_transformed_bilinear_argb8555(int count, const QSpan *spans, v
blendTransformedBilinear<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, void *userData)
@@ -5848,8 +5573,7 @@ static void blend_transformed_bilinear_rgb555(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, void *userData)
@@ -5863,8 +5587,7 @@ static void blend_transformed_bilinear_argb4444(int count, const QSpan *spans, v
blendTransformedBilinear<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, void *userData)
@@ -5878,18 +5601,16 @@ static void blend_transformed_bilinear_rgb444(int count, const QSpan *spans, voi
blendTransformedBilinear<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -6075,13 +5796,12 @@ Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_bilinear_tiled_argb(int count,
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -6203,8 +5923,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformed(int count, const QSpan *spans,
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
if (mode != QPainter::CompositionMode_SourceOver) {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -6353,8 +6072,7 @@ static void blend_transformed_rgb888(int count, const QSpan *spans,
blendTransformed<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb6666(int count, const QSpan *spans,
@@ -6369,8 +6087,7 @@ static void blend_transformed_argb6666(int count, const QSpan *spans,
blendTransformed<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb666(int count, const QSpan *spans,
@@ -6385,8 +6102,7 @@ static void blend_transformed_rgb666(int count, const QSpan *spans,
blendTransformed<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb8565(int count, const QSpan *spans,
@@ -6401,8 +6117,7 @@ static void blend_transformed_argb8565(int count, const QSpan *spans,
blendTransformed<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb565(int count, const QSpan *spans,
@@ -6417,8 +6132,7 @@ static void blend_transformed_rgb565(int count, const QSpan *spans,
blendTransformed<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb8555(int count, const QSpan *spans,
@@ -6433,8 +6147,7 @@ static void blend_transformed_argb8555(int count, const QSpan *spans,
blendTransformed<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb555(int count, const QSpan *spans,
@@ -6449,8 +6162,7 @@ static void blend_transformed_rgb555(int count, const QSpan *spans,
blendTransformed<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_argb4444(int count, const QSpan *spans,
@@ -6465,8 +6177,7 @@ static void blend_transformed_argb4444(int count, const QSpan *spans,
blendTransformed<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_rgb444(int count, const QSpan *spans,
@@ -6481,18 +6192,16 @@ static void blend_transformed_rgb444(int count, const QSpan *spans,
blendTransformed<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
template <SpanMethod spanMethod>
-Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData
- Q_TEMPLATE_ENUM_FIX(SpanMethod, spanMethod))
+Q_STATIC_TEMPLATE_FUNCTION void blend_transformed_tiled_argb(int count, const QSpan *spans, void *userData)
{
QSpanData *data = reinterpret_cast<QSpanData *>(userData);
if (data->texture.format != QImage::Format_ARGB32_Premultiplied
&& data->texture.format != QImage::Format_RGB32) {
- blend_src_generic<spanMethod>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, spanMethod));
+ blend_src_generic<spanMethod>(count, spans, userData);
return;
}
@@ -6626,8 +6335,7 @@ Q_STATIC_TEMPLATE_FUNCTION void blendTransformedTiled(int count, const QSpan *sp
QPainter::CompositionMode mode = data->rasterBuffer->compositionMode;
if (mode != QPainter::CompositionMode_SourceOver) {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
return;
}
@@ -6777,8 +6485,7 @@ static void blend_transformed_tiled_rgb888(int count, const QSpan *spans,
blendTransformedTiled<qrgb888, qrgb888>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb6666(int count, const QSpan *spans,
@@ -6793,8 +6500,7 @@ static void blend_transformed_tiled_argb6666(int count, const QSpan *spans,
blendTransformedTiled<qargb6666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb666(int count, const QSpan *spans,
@@ -6809,8 +6515,7 @@ static void blend_transformed_tiled_rgb666(int count, const QSpan *spans,
blendTransformedTiled<qrgb666, qrgb666>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb8565(int count, const QSpan *spans,
@@ -6825,8 +6530,7 @@ static void blend_transformed_tiled_argb8565(int count, const QSpan *spans,
blendTransformedTiled<qargb8565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
@@ -6841,8 +6545,7 @@ static void blend_transformed_tiled_rgb565(int count, const QSpan *spans,
blendTransformedTiled<qrgb565, qrgb565>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb8555(int count, const QSpan *spans,
@@ -6857,8 +6560,7 @@ static void blend_transformed_tiled_argb8555(int count, const QSpan *spans,
blendTransformedTiled<qargb8555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb555(int count, const QSpan *spans,
@@ -6873,8 +6575,7 @@ static void blend_transformed_tiled_rgb555(int count, const QSpan *spans,
blendTransformedTiled<qrgb555, qrgb555>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_argb4444(int count, const QSpan *spans,
@@ -6889,8 +6590,7 @@ static void blend_transformed_tiled_argb4444(int count, const QSpan *spans,
blendTransformedTiled<qargb4444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
static void blend_transformed_tiled_rgb444(int count, const QSpan *spans,
@@ -6905,36 +6605,10 @@ static void blend_transformed_tiled_rgb444(int count, const QSpan *spans,
blendTransformedTiled<qrgb444, qrgb444>(count, spans, userData);
else
#endif
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
-#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 && !defined(Q_CC_INTEL)
-
-// explicit template instantiations needed to compile with VC6 and VC2002
-
-#define SPANFUNC_INSTANTIATION(Name, Arg) \
-static inline void Name##_##Arg(int count, const QSpan *spans, void *userData) \
-{ \
- Name<Arg>(count, spans, userData Q_TEMPLATE_ENUM_CALL(SpanMethod, Arg)); \
-}
-
-SPANFUNC_INSTANTIATION(blend_untransformed_generic, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_untransformed_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_tiled_generic, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_tiled_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_src_generic, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_tiled_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_bilinear_argb, RegularSpans);
-SPANFUNC_INSTANTIATION(blend_transformed_bilinear_tiled_argb, RegularSpans);
-#undef SPANFUNC_INSTANTIATION
-
-#define SPANFUNC_POINTER(Name, Arg) Name##_##Arg
-
-#else // !VC6 && !VC2002
# define SPANFUNC_POINTER(Name, Arg) Name<Arg>
-#endif
/* Image formats here are target formats */
@@ -7301,8 +6975,7 @@ static void qt_gradient_quint32(int count, const QSpan *spans, void *userData)
}
} else {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
}
@@ -7350,8 +7023,7 @@ static void qt_gradient_quint16(int count, const QSpan *spans, void *userData)
data->solid.color = oldColor;
} else {
- blend_src_generic<RegularSpans>(count, spans, userData
- Q_TEMPLATE_ENUM_CALL(SpanMethod, RegularSpans));
+ blend_src_generic<RegularSpans>(count, spans, userData);
}
}
@@ -7410,7 +7082,13 @@ static void qt_alphamapblit_quint16(QRasterBuffer *rasterBuffer,
}
void qt_build_pow_tables() {
- qreal smoothing = 1.7;
+ qreal smoothing = qreal(1.7);
+
+#ifdef Q_WS_MAC
+ // decided by testing a few things on an iMac, should probably get this from the
+ // system...
+ smoothing = 2.0;
+#endif
#ifdef Q_WS_WIN
int winSmooth;
@@ -7426,15 +7104,15 @@ void qt_build_pow_tables() {
}
#else
for (int i=0; i<256; ++i) {
- qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / qreal(255), smoothing) * 255));
- qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / qreal(255), 1 / smoothing) * 255));
+ qt_pow_rgb_gamma[i] = uchar(qRound(pow(i / qreal(255.0), smoothing) * 255));
+ qt_pow_rgb_invgamma[i] = uchar(qRound(pow(i / qreal(255.), 1 / smoothing) * 255));
}
#endif
#if defined(Q_OS_WIN) && !defined(Q_OS_WINCE)
const qreal gray_gamma = 2.31;
for (int i=0; i<256; ++i)
- qt_pow_gamma[i] = uint(qRound(pow(i / 255.0, gray_gamma) * 2047));
+ qt_pow_gamma[i] = uint(qRound(pow(i / qreal(255.), gray_gamma) * 2047));
for (int i=0; i<2048; ++i)
qt_pow_invgamma[i] = uchar(qRound(pow(i / 2047.0, 1 / gray_gamma) * 255));
#endif
@@ -7699,13 +7377,13 @@ inline void qt_rectfill_template(QRasterBuffer *rasterBuffer,
QT_RECTFILL(quint32)
QT_RECTFILL(quint16)
QT_RECTFILL(qargb8565)
-QT_RECTFILL(qrgb666);
-QT_RECTFILL(qargb6666);
+QT_RECTFILL(qrgb666)
+QT_RECTFILL(qargb6666)
QT_RECTFILL(qrgb555)
QT_RECTFILL(qargb8555)
QT_RECTFILL(qrgb888)
-QT_RECTFILL(qrgb444);
-QT_RECTFILL(qargb4444);
+QT_RECTFILL(qrgb444)
+QT_RECTFILL(qargb4444)
#undef QT_RECTFILL
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index ddda7f7..8849128 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -110,6 +110,7 @@ struct QSpanData;
class QGradient;
class QRasterBuffer;
class QClipData;
+class QRasterPaintEngineState;
typedef QT_FT_SpanFunc ProcessSpans;
typedef void (*BitmapBlitFunc)(QRasterBuffer *rasterBuffer,
@@ -293,7 +294,7 @@ struct QSpanData
};
void init(QRasterBuffer *rb, const QRasterPaintEngine *pe);
- void setup(const QBrush &brush, int alpha);
+ void setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode);
void setupMatrix(const QTransform &matrix, int bilinear);
void initTexture(const QImage *image, int alpha, QTextureData::Type = QTextureData::Plain, const QRect &sourceRect = QRect());
void adjustSpanMethods();
@@ -453,6 +454,7 @@ public:
inline bool operator==(const qargb8565 &v) const;
inline quint32 rawValue() const;
+ inline quint16 rawValue16() const;
private:
friend class qrgb565;
@@ -469,7 +471,7 @@ public:
inline explicit qrgb565(quint32p v);
inline explicit qrgb565(quint32 v);
- inline explicit qrgb565(qargb8565 v);
+ inline explicit qrgb565(const qargb8565 &v);
inline operator quint32() const;
inline operator quint16() const;
@@ -575,6 +577,11 @@ quint32 qargb8565::rawValue() const
return (data[2] << 16) | (data[1] << 8) | data[0];
}
+quint16 qargb8565::rawValue16() const
+{
+ return (data[2] << 8) | data[1];
+}
+
qrgb565::qrgb565(quint32p v)
{
*this = qrgb565(quint32(v));
@@ -589,7 +596,7 @@ qrgb565::qrgb565(quint32 v)
data = (r & 0xf800) | (g & 0x07e0)| (b & 0x001f);
}
-qrgb565::qrgb565(qargb8565 v)
+qrgb565::qrgb565(const qargb8565 &v)
{
data = (v.data[2] << 8) | v.data[1];
}
diff --git a/src/gui/painting/qdrawutil.cpp b/src/gui/painting/qdrawutil.cpp
index 2beeb0e..29b922d 100644
--- a/src/gui/painting/qdrawutil.cpp
+++ b/src/gui/painting/qdrawutil.cpp
@@ -1038,4 +1038,328 @@ void qDrawItem(QPainter *p, Qt::GUIStyle gs,
#endif
+/*!
+ \class QMargins
+ \since 4.6
+
+ Holds the borders used to split a pixmap into nine segments in order to
+ draw it, similar to \l{http://www.w3.org/TR/css3-background/}
+ {CSS3 border-images}.
+
+ \sa Qt::TileRule, QTileRules
+*/
+
+/*! \fn QMargins::QMargins(int margin)
+ Constructs a QMargins with the top, left, bottom, and
+ right margins set to \a margin.
+*/
+
+/*! \fn QMargins::QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin)
+ Constructs a QMargins with the given \a topMargin, \a leftMargin,
+ \a bottomMargin, and \a rightMargin.
+ */
+
+/*!
+ \class QTileRules
+ \since 4.6
+
+ Holds the rules used to draw a pixmap or image split into nine segments,
+ similar to \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}.
+
+ \sa Qt::TileRule, QMargins
+*/
+
+/*! \fn QTileRules::QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule)
+ Constructs a QTileRules with the given \a horizontalRule and
+ \a verticalRule.
+ */
+
+/*! \fn QTileRules::QTileRules(Qt::TileRule rule)
+ Constructs a QTileRules with the given \a rule used for both
+ the horizontal rule and the vertical rule.
+ */
+
+/*!
+ \fn void qDrawBorderPixmap(QPainter *painter, const QRect &target, const QMargins &margins, const QPixmap &pixmap)
+ \since 4.6
+ \relates QMargins
+
+ Draws the given \a pixmap into the given \a target rectangle, using the
+ given \a painter. The pixmap will be split into nine segments and drawn
+ according to the \a margins structure.
+*/
+
+static inline void qVerticalRepeat(QPainter *painter,
+ const QRect &target,
+ const QPixmap &pixmap,
+ const QRect &source,
+ void (*drawPixmap)(QPainter*,
+ const QRect&,
+ const QPixmap&,
+ const QRect&))
+{
+ const int x = target.x();
+ const int width = target.width();
+ const int height = source.height();
+ const int bottom = target.bottom() - height;
+ int y = target.y();
+ for (; y < bottom; y += height)
+ (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
+ const QRect remaining(source.x(), source.y(), source.width(), target.bottom() - y + 1);
+ (*drawPixmap)(painter, QRect(x, y, width, remaining.height()), pixmap, remaining);
+}
+
+static inline void qHorizontalRepeat(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ const int y = target.y();
+ const int width = source.width();
+ const int height = target.height();
+ const int right = target.right() - width;
+ int x = target.x();
+ for (; x < right; x += width)
+ (*drawPixmap)(painter, QRect(x, y, width, height), pixmap, source);
+ const QRect remaining(source.x(), source.y(), target.right() - x + 1, source.height());
+ (*drawPixmap)(painter, QRect(x, y, remaining.width(), height), pixmap, remaining);
+}
+
+static inline void qVerticalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ // qreal based - slow on non-fpu devices
+ const qreal x = target.x();
+ const qreal width = target.width();
+ const qreal verticalFactor = static_cast<qreal>(target.height()) / static_cast<qreal>(source.height());
+ const qreal verticalIncrement = static_cast<qreal>(target.height()) / static_cast<int>(verticalFactor + 0.5);
+ const qreal bottom = target.bottom();
+ for (qreal y = static_cast<qreal>(target.y()); y < bottom; y += verticalIncrement)
+ (*drawPixmap)(painter, QRectF(x, y, width, verticalIncrement).toRect(), pixmap, source);
+
+}
+
+static inline void qHorizontalRound(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source,
+ void (*drawPixmap)(QPainter*, const QRect&, const QPixmap&, const QRect&))
+{
+ // qreal based - slow on non-fpu devices
+ const qreal y = target.y();
+ const qreal height = target.height();
+ const qreal horizontalFactor = static_cast<qreal>(target.width()) / static_cast<qreal>(source.width());
+ const qreal horizontalIncrement = static_cast<qreal>(target.width()) / static_cast<int>(horizontalFactor + 0.5);
+ const qreal right = target.right();
+ for (qreal x = target.x(); x < right; x += horizontalIncrement)
+ (*drawPixmap)(painter, QRectF(x, y, horizontalIncrement, height).toRect(), pixmap, source);
+}
+
+static inline void qDrawPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ painter->drawPixmap(target, pixmap, source);
+}
+
+static inline void qDrawVerticallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qVerticalRepeat(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawHorizontallyRepeatedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qHorizontalRepeat(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawVerticallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qVerticalRound(painter, target, pixmap, source, qDrawPixmap);
+}
+
+static inline void qDrawHorizontallyRoundedPixmap(QPainter *painter, const QRect &target, const QPixmap &pixmap, const QRect &source)
+{
+ qHorizontalRound(painter, target, pixmap, source, qDrawPixmap);
+}
+
+/*!
+ \since 4.6
+
+ Draws the indicated \a sourceRect rectangle from the given \a pixmap into
+ the given \a targetRect rectangle, using the given \a painter. The pixmap
+ will be split into nine segments according to the given \a targetMargins
+ and \a sourceMargins structures. Finally, the pixmap will be drawn
+ according to the given \a rules.
+
+ This function is used to draw a scaled pixmap, similar to
+ \l{http://www.w3.org/TR/css3-background/}{CSS3 border-images}
+
+ \sa Qt::TileRule, QTileRules, QMargins
+*/
+
+void qDrawBorderPixmap(QPainter *painter, const QRect &targetRect, const QMargins &targetMargins, const QPixmap &pixmap,
+ const QRect &sourceRect, const QMargins &sourceMargins, const QTileRules &rules)
+{
+ // source center
+ const int sourceTop = sourceRect.top();
+ const int sourceLeft = sourceRect.left();
+ const int sourceCenterTop = sourceTop + sourceMargins.top;
+ const int sourceCenterLeft = sourceLeft + sourceMargins.left;
+ const int sourceCenterBottom = sourceRect.bottom() - sourceMargins.bottom + 1;
+ const int sourceCenterRight = sourceRect.right() - sourceMargins.right + 1;
+ const int sourceCenterWidth = sourceCenterRight - sourceMargins.left;
+ const int sourceCenterHeight = sourceCenterBottom - sourceMargins.top;
+ // target center
+ const int targetTop = targetRect.top();
+ const int targetLeft = targetRect.left();
+ const int targetCenterTop = targetTop + targetMargins.top;
+ const int targetCenterLeft = targetLeft + targetMargins.left;
+ const int targetCenterBottom = targetRect.bottom() - targetMargins.bottom + 1;
+ const int targetCenterRight = targetRect.right() - targetMargins.right + 1;
+ const int targetCenterWidth = targetCenterRight - targetCenterLeft;
+ const int targetCenterHeight = targetCenterBottom - targetCenterTop;
+
+ // corners
+ if (targetMargins.top > 0 && targetMargins.left > 0 && sourceMargins.top > 0 && sourceMargins.left > 0) { // top left
+ const QRect targetTopLeftRect(targetLeft, targetTop, targetMargins.left, targetMargins.top);
+ const QRect sourceTopLeftRect(sourceLeft, sourceTop, sourceMargins.left, sourceMargins.top);
+ qDrawPixmap(painter, targetTopLeftRect, pixmap, sourceTopLeftRect);
+ }
+ if (targetMargins.top > 0 && targetMargins.right > 0 && sourceMargins.top > 0 && sourceMargins.right > 0) { // top right
+ const QRect targetTopRightRect(targetCenterRight, targetTop, targetMargins.right, targetMargins.top);
+ const QRect sourceTopRightRect(sourceCenterRight, sourceTop, sourceMargins.right, sourceMargins.top);
+ qDrawPixmap(painter, targetTopRightRect, pixmap, sourceTopRightRect);
+ }
+ if (targetMargins.bottom > 0 && targetMargins.left > 0 && sourceMargins.bottom > 0 && sourceMargins.left > 0) { // bottom left
+ const QRect targetBottomLeftRect(targetLeft, targetCenterBottom, targetMargins.left, targetMargins.bottom);
+ const QRect sourceBottomLeftRect(sourceLeft, sourceCenterBottom, sourceMargins.left, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomLeftRect, pixmap, sourceBottomLeftRect);
+ }
+ if (targetMargins.bottom > 0 && targetMargins.right > 0 && sourceMargins.bottom > 0 && sourceMargins.right > 0) { // bottom right
+ const QRect targetBottomRightRect(targetCenterRight, targetCenterBottom, targetMargins.right, targetMargins.bottom);
+ const QRect sourceBottomRightRect(sourceCenterRight, sourceCenterBottom, sourceMargins.right, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomRightRect, pixmap, sourceBottomRightRect);
+ }
+
+ // horizontal edges
+ switch (rules.horizontal) {
+ case Qt::Stretch:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ case Qt::Repeat:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawHorizontallyRepeatedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawHorizontallyRepeatedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ case Qt::Round:
+ if (targetMargins.top > 0 && sourceMargins.top > 0) { // top
+ const QRect targetTopRect(targetCenterLeft, targetTop, targetCenterWidth, targetMargins.top);
+ const QRect sourceTopRect(sourceCenterLeft, sourceTop, sourceCenterWidth, sourceMargins.top);
+ qDrawHorizontallyRoundedPixmap(painter, targetTopRect, pixmap, sourceTopRect);
+ }
+ if (targetMargins.bottom > 0 && sourceMargins.bottom > 0) { // bottom
+ const QRect targetBottomRect(targetCenterLeft, targetCenterBottom, targetCenterWidth, targetMargins.bottom);
+ const QRect sourceBottomRect(sourceCenterLeft, sourceCenterBottom, sourceCenterWidth, sourceMargins.bottom);
+ qDrawHorizontallyRoundedPixmap(painter, targetBottomRect, pixmap, sourceBottomRect);
+ }
+ break;
+ }
+
+ // vertical edges
+ switch (rules.vertical) {
+ case Qt::Stretch:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ case Qt::Repeat:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawVerticallyRepeatedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawVerticallyRepeatedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ case Qt::Round:
+ if (targetMargins.left > 0 && sourceMargins.left > 0) { // left
+ const QRect targetLeftRect(targetLeft, targetCenterTop, targetMargins.left, targetCenterHeight);
+ const QRect sourceLeftRect(sourceLeft, sourceCenterTop, sourceMargins.left, sourceCenterHeight);
+ qDrawVerticallyRoundedPixmap(painter, targetLeftRect, pixmap, sourceLeftRect);
+ }
+ if (targetMargins.right > 0 && sourceMargins.right > 0) { // right
+ const QRect targetRightRect(targetCenterRight, targetCenterTop, targetMargins.right, targetCenterHeight);
+ const QRect sourceRightRect(sourceCenterRight, sourceCenterTop, sourceMargins.right, sourceCenterHeight);
+ qDrawVerticallyRoundedPixmap(painter, targetRightRect, pixmap, sourceRightRect);
+ }
+ break;
+ }
+
+ // center
+ if (targetCenterWidth > 0 && targetCenterHeight > 0 && sourceCenterWidth > 0 && sourceCenterHeight > 0) {
+ const QRect targetCenterRect(targetCenterLeft, targetCenterTop, targetCenterWidth, targetCenterHeight);
+ const QRect sourceCenterRect(sourceCenterLeft, sourceCenterTop, sourceCenterWidth, sourceCenterHeight);
+ switch (rules.horizontal) {
+ case Qt::Stretch:
+ switch (rules.vertical) {
+ case Qt::Stretch: // stretch stretch
+ qDrawPixmap(painter, targetCenterRect, pixmap, sourceCenterRect);
+ break;
+ case Qt::Repeat: // stretch repeat
+ qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Round: // stretch round
+ qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ }
+ break;
+ case Qt::Repeat:
+ switch (rules.vertical) {
+ case Qt::Stretch: // repeat stretch
+ qHorizontalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Repeat: // repeat repeat
+ qVerticalRepeat(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
+ break;
+ case Qt::Round: // repeat round
+ qVerticalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawHorizontallyRepeatedPixmap);
+ break;
+ }
+ break;
+ case Qt::Round:
+ switch (rules.vertical) {
+ case Qt::Stretch: // round stretch
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawPixmap);
+ break;
+ case Qt::Repeat: // round repeat
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRepeatedPixmap);
+ break;
+ case Qt::Round: // round round
+ qHorizontalRound(painter, targetCenterRect, pixmap, sourceCenterRect, qDrawVerticallyRoundedPixmap);
+ break;
+ }
+ break;
+ }
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawutil.h b/src/gui/painting/qdrawutil.h
index 14901f3..306f4e2 100644
--- a/src/gui/painting/qdrawutil.h
+++ b/src/gui/painting/qdrawutil.h
@@ -44,6 +44,7 @@
#include <QtCore/qnamespace.h>
#include <QtCore/qstring.h> // char*->QString conversion
+#include <QtGui/qpixmap.h>
QT_BEGIN_HEADER
@@ -60,7 +61,6 @@ class QPoint;
class QColor;
class QBrush;
class QRect;
-class QPixmap;
//
// Standard shade drawing
@@ -133,6 +133,50 @@ Q_GUI_EXPORT QT3_SUPPORT void qDrawArrow(QPainter *p, Qt::ArrowType type, Qt::GU
const QPalette &pal, bool enabled);
#endif
+struct Q_GUI_EXPORT QMargins
+{
+ inline QMargins(int margin = 0)
+ : top(margin),
+ left(margin),
+ bottom(margin),
+ right(margin) {}
+ inline QMargins(int topMargin, int leftMargin, int bottomMargin, int rightMargin)
+ : top(topMargin),
+ left(leftMargin),
+ bottom(bottomMargin),
+ right(rightMargin) {}
+ int top;
+ int left;
+ int bottom;
+ int right;
+};
+
+struct Q_GUI_EXPORT QTileRules
+{
+ inline QTileRules(Qt::TileRule horizontalRule, Qt::TileRule verticalRule = Qt::Stretch)
+ : horizontal(horizontalRule), vertical(verticalRule) {}
+ inline QTileRules(Qt::TileRule rule = Qt::Stretch)
+ : horizontal(rule), vertical(rule) {}
+ Qt::TileRule horizontal;
+ Qt::TileRule vertical;
+};
+
+Q_GUI_EXPORT void qDrawBorderPixmap(QPainter *painter,
+ const QRect &targetRect,
+ const QMargins &targetMargins,
+ const QPixmap &pixmap,
+ const QRect &sourceRect,
+ const QMargins &sourceMargins,
+ const QTileRules &rules = QTileRules());
+
+Q_GUI_EXPORT inline void qDrawBorderPixmap(QPainter *painter,
+ const QRect &target,
+ const QMargins &margins,
+ const QPixmap &pixmap)
+{
+ qDrawBorderPixmap(painter, target, margins, pixmap, pixmap.rect(), margins);
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qemulationpaintengine.cpp b/src/gui/painting/qemulationpaintengine.cpp
index 175f1ab..5ce1136 100644
--- a/src/gui/painting/qemulationpaintengine.cpp
+++ b/src/gui/painting/qemulationpaintengine.cpp
@@ -99,9 +99,9 @@ void QEmulationPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
QBrush copy = brush;
QTransform mat = copy.transform();
- QRealRect r = path.controlPointRect();
- mat.translate(r.x1, r.y1);
- mat.scale(r.x2 - r.x1, r.y2 - r.y1);
+ QRectF r = path.controlPointRect();
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
copy.setTransform(mat);
real_engine->fill(path, copy);
return;
@@ -139,9 +139,9 @@ void QEmulationPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
return;
} else if (g->coordinateMode() == QGradient::ObjectBoundingMode) {
QTransform mat = brush.transform();
- QRealRect r = path.controlPointRect();
- mat.translate(r.x1, r.y1);
- mat.scale(r.x2 - r.x1, r.y2 - r.y1);
+ QRectF r = path.controlPointRect();
+ mat.translate(r.x(), r.y());
+ mat.scale(r.width(), r.height());
brush.setTransform(mat);
copy.setBrush(brush);
real_engine->stroke(path, copy);
diff --git a/src/gui/painting/qfixed_p.h b/src/gui/painting/qfixed_p.h
index 2e49615..c89d97a 100644
--- a/src/gui/painting/qfixed_p.h
+++ b/src/gui/painting/qfixed_p.h
@@ -181,8 +181,10 @@ inline bool operator<(int i, const QFixed &f) { return (i<<6) < f.value(); }
inline bool operator>(const QFixed &f, int i) { return f.value() > (i<<6); }
inline bool operator>(int i, const QFixed &f) { return (i<<6) > f.value(); }
+#ifndef QT_NO_DEBUG_STREAM
inline QDebug &operator<<(QDebug &dbg, const QFixed &f)
{ return dbg << f.toReal(); }
+#endif
struct QFixedPoint {
QFixed x;
diff --git a/src/gui/painting/qgraphicssystemfactory_p.h b/src/gui/painting/qgraphicssystemfactory_p.h
index 9e95324..523b908 100644
--- a/src/gui/painting/qgraphicssystemfactory_p.h
+++ b/src/gui/painting/qgraphicssystemfactory_p.h
@@ -63,7 +63,7 @@ QT_MODULE(Gui)
class QGraphicsSystem;
-class Q_GUI_EXPORT QGraphicsSystemFactory
+class QGraphicsSystemFactory
{
public:
static QStringList keys();
diff --git a/src/gui/painting/qgraphicssystemplugin_p.h b/src/gui/painting/qgraphicssystemplugin_p.h
index 2e70333..ea7aa2d 100644
--- a/src/gui/painting/qgraphicssystemplugin_p.h
+++ b/src/gui/painting/qgraphicssystemplugin_p.h
@@ -64,7 +64,7 @@ QT_MODULE(Gui)
class QGraphicsSystem;
-struct Q_GUI_EXPORT QGraphicsSystemFactoryInterface : public QFactoryInterface
+struct QGraphicsSystemFactoryInterface : public QFactoryInterface
{
virtual QGraphicsSystem *create(const QString &key) = 0;
};
diff --git a/src/gui/painting/qmatrix.cpp b/src/gui/painting/qmatrix.cpp
index 4439d52..030415d 100644
--- a/src/gui/painting/qmatrix.cpp
+++ b/src/gui/painting/qmatrix.cpp
@@ -208,9 +208,13 @@ QT_BEGIN_NAMESPACE
*/
QMatrix::QMatrix()
+ : _m11(1.)
+ , _m12(0.)
+ , _m21(0.)
+ , _m22(1.)
+ , _dx(0.)
+ , _dy(0.)
{
- _m11 = _m22 = 1.0;
- _m12 = _m21 = _dx = _dy = 0.0;
}
/*!
@@ -220,12 +224,14 @@ QMatrix::QMatrix()
\sa setMatrix()
*/
-QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
- qreal dx, qreal dy)
+QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
+ : _m11(m11)
+ , _m12(m12)
+ , _m21(m21)
+ , _m22(m22)
+ , _dx(dx)
+ , _dy(dy)
{
- _m11 = m11; _m12 = m12;
- _m21 = m21; _m22 = m22;
- _dx = dx; _dy = dy;
}
@@ -233,8 +239,13 @@ QMatrix::QMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
Constructs a matrix that is a copy of the given \a matrix.
*/
QMatrix::QMatrix(const QMatrix &matrix)
+ : _m11(matrix._m11)
+ , _m12(matrix._m12)
+ , _m21(matrix._m21)
+ , _m22(matrix._m22)
+ , _dx(matrix._dx)
+ , _dy(matrix._dy)
{
- *this = matrix;
}
/*!
@@ -249,12 +260,14 @@ QMatrix::QMatrix(const QMatrix &matrix)
\sa QMatrix()
*/
-void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22,
- qreal dx, qreal dy)
+void QMatrix::setMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy)
{
- _m11 = m11; _m12 = m12;
- _m21 = m21; _m22 = m22;
- _dx = dx; _dy = dy;
+ _m11 = m11;
+ _m12 = m12;
+ _m21 = m21;
+ _m22 = m22;
+ _dx = dx;
+ _dy = dy;
}
@@ -968,18 +981,17 @@ QMatrix QMatrix::inverted(bool *invertible) const
if (determinant == 0.0) {
if (invertible)
*invertible = false; // singular matrix
- QMatrix defaultMatrix;
- return defaultMatrix;
+ return QMatrix(true);
}
else { // invertible matrix
if (invertible)
*invertible = true;
qreal dinv = 1.0/determinant;
- QMatrix imatrix((_m22*dinv), (-_m12*dinv),
- (-_m21*dinv), (_m11*dinv),
- ((_m21*_dy - _m22*_dx)*dinv),
- ((_m12*_dx - _m11*_dy)*dinv));
- return imatrix;
+ return QMatrix((_m22*dinv), (-_m12*dinv),
+ (-_m21*dinv), (_m11*dinv),
+ ((_m21*_dy - _m22*_dx)*dinv),
+ ((_m12*_dx - _m11*_dy)*dinv),
+ true);
}
}
@@ -1054,9 +1066,14 @@ QMatrix &QMatrix::operator *=(const QMatrix &m)
QMatrix QMatrix::operator *(const QMatrix &m) const
{
- QMatrix result = *this;
- result *= m;
- return result;
+ qreal tm11 = _m11*m._m11 + _m12*m._m21;
+ qreal tm12 = _m11*m._m12 + _m12*m._m22;
+ qreal tm21 = _m21*m._m11 + _m22*m._m21;
+ qreal tm22 = _m21*m._m12 + _m22*m._m22;
+
+ qreal tdx = _dx*m._m11 + _dy*m._m21 + m._dx;
+ qreal tdy = _dx*m._m12 + _dy*m._m22 + m._dy;
+ return QMatrix(tm11, tm12, tm21, tm22, tdx, tdy, true);
}
/*!
@@ -1161,7 +1178,7 @@ QDebug operator<<(QDebug dbg, const QMatrix &m)
<< " 22=" << m.m22()
<< " dx=" << m.dx()
<< " dy=" << m.dy()
- << ")";
+ << ')';
return dbg.space();
}
#endif
diff --git a/src/gui/painting/qmatrix.h b/src/gui/painting/qmatrix.h
index bf53c32..1df2395 100644
--- a/src/gui/painting/qmatrix.h
+++ b/src/gui/painting/qmatrix.h
@@ -99,7 +99,7 @@ public:
QMatrix &shear(qreal sh, qreal sv);
QMatrix &rotate(qreal a);
- bool isInvertible() const { return !qFuzzyCompare(_m11*_m22 - _m12*_m21 + 1, 1); }
+ bool isInvertible() const { return !qFuzzyIsNull(_m11*_m22 - _m12*_m21); }
qreal det() const { return _m11*_m22 - _m12*_m21; }
QMatrix inverted(bool *invertible = 0) const;
@@ -121,6 +121,20 @@ public:
#endif
private:
+ inline QMatrix(bool)
+ : _m11(1.)
+ , _m12(0.)
+ , _m21(0.)
+ , _m22(1.)
+ , _dx(0.)
+ , _dy(0.) {}
+ inline QMatrix(qreal m11, qreal m12, qreal m21, qreal m22, qreal dx, qreal dy, bool)
+ : _m11(m11)
+ , _m12(m12)
+ , _m21(m21)
+ , _m22(m22)
+ , _dx(dx)
+ , _dy(dy) {}
friend class QTransform;
qreal _m11, _m12;
qreal _m21, _m22;
@@ -147,16 +161,18 @@ Q_GUI_EXPORT QPainterPath operator *(const QPainterPath &p, const QMatrix &m);
inline bool QMatrix::isIdentity() const
{
- return qFuzzyCompare(_m11, 1) && qFuzzyCompare(_m22, 1) && qFuzzyCompare(_m12 + 1, 1)
- && qFuzzyCompare(_m21 + 1, 1) && qFuzzyCompare(_dx + 1, 1) && qFuzzyCompare(_dy + 1, 1);
+ return qFuzzyIsNull(_m11 - 1) && qFuzzyIsNull(_m22 - 1) && qFuzzyIsNull(_m12)
+ && qFuzzyIsNull(_m21) && qFuzzyIsNull(_dx) && qFuzzyIsNull(_dy);
}
/*****************************************************************************
QMatrix stream functions
*****************************************************************************/
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QMatrix &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QMatrix &);
+#endif
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QMatrix &);
diff --git a/src/gui/painting/qpaintengine.cpp b/src/gui/painting/qpaintengine.cpp
index c5be802..e70d524 100644
--- a/src/gui/painting/qpaintengine.cpp
+++ b/src/gui/painting/qpaintengine.cpp
@@ -49,6 +49,7 @@
#include <private/qtextengine_p.h>
#include <qvarlengtharray.h>
#include <private/qfontengine_p.h>
+#include <private/qpaintengineex_p.h>
QT_BEGIN_NAMESPACE
@@ -302,6 +303,9 @@ void QPaintEngine::syncState()
{
Q_ASSERT(state);
updateState(*state);
+
+ if (isExtended())
+ static_cast<QPaintEngineEx *>(this)->sync();
}
static QPaintEngine *qt_polygon_recursion = 0;
diff --git a/src/gui/painting/qpaintengine_d3d.cpp b/src/gui/painting/qpaintengine_d3d.cpp
deleted file mode 100644
index bb81623..0000000
--- a/src/gui/painting/qpaintengine_d3d.cpp
+++ /dev/null
@@ -1,4576 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include <qdebug.h>
-#include "qpaintengine_d3d_p.h"
-
-#include "private/qdrawhelper_p.h"
-#include "private/qfont_p.h"
-#include "private/qfontengine_p.h"
-#include "private/qpaintengine_p.h"
-#include "private/qtessellator_p.h"
-#include <private/qbezier_p.h>
-#include <private/qpainter_p.h>
-#include <private/qpixmap_raster_p.h>
-#include <private/qpolygonclipper_p.h>
-#include <qbuffer.h>
-#include <qcache.h>
-#include <qdir.h>
-#include <qfileinfo.h>
-#include <qlibrary.h>
-#include <qlibraryinfo.h>
-#include <qmath.h>
-#include <qpaintdevice.h>
-#include <qpixmapcache.h>
-
-#include <qwidget.h>
-#include <d3d9.h>
-#include <d3dx9.h>
-
-#include <mmintrin.h>
-#include <xmmintrin.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef M_PI
- #define M_PI 3.14159265358979323846
-#endif
-
-#define QD3D_MASK_MARGIN 1
-#define QD3D_BATCH_SIZE 256
-
-// for the ClearType detection stuff..
-#ifndef SPI_GETFONTSMOOTHINGTYPE
-#define SPI_GETFONTSMOOTHINGTYPE 0x200A
-#endif
-
-#ifndef FE_FONTSMOOTHINGCLEARTYPE
-#define FE_FONTSMOOTHINGCLEARTYPE 0x0002
-#endif
-
-//#include <performance.h>
-#define PM_INIT
-#define PM_MEASURE(A)
-#define PM_DISPLAY
-
-//debugging
-//#define QT_DEBUG_VERTEXBUFFER_ACCESS
-//#define QT_DEBUG_D3D
-//#define QT_DEBUG_D3D_CALLS
-
-#define QD3D_SET_MARK(output) \
- D3DPERF_SetMarker(0, QString(output).utf16());
-
-#define QT_VERTEX_RESET_LIMIT 24576
-#define QT_VERTEX_BUF_SIZE 32768
-#define QD3DFVF_CSVERTEX (D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX2 | D3DFVF_TEXCOORDSIZE4(0) | D3DFVF_TEXCOORDSIZE4(1))
-
-// this is a different usage of the effect framework than intended,
-// but it's convenient for us to use (See effect file)
-#define PASS_STENCIL_ODDEVEN 0
-#define PASS_STENCIL_WINDING 1
-#define PASS_STENCIL_DRAW 2
-#define PASS_STENCIL_DRAW_DIRECT 3
-#define PASS_STENCIL_CLIP 4
-#define PASS_STENCIL_NOSTENCILCHECK 5
-#define PASS_STENCIL_NOSTENCILCHECK_DIRECT 6
-#define PASS_TEXT 7
-#define PASS_CLEARTYPE_TEXT 8
-#define PASS_ALIASED_LINES 9
-#define PASS_ALIASED_LINES_DIRECT 10
-
-#define PASS_AA_CREATEMASK 0
-#define PASS_AA_DRAW 1
-#define PASS_AA_DRAW_DIRECT 2
-
-#define D3D_STAGE_COUNT 2
-#define D3D_RENDER_STATES 210
-#define D3D_TEXTURE_STATES 33
-#define D3D_SAMPLE_STATES 14
-
-
-typedef HRESULT (APIENTRY *PFND3DXCREATEBUFFER)(DWORD, LPD3DXBUFFER *);
-typedef HRESULT (APIENTRY *PFND3DXCREATEEFFECT)(LPDIRECT3DDEVICE9, LPCVOID, UINT, CONST D3DXMACRO *,
- LPD3DXINCLUDE, DWORD, LPD3DXEFFECTPOOL,
- LPD3DXEFFECT *, LPD3DXBUFFER *);
-typedef D3DXMATRIX *(APIENTRY *PFND3DXMATRIXORTHOOFFCENTERLH)(D3DMATRIX *, FLOAT, FLOAT,
- FLOAT, FLOAT, FLOAT, FLOAT);
-typedef IDirect3D9 *(APIENTRY *PFNDIRECT3DCREATE9)(uint);
-
-static PFNDIRECT3DCREATE9 pDirect3DCreate9 = 0;
-static PFND3DXCREATEBUFFER pD3DXCreateBuffer = 0;
-static PFND3DXCREATEEFFECT pD3DXCreateEffect = 0;
-static PFND3DXMATRIXORTHOOFFCENTERLH pD3DXMatrixOrthoOffCenterLH = 0;
-
-
-class QD3DSurfaceManager : public QObject {
- Q_OBJECT
-
-public:
- enum QD3DSurfaceManagerStatus {
- NoStatus = 0,
- NeedsResetting = 0x01,
- MaxSizeChanged = 0x02
- };
-
- QD3DSurfaceManager();
- ~QD3DSurfaceManager();
-
- void init(LPDIRECT3D9 object);
-
- void setPaintDevice(QPaintDevice *pd);
-
- int status() const;
- void reset();
-
- LPDIRECT3DSURFACE9 renderTarget();
-
- LPDIRECT3DSURFACE9 surface(QPaintDevice *pd);
- LPDIRECT3DSWAPCHAIN9 swapChain(QPaintDevice *pd);
- void releasePaintDevice(QPaintDevice *pd);
-
- LPDIRECT3DDEVICE9 device();
- void cleanup();
-
- QSize maxSize() const;
-
-private:
- struct D3DSwapChain {
- QSize size;
- LPDIRECT3DSWAPCHAIN9 swapchain;
- LPDIRECT3DSURFACE9 surface;
- };
-
- void updateMaxSize();
- void initPresentParameters(D3DPRESENT_PARAMETERS *params);
- D3DSwapChain *createSwapChain(QWidget *w);
-
- QSize m_max_size;
- int m_status;
- QMap<QPaintDevice *, D3DSwapChain *> m_swapchains;
-
- LPDIRECT3DDEVICE9 m_device;
- QPaintDevice *m_pd;
- HWND m_dummy;
- D3DSwapChain *m_current;
-
-private Q_SLOTS:
- void cleanupPaintDevice(QObject *);
-};
-
-struct vertex {
- D3DVECTOR pos;
- DWORD color;
- FLOAT s0, t0, r0, q0;
- FLOAT s1, t1, r1, q1;
-};
-
-struct QD3DMaskPosition {
- int x, y, channel;
-};
-
-
-struct QD3DBatchItem {
- enum QD3DBatchInfo {
- BI_WINDING = 0x0001,
- BI_AA = 0x0002,
- BI_BRECT = 0x0004,
- BI_MASKFULL = 0x0008,
- BI_TEXT = 0x0010,
- BI_MASK = 0x0020,
- BI_CLIP = 0x0040,
- BI_SCISSOR = 0x0080,
-
- BI_PIXMAP = 0x0100,
- BI_IMAGE = 0x0200,
- BI_COMPLEXBRUSH = 0x0400,
-
- BI_CLEARCLIP = 0x0800, // clip nothing (filling the clip mask with 0)
- BI_TRANSFORM = 0x1000,
- BI_MASKSCISSOR = 0x2000,
- BI_FASTLINE = 0x4000,
- BI_COSMETICPEN = 0x8000
- };
-
- int m_info;
-
- int m_count;
- int m_offset;
-
- QD3DMaskPosition m_maskpos;
- qreal m_xoffset;
- qreal m_yoffset;
- qreal m_opacity;
-
- QPixmap m_pixmap;
- QRectF m_brect;
- QBrush m_brush;
-
- IDirect3DTexture9 *m_texture;
-
- qreal m_width;
- qreal m_distance;
-
- QTransform m_matrix;
- QPainter::CompositionMode m_cmode;
-
- QVector<int> m_pointstops;
-};
-
-struct QD3DBatch {
- int m_item_index;
- QD3DBatchItem items[QD3D_BATCH_SIZE];
-};
-
-class QD3DStateManager;
-class QD3DFontCache;
-class QD3DDrawHelper;
-class QD3DGradientCache;
-
-class QDirect3DPaintEnginePrivate : public QPaintEnginePrivate
-{
- Q_DECLARE_PUBLIC(QDirect3DPaintEngine)
-
-public:
- enum RenderTechnique {
- RT_NoTechnique,
- RT_Antialiased,
- RT_Aliased,
- };
-
- QDirect3DPaintEnginePrivate()
- : m_d3d_object(0)
- , m_d3d_device(0)
- , m_txop(QTransform::TxNone)
- , m_effect(0)
- , m_flush_on_end(0)
- { init(); }
-
- ~QDirect3DPaintEnginePrivate();
-
- bool init();
- void initDevice();
-
- inline QD3DBatchItem *nextBatchItem();
-
- QPolygonF brushCoordinates(const QRectF &r, bool stroke, qreal *fp) const;
- void fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform);
- void fillAntialiasedPath(const QPainterPath &path, const QRectF &brect,
- const QTransform &txform, bool stroke);
- void fillPath(const QPainterPath &path, QRectF brect);
-
- void strokePath(const QPainterPath &path, QRectF brect, bool simple = false);
- QPainterPath strokePathFastPen(const QPainterPath &path);
- void strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform);
-
- void flushBatch();
- int flushAntialiased(int offset);
- void flushAliased(QD3DBatchItem *item, int offset);
- void flushText(QD3DBatchItem *item, int offset);
- void flushLines(QD3DBatchItem *item, int offset);
-
- void updateTransform(const QTransform &matrix);
- void updatePen(const QPen &pen);
- void updateBrush(const QBrush &pen);
- void updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op = Qt::ReplaceClip);
- void updateClipPath(const QPainterPath &clipregion, Qt::ClipOperation op = Qt::ReplaceClip);
- void updateFont(const QFont &font);
-
- void setRenderTechnique(RenderTechnique technique);
-
- QPointF transformPoint(const QPointF &p, qreal *w) const;
-
- bool prepareBatch(QD3DBatchItem *item, int offset);
- void prepareItem(QD3DBatchItem *item);
- void cleanupItem(QD3DBatchItem *item);
- void setCompositionMode(QPainter::CompositionMode mode);
-
- void verifyTexture(const QPixmap &pixmap);
-
- bool isFastRect(const QRectF &rect);
-
- void releaseDC();
-
- void cleanup();
- bool testCaps();
-
- QPixmap getPattern(Qt::BrushStyle style) const;
-
- // clipping
- QPainterPath m_sysclip_path;
- QPainterPath m_clip_path;
- QRegion m_sysclip_region;
- QRegion m_clip_region;
-
- qreal m_opacity;
- D3DCOLOR m_opacity_color;
-
- int m_current_state;
-
- ID3DXEffect* m_effect;
-
- RenderTechnique m_current_technique;
-
- QTransform m_matrix;
- qreal m_inv_scale;
-
- QPen m_pen;
- Qt::BrushStyle m_pen_brush_style;
- QTransform m_inv_pen_matrix;
- D3DCOLOR m_pen_color;
- qreal m_pen_width;
-
- QBrush m_brush;
- Qt::BrushStyle m_brush_style;
- QTransform m_inv_brush_matrix;
- D3DCOLOR m_brush_color;
- QTransform m_brush_origin;
-
- uint m_clipping_enabled : 1;
- uint m_has_complex_clipping : 1;
- uint m_cleartype_text: 1;
- uint m_has_pen : 1;
- uint m_has_cosmetic_pen : 1;
- uint m_has_brush : 1;
- uint m_has_fast_pen : 1;
- uint m_has_aa_fast_pen : 1;
- uint m_flush_on_end : 1;
- uint m_supports_d3d : 1;
-
- QTransform::TransformationType m_txop;
-
- QPainter::CompositionMode m_cmode;
-
- QD3DSurfaceManager m_surface_manager;
- QSize m_surface_size;
-
- LPDIRECT3D9 m_d3d_object;
- LPDIRECT3DDEVICE9 m_d3d_device;
- IDirect3DSurface9 *m_current_surface;
- bool m_in_scene;
-
- QD3DGradientCache *m_gradient_cache;
- QD3DDrawHelper *m_draw_helper;
- QD3DBatch m_batch;
- QD3DStateManager *m_statemanager;
-
- HDC m_dc;
- IDirect3DSurface9 *m_dcsurface;
-
- QMap<Qt::BrushStyle, QPixmap> m_patterns;
-};
-
-
-class QD3DStateManager : public ID3DXEffectStateManager {
-public:
- QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect);
- void reset();
-
- inline void startStateBlock();
- inline void endStateBlock();
-
- inline void setCosmeticPen(bool enabled);
- inline void setBrushMode(int mode);
- inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture);
- inline void setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread);
- inline void setTransformation(const QTransform *matrix = 0);
- inline void setProjection(const D3DXMATRIX *pMatrix);
- inline void setMaskChannel(int channel);
- inline void setMaskOffset(qreal x, qreal y);
- inline void setFocalDistance(const qreal &fd);
-
- inline void beginPass(int pass);
- inline void endPass();
-
- STDMETHOD(QueryInterface)(REFIID iid, LPVOID *ppv);
- STDMETHOD_(ULONG, AddRef)();
- STDMETHOD_(ULONG, Release)();
-
- STDMETHOD(SetTransform)(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix);
- STDMETHOD(SetMaterial)(CONST D3DMATERIAL9 *pMaterial);
- STDMETHOD(SetLight)(DWORD Index, CONST D3DLIGHT9 *pLight);
- STDMETHOD(LightEnable)(DWORD Index, BOOL Enable);
- STDMETHOD(SetRenderState)(D3DRENDERSTATETYPE State, DWORD Value);
- STDMETHOD(SetTexture)(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture);
- STDMETHOD(SetTextureStageState)(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value);
- STDMETHOD(SetSamplerState)(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value);
- STDMETHOD(SetNPatchMode)(FLOAT NumSegments);
- STDMETHOD(SetFVF)(DWORD FVF);
- STDMETHOD(SetVertexShader)(LPDIRECT3DVERTEXSHADER9 pShader);
- STDMETHOD(SetVertexShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetVertexShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetVertexShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount);
- STDMETHOD(SetPixelShader)(LPDIRECT3DPIXELSHADER9 pShader);
- STDMETHOD(SetPixelShaderConstantF)(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetPixelShaderConstantI)(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount);
- STDMETHOD(SetPixelShaderConstantB)(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount);
-private:
- LPDIRECT3DVERTEXSHADER9 m_vertexshader;
- LPDIRECT3DPIXELSHADER9 m_pixelshader;
-
- LPDIRECT3DBASETEXTURE9 m_textures[D3D_STAGE_COUNT];
- DWORD m_texturestates[D3D_STAGE_COUNT][D3D_TEXTURE_STATES];
- DWORD m_samplerstates[D3D_STAGE_COUNT][D3D_SAMPLE_STATES];
- DWORD m_renderstate[D3D_RENDER_STATES];
-
- qreal m_radgradfd;
-
- bool m_cosmetic_pen;
- int m_pass;
- int m_maskchannel;
- int m_brushmode;
- LPDIRECT3DBASETEXTURE9 m_texture;
- D3DXMATRIX m_projection;
-
- D3DXMATRIX m_d3dIdentityMatrix;
- bool m_isIdentity;
- QTransform m_transformation;
-
- LPDIRECT3DDEVICE9 m_pDevice;
- ID3DXEffect *m_effect;
-
- LONG m_refs;
- bool m_changed;
- qreal m_xoffset, m_yoffset;
- static int m_mask_channels[4][4];
-};
-
-//
-// font cache stuff
-//
-
-struct QD3DGlyphCoord {
- // stores the offset and size of a glyph texture
- qreal x;
- qreal y;
- qreal width;
- qreal height;
- qreal log_width;
- qreal log_height;
- QFixed x_offset;
- QFixed y_offset;
-};
-
-struct QD3DFontTexture {
- int x_offset; // current glyph offset within the texture
- int y_offset;
- int width;
- int height;
- IDirect3DTexture9 *texture;
-};
-
-typedef QHash<glyph_t, QD3DGlyphCoord*> QD3DGlyphHash;
-typedef QHash<QFontEngine*, QD3DGlyphHash*> QD3DFontGlyphHash;
-typedef QHash<quint64, QD3DFontTexture*> QD3DFontTexHash;
-
-class QD3DGlyphCache : public QObject
-{
- Q_OBJECT
-public:
- QD3DGlyphCache()
- : QObject(0)
- , current_cache(0) {}
- ~QD3DGlyphCache();
- QD3DGlyphCoord *lookup(QFontEngine *, glyph_t);
- void cacheGlyphs(QDirect3DPaintEngine *, const QTextItemInt &, const QVarLengthArray<glyph_t> &,
- bool);
- void cleanCache();
- inline QD3DFontTexture *fontTexture(QFontEngine *engine) {
- return font_textures.constFind(reinterpret_cast<quint64>(engine)).value();
- }
-
-public slots:
- void fontEngineDestroyed(QObject *);
-
-private:
- QImage clearTypeGlyph(QFontEngine *, glyph_t glyph);
- QD3DGlyphHash *current_cache;
- QD3DFontTexHash font_textures;
- QD3DFontGlyphHash font_cache;
-};
-
-QD3DGlyphCache::~QD3DGlyphCache()
-{
-}
-
-QD3DGlyphCoord *QD3DGlyphCache::lookup(QFontEngine *, glyph_t g)
-{
- Q_ASSERT(current_cache != 0);
- QD3DGlyphHash::const_iterator it = current_cache->constFind(g);
- if (it == current_cache->constEnd())
- return 0;
- return it.value();
-}
-
-void QD3DGlyphCache::cleanCache()
-{
- QList<quint64> keys = font_textures.keys();
- for (int i=0; i<keys.size(); ++i)
- font_textures.value(keys.at(i))->texture->Release();
-
- qDeleteAll(font_textures);
- qDeleteAll(font_cache);
- font_textures.clear();
- font_cache.clear();
- current_cache = 0;
-}
-
-void QD3DGlyphCache::fontEngineDestroyed(QObject *object)
-{
-// qDebug() << "=> font engine destroyed: " << object;
- QFontEngine *engine = static_cast<QFontEngine *>(object);
-
- QD3DFontGlyphHash::iterator cache_it = font_cache.find(engine);
- if (cache_it != font_cache.end()) {
- QD3DGlyphHash *cache = font_cache.take(engine);
- delete cache;
- }
-
- quint64 font_key = reinterpret_cast<quint64>(engine);
- QD3DFontTexture *tex = font_textures.take(font_key);
- if (tex) {
- tex->texture->Release();
- delete tex;
- }
-}
-
-QImage QD3DGlyphCache::clearTypeGlyph(QFontEngine *engine, glyph_t glyph)
-{
- glyph_metrics_t gm = engine->boundingBox(glyph);
- int glyph_x = qFloor(gm.x.toReal());
- int glyph_y = qFloor(gm.y.toReal());
- int glyph_width = qCeil((gm.x + gm.width).toReal()) - glyph_x + 2;
- int glyph_height = qCeil((gm.y + gm.height).toReal()) - glyph_y + 2;
-
- if (glyph_width + glyph_x <= 0 || glyph_height <= 0)
- return QImage();
- QImage im(glyph_width + glyph_x, glyph_height, QImage::Format_ARGB32_Premultiplied);
- im.fill(0xff000000); // solid black
- QPainter p(&im);
-
- p.setPen(Qt::white);
- p.setBrush(Qt::NoBrush);
-
- QTextItemInt ti;
- ti.ascent = engine->ascent();
- ti.descent = engine->descent();
- ti.width = glyph_width;
- ti.fontEngine = engine;
-
- QGlyphLayoutArray<1> glyphLayout;
- ti.glyphs = glyphLayout;
- ti.glyphs.glyphs[0] = glyph;
- ti.glyphs.advances_x[0] = glyph_width;
- p.drawTextItem(QPointF(-glyph_x, -glyph_y), ti);
- p.end();
- return im;
-}
-
-#if 0
-static void dump_font_texture(QD3DFontTexture *tex)
-{
- QColor color(Qt::red);
- D3DLOCKED_RECT rect;
- if (FAILED(tex->texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "debug: unable to lock texture rect.";
- return;
- }
-
-// cleartype version
-// uint *tex_data = (uint *) rect.pBits;
-// QImage im(tex->width, tex->height, QImage::Format_ARGB32);
-// for (int y=0; y<tex->height; ++y) {
-// for (int x=0; x<tex->width; ++x) {
-// im.setPixel(x, y, ((*(tex_data+x+y*tex->width))));
-// }
-// }
- uchar *tex_data = (uchar *) rect.pBits;
- QImage im(rect.Pitch, tex->height, QImage::Format_ARGB32);
- for (int y=0; y<tex->height; ++y) {
- for (int x=0; x<rect.Pitch; ++x) {
- uchar val = ((*(tex_data+x+y*rect.Pitch)));
- im.setPixel(x, y, 0xff000000 | (val << 16) | (val << 8) | val);
- }
- }
- tex->texture->UnlockRect(0);
- static int i= 0;
- im.save(QString("tx%1.png").arg(i++));
-}
-#endif
-
-void QD3DGlyphCache::cacheGlyphs(QDirect3DPaintEngine *engine, const QTextItemInt &ti,
- const QVarLengthArray<glyph_t> &glyphs, bool clearType)
-{
- IDirect3DDevice9 *device = engine->d_func()->m_d3d_device;
- QD3DFontGlyphHash::const_iterator cache_it = font_cache.constFind(ti.fontEngine);
- QD3DGlyphHash *cache = 0;
- if (cache_it == font_cache.constEnd()) {
- cache = new QD3DGlyphHash;
- font_cache.insert(ti.fontEngine, cache);
- connect(ti.fontEngine, SIGNAL(destroyed(QObject *)), SLOT(fontEngineDestroyed(QObject *)));
- } else {
- cache = cache_it.value();
- }
-
- current_cache = cache;
-
- D3DFORMAT tex_format = clearType ? D3DFMT_A8R8G8B8 : D3DFMT_A8;
- quint64 font_key = reinterpret_cast<quint64>(ti.fontEngine);
- QD3DFontTexHash::const_iterator it = font_textures.constFind(font_key);
- QD3DFontTexture *font_tex = 0;
- if (it == font_textures.constEnd()) {
- // alloc a new texture, put it into the cache
- int tex_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5;
- int tex_width = tex_height * 30; // ###
- IDirect3DTexture9 *tex;
- if (FAILED(device->CreateTexture(tex_width, tex_height, 1, 0,
- tex_format, D3DPOOL_MANAGED, &tex, NULL)))
- {
- qWarning("QD3DGlyphCache::cacheGlyphs(): can't allocate font texture (%dx%d).",
- tex_width, tex_height);
- return;
- } else {
-// qDebug() << "=> new font texture: " << QSize(tex_width,tex_height);
- font_tex = new QD3DFontTexture;
- font_tex->texture = tex;
- font_tex->x_offset = 0;
- font_tex->y_offset = 0;
- font_tex->width = tex_width;
- font_tex->height = tex_height;
- font_textures.insert(font_key, font_tex);
- }
- } else {
- font_tex = it.value();
- // make it current render target..
- }
-
- // cache each glyph
- for (int i=0; i<glyphs.size(); ++i) {
- QD3DGlyphHash::const_iterator it = cache->constFind(glyphs[i]);
- if (it == cache->constEnd()) {
- glyph_metrics_t metrics = ti.fontEngine->boundingBox(glyphs[i]);
- int glyph_width = qCeil(metrics.width.toReal()) + 5;
- int glyph_height = qCeil(ti.ascent.toReal() + ti.descent.toReal()) + 5;
- if (font_tex->x_offset + glyph_width > font_tex->width) {
- // no room on the current line, start new glyph strip
- int strip_height = glyph_height;
- font_tex->x_offset = 0;
- font_tex->y_offset += strip_height;
- if (font_tex->y_offset >= font_tex->height) {
- // if no room in the current texture - realloc a larger texture
- int old_tex_height = font_tex->height;
- font_tex->height += strip_height;
-
- IDirect3DTexture9 *new_tex;
- if (FAILED(device->CreateTexture(font_tex->width, font_tex->height, 1, 0,
- tex_format, D3DPOOL_MANAGED, &new_tex, NULL)))
- {
- qWarning("QD3DGlyphCache(): can't re-allocate font texture.");
- return;
- } else {
-// qDebug() << " -> new glyph strip added:" << QSize(font_tex->width,font_tex->height);
-
- D3DLOCKED_RECT new_rect, old_rect;
- if (FAILED(font_tex->texture->LockRect(0, &old_rect, 0, D3DLOCK_READONLY))) {
- qDebug() << "QD3DGlyphCache: unable to lock texture rect.";
- return;
- }
- if (FAILED(new_tex->LockRect(0, &new_rect, 0, 0))) {
- qDebug() << "QD3DGlyphCache: unable to lock texture rect.";
- return;
- }
- memcpy(new_rect.pBits, old_rect.pBits, new_rect.Pitch * old_tex_height);
- font_tex->texture->UnlockRect(0);
- new_tex->UnlockRect(0);
- engine->d_func()->flushBatch();
- font_tex->texture->Release();
- font_tex->texture = new_tex;
- }
-
- // update the texture coords and the y offset for the existing glyphs in
- // the cache, because of the texture size change
- QD3DGlyphHash::iterator it = cache->begin();
- while (it != cache->end()) {
- it.value()->height = (it.value()->height * old_tex_height) / font_tex->height;
- it.value()->y = (it.value()->y * old_tex_height) / font_tex->height;
- ++it;
- }
- }
- }
- QD3DGlyphCoord *d3d_glyph = new QD3DGlyphCoord;
- d3d_glyph->x = qreal(font_tex->x_offset) / font_tex->width;
- d3d_glyph->y = qreal(font_tex->y_offset) / font_tex->height;
- d3d_glyph->width = qreal(glyph_width) / font_tex->width;
- d3d_glyph->height = qreal(glyph_height) / font_tex->height;
- d3d_glyph->log_width = d3d_glyph->width * font_tex->width;
- d3d_glyph->log_height = d3d_glyph->height * font_tex->height;
- d3d_glyph->x_offset = -metrics.x;
- d3d_glyph->y_offset = metrics.y;
-
- QImage glyph_im;
- if (clearType)
- glyph_im = clearTypeGlyph(ti.fontEngine, glyphs[i]);
- else
- glyph_im = ti.fontEngine->alphaMapForGlyph(glyphs[i]).convertToFormat(QImage::Format_Indexed8);
-
- // write glyph to texture
- D3DLOCKED_RECT rect;
- RECT glyph_rect = { font_tex->x_offset, font_tex->y_offset,
- font_tex->x_offset + glyph_im.width(),
- font_tex->y_offset + glyph_im.height() };
-
-// qDebug() << " > new glyph char added:" << QSize(glyph_im.width(), glyph_im.height());
- if (FAILED(font_tex->texture->LockRect(0, &rect, &glyph_rect, 0))) {
- qDebug() << "QD3DGlyphCache: unable to lock texture rect.";
- return;
- }
-
- // ### unify these loops
- if (clearType) {
- int ppl = rect.Pitch / 4;
- uint *tex_data = (uint *) rect.pBits;
- for (int y=0; y<glyph_im.height(); ++y) {
- uint *s = (uint *) glyph_im.scanLine(y);
- for (int x=0; x<glyph_im.width(); ++x) {
- tex_data[ppl*y + x] = *s;
- ++s;
- }
- }
- } else {
- int ppl = rect.Pitch;
- uchar *tex_data = (uchar *) rect.pBits;
- for (int y=0; y<glyph_im.height(); ++y) {
- uchar *s = (uchar *) glyph_im.scanLine(y);
- for (int x=0; x<glyph_im.width(); ++x) {
- tex_data[ppl*y + x] = *s;
- ++s;
- }
- }
- }
- font_tex->texture->UnlockRect(0);
-
- // debug
-// dump_font_texture(font_tex);
-
- if (font_tex->x_offset + glyph_width > font_tex->width) {
- font_tex->x_offset = 0;
- font_tex->y_offset += glyph_height;
- } else {
- font_tex->x_offset += glyph_width;
- }
-
- cache->insert(glyphs[i], d3d_glyph);
- }
- }
-}
-
-Q_GLOBAL_STATIC(QD3DGlyphCache, qd3d_glyph_cache)
-
-//
-// end font caching stuff
-//
-
-
-//
-// D3D image cache stuff
-//
-
-// ### keep the GL stuff in mind..
-typedef void (*_qt_image_cleanup_hook_64)(qint64);
-extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
-
-static void qd3d_image_cleanup(qint64 key);
-
-class QD3DImage
-{
-public:
- QD3DImage(IDirect3DDevice9 *device, const QImage &image);
- ~QD3DImage();
-
- IDirect3DTexture9 *texture;
-};
-
-static QList<IDirect3DTexture9 *> qd3d_release_list;
-
-QD3DImage::QD3DImage(IDirect3DDevice9 *device, const QImage &image)
-{
- texture = 0;
- Q_ASSERT(device);
- QImage im = image.convertToFormat(QImage::Format_ARGB32);
- if (FAILED(device->CreateTexture(im.width(), im.height(), 1, 0,
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &texture, 0))) {
- qWarning("QD3DImage(): unable to create Direct3D texture.");
- return;
- }
-// qDebug(" -> created image texture: %p - 0x%08x%08x",texture,uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff));
- D3DLOCKED_RECT rect;
- if (FAILED(texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "QD3DImage: unable to lock texture rect.";
- return;
- }
- DWORD *dst = (DWORD *) rect.pBits;
- DWORD *src = (DWORD *) im.scanLine(0);
-
- Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4));
- memcpy(dst, src, rect.Pitch*im.height());
- texture->UnlockRect(0);
-}
-
-QD3DImage::~QD3DImage()
-{
- if (texture)
- qd3d_release_list.append(texture);
-}
-
-static int qd3d_cache_limit = 64*1024; // cache ~64 MB worth of textures
-typedef QCache<quint64, QD3DImage> QD3DImageCache;
-
-class QD3DImageManager
-{
-public:
- QD3DImageManager() {
- // ### GL does the same!
- qt_image_cleanup_hook_64 = qd3d_image_cleanup;
- cache.setMaxCost(qd3d_cache_limit);
- }
- ~QD3DImageManager() {
-// qDebug() << "unhooking d3d image cache";
- qt_image_cleanup_hook_64 = 0;
- cache.clear();
- }
-
- IDirect3DTexture9 *lookup(IDirect3DDevice9 *device, const QImage &image);
- void remove(quint64 key);
-
-private:
- QD3DImageCache cache;
-};
-
-IDirect3DTexture9 *QD3DImageManager::lookup(IDirect3DDevice9 *device, const QImage &image)
-{
- QD3DImage *tex_image = 0;
-
- tex_image = cache.object(image.cacheKey());
- if (!tex_image) {
- // to avoid cache thrashing we remove images from the cache
- // that have the same serial no as the cached image, since
- // that image is most likely destoyed already, and we got a
- // stale cache entry
- uint serial = (uint) (image.cacheKey() >> 32);
- QList<quint64> keys = cache.keys();
- for (int i=0; i<keys.size(); ++i) {
- if ((uint)(keys.at(i) >> 32) == serial) {
- cache.remove(keys.at(i));
- break;
- }
- }
-// qDebug(" => cached: %d, adding cache image: 0x%08x%08x",cache.size(), uint (image.cacheKey() >> 32),uint (image.cacheKey() & 0xffffffff));
- // add cache entry
- int cost = image.width()*image.height()*4/1024;
- if (cache.totalCost() + cost > cache.maxCost()) {
- // no room for new entries? kick out half the cached images
- int old_max_cost = cache.maxCost();
- cache.setMaxCost(old_max_cost/2);
- cache.setMaxCost(old_max_cost);
- }
- tex_image = new QD3DImage(device, image);
- cache.insert(image.cacheKey(), tex_image, cost);
-// qDebug() << "==> total cache cost: " << cache.totalCost() << cost;
- }
-
- return tex_image->texture;
-}
-
-void QD3DImageManager::remove(quint64 key)
-{
-// QList<quint64> keys = cache.keys();
-// if (keys.contains(key))
-// qDebug() << "entery removed from cache";
- cache.remove(key);
-}
-
-Q_GLOBAL_STATIC(QD3DImageManager, qd3d_image_cache)
-
-static void qd3d_image_cleanup(qint64 key)
-{
-// qDebug() << "qd3d_image_cleanup:";
-// qDebug(" => key: 0x%08x%08x", (uint) (key >> 32), (uint)(key & 0xffffffff));
- qd3d_image_cache()->remove(key);
-}
-
-//
-// end D3D image cache stuff
-//
-
-class QD3DDrawHelper : public QTessellator
-{
-public:
- QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe);
- ~QD3DDrawHelper();
-
- bool needsFlushing() const;
- QD3DMaskPosition allocateMaskPosition(const QRectF &brect, bool *breakbatch);
-
- void setClipPath(const QPainterPath &path, QD3DBatchItem **item);
-
- void queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect);
- QRectF queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color);
-
- void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect);
- void queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color);
-
- void queueTextGlyph(const QRectF &rect, const qreal *tex_coords, QD3DBatchItem *item,
- D3DCOLOR color);
-
- void queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect);
- void queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item);
-
- int drawAntialiasedMask(int offset, int maxoffset);
- void drawAliasedMask(int offset);
- void drawAntialiasedBoundingRect(QD3DBatchItem *item);
- void drawAliasedBoundingRect(QD3DBatchItem *item);
- void drawTextItem(QD3DBatchItem *item);
- void drawAliasedLines(QD3DBatchItem *item);
-
- void setMaskSize(QSize size);
-
- void beforeReset();
- void afterReset();
-
- IDirect3DSurface9 *freeMaskSurface();
-
- inline void lockVertexBuffer();
- inline void unlockVertexBuffer();
-
- inline int index() { return m_index; }
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- enum VertexBufferAccess {
- CLEAR = 0x00,
- READ = 0x01,
- WRITE = 0x02
- };
- int accesscontrol[QT_VERTEX_BUF_SIZE];
-#endif
-
-private:
- void addTrap(const Trapezoid &trap);
- void tessellate(const QPolygonF &poly);
- inline void lineToStencil(qreal x, qreal y);
- inline void curveToStencil(const QPointF &cp1, const QPointF &cp2, const QPointF &ep);
- QRectF pathToVertexArrays(const QPainterPath &path);
- void resetMask();
-
- QDirect3DPaintEnginePrivate *m_pe;
-
- qreal m_xoffset, m_yoffset;
- int m_startindex;
- int m_index;
- int m_height, m_width;
- LPDIRECT3DVERTEXBUFFER9 m_d3dvbuff;
- vertex *m_vbuff;
- QD3DBatchItem *m_item;
- QRectF m_boundingRect;
-
- qreal max_x;
- qreal max_y;
- qreal min_x;
- qreal min_y;
- qreal firstx;
- qreal firsty;
-
- QPointF tess_lastpoint;
- int tess_index;
-
- bool m_locked;
- IDirect3DTexture9 *m_mask;
- IDirect3DSurface9 *m_maskSurface;
- IDirect3DSurface9 *m_depthStencilSurface;
-
- D3DCOLOR m_color;
- bool m_clearmask;
- bool m_isLine;
- bool m_firstPoint;
-
- QD3DMaskPosition m_mask_position;
- int m_mask_offsetX2;
- int m_mask_offsetY2;
-};
-
-QD3DStateManager::QD3DStateManager(LPDIRECT3DDEVICE9 pDevice, ID3DXEffect *effect)
- : m_pDevice(pDevice), m_effect(effect), m_refs(0)
-{
- if (FAILED(D3DXMatrixIdentity(&m_d3dIdentityMatrix))) {
- qWarning("QDirect3DPaintEngine: D3DXMatrixIdentity failed");
- }
- reset();
-}
-
-void QD3DStateManager::reset()
-{
- m_radgradfd = -1;
-
- m_cosmetic_pen = false;
- m_pass = -1;
- m_maskchannel = -1;
- m_brushmode = -1;
- m_texture = 0;
- m_xoffset = INT_MAX;
- m_yoffset = INT_MAX;
-
- m_vertexshader = 0;
- m_pixelshader = 0;
-
- m_isIdentity = true;
- m_transformation = QTransform();
- m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix);
-
- ZeroMemory(&m_projection, sizeof(D3DMATRIX));
- ZeroMemory(m_textures, sizeof(LPDIRECT3DBASETEXTURE9) * D3D_STAGE_COUNT);
- FillMemory(m_samplerstates, sizeof(DWORD) * D3D_SAMPLE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE);
- FillMemory(m_texturestates, sizeof(DWORD) * D3D_TEXTURE_STATES * D3D_STAGE_COUNT, 0xFFFFFFFE);
- FillMemory(m_renderstate, sizeof(DWORD) * D3D_RENDER_STATES, 0xFFFFFFFE);
-}
-
-inline void QD3DStateManager::beginPass(int pass)
-{
- if (pass != m_pass) {
- if (m_pass != -1)
- m_effect->EndPass();
- m_effect->BeginPass(pass);
- m_pass = pass;
- }
-}
-
-inline void QD3DStateManager::endPass()
-{
- if (m_pass != -1) {
- m_pass = -1;
- m_effect->EndPass();
- }
-}
-
-inline void QD3DStateManager::startStateBlock() {
- m_changed = false;
-}
-
-inline void QD3DStateManager::setCosmeticPen(bool enabled)
-{
- if (enabled != m_cosmetic_pen) {
- m_effect->SetBool("g_mCosmeticPen", enabled);
- m_cosmetic_pen = enabled;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setBrushMode(int mode)
-{
- if (mode != m_brushmode) {
- m_effect->SetInt("g_mBrushMode", mode);
- m_brushmode = mode;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture)
-{
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER);
-
- if (pTexture != m_texture) {
- m_texture = pTexture;
- m_effect->SetTexture("g_mTexture", pTexture);
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setTexture(LPDIRECT3DBASETEXTURE9 pTexture, QGradient::Spread spread)
-{
- switch(spread) {
- case QGradient::RepeatSpread:
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
- break;
- case QGradient::ReflectSpread:
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_MIRROR);
- break;
- default:
- SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
- SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
- break;
- };
-
- if (pTexture != m_texture) {
- m_texture = pTexture;
- m_effect->SetTexture("g_mTexture", pTexture);
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setTransformation(const QTransform *matrix)
-{
- if (matrix) {
- if (*matrix != m_transformation) {
- D3DXMATRIX dxmatrix(matrix->m11(), matrix->m12(), 0, matrix->m13(),
- matrix->m21(), matrix->m22(), 0, matrix->m23(),
- 0, 0, 1, 0,
- matrix->dx(), matrix->dy(), 0, 1);
- m_effect->SetMatrix("g_mTransformation", &dxmatrix);
- m_transformation = *matrix;
- m_changed = true;
- m_isIdentity = false;
- }
- } else if (!m_isIdentity) {
- m_effect->SetMatrix("g_mTransformation", &m_d3dIdentityMatrix);
- m_transformation = QTransform();
- m_changed = true;
- m_isIdentity = true;
- }
-}
-
-inline void QD3DStateManager::setProjection(const D3DXMATRIX *pMatrix)
-{
- if (*pMatrix != m_projection) {
- m_effect->SetMatrix("g_mViewProjection", pMatrix);
- m_projection = *pMatrix;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setFocalDistance(const qreal &fd)
-{
- if (fd != m_radgradfd) {
- m_effect->SetFloat("g_mFocalDist", fd);
- m_changed = true;
- m_radgradfd = fd;
- }
-}
-
-inline void QD3DStateManager::setMaskOffset(qreal x, qreal y)
-{
- if (x != m_xoffset || y != m_yoffset) {
- float offset[2] = {x, y};
- m_effect->SetFloatArray("g_mMaskOffset", offset, 2);
- m_xoffset = x;
- m_yoffset = y;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::setMaskChannel(int channel)
-{
- if (m_maskchannel != channel) {
- m_effect->SetIntArray("g_mChannel", m_mask_channels[channel], 4);
- m_maskchannel = channel;
- m_changed = true;
- }
-}
-
-inline void QD3DStateManager::endStateBlock()
-{
- if (m_changed) {
- m_effect->CommitChanges();
- m_changed = false;
- }
-}
-
-STDMETHODIMP QD3DStateManager::QueryInterface(REFIID iid, LPVOID *ppv)
-{
- if(iid == IID_IUnknown || iid == IID_ID3DXEffectStateManager)
- {
- *ppv = this;
- ++m_refs;
- return NOERROR;
- }
- *ppv = NULL;
- return ResultFromScode(E_NOINTERFACE);
-}
-
-STDMETHODIMP_(ULONG) QD3DStateManager::AddRef(void)
-{
- return (ULONG)InterlockedIncrement( &m_refs );
-}
-
-
-STDMETHODIMP_(ULONG) QD3DStateManager::Release(void)
-{
- if( 0L == InterlockedDecrement( &m_refs ) ) {
- delete this;
- return 0L;
- }
-
- return m_refs;
-}
-STDMETHODIMP QD3DStateManager::SetTransform(D3DTRANSFORMSTATETYPE State, CONST D3DMATRIX *pMatrix)
-{
- return m_pDevice->SetTransform(State, pMatrix);
-}
-
-STDMETHODIMP QD3DStateManager::SetMaterial(CONST D3DMATERIAL9 *pMaterial)
-{
- return m_pDevice->SetMaterial(pMaterial);
-}
-
-STDMETHODIMP QD3DStateManager::SetLight(DWORD Index, CONST D3DLIGHT9 *pLight)
-{
- return m_pDevice->SetLight(Index, pLight);
-}
-
-STDMETHODIMP QD3DStateManager::LightEnable(DWORD Index, BOOL Enable)
-{
- return m_pDevice->LightEnable(Index, Enable);
-}
-
-STDMETHODIMP QD3DStateManager::SetRenderState(D3DRENDERSTATETYPE State, DWORD Value)
-{
- if (State < D3D_RENDER_STATES) {
- if (m_renderstate[State] == Value)
- return S_OK;
- m_renderstate[State] = Value;
- }
- return m_pDevice->SetRenderState(State, Value);
-}
-
-STDMETHODIMP QD3DStateManager::SetTexture(DWORD Stage, LPDIRECT3DBASETEXTURE9 pTexture)
-{
- if (Stage < D3D_STAGE_COUNT) {
- if (m_textures[Stage] == pTexture)
- return S_OK;
- m_textures[Stage] = pTexture;
- }
- return m_pDevice->SetTexture(Stage, pTexture);
-}
-
-STDMETHODIMP QD3DStateManager::SetTextureStageState(DWORD Stage, D3DTEXTURESTAGESTATETYPE Type, DWORD Value)
-{
- if (Stage < D3D_STAGE_COUNT && Type < D3D_TEXTURE_STATES) {
- if (m_texturestates[Stage][Type] == Value)
- return S_OK;
- m_texturestates[Stage][Type] = Value;
- }
- return m_pDevice->SetTextureStageState(Stage, Type, Value);
-}
-
-STDMETHODIMP QD3DStateManager::SetSamplerState(DWORD Sampler, D3DSAMPLERSTATETYPE Type, DWORD Value)
-{
- if (Sampler < D3D_STAGE_COUNT && Type < D3D_SAMPLE_STATES) {
- if (m_samplerstates[Sampler][Type] == Value)
- return S_OK;
- m_samplerstates[Sampler][Type] = Value;
- }
- return m_pDevice->SetSamplerState(Sampler, Type, Value);
-}
-
-STDMETHODIMP QD3DStateManager::SetNPatchMode(FLOAT NumSegments)
-{
- return m_pDevice->SetNPatchMode(NumSegments);
-}
-
-STDMETHODIMP QD3DStateManager::SetFVF(DWORD FVF)
-{
- return m_pDevice->SetFVF(FVF);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShader(LPDIRECT3DVERTEXSHADER9 pShader)
-{
- if (m_vertexshader == pShader)
- return S_OK;
- m_vertexshader = pShader;
- return m_pDevice->SetVertexShader(pShader);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetVertexShaderConstantF(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetVertexShaderConstantI(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetVertexShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetVertexShaderConstantB(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShader(LPDIRECT3DPIXELSHADER9 pShader)
-{
- if (m_pixelshader == pShader)
- return S_OK;
- m_pixelshader = pShader;
- return m_pDevice->SetPixelShader(pShader);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShaderConstantF(UINT RegisterIndex, CONST FLOAT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetPixelShaderConstantF(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShaderConstantI(UINT RegisterIndex, CONST INT *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetPixelShaderConstantI(RegisterIndex, pConstantData, RegisterCount);
-}
-
-STDMETHODIMP QD3DStateManager::SetPixelShaderConstantB(UINT RegisterIndex, CONST BOOL *pConstantData, UINT RegisterCount)
-{
- return m_pDevice->SetPixelShaderConstantB(RegisterIndex, pConstantData, RegisterCount);
-}
-
-#define QD3D_GRADIENT_CACHE_SIZE 60
-#define QD3D_GRADIENT_PALETTE_SIZE 1024
-
-class QD3DGradientCache
-{
- struct CacheInfo
- {
- inline CacheInfo(QGradientStops s, qreal op) :
- stops(s), opacity(op) {}
-
- IDirect3DTexture9 *texture;
- QGradientStops stops;
- qreal opacity;
- };
-
- typedef QMultiHash<quint64, CacheInfo> QD3DGradientColorTableHash;
-
-public:
- QD3DGradientCache(LPDIRECT3DDEVICE9 device);
- ~QD3DGradientCache();
-
- inline IDirect3DTexture9 *getBuffer(const QGradientStops &stops, qreal opacity);
-
-protected:
- inline void generateGradientColorTable(const QGradientStops& s,
- uint *colorTable,
- int size, qreal opacity) const;
- IDirect3DTexture9 *addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity);
- void cleanCache();
-
- QD3DGradientColorTableHash cache;
- LPDIRECT3DDEVICE9 m_device;
-};
-
-QD3DGradientCache::QD3DGradientCache(LPDIRECT3DDEVICE9 device)
- : m_device(device)
-{
-
-}
-
-QD3DGradientCache::~QD3DGradientCache()
-{
- cleanCache();
-}
-
-inline IDirect3DTexture9 *QD3DGradientCache::getBuffer(const QGradientStops &stops, qreal opacity)
-{
- quint64 hash_val = 0;
-
- for (int i = 0; i < stops.size() && i <= 2; i++)
- hash_val += stops[i].second.rgba();
-
- QD3DGradientColorTableHash::const_iterator it = cache.constFind(hash_val);
-
- if (it == cache.constEnd())
- return addCacheElement(hash_val, stops, opacity);
- else {
- do {
- const CacheInfo &cache_info = it.value();
- if (cache_info.stops == stops && cache_info.opacity == opacity) {
- return cache_info.texture;
- }
- ++it;
- } while (it != cache.constEnd() && it.key() == hash_val);
- // an exact match for these stops and opacity was not found, create new cache
- return addCacheElement(hash_val, stops, opacity);
- }
-}
-
-void QD3DGradientCache::generateGradientColorTable(const QGradientStops& s, uint *colorTable, int size, qreal opacity) const
-{
- int pos = 0;
- qreal fpos = 0.0;
- qreal incr = 1.0 / qreal(size);
- QVector<uint> colors(s.size());
-
- for (int i = 0; i < s.size(); ++i)
- colors[i] = s[i].second.rgba();
-
- uint alpha = qRound(opacity * 255);
- while (fpos < s.first().first) {
- colorTable[pos] = ARGB_COMBINE_ALPHA(colors[0], alpha);
- pos++;
- fpos += incr;
- }
-
- for (int i = 0; i < s.size() - 1; ++i) {
- qreal delta = 1/(s[i+1].first - s[i].first);
- while (fpos < s[i+1].first && pos < size) {
- int dist = int(256 * ((fpos - s[i].first) * delta));
- int idist = 256 - dist;
- uint current_color = ARGB_COMBINE_ALPHA(colors[i], alpha);
- uint next_color = ARGB_COMBINE_ALPHA(colors[i+1], alpha);
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- colorTable[pos] = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
-#else
- uint c = INTERPOLATE_PIXEL_256(current_color, idist, next_color, dist);
- colorTable[pos] = ( (c << 24) & 0xff000000)
- | ((c >> 24) & 0x000000ff)
- | ((c << 8) & 0x00ff0000)
- | ((c >> 8) & 0x0000ff00);
-#endif // Q_BYTE_ORDER
- ++pos;
- fpos += incr;
- }
- }
- for (;pos < size; ++pos)
- colorTable[pos] = colors[s.size() - 1];
-}
-
-IDirect3DTexture9 *QD3DGradientCache::addCacheElement(quint64 hash_val, const QGradientStops &stops, qreal opacity)
-{
- if (cache.size() == QD3D_GRADIENT_CACHE_SIZE) {
- int elem_to_remove = qrand() % QD3D_GRADIENT_CACHE_SIZE;
- uint key = cache.keys()[elem_to_remove];
-
- // need to call release on each removed cache entry:
- QD3DGradientColorTableHash::const_iterator it = cache.constFind(key);
- do {
- it.value().texture->Release();
- } while (++it != cache.constEnd() && it.key() == key);
-
- cache.remove(key); // may remove more than 1, but OK
- }
-
- CacheInfo cache_entry(stops, opacity);
- uint buffer[QD3D_GRADIENT_PALETTE_SIZE];
- generateGradientColorTable(stops, buffer, QD3D_GRADIENT_PALETTE_SIZE, opacity);
-
- if (FAILED(m_device->CreateTexture(QD3D_GRADIENT_PALETTE_SIZE, 1, 1, 0,
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &cache_entry.texture, 0))) {
- qWarning("QD3DGradientCache::addCacheElement(): unable to create Direct3D texture.");
- return 0;
- }
-
- D3DLOCKED_RECT rect;
- if (FAILED(cache_entry.texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "QD3DGradientCache::addCacheElement(): unable to lock texture rect.";
- return 0;
- }
- memcpy(rect.pBits, buffer, rect.Pitch);
- cache_entry.texture->UnlockRect(0);
-
- return cache.insert(hash_val, cache_entry).value().texture;
-}
-
-void QD3DGradientCache::cleanCache()
-{
- QD3DGradientColorTableHash::const_iterator it = cache.constBegin();
- for (; it != cache.constEnd(); ++it) {
- const CacheInfo &cache_info = it.value();
- cache_info.texture->Release();
- }
- cache.clear();
-}
-
-QD3DSurfaceManager::QD3DSurfaceManager() :
- m_status(NoStatus), m_dummy(0), m_device(0), m_pd(0), m_current(0)
-{
-
-}
-
-QD3DSurfaceManager::~QD3DSurfaceManager()
-{
-}
-
-void QD3DSurfaceManager::setPaintDevice(QPaintDevice *pd)
-{
- m_status = NoStatus;
- m_pd = pd;
- m_current = 0;
-
- if (m_device->TestCooperativeLevel() != D3D_OK) {
- m_status = NeedsResetting;
- return;
- }
-
- m_current = m_swapchains.value(pd, 0);
- QWidget *w = static_cast<QWidget*>(pd);
-
- if (m_current) {
- if (m_current->size != w->size()) {
- m_swapchains.remove(pd);
- m_current->surface->Release();
- m_current->swapchain->Release();
- delete m_current;
- m_current = 0;
- }
- }
-
- if (!m_current) {
- m_current = createSwapChain(w);
- updateMaxSize();
- }
-}
-
-int QD3DSurfaceManager::status() const
-{
- return m_status;
-}
-
-void QD3DSurfaceManager::reset()
-{
- QList<QPaintDevice *> pds = m_swapchains.keys();
-
- QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin();
- while (i != m_swapchains.constEnd()) {
- i.value()->surface->Release();
- i.value()->swapchain->Release();
- ++i;
- }
- qDeleteAll(m_swapchains.values());
- m_swapchains.clear();
-
- D3DPRESENT_PARAMETERS params;
- initPresentParameters(&params);
- params.hDeviceWindow = m_dummy;
-
- HRESULT res = m_device->Reset(&params);
- if (FAILED(res)) {
- switch (res) {
- case D3DERR_DEVICELOST:
- qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DEVICELOST)");
- break;
- case D3DERR_DRIVERINTERNALERROR:
- qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_DRIVERINTERNALERROR)");
- break;
- case D3DERR_OUTOFVIDEOMEMORY:
- qWarning("QDirect3DPaintEngine: Reset failed (D3DERR_OUTOFVIDEOMEMORY)");
- break;
- default:
- qWarning("QDirect3DPaintEngine: Reset failed");
- };
- }
-
- for (int i=0; i<pds.count(); ++i) {
- QWidget *w = static_cast<QWidget*>(pds.at(i));
- createSwapChain(w);
- }
-
- // reset the mask as well
- m_status = MaxSizeChanged;
-
- setPaintDevice(m_pd);
- updateMaxSize();
-}
-
-LPDIRECT3DSURFACE9 QD3DSurfaceManager::renderTarget()
-{
- return m_current ? m_current->surface : 0;
-}
-
-LPDIRECT3DSURFACE9 QD3DSurfaceManager::surface(QPaintDevice *pd)
-{
- D3DSwapChain *swapchain = m_swapchains.value(pd, 0);
- return swapchain ? swapchain->surface : 0;
-}
-
-LPDIRECT3DSWAPCHAIN9 QD3DSurfaceManager::swapChain(QPaintDevice *pd)
-{
- D3DSwapChain *swapchain = m_swapchains.value(pd, 0);
- return swapchain ? swapchain->swapchain : 0;
-}
-
-void QD3DSurfaceManager::releasePaintDevice(QPaintDevice *pd)
-{
- D3DSwapChain *swapchain = m_swapchains.take(pd);
-
- if (swapchain) {
- swapchain->surface->Release();
- swapchain->swapchain->Release();
- delete swapchain;
- if (swapchain == m_current)
- m_current = 0;
- }
-}
-
-LPDIRECT3DDEVICE9 QD3DSurfaceManager::device()
-{
- return m_device;
-}
-
-void QD3DSurfaceManager::cleanup()
-{
- QPixmapCache::clear();
- qd3d_glyph_cache()->cleanCache();
-
- // release doomed textures
- for (int k=0; k<qd3d_release_list.size(); ++k)
- qd3d_release_list.at(k)->Release();
- qd3d_release_list.clear();
-
- QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin();
- while (i != m_swapchains.constEnd()) {
- i.value()->surface->Release();
- i.value()->swapchain->Release();
- ++i;
- }
- qDeleteAll(m_swapchains.values());
-
- if (m_device)
- m_device->Release();
-
- DestroyWindow(m_dummy);
- QString cname(QLatin1String("qt_d3d_dummy"));
- QT_WA({
- UnregisterClass((TCHAR*)cname.utf16(), (HINSTANCE)qWinAppInst());
- } , {
- UnregisterClassA(cname.toLatin1(), (HINSTANCE)qWinAppInst());
- });
-}
-
-QSize QD3DSurfaceManager::maxSize() const
-{
- return m_max_size;
-}
-
-extern "C" {
- LRESULT CALLBACK QtWndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);
-};
-
-void QD3DSurfaceManager::init(LPDIRECT3D9 object)
-{
- QString cname(QLatin1String("qt_d3d_dummy"));
- uint style = CS_DBLCLKS | CS_SAVEBITS;
- ATOM atom;
- QT_WA({
- WNDCLASS wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = 0;
- wc.lpszMenuName = 0;
- wc.lpszClassName = (TCHAR*)cname.utf16();
- atom = RegisterClass(&wc);
- } , {
- WNDCLASSA wc;
- wc.style = style;
- wc.lpfnWndProc = (WNDPROC)QtWndProc;
- wc.cbClsExtra = 0;
- wc.cbWndExtra = 0;
- wc.hInstance = (HINSTANCE)qWinAppInst();
- wc.hIcon = 0;
- wc.hCursor = 0;
- wc.hbrBackground = 0;
- wc.lpszMenuName = 0;
- QByteArray tempArray = cname.toLatin1();
- wc.lpszClassName = tempArray;
- atom = RegisterClassA(&wc);
- });
-
- QT_WA({
- const TCHAR *className = (TCHAR*)cname.utf16();
- m_dummy = CreateWindow(className, className, 0,
- 0, 0, 1, 1,
- 0, 0, qWinAppInst(), 0);
- } , {
- m_dummy = CreateWindowA(cname.toLatin1(), cname.toLatin1(), 0,
- 0, 0, 1, 1,
- 0, 0, qWinAppInst(), 0);
- });
-
- D3DPRESENT_PARAMETERS params;
- initPresentParameters(&params);
- params.hDeviceWindow = m_dummy;
-
- HRESULT res = object->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, 0,
- D3DCREATE_PUREDEVICE|D3DCREATE_HARDWARE_VERTEXPROCESSING|D3DCREATE_NOWINDOWCHANGES|D3DCREATE_FPU_PRESERVE,
- &params, &m_device);
-
- if (FAILED(res) || m_device == 0)
- qWarning("QDirect3DPaintEngine: failed to create Direct3D device (error=0x%x).", res);
-}
-
-void QD3DSurfaceManager::updateMaxSize()
-{
- int w = 0, h = 0;
- QMap<QPaintDevice *, D3DSwapChain *>::const_iterator i = m_swapchains.constBegin();
- while (i != m_swapchains.constEnd()) {
-
- int nw = i.key()->width();
- if (nw > w)
- w = nw;
-
- int nh = i.key()->height();
- if (nh > h)
- h = nh;
-
- ++i;
- }
-
- QSize newsize = QSize(w, h);
- if (newsize != m_max_size) {
- m_status |= MaxSizeChanged;
- m_max_size = newsize;
- }
-}
-
-void QD3DSurfaceManager::initPresentParameters(D3DPRESENT_PARAMETERS *params)
-{
- ZeroMemory(params, sizeof(D3DPRESENT_PARAMETERS));
- params->Windowed = true;
- params->SwapEffect = D3DSWAPEFFECT_COPY;
- params->BackBufferFormat = D3DFMT_UNKNOWN;
- params->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
- params->Flags = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
-}
-
-QD3DSurfaceManager::D3DSwapChain *QD3DSurfaceManager::createSwapChain(QWidget *w)
-{
- D3DPRESENT_PARAMETERS params;
- initPresentParameters(&params);
- params.hDeviceWindow = w->winId();
- D3DSwapChain *swapchain = new D3DSwapChain();
- swapchain->size = w->size();
- if (FAILED(m_device->CreateAdditionalSwapChain(&params, &swapchain->swapchain)))
- qWarning("QDirect3DPaintEngine: CreateAdditionalSwapChain failed");
- if (FAILED(swapchain->swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &swapchain->surface)))
- qWarning("QDirect3DPaintEngine: GetBackBuffer failed");
- m_swapchains.insert(w, swapchain);
- connect(w, SIGNAL(destroyed(QObject *)), SLOT(cleanupPaintDevice(QObject *)));
-
- // init with background color
- QColor bg = w->palette().color(QPalette::Background);
- m_device->ColorFill(swapchain->surface, 0, D3DCOLOR_ARGB(bg.alpha(), bg.red(),bg.green(),bg.blue()));
-
- return swapchain;
-}
-
-void QD3DSurfaceManager::cleanupPaintDevice(QObject *object)
-{
- QWidget *w = static_cast<QWidget *>(object);
- releasePaintDevice(w);
-}
-
-int QD3DStateManager::m_mask_channels[4][4] =
- {{1,0,0,0},{0,1,0,0},{0,0,1,0},{0,0,0,1}};
-
-QD3DDrawHelper::QD3DDrawHelper(QDirect3DPaintEnginePrivate *pe)
- : m_pe(pe), m_d3dvbuff(0), m_maskSurface(0), m_depthStencilSurface(0),
- m_locked(false), m_mask(0), m_startindex(0), m_index(0), m_vbuff(0), m_clearmask(true),
- m_isLine(false), m_firstPoint(true)
-{
- resetMask();
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess));
-#endif
-
- // create vertex buffer
- afterReset();
-}
-
-QD3DDrawHelper::~QD3DDrawHelper()
-{
- if (m_maskSurface)
- m_maskSurface->Release();
-
- if (m_mask)
- m_mask->Release();
-
- if (m_depthStencilSurface)
- m_depthStencilSurface->Release();
-
- if (m_d3dvbuff)
- m_d3dvbuff->Release();
-}
-
-inline void QD3DDrawHelper::lockVertexBuffer()
-{
- if (!m_locked) {
- DWORD lockflags = D3DLOCK_NOOVERWRITE;
- if (m_startindex >= QT_VERTEX_RESET_LIMIT) {
- m_startindex = 0;
- m_index = 0;
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=0; i<QT_VERTEX_BUF_SIZE; ++i) {
- if (accesscontrol[i] != (WRITE|READ) && accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- }
- memset(accesscontrol, 0, QT_VERTEX_BUF_SIZE * sizeof(VertexBufferAccess));
-#endif
-
- lockflags = D3DLOCK_DISCARD;
- }
-
- if (FAILED(m_d3dvbuff->Lock(0, 0, (void**)&m_vbuff, lockflags))) {
- qWarning() << "QDirect3DPaintEngine: unable to lock vertex buffer.";
- }
- m_locked = true;
- }
-}
-
-inline void QD3DDrawHelper::unlockVertexBuffer()
-{
- if (m_locked) {
- if (FAILED(m_d3dvbuff->Unlock())) {
- qWarning() << "QDirect3DPaintEngine: unable to unlock vertex buffer.";
- }
- m_locked = false;
- }
-}
-
-void QD3DDrawHelper::setClipPath(const QPainterPath &path, QD3DBatchItem **item)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_maskpos.x = m_item->m_maskpos.y = 0;
- m_item->m_maskpos.channel = 3;
- m_item->m_info |= QD3DBatchItem::BI_CLIP;
-
- bool winding = (path.fillRule() == Qt::WindingFill);
- if (winding)
- m_item->m_info |= QD3DBatchItem::BI_WINDING;
-
- if (!path.isEmpty()) {
- m_item->m_info |= QD3DBatchItem::BI_MASK;
- m_item->m_info &= ~QD3DBatchItem::BI_AA;
- m_color = 0;
- QRectF brect = pathToVertexArrays(path);
- queueRect(brect, m_item, 0);
- }
-
- *item = m_item;
-}
-
-
-
-void QD3DDrawHelper::queueAntialiasedMask(const QPolygonF &poly, QD3DBatchItem **item, const QRectF &brect)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_MASK;
- setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING);
-
- int xoffset = m_item->m_maskpos.x;
- int yoffset = m_item->m_maskpos.y;
-
- int x = brect.left();
- int y = brect.top();
-
- m_item->m_xoffset = (xoffset - x) + 1;
- m_item->m_yoffset = (yoffset - y) + 1;
-
- m_boundingRect = brect;
- tessellate(poly);
-
- *item = m_item;
-}
-
-QRectF QD3DDrawHelper::queueAliasedMask(const QPainterPath &path, QD3DBatchItem **item, D3DCOLOR color)
-{
- lockVertexBuffer();
-
- m_color = color;
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_MASK;
-
- bool winding = (path.fillRule() == Qt::WindingFill);
- if (winding)
- m_item->m_info |= QD3DBatchItem::BI_WINDING;
-
- QRectF result = pathToVertexArrays(path);
- *item = m_item;
- return result;
-}
-
-// used for drawing aliased transformed rects directly
-// don't use for antialiased or masked drawing
-void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color, const QPolygonF &trect)
-{
- lockVertexBuffer();
-
- qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f;
- item->m_info |= QD3DBatchItem::BI_BRECT;
-
- // if the item does not have a mask, the offset is different
- if (!(item->m_info & QD3DBatchItem::BI_MASK)) {
- item->m_offset = m_index;
- item->m_count = (item->m_info & QD3DBatchItem::BI_AA) ? 0 : -2;
- }
-
- qreal x1 = rect.left();
- qreal y1 = rect.top();
- qreal x2 = rect.right();
- qreal y2 = rect.bottom();
-
- QPointF tc = trect.at(0);
- vertex v1 = { {x1, y1, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f };
-
- tc = trect.at(1);
- vertex v2 = { {x2, y1, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
-
- tc = trect.at(2);
- vertex v3 = { {x2, y2, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};;
-
- tc = trect.at(3);
- vertex v4 = { {x1, y2, zval} , color,
- tc.x(), tc.y(), 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 4); ++i) {
- if ((m_index + 4) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
-
- m_startindex = m_index;
-}
-
-
-QD3DMaskPosition QD3DDrawHelper::allocateMaskPosition(const QRectF &brect, bool *breakbatch)
-{
- int w = brect.width();
- int h = brect.height();
-
- w += 3;
- h += 3;
-
- if (w > m_width)
- w = m_width;
- if (h > m_height)
- h = m_height;
-
- *breakbatch = false;
-
- if ((m_height - m_mask_offsetY2) >= h && (m_width - m_mask_position.x) >= w) {
- m_mask_position.y = m_mask_offsetY2;
- } else if ((m_width - m_mask_offsetX2) >= w) {
- m_mask_position.y = QD3D_MASK_MARGIN;
- m_mask_position.x = m_mask_offsetX2;
- } else if (m_mask_position.channel < 3) {
- ++m_mask_position.channel;
- m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN;
- m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN;
- } else {
- resetMask();
- *breakbatch = true;
- }
-
- int newoffset = m_mask_position.x + w;
- if (m_mask_offsetX2 < newoffset)
- m_mask_offsetX2 = newoffset;
- m_mask_offsetY2 = (m_mask_position.y + h);
-
- return m_mask_position;
-
-}
-
-void QD3DDrawHelper::queueRect(const QRectF &rect, QD3DBatchItem *item, D3DCOLOR color)
-{
- lockVertexBuffer();
-
- QRectF brect;
- item->m_info |= QD3DBatchItem::BI_BRECT;
- qreal zval = (item->m_info & QD3DBatchItem::BI_CLIP) ? 0.0f : 0.5f;
-
- if (item->m_info & QD3DBatchItem::BI_AA) {
- int xoffset = item->m_maskpos.x;
- int yoffset = item->m_maskpos.y;
-
- int x = rect.left();
- int y = rect.top();
-
- brect = QRectF(x, y, rect.width() + 1, rect.height() + 1);
-
- item->m_xoffset = (xoffset - x) + 1;
- item->m_yoffset = (yoffset - y) + 1;
-
- // if the item does not have a mask, the offset is different
- if (!(item->m_info & QD3DBatchItem::BI_MASK)) {
- item->m_offset = m_index;
- item->m_count = 0;
- }
- } else {
- brect = rect;
-
- if (!(item->m_info & QD3DBatchItem::BI_MASK)) {
- item->m_offset = m_index;
- item->m_count = -2;
- }
- }
-
- qreal left = brect.left();
- qreal right = brect.right();
- qreal top = brect.top();
- qreal bottom = brect.bottom();
-
- vertex v1 = { {left, bottom, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- vertex v2 = { {left, top, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- vertex v3 = { {right, top, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- vertex v4 = { {right, bottom, zval}, color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 4); ++i) {
- if ((m_index + 4) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
-
- m_startindex = m_index;
-}
-
-void QD3DDrawHelper::queueAntialiasedLines(const QPainterPath &path, QD3DBatchItem **item, const QRectF &brect)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_MASK;
- setWinding(m_item->m_info & QD3DBatchItem::BI_WINDING);
-
- int xoffset = m_item->m_maskpos.x;
- int yoffset = m_item->m_maskpos.y;
- int x = brect.left();
- int y = brect.top();
-
- m_item->m_xoffset = (xoffset - x) + 1;
- m_item->m_yoffset = (yoffset - y) + 1;
-
- m_boundingRect = brect;
-
- m_xoffset = (x - xoffset) + 0.5f;
- m_yoffset = (y - yoffset) + 0.5f;
-
- QPointF last;
- for (int i = 0; i < path.elementCount(); ++i) {
- QPainterPath::Element element = path.elementAt(i);
-
- //Q_ASSERT(!element.isCurveTo());
-
- if (element.isLineTo())
- QTessellator::tessellateRect(last, element, m_item->m_width);
-
- last = element;
- }
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 3;
- m_startindex = m_index;
-
- *item = m_item;
-}
-
-void QD3DDrawHelper::queueAliasedLines(const QLineF *lines, int lineCount, QD3DBatchItem **item)
-{
- lockVertexBuffer();
-
- m_item = *item;
- m_item->m_info |= QD3DBatchItem::BI_FASTLINE;
-
- for (int i=0; i<lineCount; ++i) {
- const QLineF line = lines[i];
- qreal p1x = line.p1().x();
- qreal p1y = line.p1().y();
- qreal p2x = line.p2().x();
- qreal p2y = line.p2().y();
-
- vertex v1 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- -1.f, -1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
- vertex v2 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- 1.f, -1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
- vertex v3 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- 1.f, 1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
- vertex v4 = { {p1x, p1y, m_pe->m_pen_width} , m_pe->m_pen_color,
- -1.f, 1.f, p2x, p2y,
- 0.f, 0.f, 0.f, 0.f };
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
-
- if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) {
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 2;
- m_startindex = m_index;
-
- QD3DBatchItem itemcopy = *m_item;
- m_item = m_pe->nextBatchItem();
- *m_item = itemcopy;
-
- lockVertexBuffer();
- }
- }
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) - 2;
- m_startindex = m_index;
-
- *item = m_item;
-}
-
-void QD3DDrawHelper::queueTextGlyph(const QRectF &rect, const qreal *tex_coords,
- QD3DBatchItem *item, D3DCOLOR color)
-{
- lockVertexBuffer();
-
- qreal x1 = rect.left();
- qreal y1 = rect.top();
- qreal x2 = rect.right();
- qreal y2 = rect.bottom();
-
- vertex v1 = { {x1, y1, 0.5f}, color,
- tex_coords[0], tex_coords[1], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v2 = { {x2, y1, 0.5f}, color,
- tex_coords[2], tex_coords[1], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v3 = { {x2, y2, 0.5f}, color,
- tex_coords[2], tex_coords[3], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v4 = { {x1, y1, 0.5f}, color,
- tex_coords[0], tex_coords[1], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v5 = { {x2, y2, 0.5f}, color,
- tex_coords[2], tex_coords[3], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
- vertex v6 = { {x1, y2, 0.5f}, color,
- tex_coords[0], tex_coords[3], 0.f, 0.f,
- 0.f , 0.f , 0.f, 0.f};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 6); ++i) {
- if ((m_index + 6) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v5;
- m_vbuff[m_index++] = v6;
-
- m_startindex = m_index;
- ++item->m_count;
-}
-
-bool QD3DDrawHelper::needsFlushing() const
-{
- return (m_pe->m_batch.m_item_index >= QD3D_BATCH_SIZE || m_startindex >= QT_VERTEX_RESET_LIMIT);
-}
-
-void QD3DDrawHelper::setMaskSize(QSize size)
-{
- m_width = size.width();
- m_height = size.height();
-
- if (m_maskSurface)
- m_maskSurface->Release();
-
- if (m_mask)
- m_mask->Release();
-
- if (FAILED(m_pe->m_d3d_device->CreateTexture(m_width, m_height, 1, D3DUSAGE_RENDERTARGET,
- D3DFMT_A8R8G8B8, D3DPOOL_DEFAULT, &m_mask, NULL))) {
- qWarning() << "QDirect3DPaintEngine: CreateTexture() failed.";
- }
-
- if (m_depthStencilSurface)
- m_depthStencilSurface->Release();
-
- if (FAILED(m_pe->m_d3d_device->CreateDepthStencilSurface(m_width, m_height, D3DFMT_D24S8, D3DMULTISAMPLE_NONE, 0,
- TRUE, &m_depthStencilSurface, NULL))) {
- qWarning() << "QDirect3DPaintEngine: CreateDepthStencilSurface() failed.";
- }
-
- m_pe->m_d3d_device->SetDepthStencilSurface(m_depthStencilSurface);
- m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER|D3DCLEAR_STENCIL, 0, 0.0f, 0);
-
- if (FAILED(m_mask->GetSurfaceLevel(0, &m_maskSurface))) {
- qWarning() << "QDirect3DPaintEngine: GetSurfaceLevel() failed.";
- }
-
- m_pe->m_d3d_device->ColorFill(m_maskSurface, 0, D3DCOLOR_ARGB(0,0,0,0));
- D3DXMATRIX projMatrix;
- pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, m_width, m_height, 0, 0, 1);
- m_pe->m_effect->SetMatrix("g_mMaskProjection", &projMatrix);
- m_pe->m_effect->SetTexture("g_mAAMask", m_mask);
-}
-
-void QD3DDrawHelper::beforeReset()
-{
- resetMask();
- m_clearmask = true;
-
- if (m_maskSurface) {
- m_maskSurface->Release();
- m_maskSurface = 0;
- }
-
- if (m_mask) {
- m_mask->Release();
- m_mask = 0;
- }
-
- if (m_depthStencilSurface) {
- m_depthStencilSurface->Release();
- m_depthStencilSurface = 0;
- }
-
- if (m_d3dvbuff)
- m_d3dvbuff->Release();
-}
-
-void QD3DDrawHelper::afterReset()
-{
- if (FAILED(m_pe->m_d3d_device->CreateVertexBuffer(QT_VERTEX_BUF_SIZE*sizeof(vertex), D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY,
- QD3DFVF_CSVERTEX,
- D3DPOOL_DEFAULT, &m_d3dvbuff, NULL))) {
- qWarning() << "QDirect3DPaintEngine: failed to create vertex buffer.";
- }
-
- m_pe->m_d3d_device->SetStreamSource(0, m_d3dvbuff, 0, sizeof(vertex));
- m_pe->m_d3d_device->SetFVF(QD3DFVF_CSVERTEX);
-
- m_startindex = 0;
- m_index = 0;
-}
-
-IDirect3DSurface9 *QD3DDrawHelper::freeMaskSurface()
-{
- // we need to make sure the mask is cleared when it's used for something else
- resetMask();
- m_clearmask = true;
-
- return m_maskSurface;
-}
-
-int QD3DDrawHelper::drawAntialiasedMask(int offset, int maxoffset)
-{
- int newoffset = offset;
- QD3DBatchItem *item = &(m_pe->m_batch.items[offset]);
-
- // set mask as render target
- if (FAILED(m_pe->m_d3d_device->SetRenderTarget(0, m_maskSurface)))
- qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!";
-
- if (m_clearmask) {
- m_pe->m_d3d_device->Clear(0, 0, D3DCLEAR_TARGET,D3DCOLOR_ARGB(0,0,0,0), 0, 0);
- m_clearmask = false;
- }
-
- // fill the mask
- m_pe->m_statemanager->beginPass(PASS_AA_CREATEMASK);
- for (; newoffset<maxoffset; ++newoffset) {
- item = &(m_pe->m_batch.items[newoffset]);
- if (!(item->m_info & QD3DBatchItem::BI_AA) || !(item->m_info & QD3DBatchItem::BI_MASK)) {
- break;
- } else if (item->m_info & QD3DBatchItem::BI_MASKFULL) {
- item->m_info &= ~QD3DBatchItem::BI_MASKFULL;
- m_clearmask = true;
- break;
- }
-
- m_pe->m_statemanager->startStateBlock();
- if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) {
- RECT rect;
- QRectF srect = item->m_brect.adjusted(item->m_xoffset, item->m_yoffset,
- item->m_xoffset, item->m_yoffset);
- rect.left = qMax(qRound(srect.left()), 0);
- rect.top = qMax(qRound(srect.top()), 0);
- rect.bottom = qMin(m_height, qRound(srect.bottom()));
- rect.right = qMin(m_width, qRound(srect.right()));
- m_pe->m_d3d_device->SetScissorRect(&rect);
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
- }
- m_pe->m_statemanager->setMaskChannel(item->m_maskpos.channel);
- m_pe->m_statemanager->endStateBlock();
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = item->m_offset;
- for (int i=vbstart; i<(vbstart + (item->m_count * 3)); ++i) {
- if (accesscontrol[i] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= READ;
- }
-#endif
-
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count);
-
- if (item->m_info & QD3DBatchItem::BI_MASKSCISSOR) {
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
- }
- }
- m_pe->m_statemanager->endPass();
-
- return newoffset;
-}
-
-void QD3DDrawHelper::drawAliasedMask(int offset)
-{
- QD3DBatchItem *item = &(m_pe->m_batch.items[offset]);
- if (item->m_info & QD3DBatchItem::BI_MASK) {
- m_pe->m_statemanager->beginPass( (item->m_info & QD3DBatchItem::BI_WINDING) ? PASS_STENCIL_WINDING : PASS_STENCIL_ODDEVEN );
- int prev_stop = 0;
- for (int i=0; i<item->m_pointstops.count(); ++i) {
- int stop = item->m_pointstops.at(i);
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = (item->m_offset + prev_stop);
- for (int j=vbstart; j<(vbstart+(stop - prev_stop)); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + prev_stop, (stop - prev_stop) - 2);
- prev_stop = stop;
- }
- m_pe->m_statemanager->endPass();
- }
-}
-
-void QD3DDrawHelper::drawTextItem(QD3DBatchItem *item)
-{
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = item->m_offset;
- for (int j=vbstart; j<(vbstart + ((item->m_count * 2) * 3)); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, item->m_count*2);
-}
-
-void QD3DDrawHelper::drawAliasedLines(QD3DBatchItem *item)
-{
- m_pe->m_statemanager->setCosmeticPen(item->m_info & QD3DBatchItem::BI_COSMETICPEN);
- if (item->m_info & QD3DBatchItem::BI_TRANSFORM) {
- m_pe->m_statemanager->setTransformation(&item->m_matrix);
- } else {
- m_pe->m_statemanager->setTransformation();
- }
- int pass = (item->m_info & QD3DBatchItem::BI_MASK)
- ? PASS_ALIASED_LINES
- : PASS_ALIASED_LINES_DIRECT;
- m_pe->m_statemanager->beginPass(pass);
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLELIST, item->m_offset, (item->m_count + 2) / 3);
- m_pe->m_statemanager->endPass();
-}
-
-void QD3DDrawHelper::drawAntialiasedBoundingRect(QD3DBatchItem *item)
-{
- if (item->m_info & QD3DBatchItem::BI_SCISSOR) {
- RECT rect;
- rect.left = qMax(qRound(item->m_brect.left()), 0);
- rect.top = qMax(qRound(item->m_brect.top()), 0);
- rect.bottom = qMin(m_height, qRound(item->m_brect.bottom()));
- rect.right = qMin(m_width, qRound(item->m_brect.right()));
- m_pe->m_d3d_device->SetScissorRect(&rect);
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
- }
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = item->m_offset + (item->m_count * 3);
- for (int j=vbstart; j<(vbstart + 4); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
-
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + (item->m_count * 3), 2);
-
- if (item->m_info & QD3DBatchItem::BI_SCISSOR) {
- m_pe->m_statemanager->SetRenderState(D3DRS_SCISSORTESTENABLE, FALSE);
- }
-}
-
-void QD3DDrawHelper::drawAliasedBoundingRect(QD3DBatchItem *item)
-{
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- int vbstart = (item->m_offset + item->m_count + 2);
- for (int j=vbstart; j<(vbstart + 4); ++j) {
- if (accesscontrol[j] != WRITE)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[j] |= READ;
- }
-#endif
-
- m_pe->m_d3d_device->DrawPrimitive(D3DPT_TRIANGLEFAN, item->m_offset + item->m_count + 2, 2);
-}
-
-void QD3DDrawHelper::addTrap(const Trapezoid &trap)
-{
- qreal topLeftY = Q27Dot5ToDouble(trap.topLeft->y) - m_yoffset;
- qreal topLeftX = Q27Dot5ToDouble(trap.topLeft->x) - m_xoffset;
- qreal topRightY = Q27Dot5ToDouble(trap.topRight->y) - m_yoffset;
- qreal topRightX = Q27Dot5ToDouble(trap.topRight->x) - m_xoffset;
- qreal top = Q27Dot5ToDouble(trap.top) - m_yoffset;
- qreal bottom = Q27Dot5ToDouble(trap.bottom) - m_yoffset;
-
- Q27Dot5 _h = trap.topLeft->y - trap.bottomLeft->y;
- Q27Dot5 _w = trap.topLeft->x - trap.bottomLeft->x;
- qreal _leftA = (qreal)_w/_h;
- qreal _leftB = topLeftX - _leftA * topLeftY;
-
- _h = trap.topRight->y - trap.bottomRight->y;
- _w = trap.topRight->x - trap.bottomRight->x;
- qreal _rightA = (qreal)_w/_h;
- qreal _rightB = topRightX - _rightA * topRightY;
-
- qreal invLeftA = qFuzzyCompare(_leftA + 1, 1) ? 0.0 : 1.0 / _leftA;
- qreal invRightA = qFuzzyCompare(_rightA + 1, 1) ? 0.0 : 1.0 / _rightA;
-
- vertex v1 = { {1.f, top - 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v2 = { {0.f, top - 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v3 = { {0.f, bottom + 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
-
- vertex v4 = { {1.f, top - 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v5 = { {0.f, bottom + 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
- vertex v6 = { {1.f, bottom + 1.f, 0.5f}, 0.f,
- top, bottom, invLeftA, -invRightA,
- _leftA, _leftB, _rightA, _rightB};
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- for (int i=m_index; i<(m_index + 6); ++i) {
- if ((m_index + 6) > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[i] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[i] |= WRITE;
- }
-#endif
-
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v5;
- m_vbuff[m_index++] = v6;
-
- // check if buffer is full
- if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) {
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 3;
- m_startindex = m_index;
-
- QD3DBatchItem itemcopy = *m_item;
- m_item = m_pe->nextBatchItem();
- *m_item = itemcopy;
- m_item->m_info &= ~QD3DBatchItem::BI_MASKFULL;
-
- lockVertexBuffer();
- }
-}
-
-void QD3DDrawHelper::tessellate(const QPolygonF &poly) {
- int xoffset = m_item->m_maskpos.x;
- int yoffset = m_item->m_maskpos.y;
-
- int x = m_boundingRect.left();
- int y = m_boundingRect.top();
- m_xoffset = (x - xoffset) + 0.5f;
- m_yoffset = (y - yoffset) + 0.5f;
-
- QTessellator::tessellate(poly.data(), poly.count());
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) / 3;
- m_startindex = m_index;
-}
-
-inline void QD3DDrawHelper::lineToStencil(qreal x, qreal y)
-{
- QPointF lastPt = tess_lastpoint;
- tess_lastpoint = QPointF(x, y);
-
- if (m_isLine && m_firstPoint)
- return;
-
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- if (m_index > QT_VERTEX_BUF_SIZE)
- qDebug() << "Vertex Buffer: Buffer overflow";
- if (accesscontrol[m_index] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[m_index] |= WRITE;
-#endif
-
- vertex v;
- if (m_isLine) {
- vertex v1 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- -1.f, -1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- vertex v2 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- 1.f, -1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- vertex v3 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- 1.f, 1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- vertex v4 = { {lastPt.x(), lastPt.y(), m_pe->m_pen_width }, m_color,
- -1.f, 1.f, x, y,
- 0.f, 0.f, 0.f, 0.f};
- m_vbuff[m_index++] = v1;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v4;
- m_vbuff[m_index++] = v2;
- m_vbuff[m_index++] = v3;
- } else {
- vertex v1 = { {x, y, 0.5f}, m_color,
- 0.f, 0.f, 0.f, 0.f,
- 0.f, 0.f, 0.f, 0.f};
- m_vbuff[m_index++] = v1;
- v = v1;
- }
- ++tess_index;
-
- // check if buffer is full
- if (m_index >= (QT_VERTEX_BUF_SIZE - 16)) {
- int firstindex = m_startindex;
- if (!m_item->m_pointstops.isEmpty())
- firstindex = m_item->m_pointstops.last();
-
- vertex first = m_vbuff[firstindex];
-
- // finish current polygon
- m_item->m_pointstops.append(tess_index);
- m_item->m_offset = m_startindex;
- m_startindex = m_index;
-
- // copy item
- QD3DBatchItem itemcopy = *m_item;
- m_item = m_pe->nextBatchItem();
- *m_item = itemcopy;
-
- // start new polygon
- lockVertexBuffer();
- m_item->m_pointstops.clear();
- if (!m_isLine) {
- tess_index = 2;
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- if (accesscontrol[m_index] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[m_index] |= WRITE;
-#endif
-
- m_vbuff[m_index++] = first;
-
-#ifdef QT_DEBUG_VERTEXBUFFER_ACCESS
- if (accesscontrol[m_index] != CLEAR)
- qDebug() << "Vertex Buffer: Access Error";
- accesscontrol[m_index] |= WRITE;
-#endif
-
- m_vbuff[m_index++] = v;
- } else {
- tess_index = 0;
- }
- }
-
- if (x > max_x)
- max_x = x;
- else if (x < min_x)
- min_x = x;
- if (y > max_y)
- max_y = y;
- else if (y < min_y)
- min_y = y;
-}
-
-inline void QD3DDrawHelper::curveToStencil(const QPointF &cp1, const QPointF &cp2,
- const QPointF &ep)
-{
- qreal inverseScale = 0.5f;
- qreal inverseScaleHalf = inverseScale / 2;
-
- QBezier beziers[32];
- beziers[0] = QBezier::fromPoints(tess_lastpoint, cp1, cp2, ep);
- QBezier *b = beziers;
- while (b >= beziers) {
- // check if we can pop the top bezier curve from the stack
- qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
- qreal d;
- if (l > inverseScale) {
- d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2) - (b->y4 - b->y1)*(b->x1 - b->x2) )
- + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3) - (b->y4 - b->y1)*(b->x1 - b->x3) );
- d /= l;
- } else {
- d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
- qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
- }
- if (d < inverseScaleHalf || b == beziers + 31) {
- // good enough, we pop it off and add the endpoint
- lineToStencil(b->x4, b->y4);
- --b;
- } else {
- // split, second half of the polygon goes lower into the stack
- b->split(b+1, b);
- ++b;
- }
- }
-}
-
-QRectF QD3DDrawHelper::pathToVertexArrays(const QPainterPath &path)
-{
- m_isLine = (m_item->m_info & QD3DBatchItem::BI_FASTLINE);
- const QPainterPath::Element &first = path.elementAt(0);
- firstx = first.x;
- firsty = first.y;
- min_x = max_x = firstx;
- min_y = max_y = firsty;
-
- m_firstPoint = true;
- tess_index = 0;
- m_item->m_pointstops.clear();
- lineToStencil(firstx, firsty);
- m_firstPoint = false;
-
- for (int i=1; i<path.elementCount(); ++i) {
- const QPainterPath::Element &e = path.elementAt(i);
- switch (e.type) {
- case QPainterPath::MoveToElement:
- m_item->m_pointstops.append(tess_index);
- m_firstPoint = true;
- lineToStencil(e.x, e.y);
- m_firstPoint = false;
- break;
- case QPainterPath::LineToElement:
- lineToStencil(e.x, e.y);
- break;
- case QPainterPath::CurveToElement:
- curveToStencil(e, path.elementAt(i+1), path.elementAt(i+2));
- i+=2;
- break;
- default:
- break;
- }
- }
-
- if (!m_isLine)
- lineToStencil(firstx, firsty);
-
- m_item->m_pointstops.append(tess_index);
-
- m_item->m_offset = m_startindex;
- m_item->m_count = ( m_index - m_startindex ) - 2;
- m_startindex = m_index;
-
- QRectF result;
- result.setLeft(min_x);
- result.setRight(max_x);
- result.setTop(min_y);
- result.setBottom(max_y);
-
- if (m_isLine)
- result.adjust(0,0,1,1);
-
- return result;
-}
-
-void QD3DDrawHelper::resetMask()
-{
- m_mask_position.x = m_mask_position.y = QD3D_MASK_MARGIN;
- m_mask_position.channel = 0;
- m_mask_offsetX2 = m_mask_offsetY2 = QD3D_MASK_MARGIN;
-}
-
-
-static inline QPainterPath strokeForPath(const QPainterPath &path, const QPen &cpen) {
- QPainterPathStroker stroker;
- if (cpen.style() == Qt::CustomDashLine)
- stroker.setDashPattern(cpen.dashPattern());
- else
- stroker.setDashPattern(cpen.style());
-
- stroker.setCapStyle(cpen.capStyle());
- stroker.setJoinStyle(cpen.joinStyle());
- stroker.setMiterLimit(cpen.miterLimit());
- stroker.setWidth(cpen.widthF());
-
- QPainterPath stroke = stroker.createStroke(path);
- stroke.setFillRule(Qt::WindingFill);
- return stroke;
-}
-
-
-QDirect3DPaintEnginePrivate::~QDirect3DPaintEnginePrivate()
-{
-
-}
-
-void QDirect3DPaintEnginePrivate::updateClipPath(const QPainterPath &path, Qt::ClipOperation op)
-{
- //#### remove me
- QRegion r(path.toFillPolygon().toPolygon(), path.fillRule());
- updateClipRegion(r, op);
-
-/* if (m_draw_helper->needsFlushing())
- flushBatch();
-
- if (op == Qt::IntersectClip && !has_clipping)
- op = Qt::ReplaceClip;
-
- // switch to paths
- if (!m_has_complex_clipping) {
- m_clip_path = QPainterPath();
- m_clip_path.addRegion(m_clip_region);
- m_clip_region = QRegion();
- m_sysclip_path = QPainterPath();
- m_sysclip_path.addRegion(m_sysclip_region);
- m_sysclip_region = QRegion();
- m_has_complex_clipping = true;
- }
-
- QPainterPath cpath = m_matrix.map(path);
-
- QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++];
- item->m_info = QD3DBatchItem::BI_COMPLEXCLIP;
-
- switch (op) {
- case Qt::UniteClip:
- has_clipping = true;
- m_clip_path = m_clip_path.united(cpath);
- break;
- case Qt::ReplaceClip:
- has_clipping = true;
- m_clip_path = cpath;
- break;
- case Qt::NoClip:
- m_has_complex_clipping = false;
- has_clipping = false;
- item->m_info |= QD3DBatchItem::BI_CLEARCLIP;
- break;
- default: // intersect clip
- has_clipping = true;
- m_clip_path = m_clip_path.intersected(cpath);
- break;
- }
-
- if (!m_sysclip_path.isEmpty()) {
- item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP;
- if (has_clipping)
- m_clip_path = m_clip_path.intersected(m_sysclip_path);
- else
- m_clip_path = m_sysclip_path;
- }
-
- // update the aliased clipping mask
- m_draw_helper->setClipPath(m_clip_path, item);
-
- // update the antialiased clipping mask
- if (m_draw_helper->needsFlushing())
- flushBatch();
-
- QD3DBatchItem *aaitem = &m_batch.items[m_batch.m_item_index++];
- aaitem->m_info = item->m_info|QD3DBatchItem::BI_AA;
- m_draw_helper->setClipPath(m_clip_path, aaitem); */
-}
-
-extern QPainterPath qt_regionToPath(const QRegion &region);
-
-void QDirect3DPaintEnginePrivate::updateClipRegion(const QRegion &clipregion, Qt::ClipOperation op)
-{
- if (m_draw_helper->needsFlushing())
- flushBatch();
- if (m_has_complex_clipping) {
- QPainterPath path = qt_regionToPath(clipregion);
- updateClipPath(path, op);
- return;
- }
-
- if (op == Qt::IntersectClip && m_clip_region.isEmpty())
- op = Qt::ReplaceClip;
-
- QRegion cregion = m_matrix.map(clipregion);
-
- QD3DBatchItem *item = nextBatchItem();
- item->m_info &= ~QD3DBatchItem::BI_AA;
-
- switch (op) {
- case Qt::UniteClip:
- m_clip_region = m_clip_region.united(cregion);
- break;
- case Qt::ReplaceClip:
- m_clip_region = cregion;
- break;
- case Qt::NoClip:
- m_clip_region = QRegion();
- item->m_info |= QD3DBatchItem::BI_CLEARCLIP;
- break;
- default: // intersect clip
- m_clip_region = m_clip_region.intersected(cregion);
- break;
- }
-
- QRegion crgn = m_clip_region;
- if (!m_sysclip_region.isEmpty()) {
- item->m_info &= ~QD3DBatchItem::BI_CLEARCLIP;
- if (!crgn.isEmpty())
- crgn = crgn.intersected(m_sysclip_region);
- else
- crgn = m_sysclip_region;
- }
-
- QPainterPath path = qt_regionToPath(crgn);
- m_draw_helper->setClipPath(path, &item);
-}
-
-void QDirect3DPaintEnginePrivate::updateFont(const QFont &)
-{
-}
-
-void QDirect3DPaintEnginePrivate::setRenderTechnique(RenderTechnique technique)
-{
- if (m_current_technique != technique) {
- if (m_current_technique != RT_NoTechnique)
- m_effect->End();
-
- if (technique == RT_Aliased) {
- m_effect->SetTechnique("Aliased");
- m_effect->Begin(0,D3DXFX_DONOTSAVESTATE);
- } else if (technique == RT_Antialiased) {
- m_effect->SetTechnique("Antialiased");
- m_effect->Begin(0,D3DXFX_DONOTSAVESTATE);
- }
- }
-
- m_current_technique = technique;
-}
-
-/*QPolygonF QDirect3DPaintEnginePrivate::transformedRect(const QRectF &brect) const
-{
- QPolygonF poly(brect);
- return m_matrix.map(poly);
-}
-
-QPolygonF QDirect3DPaintEnginePrivate::calcTextureCoords(const QPolygonF &trect) const
-{
- QPolygonF result(4);
- QRectF brect = trect.boundingRect();
- qreal angle = atan(trect.at(0).x() -
-}
-
-QPolygonF QDirect3DPaintEnginePrivate::offsetTextureCoords(const QRectF &brect, const QPolygonF &trect) const
-{
-
-}*/
-
-inline QD3DBatchItem *QDirect3DPaintEnginePrivate::nextBatchItem()
-{
- if (m_draw_helper->needsFlushing())
- flushBatch();
-
- QD3DBatchItem *item = &m_batch.items[m_batch.m_item_index++];
- item->m_info = m_current_state;
- item->m_cmode = m_cmode;
- return item;
-}
-
-qreal calculateAngle(qreal dx, qreal dy)
-{
- qreal angle;
-
- if (qFuzzyCompare(dx + 1, 1)) {
- angle = (dy < 0) ? -M_PI/2 : M_PI/2;
- } else {
- angle = atanf(dy/dx);
- if (dx < 0)
- angle += M_PI;
- }
-
- return angle;
-}
-
-QPolygonF QDirect3DPaintEnginePrivate::brushCoordinates(const QRectF &r, bool stroke, qreal *fd) const
-{
- QBrush brush;
- QTransform matrix;
- Qt::BrushStyle style;
-
- if (stroke) {
- brush = m_pen.brush();
- matrix = m_inv_pen_matrix;
- style = m_pen_brush_style;
- } else {
- brush = m_brush;
- matrix = m_inv_brush_matrix;
- style = m_brush_style;
- }
-
- QPolygonF bpoly;
- switch(style) {
- case Qt::TexturePattern: {
- QTransform totxcoords;
- QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f);
- totxcoords.scale(1.0f/brush.texture().width(),
- 1.0f/brush.texture().height());
- bpoly = matrix.map(QPolygonF(adj_brect));
- bpoly = totxcoords.map(bpoly);
- break; }
- case Qt::LinearGradientPattern: {
- const QLinearGradient *g = static_cast<const QLinearGradient *>(brush.gradient());
- QPointF start = g->start();
- QPointF stop = g->finalStop();
- qreal dx = stop.x() - start.x();
- qreal dy = stop.y() - start.y();
- qreal length = sqrt(dx * dx + dy * dy);
- qreal angle = calculateAngle(dx, dy);
- QTransform totxcoords;
- QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f);
- totxcoords.scale(1.0f/length, 1.0f/length);
- totxcoords.rotateRadians(-angle);
- totxcoords.translate(-start.x(), -start.y());
- bpoly = matrix.map(QPolygonF(adj_brect));
- bpoly = totxcoords.map(bpoly);
- break; }
- case Qt::ConicalGradientPattern: {
- const QConicalGradient *g = static_cast<const QConicalGradient *>(brush.gradient());
- QPointF center = g->center();
- qreal angle = g->angle();
- QTransform totxcoords;
- totxcoords.rotate(angle);
- totxcoords.translate(-center.x(), -center.y());
- bpoly = matrix.map(QPolygonF(r));
- bpoly = totxcoords.map(bpoly);
- break; }
- case Qt::RadialGradientPattern: {
- const QRadialGradient *g = static_cast<const QRadialGradient *>(brush.gradient());
- QPointF center = g->center();
- QPointF focalpoint = g->focalPoint();
- qreal dx = focalpoint.x() - center.x();
- qreal dy = focalpoint.y() - center.y();
- qreal radius = g->radius();
- *fd = sqrt(dx * dx + dy * dy) / radius;
- qreal angle = calculateAngle(dx, dy);
- QTransform totxcoords;
- totxcoords.scale(1.0f/radius, 1.0f/radius);
- totxcoords.rotateRadians(-angle);
- totxcoords.translate(-center.x(), -center.y());
- bpoly = matrix.map(QPolygonF(r));
- bpoly = totxcoords.map(bpoly);
- break; }
- default: {
- QTransform totxcoords;
- QRectF adj_brect = r.adjusted(-0.5f, -0.5f, -0.5f, -0.5f);
- QPixmap pat = getPattern(style);
- totxcoords.scale(1.0f/pat.width(),
- 1.0f/pat.height());
- bpoly = matrix.map(QPolygonF(adj_brect));
- bpoly = totxcoords.map(bpoly); }
- };
-
- return bpoly;
-}
-
-void QDirect3DPaintEnginePrivate::strokeAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform)
-{
- D3DCOLOR solid_color;
- QD3DBatchItem *item = nextBatchItem();
-
- if (!txform.isIdentity())
- path = txform.map(path);
-
- QRectF trect;
- QPolygonF txcoord;
-
- solid_color = m_pen_color;
- bool has_complex_brush = false;
- if (m_pen_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_pen.brush();
- item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH;
- item->m_opacity = m_opacity;
- }
-
- if (m_has_fast_pen) {
- item->m_info |= QD3DBatchItem::BI_FASTLINE;
- if (m_pen_brush_style == Qt::SolidPattern) {
- m_draw_helper->queueAliasedMask(path, &item, solid_color);
- item->m_info &= ~QD3DBatchItem::BI_MASK; // bypass stencil buffer
- return;
- }
- }
-
- QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0);
-
- if (has_complex_brush) {
- trect = brect;
- txcoord = brushCoordinates(brect, true, &item->m_distance);
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = m_matrix;
- } else {
- trect = txrect;
- static const QPolygonF empty_poly(4);
- txcoord = empty_poly;
- }
-
- m_draw_helper->queueRect(trect, item, solid_color, txcoord);
-}
-
-void QDirect3DPaintEnginePrivate::fillAliasedPath(QPainterPath path, const QRectF &brect, const QTransform &txform)
-{
- D3DCOLOR solid_color;
- QD3DBatchItem *item = nextBatchItem();
-
- if (!txform.isIdentity())
- path = txform.map(path);
-
- QRectF trect;
- QPolygonF txcoord;
-
- solid_color = m_brush_color;
- bool has_complex_brush = false;
- if (m_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_brush;
- item->m_info |= QD3DBatchItem::BI_COMPLEXBRUSH;
- item->m_opacity = m_opacity;
- }
-
- QRectF txrect = m_draw_helper->queueAliasedMask(path, &item, 0);
-
- if (has_complex_brush) {
- trect = brect;
- txcoord = brushCoordinates(brect, false, &item->m_distance);
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = m_matrix;
- } else {
- trect = txrect;
- static const QPolygonF empty_poly(4);
- txcoord = empty_poly;
- }
-
- m_draw_helper->queueRect(trect, item, solid_color, txcoord);
-}
-
-void QDirect3DPaintEnginePrivate::fillAntialiasedPath(const QPainterPath &path, const QRectF &brect,
- const QTransform &txform, bool stroke)
-{
- D3DCOLOR solid_color;
- bool winding = (path.fillRule() == Qt::WindingFill);
- QPolygonF poly;
- QRectF txrect;
- QPainterPath tpath;
-
- if (m_has_aa_fast_pen && stroke) {
- tpath = txform.map(path);
- txrect = tpath.controlPointRect();
- txrect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width);
- } else {
- poly = path.toFillPolygon(txform);
- txrect = poly.boundingRect();
- }
-
- // brect = approx. bounding rect before transformation
- // txrect = exact bounding rect after transformation
- // trect = the rectangle to be drawn
- // txcoord = the texture coordinates
- // adj_txrect = adjusted rect to include aliased outline
-
- bool use_scissor = false;
- if (txrect.left() < 0) {
- txrect.adjust(-txrect.left(),0,0,0);
- use_scissor = true;
- }
- if (txrect.top() < 0) {
- txrect.adjust(0,-txrect.top(),0,0);
- use_scissor = true;
- }
-
- if (!txrect.isValid())
- return;
-
- QD3DBatchItem *item = nextBatchItem();
-
- QRectF adj_txrect = txrect.adjusted(-1,-1,1,1);
- QRectF trect;
- QPolygonF txcoord;
-
- bool has_complex_brush = false;
- if (stroke) {
- solid_color = m_pen_color;
- if (m_pen_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_pen.brush();
- }
- item->m_width = m_pen_width;
- } else {
- solid_color = m_brush_color;
- if (m_brush_style != Qt::SolidPattern) {
- has_complex_brush = true;
- item->m_brush = m_brush;
- }
- }
-
- qreal focaldist = 0;
- if (has_complex_brush) {
- trect = brect;
- txcoord = brushCoordinates(brect, stroke, &focaldist);
- } else {
- trect = adj_txrect;
- static const QPolygonF empty_poly(4);
- txcoord = empty_poly;
- }
-
- bool maskfull;
- item->m_maskpos = m_draw_helper->allocateMaskPosition(txrect, &maskfull);
- if (maskfull)
- item->m_info |= QD3DBatchItem::BI_MASKFULL;
- item->m_distance = focaldist;
-
- if (winding)
- item->m_info |= QD3DBatchItem::BI_WINDING;
-
- if (has_complex_brush) {
- item->m_info |= QD3DBatchItem::BI_SCISSOR|QD3DBatchItem::BI_COMPLEXBRUSH|
- QD3DBatchItem::BI_TRANSFORM;
- item->m_brect = adj_txrect;
- item->m_matrix = m_matrix;
- item->m_opacity = m_opacity;
- }
- if (use_scissor) {
- item->m_info |= QD3DBatchItem::BI_MASKSCISSOR;
- item->m_brect = adj_txrect;
- }
-
- if (m_has_aa_fast_pen && stroke) {
- m_draw_helper->queueAntialiasedLines(tpath, &item, txrect);
- } else {
- m_draw_helper->queueAntialiasedMask(poly, &item, txrect);
- }
-
- m_draw_helper->queueRect(trect, item, solid_color, txcoord);
-}
-
-QPainterPath QDirect3DPaintEnginePrivate::strokePathFastPen(const QPainterPath &path)
-{
- QPainterPath result;
- QBezier beziers[32];
- for (int i=0; i<path.elementCount(); ++i) {
- const QPainterPath::Element &e = path.elementAt(i);
- switch (e.type) {
- case QPainterPath::MoveToElement:
- result.moveTo(e.x, e.y);
- break;
- case QPainterPath::LineToElement:
- result.lineTo(e.x, e.y);
- break;
-
- case QPainterPath::CurveToElement:
- {
- QPointF sp = path.elementAt(i-1);
- QPointF cp2 = path.elementAt(i+1);
- QPointF ep = path.elementAt(i+2);
- i+=2;
-
- qreal inverseScaleHalf = m_inv_scale / 2;
- beziers[0] = QBezier::fromPoints(sp, e, cp2, ep);
- QBezier *b = beziers;
- while (b >= beziers) {
- // check if we can pop the top bezier curve from the stack
- qreal l = qAbs(b->x4 - b->x1) + qAbs(b->y4 - b->y1);
- qreal d;
- if (l > m_inv_scale) {
- d = qAbs( (b->x4 - b->x1)*(b->y1 - b->y2)
- - (b->y4 - b->y1)*(b->x1 - b->x2) )
- + qAbs( (b->x4 - b->x1)*(b->y1 - b->y3)
- - (b->y4 - b->y1)*(b->x1 - b->x3) );
- d /= l;
- } else {
- d = qAbs(b->x1 - b->x2) + qAbs(b->y1 - b->y2) +
- qAbs(b->x1 - b->x3) + qAbs(b->y1 - b->y3);
- }
- if (d < inverseScaleHalf || b == beziers + 31) {
- // good enough, we pop it off and add the endpoint
- result.lineTo(b->x4, b->y4);
- --b;
- } else {
- // split, second half of the polygon goes lower into the stack
- b->split(b+1, b);
- ++b;
- }
- }
- } // case CurveToElement
- default:
- break;
- } // end of switch
- }
- return result;
-}
-
-void QDirect3DPaintEnginePrivate::strokePath(const QPainterPath &path, QRectF brect, bool simple)
-{
- QTransform txform;
- QPainterPath tpath;
-
- if (m_has_fast_pen || m_has_aa_fast_pen) {
- if (!simple)
- tpath = strokePathFastPen(path);
- else
- tpath = path; //already only lines
- } else {
- tpath = strokeForPath(path, m_pen);
- }
-
- if (tpath.isEmpty())
- return;
-
- //brect is null if the path is not transformed
- if (brect.isNull())
- txform = m_matrix;
-
- if (!brect.isNull()) {
- // brect is set when the path is transformed already,
- // this is the case when we have a cosmetic pen.
- brect.adjust(-(m_pen_width/2),-(m_pen_width/2), m_pen_width, m_pen_width);
- }
-
- if (brect.isNull())
- brect = tpath.controlPointRect();
- brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing
-
- if (m_current_state & QD3DBatchItem::BI_AA) {
- fillAntialiasedPath(tpath, brect, txform, true);
- } else {
- strokeAliasedPath(tpath, brect, txform);
- }
-}
-
-void QDirect3DPaintEnginePrivate::fillPath(const QPainterPath &path, QRectF brect)
-{
- QTransform txform;
-
- //brect is null if the path is not transformed
- if (brect.isNull())
- txform = m_matrix;
-
- if (brect.isNull())
- brect = path.controlPointRect();
- brect.adjust(-m_inv_scale,-m_inv_scale,m_inv_scale,m_inv_scale); //adjust for antialiasing
-
- if (m_current_state & QD3DBatchItem::BI_AA) {
- fillAntialiasedPath(path, brect, txform, false);
- } else {
- fillAliasedPath(path, brect, txform);
- }
-}
-
-
-bool QDirect3DPaintEnginePrivate::init()
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEnginePrivate::init()";
-#endif
-
- m_draw_helper = 0;
- m_gradient_cache = 0;
- m_dc = 0;
- m_dcsurface = 0;
-
- m_supports_d3d = false;
- m_current_state = 0;
- m_in_scene = false;
- m_has_fast_pen = false;
- m_has_aa_fast_pen = false;
- m_has_pen = false;
- m_has_brush = false;
- m_pen_color = 0;
- m_brush_color = 0;
- m_current_surface = 0;
- m_batch.m_item_index = 0;
- m_current_technique = RT_NoTechnique;
-
- if (!pDirect3DCreate9) {
- QLibrary d3d_lib(QLatin1String("d3d9.dll"));
- pDirect3DCreate9 = (PFNDIRECT3DCREATE9) d3d_lib.resolve("Direct3DCreate9");
- if (!pDirect3DCreate9) {
- qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3d9.dll.\n"
- "Make sure you have the DirectX run-time installed.");
- return false;
- }
- }
-
- if (!pD3DXCreateBuffer || !pD3DXCreateEffect || !pD3DXMatrixOrthoOffCenterLH) {
- QLibrary d3dx_lib(QLatin1String("d3dx9_32.dll"));
- pD3DXCreateBuffer = (PFND3DXCREATEBUFFER) d3dx_lib.resolve("D3DXCreateBuffer");
- pD3DXCreateEffect = (PFND3DXCREATEEFFECT) d3dx_lib.resolve("D3DXCreateEffect");
- pD3DXMatrixOrthoOffCenterLH = (PFND3DXMATRIXORTHOOFFCENTERLH)
- d3dx_lib.resolve("D3DXMatrixOrthoOffCenterLH");
- if (!(pD3DXCreateBuffer && pD3DXCreateEffect && pD3DXMatrixOrthoOffCenterLH)) {
- qWarning("QDirect3DPaintEngine: failed to resolve symbols from d3dx9_32.dll.\n"
- "Make sure you have the DirectX run-time installed.");
- return false;
- }
- }
-
- if (!m_d3d_object) {
- m_d3d_object = pDirect3DCreate9(D3D_SDK_VERSION);
- if (!m_d3d_object) {
- qWarning("QDirect3DPaintEngine: failed to create Direct3D object.\n"
- "Direct3D support in Qt will be disabled.");
- return false;
- }
- }
-
- m_supports_d3d = testCaps();
- if (!m_supports_d3d)
- return false;
-
- m_surface_manager.init(m_d3d_object);
- m_d3d_device = m_surface_manager.device();
-
- if (!m_d3d_device)
- return false;
-
- /* load shaders */
- QFile file(QLatin1String(":/qpaintengine_d3d.fx"));
- QByteArray fxFile;
- if (file.open(QFile::ReadOnly))
- fxFile = file.readAll();
-
- if (fxFile.size() > 0) {
- LPD3DXBUFFER compout;
- pD3DXCreateBuffer(4096, &compout);
- DWORD dwShaderFlags = D3DXFX_NOT_CLONEABLE|D3DXFX_DONOTSAVESTATE|D3DXSHADER_OPTIMIZATION_LEVEL3;
- if(FAILED(pD3DXCreateEffect(m_d3d_device, fxFile.constData(), fxFile.size(),
- NULL, NULL, dwShaderFlags, NULL, &m_effect, &compout))) {
- qWarning("QDirect3DPaintEngine: failed to compile effect file");
- if (compout)
- qWarning((char *)compout->GetBufferPointer());
- m_supports_d3d = false;
- return false;
- }
- if (m_effect) {
- m_statemanager = new QD3DStateManager(m_d3d_device, m_effect);
- m_effect->SetStateManager(m_statemanager);
- m_draw_helper = new QD3DDrawHelper(this);
- initDevice();
- m_gradient_cache = new QD3DGradientCache(m_d3d_device);
- }
- } else {
- return false;
- }
-
- return true;
-}
-
-QPixmap QDirect3DPaintEnginePrivate::getPattern(Qt::BrushStyle style) const
-{
- if (!m_patterns.contains(style)) {
- QImage img(16,16,QImage::Format_ARGB32);
- img.fill(0);
- QPainter p(&img);
- p.setBrush(QBrush(Qt::white, style));
- p.setPen(Qt::NoPen);
- p.drawRect(0,0,16,16);
- p.end();
- QPixmap pattern(QPixmap::fromImage(img));
- QDirect3DPaintEnginePrivate *ct = const_cast<QDirect3DPaintEnginePrivate *>(this);
- ct->verifyTexture(pattern);
- ct->m_patterns.insert(style, pattern);
- }
-
- return m_patterns.value(style);
-}
-
-bool QDirect3DPaintEnginePrivate::testCaps()
-{
- D3DCAPS9 caps;
- if (FAILED(m_d3d_object->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &caps)))
- return false;
-
- if ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
- && (caps.DevCaps & D3DDEVCAPS_PUREDEVICE)
- && (caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST)
- && (caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED))
- return true;
-#if 0
- qDebug() << "Direct3D caps:";
- qDebug() << "D3DPRESENT_INTERVAL_IMMEDIATE:" << ((caps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) != 0);
- qDebug() << "D3DDEVCAPS_PUREDEVICE:" << ((caps.DevCaps & D3DDEVCAPS_PUREDEVICE) != 0);
- qDebug() << "D3DPRASTERCAPS_SCISSORTEST:" << ((caps.RasterCaps & D3DPRASTERCAPS_SCISSORTEST) != 0);
- qDebug() << "D3DSTENCILCAPS_TWOSIDED:" << ((caps.StencilCaps & D3DSTENCILCAPS_TWOSIDED) != 0);
-#endif
- return false;
-}
-
-void QDirect3DPaintEnginePrivate::initDevice()
-{
- m_statemanager->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
- m_statemanager->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
- m_statemanager->SetRenderState(D3DRS_ZWRITEENABLE, FALSE);
- m_statemanager->SetRenderState(D3DRS_LIGHTING, FALSE);
- m_statemanager->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
- m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_DESTALPHA);
-}
-
-void QDirect3DPaintEnginePrivate::updatePen(const QPen &pen)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updatePen";
-#endif
- m_pen = pen;
- m_has_cosmetic_pen = false;
- m_has_pen = (m_pen.style() != Qt::NoPen);
- if (m_has_pen) {
- m_pen_brush_style = m_pen.brush().style();
-
- if (m_pen_brush_style >= Qt::SolidPattern && m_pen_brush_style <= Qt::DiagCrossPattern) {
- int a, r, g, b;
- m_pen.color().getRgb(&r, &g, &b, &a);
- m_pen_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b);
- } else {
- m_pen_color = m_opacity_color;
- }
-
- m_has_cosmetic_pen = m_pen.isCosmetic();
-
- if (m_pen_brush_style != Qt::NoBrush &&
- m_pen_brush_style != Qt::SolidPattern) {
- bool ok;
- m_inv_pen_matrix = m_pen.brush().transform().inverted(&ok);
- if (!ok)
- qWarning() << "QDirect3DPaintEngine: No inverse matix for pen brush matrix.";
- }
-
- m_pen_width = m_pen.widthF();
- if (m_pen_width == 0.0f)
- m_pen_width = 1.0f;
- }
-}
-
-void QDirect3DPaintEnginePrivate::updateBrush(const QBrush &brush)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updateBrush";
-#endif
- m_brush = brush;
- m_brush_style = m_brush.style();
- m_has_brush = (m_brush_style != Qt::NoBrush);
- if (m_has_brush) {
- if (m_brush_style >= Qt::SolidPattern && m_brush_style <= Qt::DiagCrossPattern) {
- int a, r, g, b;
- m_brush.color().getRgb(&r, &g, &b, &a);
- m_brush_color = D3DCOLOR_ARGB((int)(a * m_opacity),r,g,b);
- } else {
- m_brush_color = m_opacity_color;
- }
-
- if (m_brush_style != Qt::SolidPattern) {
- bool ok;
- m_inv_brush_matrix = (m_brush.transform() * m_brush_origin).inverted(&ok);
- if (!ok)
- qWarning() << "QDirect3DPaintEngine: No inverse matix for brush matrix.";
-
- // make sure the texture is loaded as a texture
- if (m_brush_style == Qt::TexturePattern)
- verifyTexture(m_brush.texture());
-
-
- }
- }
-}
-
-void QDirect3DPaintEnginePrivate::updateTransform(const QTransform &matrix)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updateTransform";
-#endif
- m_matrix = matrix;
- m_inv_scale = qMax(1 / qMax( qMax(qAbs(m_matrix.m11()), qAbs(m_matrix.m22())),
- qMax(qAbs(m_matrix.m12()), qAbs(m_matrix.m21())) ), 0.0001);
- m_txop = matrix.type();
-}
-
-int QDirect3DPaintEnginePrivate::flushAntialiased(int offset)
-{
- // fills the mask (returns number of items added to the mask)
- int newoffset = m_draw_helper->drawAntialiasedMask(offset, m_batch.m_item_index);
-
- // set the render target to the current output surface
- if (FAILED(m_d3d_device->SetRenderTarget(0, m_current_surface)))
- qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!";
-
- // draw the bounding boxes (using the mask generated by drawAntialiasedMask)
- for (int i=offset; i<newoffset; ++i) {
- QD3DBatchItem *item = &(m_batch.items[i]);
- int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_AA_DRAW : PASS_AA_DRAW_DIRECT;
- m_statemanager->beginPass(pass);
- prepareItem(item);
- if (item->m_info & QD3DBatchItem::BI_BRECT)
- m_draw_helper->drawAntialiasedBoundingRect(item);
- cleanupItem(item);
- }
-
- m_statemanager->endPass();
-
- return newoffset;
-}
-
-bool QDirect3DPaintEnginePrivate::prepareBatch(QD3DBatchItem *item, int offset)
-{
- if (item->m_info & QD3DBatchItem::BI_CLIP) {
- setRenderTechnique(RT_Aliased);
- if (item->m_info & QD3DBatchItem::BI_CLEARCLIP) {
- m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 0.0f, 0);
- return true;
- }
-
- m_draw_helper->drawAliasedMask(offset);
- m_d3d_device->Clear(0, 0, D3DCLEAR_ZBUFFER, 0, 1.0f, 0);
- if (item->m_info & QD3DBatchItem::BI_BRECT) {
- m_statemanager->beginPass(PASS_STENCIL_CLIP);
- m_draw_helper->drawAliasedBoundingRect(item);
- m_statemanager->endPass();
- }
-
- return true;
- }
-
- if (item->m_info & QD3DBatchItem::BI_AA) {
- setRenderTechnique(RT_Antialiased);
- } else {
- setRenderTechnique(RT_Aliased);
- }
-
- return false;
-}
-
-void QDirect3DPaintEnginePrivate::prepareItem(QD3DBatchItem *item) {
- // pixmap
- int brushmode = 0;
- m_statemanager->startStateBlock();
- if ((item->m_info & QD3DBatchItem::BI_PIXMAP) || (item->m_info & QD3DBatchItem::BI_IMAGE)) {
- QRasterPixmapData *data = static_cast<QRasterPixmapData*>(item->m_pixmap.data);
- IDirect3DTexture9 *tex = (item->m_info & QD3DBatchItem::BI_PIXMAP) ?
- data->texture : item->m_texture;
- m_statemanager->setTexture(tex);
- brushmode = 5;
- }
-
- if (item->m_info & QD3DBatchItem::BI_AA) {
- m_statemanager->setMaskChannel(item->m_maskpos.channel);
- m_statemanager->setMaskOffset(item->m_xoffset, item->m_yoffset);
- }
-
- if (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) {
- const QBrush brush = item->m_brush;
- switch (brush.style()) {
- case Qt::TexturePattern: {
- QRasterPixmapData *data = static_cast<QRasterPixmapData*>(brush.texture().data);
- m_statemanager->setTexture(data->texture, QGradient::RepeatSpread);
- brushmode = 1;
- break;
- }
- case Qt::LinearGradientPattern:
- m_statemanager->setTexture(m_gradient_cache->
- getBuffer(brush.gradient()->stops(), item->m_opacity),
- brush.gradient()->spread());
- brushmode = 2;
- break;
- case Qt::ConicalGradientPattern:
- m_statemanager->setTexture(m_gradient_cache->
- getBuffer(brush.gradient()->stops(), item->m_opacity),
- brush.gradient()->spread());
- brushmode = 3;
- break;
- case Qt::RadialGradientPattern:
- m_statemanager->setTexture(m_gradient_cache->
- getBuffer(brush.gradient()->stops(), item->m_opacity),
- brush.gradient()->spread());
- m_statemanager->setFocalDistance(item->m_distance);
- brushmode = 4;
- break;
- default: {
- QRasterPixmapData *data = static_cast<QRasterPixmapData*>(getPattern(brush.style()).data);
- m_statemanager->setTexture(data->texture, QGradient::RepeatSpread);
- brushmode = 5;
- }
- };
- }
-
- if (item->m_info & QD3DBatchItem::BI_TRANSFORM) {
- m_statemanager->setTransformation(&item->m_matrix);
- } else {
- m_statemanager->setTransformation();
- }
-
- m_statemanager->setBrushMode(brushmode);
- setCompositionMode(item->m_cmode);
- m_statemanager->endStateBlock();
-}
-
-
-void QDirect3DPaintEnginePrivate::releaseDC()
-{
- if (m_dc) {
- m_dcsurface->ReleaseDC(m_dc);
- m_dcsurface = 0;
- m_dc = 0;
- }
-}
-
-
-void QDirect3DPaintEnginePrivate::cleanupItem(QD3DBatchItem *item)
-{
- if (item->m_info & QD3DBatchItem::BI_PIXMAP)
- item->m_pixmap = QPixmap();
- item->m_brush = QBrush();
-}
-
-void QDirect3DPaintEnginePrivate::verifyTexture(const QPixmap &pm)
-{
- QRasterPixmapData *pmData = static_cast<QRasterPixmapData*>(pm.data);
- if (!pmData->texture) {
- QImage im = pmData->image;
- // bitmaps are drawn with the current pen color
- if (im.depth() == 1) {
- QVector<QRgb> colors(2);
- colors[0] = 0;
- colors[1] = m_pen.color().rgba();
- im.setColorTable(colors);
- }
- im = im.convertToFormat(QImage::Format_ARGB32);
- if (FAILED(m_d3d_device->CreateTexture(im.width(), im.height(), 1, 0,
- D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &pmData->texture, 0)))
- {
- qWarning("QDirect3DPaintEngine: unable to create Direct3D texture from pixmap.");
- return;
- }
- D3DLOCKED_RECT rect;
- if (FAILED(pmData->texture->LockRect(0, &rect, 0, 0))) {
- qDebug() << "QDirect3DPaintEngine: unable to lock texture rect.";
- return;
- }
- DWORD *dst = (DWORD *) rect.pBits;
- DWORD *src = (DWORD *) im.scanLine(0);
-
- Q_ASSERT((rect.Pitch/4) == (im.bytesPerLine()/4));
- memcpy(dst, src, rect.Pitch*im.height());
- pmData->texture->UnlockRect(0);
- }
-}
-
-bool QDirect3DPaintEnginePrivate::isFastRect(const QRectF &rect)
-{
- if (m_matrix.type() < QTransform::TxRotate) {
- QRectF r = m_matrix.mapRect(rect);
- return r.topLeft().toPoint() == r.topLeft()
- && r.bottomRight().toPoint() == r.bottomRight();
- }
-
- return false;
-}
-
-void QDirect3DPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode)
-{
- switch(mode) {
- case QPainter::CompositionMode_SourceOver:
- default:
- m_statemanager->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
- m_statemanager->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
- };
-}
-
-void QDirect3DPaintEnginePrivate::cleanup()
-{
- // clean batch
- for(int i=0; i<QD3D_BATCH_SIZE; ++i) {
- m_batch.items[i].m_brush = QBrush();
- m_batch.items[i].m_pixmap = QPixmap();
- }
-
- m_surface_manager.cleanup();
- m_patterns.clear();
-
- delete m_gradient_cache;
- delete m_draw_helper;
-
- if (m_effect)
- m_effect->Release();
-
- if (m_d3d_object)
- m_d3d_object->Release();
-
- m_effect = 0;
- m_d3d_object = 0;
- m_gradient_cache = 0;
- m_draw_helper = 0;
-}
-
-void QDirect3DPaintEnginePrivate::flushAliased(QD3DBatchItem *item, int offset)
-{
- m_draw_helper->drawAliasedMask(offset);
-
- if (item->m_info & QD3DBatchItem::BI_BRECT) {
- int pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW_DIRECT : PASS_STENCIL_NOSTENCILCHECK_DIRECT;
- if (item->m_info & (QD3DBatchItem::BI_COMPLEXBRUSH|QD3DBatchItem::BI_IMAGE|QD3DBatchItem::BI_PIXMAP) )
- pass = (item->m_info & QD3DBatchItem::BI_MASK) ? PASS_STENCIL_DRAW : PASS_STENCIL_NOSTENCILCHECK;
- m_statemanager->beginPass(pass);
- prepareItem(item);
- m_draw_helper->drawAliasedBoundingRect(item);
- cleanupItem(item);
- m_statemanager->endPass();
- }
-}
-
-void QDirect3DPaintEnginePrivate::flushText(QD3DBatchItem *item, int)
-{
- prepareItem(item);
- m_statemanager->setTexture(item->m_texture);
- m_statemanager->setBrushMode(1);
-// m_statemanager->SetRenderState(D3DRS_BLENDFACTOR, item->m_brush.color().rgba());
- m_statemanager->beginPass(m_cleartype_text ? PASS_CLEARTYPE_TEXT : PASS_TEXT);
- m_draw_helper->drawTextItem(item);
- m_statemanager->endPass();
- cleanupItem(item);
-}
-
-void QDirect3DPaintEnginePrivate::flushLines(QD3DBatchItem *item, int)
-{
- m_draw_helper->drawAliasedLines(item);
-
- if (item->m_info & QD3DBatchItem::BI_BRECT) {
- int pass = (item->m_info & QD3DBatchItem::BI_COMPLEXBRUSH) ? PASS_STENCIL_DRAW : PASS_STENCIL_DRAW_DIRECT;
- m_statemanager->beginPass(pass);
- prepareItem(item);
- m_draw_helper->drawAliasedBoundingRect(item);
- cleanupItem(item);
- m_statemanager->endPass();
- }
-}
-
-void QDirect3DPaintEnginePrivate::flushBatch()
-{
-// static int dbgcounter = 0;
-// ++dbgcounter;
-// qDebug() << " -> flush" << dbgcounter;
-
- int offset = 0;
- m_draw_helper->unlockVertexBuffer();
- releaseDC();
-
- // iterate over all items in the batch
- while (offset != m_batch.m_item_index) {
- QD3DBatchItem *item = &(m_batch.items[offset]);
-
- if (prepareBatch(item, offset)) {
- ++offset;
- continue;
- }
-
- if (item->m_info & QD3DBatchItem::BI_FASTLINE) {
- flushLines(item, offset++);
- } else if (item->m_info & QD3DBatchItem::BI_AA) {
- offset = flushAntialiased(offset);
- } else if (item->m_info & QD3DBatchItem::BI_TEXT) {
- flushText(item, offset++);
- } else {
- flushAliased(item, offset++);
- }
- }
-
- // reset batch
- m_batch.m_item_index = 0;
-
- // release doomed textures
- for (int i=0; i<qd3d_release_list.size(); ++i)
- qd3d_release_list.at(i)->Release();
- qd3d_release_list.clear();
-}
-
-QDirect3DPaintEngine::QDirect3DPaintEngine()
- : QPaintEngine(*(new QDirect3DPaintEnginePrivate),
- PaintEngineFeatures(AllFeatures & ~ObjectBoundingModeGradients))
-{ }
-
-QDirect3DPaintEngine::~QDirect3DPaintEngine()
-{
-}
-
-bool QDirect3DPaintEngine::begin(QPaintDevice *device)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::begin";
-#endif
- Q_D(QDirect3DPaintEngine);
- setActive(true);
-
- QSize old_size = d->m_surface_size;
- d->m_surface_size = QRect(0, 0, device->width(), device->height()).size();
-
- d->m_current_state = 0;
- d->m_inv_scale = 1;
- d->m_opacity = 1.0f;
- d->m_opacity_color = D3DCOLOR_ARGB(255,255,255,255);
- d->m_matrix = QTransform();
- d->m_brush_origin = QTransform();
- d->m_txop = QTransform::TxNone;
- d->m_cmode = QPainter::CompositionMode_SourceOver;
-
- Q_ASSERT(device && device->devType() == QInternal::Widget);
- if (d->m_d3d_device == 0) {
- qWarning() << "QDirect3DPaintEngine: No Device!";
- return false;
- }
-
- d->m_cleartype_text = false;
-// QT_WA({
-// UINT result;
-// BOOL ok;
-// ok = SystemParametersInfoW(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
-// if (ok)
-// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE);
-// }, {
-// UINT result;
-// BOOL ok;
-// ok = SystemParametersInfoA(SPI_GETFONTSMOOTHINGTYPE, 0, &result, 0);
-// if (ok)
-// d->m_cleartype_text = (result == FE_FONTSMOOTHINGCLEARTYPE);
-// });
-
- d->m_surface_manager.setPaintDevice(device);
- int status = d->m_surface_manager.status();
- if (status & QD3DSurfaceManager::NeedsResetting) {
- d->m_effect->OnLostDevice();
- d->m_draw_helper->beforeReset();
- d->m_statemanager->reset();
- d->m_surface_manager.reset();
- d->m_draw_helper->afterReset();
- d->m_effect->OnResetDevice();
- d->initDevice();
- }
-
- LPDIRECT3DSURFACE9 newsurface = d->m_surface_manager.renderTarget();
- if (d->m_current_surface != newsurface) {
- d->m_current_surface = newsurface;
- if (FAILED(d->m_d3d_device->SetRenderTarget(0, newsurface)))
- qWarning() << "QDirect3DPaintEngine: SetRenderTarget failed!";
- }
-
- status = d->m_surface_manager.status();
- if (status & QD3DSurfaceManager::MaxSizeChanged) {
- QSize maxsize = d->m_surface_manager.maxSize();
- d->m_draw_helper->setMaskSize(maxsize);
- int masksize[2] = {maxsize.width(), maxsize.height()};
- d->m_effect->SetIntArray("g_mMaskSize", masksize, 2);
- }
-
- if (old_size != d->m_surface_size) {
- D3DXMATRIX projMatrix;
- pD3DXMatrixOrthoOffCenterLH(&projMatrix, 0, d->m_surface_size.width(), d->m_surface_size.height(), 0, 0.0f, 1.0f);
- d->m_statemanager->setProjection(&projMatrix);
- }
-
- if (!d->m_in_scene) {
- if (FAILED(d->m_d3d_device->BeginScene())) {
- qWarning() << "QDirect3DPaintEngine: BeginScene() failed.";
- return false;
- }
- QWidget *widget = static_cast<QWidget *>(device);
- if (widget->autoFillBackground() == true) {
- QColor color = widget->palette().brush(widget->backgroundRole()).color();
- RECT rect = {0, 0, widget->width(), widget->height()};
- d->m_d3d_device->ColorFill(d->m_current_surface, &rect,
- D3DCOLOR_ARGB(color.alpha(), color.red(), color.green(), color.blue()));
- }
- d->m_in_scene = true;
- }
-
- // set system clip
- d->m_clipping_enabled = false;
- d->m_has_complex_clipping = false;
-
- d->m_sysclip_region = systemClip();
- QVector<QRect> rects = d->m_sysclip_region.rects();
- if (rects.count() == 1 && rects.at(0).size() == d->m_surface_size)
- d->m_sysclip_region = QRegion();
-
- d->updateClipRegion(QRegion(), Qt::NoClip);
-
- return true;
-}
-
-void QDirect3DPaintEngine::drawEllipse(const QRectF &rect)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawEllipse (float)";
-#endif
- QPaintEngine::drawEllipse(rect);
-}
-
-void QDirect3DPaintEngine::drawEllipse(const QRect &rect)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawEllipse";
-#endif
- QPaintEngine::drawEllipse(rect);
-}
-
-void QDirect3DPaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr,
- Qt::ImageConversionFlags)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawImage";
-#endif
-
- Q_D(QDirect3DPaintEngine);
- int width = image.width();
- int height = image.height();
-
- // transform rectangle
- QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height,
- sr.width() / width, sr.height() / height));
-
- QD3DBatchItem *item = d->nextBatchItem();
- item->m_info = QD3DBatchItem::BI_IMAGE | QD3DBatchItem::BI_TRANSFORM;
- item->m_texture = qd3d_image_cache()->lookup(d->m_d3d_device, image);
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect);
-}
-
-void QDirect3DPaintEngine::drawLines(const QLineF *lines, int lineCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawLines (float)";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (!d->m_has_pen)
- return;
-
- if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) {
- QD3DBatchItem *item = d->nextBatchItem();
- if (d->m_pen.isCosmetic())
- item->m_info |= QD3DBatchItem::BI_COSMETICPEN;
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueAliasedLines(lines, lineCount, &item);
- } else {
- QRectF brect;
- QPainterPath path;
-
- // creates a path with the lines
- path.moveTo(lines[0].x1(), lines[0].y1());
- qreal lastx = lines[0].x2();
- qreal lasty = lines[0].y2();
- path.lineTo(lastx, lasty);
-
- for (int i=1; i<lineCount; ++i) {
- qreal x = lines[i].x1();
- qreal y = lines[i].y1();
- if (lastx != x || lasty != y) {
- path.moveTo(x, y);
- }
- path.lineTo(lines[i].x2(), lines[i].y2());
- }
-
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- d->strokePath(path, brect, true);
- }
-}
-
-void QDirect3DPaintEngine::drawLines(const QLine *lines, int lineCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawLines";
-#endif
- QPaintEngine::drawLines(lines, lineCount);
-}
-
-void QDirect3DPaintEngine::drawPath(const QPainterPath &path)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPath";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (path.isEmpty())
- return;
-
- QRectF brect;
- QPainterPath tpath;
-
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- tpath = d->m_matrix.map(path);
- } else {
- tpath = path;
- }
-
- if (d->m_has_brush)
- d->fillPath(tpath, brect);
-
- if (d->m_has_pen)
- d->strokePath(tpath, brect);
-}
-
-
-QPointF QDirect3DPaintEnginePrivate::transformPoint(const QPointF &p, qreal *w) const
-{
- (*w) = 1.0f;
- qreal fx = p.x();
- qreal fy = p.y();
- qreal nx = m_matrix.m11()*fx + m_matrix.m21()*fy + m_matrix.m31();
- qreal ny = m_matrix.m12()*fx + m_matrix.m22()*fy + m_matrix.m32();
- if (!m_matrix.isAffine()) {
- *w = m_matrix.m13()*fx + m_matrix.m23()*fy + m_matrix.m33();
- //*w = 1/(*w);
- nx = nx/(*w);
- ny = ny/(*w);
- }
- return QPointF(nx, ny);
-}
-
-void QDirect3DPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPixmap";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (d->m_draw_helper->needsFlushing())
- d->flushBatch();
-
- int width = pm.width();
- int height = pm.height();
-
- // transform rectangle
- QPolygonF txrect(QRectF(sr.left() / width, sr.top() / height,
- sr.width() / width, sr.height() / height));
-
- QD3DBatchItem *item = d->nextBatchItem();
- item->m_info = QD3DBatchItem::BI_PIXMAP|QD3DBatchItem::BI_TRANSFORM;
-
- item->m_pixmap = pm;
- d->verifyTexture(item->m_pixmap);
-
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueRect(r.adjusted(-0.5f,-0.5f,-0.5f,-0.5f), item, d->m_opacity_color, txrect);
-}
-
-void QDirect3DPaintEngine::drawPoints(const QPointF *points, int pointCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPoints (float)";
-#endif
- QPaintEngine::drawPoints(points, pointCount);
-}
-
-void QDirect3DPaintEngine::drawPoints(const QPoint *points, int pointCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPoints";
-#endif
- QPaintEngine::drawPoints(points, pointCount);
-}
-
-void QDirect3DPaintEngine::drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPolygon";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- if (d->m_has_brush && mode != PolylineMode) {
- QPainterPath path;
- path.setFillRule(mode == WindingMode ? Qt::WindingFill : Qt::OddEvenFill);
- path.moveTo(points[0]);
- for (int i=1; i<pointCount; ++i)
- path.lineTo(points[i]);
- if (path.isEmpty())
- return;
- d->fillPath(path, QRectF());
- }
-
- if (d->m_has_pen) {
- QPainterPath path(points[0]);
- for (int i = 1; i < pointCount; ++i)
- path.lineTo(points[i]);
- if (mode != PolylineMode)
- path.lineTo(points[0]);
-
- if (path.isEmpty())
- return;
- QRectF brect;
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- d->strokePath(path, brect);
- }
-}
-
-void QDirect3DPaintEngine::drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawPolygon";
-#endif
- QPaintEngine::drawPolygon(points, pointCount, mode);
-}
-
-void QDirect3DPaintEngine::drawRects(const QRectF *rects, int rectCount)
-{
- Q_D(QDirect3DPaintEngine);
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawRects (float)";
-#endif
- for (int i=0; i<rectCount; ++i) {
- if ((d->m_brush_style == Qt::SolidPattern) &&
- (!(d->m_current_state & QD3DBatchItem::BI_AA) || d->isFastRect(rects[i]))) {
- QD3DBatchItem *item = d->nextBatchItem();
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_info &= ~QD3DBatchItem::BI_AA;
- item->m_matrix = d->m_matrix;
- const QRectF rect = rects[i];
- d->m_draw_helper->queueRect(rect, item, d->m_brush_color);
-
- if (d->m_has_pen) {
- if (d->m_has_fast_pen && (d->m_pen_brush_style == Qt::SolidPattern)) {
- QLineF lines[4];
- qreal x1 = rect.x();
- qreal y1 = rect.y();
- qreal x2 = rect.width() + x1;
- qreal y2 = rect.height() + y1;
- lines[0] = QLineF(x1, y1, x2, y1);
- lines[1] = QLineF(x2, y1, x2, y2);
- lines[2] = QLineF(x2, y2, x1, y2);
- lines[3] = QLineF(x1, y2, x1, y1);
- QD3DBatchItem *item = d->nextBatchItem();
- if (d->m_pen.isCosmetic())
- item->m_info |= QD3DBatchItem::BI_COSMETICPEN;
- item->m_info |= QD3DBatchItem::BI_TRANSFORM;
- item->m_matrix = d->m_matrix;
- d->m_draw_helper->queueAliasedLines(lines, 4, &item);
- } else {
- QPainterPath path;
- QRectF brect;
-
- path.addRect(rects[i]);
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- d->strokePath(path, brect, true);
- }
- }
- } else {
- QPainterPath path;
- QRectF brect;
-
- path.addRect(rects[i]);
- if (d->m_has_cosmetic_pen) {
- brect = path.controlPointRect();
- path = d->m_matrix.map(path);
- }
-
- if (d->m_has_brush)
- d->fillPath(path, brect);
-
- if (d->m_has_pen)
- d->strokePath(path, brect, true);
- }
- }
-}
-
-void QDirect3DPaintEngine::drawRects(const QRect *rects, int rectCount)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawRects";
-#endif
- QPaintEngine::drawRects(rects, rectCount);
-}
-
-
-void QDirect3DPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
-{
- Q_D(QDirect3DPaintEngine);
-
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawTextItem";
-#endif
-// if (d->m_matrix.isScaling() || (d->m_pen_brush_style >= Qt::LinearGradientPattern
-// && d->m_pen_brush_style <= Qt::ConicalGradientPattern)) {
-// QPaintEngine::drawTextItem(p, textItem);
-// return;
-// }
-
- const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
- QVarLengthArray<QFixedPoint> positions;
- QVarLengthArray<glyph_t> glyphs;
- QTransform matrix;
- matrix.translate(p.x(), p.y());
- ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-
- qd3d_glyph_cache()->cacheGlyphs(this, ti, glyphs, d->m_cleartype_text);
- QD3DFontTexture *font_tex = qd3d_glyph_cache()->fontTexture(ti.fontEngine);
-
- QD3DBatchItem *item = d->nextBatchItem();
- d->m_draw_helper->lockVertexBuffer();
-
- item->m_info = QD3DBatchItem::BI_TEXT
- | (d->m_current_state & ~QD3DBatchItem::BI_AA) | QD3DBatchItem::BI_TRANSFORM;
- item->m_texture = font_tex->texture;
- item->m_offset = d->m_draw_helper->index();
- item->m_matrix = d->m_matrix;
- item->m_count = 0;
- item->m_brush = d->m_pen.brush();
-
- for (int i=0; i< glyphs.size(); ++i) {
- QD3DGlyphCoord *g = qd3d_glyph_cache()->lookup(ti.fontEngine, glyphs[i]);
-
- // we don't cache glyphs with no width/height
- if (!g)
- continue;
-
- // texture coords
- qreal tex_coords[] = { g->x, g->y, g->x + g->width, g->y + g->height };
- QPointF logical_pos(qRound((positions[i].x - g->x_offset).toReal()) - 0.5f,
- qRound((positions[i].y + g->y_offset).toReal()) - 0.5f);
-
- QRectF glyph_rect(logical_pos, QSizeF(g->log_width, g->log_height));
- d->m_draw_helper->queueTextGlyph(glyph_rect, tex_coords, item, d->m_pen_color);
- }
-}
-
-void QDirect3DPaintEngine::drawTiledPixmap(const QRectF &rect, const QPixmap &pixmap, const QPointF &p)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::drawTiledPixmap";
-#endif
- QPaintEngine::drawTiledPixmap(rect, pixmap, p);
-}
-
-bool QDirect3DPaintEngine::end()
-{
- Q_D(QDirect3DPaintEngine);
-
- d->flushBatch();
-
- if (d->m_flush_on_end) {
- QPaintDevice *pdev = paintDevice();
- LPDIRECT3DSWAPCHAIN9 swapchain = swapChain(pdev);
-
-
- QWidget *w = 0;
- if (pdev->devType() == QInternal::Widget) {
- w = static_cast<QWidget *>(pdev);
- }
-
- if (w && swapchain) {
- QRect br = w->rect();
- QRect wbr = br;//.translated(-w->pos());
-
- RECT destrect;
- destrect.left = wbr.x();
- destrect.top = wbr.y();
- destrect.right = destrect.left + wbr.width();
- destrect.bottom = destrect.top + wbr.height();
-
- RECT srcrect;
- srcrect.left = br.x();// + w->x();
- srcrect.top = br.y();// + w->y();
- srcrect.right = wbr.width() + srcrect.left;
- srcrect.bottom = wbr.height() + srcrect.top;
- int devwidth = w->width();
- int devheight = w->height();
-
- if (devwidth <= srcrect.right) {
- int diff = srcrect.right - devwidth;
- srcrect.right -= diff;
- destrect.right -= diff;
- if (srcrect.right <= srcrect.left)
- return false;
- }
- if (devheight <= srcrect.bottom) {
- int diff = srcrect.bottom - devheight;
- srcrect.bottom -= diff;
- destrect.bottom -= diff;
- if (srcrect.bottom <= srcrect.top)
- return false;
- }
-
- if (FAILED(swapchain->Present(&srcrect, &destrect, w->winId(), 0, 0)))
- qWarning("QDirect3DPaintEngine: failed to present back buffer.");
- }
- }
-
-
- return true;
-}
-
-void QDirect3DPaintEngine::updateState(const QPaintEngineState &state)
-{
-#ifdef QT_DEBUG_D3D_CALLS
- qDebug() << "QDirect3DPaintEngine::updateState";
-#endif
- Q_D(QDirect3DPaintEngine);
-
- bool update_fast_pen = false;
- DirtyFlags flags = state.state();
-
- if (flags & DirtyOpacity) {
- d->m_opacity = state.opacity();
- if (d->m_opacity > 1.0f)
- d->m_opacity = 1.0f;
- if (d->m_opacity < 0.f)
- d->m_opacity = 0.f;
- uint c = (d->m_opacity * 255);
- d->m_opacity_color = D3DCOLOR_ARGB(c,c,c,c);
- flags |= (DirtyPen | DirtyBrush);
- }
-
- if (flags & DirtyCompositionMode) {
- d->m_cmode = state.compositionMode();
- }
-
- if (flags & DirtyTransform) {
- d->updateTransform(state.transform());
- update_fast_pen = true;
- }
-
- if (flags & DirtyHints) {
- if (state.renderHints() & QPainter::Antialiasing)
- d->m_current_state |= QD3DBatchItem::BI_AA;
- else
- d->m_current_state &= ~QD3DBatchItem::BI_AA;
- update_fast_pen = true;
- }
-
- if (flags & DirtyFont) {
- d->updateFont(state.font());
- }
-
- if (state.state() & DirtyClipEnabled) {
- if (state.isClipEnabled() && !d->m_clipping_enabled) {
- d->m_clipping_enabled = true;
- if (d->m_has_complex_clipping)
- d->updateClipPath(painter()->clipPath(), Qt::ReplaceClip);
- else
- d->updateClipRegion(painter()->clipRegion(), Qt::ReplaceClip);
- } else if (!state.isClipEnabled() && d->m_clipping_enabled) {
- d->m_clipping_enabled = false;
- if (d->m_has_complex_clipping)
- d->updateClipPath(QPainterPath(), Qt::NoClip);
- else
- d->updateClipRegion(QRegion(), Qt::NoClip);
- }
- }
-
- if (flags & DirtyClipRegion) {
- d->updateClipRegion(state.clipRegion(), state.clipOperation());
- }
-
- if (flags & DirtyClipPath) {
- d->updateClipPath(state.clipPath(), state.clipOperation());
- }
-
- if (flags & DirtyBrushOrigin) {
- d->m_brush_origin = QTransform();
- d->m_brush_origin.translate(-state.brushOrigin().x(),
- -state.brushOrigin().y());
- flags |= DirtyBrush;
- }
-
- if (flags & DirtyPen) {
- d->updatePen(state.pen());
- update_fast_pen = true;
- }
-
- if (flags & DirtyBrush)
- d->updateBrush(state.brush());
-
- if (update_fast_pen && d->m_has_pen) {
- if (d->m_current_state & QD3DBatchItem::BI_AA) {
- d->m_has_fast_pen = false;
- d->m_has_aa_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen)
- && (d->m_pen_width <= 1.0f)
- && (d->m_pen.style() == Qt::SolidLine);
- } else {
- d->m_has_aa_fast_pen = false;
- d->m_has_fast_pen = ((d->m_txop <= QTransform::TxTranslate) || d->m_has_cosmetic_pen)
- && (d->m_pen.style() == Qt::SolidLine)
- && (d->m_pen.capStyle() == Qt::SquareCap);
- }
- }
-}
-
-void QDirect3DPaintEngine::cleanup()
-{
- Q_D(QDirect3DPaintEngine);
- d->cleanup();
-}
-
-void QDirect3DPaintEngine::scroll(QPaintDevice *pd, const RECT &srcrect, const RECT &destrect)
-{
- Q_D(QDirect3DPaintEngine);
- LPDIRECT3DSURFACE9 srcsurf = d->m_surface_manager.surface(pd);
- LPDIRECT3DSURFACE9 masksurf = d->m_draw_helper->freeMaskSurface();
- if (FAILED(d->m_d3d_device->StretchRect(srcsurf, &srcrect, masksurf, &srcrect, D3DTEXF_NONE)))
- qWarning("QDirect3DPaintEngine: StretchRect failed.");
- if (FAILED(d->m_d3d_device->StretchRect(masksurf, &srcrect, srcsurf, &destrect, D3DTEXF_NONE)))
- qWarning("QDirect3DPaintEngine: StretchRect failed.");
-}
-
-LPDIRECT3DSWAPCHAIN9 QDirect3DPaintEngine::swapChain(QPaintDevice *pd)
-{
- Q_D(QDirect3DPaintEngine);
-
- if (d->m_in_scene) {
- if (d->m_d3d_device == 0) {
- qWarning("QDirect3DPaintEngine: No device!");
- return false;
- }
-
- d->setRenderTechnique(QDirect3DPaintEnginePrivate::RT_NoTechnique);
- if (FAILED(d->m_d3d_device->EndScene()))
- qWarning("QDirect3DPaintEngine: failed to end scene.");
-
- d->m_in_scene = false;
- }
-
- return d->m_surface_manager.swapChain(pd);
-}
-
-void QDirect3DPaintEngine::releaseSwapChain(QPaintDevice *pd)
-{
- Q_D(QDirect3DPaintEngine);
- d->m_surface_manager.releasePaintDevice(pd);
-}
-
-HDC QDirect3DPaintEngine::getDC() const
-{
- QDirect3DPaintEnginePrivate *d = const_cast<QDirect3DPaintEnginePrivate *>(d_func());
-
- if (!d->m_dc && d->m_current_surface) {
- d->m_dcsurface = d->m_current_surface;
- if (FAILED(d->m_current_surface->GetDC(&d->m_dc)))
- qWarning() << "QDirect3DPaintEngine::getDC() failed!";
- }
-
- return d->m_dc;
-}
-
-void QDirect3DPaintEngine::setFlushOnEnd(bool flushOnEnd)
-{
- Q_D(QDirect3DPaintEngine);
-
- d->m_flush_on_end = flushOnEnd;
-}
-
-bool QDirect3DPaintEngine::hasDirect3DSupport()
-{
- Q_D(QDirect3DPaintEngine);
- return d->m_supports_d3d;
-}
-
-QT_END_NAMESPACE
-
-#include "qpaintengine_d3d.moc"
diff --git a/src/gui/painting/qpaintengine_d3d.fx b/src/gui/painting/qpaintengine_d3d.fx
deleted file mode 100644
index 1148b2a..0000000
--- a/src/gui/painting/qpaintengine_d3d.fx
+++ /dev/null
@@ -1,608 +0,0 @@
-bool g_mCosmeticPen;
-int4 g_mChannel;
-float2 g_mMaskOffset;
-int2 g_mMaskSize;
-float4x4 g_mMaskProjection;
-float4x4 g_mViewProjection;
-float4x4 g_mTransformation;
-texture g_mAAMask;
-texture g_mTexture;
-int g_mBrushMode;
-float g_mFocalDist;
-
-#define M_PI 3.14159265358979323846
-
-sampler PixmapSampler = sampler_state
-{
- texture = <g_mTexture>;
- MIPFILTER = NONE;
- MINFILTER = LINEAR;
- MAGFILTER = LINEAR;
-};
-
-sampler TextSampler = sampler_state
-{
- texture = <g_mTexture>;
- MIPFILTER = NONE;
- MINFILTER = POINT;
- MAGFILTER = POINT;
-};
-
-sampler AAMaskSampler = sampler_state
-{
- texture = <g_mAAMask>;
- AddressU = WRAP;
- AddressV = WRAP;
- AddressW = WRAP;
- MIPFILTER = NONE;
- MINFILTER = POINT;
- MAGFILTER = POINT;
-};
-
-struct VS_FULL
-{
- float4 Position : POSITION;
- float4 Diffuse : COLOR0;
- float4 TexCoords0 : TEXCOORD0;
- float4 TexCoords1 : TEXCOORD1;
-};
-
-VS_FULL TrapezoidVS( float4 Position : POSITION,
- float4 Diffuse : COLOR0,
- float4 TexCoords0 : TEXCOORD0,
- float4 TexCoords1 : TEXCOORD1)
-{
- VS_FULL Output;
-
- float a = (TexCoords1.x * Position.x) + (TexCoords1.z * (1.0 - Position.x) ); // left or right a
- float b = (TexCoords1.y * Position.x) + (TexCoords1.w * (1.0 - Position.x) ); // left or right b
- float d = 1.0 - (Position.x * 2);
-
- Position.x = (a * Position.y + b) + ( sqrt( abs(a * a) ) * d );
- //Position.x += step(abs(a), 0) * d;
- Position.x += (0.5 * d);
-
- Output.Position = mul(Position, g_mMaskProjection);
- Output.Diffuse = Diffuse;
- Output.TexCoords0 = TexCoords0;
- Output.TexCoords1 = TexCoords1;
-
- return Output;
-}
-
-struct PS_OUTPUT
-{
- float4 Color : COLOR0;
-};
-
-PS_OUTPUT TrapezoidPS(VS_FULL In, float2 pixelPos : VPOS)
-{
- PS_OUTPUT Out;
-
- float top = max(pixelPos.y - 0.5, In.TexCoords0.x);
- float bottom = min(pixelPos.y + 0.5, In.TexCoords0.y);
-
- float area = bottom - top;
-
- float left = pixelPos.x - 0.5;
- float right = pixelPos.x + 0.5;
-
- // use line equations to compute intersections of left/right edges with top/bottom of truncated pixel
- // vecX: x = (left, top), y = (left, bottom), z = (right, top), w = (right, bottom)
- float4 vecX = In.TexCoords1.xxzz * float2(top, bottom).xyxy + In.TexCoords1.yyww;
-
- float2 invA = In.TexCoords0.zw;
-
- // transform right line to left to be able to use same calculations for both
- vecX.zw = 2 * pixelPos.x - vecX.zw;
-
- float2 topX = float2(vecX.x, vecX.z);
- float2 bottomX = float2(vecX.y, vecX.w);
-
- // transform lines such that top intersection is to the right of bottom intersection
- float2 topXTemp = max(topX, bottomX);
- float2 bottomXTemp = min(topX, bottomX);
-
- // make sure line slope reflects mirrored lines
- invA = lerp(invA, -invA, step(topX, bottomX));
-
- float2 vecLeftRight = float2(left, right);
-
- // compute the intersections of the lines with the left and right edges of the pixel
- // intersectY: x = (left_line, left), y = (left_line, right), z = (right_line, left), w = (right_line, right)
- float4 intersectY = top + (vecLeftRight.xyxy - topXTemp.xxyy) * invA.xxyy;
-
- float2 temp = lerp(area - 0.5 * (right - bottomXTemp) * (bottom - intersectY.yw), // left < bottom < right < top
- (0.5 * (topXTemp + bottomXTemp) - left) * area, // left < bottom < top < right
- step(topXTemp, right));
-
- float2 excluded = 0.5 * (intersectY.xz - top) * (topXTemp - left); // bottom < left < top < right
-
- excluded = lerp(0.5 * (intersectY.yw + intersectY.xz) - top, // bottom < left < right < top
- excluded, step(topXTemp, right));
-
- excluded = lerp(temp, // left < bottom < right (see calculation of temp)
- excluded, step(bottomXTemp, left));
-
- excluded = lerp(float2(area, area), // right < bottom < top
- excluded, step(bottomXTemp, right));
-
- excluded *= step(left, topXTemp);
-
- float result = (area - excluded.x - excluded.y) * step(top, bottom);
- Out.Color.r = result * g_mChannel[0];
- Out.Color.g = result * g_mChannel[1];
- Out.Color.b = result * g_mChannel[2];
- Out.Color.a = result * g_mChannel[3];
-
- return Out;
-}
-
-VS_FULL ViewProjectionVS( float4 Position : POSITION,
- float4 Diffuse : COLOR0,
- float4 TexCoords0 : TEXCOORD0,
- float4 TexCoords1 : TEXCOORD1)
-{
- VS_FULL Output;
-
- Output.Position = mul(Position, g_mTransformation);
- Output.Position = mul(Output.Position, g_mViewProjection);
- Output.Diffuse = Diffuse;
- Output.TexCoords0 = TexCoords0;
- Output.TexCoords1 = TexCoords1;
-
- return Output;
-}
-
-PS_OUTPUT DirectMaskPS(VS_FULL In, float2 pixelPos : VPOS)
-{
- PS_OUTPUT Out;
- Out.Color = In.Diffuse;
-
- float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize;
- float2 clipcoords = (pixelPos - 0.5) / g_mMaskSize;
-
- float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a;
- Out.Color.a = c.r * g_mChannel[0];
- Out.Color.a += c.g * g_mChannel[1];
- Out.Color.a += c.b * g_mChannel[2];
- Out.Color.a += c.a * g_mChannel[3];
-
- return Out;
-}
-
-PS_OUTPUT MaskPS(VS_FULL In, float2 pixelPos : VPOS)
-{
- PS_OUTPUT Out;
-
- if (g_mBrushMode == 1) {
- float x = In.TexCoords0.x;
- float y = In.TexCoords0.y;
- x = x - int(x);
- y = y - int(y);
- Out.Color = tex2D(PixmapSampler, float2(x, y));
- Out.Color.a = Out.Color.a * In.Diffuse.a;
- } else if (g_mBrushMode == 2) {
- Out.Color = tex1D(PixmapSampler, In.TexCoords0.x);
- } else if (g_mBrushMode == 3) {
- float t = atan2(In.TexCoords0.y, -In.TexCoords0.x) / (2 * M_PI);
- Out.Color = tex1D(PixmapSampler, t + 0.5);
- } else if (g_mBrushMode == 4) {
- float2 tc = float2(In.TexCoords0.x, abs(In.TexCoords0.y));
- float a = (tc.x - g_mFocalDist) / tc.y;
- float b = g_mFocalDist;
-
- float A = 1 + (a * a);
- float B = 2.0 * a * b;
- float C = (b * b) - 1;
-
- float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A);
- Out.Color = tex1D(PixmapSampler, (tc.y / y) );
- } else if (g_mBrushMode == 5) {
- Out.Color = tex2D(PixmapSampler, In.TexCoords0.xy);
- Out.Color = Out.Color * In.Diffuse;
- } else {
- Out.Color = In.Diffuse;
- }
-
- float2 maskcoords = ( (pixelPos + g_mMaskOffset) - 0.5 ) / g_mMaskSize;
-
- float4 c = tex2D(AAMaskSampler, maskcoords.xy) * Out.Color.a;
- Out.Color.a = c.r * g_mChannel[0];
- Out.Color.a += c.g * g_mChannel[1];
- Out.Color.a += c.b * g_mChannel[2];
- Out.Color.a += c.a * g_mChannel[3];
-
- return Out;
-}
-
-struct VS_NORMAL
-{
- float4 Position : POSITION;
- float4 Diffuse : COLOR0;
- float4 TexCoords : TEXCOORD0;
-};
-
-VS_NORMAL MaskProjectionVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- Output.Position = mul(In.Position, g_mMaskProjection);
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-float4 DirectSimplePS(float4 Color : COLOR0) : COLOR0
-{
- return Color;
-}
-
-float4 SimplePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0
-{
- if (g_mBrushMode == 1) {
- float opacity = Color.a;
- float x = TexCoords.x;
- float y = TexCoords.y;
- x = x - int(x);
- y = y - int(y);
- Color = tex2D(PixmapSampler, float2(x, y));
- Color.a = Color.a * opacity;
- } else if (g_mBrushMode == 2) {
- Color = tex1D(PixmapSampler, TexCoords.x);
- } else if (g_mBrushMode == 3) {
- float t = atan2(TexCoords.y, -TexCoords.x) / (2 * M_PI);
- Color = tex1D(PixmapSampler, t + 0.5);
- } else if (g_mBrushMode == 4) {
- float2 tc = float2(TexCoords.x, abs(TexCoords.y));
- float a = (tc.x - g_mFocalDist) / tc.y;
- float b = g_mFocalDist;
-
- float A = 1 + (a * a);
- float B = 2.0 * a * b;
- float C = (b * b) - 1;
-
- float y = (-B + sqrt(B*B - 4.0*A*C)) / (2.0*A);
- Color = tex1D(PixmapSampler, (tc.y / y) );
- } else if (g_mBrushMode == 5) {
- Color = tex2D(PixmapSampler, TexCoords.xy) * Color;
- }
-
- return Color;
-}
-
-float4 TextPS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0
-{
- Color.a *= tex2D(TextSampler, TexCoords.xy).a;
- return Color;
-}
-
-float4 ClearTypePS(float4 Color : COLOR0, float4 TexCoords : TEXCOORD0) : COLOR0
-{
-// if (g_mUsePixmap) {
-// float4 MaskColor = tex2D(PixmapSampler, TexCoords.xy);
-// Color = float4(1.0, 0.0, 0.0, 1.0);
-// Color.a = (1 - MaskColor.a) + MaskColor.a * Color.a;
-// Color.r = (1.0 - MaskColor.r) + (MaskColor.r * Color.r);
-// Color.g = (1.0 - MaskColor.g) + (MaskColor.g * Color.g);
-// Color.b = (1.0 - MaskColor.b) + (MaskColor.b * Color.b);
-// Color = MaskColor;
- return tex2D(PixmapSampler, TexCoords.xy);
-}
-
-VS_NORMAL NoTxAliasedVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- Output.Position = mul(In.Position, g_mViewProjection);
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-VS_NORMAL AliasedVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- Output.Position = mul(In.Position, g_mTransformation);
- Output.Position = mul(Output.Position, g_mViewProjection);
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-VS_NORMAL AliasedLinesVS(VS_NORMAL In)
-{
- VS_NORMAL Output;
-
- float4 start = float4(In.Position.x, In.Position.y, 0.5, In.Position.w);
- float4 end = float4(In.TexCoords.z, In.TexCoords.w, 0.5, In.Position.w);
- if (g_mCosmeticPen) {
- start = mul(start, g_mTransformation);
- end = mul(end, g_mTransformation);
- }
-
- float2 line_vec = end - start;
- float2 vec = normalize(line_vec);
- float2 norm = float2(-vec.y, vec.x);
-
- float pen_width = In.Position.z;
- norm = norm * pen_width * 0.5;
- vec = vec * pen_width * 0.5;
-
- Output.Position.w = In.Position.w;
- Output.Position.x = start.x + (vec.x * In.TexCoords.x);
- Output.Position.x = Output.Position.x + (norm.x * In.TexCoords.y);
- Output.Position.x = Output.Position.x + (line_vec.x * step(0, In.TexCoords.x));
- Output.Position.y = start.y + (vec.y * In.TexCoords.x);
- Output.Position.y = Output.Position.y + (norm.y * In.TexCoords.y);
- Output.Position.y = Output.Position.y + (line_vec.y * step(0, In.TexCoords.x));
- Output.Position.z = 0.5;
-
- if (!g_mCosmeticPen) {
- Output.Position = mul(Output.Position, g_mTransformation);
- }
- Output.Position = mul(Output.Position, g_mViewProjection);
-
- Output.Diffuse = In.Diffuse;
- Output.TexCoords = In.TexCoords;
-
- return Output;
-}
-
-
-technique Antialiased
-{
- pass PASS_AA_CREATEMASK
- {
- StencilEnable = False;
- ZWriteEnable = False;
- ColorWriteEnable = 0x0f;
- ZEnable = False;
-
- SrcBlend = One;
- DestBlend = One;
-
- VertexShader = compile vs_3_0 TrapezoidVS();
- PixelShader = compile ps_3_0 TrapezoidPS();
- }
-
- pass PASS_AA_DRAW
- {
- StencilEnable = False;
- ZFunc = Greater;
- ZWriteEnable = False;
- ZEnable = True;
- ColorWriteEnable = 0x0f;
-
- VertexShader = compile vs_3_0 ViewProjectionVS();
- PixelShader = compile ps_3_0 MaskPS();
- }
-
- pass PASS_AA_DRAW_DIRECT
- {
- StencilEnable = False;
- ZFunc = Greater;
- ZEnable = True;
- ZWriteEnable = False;
- ColorWriteEnable = 0x0f;
-
- VertexShader = compile vs_3_0 ViewProjectionVS();
- PixelShader = compile ps_3_0 DirectMaskPS();
- }
-}
-
-technique Aliased
-{
- pass PASS_STENCIL_ODDEVEN
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilPass = Invert;
- StencilFunc = Always;
- ColorWriteEnable = 0;
-
- ZEnable = False;
- ZWriteEnable = False;
-
- VertexShader = compile vs_1_1 NoTxAliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_WINDING
- {
- TwoSidedStencilMode = True;
- StencilEnable = True;
- StencilRef = 0;
- StencilMask = 0xFFFFFFFF;
-
- CCW_StencilPass = Incr;
- CCW_StencilFunc = Always;
-
- StencilPass = Decr;
- StencilFunc = Always;
-
- ColorWriteEnable = 0;
-
- ZEnable = False;
- ZWriteEnable = False;
-
- VertexShader = compile vs_1_1 NoTxAliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_DRAW
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilFunc = NotEqual;
- StencilMask = 0xFFFFFFFF;
- StencilRef = 0;
- StencilPass = Zero;
- StencilFail = Zero;
- StencilZFail = Zero;
-
- ColorWriteEnable = 0x0f;
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 SimplePS();
- }
-
- pass PASS_STENCIL_DRAW_DIRECT
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilFunc = NotEqual;
- StencilMask = 0xFFFFFFFF;
- StencilRef = 0;
- StencilPass = Zero;
- StencilFail = Zero;
- StencilZFail = Zero;
-
- ColorWriteEnable = 0x0f;
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_CLIP
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilFunc = NotEqual;
- StencilMask = 0xFFFFFFFF;
- StencilRef = 0;
- StencilPass = Zero;
- StencilFail = Zero;
- StencilZFail = Zero;
-
- ColorWriteEnable = 0;
- ZEnable = True;
- ZWriteEnable = True;
- ZFunc = Always;
-
- VertexShader = compile vs_1_1 NoTxAliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_STENCIL_NOSTENCILCHECK
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 SimplePS();
- }
-
- pass PASS_STENCIL_NOSTENCILCHECK_DIRECT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_TEXT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedVS();
- PixelShader = compile ps_2_0 TextPS();
- }
-
- pass PASS_CLEARTYPE_TEXT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
-// SrcBlend = SrcAlpha;
-// DestBlend = InvSrcAlpha;
-
-// SrcBlend = DestColor;
-// DestBlend = Zero;
- SrcBlend = BlendFactor;
- DestBlend = InvSrcColor;
-
-// SrcBlend = Zero;
-// DestBlend = SrcColor;
-
-// SrcBlend = One;
-// DestBlend = Zero;
-
- VertexShader = compile vs_3_0 AliasedVS();
- PixelShader = compile ps_3_0 ClearTypePS();
- }
-
- pass PASS_ALIASED_LINES
- {
- TwoSidedStencilMode = False;
- StencilEnable = True;
- StencilPass = Invert;
- StencilFunc = Always;
- ColorWriteEnable = 0;
-
- ZEnable = False;
- ZWriteEnable = False;
-
- VertexShader = compile vs_1_1 AliasedLinesVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-
- pass PASS_ALIASED_LINES_DIRECT
- {
- StencilEnable = False;
-
- ZEnable = True;
- ZWriteEnable = False;
- ZFunc = Greater;
-
- ColorWriteEnable = 0x0f;
-
- SrcBlend = SrcAlpha;
- DestBlend = InvSrcAlpha;
-
- VertexShader = compile vs_1_1 AliasedLinesVS();
- PixelShader = compile ps_2_0 DirectSimplePS();
- }
-}
-
diff --git a/src/gui/painting/qpaintengine_d3d.qrc b/src/gui/painting/qpaintengine_d3d.qrc
deleted file mode 100644
index c106f2b..0000000
--- a/src/gui/painting/qpaintengine_d3d.qrc
+++ /dev/null
@@ -1,5 +0,0 @@
-<!DOCTYPE RCC><RCC version="1.0">
-<qresource>
- <file>qpaintengine_d3d.fx</file>
-</qresource>
-</RCC>
diff --git a/src/gui/painting/qpaintengine_mac.cpp b/src/gui/painting/qpaintengine_mac.cpp
index 5889388..854bbaf 100644
--- a/src/gui/painting/qpaintengine_mac.cpp
+++ b/src/gui/painting/qpaintengine_mac.cpp
@@ -131,8 +131,8 @@ QMacCGContext::QMacCGContext(QPainter *p)
QPainterState *state = static_cast<QPainterState *>(pe->state);
Q_ASSERT(state);
- if (!state->redirection_offset.isNull())
- CGContextTranslateCTM(context, -state->redirection_offset.x(), -state->redirection_offset.y());
+ if (!state->redirectionMatrix.isIdentity())
+ CGContextTranslateCTM(context, state->redirectionMatrix.dx(), state->redirectionMatrix.dy());
}
}
CGContextRetain(context);
@@ -1496,23 +1496,23 @@ QCoreGraphicsPaintEnginePrivate::setStrokePen(const QPen &pen)
for(int i = 0; i < customs.size(); ++i)
linedashes.append(customs.at(i));
} else if(pen.style() == Qt::DashLine) {
- linedashes.append(3);
- linedashes.append(1);
+ linedashes.append(4);
+ linedashes.append(2);
} else if(pen.style() == Qt::DotLine) {
linedashes.append(1);
- linedashes.append(1);
+ linedashes.append(2);
} else if(pen.style() == Qt::DashDotLine) {
- linedashes.append(3);
- linedashes.append(1);
- linedashes.append(1);
+ linedashes.append(4);
+ linedashes.append(2);
linedashes.append(1);
+ linedashes.append(2);
} else if(pen.style() == Qt::DashDotDotLine) {
- linedashes.append(3);
- linedashes.append(1);
- linedashes.append(1);
- linedashes.append(1);
+ linedashes.append(4);
+ linedashes.append(2);
linedashes.append(1);
+ linedashes.append(2);
linedashes.append(1);
+ linedashes.append(2);
}
const CGFloat cglinewidth = pen.widthF() <= 0.0f ? 1.0f : float(pen.widthF());
for(int i = 0; i < linedashes.size(); ++i) {
diff --git a/src/gui/painting/qpaintengine_mac_p.h b/src/gui/painting/qpaintengine_mac_p.h
index 298c145..9b85800 100644
--- a/src/gui/painting/qpaintengine_mac_p.h
+++ b/src/gui/painting/qpaintengine_mac_p.h
@@ -233,6 +233,8 @@ protected:
friend class QMacPrintEngine;
friend class QMacPrintEnginePrivate;
friend void qt_mac_display_change_callbk(CGDirectDisplayID, CGDisplayChangeSummaryFlags, void *);
+ friend void qt_color_profile_changed(CFNotificationCenterRef center, void *,
+ CFStringRef , const void *, CFDictionaryRef);
QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr);
private:
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index ada3ebf..14ce18b 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -141,7 +141,6 @@ extern bool qt_cleartype_enabled;
* Span functions
*/
static void qt_span_fill_clipRect(int count, const QSpan *spans, void *userData);
-static void qt_span_fill_clipRegion(int count, const QSpan *spans, void *userData);
static void qt_span_fill_clipped(int count, const QSpan *spans, void *userData);
static void qt_span_clip(int count, const QSpan *spans, void *userData);
static void qt_merge_clip(const QClipData *c1, const QClipData *c2, QClipData *result);
@@ -366,7 +365,8 @@ void QRasterPaintEngine::init()
d->basicStroker.setCubicToHook(qt_ft_outline_cubic_to);
d->dashStroker = 0;
- d->baseClip = 0;
+ d->baseClip = new QClipData(d->device->height());
+ d->baseClip->setClipRect(QRect(0, 0, d->device->width(), d->device->height()));
d->image_filler.init(d->rasterBuffer, this);
d->image_filler.type = QSpanData::Texture;
@@ -450,6 +450,8 @@ QRasterPaintEngine::~QRasterPaintEngine()
delete d->outlineMapper;
delete d->rasterizer;
delete d->dashStroker;
+
+ delete d->baseClip;
}
/*!
@@ -486,12 +488,12 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
d->rasterizer->setClipRect(d->deviceRect);
s->penData.init(d->rasterBuffer, this);
- s->penData.setup(s->pen.brush(), s->intOpacity);
+ s->penData.setup(s->pen.brush(), s->intOpacity, s->composition_mode);
s->stroker = &d->basicStroker;
d->basicStroker.setClipRect(d->deviceRect);
s->brushData.init(d->rasterBuffer, this);
- s->brushData.setup(s->brush, s->intOpacity);
+ s->brushData.setup(s->brush, s->intOpacity, s->composition_mode);
d->rasterBuffer->compositionMode = QPainter::CompositionMode_SourceOver;
@@ -512,16 +514,20 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
if (d->mono_surface)
d->glyphCacheType = QFontEngineGlyphCache::Raster_Mono;
-#ifdef Q_WS_WIN
- else if (qt_cleartype_enabled) {
+#if defined(Q_WS_WIN)
+ else if (qt_cleartype_enabled)
+#elif defined (Q_WS_MAC)
+ else if (true)
+#else
+ else if (false)
+#endif
+ {
QImage::Format format = static_cast<QImage *>(d->device)->format();
if (format == QImage::Format_ARGB32_Premultiplied || format == QImage::Format_RGB32)
d->glyphCacheType = QFontEngineGlyphCache::Raster_RGBMask;
else
d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
- }
-#endif
- else
+ } else
d->glyphCacheType = QFontEngineGlyphCache::Raster_A8;
setActive(true);
@@ -533,19 +539,14 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
*/
bool QRasterPaintEngine::end()
{
- Q_D(QRasterPaintEngine);
#ifdef QT_DEBUG_DRAW
+ Q_D(QRasterPaintEngine);
qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect;
if (d->baseClip) {
dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), d->baseClip);
}
#endif
- if (d->baseClip) {
- delete d->baseClip;
- d->baseClip = 0;
- }
-
return true;
}
@@ -621,22 +622,22 @@ void QRasterPaintEngine::updateMatrix(const QTransform &matrix)
d->isPlain45DegreeRotation = false;
if (txop >= QTransform::TxRotate) {
d->isPlain45DegreeRotation =
- (qFuzzyCompare(matrix.m11() + 1, qreal(1))
- && qFuzzyCompare(matrix.m12(), qreal(1))
- && qFuzzyCompare(matrix.m21(), qreal(-1))
- && qFuzzyCompare(matrix.m22() + 1, qreal(1))
+ (qFuzzyIsNull(matrix.m11())
+ && qFuzzyIsNull(matrix.m12() - qreal(1))
+ && qFuzzyIsNull(matrix.m21() + qreal(1))
+ && qFuzzyIsNull(matrix.m22())
)
||
- (qFuzzyCompare(matrix.m11(), qreal(-1))
- && qFuzzyCompare(matrix.m12() + 1, qreal(1))
- && qFuzzyCompare(matrix.m21() + 1, qreal(1))
- && qFuzzyCompare(matrix.m22(), qreal(-1))
+ (qFuzzyIsNull(matrix.m11() + qreal(1))
+ && qFuzzyIsNull(matrix.m12())
+ && qFuzzyIsNull(matrix.m21())
+ && qFuzzyIsNull(matrix.m22() + qreal(1))
)
||
- (qFuzzyCompare(matrix.m11() + 1, qreal(1))
- && qFuzzyCompare(matrix.m12(), qreal(-1))
- && qFuzzyCompare(matrix.m21(), qreal(1))
- && qFuzzyCompare(matrix.m22() + 1, qreal(1))
+ (qFuzzyIsNull(matrix.m11())
+ && qFuzzyIsNull(matrix.m12() + qreal(1))
+ && qFuzzyIsNull(matrix.m21() - qreal(1))
+ && qFuzzyIsNull(matrix.m22())
)
;
}
@@ -772,7 +773,7 @@ void QRasterPaintEngine::updatePen(const QPen &pen)
s->strokeFlags = 0;
s->penData.clip = d->clip();
- s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity);
+ s->penData.setup(pen_style == Qt::NoPen ? QBrush() : pen.brush(), s->intOpacity, s->composition_mode);
if (s->strokeFlags & QRasterPaintEngine::DirtyTransform
|| pen.brush().transform().type() >= QTransform::TxNone) {
@@ -872,7 +873,7 @@ void QRasterPaintEngine::updateBrush(const QBrush &brush)
QRasterPaintEngineState *s = state();
// must set clip prior to setup, as setup uses it...
s->brushData.clip = d->clip();
- s->brushData.setup(brush, s->intOpacity);
+ s->brushData.setup(brush, s->intOpacity, s->composition_mode);
if (s->fillFlags & DirtyTransform
|| brush.transform().type() >= QTransform::TxNone)
d_func()->updateMatrixData(&s->brushData, brush, d->brushMatrix());
@@ -1027,6 +1028,10 @@ void QRasterPaintEnginePrivate::drawImage(const QPointF &pt,
{
if (alpha == 0 || !clip.isValid())
return;
+
+ if (alpha ==0)
+ return;
+
Q_ASSERT(img.depth() >= 8);
int srcBPL = img.bytesPerLine();
@@ -1095,11 +1100,10 @@ void QRasterPaintEnginePrivate::systemStateChanged()
if (!systemClip.isEmpty()) {
QRegion clippedDeviceRgn = systemClip & clipRect;
deviceRect = clippedDeviceRgn.boundingRect();
- delete baseClip;
- baseClip = new QClipData(device->height());
baseClip->setClipRegion(clippedDeviceRgn);
} else {
deviceRect = clipRect;
+ baseClip->setClipRect(deviceRect);
}
#ifdef QT_DEBUG_DRAW
qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip;
@@ -1171,6 +1175,25 @@ static void checkClipRatios(QRasterPaintEnginePrivate *d)
}
#endif
+static void qrasterpaintengine_state_setNoClip(QRasterPaintEngineState *s)
+{
+ if (s->flags.has_clip_ownership)
+ delete s->clip;
+ s->clip = 0;
+ s->flags.has_clip_ownership = false;
+}
+
+static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterPaintEngineState *s)
+{
+ s->fillFlags |= QPaintEngine::DirtyClipPath;
+ s->strokeFlags |= QPaintEngine::DirtyClipPath;
+ s->pixmapFlags |= QPaintEngine::DirtyClipPath;
+
+ d->solid_color_filler.clip = d->clip();
+ d->solid_color_filler.adjustSpanMethods();
+}
+
+
/*!
\internal
*/
@@ -1182,12 +1205,12 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
if (path.elements()) {
for (int i=0; i<path.elementCount(); ++i) {
qDebug() << " - " << path.elements()[i]
- << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")";
+ << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')';
}
} else {
for (int i=0; i<path.elementCount(); ++i) {
qDebug() << " ---- "
- << "(" << path.points()[i*2] << ", " << path.points()[i*2+1] << ")";
+ << '(' << path.points()[i*2] << ", " << path.points()[i*2+1] << ')';
}
}
#endif
@@ -1219,10 +1242,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
}
if (op == Qt::NoClip) {
- if (s->flags.has_clip_ownership)
- delete s->clip;
- s->clip = 0;
- s->flags.has_clip_ownership = false;
+ qrasterpaintengine_state_setNoClip(s);
} else {
QClipData *base = d->baseClip;
@@ -1264,17 +1284,7 @@ void QRasterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
s->clip = newClip;
s->flags.has_clip_ownership = true;
}
-
- s->fillFlags |= DirtyClipPath;
- s->strokeFlags |= DirtyClipPath;
- s->pixmapFlags |= DirtyClipPath;
-
- d->solid_color_filler.clip = d->clip();
- d->solid_color_filler.adjustSpanMethods();
-
-#ifdef QT_CLIPPING_RATIOS
- checkClipRatios(d);
-#endif
+ qrasterpaintengine_dirty_clip(d, s);
}
@@ -1292,10 +1302,7 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
QRasterPaintEngineState *s = state();
if (op == Qt::NoClip) {
- if (s->flags.has_clip_ownership)
- delete s->clip;
- s->clip = d->baseClip;
- s->flags.has_clip_ownership = false;
+ qrasterpaintengine_state_setNoClip(s);
} else if (op == Qt::UniteClip || s->matrix.type() > QTransform::TxScale) {
QPaintEngineEx::clip(rect, op);
@@ -1339,37 +1346,63 @@ void QRasterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
return;
}
}
-
- s->brushData.clip = d->clip();
- s->penData.clip = d->clip();
-
- s->fillFlags |= DirtyClipPath;
- s->strokeFlags |= DirtyClipPath;
- s->pixmapFlags |= DirtyClipPath;
-
- d->solid_color_filler.clip = d->clip();
- d->solid_color_filler.adjustSpanMethods();
-
-
-#ifdef QT_CLIPPING_RATIOS
- checkClipRatios(d);
-#endif
+ qrasterpaintengine_dirty_clip(d, s);
}
+
/*!
\internal
*/
void QRasterPaintEngine::clip(const QRegion &region, Qt::ClipOperation op)
{
- QPaintEngineEx::clip(region, op);
-}
+#ifdef QT_DEBUG_DRAW
+ qDebug() << "QRasterPaintEngine::clip(): " << region << op;
+#endif
-/*!
- \internal
-*/
-void QRasterPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
-{
- QPaintEngineEx::clip(path, op);
+ Q_D(QRasterPaintEngine);
+
+ if (region.numRects() == 1) {
+ clip(region.boundingRect(), op);
+ return;
+ }
+
+ QRasterPaintEngineState *s = state();
+ const QClipData *clip = d->clip();
+ const QClipData *baseClip = d->baseClip;
+
+ if (op == Qt::NoClip) {
+ qrasterpaintengine_state_setNoClip(s);
+ } else if (s->matrix.type() > QTransform::TxScale
+ || op == Qt::UniteClip
+ || (op == Qt::IntersectClip && !clip->hasRectClip && !clip->hasRegionClip)
+ || (op == Qt::ReplaceClip && !baseClip->hasRectClip && !baseClip->hasRegionClip)) {
+ QPaintEngineEx::clip(region, op);
+ } else {
+ const QClipData *curClip;
+ QClipData *newClip;
+
+ if (op == Qt::IntersectClip)
+ curClip = clip;
+ else
+ curClip = baseClip;
+
+ if (s->flags.has_clip_ownership) {
+ newClip = s->clip;
+ Q_ASSERT(newClip);
+ } else {
+ newClip = new QClipData(d->rasterBuffer->height());
+ s->clip = newClip;
+ s->flags.has_clip_ownership = true;
+ }
+
+ QRegion r = s->matrix.map(region);
+ if (curClip->hasRectClip)
+ newClip->setClipRegion(r & curClip->clipRect);
+ else if (curClip->hasRegionClip)
+ newClip->setClipRegion(r & clip->clipRegion);
+
+ qrasterpaintengine_dirty_clip(d, s);
+ }
}
/*!
@@ -1411,7 +1444,7 @@ static void fillRect_normalized(const QRect &r, QSpanData *data,
{
int x1, x2, y1, y2;
- bool rectClipped = false;
+ bool rectClipped = true;
if (data->clip) {
x1 = qMax(r.x(), data->clip->xmin);
@@ -1741,12 +1774,17 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline QRect toNormalizedFillRect(const QRectF &rect)
{
- const int x1 = qRound(rect.x() + aliasedCoordinateDelta);
- const int y1 = qRound(rect.y() + aliasedCoordinateDelta);
- const int x2 = qRound(rect.right() + aliasedCoordinateDelta);
- const int y2 = qRound(rect.bottom() + aliasedCoordinateDelta);
+ int x1 = int(rect.x() + aliasedCoordinateDelta);
+ int y1 = int(rect.y() + aliasedCoordinateDelta);
+ int x2 = int(rect.right() + aliasedCoordinateDelta);
+ int y2 = int(rect.bottom() + aliasedCoordinateDelta);
+
+ if (x2 < x1)
+ qSwap(x1, x2);
+ if (y2 < y1)
+ qSwap(y1, y2);
- return QRect(x1, y1, x2 - x1, y2 - y1).normalized();
+ return QRect(x1, y1, x2 - x1, y2 - y1);
}
/*!
@@ -1817,8 +1855,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
}
// ### Optimize for non transformed ellipses and rectangles...
- QRealRect r = path.controlPointRect();
- QRectF cpRect(r.x1, r.y1, r.x2 - r.x1, r.y2 - r.y1);
+ QRectF cpRect = path.controlPointRect();
const QRect deviceRect = s->matrix.mapRect(cpRect).toRect();
ProcessSpans blend = d->getBrushFunc(deviceRect, &s->brushData);
@@ -1906,9 +1943,12 @@ void QRasterPaintEngine::fillRect(const QRectF &r, const QColor &color)
QRasterPaintEngineState *s = state();
d->solid_color_filler.solid.color = PREMUL(ARGB_COMBINE_ALPHA(color.rgba(), s->intOpacity));
+ if ((d->solid_color_filler.solid.color & 0xff000000) == 0
+ && s->composition_mode == QPainter::CompositionMode_SourceOver) {
+ return;
+ }
d->solid_color_filler.clip = d->clip();
d->solid_color_filler.adjustSpanMethods();
-
fillRect(r, &d->solid_color_filler);
}
@@ -3075,7 +3115,7 @@ bool QRasterPaintEnginePrivate::isUnclipped_normalized(const QRect &r) const
if (cl->clipRect == deviceRect)
return true;
- if (cl->hasRegionClip) {
+ if (cl->hasRectClip) {
// inline contains() for performance (we know the rects are normalized)
const QRect &r1 = cl->clipRect;
return (r.left() >= r1.left() && r.right() <= r1.right()
@@ -3204,7 +3244,7 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte
// ### cases we should delegate painting to the font engine
// ### directly...
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
QFontEngine::Type fontEngineType = ti.fontEngine->type();
// qDebug() << "type" << fontEngineType << s->matrix.type();
if ((fontEngineType == QFontEngine::Win && !((QFontEngineWin *) ti.fontEngine)->ttf && s->matrix.type() > QTransform::TxTranslate)
@@ -4280,7 +4320,7 @@ QClipData::QClipData(int height)
clipSpanHeight = height;
m_clipLines = 0;
- allocated = height;
+ allocated = 0;
m_spans = 0;
xmin = xmax = ymin = ymax = 0;
count = 0;
@@ -4302,10 +4342,13 @@ void QClipData::initialize()
if (m_spans)
return;
- m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
+ if (!m_clipLines)
+ m_clipLines = (ClipLine *)calloc(sizeof(ClipLine), clipSpanHeight);
+
Q_CHECK_PTR(m_clipLines);
QT_TRY {
m_spans = (QSpan *)malloc(clipSpanHeight*sizeof(QSpan));
+ allocated = clipSpanHeight;
Q_CHECK_PTR(m_spans);
QT_TRY {
@@ -4422,20 +4465,37 @@ void QClipData::fixup()
ymax = m_spans[count-1].y + 1;
xmin = INT_MAX;
xmax = 0;
+
+ bool isRect = true;
+ int left = m_spans[0].x;
+ int right = m_spans[0].x + m_spans[0].len;
+
for (int i = 0; i < count; ++i) {
-// qDebug() << " " << spans[i].x << spans[i].y << spans[i].len << spans[i].coverage;
if (m_spans[i].y != y) {
+ if (m_spans[i].y != y + 1 && y != -1) {
+ isRect = false;
+ }
y = m_spans[i].y;
m_clipLines[y].spans = m_spans+i;
m_clipLines[y].count = 0;
// qDebug() << " new line: y=" << y;
}
++m_clipLines[y].count;
+ int sl = (int) m_spans[i].x;
+ int sr = sl + m_spans[i].len;
+
xmin = qMin(xmin, (int)m_spans[i].x);
xmax = qMax(xmax, (int)m_spans[i].x + m_spans[i].len);
+
+ if (sl != left || sr != right)
+ isRect = false;
+ }
+// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d %s", xmin, xmax, ymin, ymax, isRect ? "rectangular" : "");
+
+ if (isRect) {
+ hasRectClip = true;
+ clipRect.setRect(xmin, ymin, xmax - xmin, ymax - ymin);
}
- ++xmax;
-// qDebug("xmin=%d,xmax=%d,ymin=%d,ymax=%d", xmin, xmax, ymin, ymax);
}
/*
@@ -4443,11 +4503,12 @@ void QClipData::fixup()
*/
void QClipData::setClipRect(const QRect &rect)
{
- if (rect == clipRect)
+ if (hasRectClip && rect == clipRect)
return;
// qDebug() << "setClipRect" << clipSpanHeight << count << allocated << rect;
hasRectClip = true;
+ hasRegionClip = false;
clipRect = rect;
xmin = rect.x();
@@ -4456,7 +4517,7 @@ void QClipData::setClipRect(const QRect &rect)
ymax = qMin(rect.y() + rect.height(), clipSpanHeight);
if (m_spans) {
- delete m_spans;
+ free(m_spans);
m_spans = 0;
}
@@ -4474,6 +4535,7 @@ void QClipData::setClipRegion(const QRegion &region)
}
hasRegionClip = true;
+ hasRectClip = false;
clipRegion = region;
{ // set bounding rect
@@ -4485,7 +4547,7 @@ void QClipData::setClipRegion(const QRegion &region)
}
if (m_spans) {
- delete m_spans;
+ free(m_spans);
m_spans = 0;
}
@@ -4733,29 +4795,6 @@ static void qt_span_fill_clipRect(int count, const QSpan *spans,
fillData->unclipped_blend(count, spans, fillData);
}
-static void qt_span_fill_clipRegion(int count, const QSpan *spans,
- void *userData)
-{
- QSpanData *fillData = reinterpret_cast<QSpanData *>(userData);
- Q_ASSERT(fillData->blend && fillData->unclipped_blend);
-
- Q_ASSERT(fillData->clip);
- Q_ASSERT(!fillData->clip->clipRegion.isEmpty());
-
- const int NSPANS = 256;
- QSpan cspans[NSPANS];
- int currentClip = 0;
- while (currentClip < count) {
- const int unclipped = qt_intersect_spans(const_cast<QSpan*>(spans),
- count, &currentClip,
- &cspans[0], NSPANS,
- fillData->clip->clipRegion);
- if (unclipped > 0)
- fillData->unclipped_blend(unclipped, cspans, fillData);
- }
-
-}
-
static void qt_span_clip(int count, const QSpan *spans, void *userData)
{
ClipData *clipData = reinterpret_cast<ClipData *>(userData);
@@ -5030,7 +5069,7 @@ void QSpanData::init(QRasterBuffer *rb, const QRasterPaintEngine *pe)
extern QImage qt_imageForBrush(int brushStyle, bool invert);
-void QSpanData::setup(const QBrush &brush, int alpha)
+void QSpanData::setup(const QBrush &brush, int alpha, QPainter::CompositionMode compositionMode)
{
Qt::BrushStyle brushStyle = qbrush_style(brush);
switch (brushStyle) {
@@ -5038,6 +5077,10 @@ void QSpanData::setup(const QBrush &brush, int alpha)
type = Solid;
QColor c = qbrush_color(brush);
solid.color = PREMUL(ARGB_COMBINE_ALPHA(c.rgba(), alpha));
+ if ((solid.color & 0xff000000) == 0
+ && compositionMode == QPainter::CompositionMode_SourceOver) {
+ type = None;
+ }
break;
}
@@ -5178,8 +5221,6 @@ void QSpanData::adjustSpanMethods()
blend = unclipped_blend;
} else if (clip->hasRectClip) {
blend = clip->clipRect.isEmpty() ? 0 : qt_span_fill_clipRect;
- } else if (clip->hasRegionClip) {
- blend = clip->clipRegion.isEmpty() ? 0 : qt_span_fill_clipRegion;
} else {
blend = qt_span_fill_clipped;
}
@@ -6160,7 +6201,7 @@ void dumpClip(int width, int height, QClipData *clip)
int y1 = 0;
for (int i = 0; i < clip->count; ++i) {
- QSpan *span = clip->spans + i;
+ QSpan *span = clip->spans() + i;
for (int j = 0; j < span->len; ++j)
clipImg.setPixel(span->x + j, span->y, 0xffffff00);
x0 = qMin(x0, int(span->x));
@@ -6178,7 +6219,7 @@ void dumpClip(int width, int height, QClipData *clip)
Q_ASSERT(x1 >= 0);
fprintf(stderr,"clip %d: %d %d - %d %d\n", counter, x0, y0, x1, y1);
- clipImg.save(QString(QLatin1String("clip-%0.png")).arg(counter++));
+ clipImg.save(QString::fromLatin1("clip-%0.png").arg(counter++));
}
#endif
diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h
index 26a2b3f..1f3f006 100644
--- a/src/gui/painting/qpaintengine_raster_p.h
+++ b/src/gui/painting/qpaintengine_raster_p.h
@@ -202,7 +202,6 @@ public:
void clip(const QVectorPath &path, Qt::ClipOperation op);
void clip(const QRect &rect, Qt::ClipOperation op);
void clip(const QRegion &region, Qt::ClipOperation op);
- void clip(const QPainterPath &path, Qt::ClipOperation op);
enum ClipType {
RectClip,
diff --git a/src/gui/painting/qpaintengine_x11_p.h b/src/gui/painting/qpaintengine_x11_p.h
index f277eeb..f3dd283 100644
--- a/src/gui/painting/qpaintengine_x11_p.h
+++ b/src/gui/painting/qpaintengine_x11_p.h
@@ -153,6 +153,7 @@ public:
txop = QTransform::TxNone;
has_clipping = false;
render_hints = 0;
+ xform_scale = 1;
#ifndef QT_NO_XRENDER
tessellator = 0;
#endif
diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp
index 8eaad60..222e29f 100644
--- a/src/gui/painting/qpaintengineex.cpp
+++ b/src/gui/painting/qpaintengineex.cpp
@@ -56,15 +56,15 @@ QT_BEGIN_NAMESPACE
*
*/
-const QRealRect &QVectorPath::controlPointRect() const
+QRectF QVectorPath::controlPointRect() const
{
if (m_hints & ControlPointRect)
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
if (m_count == 0) {
m_cp_rect.x1 = m_cp_rect.x2 = m_cp_rect.y1 = m_cp_rect.y2 = 0;
m_hints |= ControlPointRect;
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
}
Q_ASSERT(m_points && m_count > 0);
@@ -88,7 +88,7 @@ const QRealRect &QVectorPath::controlPointRect() const
}
m_hints |= ControlPointRect;
- return m_cp_rect;
+ return QRectF(QPointF(m_cp_rect.x1, m_cp_rect.y1), QPointF(m_cp_rect.x2, m_cp_rect.y2));
}
const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
@@ -100,12 +100,10 @@ const QVectorPath &qtVectorPathForPath(const QPainterPath &path)
#ifndef QT_NO_DEBUG_STREAM
QDebug Q_GUI_EXPORT &operator<<(QDebug &s, const QVectorPath &path)
{
- QRealRect vectorPathBounds = path.controlPointRect();
- QRectF rf(vectorPathBounds.x1, vectorPathBounds.y1,
- vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1);
+ QRectF rf = path.controlPointRect();
s << "QVectorPath(size:" << path.elementCount()
<< " hints:" << hex << path.hints()
- << rf << ")";
+ << rf << ')';
return s;
}
#endif
@@ -138,6 +136,71 @@ QPaintEngineExPrivate::~QPaintEngineExPrivate()
}
+void QPaintEngineExPrivate::replayClipOperations()
+{
+ Q_Q(QPaintEngineEx);
+
+ QPainter *p = q->painter();
+ if (!p || !p->d_ptr)
+ return;
+
+ QPainterPrivate *pp = p->d_ptr;
+ QList<QPainterClipInfo> clipInfo = pp->state->clipInfo;
+
+ QTransform transform = q->state()->matrix;
+
+ for (int i = 0; i < clipInfo.size(); ++i) {
+ const QPainterClipInfo &info = clipInfo.at(i);
+
+ if (info.matrix != q->state()->matrix) {
+ q->state()->matrix = info.matrix;
+ q->transformChanged();
+ }
+
+ switch (info.clipType) {
+ case QPainterClipInfo::RegionClip:
+ q->clip(info.region, info.operation);
+ break;
+ case QPainterClipInfo::PathClip:
+ q->clip(info.path, info.operation);
+ break;
+ case QPainterClipInfo::RectClip:
+ q->clip(info.rect, info.operation);
+ break;
+ case QPainterClipInfo::RectFClip: {
+ qreal right = info.rectf.x() + info.rectf.width();
+ qreal bottom = info.rectf.y() + info.rectf.height();
+ qreal pts[] = { info.rectf.x(), info.rectf.y(),
+ right, info.rectf.y(),
+ right, bottom,
+ info.rectf.x(), bottom };
+ QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
+ q->clip(vp, info.operation);
+ break;
+ }
+ }
+ }
+
+ if (transform != q->state()->matrix) {
+ q->state()->matrix = transform;
+ q->transformChanged();
+ }
+}
+
+
+bool QPaintEngineExPrivate::hasClipOperations() const
+{
+ Q_Q(const QPaintEngineEx);
+
+ QPainter *p = q->painter();
+ if (!p || !p->d_ptr)
+ return false;
+
+ QPainterPrivate *pp = p->d_ptr;
+ QList<QPainterClipInfo> clipInfo = pp->state->clipInfo;
+
+ return !clipInfo.isEmpty();
+}
/*******************************************************************************
*
@@ -244,13 +307,18 @@ static void qpaintengineex_cubicTo(qreal c1x, qreal c1y, qreal c2x, qreal c2y, q
((StrokeHandler *) data)->types.add(QPainterPath::CurveToDataElement);
}
+QPaintEngineEx::QPaintEngineEx()
+ : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures)
+{
+ extended = true;
+}
+
QPaintEngineEx::QPaintEngineEx(QPaintEngineExPrivate &data)
: QPaintEngine(data, AllFeatures)
{
extended = true;
}
-
QPainterState *QPaintEngineEx::createState(QPainterState *orig) const
{
if (!orig)
@@ -483,6 +551,9 @@ void QPaintEngineEx::clip(const QRect &r, Qt::ClipOperation op)
void QPaintEngineEx::clip(const QRegion &region, Qt::ClipOperation op)
{
+ if (region.numRects() == 1)
+ clip(region.boundingRect(), op);
+
QVector<QRect> rects = region.rects();
if (rects.size() <= 32) {
qreal pts[2*32*4];
@@ -778,7 +849,7 @@ void QPaintEngineEx::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, con
{
QBrush brush(state()->pen.color(), pixmap);
QTransform xform;
- xform.translate(-s.x(), -s.y());
+ xform.translate(r.x() - s.x(), r.y() - s.y());
brush.setTransform(xform);
qreal pts[] = { r.x(), r.y(),
diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h
index 593726c..3f64260 100644
--- a/src/gui/painting/qpaintengineex_p.h
+++ b/src/gui/painting/qpaintengineex_p.h
@@ -139,27 +139,13 @@ public:
QDebug Q_GUI_EXPORT &operator<<(QDebug &, const QVectorPath &path);
#endif
-class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate
-{
-public:
- QPaintEngineExPrivate();
- ~QPaintEngineExPrivate();
-
- QStroker stroker;
- QDashStroker dasher;
- StrokeHandler *strokeHandler;
- QStrokerOps *activeStroker;
- QPen strokerPen;
-};
-
class QPixmapFilter;
class Q_GUI_EXPORT QPaintEngineEx : public QPaintEngine
{
Q_DECLARE_PRIVATE(QPaintEngineEx)
public:
- inline QPaintEngineEx()
- : QPaintEngine(*new QPaintEngineExPrivate, AllFeatures) { extended = true; }
+ QPaintEngineEx();
virtual QPainterState *createState(QPainterState *orig) const;
@@ -216,12 +202,30 @@ public:
inline QPainterState *state() { return static_cast<QPainterState *>(QPaintEngine::state); }
inline const QPainterState *state() const { return static_cast<const QPainterState *>(QPaintEngine::state); }
+ virtual void sync() {}
+
virtual QPixmapFilter *createPixmapFilter(int /*type*/) const { return 0; }
protected:
QPaintEngineEx(QPaintEngineExPrivate &data);
};
+class Q_GUI_EXPORT QPaintEngineExPrivate : public QPaintEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QPaintEngineEx)
+public:
+ QPaintEngineExPrivate();
+ ~QPaintEngineExPrivate();
+
+ void replayClipOperations();
+ bool hasClipOperations() const;
+
+ QStroker stroker;
+ QDashStroker dasher;
+ StrokeHandler *strokeHandler;
+ QStrokerOps *activeStroker;
+ QPen strokerPen;
+};
inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) {
switch (mode) {
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 0caf13b..18361d8 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -299,10 +299,14 @@ bool QPainterPrivate::attachPainterPrivate(QPainter *q, QPaintDevice *pdev)
q->d_ptr->state->wh = q->d_ptr->state->vh = widget->height();
// Update matrix.
- if (q->d_ptr->state->WxF)
- q->d_ptr->state->worldMatrix.translate(-offset.x(), -offset.y());
- else
- q->d_ptr->state->redirection_offset = offset;
+ if (q->d_ptr->state->WxF) {
+ q->d_ptr->state->redirectionMatrix *= q->d_ptr->state->worldMatrix;
+ q->d_ptr->state->redirectionMatrix.translate(-offset.x(), -offset.y());
+ q->d_ptr->state->worldMatrix = QTransform();
+ q->d_ptr->state->WxF = false;
+ } else {
+ q->d_ptr->state->redirectionMatrix = QTransform::fromTranslate(-offset.x(), -offset.y());
+ }
q->d_ptr->updateMatrix();
QPaintEnginePrivate *enginePrivate = q->d_ptr->engine->d_func();
@@ -428,7 +432,7 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio
bool old_txinv = txinv;
QTransform old_invMatrix = invMatrix;
txinv = true;
- invMatrix = QTransform().translate(-state->redirection_offset.x(), -state->redirection_offset.y());
+ invMatrix = QTransform();
QPainterPath clipPath = q->clipPath();
QRectF r = clipPath.boundingRect().intersected(absPathRect);
absPathRect = r.toAlignedRect();
@@ -652,20 +656,7 @@ void QPainterPrivate::updateMatrix()
state->matrix *= viewTransform();
txinv = false; // no inverted matrix
- if (!state->redirection_offset.isNull()) {
- // We want to translate in dev space so we do the adding of the redirection
- // offset manually.
- if (state->matrix.isAffine()) {
- state->matrix = QTransform(state->matrix.m11(), state->matrix.m12(),
- state->matrix.m21(), state->matrix.m22(),
- state->matrix.dx()-state->redirection_offset.x(),
- state->matrix.dy()-state->redirection_offset.y());
- } else {
- QTransform temp;
- temp.translate(-state->redirection_offset.x(), -state->redirection_offset.y());
- state->matrix *= temp;
- }
- }
+ state->matrix *= state->redirectionMatrix;
if (extended)
extended->transformChanged();
else
@@ -680,18 +671,7 @@ void QPainterPrivate::updateInvMatrix()
{
Q_ASSERT(txinv == false);
txinv = true; // creating inverted matrix
- QTransform m;
-
- if (state->VxF)
- m = viewTransform();
-
- if (state->WxF) {
- if (state->VxF)
- m = state->worldMatrix * m;
- else
- m = state->worldMatrix;
- }
- invMatrix = m.inverted(); // invert matrix
+ invMatrix = state->matrix.inverted();
}
void QPainterPrivate::updateEmulationSpecifier(QPainterState *s)
@@ -1592,10 +1572,8 @@ void QPainter::restore()
// replay the list of clip states,
for (int i=0; i<d->state->clipInfo.size(); ++i) {
const QPainterClipInfo &info = d->state->clipInfo.at(i);
- tmp->matrix.setMatrix(info.matrix.m11(), info.matrix.m12(), info.matrix.m13(),
- info.matrix.m21(), info.matrix.m22(), info.matrix.m23(),
- info.matrix.dx() - d->state->redirection_offset.x(),
- info.matrix.dy() - d->state->redirection_offset.y(), info.matrix.m33());
+ tmp->matrix = info.matrix;
+ tmp->matrix *= d->state->redirectionMatrix;
tmp->clipOperation = info.operation;
if (info.clipType == QPainterClipInfo::RectClip) {
tmp->dirtyFlags = QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyTransform;
@@ -1709,7 +1687,7 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->painter = this;
d->states.push_back(d->state);
- d->state->redirection_offset = redirectionOffset;
+ d->state->redirectionMatrix.translate(-redirectionOffset.x(), -redirectionOffset.y());
d->state->brushOrigin = QPointF();
if (!d->engine) {
@@ -1743,7 +1721,8 @@ bool QPainter::begin(QPaintDevice *pd)
// Adjust offset for alien widgets painting outside the paint event.
if (!inPaintEvent && paintOutsidePaintEvent && !widget->internalWinId()
&& widget->testAttribute(Qt::WA_WState_Created)) {
- d->state->redirection_offset -= widget->mapTo(widget->nativeParentWidget(), QPoint());
+ const QPoint offset = widget->mapTo(widget->nativeParentWidget(), QPoint());
+ d->state->redirectionMatrix.translate(offset.x(), offset.y());
}
break;
}
@@ -1825,11 +1804,12 @@ bool QPainter::begin(QPaintDevice *pd)
d->state->wh = d->state->vh = pd->metric(QPaintDevice::PdmHeight);
}
- d->state->redirection_offset += d->engine->coordinateOffset();
+ const QPoint coordinateOffset = d->engine->coordinateOffset();
+ d->state->redirectionMatrix.translate(-coordinateOffset.x(), -coordinateOffset.y());
Q_ASSERT(d->engine->isActive());
- if (!d->state->redirection_offset.isNull())
+ if (!d->state->redirectionMatrix.isIdentity())
d->updateMatrix();
Q_ASSERT(d->engine->isActive());
@@ -2598,7 +2578,7 @@ void QPainter::setClipRect(const QRectF &rect, Qt::ClipOperation op)
QVectorPath vp(pts, 4, 0, QVectorPath::RectangleHint);
d->state->clipEnabled = true;
d->extended->clip(vp, op);
- d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -2641,7 +2621,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
if (d->extended) {
d->state->clipEnabled = true;
d->extended->clip(rect, op);
- d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -2653,7 +2633,7 @@ void QPainter::setClipRect(const QRect &rect, Qt::ClipOperation op)
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
d->state->clipInfo.clear();
- d->state->clipInfo << QPainterClipInfo(rect, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(rect, op, d->state->matrix);
d->state->clipEnabled = true;
d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
d->updateState(d->state);
@@ -2694,7 +2674,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
if (d->extended) {
d->state->clipEnabled = true;
d->extended->clip(r, op);
- d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -2706,7 +2686,7 @@ void QPainter::setClipRegion(const QRegion &r, Qt::ClipOperation op)
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
d->state->clipInfo.clear();
- d->state->clipInfo << QPainterClipInfo(r, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(r, op, d->state->matrix);
d->state->clipEnabled = true;
d->state->dirtyFlags |= QPaintEngine::DirtyClipRegion | QPaintEngine::DirtyClipEnabled;
d->updateState(d->state);
@@ -3091,7 +3071,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
if (d->extended) {
d->state->clipEnabled = true;
d->extended->clip(path, op);
- d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
d->state->clipOperation = op;
return;
}
@@ -3105,7 +3085,7 @@ void QPainter::setClipPath(const QPainterPath &path, Qt::ClipOperation op)
d->state->clipOperation = op;
if (op == Qt::NoClip || op == Qt::ReplaceClip)
d->state->clipInfo.clear();
- d->state->clipInfo << QPainterClipInfo(path, op, combinedTransform());
+ d->state->clipInfo << QPainterClipInfo(path, op, d->state->matrix);
d->state->clipEnabled = true;
d->state->dirtyFlags |= QPaintEngine::DirtyClipPath | QPaintEngine::DirtyClipEnabled;
d->updateState(d->state);
@@ -6102,22 +6082,22 @@ void QPainter::drawTextItem(const QPointF &p, const QTextItem &_ti)
const QTransform &m = d->state->matrix;
if (d->state->matrix.type() < QTransform::TxShear) {
bool isPlain90DegreeRotation =
- (qFuzzyCompare(m.m11() + 1, qreal(1))
- && qFuzzyCompare(m.m12(), qreal(1))
- && qFuzzyCompare(m.m21(), qreal(-1))
- && qFuzzyCompare(m.m22() + 1, qreal(1))
+ (qFuzzyIsNull(m.m11())
+ && qFuzzyIsNull(m.m12() - qreal(1))
+ && qFuzzyIsNull(m.m21() + qreal(1))
+ && qFuzzyIsNull(m.m22())
)
||
- (qFuzzyCompare(m.m11(), qreal(-1))
- && qFuzzyCompare(m.m12() + 1, qreal(1))
- && qFuzzyCompare(m.m21() + 1, qreal(1))
- && qFuzzyCompare(m.m22(), qreal(-1))
+ (qFuzzyIsNull(m.m11() + qreal(1))
+ && qFuzzyIsNull(m.m12())
+ && qFuzzyIsNull(m.m21())
+ && qFuzzyIsNull(m.m22() + qreal(1))
)
||
- (qFuzzyCompare(m.m11() + 1, qreal(1))
- && qFuzzyCompare(m.m12(), qreal(-1))
- && qFuzzyCompare(m.m21(), qreal(1))
- && qFuzzyCompare(m.m22() + 1, qreal(1))
+ (qFuzzyIsNull(m.m11())
+ && qFuzzyIsNull(m.m12() + qreal(1))
+ && qFuzzyIsNull(m.m21() - qreal(1))
+ && qFuzzyIsNull(m.m22())
)
;
aa = !isPlain90DegreeRotation;
@@ -7737,7 +7717,7 @@ QPainterState::QPainterState(const QPainterState *s)
clipRegion(s->clipRegion), clipPath(s->clipPath),
clipOperation(s->clipOperation),
renderHints(s->renderHints), clipInfo(s->clipInfo),
- worldMatrix(s->worldMatrix), matrix(s->matrix), redirection_offset(s->redirection_offset),
+ worldMatrix(s->worldMatrix), matrix(s->matrix), redirectionMatrix(s->redirectionMatrix),
wx(s->wx), wy(s->wy), ww(s->ww), wh(s->wh),
vx(s->vx), vy(s->vy), vw(s->vw), vh(s->vh),
opacity(s->opacity), WxF(s->WxF), VxF(s->VxF),
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index d8c6980..4ca8923 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -510,6 +510,7 @@ private:
friend class QFontEngineXLFD;
friend class QWSManager;
friend class QPaintEngine;
+ friend class QPaintEngineExPrivate;
friend class QOpenGLPaintEngine;
friend class QX11PaintEngine;
friend class QX11PaintEnginePrivate;
diff --git a/src/gui/painting/qpainter_p.h b/src/gui/painting/qpainter_p.h
index 258b25a..8d4e6c5 100644
--- a/src/gui/painting/qpainter_p.h
+++ b/src/gui/painting/qpainter_p.h
@@ -92,8 +92,8 @@ inline Qt::PenJoinStyle qpen_joinStyle(const QPen &p) { return data_ptr(p)->join
// QBrush inline functions...
inline QBrush::DataPtr &data_ptr(const QBrush &p) { return const_cast<QBrush &>(p).data_ptr(); }
inline bool qbrush_fast_equals(const QBrush &a, const QBrush &b) { return data_ptr(a) == data_ptr(b); }
-inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; };
-inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; };
+inline Qt::BrushStyle qbrush_style(const QBrush &b) { return data_ptr(b)->style; }
+inline const QColor &qbrush_color(const QBrush &b) { return data_ptr(b)->color; }
inline bool qbrush_has_transform(const QBrush &b) { return data_ptr(b)->transform.type() > QTransform::TxNone; }
class QPainterClipInfo
@@ -158,7 +158,7 @@ public:
QList<QPainterClipInfo> clipInfo; // ### Make me smaller and faster to copy around...
QTransform worldMatrix; // World transformation matrix, not window and viewport
QTransform matrix; // Complete transformation matrix,
- QPoint redirection_offset;
+ QTransform redirectionMatrix;
int wx, wy, ww, wh; // window rectangle
int vx, vy, vw, vh; // viewport rectangle
qreal opacity;
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 635218e..57fa979 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -1309,10 +1309,10 @@ static QRectF qt_painterpath_bezier_extrema(const QBezier &b)
qreal bx = QT_BEZIER_B(b, x);
qreal cx = QT_BEZIER_C(b, x);
// specialcase quadratic curves to avoid div by zero
- if (qFuzzyCompare(ax + 1, 1)) {
+ if (qFuzzyIsNull(ax)) {
// linear curves are covered by initialization.
- if (!qFuzzyCompare(bx + 1, 1)) {
+ if (!qFuzzyIsNull(bx)) {
qreal t = -cx / bx;
QT_BEZIER_CHECK_T(b, t);
}
@@ -1339,10 +1339,10 @@ static QRectF qt_painterpath_bezier_extrema(const QBezier &b)
qreal cy = QT_BEZIER_C(b, y);
// specialcase quadratic curves to avoid div by zero
- if (qFuzzyCompare(ay + 1, 1)) {
+ if (qFuzzyIsNull(ay)) {
// linear curves are covered by initialization.
- if (!qFuzzyCompare(by + 1, 1)) {
+ if (!qFuzzyIsNull(by)) {
qreal t = -cy / by;
QT_BEZIER_CHECK_T(b, t);
}
@@ -2010,7 +2010,63 @@ bool QPainterPath::intersects(const QRectF &rect) const
return false;
}
+/*!
+ Translates all elements in the path by (\a{dx}, \a{dy}).
+
+ \since 4.6
+ \sa translated()
+*/
+void QPainterPath::translate(qreal dx, qreal dy)
+{
+ if (!d_ptr || (dx == 0 && dy == 0))
+ return;
+ int elementsLeft = d_ptr->elements.size();
+ if (elementsLeft <= 0)
+ return;
+
+ detach();
+ QPainterPath::Element *element = d_func()->elements.data();
+ Q_ASSERT(element);
+ while (elementsLeft--) {
+ element->x += dx;
+ element->y += dy;
+ ++element;
+ }
+}
+
+/*!
+ \fn void QPainterPath::translate(const QPointF &offset)
+ \overload
+ \since 4.6
+
+ Translates all elements in the path by the given \a offset.
+
+ \sa translated()
+*/
+
+/*!
+ Returns a copy of the path that is translated by (\a{dx}, \a{dy}).
+
+ \since 4.6
+ \sa translate()
+*/
+QPainterPath QPainterPath::translated(qreal dx, qreal dy) const
+{
+ QPainterPath copy(*this);
+ copy.translate(dx, dy);
+ return copy;
+}
+
+/*!
+ \fn QPainterPath QPainterPath::translated(const QPointF &offset) const;
+ \overload
+ \since 4.6
+
+ Returns a copy of the path that is translated by the given \a offset.
+
+ \sa translate()
+*/
/*!
\fn bool QPainterPath::contains(const QRectF &rectangle) const
@@ -2320,7 +2376,7 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
p.d_func()->dirtyControlBounds = true;
return s;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*******************************************************************************
@@ -2876,7 +2932,7 @@ qreal QPainterPath::angleAtPercent(qreal t) const
return QLineF(0, 0, m1, m2).angle();
}
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#pragma warning( disable : 4056 4756 )
#endif
@@ -3301,7 +3357,7 @@ QDebug operator<<(QDebug s, const QPainterPath &p)
s.nospace() << "QPainterPath: Element count=" << p.elementCount() << endl;
const char *types[] = {"MoveTo", "LineTo", "CurveTo", "CurveToData"};
for (int i=0; i<p.elementCount(); ++i) {
- s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ")" << endl;
+ s.nospace() << " -> " << types[p.elementAt(i).type] << "(x=" << p.elementAt(i).x << ", y=" << p.elementAt(i).y << ')' << endl;
}
return s;
diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h
index e12194e..cb3347a 100644
--- a/src/gui/painting/qpainterpath.h
+++ b/src/gui/painting/qpainterpath.h
@@ -149,6 +149,12 @@ public:
bool contains(const QRectF &rect) const;
bool intersects(const QRectF &rect) const;
+ void translate(qreal dx, qreal dy);
+ inline void translate(const QPointF &offset);
+
+ QPainterPath translated(qreal dx, qreal dy) const;
+ inline QPainterPath translated(const QPointF &offset) const;
+
QRectF boundingRect() const;
QRectF controlPointRect() const;
@@ -368,6 +374,12 @@ inline void QPainterPath::addText(qreal x, qreal y, const QFont &f, const QStrin
addText(QPointF(x, y), f, text);
}
+inline void QPainterPath::translate(const QPointF &offset)
+{ translate(offset.x(), offset.y()); }
+
+inline QPainterPath QPainterPath::translated(const QPointF &offset) const
+{ return translated(offset.x(), offset.y()); }
+
inline bool QPainterPath::isEmpty() const
{
return !d_ptr || (d_ptr->elements.size() == 1 && d_ptr->elements.first().type == MoveToElement);
diff --git a/src/gui/painting/qpainterpath_p.h b/src/gui/painting/qpainterpath_p.h
index 29c48df..6fb439d 100644
--- a/src/gui/painting/qpainterpath_p.h
+++ b/src/gui/painting/qpainterpath_p.h
@@ -124,7 +124,7 @@ private:
Q_DISABLE_COPY(QVectorPathConverter)
};
-class Q_GUI_EXPORT QPainterPathData : public QPainterPathPrivate
+class QPainterPathData : public QPainterPathPrivate
{
public:
QPainterPathData() :
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 297cdd3..9ef3eb7 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -138,11 +138,11 @@ bool QIntersectionFinder::linesIntersect(const QLineF &a, const QLineF &b) const
const qreal par = pDelta.x() * qDelta.y() - pDelta.y() * qDelta.x();
- if (qFuzzyCompare(par + 1, 1)) {
+ if (qFuzzyIsNull(par)) {
const QPointF normal(-pDelta.y(), pDelta.x());
// coinciding?
- if (qFuzzyCompare(dot(normal, q1 - p1) + 1, 1)) {
+ if (qFuzzyIsNull(dot(normal, q1 - p1))) {
const qreal dp = dot(pDelta, pDelta);
const qreal tq1 = dot(pDelta, q1 - p1);
@@ -202,13 +202,13 @@ void QIntersectionFinder::intersectBeziers(const QBezier &one, const QBezier &tw
qreal alpha_q = t.at(i).second;
QPointF pt;
- if (qFuzzyCompare(alpha_p + 1, 1)) {
+ if (qFuzzyIsNull(alpha_p)) {
pt = one.pt1();
- } else if (qFuzzyCompare(alpha_p, 1)) {
+ } else if (qFuzzyIsNull(alpha_p - 1)) {
pt = one.pt4();
- } else if (qFuzzyCompare(alpha_q + 1, 1)) {
+ } else if (qFuzzyIsNull(alpha_q)) {
pt = two.pt1();
- } else if (qFuzzyCompare(alpha_q, 1)) {
+ } else if (qFuzzyIsNull(alpha_q - 1)) {
pt = two.pt4();
} else {
pt = one.pointAt(alpha_p);
@@ -250,11 +250,11 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData
const qreal par = pDelta.x() * qDelta.y() - pDelta.y() * qDelta.x();
- if (qFuzzyCompare(par + 1, 1)) {
+ if (qFuzzyIsNull(par)) {
const QPointF normal(-pDelta.y(), pDelta.x());
// coinciding?
- if (qFuzzyCompare(dot(normal, q1 - p1) + 1, 1)) {
+ if (qFuzzyIsNull(dot(normal, q1 - p1))) {
const qreal invDp = 1 / dot(pDelta, pDelta);
const qreal tq1 = dot(pDelta, q1 - p1) * invDp;
@@ -315,11 +315,11 @@ void QIntersectionFinder::intersectLines(const QLineF &a, const QLineF &b, QData
if (tp<0 || tp>1 || tq<0 || tq>1)
return;
- const bool p_zero = qFuzzyCompare(tp + 1, 1);
- const bool p_one = qFuzzyCompare(tp, 1);
+ const bool p_zero = qFuzzyIsNull(tp);
+ const bool p_one = qFuzzyIsNull(tp - 1);
- const bool q_zero = qFuzzyCompare(tq + 1, 1);
- const bool q_one = qFuzzyCompare(tq, 1);
+ const bool q_zero = qFuzzyIsNull(tq);
+ const bool q_one = qFuzzyIsNull(tq - 1);
if ((q_zero || q_one) && (p_zero || p_one))
return;
@@ -922,7 +922,7 @@ qreal QWingedEdge::delta(int vertex, int a, int b) const
qreal result = b_angle - a_angle;
- if (qFuzzyCompare(result + 1, 1) || qFuzzyCompare(result, 128))
+ if (qFuzzyIsNull(result) || qFuzzyCompare(result, 128))
return 0;
if (result < 0)
@@ -951,7 +951,7 @@ static inline QPointF tangentAt(const QWingedEdge &list, int vi, int ei)
if (ep->bezier) {
normal = ep->bezier->derivedAt(t);
- if (qFuzzyCompare(normal.x() + 1, 1) && qFuzzyCompare(normal.y() + 1, 1))
+ if (qFuzzyIsNull(normal.x()) && qFuzzyIsNull(normal.y()))
normal = ep->bezier->secondDerivedAt(t);
} else {
const QPointF a = *list.vertex(ep->first);
@@ -1080,7 +1080,7 @@ QWingedEdge::TraversalStatus QWingedEdge::findInsertStatus(int vi, int ei) const
qDebug() << "Delta to edge" << status.edge << d2 << ", angles: " << op->angle << op->invAngle;
#endif
- if (!(qFuzzyCompare(d2 + 1, 1) && isLeftOf(*this, vi, status.edge, ei))
+ if (!(qFuzzyIsNull(d2) && isLeftOf(*this, vi, status.edge, ei))
&& (d2 < d || (qFuzzyCompare(d2, d) && isLeftOf(*this, vi, status.edge, position)))) {
position = status.edge;
d = d2;
@@ -1232,10 +1232,10 @@ int QWingedEdge::addEdge(int fi, int si, const QBezier *bezier, qreal t0, qreal
QPointF aTangent = bezier->derivedAt(t0);
QPointF bTangent = -bezier->derivedAt(t1);
- if (qFuzzyCompare(aTangent.x() + 1, 1) && qFuzzyCompare(aTangent.y() + 1, 1))
+ if (qFuzzyIsNull(aTangent.x()) && qFuzzyIsNull(aTangent.y()))
aTangent = bezier->secondDerivedAt(t0);
- if (qFuzzyCompare(bTangent.x() + 1, 1) && qFuzzyCompare(bTangent.y() + 1, 1))
+ if (qFuzzyIsNull(bTangent.x()) && qFuzzyIsNull(bTangent.y()))
bTangent = bezier->secondDerivedAt(t1);
ep->angle = computeAngle(aTangent);
@@ -1400,7 +1400,7 @@ static void addLineTo(QPainterPath &path, const QPointF &point)
const QPointF p(-d1.y(), d1.x());
- if (qFuzzyCompare(dot(p, d2) + 1, 1)) {
+ if (qFuzzyIsNull(dot(p, d2))) {
path.setElementPositionAt(elementCount - 1, point.x(), point.y());
return;
}
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 55006f6..0b2db8c 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -346,7 +346,7 @@ QByteArray QPdf::generateDashes(const QPen &pen)
{
QByteArray result;
ByteStream s(&result);
- s << "[";
+ s << '[';
QVector<qreal> dasharray = pen.dashPattern();
qreal w = pen.widthF();
@@ -357,7 +357,7 @@ QByteArray QPdf::generateDashes(const QPen &pen)
if (dw < 0.0001) dw = 0.0001;
s << dw;
}
- s << "]";
+ s << ']';
//qDebug() << "dasharray: pen has" << dasharray;
//qDebug() << " => " << result;
return result;
@@ -915,17 +915,17 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize)
QByteArray QPdf::stripSpecialCharacters(const QByteArray &string)
{
QByteArray s = string;
- s.replace(" ", "");
- s.replace("(", "");
- s.replace(")", "");
- s.replace("<", "");
- s.replace(">", "");
- s.replace("[", "");
- s.replace("]", "");
- s.replace("{", "");
- s.replace("}", "");
- s.replace("/", "");
- s.replace("%", "");
+ s.replace(' ', "");
+ s.replace('(', "");
+ s.replace(')', "");
+ s.replace('<', "");
+ s.replace('>', "");
+ s.replace('[', "");
+ s.replace(']', "");
+ s.replace('{', "");
+ s.replace('}', "");
+ s.replace('/', "");
+ s.replace('%', "");
return s;
}
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index 1d45ca1..7d92c0c 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -158,7 +158,7 @@ namespace QPdf {
QByteArray stripSpecialCharacters(const QByteArray &string);
-};
+}
class QPdfPage : public QPdf::ByteStream
diff --git a/src/gui/painting/qpen.cpp b/src/gui/painting/qpen.cpp
index 1d68520..ab60861 100644
--- a/src/gui/painting/qpen.cpp
+++ b/src/gui/painting/qpen.cpp
@@ -978,7 +978,7 @@ QDebug operator<<(QDebug dbg, const QPen &p)
dbg.nospace() << "QPen(" << p.width() << ',' << p.brush()
<< ',' << int(p.style()) << ',' << int(p.capStyle())
<< ',' << int(p.joinStyle()) << ',' << p.dashPattern()
- << "," << p.dashOffset()
+ << ',' << p.dashOffset()
<< ',' << p.miterLimit() << ')';
return dbg.space();
#else
diff --git a/src/gui/painting/qpolygon.cpp b/src/gui/painting/qpolygon.cpp
index 87dae0f..b79c288 100644
--- a/src/gui/painting/qpolygon.cpp
+++ b/src/gui/painting/qpolygon.cpp
@@ -208,10 +208,15 @@ QPolygon::QPolygon(int nPoints, const int *points)
/*!
Translates all points in the polygon by (\a{dx}, \a{dy}).
+
+ \sa translated()
*/
void QPolygon::translate(int dx, int dy)
{
+ if (dx == 0 && dy == 0)
+ return;
+
register QPoint *p = data();
register int i = size();
QPoint pt(dx, dy);
@@ -226,8 +231,32 @@ void QPolygon::translate(int dx, int dy)
\overload
Translates all points in the polygon by the given \a offset.
+
+ \sa translated()
+*/
+
+/*!
+ Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}).
+
+ \since 4.6
+ \sa translate()
*/
+QPolygon QPolygon::translated(int dx, int dy) const
+{
+ QPolygon copy(*this);
+ copy.translate(dx, dy);
+ return copy;
+}
+
+/*!
+ \fn void QPolygon::translated(const QPoint &offset) const
+ \overload
+ \since 4.6
+
+ Returns a copy of the polygon that is translated by the given \a offset.
+ \sa translate()
+*/
/*!
Extracts the coordinates of the point at the given \a index to
@@ -565,10 +594,15 @@ QPolygonF::QPolygonF(const QPolygon &a)
/*!
Translate all points in the polygon by the given \a offset.
+
+ \sa translated()
*/
void QPolygonF::translate(const QPointF &offset)
{
+ if (offset.isNull())
+ return;
+
register QPointF *p = data();
register int i = size();
while (i--) {
@@ -582,6 +616,31 @@ void QPolygonF::translate(const QPointF &offset)
\overload
Translates all points in the polygon by (\a{dx}, \a{dy}).
+
+ \sa translated()
+*/
+
+/*!
+ Returns a copy of the polygon that is translated by the given \a offset.
+
+ \since 4.6
+ \sa translate()
+*/
+QPolygonF QPolygonF::translated(const QPointF &offset) const
+{
+ QPolygonF copy(*this);
+ copy.translate(offset);
+ return copy;
+}
+
+/*!
+ \fn void QPolygonF::translated(qreal dx, qreal dy) const
+ \overload
+ \since 4.6
+
+ Returns a copy of the polygon that is translated by (\a{dx}, \a{dy}).
+
+ \sa translate()
*/
/*!
@@ -683,7 +742,7 @@ QDataStream &operator>>(QDataStream &s, QPolygon &a)
QVector<QPoint> &v = a;
return s >> v;
}
-#endif
+#endif // QT_NO_DATASTREAM
/*****************************************************************************
QPolygonF stream functions
diff --git a/src/gui/painting/qpolygon.h b/src/gui/painting/qpolygon.h
index e5e0bd1..c52f48c 100644
--- a/src/gui/painting/qpolygon.h
+++ b/src/gui/painting/qpolygon.h
@@ -71,6 +71,10 @@ public:
void translate(int dx, int dy);
void translate(const QPoint &offset);
+
+ QPolygon translated(int dx, int dy) const;
+ inline QPolygon translated(const QPoint &offset) const;
+
QRect boundingRect() const;
void point(int i, int *x, int *y) const;
@@ -120,6 +124,9 @@ inline QPoint QPolygon::point(int index) const
inline void QPolygon::translate(const QPoint &offset)
{ translate(offset.x(), offset.y()); }
+inline QPolygon QPolygon::translated(const QPoint &offset) const
+{ return translated(offset.x(), offset.y()); }
+
class QRectF;
class Q_GUI_EXPORT QPolygonF : public QVector<QPointF>
@@ -136,6 +143,9 @@ public:
inline void translate(qreal dx, qreal dy);
void translate(const QPointF &offset);
+ inline QPolygonF translated(qreal dx, qreal dy) const;
+ QPolygonF translated(const QPointF &offset) const;
+
QPolygon toPolygon() const;
bool isClosed() const { return !isEmpty() && first() == last(); }
@@ -166,6 +176,9 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QPolygonF &array);
inline void QPolygonF::translate(qreal dx, qreal dy)
{ translate(QPointF(dx, dy)); }
+inline QPolygonF QPolygonF::translated(qreal dx, qreal dy) const
+{ return translated(QPointF(dx, dy)); }
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/gui/painting/qprintengine_pdf.cpp b/src/gui/painting/qprintengine_pdf.cpp
index 2e063b7..e504558 100644
--- a/src/gui/painting/qprintengine_pdf.cpp
+++ b/src/gui/painting/qprintengine_pdf.cpp
@@ -423,7 +423,7 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
object = addXrefEntry(-1);
QByteArray alphaDef;
QPdf::ByteStream s(&alphaDef);
- s << "<<\n/ca " << (brushAlpha/qreal(255.)) << "\n";
+ s << "<<\n/ca " << (brushAlpha/qreal(255.)) << '\n';
s << "/CA " << (penAlpha/qreal(255.)) << "\n>>";
xprintf("%s\nendobj\n", alphaDef.constData());
alphaCache.insert(QPair<uint, uint>(brushAlpha, penAlpha), object);
@@ -1010,7 +1010,7 @@ void QPdfEnginePrivate::embedFont(QFontSubset *font)
s << (char)('A' + (tag % 26));
tag /= 26;
}
- s << "+" << properties.postscriptName << "\n"
+ s << '+' << properties.postscriptName << "\n"
"/Flags " << 4 << "\n"
"/FontBBox ["
<< properties.boundingBox.x()*scale
diff --git a/src/gui/painting/qprintengine_ps.cpp b/src/gui/painting/qprintengine_ps.cpp
index 97ec640..29f364e 100644
--- a/src/gui/painting/qprintengine_ps.cpp
+++ b/src/gui/painting/qprintengine_ps.cpp
@@ -167,7 +167,7 @@ static QByteArray wrapDSC(const QByteArray &str)
}
wrapped += "\n%%+" + tmp;
}
- return wrapped + "\n";
+ return wrapped + '\n';
}
// ----------------------------- Internal class declarations -----------------------------
@@ -422,7 +422,7 @@ void QPSPrintEnginePrivate::drawImageHelper(qreal x, qreal y, qreal w, qreal h,
<< size << " string readstring\n";
ps_r7(*currentPage, out, out.size());
*currentPage << " pop def\n";
- *currentPage << width << ' ' << height << "[" << scaleX << " 0 0 " << scaleY << " 0 0]sl "
+ *currentPage << width << ' ' << height << '[' << scaleX << " 0 0 " << scaleY << " 0 0]sl "
<< bits << (!mask.isNull() ? "mask " : "false ")
<< x << ' ' << y << " di\n";
}
@@ -529,7 +529,7 @@ void QPSPrintEnginePrivate::emitHeader(bool finished)
else
s << "\n%%BoundingBox: 0 0 " << w << h;
}
- s << "\n" << wrapDSC("%%Creator: " + creator.toUtf8());
+ s << '\n' << wrapDSC("%%Creator: " + creator.toUtf8());
if (!title.isEmpty())
s << wrapDSC("%%Title: " + title.toUtf8());
#ifndef QT_NO_DATESTRING
@@ -549,7 +549,7 @@ void QPSPrintEnginePrivate::emitHeader(bool finished)
"% Prolog copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies).\n"
"% You may copy this prolog in any way that is directly related to this document.\n"
"% For other use of this prolog, see your licensing agreement for Qt.\n"
- << ps_header << "\n";
+ << ps_header << '\n';
s << "/pageinit {\n";
@@ -560,12 +560,12 @@ void QPSPrintEnginePrivate::emitHeader(bool finished)
s << mtop*scale << mleft*scale << "translate\n";
}
if (orientation == QPrinter::Portrait) {
- s << "% " << printer->widthMM() << "*" << printer->heightMM()
+ s << "% " << printer->widthMM() << '*' << printer->heightMM()
<< "mm (portrait)\n0 " << height*scale
- << "translate " << scale << "-" << scale << "scale } def\n";
+ << "translate " << scale << '-' << scale << "scale } def\n";
} else {
- s << "% " << printer->heightMM() << "*" << printer->widthMM()
- << " mm (landscape)\n 90 rotate " << scale << "-" << scale << "scale } def\n";
+ s << "% " << printer->heightMM() << '*' << printer->widthMM()
+ << " mm (landscape)\n 90 rotate " << scale << '-' << scale << "scale } def\n";
}
s << "%%EndProlog\n";
@@ -619,8 +619,8 @@ void QPSPrintEnginePrivate::flushPage(bool last)
QPdf::ByteStream e(&trailer);
buffer << "%%Page: "
<< pageCount << pageCount << "\n"
- << "%%BeginPageSetup\n"
- << "QI\n";
+ "%%BeginPageSetup\n"
+ "QI\n";
if (hugeDocument) {
for (QHash<QFontEngine::FaceId, QFontSubset *>::const_iterator it = fonts.constBegin();
it != fonts.constEnd(); ++it) {
@@ -776,8 +776,8 @@ bool QPSPrintEngine::end()
d->flushPage(true);
QByteArray trailer;
QPdf::ByteStream s(&trailer);
- s << "%%Trailer\n";
- s << "%%Pages: " << d->pageCount - 1 << "\n" <<
+ s << "%%Trailer\n"
+ "%%Pages: " << d->pageCount - 1 << '\n' <<
wrapDSC("%%DocumentFonts: " + d->fontsUsed);
s << "%%EOF\n";
d->outDevice->write(trailer);
diff --git a/src/gui/painting/qprinter.cpp b/src/gui/painting/qprinter.cpp
index ba6baa6..0699de9 100644
--- a/src/gui/painting/qprinter.cpp
+++ b/src/gui/painting/qprinter.cpp
@@ -833,11 +833,15 @@ void QPrinter::setPrinterName(const QString &name)
#endif
QList<QPrinterInfo> prnList = QPrinterInfo::availablePrinters();
- d->validPrinter = false;
- for (int i = 0; i < prnList.size(); ++i) {
- if (prnList[i].printerName() == name) {
- d->validPrinter = true;
- break;
+ if (name.isEmpty()) {
+ d->validPrinter = d->outputFormat == QPrinter::PdfFormat || d->outputFormat == QPrinter::PostScriptFormat;
+ } else {
+ d->validPrinter = false;
+ for (int i = 0; i < prnList.size(); ++i) {
+ if (prnList[i].printerName() == name) {
+ d->validPrinter = true;
+ break;
+ }
}
}
@@ -1303,6 +1307,9 @@ void QPrinter::setNumCopies(int numCopies)
Returns true if collation is turned on when multiple copies is selected.
Returns false if it is turned off when multiple copies is selected.
+ When collating is turned off the printing of each individual page will be repeated
+ the numCopies() amount before the next page is started. With collating turned on
+ all pages are printed before the next copy of those pages is started.
\sa setCollateCopies()
*/
diff --git a/src/gui/painting/qprinterinfo_unix.cpp b/src/gui/painting/qprinterinfo_unix.cpp
index 55e3226..4887cf8 100644
--- a/src/gui/painting/qprinterinfo_unix.cpp
+++ b/src/gui/painting/qprinterinfo_unix.cpp
@@ -838,7 +838,7 @@ QList<QPrinterInfo> QPrinterInfo::availablePrinters()
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
- printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
+ printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
list.append(QPrinterInfo(printerName));
if (cupsPrinters[i].is_default)
list[i].d_ptr->m_default = true;
@@ -909,7 +909,7 @@ QPrinterInfo::QPrinterInfo(const QPrinter& printer)
for (int i = 0; i < cupsPrinterCount; ++i) {
QString printerName(QString::fromLocal8Bit(cupsPrinters[i].name));
if (cupsPrinters[i].instance)
- printerName += QLatin1String("/") + QString::fromLocal8Bit(cupsPrinters[i].instance);
+ printerName += QLatin1Char('/') + QString::fromLocal8Bit(cupsPrinters[i].instance);
if (printerName == printer.printerName()) {
if (cupsPrinters[i].is_default)
d->m_default = true;
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 65964de..55f009f 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -450,9 +450,9 @@ QDebug operator<<(QDebug s, const QRegion &r)
{
QVector<QRect> rects = r.rects();
s.nospace() << "QRegion(size=" << rects.size() << "), "
- << "bounds = " << r.boundingRect() << "\n";
+ << "bounds = " << r.boundingRect() << '\n';
for (int i=0; i<rects.size(); ++i)
- s << "- " << i << rects.at(i) << "\n";
+ s << "- " << i << rects.at(i) << '\n';
return s;
}
#endif
@@ -1601,7 +1601,7 @@ void QRegionPrivate::selfTest() const
for (int i = 0; i < numRects; ++i) {
const QRect r = rects.at(i);
if ((r.width() * r.height()) > innerArea)
- qDebug() << "selfTest(): innerRect" << innerRect << "<" << r;
+ qDebug() << "selfTest(): innerRect" << innerRect << '<' << r;
}
QRect r = rects.first();
diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp
index b894c62..5fffc72 100644
--- a/src/gui/painting/qstroker.cpp
+++ b/src/gui/painting/qstroker.cpp
@@ -763,7 +763,7 @@ template <class Iterator> bool qt_stroke_side(Iterator *it,
qreal qt_t_for_arc_angle(qreal angle)
{
- if (qFuzzyCompare(angle + 1, qreal(1)))
+ if (qFuzzyIsNull(angle))
return 0;
if (qFuzzyCompare(angle, qreal(90)))
@@ -904,13 +904,13 @@ QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLengt
}
// avoid empty start segment
- if (qFuzzyCompare(startT, qreal(1))) {
+ if (qFuzzyIsNull(startT - qreal(1))) {
startT = 0;
startSegment += delta;
}
// avoid empty end segment
- if (qFuzzyCompare(endT + 1, qreal(1))) {
+ if (qFuzzyIsNull(endT)) {
endT = 1;
endSegment -= delta;
}
@@ -918,8 +918,8 @@ QPointF qt_curves_for_arc(const QRectF &rect, qreal startAngle, qreal sweepLengt
startT = qt_t_for_arc_angle(startT * 90);
endT = qt_t_for_arc_angle(endT * 90);
- const bool splitAtStart = !qFuzzyCompare(startT + 1, qreal(1));
- const bool splitAtEnd = !qFuzzyCompare(endT, qreal(1));
+ const bool splitAtStart = !qFuzzyIsNull(startT);
+ const bool splitAtEnd = !qFuzzyIsNull(endT - qreal(1));
const int end = endSegment + delta;
@@ -1018,7 +1018,7 @@ void QDashStroker::processCurrentSubpath()
sumLength += dashes[i];
}
- if (qFuzzyCompare(sumLength + 1, qreal(1)))
+ if (qFuzzyIsNull(sumLength))
return;
Q_ASSERT(dashCount > 0);
diff --git a/src/gui/painting/qstroker_p.h b/src/gui/painting/qstroker_p.h
index 72141aa..ca1f270 100644
--- a/src/gui/painting/qstroker_p.h
+++ b/src/gui/painting/qstroker_p.h
@@ -179,7 +179,7 @@ private:
};
-class Q_GUI_EXPORT QStroker : public QStrokerOps
+class QStroker : public QStrokerOps
{
public:
diff --git a/src/gui/painting/qtessellator.cpp b/src/gui/painting/qtessellator.cpp
index a3f00e2..b3b636a 100644
--- a/src/gui/painting/qtessellator.cpp
+++ b/src/gui/painting/qtessellator.cpp
@@ -1080,7 +1080,7 @@ void QTessellatorPrivate::addIntersection(const Edge *e1, const Edge *e2)
yi = y;
}
QDEBUG() << " between edges " << e1->edge << "and" << e2->edge << "at point ("
- << Q27Dot5ToDouble(yi) << ")";
+ << Q27Dot5ToDouble(yi) << ')';
Intersection i1;
i1.y = yi;
@@ -1173,7 +1173,7 @@ void QTessellatorPrivate::addIntersections()
for (int i = 0; i < scanline.size; ++i) {
Edge *e = scanline.edges[i];
QDEBUG() << " " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right
- << ")";
+ << ')';
}
#endif
@@ -1239,8 +1239,8 @@ QRectF QTessellator::tessellate(const QPointF *points, int nPoints)
QDEBUG() << " " << i << ": "
<< "point=" << d->vertices.position(d->vertices.sorted[i])
<< "flags=" << d->vertices.sorted[i]->flags
- << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << "/"
- << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ")";
+ << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << '/'
+ << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ')';
}
#endif
@@ -1270,9 +1270,9 @@ QRectF QTessellator::tessellate(const QPointF *points, int nPoints)
for (int i = 0; i < d->scanline.size; ++i) {
QDEBUG() << " " << d->scanline.edges[i]->edge
<< "p0= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->x)
- << "/" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
+ << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
<< ") p1= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->x)
- << "/" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ")"
+ << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ')'
<< "x=" << Q27Dot5ToDouble(d->scanline.edges[i]->positionAt(d->y))
<< "isLeftOfNext="
<< ((i < d->scanline.size - 1)
@@ -1435,7 +1435,7 @@ void QTessellator::tessellateRect(const QPointF &a_, const QPointF &b_, qreal wi
QPointF perp(pb.y() - pa.y(), pa.x() - pb.x());
qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y());
- if (qFuzzyCompare(length + 1, static_cast<qreal>(1)))
+ if (qFuzzyIsNull(length))
return;
// need the half of the width
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index 89df869..6b195bf 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -157,6 +157,46 @@ void QTextureGlyphCache::populate(const QTextItemInt &ti,
}
+QImage QTextureGlyphCache::textureMapForGlyph(glyph_t g) const
+{
+#if defined(Q_WS_X11)
+ if (m_transform.type() > QTransform::TxTranslate) {
+ QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None;
+ QImage::Format imageFormat = QImage::Format_Invalid;
+ switch (m_type) {
+ case Raster_RGBMask:
+ format = QFontEngineFT::Format_A32;
+ imageFormat = QImage::Format_RGB32;
+ break;
+ case Raster_A8:
+ format = QFontEngineFT::Format_A8;
+ imageFormat = QImage::Format_Indexed8;
+ break;
+ case Raster_Mono:
+ format = QFontEngineFT::Format_Mono;
+ imageFormat = QImage::Format_Mono;
+ break;
+ };
+
+ QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
+ QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
+
+ if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
+ QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
+ const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
+ : (glyph->width + 3) & ~3);
+ return QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, imageFormat);
+ }
+ } else
+#endif
+ if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
+ return m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
+ else
+ return m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
+
+ return QImage();
+}
+
/************************************************************************
* QImageTextureGlyphCache
*/
@@ -198,34 +238,7 @@ int QImageTextureGlyphCache::glyphMargin() const
void QImageTextureGlyphCache::fillTexture(const Coord &c, glyph_t g)
{
- QImage mask;
-#if defined(Q_WS_X11)
- if (m_transform.type() > QTransform::TxTranslate) {
- QFontEngineFT::GlyphFormat format = QFontEngineFT::Format_None;
- switch (m_type) {
- case Raster_RGBMask:
- format = QFontEngineFT::Format_A32; break;
- case Raster_A8:
- format = QFontEngineFT::Format_A8; break;
- case Raster_Mono:
- format = QFontEngineFT::Format_Mono; break;
- };
-
- QFontEngineFT *ft = static_cast<QFontEngineFT*> (m_current_textitem->fontEngine);
- QFontEngineFT::QGlyphSet *gset = ft->loadTransformedGlyphSet(m_transform);
-
- if (gset && ft->loadGlyphs(gset, &g, 1, format)) {
- QFontEngineFT::Glyph *glyph = gset->glyph_data.value(g);
- const int bytesPerLine = (format == QFontEngineFT::Format_Mono ? ((glyph->width + 31) & ~31) >> 3
- : (glyph->width + 3) & ~3);
- mask = QImage(glyph->data, glyph->width, glyph->height, bytesPerLine, m_image.format());
- }
- } else
-#endif
- if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
- mask = m_current_textitem->fontEngine->alphaRGBMapForGlyph(g, glyphMargin(), m_transform);
- else
- mask = m_current_textitem->fontEngine->alphaMapForGlyph(g, m_transform);
+ QImage mask = textureMapForGlyph(g);
#ifdef CACHE_DEBUG
printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height());
diff --git a/src/gui/painting/qtextureglyphcache_p.h b/src/gui/painting/qtextureglyphcache_p.h
index 7f2c478..689c091 100644
--- a/src/gui/painting/qtextureglyphcache_p.h
+++ b/src/gui/painting/qtextureglyphcache_p.h
@@ -108,6 +108,8 @@ public:
QHash<glyph_t, Coord> coords;
+ QImage textureMapForGlyph(glyph_t g) const;
+
protected:
const QTextItemInt *m_current_textitem;
@@ -116,11 +118,10 @@ protected:
int m_cx; // current x
int m_cy; // current y
QFontEngineGlyphCache::Type m_type;
-
};
-class Q_GUI_EXPORT QImageTextureGlyphCache : public QTextureGlyphCache
+class QImageTextureGlyphCache : public QTextureGlyphCache
{
public:
QImageTextureGlyphCache(QFontEngineGlyphCache::Type type, const QTransform &matrix)
diff --git a/src/gui/painting/qtransform.cpp b/src/gui/painting/qtransform.cpp
index cec2d16..4bc20f6 100644
--- a/src/gui/painting/qtransform.cpp
+++ b/src/gui/painting/qtransform.cpp
@@ -238,11 +238,11 @@ QT_BEGIN_NAMESPACE
\sa reset()
*/
QTransform::QTransform()
- : m_13(0), m_23(0), m_33(1)
+ : affine(true)
+ , m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxNone)
{
-
}
/*!
@@ -256,12 +256,11 @@ QTransform::QTransform()
QTransform::QTransform(qreal h11, qreal h12, qreal h13,
qreal h21, qreal h22, qreal h23,
qreal h31, qreal h32, qreal h33)
- : affine(h11, h12, h21, h22, h31, h32),
- m_13(h13), m_23(h23), m_33(h33)
+ : affine(h11, h12, h21, h22, h31, h32, true)
+ , m_13(h13), m_23(h23), m_33(h33)
, m_type(TxNone)
, m_dirty(TxProject)
{
-
}
/*!
@@ -273,12 +272,11 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h13,
*/
QTransform::QTransform(qreal h11, qreal h12, qreal h21,
qreal h22, qreal dx, qreal dy)
- : affine(h11, h12, h21, h22, dx, dy),
- m_13(0), m_23(0), m_33(1)
+ : affine(h11, h12, h21, h22, dx, dy, true)
+ , m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxShear)
{
-
}
/*!
@@ -289,12 +287,11 @@ QTransform::QTransform(qreal h11, qreal h12, qreal h21,
and 1 respectively.
*/
QTransform::QTransform(const QMatrix &mtx)
- : affine(mtx),
+ : affine(mtx._m11, mtx._m12, mtx._m21, mtx._m22, mtx._dx, mtx._dy, true),
m_13(0), m_23(0), m_33(1)
, m_type(TxNone)
, m_dirty(TxShear)
{
-
}
/*!
@@ -317,7 +314,7 @@ QTransform QTransform::adjoint() const
return QTransform(h11, h12, h13,
h21, h22, h23,
- h31, h32, h33);
+ h31, h32, h33, true);
}
/*!
@@ -327,7 +324,7 @@ QTransform QTransform::transposed() const
{
QTransform t(affine._m11, affine._m21, affine._dx,
affine._m12, affine._m22, affine._dy,
- m_13, m_23, m_33);
+ m_13, m_23, m_33, true);
t.m_type = m_type;
t.m_dirty = m_dirty;
return t;
@@ -345,11 +342,10 @@ QTransform QTransform::transposed() const
*/
QTransform QTransform::inverted(bool *invertible) const
{
- QTransform invert;
+ QTransform invert(true);
bool inv = true;
- qreal det;
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
break;
case TxTranslate:
@@ -357,11 +353,11 @@ QTransform QTransform::inverted(bool *invertible) const
invert.affine._dy = -affine._dy;
break;
case TxScale:
- inv = !qFuzzyCompare(affine._m11 + 1, 1);
- inv &= !qFuzzyCompare(affine._m22 + 1, 1);
+ inv = !qFuzzyIsNull(affine._m11);
+ inv &= !qFuzzyIsNull(affine._m22);
if (inv) {
- invert.affine._m11 = 1 / affine._m11;
- invert.affine._m22 = 1 / affine._m22;
+ invert.affine._m11 = 1. / affine._m11;
+ invert.affine._m22 = 1. / affine._m22;
invert.affine._dx = -affine._dx * invert.affine._m11;
invert.affine._dy = -affine._dy * invert.affine._m22;
}
@@ -372,8 +368,8 @@ QTransform QTransform::inverted(bool *invertible) const
break;
default:
// general case
- det = determinant();
- inv = !qFuzzyCompare(det + 1, 1);
+ qreal det = determinant();
+ inv = !qFuzzyIsNull(det);
if (inv)
invert = adjoint() / det;
break;
@@ -397,12 +393,12 @@ QTransform QTransform::inverted(bool *invertible) const
\sa setMatrix()
*/
-QTransform & QTransform::translate(qreal dx, qreal dy)
+QTransform &QTransform::translate(qreal dx, qreal dy)
{
if (dx == 0 && dy == 0)
return *this;
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
affine._dx = dx;
affine._dy = dy;
@@ -424,7 +420,8 @@ QTransform & QTransform::translate(qreal dx, qreal dy)
affine._dy += dy*affine._m22 + dx*affine._m12;
break;
}
- m_dirty |= TxTranslate;
+ if (m_dirty < TxTranslate)
+ m_dirty = TxTranslate;
return *this;
}
@@ -437,7 +434,7 @@ QTransform & QTransform::translate(qreal dx, qreal dy)
*/
QTransform QTransform::fromTranslate(qreal dx, qreal dy)
{
- QTransform transform(1, 0, 0, 1, dx, dy);
+ QTransform transform(1, 0, 0, 0, 1, 0, dx, dy, 1, true);
if (dx == 0 && dy == 0)
transform.m_dirty = TxNone;
else
@@ -456,7 +453,7 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
if (sx == 1 && sy == 1)
return *this;
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m11 = sx;
@@ -476,7 +473,8 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
affine._m22 *= sy;
break;
}
- m_dirty |= TxScale;
+ if (m_dirty < TxScale)
+ m_dirty = TxScale;
return *this;
}
@@ -489,8 +487,8 @@ QTransform & QTransform::scale(qreal sx, qreal sy)
*/
QTransform QTransform::fromScale(qreal sx, qreal sy)
{
- QTransform transform(sx, 0, 0, sy, 0, 0);
- if (sx == 1 && sy == 1)
+ QTransform transform(sx, 0, 0, 0, sy, 0, 0, 0, 1, true);
+ if (sx == 1. && sy == 1.)
transform.m_dirty = TxNone;
else
transform.m_dirty = TxScale;
@@ -505,7 +503,10 @@ QTransform QTransform::fromScale(qreal sx, qreal sy)
*/
QTransform & QTransform::shear(qreal sh, qreal sv)
{
- switch(type()) {
+ if (sh == 0 && sv == 0)
+ return *this;
+
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m12 = sv;
@@ -533,7 +534,8 @@ QTransform & QTransform::shear(qreal sh, qreal sv)
break;
}
}
- m_dirty |= TxShear;
+ if (m_dirty < TxShear)
+ m_dirty = TxShear;
return *this;
}
@@ -574,7 +576,7 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
}
if (axis == Qt::ZAxis) {
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m11 = cosa;
@@ -609,7 +611,8 @@ QTransform & QTransform::rotate(qreal a, Qt::Axis axis)
break;
}
}
- m_dirty |= TxRotate;
+ if (m_dirty < TxRotate)
+ m_dirty = TxRotate;
} else {
QTransform result;
if (axis == Qt::YAxis) {
@@ -646,7 +649,7 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
qreal cosa = qCos(a);
if (axis == Qt::ZAxis) {
- switch(type()) {
+ switch(inline_type()) {
case TxNone:
case TxTranslate:
affine._m11 = cosa;
@@ -681,7 +684,8 @@ QTransform & QTransform::rotateRadians(qreal a, Qt::Axis axis)
break;
}
}
- m_dirty |= TxRotate;
+ if (m_dirty < TxRotate)
+ m_dirty = TxRotate;
} else {
QTransform result;
if (axis == Qt::YAxis) {
@@ -730,11 +734,11 @@ bool QTransform::operator!=(const QTransform &o) const
*/
QTransform & QTransform::operator*=(const QTransform &o)
{
- const TransformationType otherType = o.type();
+ const TransformationType otherType = o.inline_type();
if (otherType == TxNone)
return *this;
- const TransformationType thisType = type();
+ const TransformationType thisType = inline_type();
if (thisType == TxNone)
return operator=(o);
@@ -812,9 +816,77 @@ QTransform & QTransform::operator*=(const QTransform &o)
*/
QTransform QTransform::operator*(const QTransform &m) const
{
- QTransform result = *this;
- result *= m;
- return result;
+ const TransformationType otherType = m.inline_type();
+ if (otherType == TxNone)
+ return *this;
+
+ const TransformationType thisType = inline_type();
+ if (thisType == TxNone)
+ return m;
+
+ QTransform t(true);
+ TransformationType type = qMax(thisType, otherType);
+ switch(type) {
+ case TxNone:
+ break;
+ case TxTranslate:
+ t.affine._dx = affine._dx + m.affine._dx;
+ t.affine._dy += affine._dy + m.affine._dy;
+ break;
+ case TxScale:
+ {
+ qreal m11 = affine._m11*m.affine._m11;
+ qreal m22 = affine._m22*m.affine._m22;
+
+ qreal m31 = affine._dx*m.affine._m11 + m.affine._dx;
+ qreal m32 = affine._dy*m.affine._m22 + m.affine._dy;
+
+ t.affine._m11 = m11;
+ t.affine._m22 = m22;
+ t.affine._dx = m31; t.affine._dy = m32;
+ break;
+ }
+ case TxRotate:
+ case TxShear:
+ {
+ qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21;
+ qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22;
+
+ qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21;
+ qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22;
+
+ qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m.affine._dx;
+ qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m.affine._dy;
+
+ t.affine._m11 = m11; t.affine._m12 = m12;
+ t.affine._m21 = m21; t.affine._m22 = m22;
+ t.affine._dx = m31; t.affine._dy = m32;
+ break;
+ }
+ case TxProject:
+ {
+ qreal m11 = affine._m11*m.affine._m11 + affine._m12*m.affine._m21 + m_13*m.affine._dx;
+ qreal m12 = affine._m11*m.affine._m12 + affine._m12*m.affine._m22 + m_13*m.affine._dy;
+ qreal m13 = affine._m11*m.m_13 + affine._m12*m.m_23 + m_13*m.m_33;
+
+ qreal m21 = affine._m21*m.affine._m11 + affine._m22*m.affine._m21 + m_23*m.affine._dx;
+ qreal m22 = affine._m21*m.affine._m12 + affine._m22*m.affine._m22 + m_23*m.affine._dy;
+ qreal m23 = affine._m21*m.m_13 + affine._m22*m.m_23 + m_23*m.m_33;
+
+ qreal m31 = affine._dx*m.affine._m11 + affine._dy*m.affine._m21 + m_33*m.affine._dx;
+ qreal m32 = affine._dx*m.affine._m12 + affine._dy*m.affine._m22 + m_33*m.affine._dy;
+ qreal m33 = affine._dx*m.m_13 + affine._dy*m.m_23 + m_33*m.m_33;
+
+ t.affine._m11 = m11; t.affine._m12 = m12; t.m_13 = m13;
+ t.affine._m21 = m21; t.affine._m22 = m22; t.m_23 = m23;
+ t.affine._dx = m31; t.affine._dy = m32; t.m_33 = m33;
+ }
+ }
+
+ t.m_dirty = type;
+ t.m_type = type;
+
+ return t;
}
/*!
@@ -956,7 +1028,7 @@ QDebug operator<<(QDebug dbg, const QTransform &m)
<< " 31=" << m.m31()
<< " 32=" << m.m32()
<< " 33=" << m.m33()
- << ")";
+ << ')';
return dbg.space();
}
#endif
@@ -976,7 +1048,7 @@ QPoint QTransform::map(const QPoint &p) const
qreal x = 0, y = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x = fx;
@@ -1027,7 +1099,7 @@ QPointF QTransform::map(const QPointF &p) const
qreal x = 0, y = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x = fx;
@@ -1098,7 +1170,7 @@ QLine QTransform::map(const QLine &l) const
qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x1 = fx1;
@@ -1157,7 +1229,7 @@ QLineF QTransform::map(const QLineF &l) const
qreal x1 = 0, y1 = 0, x2 = 0, y2 = 0;
- TransformationType t = type();
+ TransformationType t = inline_type();
switch(t) {
case TxNone:
x1 = fx1;
@@ -1245,7 +1317,10 @@ static QPolygonF mapProjective(const QTransform &transform, const QPolygonF &pol
*/
QPolygonF QTransform::map(const QPolygonF &a) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return a.translated(affine._dx, affine._dy);
+
if (t >= QTransform::TxProject)
return mapProjective(*this, a);
@@ -1272,7 +1347,10 @@ QPolygonF QTransform::map(const QPolygonF &a) const
*/
QPolygon QTransform::map(const QPolygon &a) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return a.translated(qRound(affine._dx), qRound(affine._dy));
+
if (t >= QTransform::TxProject)
return mapProjective(*this, QPolygonF(a)).toPolygon();
@@ -1314,7 +1392,7 @@ extern QPainterPath qt_regionToPath(const QRegion &region);
*/
QRegion QTransform::map(const QRegion &r) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
if (t == TxNone)
return r;
@@ -1341,7 +1419,7 @@ struct QHomogeneousCoordinate
QHomogeneousCoordinate(qreal x_, qreal y_, qreal w_) : x(x_), y(y_), w(w_) {}
const QPointF toPoint() const {
- qreal iw = 1 / w;
+ qreal iw = 1. / w;
return QPointF(x * iw, y * iw);
}
};
@@ -1481,7 +1559,7 @@ static QPainterPath mapProjective(const QTransform &transform, const QPainterPat
*/
QPainterPath QTransform::map(const QPainterPath &path) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
if (t == TxNone || path.isEmpty())
return path;
@@ -1489,15 +1567,11 @@ QPainterPath QTransform::map(const QPainterPath &path) const
return mapProjective(*this, path);
QPainterPath copy = path;
- copy.detach();
if (t == TxTranslate) {
- for (int i=0; i<path.elementCount(); ++i) {
- QPainterPath::Element &e = copy.d_ptr->elements[i];
- e.x += affine._dx;
- e.y += affine._dy;
- }
+ copy.translate(affine._dx, affine._dy);
} else {
+ copy.detach();
// Full xform
for (int i=0; i<path.elementCount(); ++i) {
QPainterPath::Element &e = copy.d_ptr->elements[i];
@@ -1530,7 +1604,7 @@ QPainterPath QTransform::map(const QPainterPath &path) const
*/
QPolygon QTransform::mapToPolygon(const QRect &rect) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
QPolygon a(4);
qreal x[4] = { 0, 0, 0, 0 }, y[4] = { 0, 0, 0, 0 };
@@ -1704,7 +1778,10 @@ void QTransform::setMatrix(qreal m11, qreal m12, qreal m13,
QRect QTransform::mapRect(const QRect &rect) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return rect.translated(qRound(affine._dx), qRound(affine._dy));
+
if (t <= TxScale) {
int x = qRound(affine._m11*rect.x() + affine._dx);
int y = qRound(affine._m22*rect.y() + affine._dy);
@@ -1771,7 +1848,10 @@ QRect QTransform::mapRect(const QRect &rect) const
*/
QRectF QTransform::mapRect(const QRectF &rect) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
+ if (t <= TxTranslate)
+ return rect.translated(affine._dx, affine._dy);
+
if (t <= TxScale) {
qreal x = affine._m11*rect.x() + affine._dx;
qreal y = affine._m22*rect.y() + affine._dy;
@@ -1842,7 +1922,7 @@ QRectF QTransform::mapRect(const QRectF &rect) const
*/
void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
MAP(x, y, *tx, *ty);
}
@@ -1856,7 +1936,7 @@ void QTransform::map(qreal x, qreal y, qreal *tx, qreal *ty) const
*/
void QTransform::map(int x, int y, int *tx, int *ty) const
{
- TransformationType t = type();
+ TransformationType t = inline_type();
qreal fx = 0, fy = 0;
MAP(x, y, fx, fy);
*tx = qRound(fx);
@@ -1885,25 +1965,41 @@ const QMatrix &QTransform::toAffine() const
*/
QTransform::TransformationType QTransform::type() const
{
- if (m_dirty >= m_type) {
- if (m_dirty > TxShear && (!qFuzzyCompare(m_13 + 1, 1) || !qFuzzyCompare(m_23 + 1, 1) || !qFuzzyCompare(m_33, 1)))
+ if(m_dirty == TxNone || m_dirty < m_type)
+ return static_cast<TransformationType>(m_type);
+
+ switch (static_cast<TransformationType>(m_dirty)) {
+ case TxProject:
+ if (!qFuzzyIsNull(m_13) || !qFuzzyIsNull(m_23) || !qFuzzyIsNull(m_33 - 1)) {
m_type = TxProject;
- else if (m_dirty > TxScale && (!qFuzzyCompare(affine._m12 + 1, 1) || !qFuzzyCompare(affine._m21 + 1, 1))) {
+ break;
+ }
+ case TxShear:
+ case TxRotate:
+ if (!qFuzzyIsNull(affine._m12) || !qFuzzyIsNull(affine._m21)) {
const qreal dot = affine._m11 * affine._m12 + affine._m21 * affine._m22;
- if (qFuzzyCompare(dot + 1, 1))
+ if (qFuzzyIsNull(dot))
m_type = TxRotate;
else
m_type = TxShear;
- } else if (m_dirty > TxTranslate && (!qFuzzyCompare(affine._m11, 1) || !qFuzzyCompare(affine._m22, 1)))
+ break;
+ }
+ case TxScale:
+ if (!qFuzzyIsNull(affine._m11 - 1) || !qFuzzyIsNull(affine._m22 - 1)) {
m_type = TxScale;
- else if (m_dirty > TxNone && (!qFuzzyCompare(affine._dx + 1, 1) || !qFuzzyCompare(affine._dy + 1, 1)))
+ break;
+ }
+ case TxTranslate:
+ if (!qFuzzyIsNull(affine._dx) || !qFuzzyIsNull(affine._dy)) {
m_type = TxTranslate;
- else
- m_type = TxNone;
-
- m_dirty = TxNone;
+ break;
+ }
+ case TxNone:
+ m_type = TxNone;
+ break;
}
+ m_dirty = TxNone;
return static_cast<TransformationType>(m_type);
}
diff --git a/src/gui/painting/qtransform.h b/src/gui/painting/qtransform.h
index c76409b..a5002ca 100644
--- a/src/gui/painting/qtransform.h
+++ b/src/gui/painting/qtransform.h
@@ -159,6 +159,19 @@ public:
static QTransform fromScale(qreal dx, qreal dy);
private:
+ inline QTransform(qreal h11, qreal h12, qreal h13,
+ qreal h21, qreal h22, qreal h23,
+ qreal h31, qreal h32, qreal h33, bool)
+ : affine(h11, h12, h21, h22, h31, h32, true)
+ , m_13(h13), m_23(h23), m_33(h33)
+ , m_type(TxNone)
+ , m_dirty(TxProject) {}
+ inline QTransform(bool)
+ : affine(true)
+ , m_13(0), m_23(0), m_33(1)
+ , m_type(TxNone)
+ , m_dirty(TxNone) {}
+ inline TransformationType inline_type() const;
QMatrix affine;
qreal m_13;
qreal m_23;
@@ -173,18 +186,25 @@ private:
Q_DECLARE_TYPEINFO(QTransform, Q_MOVABLE_TYPE);
/******* inlines *****/
+inline QTransform::TransformationType QTransform::inline_type() const
+{
+ if (m_dirty == TxNone)
+ return static_cast<TransformationType>(m_type);
+ return type();
+}
+
inline bool QTransform::isAffine() const
{
- return type() < TxProject;
+ return inline_type() < TxProject;
}
inline bool QTransform::isIdentity() const
{
- return type() == TxNone;
+ return inline_type() == TxNone;
}
inline bool QTransform::isInvertible() const
{
- return !qFuzzyCompare(determinant() + 1, 1);
+ return !qFuzzyIsNull(determinant());
}
inline bool QTransform::isScaling() const
@@ -193,12 +213,12 @@ inline bool QTransform::isScaling() const
}
inline bool QTransform::isRotating() const
{
- return type() >= TxRotate;
+ return inline_type() >= TxRotate;
}
inline bool QTransform::isTranslating() const
{
- return type() >= TxTranslate;
+ return inline_type() >= TxTranslate;
}
inline qreal QTransform::determinant() const
@@ -312,8 +332,10 @@ inline QTransform &QTransform::operator-=(qreal num)
}
/****** stream functions *******************/
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTransform &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTransform &);
+#endif
#ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QTransform &);
diff --git a/src/gui/painting/qvectorpath_p.h b/src/gui/painting/qvectorpath_p.h
index 2713cda..b073f8c 100644
--- a/src/gui/painting/qvectorpath_p.h
+++ b/src/gui/painting/qvectorpath_p.h
@@ -94,7 +94,7 @@ public:
// Shape rendering specifiers...
OddEvenFill = 0x1000,
WindingFill = 0x2000,
- ImplicitClose = 0x4000,
+ ImplicitClose = 0x4000
};
// ### Falcon: introduca a struct XY for points so lars is not so confused...
@@ -112,7 +112,7 @@ public:
{
}
- const QRealRect &controlPointRect() const;
+ QRectF controlPointRect() const;
inline Hint shape() const { return (Hint) (m_hints & ShapeHintMask); }
diff --git a/src/gui/painting/qwindowsurface_d3d.cpp b/src/gui/painting/qwindowsurface_d3d.cpp
deleted file mode 100644
index 2b7f633..0000000
--- a/src/gui/painting/qwindowsurface_d3d.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtGui module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//#define D3D_DEBUG_BACKBUFFER
-
-#include <QtGui/QPaintDevice>
-#include <QtGui/QWidget>
-#include "qdebug.h"
-
-#include "qpaintengine_d3d_p.h"
-#include "qwindowsurface_d3d_p.h"
-#include "private/qwidget_p.h"
-#include "private/qbackingstore_p.h"
-
-#include <d3d9.h>
-
-QT_BEGIN_NAMESPACE
-
-extern QDirect3DPaintEngine *qt_d3dEngine();
-
-struct QD3DWindowSurfacePrivate
-{
- QSize m_lastSize;
- QWidget *m_widget;
-};
-
-QD3DWindowSurface::QD3DWindowSurface(QWidget *window)
- : QWindowSurface(window), d_ptr(new QD3DWindowSurfacePrivate)
-{
- Q_ASSERT(window->isTopLevel());
- d_ptr->m_widget = window;
-}
-
-
-QD3DWindowSurface::~QD3DWindowSurface()
-{
- delete d_ptr;
-}
-
-QPaintDevice *QD3DWindowSurface::paintDevice()
-{
- return d_ptr->m_widget;
-}
-
-
-void QD3DWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &offset)
-{
- QPoint wOffset = qt_qwidget_data(widget)->wrect.topLeft();
-
- QDirect3DPaintEngine *engine = qt_d3dEngine();
- LPDIRECT3DSWAPCHAIN9 swapchain = engine->swapChain(d_ptr->m_widget);
-
- if (swapchain) {
- QRect br = rgn.boundingRect();
- QRect wbr = br.translated(-wOffset);
-
- RECT destrect;
- destrect.left = wbr.x();
- destrect.top = wbr.y();
- destrect.right = destrect.left + wbr.width();
- destrect.bottom = destrect.top + wbr.height();
-
- RECT srcrect;
- srcrect.left = br.x() + offset.x();
- srcrect.top = br.y() + offset.y();
- srcrect.right = wbr.width() + srcrect.left;
- srcrect.bottom = wbr.height() + srcrect.top;
- int devwidth = d_ptr->m_lastSize.width();
- int devheight = d_ptr->m_lastSize.height();
-
- if (devwidth <= srcrect.right) {
- int diff = srcrect.right - devwidth;
- srcrect.right -= diff;
- destrect.right -= diff;
- if (srcrect.right <= srcrect.left)
- return;
- }
- if (devheight <= srcrect.bottom) {
- int diff = srcrect.bottom - devheight;
- srcrect.bottom -= diff;
- destrect.bottom -= diff;
- if (srcrect.bottom <= srcrect.top)
- return;
- }
-
- if (FAILED(swapchain->Present(&srcrect, &destrect, widget->winId(), 0, 0)))
- qWarning("QDirect3DPaintEngine: failed to present back buffer.");
-
-#ifdef D3D_DEBUG_BACKBUFFER
- qDebug() << widget << srcrect.left << srcrect.top << wbr.width() << wbr.height() << "Dest: " << destrect.left << destrect.top;
- IDirect3DSurface9 *surface;
- swapchain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &surface);
- QString filename("C:\\test.bmp");
- D3DXSaveSurfaceToFile(filename.utf16(), D3DXIFF_BMP, surface, 0, 0);
- surface->Release();
-#endif
- }
-}
-
-void QD3DWindowSurface::setGeometry(const QRect &rect)
-{
- if (rect.isEmpty())
- qt_d3dEngine()->releaseSwapChain(d_ptr->m_widget);
-
- d_ptr->m_lastSize = rect.size();
- QWindowSurface::setGeometry(rect);
-}
-
-
-bool QD3DWindowSurface::scroll(const QRegion &area, int dx, int dy)
-{
- QDirect3DPaintEngine *engine = qt_d3dEngine();
- QRect rect = area.boundingRect();
-
- RECT destrect;
- destrect.left = rect.x()+dx;
- destrect.top = rect.y()+dy;
- destrect.right = rect.width() + destrect.left;
- destrect.bottom = rect.height() + destrect.top;
-
- RECT srcrect;
- srcrect.left = rect.x();
- srcrect.top = rect.y();
- srcrect.right = rect.width() + srcrect.left;
- srcrect.bottom = rect.height() + srcrect.top;
-
- engine->scroll(d_ptr->m_widget, srcrect, destrect);
- return true;
-}
-
-QT_END_NAMESPACE
diff --git a/src/gui/painting/qwindowsurface_raster.cpp b/src/gui/painting/qwindowsurface_raster.cpp
index 97178a6..d1c8d4d 100644
--- a/src/gui/painting/qwindowsurface_raster.cpp
+++ b/src/gui/painting/qwindowsurface_raster.cpp
@@ -82,7 +82,7 @@ public:
uint translucentBackground : 1;
#endif
#endif
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
uint canUseLayeredWindow : 1;
#endif
uint inSetGeometry : 1;
@@ -98,7 +98,7 @@ QRasterWindowSurface::QRasterWindowSurface(QWidget *window)
&& window->x11Info().depth() == 32;
#endif
#endif
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
d_ptr->canUseLayeredWindow = ptrUpdateLayeredWindowIndirect
&& (qt_widget_private(window)->data.window_flags & Qt::FramelessWindowHint);
#endif
@@ -125,9 +125,9 @@ QPaintDevice *QRasterWindowSurface::paintDevice()
void QRasterWindowSurface::beginPaint(const QRegion &rgn)
{
-#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE))
+#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE))
if (!qt_widget_private(window())->isOpaque) {
-#if defined(Q_WS_WIN) && !defined(Q_OS_WINCE)
+#if defined(Q_WS_WIN) && !defined(Q_WS_WINCE)
if (d_ptr->image->image.format() != QImage::Format_ARGB32_Premultiplied
&& d_ptr->canUseLayeredWindow)
prepareBuffer(QImage::Format_ARGB32_Premultiplied, window());
@@ -157,7 +157,7 @@ void QRasterWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoi
#ifdef Q_WS_WIN
QRect br = rgn.boundingRect();
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (!qt_widget_private(window())->isOpaque && d->canUseLayeredWindow) {
QRect r = window()->frameGeometry();
QPoint frameOffset = qt_widget_private(window())->frameStrut().topLeft();
@@ -302,7 +302,7 @@ void QRasterWindowSurface::setGeometry(const QRect &rect)
Q_D(QRasterWindowSurface);
d->inSetGeometry = true;
if (d->image == 0 || d->image->width() < rect.width() || d->image->height() < rect.height()) {
-#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_OS_WINCE))
+#if (defined(Q_WS_X11) && !defined(QT_NO_XRENDER)) || (defined(Q_WS_WIN) && !defined(Q_WS_WINCE))
#ifndef Q_WS_WIN
if (d_ptr->translucentBackground)
#else
diff --git a/src/gui/painting/qwindowsurface_x11.cpp b/src/gui/painting/qwindowsurface_x11.cpp
index 9e8b498..f29d627 100644
--- a/src/gui/painting/qwindowsurface_x11.cpp
+++ b/src/gui/painting/qwindowsurface_x11.cpp
@@ -128,7 +128,7 @@ void QX11WindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint
return;
// qDebug() << "XSetClipRectangles";
// for (int i = 0; i < num; ++i)
-// qDebug() << " " << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
+// qDebug() << ' ' << i << rects[i].x << rects[i].x << rects[i].y << rects[i].width << rects[i].height;
XSetClipRectangles(X11->display, gc, 0, 0, rects, num, YXBanded);
XCopyArea(X11->display, d_ptr->device.handle(), widget->handle(), gc,
br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), wbr.x(), wbr.y());
diff --git a/src/gui/statemachine/qbasickeyeventtransition.cpp b/src/gui/statemachine/qbasickeyeventtransition.cpp
new file mode 100644
index 0000000..61362b2
--- /dev/null
+++ b/src/gui/statemachine/qbasickeyeventtransition.cpp
@@ -0,0 +1,208 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasickeyeventtransition_p.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+#include <qdebug.h>
+#include <private/qabstracttransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QBasicKeyEventTransition
+ \since 4.6
+ \ingroup statemachine
+
+ \brief The QBasicKeyEventTransition class provides a transition for Qt key events.
+*/
+
+class QBasicKeyEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QBasicKeyEventTransition)
+public:
+ QBasicKeyEventTransitionPrivate();
+
+ static QBasicKeyEventTransitionPrivate *get(QBasicKeyEventTransition *q);
+
+ QEvent::Type eventType;
+ int key;
+ Qt::KeyboardModifiers modifiersMask;
+};
+
+QBasicKeyEventTransitionPrivate::QBasicKeyEventTransitionPrivate()
+{
+ eventType = QEvent::None;
+ key = 0;
+ modifiersMask = Qt::NoModifier;
+}
+
+QBasicKeyEventTransitionPrivate *QBasicKeyEventTransitionPrivate::get(QBasicKeyEventTransition *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new key event transition with the given \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new event transition for events of the given \a type for the
+ given \a key, with the given \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+ d->key = key;
+}
+
+/*!
+ Constructs a new event transition for events of the given \a type for the
+ given \a key, with the given \a modifiersMask and \a sourceState.
+*/
+QBasicKeyEventTransition::QBasicKeyEventTransition(QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiersMask,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+ d->key = key;
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ Destroys this event transition.
+*/
+QBasicKeyEventTransition::~QBasicKeyEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this key event transition is associated with.
+*/
+QEvent::Type QBasicKeyEventTransition::eventType() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this key event transition is associated with.
+*/
+void QBasicKeyEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->eventType = type;
+}
+
+/*!
+ Returns the key that this key event transition checks for.
+*/
+int QBasicKeyEventTransition::key() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->key;
+}
+
+/*!
+ Sets the key that this key event transition will check for.
+*/
+void QBasicKeyEventTransition::setKey(int key)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->key = key;
+}
+
+/*!
+ Returns the keyboard modifiers mask that this key event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QBasicKeyEventTransition::modifiersMask() const
+{
+ Q_D(const QBasicKeyEventTransition);
+ return d->modifiersMask;
+}
+
+/*!
+ Sets the keyboard modifiers mask that this key event transition will check
+ for.
+*/
+void QBasicKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QBasicKeyEventTransition);
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ \reimp
+*/
+bool QBasicKeyEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QBasicKeyEventTransition);
+ if (event->type() == d->eventType) {
+ QKeyEvent *ke = static_cast<QKeyEvent*>(event);
+ return (ke->key() == d->key)
+ && ((ke->modifiers() & d->modifiersMask) == d->modifiersMask);
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QBasicKeyEventTransition::onTransition(QEvent *)
+{
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qbasickeyeventtransition_p.h b/src/gui/statemachine/qbasickeyeventtransition_p.h
new file mode 100644
index 0000000..aef1f99
--- /dev/null
+++ b/src/gui/statemachine/qbasickeyeventtransition_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICKEYEVENTTRANSITION_P_H
+#define QBASICKEYEVENTTRANSITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qabstracttransition.h>
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBasicKeyEventTransitionPrivate;
+class Q_AUTOTEST_EXPORT QBasicKeyEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+public:
+ QBasicKeyEventTransition(QState *sourceState = 0);
+ QBasicKeyEventTransition(QEvent::Type type, int key, QState *sourceState = 0);
+ QBasicKeyEventTransition(QEvent::Type type, int key,
+ Qt::KeyboardModifiers modifiersMask,
+ QState *sourceState = 0);
+ ~QBasicKeyEventTransition();
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+ int key() const;
+ void setKey(int key);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QBasicKeyEventTransition)
+ Q_DECLARE_PRIVATE(QBasicKeyEventTransition)
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
+
+#endif
diff --git a/src/gui/statemachine/qbasicmouseeventtransition.cpp b/src/gui/statemachine/qbasicmouseeventtransition.cpp
new file mode 100644
index 0000000..0304e28
--- /dev/null
+++ b/src/gui/statemachine/qbasicmouseeventtransition.cpp
@@ -0,0 +1,213 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbasicmouseeventtransition_p.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+#include <QtGui/qpainterpath.h>
+#include <qdebug.h>
+#include <private/qabstracttransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ \class QBasicMouseEventTransition
+ \since 4.6
+ \ingroup statemachine
+
+ \brief The QBasicMouseEventTransition class provides a transition for Qt mouse events.
+*/
+
+class QBasicMouseEventTransitionPrivate : public QAbstractTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QBasicMouseEventTransition)
+public:
+ QBasicMouseEventTransitionPrivate();
+
+ static QBasicMouseEventTransitionPrivate *get(QBasicMouseEventTransition *q);
+
+ QEvent::Type eventType;
+ Qt::MouseButton button;
+ Qt::KeyboardModifiers modifiersMask;
+ QPainterPath path;
+};
+
+QBasicMouseEventTransitionPrivate::QBasicMouseEventTransitionPrivate()
+{
+ eventType = QEvent::None;
+ button = Qt::NoButton;
+}
+
+QBasicMouseEventTransitionPrivate *QBasicMouseEventTransitionPrivate::get(QBasicMouseEventTransition *q)
+{
+ return q->d_func();
+}
+
+/*!
+ Constructs a new mouse event transition with the given \a sourceState.
+*/
+QBasicMouseEventTransition::QBasicMouseEventTransition(QState *sourceState)
+ : QAbstractTransition(*new QBasicMouseEventTransitionPrivate, sourceState)
+{
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type.
+*/
+QBasicMouseEventTransition::QBasicMouseEventTransition(QEvent::Type type,
+ Qt::MouseButton button,
+ QState *sourceState)
+ : QAbstractTransition(*new QBasicMouseEventTransitionPrivate, sourceState)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->eventType = type;
+ d->button = button;
+}
+
+/*!
+ Destroys this mouse event transition.
+*/
+QBasicMouseEventTransition::~QBasicMouseEventTransition()
+{
+}
+
+/*!
+ Returns the event type that this mouse event transition is associated with.
+*/
+QEvent::Type QBasicMouseEventTransition::eventType() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->eventType;
+}
+
+/*!
+ Sets the event \a type that this mouse event transition is associated with.
+*/
+void QBasicMouseEventTransition::setEventType(QEvent::Type type)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->eventType = type;
+}
+
+/*!
+ Returns the button that this mouse event transition checks for.
+*/
+Qt::MouseButton QBasicMouseEventTransition::button() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->button;
+}
+
+/*!
+ Sets the button that this mouse event transition will check for.
+*/
+void QBasicMouseEventTransition::setButton(Qt::MouseButton button)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->button = button;
+}
+
+/*!
+ Returns the keyboard modifiers mask that this mouse event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QBasicMouseEventTransition::modifiersMask() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->modifiersMask;
+}
+
+/*!
+ Sets the keyboard modifiers mask that this mouse event transition will check
+ for.
+*/
+void QBasicMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->modifiersMask = modifiersMask;
+}
+
+/*!
+ Returns the path for this mouse event transition.
+*/
+QPainterPath QBasicMouseEventTransition::path() const
+{
+ Q_D(const QBasicMouseEventTransition);
+ return d->path;
+}
+
+/*!
+ Sets the path for this mouse event transition.
+*/
+void QBasicMouseEventTransition::setPath(const QPainterPath &path)
+{
+ Q_D(QBasicMouseEventTransition);
+ d->path = path;
+}
+
+/*!
+ \reimp
+*/
+bool QBasicMouseEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QBasicMouseEventTransition);
+ if (event->type() == d->eventType) {
+ QMouseEvent *me = static_cast<QMouseEvent*>(event);
+ return (me->button() == d->button)
+ && ((me->modifiers() & d->modifiersMask) == d->modifiersMask)
+ && (d->path.isEmpty() || d->path.contains(me->pos()));
+ }
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QBasicMouseEventTransition::onTransition(QEvent *)
+{
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qbasicmouseeventtransition_p.h b/src/gui/statemachine/qbasicmouseeventtransition_p.h
new file mode 100644
index 0000000..ed0022a
--- /dev/null
+++ b/src/gui/statemachine/qbasicmouseeventtransition_p.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBASICMOUSEEVENTTRANSITION_P_H
+#define QBASICMOUSEEVENTTRANSITION_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qabstracttransition.h>
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <QtGui/qevent.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPainterPath;
+
+class QBasicMouseEventTransitionPrivate;
+class Q_AUTOTEST_EXPORT QBasicMouseEventTransition : public QAbstractTransition
+{
+ Q_OBJECT
+public:
+ QBasicMouseEventTransition(QState *sourceState = 0);
+ QBasicMouseEventTransition(QEvent::Type type, Qt::MouseButton button,
+ QState *sourceState = 0);
+ ~QBasicMouseEventTransition();
+
+ QEvent::Type eventType() const;
+ void setEventType(QEvent::Type type);
+
+ Qt::MouseButton button() const;
+ void setButton(Qt::MouseButton button);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+ QPainterPath path() const;
+ void setPath(const QPainterPath &path);
+
+protected:
+ bool eventTest(QEvent *event);
+ void onTransition(QEvent *);
+
+private:
+ Q_DISABLE_COPY(QBasicMouseEventTransition)
+ Q_DECLARE_PRIVATE(QBasicMouseEventTransition)
+};
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
+
+#endif
diff --git a/src/gui/statemachine/qguistatemachine.cpp b/src/gui/statemachine/qguistatemachine.cpp
new file mode 100644
index 0000000..69155a9
--- /dev/null
+++ b/src/gui/statemachine/qguistatemachine.cpp
@@ -0,0 +1,564 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qstatemachine.h>
+
+#ifndef QT_NO_STATEMACHINE
+
+#include <private/qstatemachine_p.h>
+#include <QtGui/qevent.h>
+#include <QtGui/qgraphicssceneevent.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_CORE_EXPORT const QStateMachinePrivate::Handler *qcoreStateMachineHandler();
+
+static QEvent *cloneEvent(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseMove:
+ return new QMouseEvent(*static_cast<QMouseEvent*>(e));
+ case QEvent::KeyPress:
+ case QEvent::KeyRelease:
+ return new QKeyEvent(*static_cast<QKeyEvent*>(e));
+ case QEvent::FocusIn:
+ case QEvent::FocusOut:
+ return new QFocusEvent(*static_cast<QFocusEvent*>(e));
+ case QEvent::Enter:
+ return new QEvent(*e);
+ case QEvent::Leave:
+ return new QEvent(*e);
+ break;
+ case QEvent::Paint:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Move:
+ return new QMoveEvent(*static_cast<QMoveEvent*>(e));
+ case QEvent::Resize:
+ return new QResizeEvent(*static_cast<QResizeEvent*>(e));
+ case QEvent::Create:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Destroy:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Show:
+ return new QShowEvent(*static_cast<QShowEvent*>(e));
+ case QEvent::Hide:
+ return new QHideEvent(*static_cast<QHideEvent*>(e));
+ case QEvent::Close:
+ return new QCloseEvent(*static_cast<QCloseEvent*>(e));
+ case QEvent::Quit:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ParentChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ParentAboutToChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ThreadChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::WindowActivate:
+ case QEvent::WindowDeactivate:
+ return new QEvent(*e);
+
+ case QEvent::ShowToParent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HideToParent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Wheel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowTitleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowIconChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationWindowIconChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationFontChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationLayoutDirectionChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationPaletteChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::PaletteChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Clipboard:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Speech:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::MetaCall:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::SockAct:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WinEventAct:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DeferredDelete:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DragEnter:
+ return new QDragEnterEvent(*static_cast<QDragEnterEvent*>(e));
+ case QEvent::DragMove:
+ return new QDragMoveEvent(*static_cast<QDragMoveEvent*>(e));
+ case QEvent::DragLeave:
+ return new QDragLeaveEvent(*static_cast<QDragLeaveEvent*>(e));
+ case QEvent::Drop:
+ return new QDropEvent(*static_cast<QDragMoveEvent*>(e));
+ case QEvent::DragResponse:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildAdded:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildPolished:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#ifdef QT3_SUPPORT
+ case QEvent::ChildInsertedRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ChildInserted:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutHint:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::ChildRemoved:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ShowWindowRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::PolishRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Polish:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::UpdateRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::UpdateLater:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::EmbeddingControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ActivateControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::DeactivateControl:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ContextMenu:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::InputMethod:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccessibilityPrepare:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LocaleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LanguageChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LayoutDirectionChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::Style:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletPress:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletRelease:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::OkRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HelpRequest:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::IconDrag:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::FontChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::EnabledChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ActivationChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::StyleChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::IconTextChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ModifiedChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::MouseTrackingChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::WindowBlocked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowUnblocked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WindowStateChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ToolTip:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::WhatsThis:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::StatusTip:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ActionChanged:
+ case QEvent::ActionAdded:
+ case QEvent::ActionRemoved:
+ return new QActionEvent(*static_cast<QActionEvent*>(e));
+
+ case QEvent::FileOpen:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::Shortcut:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ShortcutOverride:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+#ifdef QT3_SUPPORT
+ case QEvent::Accel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccelAvailable:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+
+ case QEvent::WhatsThisClicked:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ToolBarChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ApplicationActivate:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ApplicationDeactivate:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::QueryWhatsThis:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::EnterWhatsThisMode:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LeaveWhatsThisMode:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ZOrderChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::HoverEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HoverLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::HoverMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::AccessibilityHelp:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::AccessibilityDescription:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+#ifdef QT_KEYPAD_NAVIGATION
+ case QEvent::EnterEditFocus:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::LeaveEditFocus:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::AcceptDropsChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MenubarUpdated:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ZeroTimerEvent:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GraphicsSceneMouseMove:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseDoubleClick: {
+ QGraphicsSceneMouseEvent *me = static_cast<QGraphicsSceneMouseEvent*>(e);
+ QGraphicsSceneMouseEvent *me2 = new QGraphicsSceneMouseEvent(me->type());
+ me2->setWidget(me->widget());
+ me2->setPos(me->pos());
+ me2->setScenePos(me->scenePos());
+ me2->setScreenPos(me->screenPos());
+// ### for all buttons
+ me2->setButtonDownPos(Qt::LeftButton, me->buttonDownPos(Qt::LeftButton));
+ me2->setButtonDownPos(Qt::RightButton, me->buttonDownPos(Qt::RightButton));
+ me2->setButtonDownScreenPos(Qt::LeftButton, me->buttonDownScreenPos(Qt::LeftButton));
+ me2->setButtonDownScreenPos(Qt::RightButton, me->buttonDownScreenPos(Qt::RightButton));
+ me2->setLastPos(me->lastPos());
+ me2->setLastScenePos(me->lastScenePos());
+ me2->setLastScreenPos(me->lastScreenPos());
+ me2->setButtons(me->buttons());
+ me2->setButton(me->button());
+ me2->setModifiers(me->modifiers());
+ return me2;
+ }
+
+ case QEvent::GraphicsSceneContextMenu: {
+ QGraphicsSceneContextMenuEvent *me = static_cast<QGraphicsSceneContextMenuEvent*>(e);
+ QGraphicsSceneContextMenuEvent *me2 = new QGraphicsSceneContextMenuEvent(me->type());
+ me2->setWidget(me->widget());
+ me2->setPos(me->pos());
+ me2->setScenePos(me->scenePos());
+ me2->setScreenPos(me->screenPos());
+ me2->setModifiers(me->modifiers());
+ me2->setReason(me->reason());
+ return me2;
+ }
+
+ case QEvent::GraphicsSceneHoverEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHoverMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHoverLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneHelp:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragEnter:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDragLeave:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneDrop:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneWheel:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::KeyboardLayoutChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::DynamicPropertyChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::TabletEnterProximity:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::TabletLeaveProximity:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::NonClientAreaMouseMove:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonPress:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonRelease:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MacSizeChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::ContentsRectChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::MacGLWindowChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::FutureCallOut:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GraphicsSceneResize:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::GraphicsSceneMove: {
+ QGraphicsSceneMoveEvent *me = static_cast<QGraphicsSceneMoveEvent*>(e);
+ QGraphicsSceneMoveEvent *me2 = new QGraphicsSceneMoveEvent();
+ me2->setWidget(me->widget());
+ me2->setNewPos(me->newPos());
+ me2->setOldPos(me->oldPos());
+ return me2;
+ }
+
+ case QEvent::CursorChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ case QEvent::ToolTipChange:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::NetworkReplyUpdated:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+
+ case QEvent::GrabMouse:
+ case QEvent::UngrabMouse:
+ case QEvent::GrabKeyboard:
+ case QEvent::UngrabKeyboard:
+ return new QEvent(*e);
+
+#ifdef QT_MAC_USE_COCOA
+ case QEvent::CocoaRequestModal:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+#endif
+ case QEvent::User:
+ case QEvent::MaxUser:
+ Q_ASSERT_X(false, "cloneEvent()", "not implemented");
+ break;
+ default:
+ ;
+ }
+ return qcoreStateMachineHandler()->cloneEvent(e);
+}
+
+const QStateMachinePrivate::Handler qt_gui_statemachine_handler = {
+ cloneEvent
+};
+
+static const QStateMachinePrivate::Handler *qt_guistatemachine_last_handler = 0;
+int qRegisterGuiStateMachine()
+{
+ qt_guistatemachine_last_handler = QStateMachinePrivate::handler;
+ QStateMachinePrivate::handler = &qt_gui_statemachine_handler;
+ return 1;
+}
+Q_CONSTRUCTOR_FUNCTION(qRegisterGuiStateMachine)
+
+int qUnregisterGuiStateMachine()
+{
+ QStateMachinePrivate::handler = qt_guistatemachine_last_handler;
+ return 1;
+}
+Q_DESTRUCTOR_FUNCTION(qUnregisterGuiStateMachine)
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qkeyeventtransition.cpp b/src/gui/statemachine/qkeyeventtransition.cpp
new file mode 100644
index 0000000..fee9f81
--- /dev/null
+++ b/src/gui/statemachine/qkeyeventtransition.cpp
@@ -0,0 +1,191 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkeyeventtransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qbasickeyeventtransition_p.h"
+#include <QtCore/qwrappedevent.h>
+#include <private/qeventtransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QKeyEventTransition
+
+ \brief The QKeyEventTransition class provides a transition for key events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QKeyEventTransition is part of \l{The State Machine Framework}.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QKeyEventTransition::key
+
+ \brief the key that this key event transition is associated with
+*/
+
+/*!
+ \property QKeyEventTransition::modifiersMask
+
+ \brief the keyboard modifiers mask that this key event transition checks for
+*/
+
+class QKeyEventTransitionPrivate : public QEventTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QKeyEventTransition)
+public:
+ QKeyEventTransitionPrivate() {}
+
+ QBasicKeyEventTransition *transition;
+};
+
+/*!
+ Constructs a new key event transition with the given \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition();
+}
+
+/*!
+ Constructs a new key event transition for events of the given \a type for
+ the given \a object, with the given \a key and \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type,
+ int key, QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, object, type, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition(type, key);
+}
+
+/*!
+ Constructs a new key event transition for events of the given \a type for
+ the given \a object, with the given \a key, \a targets and \a sourceState.
+*/
+QKeyEventTransition::QKeyEventTransition(QObject *object, QEvent::Type type,
+ int key, const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QEventTransition(*new QKeyEventTransitionPrivate, object, type, targets, sourceState)
+{
+ Q_D(QKeyEventTransition);
+ d->transition = new QBasicKeyEventTransition(type, key);
+}
+
+/*!
+ Destroys this key event transition.
+*/
+QKeyEventTransition::~QKeyEventTransition()
+{
+ Q_D(QKeyEventTransition);
+ delete d->transition;
+}
+
+/*!
+ Returns the key that this key event transition checks for.
+*/
+int QKeyEventTransition::key() const
+{
+ Q_D(const QKeyEventTransition);
+ return d->transition->key();
+}
+
+/*!
+ Sets the key that this key event transition will check for.
+*/
+void QKeyEventTransition::setKey(int key)
+{
+ Q_D(QKeyEventTransition);
+ d->transition->setKey(key);
+}
+
+/*!
+ Returns the keyboard modifiers mask that this key event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QKeyEventTransition::modifiersMask() const
+{
+ Q_D(const QKeyEventTransition);
+ return d->transition->modifiersMask();
+}
+
+/*!
+ Sets the keyboard \a modifiers mask that this key event transition will
+ check for.
+*/
+void QKeyEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QKeyEventTransition);
+ d->transition->setModifiersMask(modifiersMask);
+}
+
+/*!
+ \reimp
+*/
+bool QKeyEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QKeyEventTransition);
+ if (!QEventTransition::eventTest(event))
+ return false;
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ d->transition->setEventType(we->event()->type());
+ return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event());
+}
+
+/*!
+ \reimp
+*/
+void QKeyEventTransition::onTransition(QEvent *event)
+{
+ QEventTransition::onTransition(event);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qkeyeventtransition.h b/src/gui/statemachine/qkeyeventtransition.h
new file mode 100644
index 0000000..c9e06f5
--- /dev/null
+++ b/src/gui/statemachine/qkeyeventtransition.h
@@ -0,0 +1,91 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKEYEVENTTRANSITION_H
+#define QKEYEVENTTRANSITION_H
+
+#include <QtCore/qeventtransition.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QKeyEventTransitionPrivate;
+class Q_GUI_EXPORT QKeyEventTransition : public QEventTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(int key READ key WRITE setKey)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask)
+public:
+ QKeyEventTransition(QState *sourceState = 0);
+ QKeyEventTransition(QObject *object, QEvent::Type type, int key,
+ QState *sourceState = 0);
+ QKeyEventTransition(QObject *object, QEvent::Type type, int key,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState = 0);
+ ~QKeyEventTransition();
+
+ int key() const;
+ void setKey(int key);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+protected:
+ void onTransition(QEvent *event);
+ bool eventTest(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QKeyEventTransition)
+ Q_DECLARE_PRIVATE(QKeyEventTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/qmouseeventtransition.cpp b/src/gui/statemachine/qmouseeventtransition.cpp
new file mode 100644
index 0000000..6ae3d36
--- /dev/null
+++ b/src/gui/statemachine/qmouseeventtransition.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouseeventtransition.h"
+
+#ifndef QT_NO_STATEMACHINE
+
+#include "qbasicmouseeventtransition_p.h"
+#include <QtCore/qwrappedevent.h>
+#include <QtGui/qpainterpath.h>
+#include <private/qeventtransition_p.h>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMouseEventTransition
+
+ \brief The QMouseEventTransition class provides a transition for mouse events.
+
+ \since 4.6
+ \ingroup statemachine
+
+ QMouseEventTransition is part of \l{The State Machine Framework}.
+
+ \sa QState::addTransition()
+*/
+
+/*!
+ \property QMouseEventTransition::button
+
+ \brief the button that this mouse event transition is associated with
+*/
+
+/*!
+ \property QMouseEventTransition::modifiersMask
+
+ \brief the keyboard modifiers mask that this mouse event transition checks for
+*/
+
+class QMouseEventTransitionPrivate : public QEventTransitionPrivate
+{
+ Q_DECLARE_PUBLIC(QMouseEventTransition)
+public:
+ QMouseEventTransitionPrivate();
+
+ QBasicMouseEventTransition *transition;
+};
+
+QMouseEventTransitionPrivate::QMouseEventTransitionPrivate()
+{
+}
+
+/*!
+ Constructs a new mouse event transition with the given \a sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition();
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type for
+ the given \a object, with the given \a button and \a sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, object, type, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition(type, button);
+}
+
+/*!
+ Constructs a new mouse event transition for events of the given \a type for
+ the given \a object, with the given \a button, \a targets and \a
+ sourceState.
+*/
+QMouseEventTransition::QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState)
+ : QEventTransition(*new QMouseEventTransitionPrivate, object, type, targets, sourceState)
+{
+ Q_D(QMouseEventTransition);
+ d->transition = new QBasicMouseEventTransition(type, button);
+}
+
+/*!
+ Destroys this mouse event transition.
+*/
+QMouseEventTransition::~QMouseEventTransition()
+{
+ Q_D(QMouseEventTransition);
+ delete d->transition;
+}
+
+/*!
+ Returns the button that this mouse event transition checks for.
+*/
+Qt::MouseButton QMouseEventTransition::button() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->button();
+}
+
+/*!
+ Sets the \a button that this mouse event transition will check for.
+*/
+void QMouseEventTransition::setButton(Qt::MouseButton button)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setButton(button);
+}
+
+/*!
+ Returns the keyboard modifiers mask that this mouse event transition checks
+ for.
+*/
+Qt::KeyboardModifiers QMouseEventTransition::modifiersMask() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->modifiersMask();
+}
+
+/*!
+ Sets the keyboard \a modifiers mask that this mouse event transition will
+ check for.
+*/
+void QMouseEventTransition::setModifiersMask(Qt::KeyboardModifiers modifiersMask)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setModifiersMask(modifiersMask);
+}
+
+/*!
+ Returns the path for this mouse event transition.
+*/
+QPainterPath QMouseEventTransition::path() const
+{
+ Q_D(const QMouseEventTransition);
+ return d->transition->path();
+}
+
+/*!
+ Sets the \a path for this mouse event transition.
+ If a valid path has been set, the transition will only trigger if the mouse
+ event position (QMouseEvent::pos()) is inside the path.
+
+ \sa QPainterPath::contains()
+*/
+void QMouseEventTransition::setPath(const QPainterPath &path)
+{
+ Q_D(QMouseEventTransition);
+ d->transition->setPath(path);
+}
+
+/*!
+ \reimp
+*/
+bool QMouseEventTransition::eventTest(QEvent *event)
+{
+ Q_D(const QMouseEventTransition);
+ if (!QEventTransition::eventTest(event))
+ return false;
+ QWrappedEvent *we = static_cast<QWrappedEvent*>(event);
+ d->transition->setEventType(we->event()->type());
+ return QAbstractTransitionPrivate::get(d->transition)->callEventTest(we->event());
+}
+
+/*!
+ \reimp
+*/
+void QMouseEventTransition::onTransition(QEvent *event)
+{
+ QEventTransition::onTransition(event);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_STATEMACHINE
diff --git a/src/gui/statemachine/qmouseeventtransition.h b/src/gui/statemachine/qmouseeventtransition.h
new file mode 100644
index 0000000..557b2c3
--- /dev/null
+++ b/src/gui/statemachine/qmouseeventtransition.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEEVENTTRANSITION_H
+#define QMOUSEEVENTTRANSITION_H
+
+#include <QtCore/qeventtransition.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_STATEMACHINE
+
+class QMouseEventTransitionPrivate;
+class QPainterPath;
+class Q_GUI_EXPORT QMouseEventTransition : public QEventTransition
+{
+ Q_OBJECT
+ Q_PROPERTY(Qt::MouseButton button READ button WRITE setButton)
+ Q_PROPERTY(Qt::KeyboardModifiers modifiersMask READ modifiersMask WRITE setModifiersMask)
+public:
+ QMouseEventTransition(QState *sourceState = 0);
+ QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button, QState *sourceState = 0);
+ QMouseEventTransition(QObject *object, QEvent::Type type,
+ Qt::MouseButton button,
+ const QList<QAbstractState*> &targets,
+ QState *sourceState = 0);
+ ~QMouseEventTransition();
+
+ Qt::MouseButton button() const;
+ void setButton(Qt::MouseButton button);
+
+ Qt::KeyboardModifiers modifiersMask() const;
+ void setModifiersMask(Qt::KeyboardModifiers modifiers);
+
+ QPainterPath path() const;
+ void setPath(const QPainterPath &path);
+
+protected:
+ void onTransition(QEvent *event);
+ bool eventTest(QEvent *event);
+
+private:
+ Q_DISABLE_COPY(QMouseEventTransition)
+ Q_DECLARE_PRIVATE(QMouseEventTransition)
+};
+
+#endif //QT_NO_STATEMACHINE
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/statemachine/statemachine.pri b/src/gui/statemachine/statemachine.pri
new file mode 100644
index 0000000..2eb1e05
--- /dev/null
+++ b/src/gui/statemachine/statemachine.pri
@@ -0,0 +1,13 @@
+SOURCES += $$PWD/qguistatemachine.cpp
+!contains(DEFINES, QT_NO_STATEMACHINE_EVENTFILTER) {
+ HEADERS += \
+ $$PWD/qkeyeventtransition.h \
+ $$PWD/qmouseeventtransition.h \
+ $$PWD/qbasickeyeventtransition_p.h \
+ $$PWD/qbasicmouseeventtransition_p.h
+ SOURCES += \
+ $$PWD/qkeyeventtransition.cpp \
+ $$PWD/qmouseeventtransition.cpp \
+ $$PWD/qbasickeyeventtransition.cpp \
+ $$PWD/qbasicmouseeventtransition.cpp
+}
diff --git a/src/gui/styles/gtksymbols.cpp b/src/gui/styles/gtksymbols.cpp
index d8a67c2..f92fd0e 100644
--- a/src/gui/styles/gtksymbols.cpp
+++ b/src/gui/styles/gtksymbols.cpp
@@ -207,118 +207,118 @@ static QString classPath(GtkWidget *widget)
static void resolveGtk()
{
- const QString GTK_PATH(QLS("gtk-x11-2.0"));
- QGtk::gtk_init = (Ptr_gtk_init)QLibrary::resolve(GTK_PATH, 0, "gtk_init");
- QGtk::gtk_window_new = (Ptr_gtk_window_new)QLibrary::resolve(GTK_PATH, 0, "gtk_window_new");
- QGtk::gtk_style_attach = (Ptr_gtk_style_attach)QLibrary::resolve(GTK_PATH, 0, "gtk_style_attach");
- QGtk::gtk_widget_destroy = (Ptr_gtk_widget_destroy)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_destroy");
- QGtk::gtk_widget_realize = (Ptr_gtk_widget_realize)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_realize");
-
- QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_folder");
- QGtk::gtk_file_filter_new = (Ptr_gtk_file_filter_new)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_new");
- QGtk::gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_set_name");
- QGtk::gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)QLibrary::resolve(GTK_PATH, 0, "gtk_file_filter_add_pattern");
- QGtk::gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_add_filter");
- QGtk::gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_filter");
- QGtk::gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_dialog_new");
- QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_folder");
- QGtk::gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_get_filename");
- QGtk::gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_get_filenames");
- QGtk::gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_current_name");
- QGtk::gtk_dialog_run = (Ptr_gtk_dialog_run)QLibrary::resolve(GTK_PATH, 0, "gtk_dialog_run");
- QGtk::gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)QLibrary::resolve(GTK_PATH, 0, "gtk_file_chooser_set_filename");
-
- QGtk::gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_pixels");
- QGtk::gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_width");
- QGtk::gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_height");
- QGtk::gdk_pixmap_new = (Ptr_gdk_pixmap_new)QLibrary::resolve(GTK_PATH, 0, "gdk_pixmap_new");
- QGtk::gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_new");
- QGtk::gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_get_from_drawable");
- QGtk::gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)QLibrary::resolve(GTK_PATH, 0, "gdk_draw_rectangle");
- QGtk::gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)QLibrary::resolve(GTK_PATH, 0, "gdk_pixbuf_unref");
- QGtk::gdk_drawable_unref = (Ptr_gdk_drawable_unref)QLibrary::resolve(GTK_PATH, 0, "gdk_drawable_unref");
- QGtk::gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)QLibrary::resolve(GTK_PATH, 0, "gdk_drawable_get_depth");
- QGtk::gdk_color_free = (Ptr_gdk_color_free)QLibrary::resolve(GTK_PATH, 0, "gdk_color_free");
- QGtk::gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_window_set_user_time");
- QGtk::gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_drawable_get_xid");
- QGtk::gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)QLibrary::resolve(GTK_PATH, 0, "gdk_x11_drawable_get_xdisplay");
-
- QGtk::gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_set_default_direction");
- QGtk::gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_modify_fg");
- QGtk::gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_modify_bg");
- QGtk::gtk_arrow_new = (Ptr_gtk_arrow_new)QLibrary::resolve(GTK_PATH, 0, "gtk_arrow_new");
- QGtk::gtk_menu_item_new = (Ptr_gtk_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_item_new");
- QGtk::gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_check_menu_item_new");
- QGtk::gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_bar_new");
- QGtk::gtk_menu_new = (Ptr_gtk_menu_new)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_new");
- QGtk::gtk_toolbar_new = (Ptr_gtk_toolbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_toolbar_new");
- QGtk::gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_separator_tool_item_new");
- QGtk::gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)QLibrary::resolve(GTK_PATH, 0, "gtk_toolbar_insert");
- QGtk::gtk_button_new = (Ptr_gtk_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_button_new");
- QGtk::gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hbutton_box_new");
- QGtk::gtk_check_button_new = (Ptr_gtk_check_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_check_button_new");
- QGtk::gtk_radio_button_new = (Ptr_gtk_radio_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_radio_button_new");
- QGtk::gtk_notebook_new = (Ptr_gtk_notebook_new)QLibrary::resolve(GTK_PATH, 0, "gtk_notebook_new");
- QGtk::gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_progress_bar_new");
- QGtk::gtk_spin_button_new = (Ptr_gtk_spin_button_new)QLibrary::resolve(GTK_PATH, 0, "gtk_spin_button_new");
- QGtk::gtk_hscale_new = (Ptr_gtk_hscale_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hscale_new");
- QGtk::gtk_vscale_new = (Ptr_gtk_vscale_new)QLibrary::resolve(GTK_PATH, 0, "gtk_vscale_new");
- QGtk::gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_hscrollbar_new");
- QGtk::gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_vscrollbar_new");
- QGtk::gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)QLibrary::resolve(GTK_PATH, 0, "gtk_scrolled_window_new");
- QGtk::gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_shell_append");
- QGtk::gtk_entry_new = (Ptr_gtk_entry_new)QLibrary::resolve(GTK_PATH, 0, "gtk_entry_new");
- QGtk::gtk_tree_view_new = (Ptr_gtk_tree_view_new)QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_new");
- QGtk::gtk_combo_box_new = (Ptr_gtk_combo_box_new)QLibrary::resolve(GTK_PATH, 0, "gtk_combo_box_new");
- QGtk::gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)QLibrary::resolve(GTK_PATH, 0, "gtk_progress_set_adjustment");
- QGtk::gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)QLibrary::resolve(GTK_PATH, 0, "gtk_range_set_adjustment");
- QGtk::gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)QLibrary::resolve(GTK_PATH, 0, "gtk_range_set_inverted");
- QGtk::gtk_container_add = (Ptr_gtk_container_add)QLibrary::resolve(GTK_PATH, 0, "gtk_container_add");
- QGtk::gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)QLibrary::resolve(GTK_PATH, 0, "gtk_icon_factory_lookup_default");
- QGtk::gtk_widget_style_get = (Ptr_gtk_widget_style_get)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_style_get");
- QGtk::gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)QLibrary::resolve(GTK_PATH, 0, "gtk_icon_set_render_icon");
- QGtk::gtk_fixed_new = (Ptr_gtk_fixed_new)QLibrary::resolve(GTK_PATH, 0, "gtk_fixed_new");
- QGtk::gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_column_new");
- QGtk::gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_append_column");
- QGtk::gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )QLibrary::resolve(GTK_PATH, 0, "gtk_tree_view_get_column");
- QGtk::gtk_paint_check = (Ptr_gtk_paint_check)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_check");
- QGtk::gtk_paint_box = (Ptr_gtk_paint_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box");
- QGtk::gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_flat_box");
- QGtk::gtk_paint_check = (Ptr_gtk_paint_check)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_check");
- QGtk::gtk_paint_box = (Ptr_gtk_paint_box)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box");
- QGtk::gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_resize_grip");
- QGtk::gtk_paint_focus = (Ptr_gtk_paint_focus)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_focus");
- QGtk::gtk_paint_shadow = (Ptr_gtk_paint_shadow)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_shadow");
- QGtk::gtk_paint_slider = (Ptr_gtk_paint_slider)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_slider");
- QGtk::gtk_paint_expander = (Ptr_gtk_paint_expander)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_expander");
- QGtk::gtk_paint_handle = (Ptr_gtk_paint_handle)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_handle");
- QGtk::gtk_paint_option = (Ptr_gtk_paint_option)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_option");
- QGtk::gtk_paint_arrow = (Ptr_gtk_paint_arrow)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_arrow");
- QGtk::gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_box_gap");
- QGtk::gtk_paint_extension = (Ptr_gtk_paint_extension)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_extension");
- QGtk::gtk_paint_hline = (Ptr_gtk_paint_hline)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_hline");
- QGtk::gtk_paint_vline = (Ptr_gtk_paint_vline)QLibrary::resolve(GTK_PATH, 0, "gtk_paint_vline");
- QGtk::gtk_adjustment_new = (Ptr_gtk_adjustment_new)QLibrary::resolve(GTK_PATH, 0, "gtk_adjustment_new");
- QGtk::gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)QLibrary::resolve(GTK_PATH, 0, "gtk_menu_item_set_submenu");
- QGtk::gtk_settings_get_default = (Ptr_gtk_settings_get_default)QLibrary::resolve(GTK_PATH, 0, "gtk_settings_get_default");
- QGtk::gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)QLibrary::resolve(GTK_PATH, 0, "gtk_separator_menu_item_new");
- QGtk::gtk_frame_new = (Ptr_gtk_frame_new)QLibrary::resolve(GTK_PATH, 0, "gtk_frame_new");
- QGtk::gtk_expander_new = (Ptr_gtk_expander_new)QLibrary::resolve(GTK_PATH, 0, "gtk_expander_new");
- QGtk::gtk_statusbar_new = (Ptr_gtk_statusbar_new)QLibrary::resolve(GTK_PATH, 0, "gtk_statusbar_new");
- QGtk::gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)QLibrary::resolve(GTK_PATH, 0, "gtk_combo_box_entry_new");
- QGtk::gtk_container_forall = (Ptr_gtk_container_forall)QLibrary::resolve(GTK_PATH, 0, "gtk_container_forall");
- QGtk::gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_size_allocate");
- QGtk::gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_set_direction");
- QGtk::gtk_widget_path =(Ptr_gtk_widget_path)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_path");
- QGtk::gtk_container_get_type =(Ptr_gtk_container_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_container_get_type");
- QGtk::gtk_window_get_type =(Ptr_gtk_window_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_window_get_type");
- QGtk::gtk_widget_get_type =(Ptr_gtk_widget_get_type)QLibrary::resolve(GTK_PATH, 0, "gtk_widget_get_type");
- QGtk::gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)QLibrary::resolve(GTK_PATH, 0, "gtk_rc_get_style_by_paths");
- QGtk::gtk_check_version =(Ptr_gtk_check_version)QLibrary::resolve(GTK_PATH, 0, "gtk_check_version");
- QGtk::pango_font_description_get_size = (Ptr_pango_font_description_get_size)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_size");
- QGtk::pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_weight");
- QGtk::pango_font_description_get_family = (Ptr_pango_font_description_get_family)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_family");
- QGtk::pango_font_description_get_style = (Ptr_pango_font_description_get_style)QLibrary::resolve(GTK_PATH, 0, "pango_font_description_get_style");
+ QLibrary libgtk(QLS("gtk-x11-2.0"));
+ QGtk::gtk_init = (Ptr_gtk_init)libgtk.resolve("gtk_init");
+ QGtk::gtk_window_new = (Ptr_gtk_window_new)libgtk.resolve("gtk_window_new");
+ QGtk::gtk_style_attach = (Ptr_gtk_style_attach)libgtk.resolve("gtk_style_attach");
+ QGtk::gtk_widget_destroy = (Ptr_gtk_widget_destroy)libgtk.resolve("gtk_widget_destroy");
+ QGtk::gtk_widget_realize = (Ptr_gtk_widget_realize)libgtk.resolve("gtk_widget_realize");
+
+ QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder");
+ QGtk::gtk_file_filter_new = (Ptr_gtk_file_filter_new)libgtk.resolve("gtk_file_filter_new");
+ QGtk::gtk_file_filter_set_name = (Ptr_gtk_file_filter_set_name)libgtk.resolve("gtk_file_filter_set_name");
+ QGtk::gtk_file_filter_add_pattern = (Ptr_gtk_file_filter_add_pattern)libgtk.resolve("gtk_file_filter_add_pattern");
+ QGtk::gtk_file_chooser_add_filter = (Ptr_gtk_file_chooser_add_filter)libgtk.resolve("gtk_file_chooser_add_filter");
+ QGtk::gtk_file_chooser_set_filter = (Ptr_gtk_file_chooser_set_filter)libgtk.resolve("gtk_file_chooser_set_filter");
+ QGtk::gtk_file_chooser_dialog_new = (Ptr_gtk_file_chooser_dialog_new)libgtk.resolve("gtk_file_chooser_dialog_new");
+ QGtk::gtk_file_chooser_set_current_folder = (Ptr_gtk_file_chooser_set_current_folder)libgtk.resolve("gtk_file_chooser_set_current_folder");
+ QGtk::gtk_file_chooser_get_filename = (Ptr_gtk_file_chooser_get_filename)libgtk.resolve("gtk_file_chooser_get_filename");
+ QGtk::gtk_file_chooser_get_filenames = (Ptr_gtk_file_chooser_get_filenames)libgtk.resolve("gtk_file_chooser_get_filenames");
+ QGtk::gtk_file_chooser_set_current_name = (Ptr_gtk_file_chooser_set_current_name)libgtk.resolve("gtk_file_chooser_set_current_name");
+ QGtk::gtk_dialog_run = (Ptr_gtk_dialog_run)libgtk.resolve("gtk_dialog_run");
+ QGtk::gtk_file_chooser_set_filename = (Ptr_gtk_file_chooser_set_filename)libgtk.resolve("gtk_file_chooser_set_filename");
+
+ QGtk::gdk_pixbuf_get_pixels = (Ptr_gdk_pixbuf_get_pixels)libgtk.resolve("gdk_pixbuf_get_pixels");
+ QGtk::gdk_pixbuf_get_width = (Ptr_gdk_pixbuf_get_width)libgtk.resolve("gdk_pixbuf_get_width");
+ QGtk::gdk_pixbuf_get_height = (Ptr_gdk_pixbuf_get_height)libgtk.resolve("gdk_pixbuf_get_height");
+ QGtk::gdk_pixmap_new = (Ptr_gdk_pixmap_new)libgtk.resolve("gdk_pixmap_new");
+ QGtk::gdk_pixbuf_new = (Ptr_gdk_pixbuf_new)libgtk.resolve("gdk_pixbuf_new");
+ QGtk::gdk_pixbuf_get_from_drawable = (Ptr_gdk_pixbuf_get_from_drawable)libgtk.resolve("gdk_pixbuf_get_from_drawable");
+ QGtk::gdk_draw_rectangle = (Ptr_gdk_draw_rectangle)libgtk.resolve("gdk_draw_rectangle");
+ QGtk::gdk_pixbuf_unref = (Ptr_gdk_pixbuf_unref)libgtk.resolve("gdk_pixbuf_unref");
+ QGtk::gdk_drawable_unref = (Ptr_gdk_drawable_unref)libgtk.resolve("gdk_drawable_unref");
+ QGtk::gdk_drawable_get_depth = (Ptr_gdk_drawable_get_depth)libgtk.resolve("gdk_drawable_get_depth");
+ QGtk::gdk_color_free = (Ptr_gdk_color_free)libgtk.resolve("gdk_color_free");
+ QGtk::gdk_x11_window_set_user_time = (Ptr_gdk_x11_window_set_user_time)libgtk.resolve("gdk_x11_window_set_user_time");
+ QGtk::gdk_x11_drawable_get_xid = (Ptr_gdk_x11_drawable_get_xid)libgtk.resolve("gdk_x11_drawable_get_xid");
+ QGtk::gdk_x11_drawable_get_xdisplay = (Ptr_gdk_x11_drawable_get_xdisplay)libgtk.resolve("gdk_x11_drawable_get_xdisplay");
+
+ QGtk::gtk_widget_set_default_direction = (Ptr_gtk_widget_set_default_direction)libgtk.resolve("gtk_widget_set_default_direction");
+ QGtk::gtk_widget_modify_fg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_fg");
+ QGtk::gtk_widget_modify_bg = (Ptr_gtk_widget_modify_color)libgtk.resolve("gtk_widget_modify_bg");
+ QGtk::gtk_arrow_new = (Ptr_gtk_arrow_new)libgtk.resolve("gtk_arrow_new");
+ QGtk::gtk_menu_item_new = (Ptr_gtk_menu_item_new)libgtk.resolve("gtk_menu_item_new");
+ QGtk::gtk_check_menu_item_new = (Ptr_gtk_check_menu_item_new)libgtk.resolve("gtk_check_menu_item_new");
+ QGtk::gtk_menu_bar_new = (Ptr_gtk_menu_bar_new)libgtk.resolve("gtk_menu_bar_new");
+ QGtk::gtk_menu_new = (Ptr_gtk_menu_new)libgtk.resolve("gtk_menu_new");
+ QGtk::gtk_toolbar_new = (Ptr_gtk_toolbar_new)libgtk.resolve("gtk_toolbar_new");
+ QGtk::gtk_separator_tool_item_new = (Ptr_gtk_separator_tool_item_new)libgtk.resolve("gtk_separator_tool_item_new");
+ QGtk::gtk_toolbar_insert = (Ptr_gtk_toolbar_insert)libgtk.resolve("gtk_toolbar_insert");
+ QGtk::gtk_button_new = (Ptr_gtk_button_new)libgtk.resolve("gtk_button_new");
+ QGtk::gtk_hbutton_box_new = (Ptr_gtk_hbutton_box_new)libgtk.resolve("gtk_hbutton_box_new");
+ QGtk::gtk_check_button_new = (Ptr_gtk_check_button_new)libgtk.resolve("gtk_check_button_new");
+ QGtk::gtk_radio_button_new = (Ptr_gtk_radio_button_new)libgtk.resolve("gtk_radio_button_new");
+ QGtk::gtk_notebook_new = (Ptr_gtk_notebook_new)libgtk.resolve("gtk_notebook_new");
+ QGtk::gtk_progress_bar_new = (Ptr_gtk_progress_bar_new)libgtk.resolve("gtk_progress_bar_new");
+ QGtk::gtk_spin_button_new = (Ptr_gtk_spin_button_new)libgtk.resolve("gtk_spin_button_new");
+ QGtk::gtk_hscale_new = (Ptr_gtk_hscale_new)libgtk.resolve("gtk_hscale_new");
+ QGtk::gtk_vscale_new = (Ptr_gtk_vscale_new)libgtk.resolve("gtk_vscale_new");
+ QGtk::gtk_hscrollbar_new = (Ptr_gtk_hscrollbar_new)libgtk.resolve("gtk_hscrollbar_new");
+ QGtk::gtk_vscrollbar_new = (Ptr_gtk_vscrollbar_new)libgtk.resolve("gtk_vscrollbar_new");
+ QGtk::gtk_scrolled_window_new = (Ptr_gtk_scrolled_window_new)libgtk.resolve("gtk_scrolled_window_new");
+ QGtk::gtk_menu_shell_append = (Ptr_gtk_menu_shell_append)libgtk.resolve("gtk_menu_shell_append");
+ QGtk::gtk_entry_new = (Ptr_gtk_entry_new)libgtk.resolve("gtk_entry_new");
+ QGtk::gtk_tree_view_new = (Ptr_gtk_tree_view_new)libgtk.resolve("gtk_tree_view_new");
+ QGtk::gtk_combo_box_new = (Ptr_gtk_combo_box_new)libgtk.resolve("gtk_combo_box_new");
+ QGtk::gtk_progress_set_adjustment = (Ptr_gtk_progress_set_adjustment)libgtk.resolve("gtk_progress_set_adjustment");
+ QGtk::gtk_range_set_adjustment = (Ptr_gtk_range_set_adjustment)libgtk.resolve("gtk_range_set_adjustment");
+ QGtk::gtk_range_set_inverted = (Ptr_gtk_range_set_inverted)libgtk.resolve("gtk_range_set_inverted");
+ QGtk::gtk_container_add = (Ptr_gtk_container_add)libgtk.resolve("gtk_container_add");
+ QGtk::gtk_icon_factory_lookup_default = (Ptr_gtk_icon_factory_lookup_default)libgtk.resolve("gtk_icon_factory_lookup_default");
+ QGtk::gtk_widget_style_get = (Ptr_gtk_widget_style_get)libgtk.resolve("gtk_widget_style_get");
+ QGtk::gtk_icon_set_render_icon = (Ptr_gtk_icon_set_render_icon)libgtk.resolve("gtk_icon_set_render_icon");
+ QGtk::gtk_fixed_new = (Ptr_gtk_fixed_new)libgtk.resolve("gtk_fixed_new");
+ QGtk::gtk_tree_view_column_new = (Ptr_gtk_tree_view_column_new)libgtk.resolve("gtk_tree_view_column_new");
+ QGtk::gtk_tree_view_append_column= (Ptr_gtk_tree_view_append_column )libgtk.resolve("gtk_tree_view_append_column");
+ QGtk::gtk_tree_view_get_column = (Ptr_gtk_tree_view_get_column )libgtk.resolve("gtk_tree_view_get_column");
+ QGtk::gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check");
+ QGtk::gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box");
+ QGtk::gtk_paint_flat_box = (Ptr_gtk_paint_flat_box)libgtk.resolve("gtk_paint_flat_box");
+ QGtk::gtk_paint_check = (Ptr_gtk_paint_check)libgtk.resolve("gtk_paint_check");
+ QGtk::gtk_paint_box = (Ptr_gtk_paint_box)libgtk.resolve("gtk_paint_box");
+ QGtk::gtk_paint_resize_grip = (Ptr_gtk_paint_resize_grip)libgtk.resolve("gtk_paint_resize_grip");
+ QGtk::gtk_paint_focus = (Ptr_gtk_paint_focus)libgtk.resolve("gtk_paint_focus");
+ QGtk::gtk_paint_shadow = (Ptr_gtk_paint_shadow)libgtk.resolve("gtk_paint_shadow");
+ QGtk::gtk_paint_slider = (Ptr_gtk_paint_slider)libgtk.resolve("gtk_paint_slider");
+ QGtk::gtk_paint_expander = (Ptr_gtk_paint_expander)libgtk.resolve("gtk_paint_expander");
+ QGtk::gtk_paint_handle = (Ptr_gtk_paint_handle)libgtk.resolve("gtk_paint_handle");
+ QGtk::gtk_paint_option = (Ptr_gtk_paint_option)libgtk.resolve("gtk_paint_option");
+ QGtk::gtk_paint_arrow = (Ptr_gtk_paint_arrow)libgtk.resolve("gtk_paint_arrow");
+ QGtk::gtk_paint_box_gap = (Ptr_gtk_paint_box_gap)libgtk.resolve("gtk_paint_box_gap");
+ QGtk::gtk_paint_extension = (Ptr_gtk_paint_extension)libgtk.resolve("gtk_paint_extension");
+ QGtk::gtk_paint_hline = (Ptr_gtk_paint_hline)libgtk.resolve("gtk_paint_hline");
+ QGtk::gtk_paint_vline = (Ptr_gtk_paint_vline)libgtk.resolve("gtk_paint_vline");
+ QGtk::gtk_adjustment_new = (Ptr_gtk_adjustment_new)libgtk.resolve("gtk_adjustment_new");
+ QGtk::gtk_menu_item_set_submenu = (Ptr_gtk_menu_item_set_submenu)libgtk.resolve("gtk_menu_item_set_submenu");
+ QGtk::gtk_settings_get_default = (Ptr_gtk_settings_get_default)libgtk.resolve("gtk_settings_get_default");
+ QGtk::gtk_separator_menu_item_new = (Ptr_gtk_separator_menu_item_new)libgtk.resolve("gtk_separator_menu_item_new");
+ QGtk::gtk_frame_new = (Ptr_gtk_frame_new)libgtk.resolve("gtk_frame_new");
+ QGtk::gtk_expander_new = (Ptr_gtk_expander_new)libgtk.resolve("gtk_expander_new");
+ QGtk::gtk_statusbar_new = (Ptr_gtk_statusbar_new)libgtk.resolve("gtk_statusbar_new");
+ QGtk::gtk_combo_box_entry_new = (Ptr_gtk_combo_box_entry_new)libgtk.resolve("gtk_combo_box_entry_new");
+ QGtk::gtk_container_forall = (Ptr_gtk_container_forall)libgtk.resolve("gtk_container_forall");
+ QGtk::gtk_widget_size_allocate =(Ptr_gtk_widget_size_allocate)libgtk.resolve("gtk_widget_size_allocate");
+ QGtk::gtk_widget_set_direction =(Ptr_gtk_widget_set_direction)libgtk.resolve("gtk_widget_set_direction");
+ QGtk::gtk_widget_path =(Ptr_gtk_widget_path)libgtk.resolve("gtk_widget_path");
+ QGtk::gtk_container_get_type =(Ptr_gtk_container_get_type)libgtk.resolve("gtk_container_get_type");
+ QGtk::gtk_window_get_type =(Ptr_gtk_window_get_type)libgtk.resolve("gtk_window_get_type");
+ QGtk::gtk_widget_get_type =(Ptr_gtk_widget_get_type)libgtk.resolve("gtk_widget_get_type");
+ QGtk::gtk_rc_get_style_by_paths =(Ptr_gtk_rc_get_style_by_paths)libgtk.resolve("gtk_rc_get_style_by_paths");
+ QGtk::gtk_check_version =(Ptr_gtk_check_version)libgtk.resolve("gtk_check_version");
+ QGtk::pango_font_description_get_size = (Ptr_pango_font_description_get_size)libgtk.resolve("pango_font_description_get_size");
+ QGtk::pango_font_description_get_weight = (Ptr_pango_font_description_get_weight)libgtk.resolve("pango_font_description_get_weight");
+ QGtk::pango_font_description_get_family = (Ptr_pango_font_description_get_family)libgtk.resolve("pango_font_description_get_family");
+ QGtk::pango_font_description_get_style = (Ptr_pango_font_description_get_style)libgtk.resolve("pango_font_description_get_style");
}
void QGtk::cleanup_gtk_widgets()
@@ -374,8 +374,8 @@ static QString getThemeName()
while(!in.atEnd()) {
QString line = in.readLine();
if (line.contains(QLS("gtk-theme-name"))) {
- line = line.right(line.length() - line.indexOf(QLS("=")) - 1);
- line.remove(QLS("\""));
+ line = line.right(line.length() - line.indexOf(QLatin1Char('=')) - 1);
+ line.remove(QLatin1Char('\"'));
line = line.trimmed();
themeName = line;
break;
@@ -695,7 +695,7 @@ void QGtk::initGtkWidgets()
QHashIterator<QString, GtkWidget*> it(oldMap);
while (it.hasNext()) {
it.next();
- if (!it.key().contains(QLS("."))) {
+ if (!it.key().contains(QLatin1Char('.'))) {
add_all_sub_widgets(it.value());
}
}
diff --git a/src/gui/styles/qcleanlooksstyle.cpp b/src/gui/styles/qcleanlooksstyle.cpp
index 468ada9..ac433b4 100644
--- a/src/gui/styles/qcleanlooksstyle.cpp
+++ b/src/gui/styles/qcleanlooksstyle.cpp
@@ -44,6 +44,7 @@
#if !defined(QT_NO_STYLE_CLEANLOOKS) || defined(QT_PLUGIN)
+#include <private/qstylehelper_p.h>
#include "qwindowsstyle_p.h"
#include <qcombobox.h>
#include <qpushbutton.h>
@@ -72,7 +73,7 @@
QT_BEGIN_NAMESPACE
-static const bool UsePixmapCache = true;
+using namespace QStyleHelper;
enum Direction {
TopDown,
@@ -553,26 +554,6 @@ static void qt_cleanlooks_draw_buttongradient(QPainter *painter, const QRect &re
delete gradient;
}
-static QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
-{
- QString tmp;
- const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
- tmp.sprintf("%s-%d-%d-%lld-%dx%d-%d", key.toLatin1().constData(), uint(option->state),
- complexOption ? uint(complexOption->activeSubControls) : uint(0),
- option->palette.cacheKey(), size.width(), size.height(), option->direction);
-#ifndef QT_NO_SPINBOX
- if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
- tmp.append(QLatin1Char('-'));
- tmp.append(QString::number(spinBox->buttonSymbols));
- tmp.append(QLatin1Char('-'));
- tmp.append(QString::number(spinBox->stepEnabled));
- tmp.append(QLatin1Char('-'));
- tmp.append(QLatin1Char(spinBox->frame ? '1' : '0'));
- }
-#endif // QT_NO_SPINBOX
- return tmp;
-}
-
static void qt_cleanlooks_draw_mdibutton(QPainter *painter, const QStyleOptionTitleBar *option, const QRect &tmp, bool hover, bool sunken)
{
QColor dark;
@@ -782,7 +763,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
button.state &= ~State_MouseOver;
- drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
}
return;
case PE_IndicatorHeaderArrow:
@@ -802,7 +783,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
}
break;
case PE_IndicatorButtonDropDown:
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
break;
case PE_IndicatorToolBarSeparator:
{
@@ -887,9 +868,9 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
if (widget && widget->inherits("QDockWidgetTitleButton")) {
if (option->state & State_MouseOver)
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
} else {
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
}
}
painter->restore();
@@ -902,7 +883,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
dockWidgetHandle.state &= ~State_Horizontal;
else
dockWidgetHandle.state |= State_Horizontal;
- drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
+ proxy()->drawControl(CE_Splitter, &dockWidgetHandle, painter, widget);
}
break;
case PE_FrameWindow:
@@ -928,7 +909,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
#endif // QT_NO_LINEEDIT
#ifdef QT3_SUPPORT
if (widget && widget->inherits("Q3ToolBar")) {
- drawPrimitive(PE_Q3Separator, option, painter, widget);
+ proxy()->drawPrimitive(PE_Q3Separator, option, painter, widget);
break;
}
#endif
@@ -1257,7 +1238,7 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
QColor alphaCornerColor = mergedColors(borderColor, option->palette.background().color());
QColor innerShadow = mergedColors(borderColor, option->palette.base().color());
- int borderThickness = pixelMetric(PM_TabBarBaseOverlap, twf, widget);
+ int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget);
bool reverse = (twf->direction == Qt::RightToLeft);
QRect tabBarRect;
@@ -1370,9 +1351,9 @@ void QCleanlooksStyle::drawPrimitive(PrimitiveElement elem,
if (d->tabBarcloseButtonIcon.isNull())
d->tabBarcloseButtonIcon = standardIcon(SP_DialogCloseButton, option, widget);
if ((option->state & State_Enabled) && (option->state & State_MouseOver))
- drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, option, painter, widget);
QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(QSize(16, 16), QIcon::Normal, QIcon::On);
- drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(painter, option->rect, Qt::AlignCenter, pixmap);
}
break;
@@ -1649,7 +1630,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
QString titleText
= painter->fontMetrics().elidedText(dwOpt->title,
Qt::ElideRight, titleRect.width());
- drawItemText(painter,
+ proxy()->drawItemText(painter,
titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
@@ -1664,9 +1645,9 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
// Draws the header in tables.
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size());
- pixmapName += QLatin1String("-") + QString::number(int(header->position));
- pixmapName += QLatin1String("-") + QString::number(int(header->orientation));
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("headersection"), option, option->rect.size());
+ pixmapName += QString::number(- int(header->position));
+ pixmapName += QString::number(- int(header->orientation));
QRect r = option->rect;
QColor gradientStopColor;
QColor gradientStartColor = option->palette.button().color();
@@ -1683,7 +1664,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
}
painter->fillRect(r, gradient);
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(r.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, r.width(), r.height());
@@ -1702,8 +1683,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
cachePainter.drawLine(pixmapRect.topRight() + QPoint(-1, 3), pixmapRect.bottomRight() + QPoint(-1, -3)); cachePainter.setPen(QPen(option->palette.light().color()));
cachePainter.drawLine(pixmapRect.topRight() + QPoint(0, 3), pixmapRect.bottomRight() + QPoint(0, -3)); }
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(r.topLeft(), cache);
}
@@ -1864,7 +1844,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
if (!styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
+ proxy()->drawItemText(painter, item.rect, alignment, mbi->palette, mbi->state & State_Enabled, mbi->text, textRole);
}
}
@@ -1891,7 +1871,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
int w = 0;
if (!menuItem->text.isEmpty()) {
painter->setFont(menuItem->font);
- drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
QPalette::Text);
w = menuItem->fontMetrics.width(menuItem->text) + 5;
@@ -1995,7 +1975,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
mode = QIcon::Active;
QPixmap pixmap;
- int smallIconSize = pixelMetric(PM_SmallIconSize, option, widget);
+ int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
QSize iconSize(smallIconSize, smallIconSize);
#ifndef QT_NO_COMBOBOX
if (const QComboBox *combo = qobject_cast<const QComboBox*>(widget))
@@ -2021,7 +2001,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
}
opt.state |= State_Sunken;
opt.rect = vCheckRect;
- drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
}
painter->drawPixmap(pmr.topLeft(), pixmap);
}
@@ -2054,7 +2034,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
if (t >= 0) {
QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vShortcutRect.adjusted(1, 1, 1, 1), text_flags, s.mid(t + 1));
p->setPen(discol);
@@ -2068,7 +2048,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
font.setBold(true);
p->setFont(font);
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vTextRect.adjusted(1, 1, 1, 1), text_flags, s.left(t));
p->setPen(discol);
@@ -2091,7 +2071,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
if (selected)
newMI.palette.setColor(QPalette::ButtonText,
newMI.palette.highlightedText().color());
- drawPrimitive(arrow, &newMI, painter, widget);
+ proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
}
painter->restore();
@@ -2152,7 +2132,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
if (button->features & QStyleOptionButton::HasMenu)
ir = ir.adjusted(0, 0, -pixelMetric(PM_MenuButtonIndicator, button, widget), 0);
- drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
+ proxy()->drawItemText(painter, ir, tf, button->palette, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
}
break;
@@ -2207,7 +2187,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
|| (rtlHorTabs
&& tab->selectedPosition
== QStyleOptionTab::PreviousIsSelected));
- int tabBarAlignment = styleHint(SH_TabBar_Alignment, tab, widget);
+ int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget);
bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft)
|| (rtlHorTabs
&& tabBarAlignment == Qt::AlignRight);
@@ -2220,7 +2200,7 @@ void QCleanlooksStyle::drawControl(ControlElement element, const QStyleOption *o
QColor midlight = tab->palette.midlight().color();
QColor background = tab->palette.background().color();
- int borderThinkness = pixelMetric(PM_TabBarBaseOverlap, tab, widget);
+ int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
if (selected)
borderThinkness /= 2;
QRect r2(option->rect);
@@ -2456,8 +2436,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("spinbox"), spinBox, spinBox->rect.size());
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(spinBox->rect.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, spinBox->rect.width(), spinBox->rect.height());
@@ -2473,10 +2453,10 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QRect rect = pixmapRect;
QStyleOptionSpinBox spinBoxCopy = *spinBox;
spinBoxCopy.rect = pixmapRect;
- QRect upRect = subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget);
- QRect downRect = subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget);
+ QRect upRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxUp, widget);
+ QRect downRect = proxy()->subControlRect(CC_SpinBox, &spinBoxCopy, SC_SpinBoxDown, widget);
- int fw = spinBoxCopy.frame ? pixelMetric(PM_SpinBoxFrameWidth, &spinBoxCopy, widget) : 0;
+ int fw = spinBoxCopy.frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, &spinBoxCopy, widget) : 0;
cachePainter.fillRect(rect.adjusted(1, qMax(fw - 1, 0), -1, -fw),
option->palette.base());
@@ -2674,8 +2654,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
cachePainter.fillRect(downRect.adjusted(1, 0, 0, 0), disabledColor);
}
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(spinBox->rect.topLeft(), cache);
}
@@ -2699,7 +2678,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (widget && widget->inherits("Q3DockWindowTitleBar")) {
QStyleOptionDockWidgetV2 dockwidget;
dockwidget.QStyleOption::operator=(*option);
- drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
+ proxy()->drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
} else
#endif // QT3_SUPPORT
{
@@ -2742,7 +2721,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
painter->drawLine(fullRect.left() + 6, fullRect.top() + 1, fullRect.right() - 6, fullRect.top() + 1);
}
// draw title
- QRect textRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
+ QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
QFont font = painter->font();
font.setBold(true);
painter->setFont(font);
@@ -2757,7 +2736,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// min button
if ((titleBar->subControls & SC_TitleBarMinButton) && (titleBar->titleBarFlags & Qt::WindowMinimizeButtonHint) &&
!(titleBar->titleBarState& Qt::WindowMinimized)) {
- QRect minButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
+ QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
if (minButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
@@ -2778,7 +2757,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// max button
if ((titleBar->subControls & SC_TitleBarMaxButton) && (titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
!(titleBar->titleBarState & Qt::WindowMaximized)) {
- QRect maxButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
+ QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
if (maxButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
@@ -2800,7 +2779,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// close button
if ((titleBar->subControls & SC_TitleBarCloseButton) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
- QRect closeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
+ QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
if (closeButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
@@ -2834,7 +2813,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
(titleBar->titleBarState & Qt::WindowMinimized)) ||
((titleBar->titleBarFlags & Qt::WindowMaximizeButtonHint) &&
(titleBar->titleBarState & Qt::WindowMaximized)))) {
- QRect normalButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
+ QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
if (normalButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
@@ -2874,7 +2853,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// context help button
if (titleBar->subControls & SC_TitleBarContextHelpButton
&& (titleBar->titleBarFlags & Qt::WindowContextHelpButtonHint)) {
- QRect contextHelpButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
+ QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
if (contextHelpButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
@@ -2893,7 +2872,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// shade button
if (titleBar->subControls & SC_TitleBarShadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
- QRect shadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
+ QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
if (shadeButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
@@ -2906,7 +2885,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// unshade button
if (titleBar->subControls & SC_TitleBarUnshadeButton && (titleBar->titleBarFlags & Qt::WindowShadeButtonHint)) {
- QRect unshadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
+ QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
if (unshadeButtonRect.isValid()) {
bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
@@ -2918,7 +2897,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
if ((titleBar->subControls & SC_TitleBarSysMenu) && (titleBar->titleBarFlags & Qt::WindowSystemMenuHint)) {
- QRect iconRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
+ QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
if (iconRect.isValid()) {
if (!titleBar->icon.isNull()) {
titleBar->icon.paint(painter, iconRect);
@@ -2928,7 +2907,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QPixmap pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(16, 16);
tool.rect = iconRect;
painter->save();
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
painter->restore();
}
}
@@ -2948,10 +2927,10 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
painter->fillRect(option->rect, option->palette.background());
QRect rect = scrollBar->rect;
- QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
- QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
- QRect scrollBarSlider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
- QRect grooveRect = subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
+ QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
+ QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
+ QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
+ QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
// paint groove
if (scrollBar->subControls & SC_ScrollBarGroove) {
@@ -3086,7 +3065,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// The SubLine (up/left) buttons
if (scrollBar->subControls & SC_ScrollBarSubLine) {
- //int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget);
+ //int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
QRect pixmapRect = scrollBarSubLine;
if (isEnabled ) {
QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1);
@@ -3132,12 +3111,12 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
arrow = PE_IndicatorArrowUp;
QStyleOption arrowOpt = *option;
arrowOpt.rect = scrollBarSubLine.adjusted(3, 3, -2, -2);
- drawPrimitive(arrow, &arrowOpt, painter, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, painter, widget);
// The AddLine (down/right) button
if (scrollBar->subControls & SC_ScrollBarAddLine) {
- QString addLinePixmapName = uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16));
+ QString addLinePixmapName = QStyleHelper::uniqueName(QLatin1String("scrollbar_addline"), option, QSize(16, 16));
QRect pixmapRect = scrollBarAddLine;
if (isEnabled) {
QRect fillRect = pixmapRect.adjusted(1, 1, -1, -1);
@@ -3183,7 +3162,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QStyleOption arrowOpt = *option;
arrowOpt.rect = scrollBarAddLine.adjusted(3, 3, -2, -2);
- drawPrimitive(arrow, &arrowOpt, painter, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, painter, widget);
}
}
}
@@ -3198,7 +3177,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
bool isEnabled = (comboBox->state & State_Enabled);
bool focus = isEnabled && (comboBox->state & State_HasFocus);
QPixmap cache;
- QString pixmapName = uniqueName(QLatin1String("combobox"), option, comboBox->rect.size());
+ QString pixmapName = QStyleHelper::uniqueName(QLatin1String("combobox"), option, comboBox->rect.size());
if (sunken)
pixmapName += QLatin1String("-sunken");
if (comboBox->editable)
@@ -3206,7 +3185,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (isEnabled)
pixmapName += QLatin1String("-enabled");
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(comboBox->rect.size());
cache.fill(Qt::transparent);
QPainter cachePainter(&cache);
@@ -3215,9 +3194,9 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
comboBoxCopy.rect = pixmapRect;
QRect rect = pixmapRect;
- QRect downArrowRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect downArrowRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxArrow, widget);
- QRect editRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxEditField, widget);
// Draw a push button
if (comboBox->editable) {
@@ -3231,7 +3210,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
buttonOption.state &= ~State_MouseOver;
}
- drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
//remove shadow from left side of edit field when pressed:
if (comboBox->direction != Qt::RightToLeft)
@@ -3273,7 +3252,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
buttonOption.state |= State_Sunken;
buttonOption.state &= ~State_MouseOver;
}
- drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, &cachePainter, widget);
cachePainter.setPen(buttonShadow.darker(102));
int borderSize = 4;
@@ -3326,15 +3305,15 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
}
// Draw the focus rect
- if ((focus && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) {
+ if (focus && !comboBox->editable
+ && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) {
QStyleOptionFocusRect focus;
- focus.rect = subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget)
+ focus.rect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy, SC_ComboBoxEditField, widget)
.adjusted(0, 2, option->direction == Qt::RightToLeft ? 1 : -1, -2);
- drawPrimitive(PE_FrameFocusRect, &focus, &cachePainter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, &cachePainter, widget);
}
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(comboBox->rect.topLeft(), cache);
}
@@ -3345,8 +3324,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
case CC_GroupBox:
painter->save();
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
- QRect textRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
bool flat = groupBox->features & QStyleOptionFrameV2::Flat;
if(!flat) {
@@ -3356,7 +3335,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
frame.midLineWidth = groupBox->midLineWidth;
- frame.rect = subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
+ frame.rect = proxy()->subControlRect(CC_GroupBox, option, SC_GroupBoxFrame, widget);
painter->save();
QRegion region(groupBox->rect);
@@ -3365,7 +3344,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
if (!groupBox->text.isEmpty() || groupBox->subControls & SC_GroupBoxCheckBox)
painter->setClipRegion(region);
frame.palette.setBrush(QPalette::Dark, option->palette.mid().color().lighter(110));
- drawPrimitive(PE_FrameGroupBox, &frame, painter);
+ proxy()->drawPrimitive(PE_FrameGroupBox, &frame, painter);
painter->restore();
}
}
@@ -3393,7 +3372,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
}
}
painter->restore();
@@ -3402,9 +3381,9 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
@@ -3421,11 +3400,11 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
highlightAlpha.setAlpha(80);
if ((option->subControls & SC_SliderGroove) && groove.isValid()) {
- QString groovePixmapName = uniqueName(QLatin1String("slider_groove"), option, groove.size());
+ QString groovePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_groove"), option, groove.size());
QRect pixmapRect(0, 0, groove.width(), groove.height());
// draw background groove
- if (!UsePixmapCache || !QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, cache)) {
cache = QPixmap(pixmapRect.size());
cache.fill(Qt::transparent);
QPainter groovePainter(&cache);
@@ -3452,15 +3431,14 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
groovePainter.setBrush(gradient);
groovePainter.drawRect(pixmapRect.adjusted(1, 1, -2, -2));
groovePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(groovePixmapName, cache);
+ QPixmapCache::insert(groovePixmapName, cache);
}
painter->drawPixmap(groove.topLeft(), cache);
// draw blue groove highlight
QRect clipRect;
groovePixmapName += QLatin1String("_blue");
- if (!UsePixmapCache || !QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, cache)) {
cache = QPixmap(pixmapRect.size());
cache.fill(Qt::transparent);
QPainter groovePainter(&cache);
@@ -3479,8 +3457,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
groovePainter.setBrush(gradient);
groovePainter.drawRect(pixmapRect.adjusted(1, 1, -2, -2));
groovePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(groovePixmapName, cache);
+ QPixmapCache::insert(groovePixmapName, cache);
}
if (horizontal) {
if (slider->upsideDown)
@@ -3501,8 +3478,8 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
// draw handle
if ((option->subControls & SC_SliderHandle) ) {
- QString handlePixmapName = uniqueName(QLatin1String("slider_handle"), option, handle.size());
- if (!UsePixmapCache || !QPixmapCache::find(handlePixmapName, cache)) {
+ QString handlePixmapName = QStyleHelper::uniqueName(QLatin1String("slider_handle"), option, handle.size());
+ if (!QPixmapCache::find(handlePixmapName, cache)) {
cache = QPixmap(handle.size());
cache.fill(Qt::transparent);
QRect pixmapRect(0, 0, handle.width(), handle.height());
@@ -3583,8 +3560,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
}
handlePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(handlePixmapName, cache);
+ QPixmapCache::insert(handlePixmapName, cache);
}
painter->drawPixmap(handle.topLeft(), cache);
@@ -3593,13 +3569,13 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = slider->rect;
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
if (option->subControls & SC_SliderTickmarks) {
painter->setPen(darkOutline);
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -3613,7 +3589,7 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
interval = 1;
int v = slider->minimum;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
break;
@@ -3656,6 +3632,12 @@ void QCleanlooksStyle::drawComplexControl(ComplexControl control, const QStyleOp
}
break;
#endif // QT_NO_SLIDER
+#ifndef QT_NO_DIAL
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
+ QStyleHelper::drawDial(dial, painter);
+ break;
+#endif // QT_NO_DIAL
default:
QWindowsStyle::drawComplexControl(control, option, painter, widget);
break;
@@ -3781,6 +3763,20 @@ QSize QCleanlooksStyle::sizeFromContents(ContentsType type, const QStyleOption *
}
break;
case CT_GroupBox:
+ // Since we use a bold font we have to recalculate base width
+ if (const QGroupBox *gb = qobject_cast<const QGroupBox*>(widget)) {
+ QFont font = gb->font();
+ font.setBold(true);
+ QFontMetrics metrics(font);
+ int baseWidth = metrics.width(gb->title()) + metrics.width(QLatin1Char(' '));
+ if (gb->isCheckable()) {
+ baseWidth += proxy()->pixelMetric(QStyle::PM_IndicatorWidth, option, widget);
+ baseWidth += proxy()->pixelMetric(QStyle::PM_CheckBoxLabelSpacing, option, widget);
+ }
+ newSize.setWidth(qMax(baseWidth, newSize.width()));
+ }
+ newSize += QSize(0, 1);
+ break;
case CT_RadioButton:
case CT_CheckBox:
newSize += QSize(0, 1);
@@ -3857,7 +3853,7 @@ void QCleanlooksStyle::polish(QApplication *app)
dataDirs = QLatin1String("/usr/local/share/:/usr/share/");
dataDirs.prepend(QDir::homePath() + QLatin1String("/:"));
- d->iconDirs = dataDirs.split(QLatin1String(":"));
+ d->iconDirs = dataDirs.split(QLatin1Char(':'));
#endif
}
@@ -3959,7 +3955,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
switch (subControl) {
case SC_SliderHandle: {
if (slider->orientation == Qt::Horizontal) {
@@ -4014,7 +4010,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
QSize bs;
int center = spinbox->rect.height() / 2;
- int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
int y = fw;
bs.setHeight(qMax(8, spinbox->rect.height()/2 - y));
bs.setWidth(15);
@@ -4055,7 +4051,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
int topMargin = 0;
int topHeight = 0;
- int verticalAlignment = styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
+ int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
bool flat = groupBox->features & QStyleOptionFrameV2::Flat;
if (!groupBox->text.isEmpty()) {
topHeight = groupBox->fontMetrics.height();
@@ -4086,8 +4082,8 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(2, 2);
if (subControl == SC_GroupBoxCheckBox) {
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, option, widget);
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, option, widget);
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
rect.setWidth(indicatorWidth);
rect.setHeight(indicatorHeight);
rect.moveTop((fontMetrics.height() - indicatorHeight) / 2 + 2);
@@ -4108,7 +4104,7 @@ QRect QCleanlooksStyle::subControlRect(ComplexControl control, const QStyleOptio
rect = visualRect(option->direction, option->rect, rect);
break;
case SC_ComboBoxEditField: {
- int frameWidth = pixelMetric(PM_DefaultFrameWidth);
+ int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth);
rect = visualRect(option->direction, option->rect, rect);
rect.setRect(option->rect.left() + frameWidth, option->rect.top() + frameWidth,
option->rect.width() - 19 - 2 * frameWidth,
@@ -4423,7 +4419,7 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
{
#ifdef Q_WS_X11
Q_D(const QCleanlooksStyle);
- if (!qApp->desktopSettingsAware())
+ if (!QApplication::desktopSettingsAware())
return QWindowsStyle::standardIconImplementation(standardIcon, option, widget);
QIcon icon;
QPixmap pixmap;
@@ -4431,8 +4427,8 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
d->lookupIconTheme();
switch (standardIcon) {
case SP_DirIcon: {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
- icon.addPixmap(standardPixmap(SP_DirClosedIcon, option, widget),
+ icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget));
+ icon.addPixmap(proxy()->standardPixmap(SP_DirClosedIcon, option, widget),
QIcon::Normal, QIcon::Off);
pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png"));
if (!pixmap.isNull())
@@ -4450,10 +4446,10 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
break;
case SP_DirLinkIcon:
{
- icon = QIcon(standardPixmap(standardIcon, option, widget));
+ icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget));
QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png"));
if (!link.isNull()) {
- icon.addPixmap(standardPixmap(SP_DirLinkIcon, option, widget));
+ icon.addPixmap(proxy()->standardPixmap(SP_DirLinkIcon, option, widget));
pixmap = d->findIcon(16, QLatin1String("gnome-fs-directory.png"));
if (!pixmap.isNull()) {
QPainter painter(&pixmap);
@@ -4550,10 +4546,10 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
}
case SP_FileLinkIcon:
{
- icon = QIcon(standardPixmap(standardIcon, option, widget));
+ icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget));
QPixmap link = d->findIcon(12, QLatin1String("emblem-symbolic-link.png"));
if (!link.isNull()) {
- icon.addPixmap(standardPixmap(SP_FileLinkIcon,option, widget));
+ icon.addPixmap(proxy()->standardPixmap(SP_FileLinkIcon,option, widget));
pixmap = d->findIcon(16, QLatin1String("unknown.png"));
if (pixmap.isNull())
pixmap = d->findIcon(16, QLatin1String("stock_new.png"));
@@ -4575,7 +4571,7 @@ QIcon QCleanlooksStyle::standardIconImplementation(StandardPixmap standardIcon,
return standardIconImplementation(SP_ArrowRight, option, widget);
return standardIconImplementation(SP_ArrowLeft, option, widget);
default:
- icon = QIcon(standardPixmap(standardIcon, option, widget));
+ icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget));
}
if (!icon.isNull())
return icon;
@@ -4592,7 +4588,7 @@ QPixmap QCleanlooksStyle::standardPixmap(StandardPixmap standardPixmap, const QS
#ifdef Q_WS_X11
Q_D(const QCleanlooksStyle);
QPixmap pixmap;
- if (!qApp->desktopSettingsAware())
+ if (!QApplication::desktopSettingsAware())
return QWindowsStyle::standardPixmap(standardPixmap, opt, widget);
d->lookupIconTheme();
#ifndef QT_NO_IMAGEFORMAT_XPM
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index f3d1537..7d8436e 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -66,6 +66,7 @@
#include <private/qapplication_p.h>
#include <private/qcommonstylepixmaps_p.h>
#include <private/qmath_p.h>
+#include <private/qstylehelper_p.h>
#include <qdebug.h>
#include <qtextformat.h>
#include <qwizard.h>
@@ -154,7 +155,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
&opt->palette.brush(QPalette::Button));
break;
case PE_IndicatorViewItemCheck:
- drawPrimitive(PE_IndicatorCheckBox, opt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, opt, p, widget);
break;
case PE_IndicatorCheckBox:
if (opt->state & State_NoChange) {
@@ -504,7 +505,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
QIcon::Active, QIcon::Off);
}
- int size = pixelMetric(QStyle::PM_SmallIconSize);
+ int size = proxy()->pixelMetric(QStyle::PM_SmallIconSize);
QIcon::Mode mode = opt->state & State_Enabled ?
(opt->state & State_Raised ? QIcon::Active : QIcon::Normal)
: QIcon::Disabled;
@@ -515,7 +516,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
QIcon::State state = opt->state & State_Sunken ? QIcon::On : QIcon::Off;
QPixmap pixmap = d->tabBarcloseButtonIcon.pixmap(size, mode, state);
- drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(p, opt->rect, Qt::AlignCenter, pixmap);
break;
}
#endif // QT_NO_TABBAR
@@ -524,7 +525,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
qDrawWinPanel(p, opt->rect, opt->palette, false, 0);
break;
case PE_FrameLineEdit:
- drawPrimitive(PE_Frame, opt, p, widget);
+ proxy()->drawPrimitive(PE_Frame, opt, p, widget);
break;
#ifndef QT_NO_GROUPBOX
case PE_FrameGroupBox:
@@ -549,7 +550,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (const QStyleOptionFrame *frame = qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
int lw = frame->lineWidth;
if (lw <= 0)
- lw = pixelMetric(PM_DockWidgetFrameWidth);
+ lw = proxy()->pixelMetric(PM_DockWidgetFrameWidth);
qDrawShadePanel(p, frame->rect, frame->palette, false, lw);
}
@@ -581,7 +582,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
p->restore();
break;
case PE_Q3DockWindowSeparator:
- drawPrimitive(PE_IndicatorToolBarSeparator, opt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorToolBarSeparator, opt, p, widget);
break;
case PE_IndicatorToolBarSeparator:
{
@@ -601,7 +602,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
case PE_IndicatorSpinPlus:
case PE_IndicatorSpinMinus: {
QRect r = opt->rect;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
QRect br = r.adjusted(fw, fw, -fw, -fw);
int offset = (opt->state & State_Sunken) ? 1 : 0;
@@ -618,7 +619,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
case PE_IndicatorSpinUp:
case PE_IndicatorSpinDown: {
QRect r = opt->rect;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
// QRect br = r.adjusted(fw, fw, -fw, -fw);
int x = r.x(), y = r.y(), w = r.width(), h = r.height();
int sw = w-4;
@@ -643,8 +644,8 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
int bsx = 0;
int bsy = 0;
if (opt->state & State_Sunken) {
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
}
p->save();
p->translate(sx + bsx, sy + bsy);
@@ -693,7 +694,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
panel->palette.brush(QPalette::Base));
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, panel, p, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget);
}
break;
#endif // QT_NO_LINEEDIT
@@ -765,7 +766,7 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q
if (cg == QPalette::Normal && !(vopt->state & QStyle::State_Active))
cg = QPalette::Inactive;
- if ((vopt->state & QStyle::State_Selected) && styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
+ if ((vopt->state & QStyle::State_Selected) && proxy()->styleHint(QStyle::SH_ItemView_ShowDecorationSelected, opt, widget))
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::Highlight));
else if (vopt->features & QStyleOptionViewItemV2::Alternate)
p->fillRect(vopt->rect, vopt->palette.brush(cg, QPalette::AlternateBase));
@@ -848,9 +849,9 @@ void QCommonStylePrivate::lookupIconTheme() const
dataDirs = QLatin1String("/usr/local/share/:/usr/share/");
dataDirs += QLatin1Char(':') + QApplicationPrivate::kdeHome() + QLatin1String("/share");
dataDirs.prepend(QDir::homePath() + QLatin1String("/:"));
- QStringList kdeDirs = QString::fromLocal8Bit(getenv("KDEDIRS")).split(QLatin1Char(':'));
+ QStringList kdeDirs = QString::fromLocal8Bit(getenv("KDEDIRS")).split(QLatin1Char(':'), QString::SkipEmptyParts);
foreach (const QString &dirName, kdeDirs)
- dataDirs.append(QLatin1String(":") + dirName + QLatin1String("/share"));
+ dataDirs.append(QLatin1Char(':') + dirName + QLatin1String("/share"));
iconDirs = dataDirs.split(QLatin1Char(':'));
QFileInfo fileInfo(QLatin1String("/usr/share/icons/default.kde"));
@@ -892,7 +893,7 @@ QIconTheme QCommonStylePrivate::parseIndexFile(const QString &themeName) const
parents = line.split(QLatin1Char(','));
}
- if (line.startsWith(QLatin1String("["))) {
+ if (line.startsWith(QLatin1Char('['))) {
line = line.trimmed();
line.chop(1);
QString dirName = line.right(line.length() - 1);
@@ -1290,24 +1291,24 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- drawControl(CE_PushButtonBevel, btn, p, widget);
+ proxy()->drawControl(CE_PushButtonBevel, btn, p, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
- drawControl(CE_PushButtonLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
case CE_PushButtonBevel:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
QRect br = btn->rect;
- int dbi = pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ int dbi = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
if (btn->features & QStyleOptionButton::DefaultButton)
- drawPrimitive(PE_FrameDefaultButton, opt, p, widget);
+ proxy()->drawPrimitive(PE_FrameDefaultButton, opt, p, widget);
if (btn->features & QStyleOptionButton::AutoDefaultButton)
br.setCoords(br.left() + dbi, br.top() + dbi, br.right() - dbi, br.bottom() - dbi);
if (!(btn->features & (QStyleOptionButton::Flat | QStyleOptionButton::CommandLinkButton))
@@ -1315,14 +1316,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
|| (btn->features & QStyleOptionButton::CommandLinkButton && btn->state & State_MouseOver)) {
QStyleOptionButton tmpBtn = *btn;
tmpBtn.rect = br;
- drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &tmpBtn, p, widget);
}
if (btn->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, btn, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbi + 2, ir.height()/2 - mbi/2 + 3, mbi - 6, mbi - 6);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -1330,7 +1331,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionButton *button = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
QRect textRect = button->rect;
uint tf = Qt::AlignVCenter | Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, button, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, button, widget))
tf |= Qt::TextHideMnemonic;
if (!button->icon.isNull()) {
@@ -1365,24 +1366,24 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
textRect.setLeft(iconRect.left() + iconRect.width() + iconSpacing);
if (button->state & (State_On | State_Sunken))
- iconRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
- pixelMetric(PM_ButtonShiftVertical, opt, widget));
+ iconRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
p->drawPixmap(iconRect, pixmap);
} else {
tf |= Qt::AlignHCenter;
}
if (button->state & (State_On | State_Sunken))
- textRect.translate(pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
- pixelMetric(PM_ButtonShiftVertical, opt, widget));
+ textRect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, opt, widget));
if (button->features & QStyleOptionButton::HasMenu) {
- int indicatorSize = pixelMetric(PM_MenuButtonIndicator, button, widget);
+ int indicatorSize = proxy()->pixelMetric(PM_MenuButtonIndicator, button, widget);
if (button->direction == Qt::LeftToRight)
textRect = textRect.adjusted(0, 0, -indicatorSize, 0);
else
textRect = textRect.adjusted(indicatorSize, 0, 0, 0);
}
- drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled),
+ proxy()->drawItemText(p, textRect, tf, button->palette, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
}
break;
@@ -1393,17 +1394,17 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, p, widget);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, widget);
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
@@ -1412,20 +1413,20 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
uint alignment = visualAlignment(btn->direction, Qt::AlignLeft | Qt::AlignVCenter);
- if (!styleHint(SH_UnderlineShortcut, btn, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, btn, widget))
alignment |= Qt::TextHideMnemonic;
QPixmap pix;
QRect textRect = btn->rect;
if (!btn->icon.isNull()) {
pix = btn->icon.pixmap(btn->iconSize, btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled);
- drawItemPixmap(p, btn->rect, alignment, pix);
+ proxy()->drawItemPixmap(p, btn->rect, alignment, pix);
if (btn->direction == Qt::RightToLeft)
textRect.setRight(textRect.right() - btn->iconSize.width() - 4);
else
textRect.setLeft(textRect.left() + btn->iconSize.width() + 4);
}
if (!btn->text.isEmpty()){
- drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
+ proxy()->drawItemText(p, textRect, alignment | Qt::TextShowMnemonic,
btn->palette, btn->state & State_Enabled, btn->text, QPalette::WindowText);
}
}
@@ -1435,7 +1436,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->fillRect(opt->rect, opt->palette.background());
QStyleOption arrowOpt = *opt;
arrowOpt.state |= State_Enabled;
- drawPrimitive(((opt->state & State_DownArrow) ? PE_IndicatorArrowDown : PE_IndicatorArrowUp),
+ proxy()->drawPrimitive(((opt->state & State_DownArrow) ? PE_IndicatorArrowDown : PE_IndicatorArrowUp),
&arrowOpt, p, widget);
break; }
case CE_MenuTearoff:
@@ -1457,13 +1458,13 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionMenuItem *mbi = qstyleoption_cast<const QStyleOptionMenuItem *>(opt)) {
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip
| Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
+ QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), (mbi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
if (!pix.isNull())
- drawItemPixmap(p,mbi->rect, alignment, pix);
+ proxy()->drawItemPixmap(p,mbi->rect, alignment, pix);
else
- drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled,
+ proxy()->drawItemText(p, mbi->rect, alignment, mbi->palette, mbi->state & State_Enabled,
mbi->text, QPalette::ButtonText);
}
break;
@@ -1478,12 +1479,12 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
= qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) {
QStyleOptionProgressBarV2 subopt = *pb;
subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget);
- drawControl(CE_ProgressBarGroove, &subopt, p, widget);
+ proxy()->drawControl(CE_ProgressBarGroove, &subopt, p, widget);
subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget);
- drawControl(CE_ProgressBarContents, &subopt, p, widget);
+ proxy()->drawControl(CE_ProgressBarContents, &subopt, p, widget);
if (pb->textVisible) {
subopt.rect = subElementRect(SE_ProgressBarLabel, pb, widget);
- drawControl(CE_ProgressBarLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_ProgressBarLabel, &subopt, p, widget);
}
}
break;
@@ -1509,10 +1510,10 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
? QColor(255,255,255,160) : QColor(0,0,0,160);
QPalette shadowPalette = pb->palette;
shadowPalette.setColor(textRole, shadowColor);
- drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette,
+ proxy()->drawItemText(p, shadowRect, Qt::AlignCenter | Qt::TextSingleLine, shadowPalette,
pb->state & State_Enabled, pb->text, textRole);
}
- drawItemText(p, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
+ proxy()->drawItemText(p, pb->rect, Qt::AlignCenter | Qt::TextSingleLine, pb->palette,
pb->state & State_Enabled, pb->text, textRole);
}
}
@@ -1559,7 +1560,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->setPen(QPen(pal2.highlight().color(), 4));
p->drawLine(x, rect.y(), x, rect.height());
} else {
- const int unit_width = pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
+ const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
if (!unit_width)
return;
@@ -1601,7 +1602,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
for (int i = 0; i < nu; ++i) {
pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
x += reverse ? -unit_width : unit_width;
}
@@ -1612,7 +1613,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
int offset = reverse ? x0 + x + unit_width-pixels_left : x0 + x;
pbBits.rect.setRect(offset, myY, pixels_left, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
}
}
}
@@ -1623,7 +1624,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect rect = header->rect;
if (!header->icon.isNull()) {
QPixmap pixmap
- = header->icon.pixmap(pixelMetric(PM_SmallIconSize), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
+ = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), (header->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled);
int pixw = pixmap.width();
QRect aligned = alignedRect(header->direction, QFlag(header->iconAlignment), pixmap.size(), rect);
@@ -1640,7 +1641,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
fnt.setBold(true);
p->setFont(fnt);
}
- drawItemText(p, rect, header->textAlignment, header->palette,
+ proxy()->drawItemText(p, rect, header->textAlignment, header->palette,
(header->state & State_Enabled), header->text, QPalette::ButtonText);
}
break;
@@ -1652,18 +1653,19 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
int shiftX = 0;
int shiftY = 0;
if (toolbutton->state & (State_Sunken | State_On)) {
- shiftX = pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
- shiftY = pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
+ shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, toolbutton, widget);
+ shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, toolbutton, widget);
}
// Arrow type always overrules and is always shown
bool hasArrow = toolbutton->features & QStyleOptionToolButton::Arrow;
if (((!hasArrow && toolbutton->icon.isNull()) && !toolbutton->text.isEmpty())
|| toolbutton->toolButtonStyle == Qt::ToolButtonTextOnly) {
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
rect.translate(shiftX, shiftY);
- drawItemText(p, rect, alignment, toolbutton->palette,
+ p->setFont(toolbutton->font);
+ proxy()->drawItemText(p, rect, alignment, toolbutton->palette,
opt->state & State_Enabled, toolbutton->text,
QPalette::ButtonText);
} else {
@@ -1688,7 +1690,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect pr = rect,
tr = rect;
int alignment = Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
if (toolbutton->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
@@ -1696,7 +1698,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr.adjust(0, pr.height() - 1, 0, -3);
pr.translate(shiftX, shiftY);
if (!hasArrow) {
- drawItemPixmap(p, pr, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pm);
} else {
drawArrow(this, toolbutton, pr, p, widget);
}
@@ -1706,14 +1708,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr.adjust(pr.width(), 0, 0, 0);
pr.translate(shiftX, shiftY);
if (!hasArrow) {
- drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, QStyle::visualRect(opt->direction, rect, pr), Qt::AlignCenter, pm);
} else {
drawArrow(this, toolbutton, pr, p, widget);
}
alignment |= Qt::AlignLeft | Qt::AlignVCenter;
}
tr.translate(shiftX, shiftY);
- drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette,
+ proxy()->drawItemText(p, QStyle::visualRect(opt->direction, rect, tr), alignment, toolbutton->palette,
toolbutton->state & State_Enabled, toolbutton->text,
QPalette::ButtonText);
} else {
@@ -1721,7 +1723,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (hasArrow) {
drawArrow(this, toolbutton, rect, p, widget);
} else {
- drawItemPixmap(p, rect, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, rect, Qt::AlignCenter, pm);
}
}
}
@@ -1731,8 +1733,8 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#ifndef QT_NO_TOOLBOX
case CE_ToolBoxTab:
if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
- drawControl(CE_ToolBoxTabShape, tb, p, widget);
- drawControl(CE_ToolBoxTabLabel, tb, p, widget);
+ proxy()->drawControl(CE_ToolBoxTabShape, tb, p, widget);
+ proxy()->drawControl(CE_ToolBoxTabLabel, tb, p, widget);
}
break;
case CE_ToolBoxTabShape:
@@ -1778,8 +1780,8 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#ifndef QT_NO_TABBAR
case CE_TabBarTab:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- drawControl(CE_TabBarTabShape, tab, p, widget);
- drawControl(CE_TabBarTabLabel, tab, p, widget);
+ proxy()->drawControl(CE_TabBarTabShape, tab, p, widget);
+ proxy()->drawControl(CE_TabBarTabLabel, tab, p, widget);
}
break;
case CE_TabBarTabShape:
@@ -1789,7 +1791,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect rect(tab->rect);
bool selected = tab->state & State_Selected;
bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
- int tabOverlap = onlyOne ? 0 : pixelMetric(PM_TabBarTabOverlap, opt, widget);
+ int tabOverlap = onlyOne ? 0 : proxy()->pixelMetric(PM_TabBarTabOverlap, opt, widget);
if (!selected) {
switch (tab->shape) {
@@ -1893,7 +1895,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionToolBox *tb = qstyleoption_cast<const QStyleOptionToolBox *>(opt)) {
bool enabled = tb->state & State_Enabled;
bool selected = tb->state & State_Selected;
- QPixmap pm = tb->icon.pixmap(pixelMetric(QStyle::PM_SmallIconSize, tb, widget),
+ QPixmap pm = tb->icon.pixmap(proxy()->pixelMetric(QStyle::PM_SmallIconSize, tb, widget),
enabled ? QIcon::Normal : QIcon::Disabled);
QRect cr = subElementRect(QStyle::SE_ToolBoxTabContents, tb, widget);
@@ -1909,7 +1911,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
tr = QRect(ir.right(), cr.top(), cr.width() - ir.right() - 4, cr.height());
}
- if (selected && styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget)) {
+ if (selected && proxy()->styleHint(QStyle::SH_ToolBox_SelectedPageTitleBold, tb, widget)) {
QFont f(p->font());
f.setBold(true);
p->setFont(f);
@@ -1921,16 +1923,16 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->drawPixmap(ir.left(), (tb->rect.height() - ih) / 2, pm);
int alignment = Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic;
- if (!styleHint(QStyle::SH_UnderlineShortcut, tb, widget))
+ if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, tb, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(p, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText);
+ proxy()->drawItemText(p, tr, alignment, tb->palette, enabled, txt, QPalette::ButtonText);
if (!txt.isEmpty() && opt->state & State_HasFocus) {
QStyleOptionFocusRect opt;
opt.rect = tr;
opt.palette = tb->palette;
opt.state = QStyle::State_None;
- drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &opt, p, widget);
}
}
break;
@@ -1945,7 +1947,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
|| tabV2.shape == QTabBar::TriangularWest;
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic;
- if (!styleHint(SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
if (verticalTabs) {
@@ -1971,7 +1973,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (!tabV2.icon.isNull()) {
QSize iconSize = tabV2.iconSize;
if (!iconSize.isValid()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
iconSize = QSize(iconExtent, iconExtent);
}
QSize tabIconSize = tabV2.icon.actualSize(iconSize,
@@ -1979,7 +1981,9 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
: QIcon::Disabled);
QPixmap tabIcon = tabV2.icon.pixmap(iconSize,
(tabV2.state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled);
+ : QIcon::Disabled,
+ (tabV2.state & State_Selected) ? QIcon::On
+ : QIcon::Off);
int offset = 4;
int left = opt->rect.left();
@@ -1994,7 +1998,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon);
}
- drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
+ proxy()->drawItemText(p, tr, alignment, tab->palette, tab->state & State_Enabled, tab->text, QPalette::WindowText);
if (verticalTabs)
p->restore();
@@ -2105,7 +2109,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
p->save();
QRect r = opt->rect;
QStyleHintReturnMask mask;
- if (styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
+ if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
p->setClipRegion(mask.region);
p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap);
p->setPen(opt->palette.color(QPalette::Active, QPalette::WindowText));
@@ -2143,7 +2147,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
}
const int indent = p->fontMetrics().descent();
- drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1),
+ proxy()->drawItemText(p, r.adjusted(indent + 1, 1, -indent - 1, -1),
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, dwOpt->title,
QPalette::WindowText);
@@ -2158,14 +2162,14 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
QRegion clipRegion = p->clipRegion();
p->setClipRect(opt->rect);
- drawControl(CE_HeaderSection, header, p, widget);
+ proxy()->drawControl(CE_HeaderSection, header, p, widget);
QStyleOptionHeader subopt = *header;
subopt.rect = subElementRect(SE_HeaderLabel, header, widget);
if (subopt.rect.isValid())
- drawControl(CE_HeaderLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_HeaderLabel, &subopt, p, widget);
if (header->sortIndicator != QStyleOptionHeader::None) {
subopt.rect = subElementRect(SE_HeaderArrow, opt, widget);
- drawPrimitive(PE_IndicatorHeaderArrow, &subopt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorHeaderArrow, &subopt, p, widget);
}
p->setClipRegion(clipRegion);
}
@@ -2184,7 +2188,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
#ifndef QT_NO_COMBOBOX
case CE_ComboBoxLabel:
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
p->save();
p->setClipRect(editRect);
if (!cb->currentIcon.isNull()) {
@@ -2198,7 +2202,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
iconRect.size(), editRect);
if (cb->editable)
p->fillRect(iconRect, opt->palette.brush(QPalette::Base));
- drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(p, iconRect, Qt::AlignCenter, pixmap);
if (cb->direction == Qt::RightToLeft)
editRect.translate(-4 - cb->iconSize.width(), 0);
@@ -2206,7 +2210,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
editRect.translate(cb->iconSize.width() + 4, 0);
}
if (!cb->currentText.isEmpty() && !cb->editable) {
- drawItemText(p, editRect.adjusted(1, 0, -1, 0),
+ proxy()->drawItemText(p, editRect.adjusted(1, 0, -1, 0),
visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
cb->palette, cb->state & State_Enabled, cb->currentText);
}
@@ -2222,7 +2226,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
frame.QStyleOption::operator=(*toolBar);
frame.lineWidth = toolBar->lineWidth;
frame.midLineWidth = toolBar->midLineWidth;
- drawPrimitive(PE_PanelToolBar, opt, p, widget);
+ proxy()->drawPrimitive(PE_PanelToolBar, opt, p, widget);
if (widget && qobject_cast<QToolBar *>(widget->parentWidget()))
break;
@@ -2264,10 +2268,10 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
QRect textRect = subElementRect(SE_ItemViewItemText, vopt, widget);
// draw the background
- drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
+ proxy()->drawPrimitive(PE_PanelItemViewItem, opt, p, widget);
// draw the check mark
- if (checkRect.isValid()) {
+ if (vopt->features & QStyleOptionViewItemV2::HasCheckIndicator) {
QStyleOptionViewItemV4 option(*vopt);
option.rect = checkRect;
option.state = option.state & ~QStyle::State_HasFocus;
@@ -2283,7 +2287,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
option.state |= QStyle::State_On;
break;
}
- drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_IndicatorViewItemCheck, &option, p, widget);
}
// draw the icon
@@ -2326,7 +2330,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
? QPalette::Normal : QPalette::Disabled;
o.backgroundColor = vopt->palette.color(cg, (vopt->state & QStyle::State_Selected)
? QPalette::Highlight : QPalette::Window);
- drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &o, p, widget);
}
p->restore();
@@ -2365,7 +2369,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt,
if (widget) {
widget->style()->drawPrimitive(QStyle::PE_Frame, opt, p, widget);
} else {
- drawPrimitive(QStyle::PE_Frame, opt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_Frame, opt, p, widget);
}
break;
case QFrame::Panel:
@@ -2423,9 +2427,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_PushButtonContents:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
int dx1, dx2;
- dx1 = pixelMetric(PM_DefaultFrameWidth, btn, widget);
+ dx1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
if (btn->features & QStyleOptionButton::AutoDefaultButton)
- dx1 += pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ dx1 += proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
dx2 = dx1 * 2;
r.setRect(opt->rect.x() + dx1, opt->rect.y() + dx1, opt->rect.width() - dx2,
opt->rect.height() - dx2);
@@ -2436,11 +2440,11 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
int dbw1 = 0, dbw2 = 0;
if (btn->features & QStyleOptionButton::AutoDefaultButton){
- dbw1 = pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ dbw1 = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
dbw2 = dbw1 * 2;
}
- int dfw1 = pixelMetric(PM_DefaultFrameWidth, btn, widget) + 1,
+ int dfw1 = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) + 1,
dfw2 = dfw1 * 2;
r.setRect(btn->rect.x() + dfw1 + dbw1, btn->rect.y() + dfw1 + dbw1,
@@ -2450,9 +2454,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_CheckBoxIndicator:
{
- int h = pixelMetric(PM_IndicatorHeight, opt, widget);
+ int h = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2),
- pixelMetric(PM_IndicatorWidth, opt, widget), h);
+ proxy()->pixelMetric(PM_IndicatorWidth, opt, widget), h);
r = visualRect(opt->direction, opt->rect, r);
}
break;
@@ -2462,7 +2466,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
// Deal with the logical first, then convert it back to screen coords.
QRect ir = visualRect(opt->direction, opt->rect,
subElementRect(SE_CheckBoxIndicator, opt, widget));
- int spacing = pixelMetric(PM_CheckBoxLabelSpacing, opt, widget);
+ int spacing = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget);
r.setRect(ir.right() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing,
opt->rect.height());
r = visualRect(opt->direction, opt->rect, r);
@@ -2502,9 +2506,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_RadioButtonIndicator:
{
- int h = pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget);
+ int h = proxy()->pixelMetric(PM_ExclusiveIndicatorHeight, opt, widget);
r.setRect(opt->rect.x(), opt->rect.y() + ((opt->rect.height() - h) / 2),
- pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), h);
+ proxy()->pixelMetric(PM_ExclusiveIndicatorWidth, opt, widget), h);
r = visualRect(opt->direction, opt->rect, r);
}
break;
@@ -2513,7 +2517,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
{
QRect ir = visualRect(opt->direction, opt->rect,
subElementRect(SE_RadioButtonIndicator, opt, widget));
- int spacing = pixelMetric(PM_RadioButtonLabelSpacing, opt, widget);
+ int spacing = proxy()->pixelMetric(PM_RadioButtonLabelSpacing, opt, widget);
r.setRect(ir.left() + ir.width() + spacing, opt->rect.y(), opt->rect.width() - ir.width() - spacing,
opt->rect.height());
r = visualRect(opt->direction, opt->rect, r);
@@ -2550,8 +2554,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
#ifndef QT_NO_SLIDER
case SE_SliderFocusRect:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
if (slider->orientation == Qt::Horizontal)
r.setRect(0, tickOffset - 1, slider->rect.width(), thickness + 2);
else
@@ -2622,7 +2626,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
#endif // QT_NO_TOOLBOX
case SE_HeaderLabel: {
- int margin = pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
r.setRect(opt->rect.x() + margin, opt->rect.y() + margin,
opt->rect.width() - margin * 2, opt->rect.height() - margin * 2);
@@ -2642,7 +2646,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
int w = opt->rect.width();
int x = opt->rect.x();
int y = opt->rect.y();
- int margin = pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, opt, widget);
if (opt->state & State_Horizontal) {
int horiz_size = h / 2;
@@ -2678,7 +2682,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setWidth(qMin(r.width(), twf->rect.width()
- twf->leftCornerWidgetSize.width()
- twf->rightCornerWidgetSize.width()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(), 0));
@@ -2700,7 +2704,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setWidth(qMin(r.width(), twf->rect.width()
- twf->leftCornerWidgetSize.width()
- twf->rightCornerWidgetSize.width()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(twf->leftCornerWidgetSize.width(),
@@ -2725,7 +2729,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setHeight(qMin(r.height(), twf->rect.height()
- twf->leftCornerWidgetSize.height()
- twf->rightCornerWidgetSize.height()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(twf->rect.width() - twf->tabBarSize.width(),
@@ -2747,7 +2751,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
r.setHeight(qMin(r.height(), twf->rect.height()
- twf->leftCornerWidgetSize.height()
- twf->rightCornerWidgetSize.height()));
- switch (styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
+ switch (proxy()->styleHint(SH_TabBar_Alignment, twf, widget) & alingMask) {
default:
case Qt::AlignLeft:
r.moveTopLeft(QPoint(0, twf->leftCornerWidgetSize.height()));
@@ -2769,7 +2773,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (const QStyleOptionTabWidgetFrame *twf = qstyleoption_cast<const QStyleOptionTabWidgetFrame *>(opt)) {
QStyleOptionTab tabopt;
tabopt.shape = twf->shape;
- int overlap = pixelMetric(PM_TabBarBaseOverlap, &tabopt, widget);
+ int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &tabopt, widget);
if (twf->lineWidth == 0)
overlap = 0;
switch (twf->shape) {
@@ -2849,9 +2853,11 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
tr.setRect(0, 0, tr.height(), tr.width());
int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
+ int hpadding = proxy()->pixelMetric(QStyle::PM_TabBarTabHSpace, opt, widget) / 2;
+ int vpadding = proxy()->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;
if (tabV2.shape == QTabBar::RoundedSouth || tabV2.shape == QTabBar::TriangularSouth)
verticalShift = -verticalShift;
- tr.adjust(0, 0, horizontalShift, verticalShift);
+ tr.adjust(hpadding, vpadding, horizontalShift - hpadding, verticalShift - vpadding);
bool selected = tabV2.state & State_Selected;
if (selected) {
tr.setBottom(tr.bottom() - verticalShift);
@@ -2868,7 +2874,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (!tabV2.icon.isNull()) {
QSize iconSize = tabV2.iconSize;
if (!iconSize.isValid()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
iconSize = QSize(iconExtent, iconExtent);
}
QSize tabIconSize = tabV2.icon.actualSize(iconSize,
@@ -2900,8 +2906,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_TabBarTabRightButton:
if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) {
bool selected = tab->state & State_Selected;
- int verticalShift = pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
- int horizontalShift = pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
+ int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget);
+ int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget);
bool verticalTabs = tab->shape == QTabBar::RoundedEast
|| tab->shape == QTabBar::RoundedWest
@@ -2990,7 +2996,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
break;
case SE_FrameContents:
if (const QStyleOptionFrameV2 *f = qstyleoption_cast<const QStyleOptionFrameV2 *>(opt)) {
- int fw = pixelMetric(PM_DefaultFrameWidth, f, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, f, widget);
r = opt->rect.adjusted(fw, fw, -fw, -fw);
r = visualRect(opt->direction, opt->rect, r);
}
@@ -3057,9 +3063,9 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
case SE_DockWidgetFloatButton:
case SE_DockWidgetTitleBarText:
case SE_DockWidgetIcon: {
- int iconSize = pixelMetric(PM_SmallIconSize, opt, widget);
- int buttonMargin = pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
- int margin = pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget);
+ int iconSize = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
+ int buttonMargin = proxy()->pixelMetric(PM_DockWidgetTitleBarButtonMargin, opt, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, opt, widget);
QRect rect = opt->rect;
const QStyleOptionDockWidget *dwOpt
@@ -3124,7 +3130,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
if (dw->isFloating())
icon = dw->windowIcon();
if (!icon.isNull()
- && icon.cacheKey() != qApp->windowIcon().cacheKey()) {
+ && icon.cacheKey() != QApplication::windowIcon().cacheKey()) {
QSize sz = icon.actualSize(QSize(r.height(), r.height()));
if (verticalTitleBar)
sz.transpose();
@@ -3182,6 +3188,25 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
break;
#endif //QT_NO_ITEMVIEWS
+#ifndef QT_NO_TOOLBAR
+ case SE_ToolBarHandle:
+ if (const QStyleOptionToolBar *tbopt = qstyleoption_cast<const QStyleOptionToolBar *>(opt)) {
+ if (tbopt->features & QStyleOptionToolBar::Movable) {
+ ///we need to access the widget here because the style option doesn't
+ //have all the information we need (ie. the layout's margin)
+ const QToolBar *tb = qobject_cast<const QToolBar*>(widget);
+ const int margin = tb && tb->layout() ? tb->layout()->margin() : 2;
+ const int handleExtent = pixelMetric(QStyle::PM_ToolBarExtensionExtent, opt, tb);
+ if (tbopt->state & QStyle::State_Horizontal) {
+ r = QRect(margin, margin, handleExtent, tbopt->rect.height() - 2*margin);
+ r = QStyle::visualRect(tbopt->direction, tbopt->rect, r);
+ } else {
+ r = QRect(margin, margin, tbopt->rect.width() - 2*margin, handleExtent);
+ }
+ }
+ }
+ break;
+#endif //QT_NO_TOOLBAR
default:
break;
}
@@ -3189,47 +3214,6 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt,
}
#ifndef QT_NO_DIAL
-static qreal angle(const QPointF &p1, const QPointF &p2)
-{
- static const qreal rad_factor = 180 / Q_PI;
- qreal _angle = 0;
-
- if (p1.x() == p2.x()) {
- if (p1.y() < p2.y())
- _angle = 270;
- else
- _angle = 90;
- } else {
- qreal x1, x2, y1, y2;
-
- if (p1.x() <= p2.x()) {
- x1 = p1.x(); y1 = p1.y();
- x2 = p2.x(); y2 = p2.y();
- } else {
- x2 = p1.x(); y2 = p1.y();
- x1 = p2.x(); y1 = p2.y();
- }
-
- qreal m = -(y2 - y1) / (x2 - x1);
- _angle = atan(m) * rad_factor;
-
- if (p1.x() < p2.x())
- _angle = 180 - _angle;
- else
- _angle = -_angle;
- }
- return _angle;
-}
-
-static int calcBigLineSize(int radius)
-{
- int bigLineSize = radius / 6;
- if (bigLineSize < 4)
- bigLineSize = 4;
- if (bigLineSize > radius / 2)
- bigLineSize = radius / 2;
- return bigLineSize;
-}
static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a)
{
@@ -3250,7 +3234,7 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a)
int xc = width / 2;
int yc = height / 2;
- int len = r - calcBigLineSize(r) - 5;
+ int len = r - QStyleHelper::calcBigLineSize(r) - 5;
if (len < 5)
len = 5;
int back = len / 2;
@@ -3265,45 +3249,6 @@ static QPolygonF calcArrow(const QStyleOptionSlider *dial, qreal &a)
return arrow;
}
-static QPolygonF calcLines(const QStyleOptionSlider *dial, const QWidget *)
-{
- QPolygonF poly;
- int width = dial->rect.width();
- int height = dial->rect.height();
- qreal r = qMin(width, height) / 2;
- int bigLineSize = calcBigLineSize(int(r));
-
- qreal xc = width / 2;
- qreal yc = height / 2;
- int ns = dial->tickInterval;
- int notches = (dial->maximum + ns - 1 - dial->minimum) / ns;
- if (notches <= 0)
- return poly;
- if (dial->maximum < dial->minimum
- || dial->maximum - dial->minimum > 1000) {
- int maximum = dial->minimum + 1000;
- notches = (maximum + ns - 1 - dial->minimum) / ns;
- }
-
- poly.resize(2 + 2 * notches);
- int smallLineSize = bigLineSize / 2;
- for (int i = 0; i <= notches; ++i) {
- qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches
- : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6;
- qreal s = qSin(angle);
- qreal c = qCos(angle);
- if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) {
- poly[2 * i] = QPointF(xc + (r - bigLineSize) * c,
- yc - (r - bigLineSize) * s);
- poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s);
- } else {
- poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c,
- yc - (r - 1 - smallLineSize) * s);
- poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s);
- }
- }
- return poly;
-}
#endif // QT_NO_DIAL
/*!
@@ -3317,11 +3262,11 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (slider->subControls == SC_SliderTickmarks) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
int ticks = slider->tickPosition;
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -3379,71 +3324,71 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (scrollbar->subControls & SC_ScrollBarSubLine) {
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSubLine))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarSubLine, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarAddLine) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddLine, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarAddLine))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarAddLine, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarSubPage) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSubPage, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSubPage))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarSubPage, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarAddPage) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarAddPage, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarAddPage))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarAddPage, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarFirst) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarFirst, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarFirst))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarFirst, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarLast) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarLast, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarLast))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarLast, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarLast, &newScrollbar, p, widget);
}
}
if (scrollbar->subControls & SC_ScrollBarSlider) {
newScrollbar.rect = scrollbar->rect;
newScrollbar.state = saveFlags;
- newScrollbar.rect = subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget);
+ newScrollbar.rect = proxy()->subControlRect(cc, &newScrollbar, SC_ScrollBarSlider, widget);
if (newScrollbar.rect.isValid()) {
if (!(scrollbar->activeSubControls & SC_ScrollBarSlider))
newScrollbar.state &= ~(State_Sunken | State_MouseOver);
- drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget);
+ proxy()->drawControl(CE_ScrollBarSlider, &newScrollbar, p, widget);
if (scrollbar->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
@@ -3451,7 +3396,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
fropt.rect.setRect(newScrollbar.rect.x() + 2, newScrollbar.rect.y() + 2,
newScrollbar.rect.width() - 5,
newScrollbar.rect.height() - 5);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
}
@@ -3473,7 +3418,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
PrimitiveElement pe;
if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
- QRect r = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
+ QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
qDrawWinPanel(p, r, sb->palette, true);
}
@@ -3497,10 +3442,10 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
: PE_IndicatorSpinUp);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
- drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
copy.rect.adjust(3, 0, -4, 0);
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
if (sb->subControls & SC_SpinBoxDown) {
@@ -3523,10 +3468,10 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
: PE_IndicatorSpinDown);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
- drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &copy, p, widget);
copy.rect.adjust(3, 0, -4, 0);
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
}
break;
@@ -3536,8 +3481,8 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QRect button, menuarea;
- button = subControlRect(cc, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
@@ -3559,7 +3504,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (bflags & (State_Sunken | State_On | State_Raised)) {
tool.rect = button;
tool.state = bflags;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
}
@@ -3568,28 +3513,28 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
fr.QStyleOption::operator=(*toolbutton);
fr.rect.adjust(3, 3, -3, -3);
if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
- fr.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator,
+ fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
toolbutton, widget), 0);
- drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
if (mflags & (State_Sunken | State_On | State_Raised))
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
- drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 5 - mbi, ir.y() + ir.height() - mbi + 4, mbi - 6, mbi - 6);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -3613,7 +3558,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
p->fillRect(opt->rect, fillBrush);
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
p->setPen(tb->palette.highlightedText().color());
p->drawText(ir.x() + 2, ir.y(), ir.width() - 2, ir.height(),
@@ -3626,7 +3571,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QStyleOption tool(0);
tool.palette = tb->palette;
if (tb->subControls & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarCloseButton, widget);
down = tb->activeSubControls & SC_TitleBarCloseButton && (opt->state & State_Sunken);
if ((tb->titleBarFlags & Qt::WindowType_Mask) == Qt::Tool
#ifndef QT_NO_DOCKWIDGET
@@ -3638,50 +3583,50 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
pm = standardIcon(SP_TitleBarCloseButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarMaxButton
&& tb->titleBarFlags & Qt::WindowMaximizeButtonHint
&& !(tb->titleBarState & Qt::WindowMaximized)) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMaxButton, widget);
down = tb->activeSubControls & SC_TitleBarMaxButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarMaxButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarMinButton
&& tb->titleBarFlags & Qt::WindowMinimizeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarMinButton, widget);
down = tb->activeSubControls & SC_TitleBarMinButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarMinButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
@@ -3692,81 +3637,81 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
&& (tb->titleBarState & Qt::WindowMaximized)));
if (drawNormalButton) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarNormalButton, widget);
down = tb->activeSubControls & SC_TitleBarNormalButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarNormalButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarShadeButton
&& tb->titleBarFlags & Qt::WindowShadeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarShadeButton, widget);
down = (tb->activeSubControls & SC_TitleBarShadeButton && (opt->state & State_Sunken));
pm = standardIcon(SP_TitleBarShadeButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarUnshadeButton
&& tb->titleBarFlags & Qt::WindowShadeButtonHint
&& tb->titleBarState & Qt::WindowMinimized) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarUnshadeButton, widget);
down = tb->activeSubControls & SC_TitleBarUnshadeButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarUnshadeButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarContextHelpButton
&& tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarContextHelpButton, widget);
down = tb->activeSubControls & SC_TitleBarContextHelpButton && (opt->state & State_Sunken);
pm = standardIcon(SP_TitleBarContextHelpButton, &tool, widget).pixmap(10, 10);
tool.rect = ir;
tool.state = down ? State_Sunken : State_Raised;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
p->save();
if (down)
- p->translate(pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
- pixelMetric(PM_ButtonShiftVertical, tb, widget));
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ p->translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, tb, widget));
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
if (tb->subControls & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- ir = subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget);
+ ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarSysMenu, widget);
if (!tb->icon.isNull()) {
tb->icon.paint(p, ir);
} else {
- int iconSize = pixelMetric(PM_SmallIconSize, tb, widget);
+ int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget);
pm = standardIcon(SP_TitleBarMenuButton, &tool, widget).pixmap(iconSize, iconSize);
tool.rect = ir;
p->save();
- drawItemPixmap(p, ir, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, ir, Qt::AlignCenter, pm);
p->restore();
}
}
@@ -3794,11 +3739,11 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
// draw notches
if (dial->subControls & QStyle::SC_DialTickmarks) {
p->setPen(pal.foreground().color());
- p->drawLines(calcLines(dial, widget)); // ### calcLines could be cached...
+ p->drawLines(QStyleHelper::calcLines(dial));
}
if (dial->state & State_Enabled) {
- p->setBrush(pal.brush(QPalette::ColorRole(styleHint(SH_Dial_BackgroundRole,
+ p->setBrush(pal.brush(QPalette::ColorRole(proxy()->styleHint(SH_Dial_BackgroundRole,
dial, widget))));
p->setPen(Qt::NoPen);
p->drawEllipse(br);
@@ -3816,7 +3761,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
p->setBrush(pal.button());
p->drawPolygon(arrow);
- a = angle(QPointF(width / 2, height / 2), arrow[0]);
+ a = QStyleHelper::angle(QPointF(width / 2, height / 2), arrow[0]);
p->setBrush(Qt::NoBrush);
if (a <= 0 || a > 200) {
@@ -3859,7 +3804,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
br.setHeight(br.height() + r / 3);
}
fropt.rect = br.adjusted(-2, -2, 2, 2);
- drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameFocusRect, &fropt, p, widget);
}
p->restore();
}
@@ -3869,15 +3814,15 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
case CC_GroupBox:
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(opt)) {
// Draw frame
- QRect textRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxCheckBox, widget);
if (groupBox->subControls & QStyle::SC_GroupBoxFrame) {
QStyleOptionFrameV2 frame;
frame.QStyleOption::operator=(*groupBox);
frame.features = groupBox->features;
frame.lineWidth = groupBox->lineWidth;
frame.midLineWidth = groupBox->midLineWidth;
- frame.rect = subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
+ frame.rect = proxy()->subControlRect(CC_GroupBox, opt, SC_GroupBoxFrame, widget);
p->save();
QRegion region(groupBox->rect);
if (!groupBox->text.isEmpty()) {
@@ -3892,7 +3837,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
region -= finalRect;
}
p->setClipRegion(region);
- drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
+ proxy()->drawPrimitive(PE_FrameGroupBox, &frame, p, widget);
p->restore();
}
@@ -3902,10 +3847,10 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (textColor.isValid())
p->setPen(textColor);
int alignment = int(groupBox->textAlignment);
- if (!styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
+ if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, opt, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
+ proxy()->drawItemText(p, textRect, Qt::TextShowMnemonic | Qt::AlignHCenter | alignment,
groupBox->palette, groupBox->state & State_Enabled, groupBox->text,
textColor.isValid() ? QPalette::NoRole : QPalette::WindowText);
@@ -3913,7 +3858,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*groupBox);
fropt.rect = textRect;
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
@@ -3922,7 +3867,7 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, p, widget);
}
}
break;
@@ -3939,52 +3884,52 @@ void QCommonStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCompl
if (opt->activeSubControls & QStyle::SC_MdiCloseButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
bsx = 0;
bsy = 0;
}
- btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget);
- drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
+ btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiCloseButton, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
QPixmap pm = standardIcon(SP_TitleBarCloseButton).pixmap(16, 16);
- drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
}
if (opt->subControls & QStyle::SC_MdiNormalButton) {
if (opt->activeSubControls & QStyle::SC_MdiNormalButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
bsx = 0;
bsy = 0;
}
- btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget);
- drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
+ btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiNormalButton, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
QPixmap pm = standardIcon(SP_TitleBarNormalButton).pixmap(16, 16);
- drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
}
if (opt->subControls & QStyle::SC_MdiMinButton) {
if (opt->activeSubControls & QStyle::SC_MdiMinButton && (opt->state & State_Sunken)) {
btnOpt.state |= State_Sunken;
btnOpt.state &= ~State_Raised;
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
} else {
btnOpt.state |= State_Raised;
btnOpt.state &= ~State_Sunken;
bsx = 0;
bsy = 0;
}
- btnOpt.rect = subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget);
- drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
+ btnOpt.rect = proxy()->subControlRect(CC_MdiControls, opt, SC_MdiMinButton, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btnOpt, p, widget);
QPixmap pm = standardIcon(SP_TitleBarMinButton).pixmap(16, 16);
- drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(p, btnOpt.rect.translated(bsx, bsy), Qt::AlignCenter, pm);
}
}
break;
@@ -4006,11 +3951,11 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- QRect r = subControlRect(cc, slider, SC_SliderHandle, widget);
+ QRect r = proxy()->subControlRect(cc, slider, SC_SliderHandle, widget);
if (r.isValid() && r.contains(pt)) {
sc = SC_SliderHandle;
} else {
- r = subControlRect(cc, slider, SC_SliderGroove ,widget);
+ r = proxy()->subControlRect(cc, slider, SC_SliderGroove ,widget);
if (r.isValid() && r.contains(pt))
sc = SC_SliderGroove;
}
@@ -4023,7 +3968,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_ScrollBarAddLine;
while (ctrl <= SC_ScrollBarGroove) {
- r = subControlRect(cc, scrollbar, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, scrollbar, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4039,7 +3984,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_ToolButton;
while (ctrl <= SC_ToolButtonMenu) {
- r = subControlRect(cc, toolbutton, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, toolbutton, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4063,7 +4008,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_SpinBoxUp;
while (ctrl <= SC_SpinBoxEditField) {
- r = subControlRect(cc, spinbox, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, spinbox, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4079,7 +4024,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
uint ctrl = SC_TitleBarSysMenu;
while (ctrl <= SC_TitleBarLabel) {
- r = subControlRect(cc, tb, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, tb, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4094,7 +4039,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_ComboBoxArrow; // Start here and go down.
while (ctrl > 0) {
- r = subControlRect(cc, cb, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, cb, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4110,7 +4055,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_GroupBoxCheckBox;
while (ctrl <= SC_GroupBoxFrame) {
- r = subControlRect(cc, groupBox, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(cc, groupBox, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt)) {
sc = QStyle::SubControl(ctrl);
break;
@@ -4125,7 +4070,7 @@ QStyle::SubControl QCommonStyle::hitTestComplexControl(ComplexControl cc, const
QRect r;
uint ctrl = SC_MdiMinButton;
while (ctrl <= SC_MdiCloseButton) {
- r = subControlRect(CC_MdiControls, opt, QStyle::SubControl(ctrl), widget);
+ r = proxy()->subControlRect(CC_MdiControls, opt, QStyle::SubControl(ctrl), widget);
if (r.isValid() && r.contains(pt) && (opt->subControls & ctrl)) {
sc = QStyle::SubControl(ctrl);
return sc;
@@ -4151,13 +4096,13 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
switch (sc) {
case SC_SliderHandle: {
int sliderPos = 0;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum,
slider->sliderPosition,
@@ -4188,7 +4133,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
const QRect scrollBarRect = scrollbar->rect;
- int sbextent = pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
+ int sbextent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollbar, widget);
int maxlen = ((scrollbar->orientation == Qt::Horizontal) ?
scrollBarRect.width() : scrollBarRect.height()) - (sbextent * 2);
int sliderlen;
@@ -4198,7 +4143,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
uint range = scrollbar->maximum - scrollbar->minimum;
sliderlen = (qint64(scrollbar->pageStep) * maxlen) / (range + scrollbar->pageStep);
- int slidermin = pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
+ int slidermin = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollbar, widget);
if (sliderlen < slidermin || range > INT_MAX / 2)
sliderlen = slidermin;
if (sliderlen > maxlen)
@@ -4271,7 +4216,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
QSize bs;
- int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
bs.setHeight(qMax(8, spinbox->rect.height()/2 - fw));
// 1.6 -approximate golden mean
bs.setWidth(qMax(16, qMin(bs.height() * 8 / 5, spinbox->rect.width() / 4)));
@@ -4312,7 +4257,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
#ifndef QT_NO_TOOLBUTTON
case CC_ToolButton:
if (const QStyleOptionToolButton *tb = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, tb, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, tb, widget);
ret = tb->rect;
switch (sc) {
case SC_ToolButton:
@@ -4452,7 +4397,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
case SC_GroupBoxContents: {
int topMargin = 0;
int topHeight = 0;
- int verticalAlignment = styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
+ int verticalAlignment = proxy()->styleHint(SH_GroupBox_TextLabelVerticalAlignment, groupBox, widget);
if (groupBox->text.size() || (groupBox->subControls & QStyle::SC_GroupBoxCheckBox)) {
topHeight = groupBox->fontMetrics.height();
if (verticalAlignment & Qt::AlignVCenter)
@@ -4472,7 +4417,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
int frameWidth = 0;
if (!(widget && widget->inherits("Q3GroupBox"))
&& ((groupBox->features & QStyleOptionFrameV2::Flat) == 0)) {
- frameWidth = pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
+ frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth, groupBox, widget);
}
ret = frameRect.adjusted(frameWidth, frameWidth + topHeight - topMargin,
-frameWidth, -frameWidth);
@@ -4488,8 +4433,8 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
ret = groupBox->rect.adjusted(marg, 0, -marg, 0);
ret.setHeight(h);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, opt, widget);
- int indicatorSpace = pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
+ int indicatorSpace = proxy()->pixelMetric(PM_CheckBoxLabelSpacing, opt, widget) - 1;
bool hasCheckBox = groupBox->subControls & QStyle::SC_GroupBoxCheckBox;
int checkBoxSize = hasCheckBox ? (indicatorWidth + indicatorSpace) : 0;
@@ -4503,7 +4448,7 @@ QRect QCommonStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex
int left = 0;
// Adjust for check box
if (sc == SC_GroupBoxCheckBox) {
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, opt, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, opt, widget);
left = ltr ? totalRect.left() : (totalRect.right() - indicatorWidth);
int top = totalRect.top() + (fontMetrics.height() - indicatorHeight) / 2;
totalRect.setRect(left, top, indicatorWidth, indicatorHeight);
@@ -4649,7 +4594,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_MenuPanelWidth:
case PM_TabBarBaseOverlap:
case PM_TabBarBaseHeight:
- ret = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
break;
case PM_MdiSubWindowFrameWidth:
@@ -4685,7 +4630,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
int space = (sl->orientation == Qt::Horizontal) ? sl->rect.height()
: sl->rect.width();
- int thickness = pixelMetric(PM_SliderControlThickness, sl, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, sl, widget);
int ticks = sl->tickPosition;
if (ticks == QSlider::TicksBothSides)
@@ -4702,9 +4647,9 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_SliderSpaceAvailable:
if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (sl->orientation == Qt::Horizontal)
- ret = sl->rect.width() - pixelMetric(PM_SliderLength, sl, widget);
+ ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
else
- ret = sl->rect.height() - pixelMetric(PM_SliderLength, sl, widget);
+ ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, sl, widget);
} else {
ret = 0;
}
@@ -4848,12 +4793,12 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
} else if (widget) {
isWindow = widget->isWindow();
}
- ret = pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin);
+ ret = proxy()->pixelMetric(isWindow ? PM_DefaultTopLevelMargin : PM_DefaultChildMargin);
}
break;
case PM_LayoutHorizontalSpacing:
case PM_LayoutVerticalSpacing:
- ret = pixelMetric(PM_DefaultLayoutSpacing);
+ ret = proxy()->pixelMetric(PM_DefaultLayoutSpacing);
break;
case PM_DefaultTopLevelMargin:
@@ -4869,7 +4814,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
case PM_TabBarIconSize:
case PM_ToolBarIconSize:
case PM_ListViewIconSize:
- ret = pixelMetric(PM_SmallIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
break;
case PM_ButtonIconSize:
@@ -4877,7 +4822,7 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
ret = 16;
break;
case PM_IconViewIconSize:
- ret = pixelMetric(PM_LargeIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
break;
case PM_LargeIconSize:
@@ -4908,10 +4853,10 @@ int QCommonStyle::pixelMetric(PixelMetric m, const QStyleOption *opt, const QWid
ret = 16;
break;
case PM_ScrollView_ScrollBarSpacing:
- ret = 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
break;
case PM_SubMenuOverlap:
- ret = -pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget);
+ ret = -proxy()->pixelMetric(QStyle::PM_MenuPanelWidth, opt, widget);
break;
default:
ret = 0;
@@ -4934,12 +4879,12 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
int w = csz.width(),
h = csz.height(),
- bm = pixelMetric(PM_ButtonMargin, btn, widget),
- fw = pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2;
+ bm = proxy()->pixelMetric(PM_ButtonMargin, btn, widget),
+ fw = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget) * 2;
w += bm + fw;
h += bm + fw;
if (btn->features & QStyleOptionButton::AutoDefaultButton){
- int dbw = pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2;
+ int dbw = proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget) * 2;
w += dbw;
h += dbw;
}
@@ -4951,15 +4896,15 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
bool isRadio = (ct == CT_RadioButton);
- int w = pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
+ int w = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorWidth
: PM_IndicatorWidth, btn, widget);
- int h = pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
+ int h = proxy()->pixelMetric(isRadio ? PM_ExclusiveIndicatorHeight
: PM_IndicatorHeight, btn, widget);
int margins = 0;
// we add 4 pixels for label margins
if (btn->icon.isNull() || !btn->text.isEmpty())
- margins = 4 + pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
+ margins = 4 + proxy()->pixelMetric(isRadio ? PM_RadioButtonLabelSpacing
: PM_CheckBoxLabelSpacing, opt, widget);
sz += QSize(w + margins, 4);
sz.setHeight(qMax(sz.height(), h));
@@ -4977,7 +4922,7 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
} else {
h = mi->fontMetrics.height() + 8;
if (!mi->icon.isNull()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
}
}
@@ -5002,10 +4947,10 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#ifndef QT_NO_COMBOBOX
case CT_ComboBox:
if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
- int fw = cmb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
- const int textMargins = 2*(pixelMetric(PM_FocusFrameHMargin) + 1);
+ int fw = cmb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) * 2 : 0;
+ const int textMargins = 2*(proxy()->pixelMetric(PM_FocusFrameHMargin) + 1);
// QItemDelegate::sizeHint expands the textMargins two times, thus the 2*textMargins...
- int other = qMax(23, 2*textMargins + pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
+ int other = qMax(23, 2*textMargins + proxy()->pixelMetric(QStyle::PM_ScrollBarExtent, opt, widget));
sz = QSize(sz.width() + fw + other, sz.height() + fw);
}
break;
@@ -5013,8 +4958,8 @@ QSize QCommonStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
case CT_HeaderSection:
if (const QStyleOptionHeader *hdr = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
bool nullIcon = hdr->icon.isNull();
- int margin = pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
- int iconSize = nullIcon ? 0 : pixelMetric(QStyle::PM_SmallIconSize, hdr, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, hdr, widget);
+ int iconSize = nullIcon ? 0 : proxy()->pixelMetric(QStyle::PM_SmallIconSize, hdr, widget);
QSize txt = hdr->fontMetrics.size(0, hdr->text);
sz.setHeight(margin + qMax(iconSize, txt.height()) + margin);
sz.setWidth((nullIcon ? 0 : margin) + iconSize
@@ -5212,8 +5157,8 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
if (widget) {
if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
mask->region = widget->rect();
- int vmargin = pixelMetric(QStyle::PM_FocusFrameVMargin),
- hmargin = pixelMetric(QStyle::PM_FocusFrameHMargin);
+ int vmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameVMargin),
+ hmargin = proxy()->pixelMetric(QStyle::PM_FocusFrameHMargin);
mask->region -= QRect(widget->rect().adjusted(hmargin, vmargin, -hmargin, -vmargin));
}
}
@@ -5226,7 +5171,7 @@ int QCommonStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget
ret = true;
if(QStyleHintReturnMask *mask = qstyleoption_cast<QStyleHintReturnMask*>(hret)) {
mask->region = opt->rect;
- int margin = pixelMetric(PM_DefaultFrameWidth) * 2;
+ int margin = proxy()->pixelMetric(PM_DefaultFrameWidth) * 2;
mask->region -= opt->rect.adjusted(margin, margin, -margin, -margin);
}
}
@@ -5364,7 +5309,7 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
#ifdef Q_WS_X11
Q_D(const QCommonStyle);
QPixmap pixmap;
- if (qApp->desktopSettingsAware()) {
+ if (QApplication::desktopSettingsAware()) {
d->lookupIconTheme();
switch (sp) {
case SP_DirHomeIcon:
@@ -5669,12 +5614,12 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
case SP_CommandLink:
case SP_ArrowForward:
if (QApplication::layoutDirection() == Qt::RightToLeft)
- return standardPixmap(SP_ArrowLeft, option, widget);
- return standardPixmap(SP_ArrowRight, option, widget);
+ return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
+ return proxy()->standardPixmap(SP_ArrowRight, option, widget);
case SP_ArrowBack:
if (QApplication::layoutDirection() == Qt::RightToLeft)
- return standardPixmap(SP_ArrowRight, option, widget);
- return standardPixmap(SP_ArrowLeft, option, widget);
+ return proxy()->standardPixmap(SP_ArrowRight, option, widget);
+ return proxy()->standardPixmap(SP_ArrowLeft, option, widget);
case SP_ArrowLeft:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/left-16.png"));
case SP_ArrowRight:
@@ -5684,7 +5629,7 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
case SP_ArrowDown:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/down-16.png"));
case SP_FileDialogToParent:
- return standardPixmap(SP_ArrowUp, option, widget);
+ return proxy()->standardPixmap(SP_ArrowUp, option, widget);
case SP_FileDialogNewFolder:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/newdirectory-16.png"));
case SP_FileDialogDetailedView:
@@ -5696,7 +5641,7 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
case SP_FileDialogListView:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/viewlist-16.png"));
case SP_FileDialogBack:
- return standardPixmap(SP_ArrowBack, option, widget);
+ return proxy()->standardPixmap(SP_ArrowBack, option, widget);
case SP_DriveHDIcon:
return QPixmap(QLatin1String(":/trolltech/styles/commonstyle/images/harddrive-16.png"));
case SP_TrashIcon:
@@ -5785,7 +5730,7 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
QIcon icon;
#ifdef Q_WS_X11
Q_D(const QCommonStyle);
- if (qApp->desktopSettingsAware()) {
+ if (QApplication::desktopSettingsAware()) {
d->lookupIconTheme();
QPixmap pixmap;
switch (standardIcon) {
@@ -5997,7 +5942,7 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
}
case SP_FileLinkIcon: {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
+ icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget));
QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png"));
if (!pixmap.isNull()) {
QPixmap fileIcon = d->findIcon(32, QLatin1String("text-x-generic.png"));
@@ -6012,7 +5957,7 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
}
break;
case SP_DirLinkIcon: {
- icon = QIcon(standardPixmap(standardIcon, option, widget));
+ icon = QIcon(proxy()->standardPixmap(standardIcon, option, widget));
QPixmap pixmap = d->findIcon(32, QLatin1String("link_overlay.png"));
if (!pixmap.isNull()) {
QPixmap fileIcon = d->findIcon(32, QLatin1String("folder.png"));
@@ -6230,7 +6175,7 @@ QIcon QCommonStyle::standardIconImplementation(StandardPixmap standardIcon, cons
break;
#endif // QT_NO_IMAGEFORMAT_PNG
default:
- icon.addPixmap(standardPixmap(standardIcon, option, widget));
+ icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget));
break;
}
return icon;
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index 0e54af8..28dff3b 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -176,7 +176,6 @@ public:
static const int groupBoxBottomMargin = 2; // space below the groupbox
static const int groupBoxTitleMargin = 6; // space between contents and title
static const int groupBoxTopMargin = 2;
-static bool UsePixmapCache = true;
// Get size of the arrow controls in a GtkSpinButton
static int spinboxArrowSize()
@@ -675,14 +674,14 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
if (widget && widget->inherits("QComboBoxPrivateContainer")){
QStyleOption copy = *option;
copy.state |= State_Raised;
- drawPrimitive(PE_PanelMenu, &copy, painter, widget);
+ proxy()->drawPrimitive(PE_PanelMenu, &copy, painter, widget);
break;
}
// Drawing the entire itemview frame is very expensive, especially on the native X11 engine
// Instead we cheat a bit and draw a border image without the center part, hence only scaling
// thin rectangular images
const int pmSize = 64;
- const int border = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ const int border = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
const QString pmKey = QString(QLS("windowframe %0")).arg(option->state);
QPixmap pixmap;
@@ -893,8 +892,8 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
int border = (size > 9) ? (size/4) : 0; //Allow small arrows to have exact dimensions
int bsx = 0, bsy = 0;
if (option->state & State_Sunken) {
- bsx = pixelMetric(PM_ButtonShiftHorizontal);
- bsy = pixelMetric(PM_ButtonShiftVertical);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical);
}
QRect arrowRect = option->rect.adjusted(border + bsx, border + bsy, -border + bsx, -border + bsy);
GtkShadowType shadow = option->state & State_Sunken ? GTK_SHADOW_IN : GTK_SHADOW_OUT;
@@ -974,7 +973,7 @@ void QGtkStyle::drawPrimitive(PrimitiveElement element,
if (const QStyleOptionFrame *panel = qstyleoption_cast<const QStyleOptionFrame *>(option)) {
GtkWidget *gtkEntry = QGtk::gtkWidget(QLS("GtkEntry"));
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, option, painter, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, option, painter, widget);
uint resolve_mask = option->palette.resolve();
QRect textRect = option->rect.adjusted(gtkEntry->style->xthickness, gtkEntry->style->ythickness,
-gtkEntry->style->xthickness, -gtkEntry->style->ythickness);
@@ -1245,8 +1244,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
painter->save();
if (const QStyleOptionGroupBox *groupBox = qstyleoption_cast<const QStyleOptionGroupBox *>(option)) {
- QRect textRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
- QRect checkBoxRect = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
+ QRect textRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
+ QRect checkBoxRect = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxCheckBox, widget);
// Draw title
if ((groupBox->subControls & QStyle::SC_GroupBoxLabel) && !groupBox->text.isEmpty()) {
@@ -1261,7 +1260,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (!groupBox->text.isEmpty()) {
int alignment = int(groupBox->textAlignment);
- if (!styleHint(QStyle::SH_UnderlineShortcut, option, widget))
+ if (!proxy()->styleHint(QStyle::SH_UnderlineShortcut, option, widget))
alignment |= Qt::TextHideMnemonic;
QColor textColor = groupBox->textColor; // Note: custom textColor is currently ignored
int labelState = GTK_STATE_INSENSITIVE;
@@ -1286,7 +1285,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QStyleOptionButton box;
box.QStyleOption::operator=(*groupBox);
box.rect = checkBoxRect;
- drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &box, painter, widget);
}
}
@@ -1309,7 +1308,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
bool focus = isEnabled && (comboBox->state & State_HasFocus);
QColor buttonShadow = option->palette.dark().color();
GtkStateType state = gtkPainter.gtkState(option);
- int appears_as_list = !styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget);
+ int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, comboBox, widget);
QPixmap cache;
QString pixmapName;
QStyleOptionComboBox comboBoxCopy = *comboBox;
@@ -1317,9 +1316,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
bool reverse = (option->direction == Qt::RightToLeft);
QRect rect = option->rect;
- QRect arrowButtonRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxArrow, widget);
- QRect editRect = subControlRect(CC_ComboBox, &comboBoxCopy,
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, &comboBoxCopy,
SC_ComboBoxEditField, widget);
GtkShadowType shadow = (option->state & State_Sunken || option->state & State_On ) ?
@@ -1427,7 +1426,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QGtk::gtk_widget_style_get(gtkToggleButton, "interior-focus", &interiorFocus, NULL);
int xt = interiorFocus ? gtkToggleButton->style->xthickness : 0;
int yt = interiorFocus ? gtkToggleButton->style->ythickness : 0;
- if ((focus && (option->state & State_KeyboardFocusChange)))
+ if (focus && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget)))
gtkCachedPainter.paintFocus(gtkToggleButton, "button",
option->rect.adjusted(xt, yt, -xt, -yt),
option->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
@@ -1498,8 +1497,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
QRect button, menuarea;
- button = subControlRect(control, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(control, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(control, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~(State_Sunken | State_MouseOver);
if (bflags & State_AutoRaise)
@@ -1528,7 +1527,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (bflags & (State_Sunken | State_On | State_Raised | State_MouseOver)) {
tool.rect = button;
tool.state = bflags;
- drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, painter, widget);
}
}
@@ -1539,9 +1538,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (toolbutton->state & State_HasFocus) {
QStyleOptionFocusRect fr;
fr.QStyleOption::operator=(*toolbutton);
- fr.rect = subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget);
+ fr.rect = proxy()->subControlRect(CC_ToolButton, toolbutton, SC_ToolButton, widget);
fr.rect.adjust(1, 1, -1, -1);
- drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, painter, widget);
}
QStyleOptionToolButton label = *toolbutton;
@@ -1557,21 +1556,21 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
}
label.rect = button.adjusted(style->xthickness, style->ythickness,
-style->xthickness - popupArrowSize, -style->ythickness);
- drawControl(CE_ToolButtonLabel, &label, painter, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, painter, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
if ((mflags & State_Enabled && (mflags & (State_Sunken | State_Raised | State_MouseOver))) || !(mflags & State_AutoRaise))
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, painter, widget);
- drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, painter, widget);
} else if (drawMenuArrow) {
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() - popupArrowSize - style->xthickness - 3, ir.height()/2 - 1, popupArrowSize, popupArrowSize);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
}
}
break;
@@ -1588,10 +1587,10 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
painter->fillRect(option->rect, option->palette.background());
QRect rect = scrollBar->rect;
- QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
- QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
- QRect scrollBarSlider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
- QRect grooveRect = subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
+ QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
+ QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
+ QRect scrollBarSlider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
+ QRect grooveRect = proxy()->subControlRect(control, scrollBar, SC_ScrollBarGroove, widget);
bool horizontal = scrollBar->orientation == Qt::Horizontal;
GtkWidget * scrollbarWidget = horizontal ? gtkHScrollBar : gtkVScrollBar;
style = scrollbarWidget->style;
@@ -1735,7 +1734,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
bool reverse = (spinBox->direction == Qt::RightToLeft);
//### Move this to subControlRect
- QRect upRect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
+ QRect upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
upRect.setTop(option->rect.top());
if (reverse)
@@ -1743,8 +1742,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
else
upRect.setRight(option->rect.right());
- QRect editRect = subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget);
- QRect downRect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ QRect editRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxEditField, widget);
+ QRect downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
downRect.setBottom(option->rect.bottom());
if (reverse)
@@ -1776,8 +1775,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
QString key;
+
if (option->state & State_HasFocus) {
- key = QLS("f");
+ key += QLatin1Char('f');
GTK_WIDGET_SET_FLAGS(gtkSpinButton, GTK_HAS_FOCUS);
}
@@ -1875,9 +1875,9 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
GtkWidget *hScaleWidget = QGtk::gtkWidget(QLS("GtkHScale"));
GtkWidget *vScaleWidget = QGtk::gtkWidget(QLS("GtkVScale"));
- QRect groove = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
@@ -1932,8 +1932,8 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
if (option->subControls & SC_SliderTickmarks) {
painter->setPen(darkOutline);
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
@@ -1950,7 +1950,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
interval = 1;
int v = slider->minimum;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
break;
@@ -2011,7 +2011,7 @@ void QGtkStyle::drawComplexControl(ComplexControl control, const QStyleOptionCom
fropt.rect.setLeft(handle.left() - 3);
fropt.rect.setRight(handle.right() + 3);
}
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
gtkPainter.paintSlider( scaleWidget, horizontal ? "hscale" : "vscale", handle, state, shadow, style,
@@ -2101,9 +2101,9 @@ void QGtkStyle::drawControl(ControlElement element,
if (option->state & State_Sunken)
buttonShift = QPoint(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
- pixelMetric(PM_ButtonShiftVertical, option, widget));
+ proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
- if (styleHint(SH_UnderlineShortcut, button, widget))
+ if (proxy()->styleHint(SH_UnderlineShortcut, button, widget))
tf |= Qt::TextShowMnemonic;
else
tf |= Qt::TextHideMnemonic;
@@ -2164,7 +2164,7 @@ void QGtkStyle::drawControl(ControlElement element,
GdkColor gdkText = gtkButton->style->fg[labelState];
QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
pal.setBrush(QPalette::ButtonText, textColor);
- drawItemText(painter, ir, tf, pal, (button->state & State_Enabled),
+ proxy()->drawItemText(painter, ir, tf, pal, (button->state & State_Enabled),
button->text, QPalette::ButtonText);
}
break;
@@ -2185,7 +2185,7 @@ void QGtkStyle::drawControl(ControlElement element,
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, painter, widget);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, widget);
@@ -2199,14 +2199,14 @@ void QGtkStyle::drawControl(ControlElement element,
QColor textColor = QColor(gdkText.red>>8, gdkText.green>>8, gdkText.blue>>8);
pal.setBrush(QPalette::WindowText, textColor);
subopt.palette = pal;
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, painter, widget);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
break;
@@ -2215,8 +2215,8 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_ComboBoxLabel:
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- QRect editRect = subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
- bool appearsAsList = !styleHint(QStyle::SH_ComboBox_Popup, cb, widget);
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, cb, SC_ComboBoxEditField, widget);
+ bool appearsAsList = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, cb, widget);
painter->save();
painter->setClipRect(editRect);
@@ -2234,7 +2234,7 @@ void QGtkStyle::drawControl(ControlElement element,
if (cb->editable)
painter->fillRect(iconRect, option->palette.brush(QPalette::Base));
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
if (cb->direction == Qt::RightToLeft)
editRect.translate(-4 - cb->iconSize.width(), 0);
@@ -2256,7 +2256,7 @@ void QGtkStyle::drawControl(ControlElement element,
pal.setBrush(QPalette::ButtonText, textColor);
- drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
+ proxy()->drawItemText(painter, editRect.adjusted(1, 0, -1, 0),
visualAlignment(cb->direction, Qt::AlignLeft | Qt::AlignVCenter),
pal, cb->state & State_Enabled, cb->currentText, QPalette::ButtonText);
}
@@ -2302,7 +2302,7 @@ void QGtkStyle::drawControl(ControlElement element,
QString titleText
= painter->fontMetrics().elidedText(dwOpt->title,
Qt::ElideRight, titleRect.width());
- drawItemText(painter,
+ proxy()->drawItemText(painter,
titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, dwOpt->palette,
dwOpt->state & State_Enabled, titleText,
@@ -2423,10 +2423,10 @@ void QGtkStyle::drawControl(ControlElement element,
QPalette::ColorRole textRole = dis ? QPalette::Text : QPalette::HighlightedText;
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!QCleanlooksStyle::styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
- drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole);
+ proxy()->drawItemText(painter, item.rect, alignment, item.palette, mbi->state & State_Enabled, mbi->text, textRole);
}
}
painter->restore();
@@ -2598,7 +2598,7 @@ void QGtkStyle::drawControl(ControlElement element,
mode = QIcon::Active;
QPixmap pixmap;
- int smallIconSize = pixelMetric(PM_SmallIconSize, option, widget);
+ int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize, option, widget);
QSize iconSize(smallIconSize, smallIconSize);
#ifndef QT_NO_COMBOBOX
@@ -2626,7 +2626,7 @@ void QGtkStyle::drawControl(ControlElement element,
}
opt.state |= State_Sunken;
opt.rect = vCheckRect;
- drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &opt, painter, widget);
}
painter->drawPixmap(pmr.topLeft(), pixmap);
}
@@ -2666,7 +2666,7 @@ void QGtkStyle::drawControl(ControlElement element,
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
// Draw shortcut right aligned
@@ -2699,7 +2699,7 @@ void QGtkStyle::drawControl(ControlElement element,
// Arrow
if (menuItem->menuItemType == QStyleOptionMenuItem::SubMenu) {// draw sub menu arrow
QPoint buttonShift(pixelMetric(PM_ButtonShiftHorizontal, option, widget),
- pixelMetric(PM_ButtonShiftVertical, option, widget));
+ proxy()->pixelMetric(PM_ButtonShiftVertical, option, widget));
QFontMetrics fm(menuitem->font);
int arrow_size = fm.ascent() + fm.descent() - 2 * gtkMenuItem->style->ythickness;
@@ -2727,7 +2727,7 @@ void QGtkStyle::drawControl(ControlElement element,
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(option)) {
GtkWidget *gtkButton = QGtk::gtkWidget(QLS("GtkButton"));
- drawControl(CE_PushButtonBevel, btn, painter, widget);
+ proxy()->drawControl(CE_PushButtonBevel, btn, painter, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
gint interiorFocus = true;
@@ -2737,14 +2737,14 @@ void QGtkStyle::drawControl(ControlElement element,
if (btn->features & QStyleOptionButton::Flat && btn->state & State_HasFocus)
// The normal button focus rect does not work well for flat buttons in Clearlooks
- drawPrimitive(PE_FrameFocusRect, option, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, option, painter, widget);
else if (btn->state & State_HasFocus)
gtkPainter.paintFocus(gtkButton, "button",
option->rect.adjusted(xt, yt, -xt, -yt),
btn->state & State_Sunken ? GTK_STATE_ACTIVE : GTK_STATE_NORMAL,
gtkButton->style);
- drawControl(CE_PushButtonLabel, &subopt, painter, widget);
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, painter, widget);
}
break;
@@ -2962,8 +2962,8 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
font.setBold(true);
QFontMetrics fontMetrics(font);
QSize textRect = fontMetrics.boundingRect(groupBoxWidget->title()).size() + QSize(4, 4);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, option, widget);
- int indicatorHeight = pixelMetric(PM_IndicatorHeight, option, widget);
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, option, widget);
+ int indicatorHeight = proxy()->pixelMetric(PM_IndicatorHeight, option, widget);
if (subControl == SC_GroupBoxCheckBox) {
rect.setWidth(indicatorWidth);
@@ -3044,7 +3044,7 @@ QRect QGtkStyle::subControlRect(ComplexControl control, const QStyleOptionComple
QGtk::gtk_widget_set_direction(gtkCombo, (option->direction == Qt::RightToLeft) ? GTK_TEXT_DIR_RTL : GTK_TEXT_DIR_LTR);
GtkAllocation geometry = {0, 0, qMax(0, option->rect.width()), qMax(0, option->rect.height())};
QGtk::gtk_widget_size_allocate(gtkCombo, &geometry);
- int appears_as_list = !styleHint(QStyle::SH_ComboBox_Popup, option, widget);
+ int appears_as_list = !proxy()->styleHint(QStyle::SH_ComboBox_Popup, option, widget);
QString arrowPath = comboBoxPath + QLS(".GtkToggleButton");
if (!box->editable && !appears_as_list)
@@ -3208,7 +3208,7 @@ QSize QGtkStyle::sizeFromContents(ContentsType type, const QStyleOption *option,
case CT_ComboBox:
if (const QStyleOptionComboBox *combo = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
GtkWidget *gtkCombo = QGtk::gtkWidget(QLS("GtkComboBox"));
- QRect arrowButtonRect = subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget);
+ QRect arrowButtonRect = proxy()->subControlRect(CC_ComboBox, combo, SC_ComboBoxArrow, widget);
newSize = size + QSize(12 + arrowButtonRect.width() + 2*gtkCombo->style->xthickness, 4 + 2*gtkCombo->style->ythickness);
if (!(widget && qobject_cast<QToolBar *>(widget->parentWidget())))
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index 1be3d6e..ec75138 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -55,6 +55,7 @@
#include <private/qpaintengine_mac_p.h>
#include <private/qpainter_p.h>
#include <private/qprintengine_mac_p.h>
+#include <private/qstylehelper_p.h>
#include <qapplication.h>
#include <qbitmap.h>
#include <qcheckbox.h>
@@ -130,6 +131,20 @@ static const QColor titlebarSeparatorLineInactive(131, 131, 131);
static const QColor mainWindowGradientBegin(240, 240, 240);
static const QColor mainWindowGradientEnd(200, 200, 200);
+#if (MAC_OS_X_VERSION_MAX_ALLOWED <= MAC_OS_X_VERSION_10_5)
+enum {
+ kThemePushButtonTextured = 31,
+ kThemePushButtonTexturedSmall = 32,
+ kThemePushButtonTexturedMini = 33
+};
+
+/* Search fields */
+enum {
+ kHIThemeFrameTextFieldRound = 1000,
+ kHIThemeFrameTextFieldRoundSmall = 1001,
+ kHIThemeFrameTextFieldRoundMini = 1002
+};
+#endif
// Resolve these at run-time, since the functions was moved in Leopard.
typedef HIRect * (*PtrHIShapeGetBounds)(HIShapeRef, HIRect *);
@@ -836,7 +851,7 @@ static QSize qt_aqua_get_known_size(QStyle::ContentsType ct, const QWidget *widg
}
break;
case QStyle::CT_HeaderSection:
- if (sz == QAquaSizeLarge && isTreeView(widg))
+ if (isTreeView(widg))
ret = QSize(-1, qt_mac_aqua_get_metric(kThemeMetricListHeaderHeight));
break;
case QStyle::CT_MenuBar:
@@ -1036,7 +1051,7 @@ QSize QMacStylePrivate::pushButtonSizeFromContents(const QStyleOptionButton *btn
: btn->fontMetrics.boundingRect(QRect(), Qt::AlignCenter, btn->text);
csz.setWidth(iconSize.width() + textRect.width()
+ ((btn->features & QStyleOptionButton::HasMenu)
- ? q->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0));
+ ? q->proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, 0) : 0));
csz.setHeight(qMax(iconSize.height(), textRect.height()));
return csz;
}
@@ -2207,7 +2222,7 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
ret = closeButtonSize;
break;
case PM_ToolBarIconSize:
- ret = pixelMetric(PM_LargeIconSize);
+ ret = proxy()->pixelMetric(PM_LargeIconSize);
break;
case PM_FocusFrameVMargin:
case PM_FocusFrameHMargin:
@@ -2567,6 +2582,9 @@ int QMacStyle::pixelMetric(PixelMetric metric, const QStyleOption *opt, const QW
case PM_MenuHMargin:
ret = 0;
break;
+ case PM_ToolBarFrameWidth:
+ ret = 0;
+ break;
default:
ret = QWindowsStyle::pixelMetric(metric, opt, widget);
break;
@@ -2728,7 +2746,7 @@ int QMacStyle::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w
QPixmap pix(pixmapSize);
pix.fill(QColor(fillR, fillG, fillB));
QPainter pix_paint(&pix);
- drawControl(CE_FocusFrame, opt, &pix_paint, w);
+ proxy()->drawControl(CE_FocusFrame, opt, &pix_paint, w);
pix_paint.end();
img = pix.toImage();
}
@@ -3043,7 +3061,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
twf.rect = twf.rect.adjusted(0, -10, 0, 0);
break;
}
- drawPrimitive(PE_FrameTabWidget, &twf, p, w);
+ proxy()->drawPrimitive(PE_FrameTabWidget, &twf, p, w);
p->restore();
}
break;
@@ -3141,7 +3159,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
// In HITheme, up is down, down is up and hamburgers eat people.
if (header->sortIndicator != QStyleOptionHeader::None)
- drawPrimitive(
+ proxy()->drawPrimitive(
(header->sortIndicator == QStyleOptionHeader::SortDown) ?
PE_IndicatorArrowUp : PE_IndicatorArrowDown, header, p, w);
}
@@ -3275,7 +3293,7 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
fdi.isFocused = (frame->state & State_HasFocus);
int lw = frame->lineWidth;
if (lw <= 0)
- lw = pixelMetric(PM_DefaultFrameWidth, frame, w);
+ lw = proxy()->pixelMetric(PM_DefaultFrameWidth, frame, w);
{ //clear to base color
p->save();
p->setPen(QPen(baseColor, lw));
@@ -3488,16 +3506,16 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QIcon::Mode mode = QIcon::Disabled;
if (opt->state & State_Enabled)
mode = QIcon::Normal;
- QPixmap pixmap = header->icon.pixmap(pixelMetric(PM_SmallIconSize), mode);
+ QPixmap pixmap = header->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), mode);
QRect pixr = header->rect;
pixr.setY(header->rect.center().y() - (pixmap.height() - 1) / 2);
- drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap);
+ proxy()->drawItemPixmap(p, pixr, Qt::AlignVCenter, pixmap);
textr.translate(pixmap.width() + 2, 0);
}
- drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette,
- header->state & State_Enabled, header->text, QPalette::ButtonText);
+ proxy()->drawItemText(p, textr, header->textAlignment | Qt::AlignVCenter, header->palette,
+ header->state & State_Enabled, header->text, QPalette::ButtonText);
}
break;
case CE_ToolButtonLabel:
@@ -3508,59 +3526,87 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QRect cr = tb->rect;
int shiftX = 0;
int shiftY = 0;
- if (tb->state & (State_Sunken | State_On)) {
- shiftX = pixelMetric(PM_ButtonShiftHorizontal, tb, w);
- shiftY = pixelMetric(PM_ButtonShiftVertical, tb, w);
+ bool needText = false;
+ int alignment = 0;
+ bool down = tb->state & (State_Sunken | State_On);
+ if (down) {
+ shiftX = proxy()->pixelMetric(PM_ButtonShiftHorizontal, tb, w);
+ shiftY = proxy()->pixelMetric(PM_ButtonShiftVertical, tb, w);
}
// The down state is special for QToolButtons in a toolbar on the Mac
// The text is a bit bolder and gets a drop shadow and the icons are also darkened.
// This doesn't really fit into any particular case in QIcon, so we
// do the majority of the work ourselves.
- if (tb->state & State_Sunken
- && !(tb->features & QStyleOptionToolButton::Arrow)) {
+ if (!(tb->features & QStyleOptionToolButton::Arrow)) {
Qt::ToolButtonStyle tbstyle = tb->toolButtonStyle;
if (tb->icon.isNull() && !tb->text.isEmpty())
tbstyle = Qt::ToolButtonTextOnly;
switch (tbstyle) {
- case Qt::ToolButtonTextOnly:
- drawItemText(p, cr, Qt::AlignCenter, tb->palette,
- tb->state & State_Enabled, tb->text);
- break;
+ case Qt::ToolButtonTextOnly: {
+ needText = true;
+ alignment = Qt::AlignCenter;
+ break; }
case Qt::ToolButtonIconOnly:
case Qt::ToolButtonTextBesideIcon:
case Qt::ToolButtonTextUnderIcon: {
QRect pr = cr;
QIcon::Mode iconMode = (tb->state & State_Enabled) ? QIcon::Normal
- : QIcon::Disabled;
+ : QIcon::Disabled;
QIcon::State iconState = (tb->state & State_On) ? QIcon::On
- : QIcon::Off;
+ : QIcon::Off;
QPixmap pixmap = tb->icon.pixmap(tb->rect.size().boundedTo(tb->iconSize), iconMode, iconState);
// Draw the text if it's needed.
if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
- int alignment = 0;
+ needText = true;
if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
- pr.setHeight(pixmap.size().height() + 6);
- cr.adjust(0, pr.bottom(), 0, -3);
+ pr.setHeight(pixmap.size().height());
+ cr.adjust(0, pr.bottom() + 1, 0, 1);
alignment |= Qt::AlignCenter;
} else {
pr.setWidth(pixmap.width() + 8);
cr.adjust(pr.right(), 0, 0, 0);
alignment |= Qt::AlignLeft | Qt::AlignVCenter;
}
- cr.translate(shiftX, shiftY);
- drawItemText(p, cr, alignment, tb->palette,
- tb->state & State_Enabled, tb->text);
- cr.adjust(0, 3, 0, -3); // the drop shadow
- drawItemText(p, cr, alignment, tb->palette,
- tb->state & State_Enabled, tb->text);
}
- pr.translate(shiftX, shiftY);
- pixmap = darkenPixmap(pixmap);
- drawItemPixmap(p, pr, Qt::AlignCenter, pixmap);
+ if (opt->state & State_Sunken) {
+ pr.translate(shiftX, shiftY);
+ pixmap = darkenPixmap(pixmap);
+ }
+ proxy()->drawItemPixmap(p, pr, Qt::AlignCenter, pixmap);
break; }
}
+
+ if (needText) {
+ QPalette pal = tb->palette;
+ QPalette::ColorRole role = QPalette::NoRole;
+ if (down)
+ cr.translate(shiftX, shiftY);
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5
+ && (tbstyle == Qt::ToolButtonTextOnly
+ || (tbstyle != Qt::ToolButtonTextOnly && !down))) {
+ QPen pen = p->pen();
+ QColor light = down ? Qt::black : Qt::white;
+ light.setAlphaF(0.375f);
+ p->setPen(light);
+ p->drawText(cr.adjusted(0, 1, 0, 1), alignment, tb->text);
+ p->setPen(pen);
+ if (down && tbstyle == Qt::ToolButtonTextOnly) {
+ pal = QApplication::palette("QMenu");
+ pal.setCurrentColorGroup(tb->palette.currentColorGroup());
+ role = QPalette::HighlightedText;
+ }
+ }
+ drawItemText(p, cr, alignment, pal,
+ tb->state & State_Enabled, tb->text, role);
+ if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_5 &&
+ (tb->state & State_Sunken)) {
+ // Draw a "drop shadow" in earlier versions.
+ drawItemText(p, cr.adjusted(0, 1, 0, 1), alignment,
+ tb->palette, tb->state & State_Enabled, tb->text);
+ }
+ }
} else {
QWindowsStyle::drawControl(ce, &myTb, p, w);
}
@@ -3609,7 +3655,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
if (btn->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
+ int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
QRect ir = btn->rect;
HIRect arrowRect = CGRectMake(ir.right() - mbi - PushButtonRightOffset,
ir.height() / 2 - 4, mbi, ir.height() / 2);
@@ -3696,7 +3742,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (hasIcon) {
int contentW = textRect.width();
if (hasMenu)
- contentW += pixelMetric(PM_MenuButtonIndicator) + 4;
+ contentW += proxy()->pixelMetric(PM_MenuButtonIndicator) + 4;
QIcon::Mode mode = btn->state & State_Enabled ? QIcon::Normal : QIcon::Disabled;
if (mode == QIcon::Normal && btn->state & State_HasFocus)
mode = QIcon::Active;
@@ -3710,7 +3756,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
int iconTopOffset = freeContentRect.y() + (freeContentRect.height() - pixmap.height()) / 2;
QRect iconDestRect(iconLeftOffset, iconTopOffset, pixmap.width(), pixmap.height());
QRect visualIconDestRect = visualRect(btn->direction, freeContentRect, iconDestRect);
- drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
+ proxy()->drawItemPixmap(p, visualIconDestRect, Qt::AlignLeft | Qt::AlignVCenter, pixmap);
int newOffset = iconDestRect.x() + iconDestRect.width()
+ PushButtonContentPadding - textRect.x();
textRect.adjust(newOffset, 0, newOffset, 0);
@@ -3718,8 +3764,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
// Draw the text:
if (hasText) {
textRect = visualRect(btn->direction, freeContentRect, textRect);
- drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette,
- (btn->state & State_Enabled), btn->text, QPalette::ButtonText);
+ proxy()->drawItemText(p, textRect, Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, btn->palette,
+ (btn->state & State_Enabled), btn->text, QPalette::ButtonText);
}
}
}
@@ -3876,7 +3922,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QRect nr = subElementRect(SE_TabBarTabText, opt, w);
nr.moveTop(+1);
int alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextHideMnemonic;
- drawItemText(p, nr, alignment, np, tab->state & State_Enabled, tab->text, QPalette::WindowText);
+ proxy()->drawItemText(p, nr, alignment, np, tab->state & State_Enabled,
+ tab->text, QPalette::WindowText);
p->restore();
}
@@ -3999,8 +4046,8 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
}
break;
case CE_FocusFrame: {
- int xOff = pixelMetric(PM_FocusFrameHMargin, opt, w) + 1;
- int yOff = pixelMetric(PM_FocusFrameVMargin, opt, w) + 1;
+ int xOff = proxy()->pixelMetric(PM_FocusFrameHMargin, opt, w) + 1;
+ int yOff = proxy()->pixelMetric(PM_FocusFrameVMargin, opt, w) + 1;
HIRect hirect = CGRectMake(xOff+opt->rect.x(), yOff+opt->rect.y(), opt->rect.width() - 2 * xOff,
opt->rect.height() - 2 * yOff);
HIThemeDrawFocusRect(&hirect, true, QMacCGContext(p), kHIThemeOrientationNormal);
@@ -4123,7 +4170,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
QIcon::Mode mode = (mi->state & State_Enabled) ? QIcon::Normal
: QIcon::Disabled;
// Always be normal or disabled to follow the Mac style.
- int smallIconSize = pixelMetric(PM_SmallIconSize);
+ int smallIconSize = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize(smallIconSize, smallIconSize);
if (const QComboBox *comboBox = qobject_cast<const QComboBox *>(w)) {
iconSize = comboBox->iconSize();
@@ -4233,7 +4280,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
drawItemPixmap(p, mi->rect,
Qt::AlignCenter | Qt::TextHideMnemonic | Qt::TextDontClip
| Qt::TextSingleLine,
- mi->icon.pixmap(pixelMetric(PM_SmallIconSize),
+ mi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize),
(mi->state & State_Enabled) ? QIcon::Normal : QIcon::Disabled));
} else {
drawItemText(p, mi->rect,
@@ -4293,7 +4340,19 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
tdi.enableState = kThemeTrackDisabled;
else
tdi.enableState = kThemeTrackActive;
- HIThemeDrawTrack(&tdi, 0, cg, kHIThemeOrientationNormal);
+ HIThemeOrientation drawOrientation = kHIThemeOrientationNormal;
+ if (reverse) {
+ if (vertical) {
+ drawOrientation = kHIThemeOrientationInverted;
+ } else {
+ CGContextSaveGState(cg);
+ CGContextTranslateCTM(cg, pb->rect.width(), 0);
+ CGContextScaleCTM(cg, -1, 1);
+ }
+ }
+ HIThemeDrawTrack(&tdi, 0, cg, drawOrientation);
+ if (reverse && !vertical)
+ CGContextRestoreGState(cg);
}
break;
case CE_ProgressBarLabel:
@@ -4381,9 +4440,10 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
case CE_ToolBar: {
// For unified tool bars, draw nothing.
if (w) {
- if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window()))
+ if (QMainWindow * mainWindow = qobject_cast<QMainWindow *>(w->window())) {
if (mainWindow->unifiedTitleAndToolBarOnMac())
break;
+ }
}
// draw background gradient
@@ -4857,7 +4917,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
treeOpt.state |= State_Children;
if (item.state & State_Open)
treeOpt.state |= State_Open;
- drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorBranch, &treeOpt, p, widget);
}
y += item.totalHeight;
}
@@ -4871,7 +4931,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
SInt32 frame_size;
GetThemeMetric(kThemeMetricEditTextFrameOutset, &frame_size);
- QRect lineeditRect = subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
+ QRect lineeditRect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxEditField, widget);
lineeditRect.adjust(-frame_size, -frame_size, +frame_size, +frame_size);
HIThemeFrameDrawInfo fdi;
@@ -4915,9 +4975,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
bdi.value = kThemeButtonOff;
bdi.adornment = kThemeAdornmentNone;
- QRect updown = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
+ QRect updown = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
- updown |= subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+ updown |= proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
HIRect newRect = qt_hirectForQRect(updown);
QRect off_rct;
HIRect outRect;
@@ -5030,7 +5090,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
&titleRegion2);
ptrHIShapeGetBounds(titleRegion2, &tmpRect);
if (tmpRect.size.width != 1) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
iw = titlebar->icon.actualSize(QSize(iconExtent, iconExtent)).width();
}
}
@@ -5048,7 +5108,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
else
x += br.width() / 2 - p->fontMetrics().width(titlebar->text) / 2;
if (iw)
- p->drawPixmap(x - iw, y, titlebar->icon.pixmap(pixelMetric(PM_SmallIconSize), QIcon::Normal));
+ p->drawPixmap(x - iw, y,
+ titlebar->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize), QIcon::Normal));
drawItemText(p, br, Qt::AlignCenter, opt->palette, tds == kThemeStateActive,
titlebar->text, QPalette::Text);
p->restore();
@@ -5085,7 +5146,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
tti.truncationPosition = kHIThemeTextTruncationNone;
tti.truncationMaxLines = 1 + groupBox->text.count(QLatin1Char('\n'));
QCFString groupText = qt_mac_removeMnemonics(groupBox->text);
- QRect r = subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
+ QRect r = proxy()->subControlRect(CC_GroupBox, groupBox, SC_GroupBoxLabel, widget);
HIRect bounds = qt_hirectForQRect(r);
HIThemeDrawTextBox(groupText, &bounds, &tti, cg, kHIThemeOrientationNormal);
p->restore();
@@ -5098,29 +5159,35 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
if (widget && qobject_cast<QToolBar *>(widget->parentWidget())) {
if (tb->subControls & SC_ToolButtonMenu) {
QStyleOption arrowOpt(0);
- arrowOpt.rect = subControlRect(cc, tb, SC_ToolButtonMenu, widget);
+ arrowOpt.rect = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
arrowOpt.rect.setY(arrowOpt.rect.y() + arrowOpt.rect.height() / 2);
arrowOpt.rect.setHeight(arrowOpt.rect.height() / 2);
arrowOpt.state = tb->state;
arrowOpt.palette = tb->palette;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
} else if ((tb->features & QStyleOptionToolButton::HasMenu)
&& (tb->toolButtonStyle != Qt::ToolButtonTextOnly && !tb->icon.isNull())) {
drawToolbarButtonArrow(tb->rect, tds, cg);
}
if (tb->state & State_On) {
- QPen oldPen = p->pen();
- p->setPen(QColor(0, 0, 0, 0x3a));
- p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12));
- p->drawLine(tb->rect.left() + 1, tb->rect.top(),
- tb->rect.right() - 1, tb->rect.top());
- p->drawLine(tb->rect.left() + 1, tb->rect.bottom(),
- tb->rect.right() - 1, tb->rect.bottom());
- p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft());
- p->drawLine(tb->rect.topRight(), tb->rect.bottomRight());
- p->setPen(oldPen);
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5) {
+ static QPixmap pm(QLatin1String(":/trolltech/mac/style/images/leopard-unified-toolbar-on.png"));
+ p->setRenderHint(QPainter::SmoothPixmapTransform);
+ QStyleHelper::drawBorderPixmap(pm, p, tb->rect, 2, 2, 2, 2);
+ } else {
+ QPen oldPen = p->pen();
+ p->setPen(QColor(0, 0, 0, 0x3a));
+ p->fillRect(tb->rect.adjusted(1, 1, -1, -1), QColor(0, 0, 0, 0x12));
+ p->drawLine(tb->rect.left() + 1, tb->rect.top(),
+ tb->rect.right() - 1, tb->rect.top());
+ p->drawLine(tb->rect.left() + 1, tb->rect.bottom(),
+ tb->rect.right() - 1, tb->rect.bottom());
+ p->drawLine(tb->rect.topLeft(), tb->rect.bottomLeft());
+ p->drawLine(tb->rect.topRight(), tb->rect.bottomRight());
+ p->setPen(oldPen);
+ }
}
- drawControl(CE_ToolButtonLabel, opt, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, opt, p, widget);
} else {
ThemeButtonKind bkind = kThemeBevelButton;
switch (d->aquaSizeConstrain(opt, widget)) {
@@ -5141,8 +5208,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
QRect button, menuarea;
- button = subControlRect(cc, tb, SC_ToolButton, widget);
- menuarea = subControlRect(cc, tb, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, tb, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, tb, SC_ToolButtonMenu, widget);
State bflags = tb->state,
mflags = tb->state;
if (tb->subControls & SC_ToolButton)
@@ -5205,14 +5272,18 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
} else if (tb->features & QStyleOptionToolButton::HasMenu) {
drawToolbarButtonArrow(tb->rect, tds, cg);
}
- QRect buttonRect = subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ QRect buttonRect = proxy()->subControlRect(CC_ToolButton, tb, SC_ToolButton, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
QStyleOptionToolButton label = *tb;
label.rect = buttonRect.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
}
}
break;
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(opt))
+ QStyleHelper::drawDial(dial, p);
+ break;
default:
QWindowsStyle::drawComplexControl(cc, opt, p, widget);
break;
@@ -5436,7 +5507,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
else if (sc == SC_TitleBarLabel)
wrc = kWindowTitleTextRgn;
else if (sc == SC_TitleBarSysMenu)
- ret.setRect(-1024, -1024, 10, pixelMetric(PM_TitleBarHeight,
+ ret.setRect(-1024, -1024, 10, proxy()->pixelMetric(PM_TitleBarHeight,
titlebar, widget));
if (wrc != kWindowGlobalPortRgn) {
QCFType<HIShapeRef> region;
@@ -5533,7 +5604,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
QRect labelRect = alignedRect(groupBox->direction, groupBox->textAlignment,
QSize(tw, h), ret);
- int indicatorWidth = pixelMetric(PM_IndicatorWidth, opt, widget);
+ int indicatorWidth = proxy()->pixelMetric(PM_IndicatorWidth, opt, widget);
bool rtl = groupBox->direction == Qt::RightToLeft;
if (sc == SC_GroupBoxLabel) {
if (checkable) {
@@ -5555,7 +5626,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
if (sc == SC_GroupBoxCheckBox) {
int left = rtl ? labelRect.right() - indicatorWidth : labelRect.left();
ret.setRect(left, ret.top(),
- indicatorWidth, pixelMetric(PM_IndicatorHeight, opt, widget));
+ indicatorWidth, proxy()->pixelMetric(PM_IndicatorHeight, opt, widget));
}
break;
}
@@ -5593,7 +5664,7 @@ QRect QMacStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *op
QAquaWidgetSize aquaSize = d->aquaSizeConstrain(spin, widget);
int spinner_w;
int spinBoxSep;
- int fw = pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
+ int fw = proxy()->pixelMetric(PM_SpinBoxFrameWidth, spin, widget);
switch (aquaSize) {
default:
case QAquaSizeUnknown:
@@ -5715,7 +5786,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
sz.transpose();
if (newStyleTabs) {
int defaultTabHeight;
- int defaultExtraSpace = pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK)
+ int defaultExtraSpace = proxy()->pixelMetric(PM_TabBarTabHSpace, tab, widget); // Remove spurious gcc warning (AFAIK)
QFontMetrics fm = opt->fontMetrics;
switch (AquaSize) {
case QAquaSizeUnknown:
@@ -5822,7 +5893,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
h = qMax(h, iconSize.height() + 4);
maxpmw = qMax(maxpmw, iconSize.width());
} else {
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
h = qMax(h, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height() + 4);
}
}
@@ -5851,6 +5922,14 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
}
break;
case CT_ToolButton:
+ if (widget && qobject_cast<const QToolBar *>(widget->parentWidget())) {
+ sz.rwidth() += 4;
+ if (sz.height() <= 32) {
+ // Workaround strange HIToolBar bug when getting constraints.
+ sz.rheight() += 1;
+ }
+ return sz;
+ }
sz.rwidth() += 10;
sz.rheight() += 10;
return sz;
@@ -5861,7 +5940,7 @@ QSize QMacStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
QStyleHintReturnMask menuMask;
QStyleOption myOption = *opt;
myOption.rect.setSize(sz);
- if (styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) {
+ if (proxy()->styleHint(SH_Menu_Mask, &myOption, widget, &menuMask)) {
sz = menuMask.region.boundingRect().size();
}
break; }
diff --git a/src/gui/styles/qmotifstyle.cpp b/src/gui/styles/qmotifstyle.cpp
index d19750f..95f69b9 100644
--- a/src/gui/styles/qmotifstyle.cpp
+++ b/src/gui/styles/qmotifstyle.cpp
@@ -386,7 +386,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
case PE_FrameTabWidget:
case PE_FrameWindow:
- qDrawShadePanel(p, opt->rect, opt->palette, QStyle::State_None, pixelMetric(PM_DefaultFrameWidth));
+ qDrawShadePanel(p, opt->rect, opt->palette, QStyle::State_None, proxy()->pixelMetric(PM_DefaultFrameWidth));
break;
case PE_FrameFocusRect:
if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
@@ -475,7 +475,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
fill = opt->palette.brush(QPalette::Button);
if ((opt->state & State_Enabled || opt->state & State_On) || !(opt->state & State_AutoRaise))
qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken | State_On)),
- pixelMetric(PM_DefaultFrameWidth), &fill);
+ proxy()->pixelMetric(PM_DefaultFrameWidth), &fill);
break; }
case PE_IndicatorCheckBox: {
@@ -490,9 +490,9 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
opt->rect.x(), opt->rect.y() + opt->rect.height() - 1);
} else {
qDrawShadePanel(p, opt->rect, opt->palette, !showUp,
- pixelMetric(PM_DefaultFrameWidth), &fill);
+ proxy()->pixelMetric(PM_DefaultFrameWidth), &fill);
}
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
break; }
@@ -545,7 +545,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
a.setPoints(INTARRLEN(bottom_pts), bottom_pts);
a.translate(opt->rect.x(), opt->rect.y());
p->drawPolyline(a);
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
p->setPen(oldPen);
p->setBrush(oldBrush);
@@ -736,13 +736,13 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
#undef CLEFT
#undef CTOP
#undef CBOT
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
break; }
case PE_IndicatorDockWidgetResizeHandle: {
const int motifOffset = 10;
- int sw = pixelMetric(PM_SplitterWidth);
+ int sw = proxy()->pixelMetric(PM_SplitterWidth);
if (opt->state & State_Horizontal) {
int yPos = opt->rect.y() + opt->rect.height() / 2;
int kPos = opt->rect.right() - motifOffset - sw;
@@ -769,7 +769,7 @@ void QMotifStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QP
const int markH = 6;
int posX = opt->rect.x() + (opt->rect.width() - markW) / 2 - 1;
int posY = opt->rect.y() + (opt->rect.height() - markH) / 2;
- int dfw = pixelMetric(PM_DefaultFrameWidth);
+ int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth);
if (dfw < 2) {
// Could do with some optimizing/caching...
@@ -843,7 +843,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
handleOpt.state &= ~State_Horizontal;
else
handleOpt.state |= State_Horizontal;
- drawPrimitive(PE_IndicatorDockWidgetResizeHandle, &handleOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorDockWidgetResizeHandle, &handleOpt, p, widget);
break; }
case CE_ScrollBarSubLine:
@@ -855,9 +855,9 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
pe = (opt->state & State_Horizontal) ? (opt->direction == Qt::LeftToRight ? PE_IndicatorArrowLeft : PE_IndicatorArrowRight) : PE_IndicatorArrowUp;
QStyleOption arrowOpt = *opt;
arrowOpt.state |= State_Enabled;
- drawPrimitive(pe, &arrowOpt, p, widget);
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText)) {
- int fw = pixelMetric(PM_DefaultFrameWidth);
+ proxy()->drawPrimitive(pe, &arrowOpt, p, widget);
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText)) {
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth);
p->fillRect(opt->rect.adjusted(fw, fw, -fw, -fw), QBrush(p->background().color(), Qt::Dense5Pattern));
}
}break;
@@ -873,9 +873,9 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
bevelOpt.state &= ~(State_Sunken | State_On);
p->save();
p->setBrushOrigin(bevelOpt.rect.topLeft());
- drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
p->restore();
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(opt->rect, QBrush(p->background().color(), Qt::Dense5Pattern));
break; }
@@ -886,31 +886,31 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(isRadio ? SE_RadioButtonIndicator
: SE_CheckBoxIndicator, btn, widget);
- drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
+ proxy()->drawPrimitive(isRadio ? PE_IndicatorRadioButton : PE_IndicatorCheckBox,
&subopt, p, widget);
subopt.rect = subElementRect(isRadio ? SE_RadioButtonContents
: SE_CheckBoxContents, btn, widget);
- drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
+ proxy()->drawControl(isRadio ? CE_RadioButtonLabel : CE_CheckBoxLabel, &subopt, p, widget);
if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(isRadio ? SE_RadioButtonFocusRect
: SE_CheckBoxFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
case CE_PushButton:
if (const QStyleOptionButton *btn = qstyleoption_cast<const QStyleOptionButton *>(opt)) {
- drawControl(CE_PushButtonBevel, btn, p, widget);
+ proxy()->drawControl(CE_PushButtonBevel, btn, p, widget);
QStyleOptionButton subopt = *btn;
subopt.rect = subElementRect(SE_PushButtonContents, btn, widget);
- drawControl(CE_PushButtonLabel, &subopt, p, widget);
+ proxy()->drawControl(CE_PushButtonLabel, &subopt, p, widget);
if ((btn->state & State_HasFocus) && (!focus || !focus->isVisible())) {
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*btn);
fropt.rect = subElementRect(SE_PushButtonFocusRect, btn, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
@@ -919,7 +919,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
int diw, x1, y1, x2, y2;
p->setPen(opt->palette.foreground().color());
p->setBrush(QBrush(opt->palette.button().color(), Qt::NoBrush));
- diw = pixelMetric(PM_ButtonDefaultIndicator);
+ diw = proxy()->pixelMetric(PM_ButtonDefaultIndicator);
opt->rect.getCoords(&x1, &y1, &x2, &y2);
if (btn->features & (QStyleOptionButton::AutoDefaultButton|QStyleOptionButton::DefaultButton)) {
x1 += diw;
@@ -948,14 +948,14 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
QStyleOptionButton newOpt = *btn;
newOpt.rect = QRect(x1, y1, x2 - x1 + 1, y2 - y1 + 1);
p->setBrushOrigin(p->brushOrigin());
- drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &newOpt, p, widget);
}
if (btn->features & QStyleOptionButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, btn, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, btn, widget);
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbi - 3, ir.y() + 4, mbi, ir.height() - 8);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
break;
}
@@ -963,7 +963,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
#ifndef QT_NO_TABBAR
case CE_TabBarTabShape:
if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) {
- const int default_frame = pixelMetric(PM_DefaultFrameWidth, tab, widget);
+ const int default_frame = proxy()->pixelMetric(PM_DefaultFrameWidth, tab, widget);
const int frame_offset = (default_frame > 1) ? 1 : 0;
if (tab->shape == QTabBar::RoundedNorth || tab->shape == QTabBar::RoundedEast ||
@@ -1081,7 +1081,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
}
p->setTransform(m, true);
}
- const int unit_width = pixelMetric(PM_ProgressBarChunkWidth, opt, widget);
+ const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, widget);
int u = rect.width() / unit_width;
int p_v = pb->progress - pb->minimum;
int t_s = qMax(0, pb->maximum - pb->minimum);
@@ -1150,7 +1150,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
QFont oldFont = p->font();
p->setFont(menuitem->font);
p->fillRect(x, y, w, h, opt->palette.brush(QPalette::Button));
- drawItemText(p, menuitem->rect.adjusted(10, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(p, menuitem->rect.adjusted(10, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuitem->palette, menuitem->state & State_Enabled, menuitem->text,
QPalette::Text);
textWidth = menuitem->fontMetrics.width(menuitem->text) + 10;
@@ -1220,10 +1220,10 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
}
if (menuitem->checkType & QStyleOptionMenuItem::Exclusive) {
newMenuItem.rect.setRect(xvis + 2, y + motifItemFrame + mh / 4, 11, 11);
- drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorRadioButton, &newMenuItem, p, widget);
} else {
newMenuItem.rect.setRect(xvis + 5, y + motifItemFrame + mh / 4, 9, 9);
- drawPrimitive(PE_IndicatorCheckBox, &newMenuItem, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &newMenuItem, p, widget);
}
}
@@ -1258,14 +1258,14 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
int xv = vr.x();
QRect tr(xv, y+m, menuitem->tabWidth, h-2*m);
p->drawText(tr, text_flags, s.mid(t+1));
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern));
s = s.left(t);
}
QRect tr(xvis, y+m, w - xm - menuitem->tabWidth + 1, h-2*m);
p->drawText(tr, text_flags, s.left(t));
p->setFont(oldFont);
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(tr, QBrush(p->background().color(), Qt::Dense5Pattern));
}
if (menuitem->menuItemType == QStyleOptionMenuItem::SubMenu) { // draw sub menu arrow
@@ -1279,7 +1279,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
arrowOpt.state = (State_Sunken | ((opt->state & State_Enabled) ? State_Enabled : State_None));
else
arrowOpt.state = ((opt->state & State_Enabled) ? State_Enabled : State_None);
- drawPrimitive(arrow, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, p, widget);
}
break; }
@@ -1296,7 +1296,7 @@ void QMotifStyle::drawControl(ControlElement element, const QStyleOption *opt, Q
p->save();
p->setBrushOrigin(opt->rect.topLeft());
qDrawShadePanel(p, opt->rect, opt->palette, bool(opt->state & (State_Sunken|State_On)),
- pixelMetric(PM_DefaultFrameWidth),
+ proxy()->pixelMetric(PM_DefaultFrameWidth),
&opt->palette.brush((opt->state & State_Sunken) ? QPalette::Mid : QPalette::Button));
p->restore();
break;
@@ -1431,8 +1431,8 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QRect button, menuarea;
- button = subControlRect(cc, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
if (bflags & State_AutoRaise) {
@@ -1453,7 +1453,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
if (bflags & (State_Sunken | State_On | State_Raised)) {
tool.rect = button;
tool.state = bflags;
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
}
@@ -1461,26 +1461,26 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
QStyleOptionFocusRect fr;
fr.QStyleOption::operator=(*toolbutton);
fr.rect = toolbutton->rect.adjusted(3, 3, -3, -3);
- drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
if (mflags & (State_Sunken | State_On | State_Raised))
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
- drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 5 - mbi, ir.height() - mbi + 4, mbi - 6, mbi - 6);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -1491,18 +1491,18 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
PrimitiveElement pe;
if (spinbox->frame && (spinbox->subControls & SC_SpinBoxFrame)) {
- QRect r = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget);
- qDrawShadePanel(p, r, opt->palette, false, pixelMetric(PM_SpinBoxFrameWidth));
+ QRect r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxFrame, widget);
+ qDrawShadePanel(p, r, opt->palette, false, proxy()->pixelMetric(PM_SpinBoxFrameWidth));
- int fw = pixelMetric(QStyle::PM_DefaultFrameWidth);
- r = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxEditField, widget).adjusted(-fw,-fw,fw,fw);
+ int fw = proxy()->pixelMetric(QStyle::PM_DefaultFrameWidth);
+ r = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxEditField, widget).adjusted(-fw,-fw,fw,fw);
QStyleOptionFrame lineOpt;
lineOpt.QStyleOption::operator=(*opt);
lineOpt.rect = r;
lineOpt.lineWidth = fw;
lineOpt.midLineWidth = 0;
lineOpt.state |= QStyle::State_Sunken;
- drawPrimitive(QStyle::PE_FrameLineEdit, &lineOpt, p, widget);
+ proxy()->drawPrimitive(QStyle::PE_FrameLineEdit, &lineOpt, p, widget);
}
if (spinbox->subControls & SC_SpinBoxUp) {
@@ -1525,8 +1525,8 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
: PE_IndicatorSpinUp);
- copy.rect = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget);
- drawPrimitive(pe, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxUp, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
if (spinbox->subControls & SC_SpinBoxDown) {
@@ -1549,8 +1549,8 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
pe = (spinbox->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
: PE_IndicatorSpinDown);
- copy.rect = subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget);
- drawPrimitive(pe, &copy, p, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, spinbox, SC_SpinBoxDown, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
}
break;
@@ -1558,16 +1558,16 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- QRect groove = subControlRect(CC_Slider, opt, SC_SliderGroove, widget),
- handle = subControlRect(CC_Slider, opt, SC_SliderHandle, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, opt, SC_SliderGroove, widget),
+ handle = proxy()->subControlRect(CC_Slider, opt, SC_SliderHandle, widget);
if ((opt->subControls & SC_SliderGroove) && groove.isValid()) {
- qDrawShadePanel(p, groove, opt->palette, true, pixelMetric(PM_DefaultFrameWidth),
+ qDrawShadePanel(p, groove, opt->palette, true, proxy()->pixelMetric(PM_DefaultFrameWidth),
&opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window));
if ((opt->state & State_HasFocus) && (!focus || !focus->isVisible())) {
QStyleOption focusOpt = *opt;
focusOpt.rect = subElementRect(SE_SliderFocusRect, opt, widget);
- drawPrimitive(PE_FrameFocusRect, &focusOpt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focusOpt, p, widget);
}
}
@@ -1577,7 +1577,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
bevelOpt.rect = handle;
p->save();
p->setBrushOrigin(bevelOpt.rect.topLeft());
- drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &bevelOpt, p, widget);
p->restore();
if (slider->orientation == Qt::Horizontal) {
@@ -1589,14 +1589,14 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
qDrawShadeLine(p, handle.x(), mid, handle.x() + handle.width() - 2, mid, opt->palette,
true, 1);
}
- if (!(opt->state & State_Enabled) && styleHint(SH_DitherDisabledText))
+ if (!(opt->state & State_Enabled) && proxy()->styleHint(SH_DitherDisabledText))
p->fillRect(handle, QBrush(p->background().color(), Qt::Dense5Pattern));
}
if (slider->subControls & SC_SliderTickmarks) {
QStyleOptionSlider tmpSlider = *slider;
tmpSlider.subControls = SC_SliderTickmarks;
- int frameWidth = pixelMetric(PM_DefaultFrameWidth);
+ int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth);
tmpSlider.rect.translate(frameWidth - 1, 0);
QCommonStyle::drawComplexControl(cc, &tmpSlider, p, widget);
}
@@ -1607,13 +1607,13 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
if (const QStyleOptionComboBox *cb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
if (opt->subControls & SC_ComboBoxArrow) {
int awh, ax, ay, sh, sy, dh, ew;
- int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
+ int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
if (cb->frame) {
QStyleOptionButton btn;
btn.QStyleOption::operator=(*cb);
btn.state |= QStyle::State_Raised;
- drawPrimitive(PE_PanelButtonCommand, &btn, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &btn, p, widget);
} else {
p->fillRect(opt->rect, opt->palette.brush(QPalette::Button));
}
@@ -1627,7 +1627,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
QStyleOption arrowOpt = *opt;
arrowOpt.rect = ar;
arrowOpt.state |= State_Enabled;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
// draws the shaded line under the arrow
@@ -1643,13 +1643,13 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
focus.QStyleOption::operator=(*opt);
focus.rect = subElementRect(SE_ComboBoxFocusRect, opt, widget);
focus.backgroundColor = opt->palette.button().color();
- drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
}
}
if (opt->subControls & SC_ComboBoxEditField) {
if (cb->editable) {
- QRect er = subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, widget);
+ QRect er = proxy()->subControlRect(CC_ComboBox, opt, SC_ComboBoxEditField, widget);
er.adjust(-1, -1, 1, 1);
qDrawShadePanel(p, er, opt->palette, true, 1,
&opt->palette.brush(QPalette::Base));
@@ -1663,7 +1663,7 @@ void QMotifStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComple
case CC_ScrollBar: {
if (opt->subControls & SC_ScrollBarGroove)
qDrawShadePanel(p, opt->rect, opt->palette, true,
- pixelMetric(PM_DefaultFrameWidth, opt, widget),
+ proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget),
&opt->palette.brush((opt->state & State_Enabled) ? QPalette::Mid : QPalette::Window));
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
@@ -1798,7 +1798,7 @@ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt,
break;
case PM_ToolBarFrameWidth:
- ret = pixelMetric(PM_DefaultFrameWidth);
+ ret = proxy()->pixelMetric(PM_DefaultFrameWidth);
break;
case PM_ToolBarItemMargin:
@@ -1819,7 +1819,7 @@ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt,
break;
case PM_SliderThickness:
- ret = 16 + 4 * pixelMetric(PM_DefaultFrameWidth);
+ ret = 16 + 4 * proxy()->pixelMetric(PM_DefaultFrameWidth);
break;
#ifndef QT_NO_SLIDER
case PM_SliderControlThickness:
@@ -1849,9 +1849,9 @@ int QMotifStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt,
case PM_SliderSpaceAvailable:
if (const QStyleOptionSlider *sl = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (sl->orientation == Qt::Horizontal)
- ret = sl->rect.width() - pixelMetric(PM_SliderLength, opt, widget) - 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = sl->rect.width() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
else
- ret = sl->rect.height() - pixelMetric(PM_SliderLength, opt, widget) - 2 * pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ ret = sl->rect.height() - proxy()->pixelMetric(PM_SliderLength, opt, widget) - 2 * proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
}
break;
#endif // QT_NO_SLIDER
@@ -1901,7 +1901,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
#ifndef QT_NO_SPINBOX
case CC_SpinBox:
if (const QStyleOptionSpinBox *spinbox = qstyleoption_cast<const QStyleOptionSpinBox *>(opt)) {
- int fw = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
+ int fw = spinbox->frame ? proxy()->pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
QSize bs;
bs.setHeight(opt->rect.height()/2 - fw);
bs.setWidth(qMin(bs.height() * 8 / 5, opt->rect.width() / 4)); // 1.6 -approximate golden mean
@@ -1944,11 +1944,11 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
if (sc == SC_SliderHandle) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, opt, widget);
- int thickness = pixelMetric(PM_SliderControlThickness, opt, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, opt, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, opt, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
- int len = pixelMetric(PM_SliderLength, opt, widget);
- int motifBorder = pixelMetric(PM_DefaultFrameWidth);
+ int len = proxy()->pixelMetric(PM_SliderLength, opt, widget);
+ int motifBorder = proxy()->pixelMetric(PM_DefaultFrameWidth);
int sliderPos = sliderPositionFromValue(slider->minimum, slider->maximum, slider->sliderPosition,
horizontal ? slider->rect.width() - len - 2 * motifBorder
: slider->rect.height() - len - 2 * motifBorder,
@@ -1967,7 +1967,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int dfw = pixelMetric(PM_DefaultFrameWidth);
+ int dfw = proxy()->pixelMetric(PM_DefaultFrameWidth);
QRect rect = visualRect(scrollbar->direction, scrollbar->rect,
QCommonStyle::subControlRect(cc, scrollbar, sc, widget));
if (sc == SC_ScrollBarSlider) {
@@ -1991,7 +1991,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
switch (sc) {
case SC_ComboBoxArrow: {
int ew, awh, sh, dh, ax, ay, sy;
- int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
+ int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
QRect cr = opt->rect;
cr.adjust(fw, fw, -fw, -fw);
get_combo_parameters(cr, ew, awh, ax, ay, sh, dh, sy);
@@ -1999,7 +1999,7 @@ QMotifStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *opt,
}
case SC_ComboBoxEditField: {
- int fw = cb->frame ? pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
+ int fw = cb->frame ? proxy()->pixelMetric(PM_ComboBoxFrameWidth, opt, widget) : 0;
QRect rect = opt->rect;
rect.adjust(fw, fw, -fw, -fw);
int ew = get_combo_extra_width(rect.height(), rect.width());
@@ -2029,10 +2029,6 @@ QMotifStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
QSize sz(contentsSize);
switch(ct) {
- case CT_Splitter:
- sz = QSize(10, 10);
- break;
-
case CT_RadioButton:
case CT_CheckBox:
sz = QCommonStyle::sizeFromContents(ct, opt, contentsSize, widget);
@@ -2119,7 +2115,7 @@ QMotifStyle::subElementRect(SubElement sr, const QStyleOption *opt, const QWidge
case SE_ComboBoxFocusRect:
{
int awh, ax, ay, sh, sy, dh, ew;
- int fw = pixelMetric(PM_DefaultFrameWidth, opt, widget);
+ int fw = proxy()->pixelMetric(PM_DefaultFrameWidth, opt, widget);
QRect tr = opt->rect;
tr.adjust(fw, fw, -fw, -fw);
diff --git a/src/gui/styles/qplastiquestyle.cpp b/src/gui/styles/qplastiquestyle.cpp
index 24d7748..725e1d5 100644
--- a/src/gui/styles/qplastiquestyle.cpp
+++ b/src/gui/styles/qplastiquestyle.cpp
@@ -43,7 +43,6 @@
#if !defined(QT_NO_STYLE_PLASTIQUE) || defined(QT_PLUGIN)
-static bool UsePixmapCache = true;
static const bool AnimateBusyProgressBar = true;
static const bool AnimateProgressBar = false;
// #define QPlastique_MaskButtons
@@ -51,6 +50,7 @@ static const int ProgressBarFps = 25;
static const int blueFrameWidth = 2; // with of line edit focus frame
#include "qwindowsstyle_p.h"
+#include <private/qstylehelper_p.h>
#include <qapplication.h>
#include <qbitmap.h>
#include <qabstractitemview.h>
@@ -490,7 +490,7 @@ static void qBrushSetAlphaF(QBrush *brush, qreal alpha)
QPixmap texture = brush->texture();
QPixmap pixmap;
QString name = QString::fromLatin1("qbrushtexture-alpha-%1-%2").arg(alpha).arg(texture.cacheKey());
- if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, pixmap)) {
QImage image = texture.toImage();
QRgb *rgb = reinterpret_cast<QRgb *>(image.bits());
int pixels = image.width() * image.height();
@@ -551,7 +551,7 @@ static QBrush qBrushLight(QBrush brush, int light)
QPixmap texture = brush.texture();
QPixmap pixmap;
QString name = QString::fromLatin1("qbrushtexture-light-%1-%2").arg(light).arg(texture.cacheKey());
- if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, pixmap)) {
QImage image = texture.toImage();
QRgb *rgb = reinterpret_cast<QRgb *>(image.bits());
int pixels = image.width() * image.height();
@@ -610,7 +610,7 @@ static QBrush qBrushDark(QBrush brush, int dark)
QPixmap texture = brush.texture();
QPixmap pixmap;
QString name = QString::fromLatin1("qbrushtexture-dark-%1-%2").arg(dark).arg(brush.texture().cacheKey());
- if (UsePixmapCache && !QPixmapCache::find(name, pixmap)) {
+ if (!QPixmapCache::find(name, pixmap)) {
QImage image = texture.toImage();
QRgb *rgb = reinterpret_cast<QRgb *>(image.bits());
int pixels = image.width() * image.height();
@@ -749,8 +749,7 @@ static void qt_plastique_draw_gradient(QPainter *painter, const QRect &rect, con
QPainter *p = painter;
QRect r = rect;
- bool doPixmapCache = UsePixmapCache
- && painter->deviceTransform().isIdentity()
+ bool doPixmapCache = painter->deviceTransform().isIdentity()
&& painter->worldMatrix().isIdentity();
if (doPixmapCache && QPixmapCache::find(gradientName, cache)) {
painter->drawPixmap(rect, cache);
@@ -1005,8 +1004,6 @@ QPlastiqueStylePrivate::QPlastiqueStylePrivate() :
, progressBarAnimateTimer(0)
#endif
{
- if (!qgetenv("QT_STYLE_NO_PIXMAPCACHE").isNull())
- UsePixmapCache = false;
}
/*!
@@ -1132,7 +1129,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
switch (element) {
case PE_IndicatorButtonDropDown:
- drawPrimitive(PE_PanelButtonTool, option, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, option, painter, widget);
break;
case PE_FrameDefaultButton: {
if (!(option->state & QStyle::State_Enabled))
@@ -1178,7 +1175,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
break;
}
- int borderThickness = pixelMetric(PM_TabBarBaseOverlap, twf, widget);
+ int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, twf, widget);
bool reverse = (twf->direction == Qt::RightToLeft);
painter->save();
@@ -1357,7 +1354,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
painter->setPen(oldPen);
} else {
frameV2.state &= ~(State_Sunken | State_HasFocus);
- drawPrimitive(PE_Frame, &frameV2, painter, widget);
+ proxy()->drawPrimitive(PE_Frame, &frameV2, painter, widget);
}
}
break;
@@ -1516,7 +1513,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
}
#endif
QString pixmapName = uniqueName(QLatin1String("toolbarhandle"), option, rect.size());
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(rect.size());
cache.fill(Qt::transparent);
QPainter cachePainter(&cache);
@@ -1546,8 +1543,7 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
handle);
}
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(rect.topLeft(), cache);
break;
@@ -1857,13 +1853,13 @@ void QPlastiqueStyle::drawPrimitive(PrimitiveElement element, const QStyleOption
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
button.state &= ~State_MouseOver;
- drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
break;
}
case PE_FrameWindow: {
painter->save();
bool active = (option->state & State_Active);
- int titleBarStop = option->rect.top() + pixelMetric(PM_TitleBarHeight, option, widget);
+ int titleBarStop = option->rect.top() + proxy()->pixelMetric(PM_TitleBarHeight, option, widget);
QPalette palette = option->palette;
if (!active)
@@ -2073,7 +2069,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
&& !leftCornerWidget;
bool reverseShadow = false;
- int borderThickness = pixelMetric(PM_TabBarBaseOverlap, tab, widget);
+ int borderThickness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
int marginLeft = 0;
if ((atBeginning && !selected) || (selected && leftCornerWidget && ((tab->position == QStyleOptionTab::Beginning) || onlyTab))) {
marginLeft = 1;
@@ -2785,7 +2781,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QString progressBarName = uniqueName(QLatin1String("progressBarContents"),
option, rect.size());
QPixmap cache;
- if ((!UsePixmapCache || !QPixmapCache::find(progressBarName, cache)) && rect.height() > 7) {
+ if (!QPixmapCache::find(progressBarName, cache) && rect.height() > 7) {
QSize size = rect.size();
cache = QPixmap(QSize(size.width() - 6 + 30, size.height() - 6));
cache.fill(Qt::white);
@@ -2818,8 +2814,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
leftEdge += 10;
}
- if (UsePixmapCache)
- QPixmapCache::insert(progressBarName, cache);
+ QPixmapCache::insert(progressBarName, cache);
}
painter->setClipRect(progressBar.adjusted(1, 0, -1, -1));
@@ -2844,10 +2839,10 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
if (const QStyleOptionHeader *header = qstyleoption_cast<const QStyleOptionHeader *>(option)) {
QPixmap cache;
QString pixmapName = uniqueName(QLatin1String("headersection"), option, option->rect.size());
- pixmapName += QLatin1String("-") + QString::number(int(header->position));
- pixmapName += QLatin1String("-") + QString::number(int(header->orientation));
+ pixmapName += QString::number(- int(header->position));
+ pixmapName += QString::number(- int(header->orientation));
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, option->rect.width(), option->rect.height());
@@ -2891,8 +2886,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
cachePainter.drawLines(lines, 2);
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
@@ -2915,7 +2909,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
int w = 0;
if (!menuItem->text.isEmpty()) {
painter->setFont(menuItem->font);
- drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
+ proxy()->drawItemText(painter, menuItem->rect.adjusted(5, 0, -5, 0), Qt::AlignLeft | Qt::AlignVCenter,
menuItem->palette, menuItem->state & State_Enabled, menuItem->text,
QPalette::Text);
w = menuItem->fontMetrics.width(menuItem->text) + 5;
@@ -2958,7 +2952,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
if (checked)
button.state |= State_On;
button.palette = menuItem->palette;
- drawPrimitive(PE_IndicatorRadioButton, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorRadioButton, &button, painter, widget);
} else {
if (menuItem->icon.isNull()) {
QStyleOptionButton button;
@@ -2967,7 +2961,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
if (checked)
button.state |= State_On;
button.palette = menuItem->palette;
- drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, painter, widget);
} else if (checked) {
int iconSize = qMax(menuItem->maxIconWidth, 20);
QRect sunkenRect(option->rect.left() + 1,
@@ -3079,7 +3073,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
newMI.palette.highlightedText().color());
else
newMI.palette.setColor(QPalette::ButtonText, textBrush.color());
- drawPrimitive(arrow, &newMI, painter, widget);
+ proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
painter->restore();
@@ -3092,7 +3086,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
if ((option->state & State_Selected)) {
QPixmap cache;
QString pixmapName = uniqueName(QLatin1String("menubaritem"), option, option->rect.size());
- if (!UsePixmapCache || !QPixmapCache::find(pixmapName, cache)) {
+ if (!QPixmapCache::find(pixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, option->rect.width(), option->rect.height());
@@ -3142,8 +3136,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
lines[1] = QLine(rect.right() - 1, rect.top() + 1, rect.right() - 1, rect.bottom() - 2);
cachePainter.drawLines(lines, 2);
cachePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(pixmapName, cache);
+ QPixmapCache::insert(pixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
} else {
@@ -3457,7 +3450,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QString addLinePixmapName = uniqueName(QLatin1String("scrollbar_addline"), option, option->rect.size());
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(addLinePixmapName, cache)) {
+ if (!QPixmapCache::find(addLinePixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, cache.width(), cache.height());
@@ -3516,8 +3509,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
addLinePainter.drawImage(QPoint(pixmapRect.center().x() - 3, pixmapRect.center().y() - 2), arrow);
}
addLinePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(addLinePixmapName, cache);
+ QPixmapCache::insert(addLinePixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
}
@@ -3535,7 +3527,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
groovePixmapName += QLatin1String("-addpage");
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(groovePixmapName, cache)) {
+ if (!QPixmapCache::find(groovePixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(option->palette.background().color());
QPainter groovePainter(&cache);
@@ -3561,8 +3553,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
}
groovePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(groovePixmapName, cache);
+ QPixmapCache::insert(groovePixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
}
@@ -3579,7 +3570,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
// The SubLine (up/left) buttons
QRect button1;
QRect button2;
- int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget);
+ int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
if (horizontal) {
button1.setRect(scrollBarSubLine.left(), scrollBarSubLine.top(), scrollBarExtent, scrollBarSubLine.height());
button2.setRect(scrollBarSubLine.right() - (scrollBarExtent - 1), scrollBarSubLine.top(), scrollBarExtent, scrollBarSubLine.height());
@@ -3590,7 +3581,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QString subLinePixmapName = uniqueName(QLatin1String("scrollbar_subline"), option, button1.size());
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(subLinePixmapName, cache)) {
+ if (!QPixmapCache::find(subLinePixmapName, cache)) {
cache = QPixmap(button1.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, cache.width(), cache.height());
@@ -3650,8 +3641,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
subLinePainter.drawImage(QPoint(pixmapRect.center().x() - 3, pixmapRect.center().y() - 2), arrow);
}
subLinePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(subLinePixmapName, cache);
+ QPixmapCache::insert(subLinePixmapName, cache);
}
painter->drawPixmap(button1.topLeft(), cache);
painter->drawPixmap(button2.topLeft(), cache);
@@ -3669,7 +3659,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
sliderPixmapName += QLatin1String("-horizontal");
QPixmap cache;
- if (!UsePixmapCache || !QPixmapCache::find(sliderPixmapName, cache)) {
+ if (!QPixmapCache::find(sliderPixmapName, cache)) {
cache = QPixmap(option->rect.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, cache.width(), cache.height());
@@ -3720,7 +3710,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
pixmapRect.right() - 1, pixmapRect.bottom() - 1);
sliderPainter.drawLines(lines, 2);
- int sliderMinLength = pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
+ int sliderMinLength = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
if ((horizontal && scrollBar->rect.width() > sliderMinLength)
|| (!horizontal && scrollBar->rect.height() > sliderMinLength)) {
QImage pattern(horizontal ? qt_scrollbar_slider_pattern_horizontal
@@ -3740,8 +3730,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
}
sliderPainter.end();
// insert the slider into the cache
- if (UsePixmapCache)
- QPixmapCache::insert(sliderPixmapName, cache);
+ QPixmapCache::insert(sliderPixmapName, cache);
}
painter->drawPixmap(option->rect.topLeft(), cache);
}
@@ -3760,7 +3749,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
QWindowsStyle::drawControl(element, option, painter, widget);
} else if (!comboBox->currentIcon.isNull()) {
{
- QRect editRect = subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
+ QRect editRect = proxy()->subControlRect(CC_ComboBox, comboBox, SC_ComboBoxEditField, widget);
if (comboBox->direction == Qt::RightToLeft)
editRect.adjust(0, 2, -2, -2);
else
@@ -3777,7 +3766,7 @@ void QPlastiqueStyle::drawControl(ControlElement element, const QStyleOption *op
Qt::AlignLeft | Qt::AlignVCenter,
iconRect.size(), editRect);
painter->fillRect(iconRect, option->palette.brush(QPalette::Base));
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pixmap);
}
painter->restore();
}
@@ -3820,9 +3809,9 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- QRect grooveRegion = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
- QRect ticks = subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
+ QRect grooveRegion = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ QRect ticks = proxy()->subControlRect(CC_Slider, option, SC_SliderTickmarks, widget);
bool horizontal = slider->orientation == Qt::Horizontal;
bool ticksAbove = slider->tickPosition & QSlider::TicksAbove;
bool ticksBelow = slider->tickPosition & QSlider::TicksBelow;
@@ -3891,7 +3880,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
if ((option->activeSubControls & SC_SliderHandle) && (option->state & State_Sunken))
handlePixmapName += QLatin1String("-sunken");
- if (!UsePixmapCache || !QPixmapCache::find(handlePixmapName, cache)) {
+ if (!QPixmapCache::find(handlePixmapName, cache)) {
cache = QPixmap(handle.size());
cache.fill(Qt::white);
QRect pixmapRect(0, 0, handle.width(), handle.height());
@@ -3974,8 +3963,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
handlePainter.drawImage(pixmapRect, image);
handlePainter.end();
- if (UsePixmapCache)
- QPixmapCache::insert(handlePixmapName, cache);
+ QPixmapCache::insert(handlePixmapName, cache);
}
painter->drawPixmap(handle.topLeft(), cache);
@@ -3984,15 +3972,15 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, painter, widget);
}
}
if (option->subControls & SC_SliderTickmarks) {
QPen oldPen = painter->pen();
painter->setPen(borderColor);
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -4006,7 +3994,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
interval = 1;
int v = slider->minimum;
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
QVarLengthArray<QLine, 32> lines;
while (v <= slider->maximum + 1) {
if (v == slider->maximum + 1 && interval == 1)
@@ -4061,8 +4049,8 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool reverse = (spinBox->direction == Qt::RightToLeft);
// Rects
- QRect upRect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
- QRect downRect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ QRect upRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
+ QRect downRect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
QRect buttonRect = upRect | downRect;
// Brushes
@@ -4083,7 +4071,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
} else {
d->drawPartialFrame(painter,
option,
- subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget),
+ proxy()->subControlRect(CC_SpinBox, spinBox, SC_SpinBoxEditField, widget),
widget);
}
// Paint buttons
@@ -4423,7 +4411,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
Q_D(const QPlastiqueStyle);
d->drawPartialFrame(painter,
option,
- subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget),
+ proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget),
widget);
QBrush border = qMapBrushToRect(option->palette.shadow(), buttonRect);
@@ -4547,7 +4535,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
if (!sunken) {
buttonOption.state &= ~State_Sunken;
}
- drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
+ proxy()->drawPrimitive(PE_PanelButtonCommand, &buttonOption, painter, widget);
// Draw the menu button separator line
QBrush border = qMapBrushToRect(option->palette.shadow(), rect);
@@ -4580,11 +4568,12 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
// Draw the focus rect
- if (((option->state & State_HasFocus) && (option->state & State_KeyboardFocusChange)) && !comboBox->editable) {
+ if ((option->state & State_HasFocus) && !comboBox->editable
+ && ((option->state & State_KeyboardFocusChange) || styleHint(SH_UnderlineShortcut, option, widget))) {
QStyleOptionFocusRect focus;
- focus.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget)
+ focus.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget)
.adjusted(-2, 0, 2, 0);
- drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, painter, widget);
}
painter->setPen(oldPen);
@@ -4614,7 +4603,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
QStyleOptionDockWidgetV2 dockwidget;
dockwidget.QStyleOption::operator=(*option);
dockwidget.title = titleBar->text;
- drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
+ proxy()->drawControl(CE_DockWidgetTitle, &dockwidget, painter, widget);
} else
#endif // QT3_SUPPORT
@@ -4687,7 +4676,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
}
}
// draw title
- QRect textRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
+ QRect textRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarLabel, widget);
QFont font = painter->font();
font.setBold(true);
@@ -4714,7 +4703,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMinButton) && (titleBar->state & State_Sunken);
- QRect minButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
+ QRect minButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMinButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, minButtonRect, hover, sunken);
int xoffset = minButtonRect.width() / 3;
@@ -4758,7 +4747,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarMaxButton) && (titleBar->state & State_Sunken);
- QRect maxButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
+ QRect maxButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarMaxButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, maxButtonRect, hover, sunken);
int xoffset = maxButtonRect.width() / 3;
@@ -4783,7 +4772,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarCloseButton) && (titleBar->state & State_Sunken);
- QRect closeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
+ QRect closeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarCloseButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, closeButtonRect, hover, sunken);
int xoffset = closeButtonRect.width() / 3;
@@ -4829,7 +4818,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarNormalButton) && (titleBar->state & State_Sunken);
- QRect normalButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
+ QRect normalButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarNormalButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, normalButtonRect, hover, sunken);
int xoffset = int(normalButtonRect.width() / 3.5);
int yoffset = int(normalButtonRect.height() / 3.5);
@@ -4875,7 +4864,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarContextHelpButton) && (titleBar->state & State_Sunken);
- QRect contextHelpButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
+ QRect contextHelpButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarContextHelpButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, contextHelpButtonRect, hover, sunken);
@@ -4902,7 +4891,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarShadeButton) && (titleBar->state & State_Sunken);
- QRect shadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
+ QRect shadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarShadeButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, shadeButtonRect, hover, sunken);
int xoffset = shadeButtonRect.width() / 3;
@@ -4926,7 +4915,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarUnshadeButton) && (titleBar->state & State_Sunken);
- QRect unshadeButtonRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
+ QRect unshadeButtonRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarUnshadeButton, widget);
qt_plastique_draw_mdibutton(painter, titleBar, unshadeButtonRect, hover, sunken);
int xoffset = unshadeButtonRect.width() / 3;
@@ -4951,7 +4940,7 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
bool hover = (titleBar->activeSubControls & SC_TitleBarSysMenu) && (titleBar->state & State_MouseOver);
bool sunken = (titleBar->activeSubControls & SC_TitleBarSysMenu) && (titleBar->state & State_Sunken);
- QRect iconRect = subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
+ QRect iconRect = proxy()->subControlRect(CC_TitleBar, titleBar, SC_TitleBarSysMenu, widget);
if (hover)
qt_plastique_draw_mdibutton(painter, titleBar, iconRect, hover, sunken);
@@ -4963,13 +4952,19 @@ void QPlastiqueStyle::drawComplexControl(ComplexControl control, const QStyleOpt
QPixmap pm = standardPixmap(SP_TitleBarMenuButton, &tool, widget);
tool.rect = iconRect;
painter->save();
- drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
+ proxy()->drawItemPixmap(painter, iconRect, Qt::AlignCenter, pm);
painter->restore();
}
}
painter->restore();
}
break;
+#ifndef QT_NO_DIAL
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
+ QStyleHelper::drawDial(dial, painter);
+ break;
+#endif // QT_NO_DIAL
default:
QWindowsStyle::drawComplexControl(control, option, painter, widget);
break;
@@ -4992,7 +4987,7 @@ QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *o
#ifndef QT_NO_SLIDER
case CT_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
if (slider->tickPosition & QSlider::TicksBelow) {
if (slider->orientation == Qt::Horizontal)
newSize.rheight() += tickSize;
@@ -5011,8 +5006,8 @@ QSize QPlastiqueStyle::sizeFromContents(ContentsType type, const QStyleOption *o
#ifndef QT_NO_SCROLLBAR
case CT_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, option, widget);
- int scrollBarSliderMinimum = pixelMetric(PM_ScrollBarSliderMin, option, widget);
+ int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, option, widget);
+ int scrollBarSliderMinimum = proxy()->pixelMetric(PM_ScrollBarSliderMin, option, widget);
if (scrollBar->orientation == Qt::Horizontal) {
newSize = QSize(scrollBarExtent * 3 + scrollBarSliderMinimum, scrollBarExtent);
} else {
@@ -5093,7 +5088,7 @@ QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOption
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int tickSize = pixelMetric(PM_SliderTickmarkOffset, option, widget);
+ int tickSize = proxy()->pixelMetric(PM_SliderTickmarkOffset, option, widget);
switch (subControl) {
case SC_SliderHandle:
@@ -5146,10 +5141,10 @@ QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOption
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- int scrollBarExtent = pixelMetric(PM_ScrollBarExtent, scrollBar, widget);
+ int scrollBarExtent = proxy()->pixelMetric(PM_ScrollBarExtent, scrollBar, widget);
int sliderMaxLength = ((scrollBar->orientation == Qt::Horizontal) ?
scrollBar->rect.width() : scrollBar->rect.height()) - (scrollBarExtent * 3);
- int sliderMinLength = pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
+ int sliderMinLength = proxy()->pixelMetric(PM_ScrollBarSliderMin, scrollBar, widget);
int sliderLength;
// calculate slider length
@@ -5271,7 +5266,7 @@ QRect QPlastiqueStyle::subControlRect(ComplexControl control, const QStyleOption
break;
case SC_ComboBoxEditField: {
if (const QStyleOptionComboBox *box = qstyleoption_cast<const QStyleOptionComboBox *>(option)) {
- int frameWidth = pixelMetric(PM_DefaultFrameWidth);
+ int frameWidth = proxy()->pixelMetric(PM_DefaultFrameWidth);
rect = visualRect(option->direction, option->rect, rect);
if (box->editable) {
@@ -5453,6 +5448,11 @@ int QPlastiqueStyle::styleHint(StyleHint hint, const QStyleOption *option, const
case SH_Menu_SubMenuPopupDelay:
ret = 96; // from Plastik
break;
+#ifndef Q_OS_WIN
+ case SH_Menu_AllowActiveAndDisabled:
+ ret = false;
+ break;
+#endif
default:
ret = QWindowsStyle::styleHint(hint, option, widget, returnData);
break;
@@ -5471,31 +5471,31 @@ QStyle::SubControl QPlastiqueStyle::hitTestComplexControl(ComplexControl control
#ifndef QT_NO_SCROLLBAR
case CC_ScrollBar:
if (const QStyleOptionSlider *scrollBar = qstyleoption_cast<const QStyleOptionSlider *>(option)) {
- QRect slider = subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
+ QRect slider = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSlider, widget);
if (slider.contains(pos)) {
ret = SC_ScrollBarSlider;
break;
}
- QRect scrollBarAddLine = subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
+ QRect scrollBarAddLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddLine, widget);
if (scrollBarAddLine.contains(pos)) {
ret = SC_ScrollBarAddLine;
break;
}
- QRect scrollBarSubPage = subControlRect(control, scrollBar, SC_ScrollBarSubPage, widget);
+ QRect scrollBarSubPage = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubPage, widget);
if (scrollBarSubPage.contains(pos)) {
ret = SC_ScrollBarSubPage;
break;
}
- QRect scrollBarAddPage = subControlRect(control, scrollBar, SC_ScrollBarAddPage, widget);
+ QRect scrollBarAddPage = proxy()->subControlRect(control, scrollBar, SC_ScrollBarAddPage, widget);
if (scrollBarAddPage.contains(pos)) {
ret = SC_ScrollBarAddPage;
break;
}
- QRect scrollBarSubLine = subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
+ QRect scrollBarSubLine = proxy()->subControlRect(control, scrollBar, SC_ScrollBarSubLine, widget);
if (scrollBarSubLine.contains(pos)) {
ret = SC_ScrollBarSubLine;
break;
diff --git a/src/gui/styles/qproxystyle.cpp b/src/gui/styles/qproxystyle.cpp
new file mode 100644
index 0000000..f36ad64
--- /dev/null
+++ b/src/gui/styles/qproxystyle.cpp
@@ -0,0 +1,366 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qstyle.h>
+#include <private/qstyle_p.h>
+#include <private/qproxystyle_p.h>
+#include <private/qapplication_p.h>
+#include "qproxystyle.h"
+#include "qstylefactory.h"
+
+#if !defined(QT_NO_STYLE_PROXY) || defined(QT_PLUGIN)
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QProxyStyle
+
+ \brief The QProxyStyle is a convenience class that simplifies
+ the creation of proxy styles in Qt.
+
+ \since 4.6
+
+ A proxy style is a style that wraps a different,
+ usually the default system style, to override the painting or
+ behavior of only specific parts.
+
+ Here's an example allowing you to override the shortcut underline
+ behavior on all platforms:
+
+ \snippet doc/src/snippets/code/src_gui_proxystyle.cpp 0
+
+ Warning: Note that even though Qt's internal styles should respect this.
+ hint, there is no guarantee that it will work for all styles.
+ The example above would for instance not work on Mac since menus are
+ handled by the operating system.
+
+ \sa QStyle
+*/
+void QProxyStylePrivate::ensureBaseStyle() const
+{
+ Q_Q(const QProxyStyle);
+
+ if (baseStyle)
+ return;
+
+ if (!baseStyle && !QApplicationPrivate::styleOverride.isEmpty()) {
+ baseStyle = QStyleFactory::create(QApplicationPrivate::styleOverride);
+ if (baseStyle) {
+ // If baseStyle is an instance of the same proxyStyle
+ // we destroy it and fall back to the desktop style
+ if (qstrcmp(baseStyle->metaObject()->className(),
+ q->metaObject()->className()) == 0) {
+ delete baseStyle;
+ baseStyle = 0;
+ }
+ }
+ }
+
+ if (!baseStyle) // Use application desktop style
+ baseStyle = QStyleFactory::create(QApplicationPrivate::desktopStyleKey());
+
+ if (!baseStyle) // Fallback to windows style
+ baseStyle = QStyleFactory::create(QLatin1String("windows"));
+
+ baseStyle->setProxy(const_cast<QProxyStyle*>(q));
+ baseStyle->setParent(const_cast<QProxyStyle*>(q)); // Take ownership
+}
+
+/*!
+ Constructs a QProxyStyle object.
+
+ If no base style is provided, the current application style
+ will be used as the base style.
+
+ Ownership of \style is transferred to QProxyStyle.
+*/
+QProxyStyle::QProxyStyle(QStyle *style) :
+ QCommonStyle(*new QProxyStylePrivate())
+{
+ Q_D(QProxyStyle);
+ if (style) {
+ style->setProxy(this);
+ style->setParent(this); // Take ownership
+ d->baseStyle = style;
+ }
+}
+
+/*!
+ Destroys the QProxyStyle object.
+*/
+QProxyStyle::~QProxyStyle()
+{
+}
+
+/*!
+ Returns the proxy base style object. If no base style
+ is set on the proxy style, QProxyStyle will create
+ an instance of the application style instead.
+
+ \sa setBaseStyle(), QStyle
+*/
+QStyle *QProxyStyle::baseStyle() const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle;
+}
+
+/*!
+ Sets the base style that should be proxied.
+
+ Ownership of \style is transferred to QProxyStyle.
+
+ If style is zero, a desktop-dependant style will be
+ assigned automatically.
+*/
+void QProxyStyle::setBaseStyle(QStyle *style)
+{
+ Q_D (QProxyStyle);
+
+ if (d->baseStyle && d->baseStyle->parent() == this)
+ d->baseStyle->deleteLater();
+
+ d->baseStyle = style;
+
+ if (d->baseStyle) {
+ d->baseStyle->setProxy(this);
+ d->baseStyle->setParent(this);
+ }
+}
+
+/*! reimp */
+void QProxyStyle::drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawPrimitive(element, option, painter, widget);
+}
+
+/*! reimp */
+void QProxyStyle::drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawControl(element, option, painter, widget);
+}
+
+/*! reimp */
+void QProxyStyle::drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawComplexControl(control, option, painter, widget);
+}
+
+/*! reimp */
+void QProxyStyle::drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled,
+ const QString &text, QPalette::ColorRole textRole) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawItemText(painter, rect, flags, pal, enabled, text, textRole);
+}
+
+/*! reimp */
+void QProxyStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->drawItemPixmap(painter, rect, alignment, pixmap);
+}
+
+/*! reimp */
+QSize QProxyStyle::sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->sizeFromContents(type, option, size, widget);
+}
+
+/*! reimp */
+QRect QProxyStyle::subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->subElementRect(element, option, widget);
+}
+
+/*! reimp */
+QRect QProxyStyle::subControlRect(ComplexControl cc, const QStyleOptionComplex *option, SubControl sc, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->subControlRect(cc, option, sc, widget);
+}
+
+/*! reimp */
+QRect QProxyStyle::itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->itemTextRect(fm, r, flags, enabled, text);
+}
+
+/*! reimp */
+QRect QProxyStyle::itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->itemPixmapRect(r, flags, pixmap);
+}
+
+/*! reimp */
+QStyle::SubControl QProxyStyle::hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->hitTestComplexControl(control, option, pos, widget);
+}
+
+/*! reimp */
+int QProxyStyle::styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *returnData) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->styleHint(hint, option, widget, returnData);
+}
+
+/*! reimp */
+int QProxyStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->pixelMetric(metric, option, widget);
+}
+
+/*! reimp */
+QPixmap QProxyStyle::standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->standardPixmap(standardPixmap, opt, widget);
+}
+
+/*! reimp */
+QPixmap QProxyStyle::generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->generatedIconPixmap(iconMode, pixmap, opt);
+}
+
+/*! reimp */
+QPalette QProxyStyle::standardPalette() const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->standardPalette();
+}
+
+/*! reimp */
+void QProxyStyle::polish(QWidget *widget)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->polish(widget);
+}
+
+/*! reimp */
+void QProxyStyle::polish(QPalette &pal)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->polish(pal);
+}
+
+/*! reimp */
+void QProxyStyle::polish(QApplication *app)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->polish(app);
+}
+
+/*! reimp */
+void QProxyStyle::unpolish(QWidget *widget)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->unpolish(widget);
+}
+
+/*! reimp */
+void QProxyStyle::unpolish(QApplication *app)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ d->baseStyle->unpolish(app);
+}
+
+/*! reimp */
+bool QProxyStyle::event(QEvent *e)
+{
+ Q_D (QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->event(e);
+}
+
+/*! reimp */
+QIcon QProxyStyle::standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->standardIcon(standardIcon, option, widget);
+}
+
+/*! reimp */
+int QProxyStyle::layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2,
+ Qt::Orientation orientation, const QStyleOption *option, const QWidget *widget) const
+{
+ Q_D (const QProxyStyle);
+ d->ensureBaseStyle();
+ return d->baseStyle->layoutSpacing(control1, control2, orientation, option, widget);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_STYLE_PROXY
diff --git a/src/gui/styles/qproxystyle.h b/src/gui/styles/qproxystyle.h
new file mode 100644
index 0000000..76b0768
--- /dev/null
+++ b/src/gui/styles/qproxystyle.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROXYSTYLE_H
+#define QPROXYSTYLE_H
+
+#include <QtGui/QCommonStyle>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_STYLE_PROXY)
+
+class QProxyStylePrivate;
+class Q_GUI_EXPORT QProxyStyle : public QCommonStyle
+{
+ Q_OBJECT
+
+public:
+ QProxyStyle(QStyle *baseStyle = 0);
+ ~QProxyStyle();
+
+ QStyle *baseStyle() const;
+ void setBaseStyle(QStyle *style);
+
+ void drawPrimitive(PrimitiveElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawControl(ControlElement element, const QStyleOption *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawComplexControl(ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = 0) const;
+ void drawItemText(QPainter *painter, const QRect &rect, int flags, const QPalette &pal, bool enabled,
+ const QString &text, QPalette::ColorRole textRole = QPalette::NoRole) const;
+ virtual void drawItemPixmap(QPainter *painter, const QRect &rect, int alignment, const QPixmap &pixmap) const;
+
+ QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &size, const QWidget *widget) const;
+
+ QRect subElementRect(SubElement element, const QStyleOption *option, const QWidget *widget) const;
+ QRect subControlRect(ComplexControl cc, const QStyleOptionComplex *opt, SubControl sc, const QWidget *widget) const;
+ QRect itemTextRect(const QFontMetrics &fm, const QRect &r, int flags, bool enabled, const QString &text) const;
+ QRect itemPixmapRect(const QRect &r, int flags, const QPixmap &pixmap) const;
+
+ SubControl hitTestComplexControl(ComplexControl control, const QStyleOptionComplex *option, const QPoint &pos, const QWidget *widget = 0) const;
+ int styleHint(StyleHint hint, const QStyleOption *option = 0, const QWidget *widget = 0, QStyleHintReturn *returnData = 0) const;
+ int pixelMetric(PixelMetric metric, const QStyleOption *option = 0, const QWidget *widget = 0) const;
+
+ QPixmap standardPixmap(StandardPixmap standardPixmap, const QStyleOption *opt, const QWidget *widget = 0) const;
+ QPixmap generatedIconPixmap(QIcon::Mode iconMode, const QPixmap &pixmap, const QStyleOption *opt) const;
+ QPalette standardPalette() const;
+
+ void polish(QWidget *widget);
+ void polish(QPalette &pal);
+ void polish(QApplication *app);
+
+ void unpolish(QWidget *widget);
+ void unpolish(QApplication *app);
+
+protected:
+ bool event(QEvent *e);
+
+protected Q_SLOTS:
+ QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *option, const QWidget *widget) const;
+ int layoutSpacingImplementation(QSizePolicy::ControlType control1, QSizePolicy::ControlType control2,
+ Qt::Orientation orientation, const QStyleOption *option = 0, const QWidget *widget = 0) const;
+private:
+ Q_DISABLE_COPY(QProxyStyle)
+ Q_DECLARE_PRIVATE(QProxyStyle)
+};
+
+#endif // QT_NO_STYLE_PROXY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QPROXYSTYLE_H
diff --git a/src/gui/painting/qwindowsurface_d3d_p.h b/src/gui/styles/qproxystyle_p.h
index 9cdfe29..e7630d9 100644
--- a/src/gui/painting/qwindowsurface_d3d_p.h
+++ b/src/gui/styles/qproxystyle_p.h
@@ -39,46 +39,41 @@
**
****************************************************************************/
-#ifndef QWINDOWSURFACE_D3D_P_H
-#define QWINDOWSURFACE_D3D_P_H
+#ifndef QPROXYSTYLE_P_H
+#define QPROXYSTYLE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
-// version to version without notice, or even be removed.
+// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
+// file may change from version to version without notice, or even be removed.
//
// We mean it.
//
-#include <qglobal.h>
-#include "private/qwindowsurface_p.h"
+#include "qcommonstyle.h"
+#include "qcommonstyle_p.h"
+#include "qproxystyle.h"
-QT_BEGIN_NAMESPACE
+#ifndef QT_NO_STYLE_PROXY
-class QPaintDevice;
-class QPoint;
-class QRegion;
-class QWidget;
-struct QD3DWindowSurfacePrivate;
+QT_BEGIN_NAMESPACE
-class QD3DWindowSurface : public QWindowSurface
+class QProxyStylePrivate : public QCommonStylePrivate
{
+ Q_DECLARE_PUBLIC(QProxyStyle)
public:
- QD3DWindowSurface(QWidget *widget);
- ~QD3DWindowSurface();
-
- QPaintDevice *paintDevice();
- void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
- void setGeometry(const QRect &rect);
- bool scroll(const QRegion &area, int dx, int dy);
-
+ void ensureBaseStyle() const;
private:
- QD3DWindowSurfacePrivate *d_ptr;
+ QProxyStylePrivate() :
+ QCommonStylePrivate(), baseStyle(0) {}
+ mutable QPointer <QStyle> baseStyle;
};
QT_END_NAMESPACE
-#endif // QWINDOWSURFACE_D3D_P_H
+#endif // QT_NO_STYLE_PROXY
+
+#endif //QPROXYSTYLE_P_H
diff --git a/src/gui/styles/qstyle.cpp b/src/gui/styles/qstyle.cpp
index 982f48f..c0fdc83 100644
--- a/src/gui/styles/qstyle.cpp
+++ b/src/gui/styles/qstyle.cpp
@@ -325,9 +325,10 @@ static int unpackControlTypes(QSizePolicy::ControlTypes controls, QSizePolicy::C
QStyle::QStyle()
: QObject(*new QStylePrivate)
{
+ Q_D(QStyle);
+ d->proxyStyle = this;
}
-
/*!
\internal
@@ -336,6 +337,8 @@ QStyle::QStyle()
QStyle::QStyle(QStylePrivate &dd)
: QObject(dd)
{
+ Q_D(QStyle);
+ d->proxyStyle = this;
}
/*!
@@ -1048,6 +1051,8 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SE_TabBarTabRightButton Area for a widget on the right side of a tab in a tab bar.
\value SE_TabBarTabText Area for the text on a tab in a tab bar.
+ \value SE_ToolBarHandle Area for the handle of a tool bar.
+
\sa subElementRect()
*/
@@ -1330,7 +1335,7 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value PM_LayoutVerticalSpacing Default \l{QLayout::spacing}{vertical spacing} for a QLayout.
\value PM_MaximumDragDistance The maximum allowed distance between
- the mouse and a slider when dragging. Exceeding the specified
+ the mouse and a scrollbar when dragging. Exceeding the specified
distance will cause the slider to jump back to the original
position; a value of -1 disables this behavior.
@@ -2437,9 +2442,38 @@ QDebug operator<<(QDebug debug, QStyle::State state)
qSort(states);
debug << states.join(QLatin1String(" | "));
- debug << ")";
+ debug << ')';
return debug;
}
#endif
+/*!
+ \since 4.6
+
+ \fn const QStyle * proxy() const
+
+ This function returns the current proxy for this style.
+ By default most styles will return themselves. However
+ when a proxy style is in use, it will allow the style to
+ call back into its proxy.
+
+ \sa setProxyStyle
+*/
+const QStyle * QStyle::proxy() const
+{
+ Q_D(const QStyle);
+ return d->proxyStyle;
+}
+
+/* \internal
+
+ This function sets the base style that style calls will be
+ redirected to. Note that ownership is not transferred.
+*/
+void QStyle::setProxy(QStyle *style)
+{
+ Q_D(QStyle);
+ d->proxyStyle = style;
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/styles/qstyle.h b/src/gui/styles/qstyle.h
index 6191d51..eec3326 100644
--- a/src/gui/styles/qstyle.h
+++ b/src/gui/styles/qstyle.h
@@ -373,6 +373,8 @@ public:
SE_ShapedFrameContents,
+ SE_ToolBarHandle,
+
// do not add any values below/greater than this
SE_CustomBase = 0xf0000000
};
@@ -453,6 +455,7 @@ public:
SC_MdiNormalButton = 0x00000002,
SC_MdiCloseButton = 0x00000004,
+ SC_CustomBase = 0xf0000000,
SC_All = 0xffffffff
};
Q_DECLARE_FLAGS(SubControls, SubControl)
@@ -845,6 +848,8 @@ public:
QSizePolicy::ControlTypes controls2, Qt::Orientation orientation,
QStyleOption *option = 0, QWidget *widget = 0) const;
+ const QStyle * proxy() const;
+
protected Q_SLOTS:
QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0,
const QWidget *widget = 0) const;
@@ -859,6 +864,9 @@ private:
friend class QWidget;
friend class QWidgetPrivate;
friend class QApplication;
+ friend class QProxyStyle;
+ friend class QProxyStylePrivate;
+ void setProxy(QStyle *style);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QStyle::State)
diff --git a/src/gui/styles/qstyle_p.h b/src/gui/styles/qstyle_p.h
index 848bad6..4cf20f0 100644
--- a/src/gui/styles/qstyle_p.h
+++ b/src/gui/styles/qstyle_p.h
@@ -43,6 +43,7 @@
#define QSTYLE_P_H
#include "private/qobject_p.h"
+#include <QtGui/qstyle.h>
QT_BEGIN_NAMESPACE
@@ -51,22 +52,24 @@ QT_BEGIN_NAMESPACE
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of qapplication_*.cpp, qwidget*.cpp and qfiledialog.cpp. This header
-// file may change from version to version without notice, or even be removed.
+// of qstyle_*.cpp. This header file may change from version to version
+// without notice, or even be removed.
//
// We mean it.
//
// Private class
+class QStyle;
+
class QStylePrivate: public QObjectPrivate
{
- Q_DECLARE_PUBLIC(QStyle)
+ Q_DECLARE_PUBLIC(QStyle);
public:
inline QStylePrivate()
- : layoutSpacingIndex(-1)
- { }
+ : layoutSpacingIndex(-1), proxyStyle(0) {}
mutable int layoutSpacingIndex;
+ QStyle *proxyStyle;
};
@@ -77,7 +80,7 @@ public:
QPainter *p = painter; \
QString unique = uniqueName((a), option, option->rect.size()); \
int txType = painter->deviceTransform().type() | painter->worldTransform().type(); \
- bool doPixmapCache = UsePixmapCache && txType <= QTransform::TxTranslate; \
+ bool doPixmapCache = txType <= QTransform::TxTranslate; \
if (doPixmapCache && QPixmapCache::find(unique, internalPixmapCache)) { \
painter->drawPixmap(option->rect.topLeft(), internalPixmapCache); \
} else { \
@@ -89,6 +92,7 @@ public:
}
+
#define END_STYLE_PIXMAPCACHE \
if (doPixmapCache) { \
p->end(); \
diff --git a/src/gui/styles/qstylefactory.cpp b/src/gui/styles/qstylefactory.cpp
index 42cd6dc..2e0448c 100644
--- a/src/gui/styles/qstylefactory.cpp
+++ b/src/gui/styles/qstylefactory.cpp
@@ -178,7 +178,7 @@ QStyle *QStyleFactory::create(const QString& key)
else
#endif
#ifndef QT_NO_STYLE_MAC
- if (style.left(9) == QLatin1String("macintosh")) {
+ if (style.startsWith(QLatin1String("macintosh"))) {
ret = new QMacStyle;
# ifdef Q_WS_MAC
if (style == QLatin1String("macintosh"))
diff --git a/src/gui/styles/qstylehelper.cpp b/src/gui/styles/qstylehelper.cpp
new file mode 100644
index 0000000..20de892
--- /dev/null
+++ b/src/gui/styles/qstylehelper.cpp
@@ -0,0 +1,352 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qstylehelper_p.h"
+
+#include <qstyleoption.h>
+#include <qpainter.h>
+#include <qpixmapcache.h>
+#include <private/qmath_p.h>
+#include <private/qstyle_p.h>
+#include <qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QStyleHelper {
+
+QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size)
+{
+ QString tmp;
+ const QStyleOptionComplex *complexOption = qstyleoption_cast<const QStyleOptionComplex *>(option);
+ tmp.sprintf("%s-%d-%d-%lld-%dx%d-%d", key.toLatin1().constData(), uint(option->state),
+ complexOption ? uint(complexOption->activeSubControls) : uint(0),
+ option->palette.cacheKey(), size.width(), size.height(), option->direction);
+#ifndef QT_NO_SPINBOX
+ if (const QStyleOptionSpinBox *spinBox = qstyleoption_cast<const QStyleOptionSpinBox *>(option)) {
+ tmp.append(QLatin1Char('-'));
+ tmp.append(QString::number(spinBox->buttonSymbols));
+ tmp.append(QLatin1Char('-'));
+ tmp.append(QString::number(spinBox->stepEnabled));
+ tmp.append(QLatin1Char('-'));
+ tmp.append(QLatin1Char(spinBox->frame ? '1' : '0'));
+ }
+#endif // QT_NO_SPINBOX
+ return tmp;
+}
+
+#ifndef QT_NO_DIAL
+
+int calcBigLineSize(int radius)
+{
+ int bigLineSize = radius / 6;
+ if (bigLineSize < 4)
+ bigLineSize = 4;
+ if (bigLineSize > radius / 2)
+ bigLineSize = radius / 2;
+ return bigLineSize;
+}
+
+static QPointF calcRadialPos(const QStyleOptionSlider *dial, qreal offset)
+{
+ const int width = dial->rect.width();
+ const int height = dial->rect.height();
+ const int r = qMin(width, height) / 2;
+ const int currentSliderPosition = dial->upsideDown ? dial->sliderPosition : (dial->maximum - dial->sliderPosition);
+ qreal a = 0;
+ if (dial->maximum == dial->minimum)
+ a = Q_PI / 2;
+ else if (dial->dialWrapping)
+ a = Q_PI * 3 / 2 - (currentSliderPosition - dial->minimum) * 2 * Q_PI
+ / (dial->maximum - dial->minimum);
+ else
+ a = (Q_PI * 8 - (currentSliderPosition - dial->minimum) * 10 * Q_PI
+ / (dial->maximum - dial->minimum)) / 6;
+ qreal xc = width / 2.0;
+ qreal yc = height / 2.0;
+ qreal len = r - QStyleHelper::calcBigLineSize(r) - 3;
+ qreal back = offset * len;
+ QPointF pos(QPointF(xc + back * qCos(a), yc - back * qSin(a)));
+ return pos;
+}
+
+qreal angle(const QPointF &p1, const QPointF &p2)
+{
+ static const qreal rad_factor = 180 / Q_PI;
+ qreal _angle = 0;
+
+ if (p1.x() == p2.x()) {
+ if (p1.y() < p2.y())
+ _angle = 270;
+ else
+ _angle = 90;
+ } else {
+ qreal x1, x2, y1, y2;
+
+ if (p1.x() <= p2.x()) {
+ x1 = p1.x(); y1 = p1.y();
+ x2 = p2.x(); y2 = p2.y();
+ } else {
+ x2 = p1.x(); y2 = p1.y();
+ x1 = p2.x(); y1 = p2.y();
+ }
+
+ qreal m = -(y2 - y1) / (x2 - x1);
+ _angle = atan(m) * rad_factor;
+
+ if (p1.x() < p2.x())
+ _angle = 180 - _angle;
+ else
+ _angle = -_angle;
+ }
+ return _angle;
+}
+
+QPolygonF calcLines(const QStyleOptionSlider *dial)
+{
+ QPolygonF poly;
+ int width = dial->rect.width();
+ int height = dial->rect.height();
+ qreal r = qMin(width, height) / 2;
+ int bigLineSize = calcBigLineSize(int(r));
+
+ qreal xc = width / 2 + 0.5;
+ qreal yc = height / 2 + 0.5;
+ int ns = dial->tickInterval;
+ int notches = (dial->maximum + ns - 1 - dial->minimum) / ns;
+ if (notches <= 0)
+ return poly;
+ if (dial->maximum < dial->minimum || dial->maximum - dial->minimum > 1000) {
+ int maximum = dial->minimum + 1000;
+ notches = (maximum + ns - 1 - dial->minimum) / ns;
+ }
+
+ poly.resize(2 + 2 * notches);
+ int smallLineSize = bigLineSize / 2;
+ for (int i = 0; i <= notches; ++i) {
+ qreal angle = dial->dialWrapping ? Q_PI * 3 / 2 - i * 2 * Q_PI / notches
+ : (Q_PI * 8 - i * 10 * Q_PI / notches) / 6;
+ qreal s = qSin(angle);
+ qreal c = qCos(angle);
+ if (i == 0 || (((ns * i) % (dial->pageStep ? dial->pageStep : 1)) == 0)) {
+ poly[2 * i] = QPointF(xc + (r - bigLineSize) * c,
+ yc - (r - bigLineSize) * s);
+ poly[2 * i + 1] = QPointF(xc + r * c, yc - r * s);
+ } else {
+ poly[2 * i] = QPointF(xc + (r - 1 - smallLineSize) * c,
+ yc - (r - 1 - smallLineSize) * s);
+ poly[2 * i + 1] = QPointF(xc + (r - 1) * c, yc -(r - 1) * s);
+ }
+ }
+ return poly;
+}
+
+
+// This will draw a nice and shiny QDial for us. We don't want
+// all the shinyness in QWindowsStyle, hence we place it here
+
+void drawDial(const QStyleOptionSlider *option, QPainter *painter)
+{
+ QPalette pal = option->palette;
+ QColor buttonColor = pal.button().color();
+ const int width = option->rect.width();
+ const int height = option->rect.height();
+ const bool enabled = option->state & QStyle::State_Enabled;
+ qreal r = qMin(width, height) / 2;
+ r -= r/50;
+ const qreal penSize = r/20.0;
+
+ painter->save();
+ painter->setRenderHint(QPainter::Antialiasing);
+
+ // Draw notches
+ if (option->subControls & QStyle::SC_DialTickmarks) {
+ painter->setPen(option->palette.dark().color().darker(120));
+ painter->drawLines(QStyleHelper::calcLines(option));
+ }
+
+ // Cache dial background
+ BEGIN_STYLE_PIXMAPCACHE(QString::fromLatin1("qdial"));
+ p->setRenderHint(QPainter::Antialiasing);
+
+ const qreal d_ = r / 6;
+ const qreal dx = option->rect.x() + d_ + (width - 2 * r) / 2 + 1;
+ const qreal dy = option->rect.y() + d_ + (height - 2 * r) / 2 + 1;
+
+ QRectF br = QRectF(dx + 0.5, dy + 0.5,
+ int(r * 2 - 2 * d_ - 2),
+ int(r * 2 - 2 * d_ - 2));
+ buttonColor.setHsv(buttonColor .hue(),
+ qMin(140, buttonColor .saturation()),
+ qMax(180, buttonColor.value()));
+ QColor shadowColor(0, 0, 0, 20);
+
+ if (enabled) {
+ // Drop shadow
+ qreal shadowSize = qMax(1.0, penSize/2.0);
+ QRectF shadowRect= br.adjusted(-2*shadowSize, -2*shadowSize,
+ 2*shadowSize, 2*shadowSize);
+ QRadialGradient shadowGradient(shadowRect.center().x(),
+ shadowRect.center().y(), shadowRect.width()/2.0,
+ shadowRect.center().x(), shadowRect.center().y());
+ shadowGradient.setColorAt(0.91, QColor(0, 0, 0, 40));
+ shadowGradient.setColorAt(1.0, Qt::transparent);
+ p->setBrush(shadowGradient);
+ p->setPen(Qt::NoPen);
+ p->translate(shadowSize, shadowSize);
+ p->drawEllipse(shadowRect);
+ p->translate(-shadowSize, -shadowSize);
+
+ // Main gradient
+ QRadialGradient gradient(br.center().x() - br.width()/3, dy,
+ br.width()*1.3, br.center().x(),
+ br.center().y() - br.height()/2);
+ gradient.setColorAt(0, buttonColor.lighter(110));
+ gradient.setColorAt(0.5, buttonColor);
+ gradient.setColorAt(0.501, buttonColor.darker(102));
+ gradient.setColorAt(1, buttonColor.darker(115));
+ p->setBrush(gradient);
+ } else {
+ p->setBrush(Qt::NoBrush);
+ }
+
+ p->setPen(QPen(buttonColor.darker(280)));
+ p->drawEllipse(br);
+ p->setBrush(Qt::NoBrush);
+ p->setPen(buttonColor.lighter(110));
+ p->drawEllipse(br.adjusted(1, 1, -1, -1));
+
+ if (option->state & QStyle::State_HasFocus) {
+ QColor highlight = pal.highlight().color();
+ highlight.setHsv(highlight.hue(),
+ qMin(160, highlight.saturation()),
+ qMax(230, highlight.value()));
+ highlight.setAlpha(127);
+ p->setPen(QPen(highlight, 2.0));
+ p->setBrush(Qt::NoBrush);
+ p->drawEllipse(br.adjusted(-1, -1, 1, 1));
+ }
+
+ END_STYLE_PIXMAPCACHE
+
+ QPointF dp = calcRadialPos(option, 0.70);
+ buttonColor = buttonColor.lighter(104);
+ buttonColor.setAlphaF(0.8);
+ const qreal ds = r/7.0;
+ QRectF dialRect(dp.x() - ds, dp.y() - ds, 2*ds, 2*ds);
+ QRadialGradient dialGradient(dialRect.center().x() + dialRect.width()/2,
+ dialRect.center().y() + dialRect.width(),
+ dialRect.width()*2,
+ dialRect.center().x(), dialRect.center().y());
+ dialGradient.setColorAt(1, buttonColor.darker(140));
+ dialGradient.setColorAt(0.4, buttonColor.darker(120));
+ dialGradient.setColorAt(0, buttonColor.darker(110));
+ if (penSize > 3.0) {
+ painter->setPen(QPen(QColor(0, 0, 0, 25), penSize));
+ painter->drawLine(calcRadialPos(option, 0.90), calcRadialPos(option, 0.96));
+ }
+
+ painter->setBrush(dialGradient);
+ painter->setPen(QColor(255, 255, 255, 150));
+ painter->drawEllipse(dialRect.adjusted(-1, -1, 1, 1));
+ painter->setPen(QColor(0, 0, 0, 80));
+ painter->drawEllipse(dialRect);
+ painter->restore();
+}
+#endif //QT_NO_DIAL
+
+void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect,
+ int left, int top, int right,
+ int bottom)
+{
+ QSize size = pixmap.size();
+ //painter->setRenderHint(QPainter::SmoothPixmapTransform);
+
+ //top
+ if (top > 0) {
+ painter->drawPixmap(QRect(rect.left() + left, rect.top(), rect.width() -right - left, top), pixmap,
+ QRect(left, 0, size.width() -right - left, top));
+
+ //top-left
+ if(left > 0)
+ painter->drawPixmap(QRect(rect.left(), rect.top(), left, top), pixmap,
+ QRect(0, 0, left, top));
+
+ //top-right
+ if (right > 0)
+ painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top(), right, top), pixmap,
+ QRect(size.width() - right, 0, right, top));
+ }
+
+ //left
+ if (left > 0)
+ painter->drawPixmap(QRect(rect.left(), rect.top()+top, left, rect.height() - top - bottom), pixmap,
+ QRect(0, top, left, size.height() - bottom - top));
+
+ //center
+ painter->drawPixmap(QRect(rect.left() + left, rect.top()+top, rect.width() -right - left,
+ rect.height() - bottom - top), pixmap,
+ QRect(left, top, size.width() -right -left,
+ size.height() - bottom - top));
+ //right
+ if (right > 0)
+ painter->drawPixmap(QRect(rect.left() +rect.width() - right, rect.top()+top, right, rect.height() - top - bottom), pixmap,
+ QRect(size.width() - right, top, right, size.height() - bottom - top));
+
+ //bottom
+ if (bottom > 0) {
+ painter->drawPixmap(QRect(rect.left() +left, rect.top() + rect.height() - bottom,
+ rect.width() - right - left, bottom), pixmap,
+ QRect(left, size.height() - bottom,
+ size.width() - right - left, bottom));
+ //bottom-left
+ if (left > 0)
+ painter->drawPixmap(QRect(rect.left(), rect.top() + rect.height() - bottom, left, bottom), pixmap,
+ QRect(0, size.height() - bottom, left, bottom));
+
+ //bottom-right
+ if (right > 0)
+ painter->drawPixmap(QRect(rect.left() + rect.width() - right, rect.top() + rect.height() - bottom, right, bottom), pixmap,
+ QRect(size.width() - right, size.height() - bottom, right, bottom));
+
+ }
+}
+}
+QT_END_NAMESPACE
diff --git a/src/gui/styles/qstylehelper_p.h b/src/gui/styles/qstylehelper_p.h
new file mode 100644
index 0000000..ef6e66c
--- /dev/null
+++ b/src/gui/styles/qstylehelper_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qpoint.h>
+#include <QtGui/qpolygon.h>
+
+#ifndef QSTYLEHELPER_P_H
+#define QSTYLEHELPER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_NAMESPACE
+
+class QPainter;
+class QPixmap;
+class QStyleOptionSlider;
+class QStyleOption;
+
+namespace QStyleHelper
+{
+ QString uniqueName(const QString &key, const QStyleOption *option, const QSize &size);
+#ifndef QT_NO_DIAL
+ qreal angle(const QPointF &p1, const QPointF &p2);
+ QPolygonF calcLines(const QStyleOptionSlider *dial);
+ int calcBigLineSize(int radius);
+ void drawDial(const QStyleOptionSlider *dial, QPainter *painter);
+#endif //QT_NO_DIAL
+ void drawBorderPixmap(const QPixmap &pixmap, QPainter *painter, const QRect &rect,
+ int left = 0, int top = 0, int right = 0,
+ int bottom = 0);
+}
+
+QT_END_NAMESPACE
+
+#endif // QSTYLEHELPER_P_H
diff --git a/src/gui/styles/qstyleoption.cpp b/src/gui/styles/qstyleoption.cpp
index ce053ae..e441101 100644
--- a/src/gui/styles/qstyleoption.cpp
+++ b/src/gui/styles/qstyleoption.cpp
@@ -48,6 +48,7 @@
#ifndef QT_NO_DEBUG
#include <qdebug.h>
#endif
+#include <QtCore/qmath.h>
QT_BEGIN_NAMESPACE
@@ -4998,6 +4999,34 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
}
/*!
+ \since 4.6
+
+ Returns the level of detail from the \a worldTransform.
+
+ Its value represents the maximum value of the height and
+ width of a unity rectangle, mapped using the \a worldTransform
+ of the painter used to draw the item. By default, if no
+ transformations are applied, its value is 1. If zoomed out 1:2, the level
+ of detail will be 0.5, and if zoomed in 2:1, its value is 2.
+
+ For more advanced level-of-detail metrics, use
+ QStyleOptionGraphicsItem::matrix directly.
+
+ \sa QStyleOptionGraphicsItem::matrix
+*/
+qreal QStyleOptionGraphicsItem::levelOfDetailFromTransform(const QTransform &worldTransform)
+{
+ if (worldTransform.type() <= QTransform::TxTranslate)
+ return 1; // Translation only? The LOD is 1.
+
+ // Two unit vectors.
+ QLineF v1(0, 0, 1, 0);
+ QLineF v2(0, 0, 0, 1);
+ // LOD is the transformed area of a 1x1 rectangle.
+ return qSqrt(worldTransform.map(v1).length() * worldTransform.map(v2).length());
+}
+
+/*!
\fn QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other)
Constructs a copy of \a other.
@@ -5029,19 +5058,10 @@ QStyleOptionGraphicsItem::QStyleOptionGraphicsItem(int version)
/*!
\variable QStyleOptionGraphicsItem::levelOfDetail
- \brief a simple metric for determining an item's level of detail
-
- This simple metric provides an easy way to determine the level of detail
- for an item. Its value represents the maximum value of the height and
- width of a unity rectangle, mapped using the complete transformation
- matrix of the painter used to draw the item. By default, if no
- transformations are applied, its value is 1. If zoomed out 1:2, the level
- of detail will be 0.5, and if zoomed in 2:1, its value is 2.
-
- For more advanced level-of-detail metrics, use
- QStyleOptionGraphicsItem::matrix directly.
+ \obsolete
- \sa QStyleOptionGraphicsItem::matrix
+ Use QStyleOptionGraphicsItem::levelOfDetailFromTransform
+ together with QPainter::worldTransform() instead.
*/
/*!
@@ -5342,10 +5362,10 @@ QDebug operator<<(QDebug debug, const QStyleOption &option)
{
debug << "QStyleOption(";
debug << QStyleOption::OptionType(option.type);
- debug << "," << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight");
- debug << "," << option.state;
- debug << "," << option.rect;
- debug << ")";
+ debug << ',' << (option.direction == Qt::RightToLeft ? "RightToLeft" : "LeftToRight");
+ debug << ',' << option.state;
+ debug << ',' << option.rect;
+ debug << ')';
return debug;
}
#endif
diff --git a/src/gui/styles/qstyleoption.h b/src/gui/styles/qstyleoption.h
index 5759a05..eb05324 100644
--- a/src/gui/styles/qstyleoption.h
+++ b/src/gui/styles/qstyleoption.h
@@ -856,6 +856,7 @@ public:
QStyleOptionGraphicsItem();
QStyleOptionGraphicsItem(const QStyleOptionGraphicsItem &other) : QStyleOption(Version, Type) { *this = other; }
+ static qreal levelOfDetailFromTransform(const QTransform &worldTransform);
protected:
QStyleOptionGraphicsItem(int version);
};
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index bd80bb6..1bbe70e 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -81,6 +81,7 @@
#include <private/qwidget_p.h>
#include <QAbstractSpinBox>
#include <QLabel>
+#include "qdrawutil.h"
#include <limits.h>
@@ -312,15 +313,10 @@ struct QStyleSheetBorderImageData : public QSharedData
for (int i = 0; i < 4; i++)
cuts[i] = -1;
}
- QPixmap topEdge, bottomEdge, leftEdge, rightEdge, middle;
- QRect topEdgeRect, bottomEdgeRect, leftEdgeRect, rightEdgeRect, middleRect;
- QRect topLeftCorner, topRightCorner, bottomRightCorner, bottomLeftCorner;
int cuts[4];
QPixmap pixmap;
QImage image;
QCss::TileMode horizStretch, vertStretch;
-
- void cutBorderImage();
};
struct QStyleSheetBackgroundData : public QSharedData
@@ -871,7 +867,7 @@ static QStyle::StandardPixmap subControlIcon(int pe)
QRenderRule::QRenderRule(const QVector<Declaration> &declarations, const QWidget *widget)
: features(0), hasFont(false), pal(0), b(0), bg(0), bd(0), ou(0), geo(0), p(0), img(0), clipset(0)
{
- QPalette palette = qApp->palette(); // ###: ideally widget's palette
+ QPalette palette = QApplication::palette(); // ###: ideally widget's palette
ValueExtractor v(declarations, palette);
features = v.extractStyleFeatures();
@@ -1122,176 +1118,27 @@ void QRenderRule::fixupBorder(int nativeWidth)
for (int i = 0; i < 4; i++) // assume, cut = border
bi->cuts[i] = int(border()->borders[i]);
}
- bi->cutBorderImage();
-}
-
-void QStyleSheetBorderImageData::cutBorderImage()
-{
- const int w = pixmap.width();
- const int h = pixmap.height();
- const int &l = cuts[LeftEdge], &r = cuts[RightEdge],
- &t = cuts[TopEdge], &b = cuts[BottomEdge];
-
- topEdgeRect = QRect(l, 0, w - r - l, t);
- bottomEdgeRect = QRect(l, h - b, w - l - r, b);
- if (horizStretch != TileMode_Stretch) {
- if (topEdgeRect.isValid())
- topEdge = pixmap.copy(topEdgeRect).scaledToHeight(t);
- if (bottomEdgeRect.isValid())
- bottomEdge = pixmap.copy(bottomEdgeRect).scaledToHeight(b);
- }
-
- leftEdgeRect = QRect(0, t, l, h - b - t);
- rightEdgeRect = QRect(w - r, t, r, h - t- b);
- if (vertStretch != TileMode_Stretch) {
- if (leftEdgeRect.isValid())
- leftEdge = pixmap.copy(leftEdgeRect).scaledToWidth(l);
- if (rightEdgeRect.isValid())
- rightEdge = pixmap.copy(rightEdgeRect).scaledToWidth(r);
- }
-
- middleRect = QRect(l, t, w - r -l, h - t - b);
- if (middleRect.isValid()
- && !(horizStretch == TileMode_Stretch && vertStretch == TileMode_Stretch)) {
- middle = pixmap.copy(middleRect);
- }
}
-static void qDrawCenterTiledPixmap(QPainter *p, const QRectF& r, const QPixmap& pix)
-{
- p->drawTiledPixmap(r, pix, QPoint(pix.width() - int(r.width())%pix.width(),
- pix.height() - int(r.height())%pix.height()));
-}
-
-// Note: Round is not supported
void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
{
- setClip(p, rect);
- const QRectF br(rect);
- const int *borders = border()->borders;
- const int &l = borders[LeftEdge], &r = borders[RightEdge],
- &t = borders[TopEdge], &b = borders[BottomEdge];
- QRectF pr = br.adjusted(l, t, -r, -b);
+ static const Qt::TileRule tileMode2TileRule[] = {
+ Qt::Stretch, Qt::Round, Qt::Stretch, Qt::Repeat, Qt::Stretch };
+
+ const QStyleSheetBorderImageData *borderImageData = border()->borderImage();
+ const int *targetBorders = border()->borders;
+ const int *sourceBorders = borderImageData->cuts;
+ QMargins sourceMargins(sourceBorders[TopEdge], sourceBorders[LeftEdge],
+ sourceBorders[BottomEdge], sourceBorders[RightEdge]);
+ QMargins targetMargins(targetBorders[TopEdge], targetBorders[LeftEdge],
+ targetBorders[BottomEdge], targetBorders[RightEdge]);
bool wasSmoothPixmapTransform = p->renderHints() & QPainter::SmoothPixmapTransform;
p->setRenderHint(QPainter::SmoothPixmapTransform);
-
- const QStyleSheetBorderImageData *bi = border()->borderImage();
- const QPixmap& pix = bi->pixmap;
- const int *c = bi->cuts;
- QRectF tlc(0, 0, c[LeftEdge], c[TopEdge]);
- if (tlc.isValid())
- p->drawPixmap(QRectF(br.topLeft(), QSizeF(l, t)), pix, tlc);
- QRectF trc(pix.width() - c[RightEdge], 0, c[RightEdge], c[TopEdge]);
- if (trc.isValid())
- p->drawPixmap(QRectF(br.left() + br.width() - r, br.y(), r, t), pix, trc);
- QRectF blc(0, pix.height() - c[BottomEdge], c[LeftEdge], c[BottomEdge]);
- if (blc.isValid())
- p->drawPixmap(QRectF(br.x(), br.y() + br.height() - b, l, b), pix, blc);
- QRectF brc(pix.width() - c[RightEdge], pix.height() - c[BottomEdge],
- c[RightEdge], c[BottomEdge]);
- if (brc.isValid())
- p->drawPixmap(QRectF(br.x() + br.width() - r, br.y() + br.height() - b, r, b),
- pix, brc);
-
- QRectF topEdgeRect(br.x() + l, br.y(), pr.width(), t);
- QRectF bottomEdgeRect(br.x() + l, br.y() + br.height() - b, pr.width(), b);
-
- switch (bi->horizStretch) {
- case TileMode_Stretch:
- if (bi->topEdgeRect.isValid())
- p->drawPixmap(topEdgeRect, pix, bi->topEdgeRect);
- if (bi->bottomEdgeRect.isValid())
- p->drawPixmap(bottomEdgeRect, pix, bi->bottomEdgeRect);
- if (bi->middleRect.isValid()) {
- if (bi->vertStretch == TileMode_Stretch)
- p->drawPixmap(pr, pix, bi->middleRect);
- else if (bi->vertStretch == TileMode_Repeat) {
- QPixmap scaled = bi->middle.scaled(int(pr.width()), bi->middle.height());
- qDrawCenterTiledPixmap(p, pr, scaled);
- }
- }
- break;
- case TileMode_Repeat:
- if (!bi->topEdge.isNull() && !topEdgeRect.isEmpty()) {
- QPixmap scaled = bi->topEdge.scaled(bi->topEdge.width(), t);
- qDrawCenterTiledPixmap(p, topEdgeRect, scaled);
- }
- if (!bi->bottomEdge.isNull() && !bottomEdgeRect.isEmpty()) {
- QPixmap scaled = bi->bottomEdge.scaled(bi->bottomEdge.width(), b);
- qDrawCenterTiledPixmap(p, bottomEdgeRect, scaled);
- }
- if (bi->middleRect.isValid()) {
- if (bi->vertStretch == TileMode_Repeat) {
- qDrawCenterTiledPixmap(p, pr, bi->middle);
- } else if (bi->vertStretch == TileMode_Stretch) {
- QPixmap scaled = bi->middle.scaled(bi->middle.width(), int(pr.height()));
- qDrawCenterTiledPixmap(p, pr, scaled);
- }
- }
- break;
- case TileMode_Round:
- if (!bi->topEdge.isNull()) {
- int rwh = (int)pr.width()/ceil(pr.width()/bi->topEdge.width());
- QPixmap scaled = bi->topEdge.scaled(rwh, bi->topEdge.height());
- int blank = int(pr.width()) % rwh;
- p->drawTiledPixmap(QRectF(br.x() + l + blank/2, br.y(), pr.width() - blank, t),
- scaled);
- }
- if (!bi->bottomEdge.isNull()) {
- int rwh = (int) pr.width()/ceil(pr.width()/bi->bottomEdge.width());
- QPixmap scaled = bi->bottomEdge.scaled(rwh, bi->bottomEdge.height());
- int blank = int(pr.width()) % rwh;
- p->drawTiledPixmap(QRectF(br.x() + l+ blank/2, br.y()+br.height()-b,
- pr.width() - blank, b), scaled);
- }
- break;
- default:
- break;
- }
-
- QRectF leftEdgeRect(br.x(), br.y() + t, l, pr.height());
- QRectF rightEdgeRect(br.x() + br.width()- r, br.y() + t, r, pr.height());
-
- switch (bi->vertStretch) {
- case TileMode_Stretch:
- if (bi->leftEdgeRect.isValid())
- p->drawPixmap(leftEdgeRect, pix, bi->leftEdgeRect);
- if (bi->rightEdgeRect.isValid())
- p->drawPixmap(rightEdgeRect, pix, bi->rightEdgeRect);
- break;
- case TileMode_Repeat:
- if (!bi->leftEdge.isNull() && !leftEdgeRect.isEmpty()) {
- QPixmap scaled = bi->leftEdge.scaled(l, bi->leftEdge.height());
- qDrawCenterTiledPixmap(p, leftEdgeRect, scaled);
- }
- if (!bi->rightEdge.isNull() && !rightEdgeRect.isEmpty()) {
- QPixmap scaled = bi->rightEdge.scaled(r, bi->rightEdge.height());
- qDrawCenterTiledPixmap(p, rightEdgeRect, scaled);
- }
- break;
- case TileMode_Round:
- if (!bi->leftEdge.isNull()) {
- int rwh = (int) pr.height()/ceil(pr.height()/bi->leftEdge.height());
- QPixmap scaled = bi->leftEdge.scaled(bi->leftEdge.width(), rwh);
- int blank = int(pr.height()) % rwh;
- p->drawTiledPixmap(QRectF(br.x(), br.y() + t + blank/2, l, pr.height() - blank),
- scaled);
- }
- if (!bi->rightEdge.isNull()) {
- int rwh = (int) pr.height()/ceil(pr.height()/bi->rightEdge.height());
- QPixmap scaled = bi->rightEdge.scaled(bi->rightEdge.width(), rwh);
- int blank = int(pr.height()) % rwh;
- p->drawTiledPixmap(QRectF(br.x() + br.width() - r, br.y()+t+blank/2, r,
- pr.height() - blank), scaled);
- }
- break;
- default:
- break;
- }
-
+ qDrawBorderPixmap(p, rect, targetMargins, borderImageData->pixmap,
+ QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins,
+ QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch]));
p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform);
- unsetClip(p);
}
QRect QRenderRule::originRect(const QRect &rect, Origin origin) const
@@ -1525,7 +1372,7 @@ void QRenderRule::configurePalette(QPalette *p, QPalette::ColorGroup cg, const Q
/* For embedded widgets (ComboBox, SpinBox and ScrollArea) we want the embedded widget
* to be transparent when we have a transparent background or border image */
if ((hasBackground() && background()->isTransparent())
- || (hasBorder() && border()->hasBorderImage() && border()->borderImage()->middleRect.isValid()))
+ || (hasBorder() && border()->hasBorderImage() && !border()->borderImage()->pixmap.isNull()))
p->setBrush(cg, w->backgroundRole(), Qt::NoBrush);
}
@@ -1708,7 +1555,7 @@ QVector<QCss::StyleRule> QStyleSheetStyle::styleRules(const QWidget *w) const
if (widCacheIt == styleSheetCache->constEnd()) {
parser.init(wid->styleSheet());
if (!parser.parse(&ss)) {
- parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1String("}"));
+ parser.init(QLatin1String("* {") + wid->styleSheet() + QLatin1Char('}'));
if (!parser.parse(&ss))
qWarning("Could not parse stylesheet of widget %p", wid);
}
@@ -2737,7 +2584,7 @@ static void updateWidgets(const QList<const QWidget *>& widgets)
continue;
widget->style()->polish(widget);
QEvent event(QEvent::StyleChange);
- qApp->sendEvent(widget, &event);
+ QApplication::sendEvent(widget, &event);
widget->update();
widget->updateGeometry();
}
@@ -2783,9 +2630,9 @@ QStyle *QStyleSheetStyle::baseStyle() const
{
if (base)
return base;
- if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(qApp->style()))
+ if (QStyleSheetStyle *me = qobject_cast<QStyleSheetStyle *>(QApplication::style()))
return me->base;
- return qApp->style();
+ return QApplication::style();
}
void QStyleSheetStyle::widgetDestroyed(QObject *o)
@@ -2855,14 +2702,10 @@ void QStyleSheetStyle::polish(QWidget *w)
QRenderRule rule = renderRule(sa, PseudoElement_None, PseudoClass_Enabled);
if ((rule.hasBorder() && rule.border()->hasBorderImage())
|| (rule.hasBackground() && !rule.background()->pixmap.isNull())) {
- QObject::disconnect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
- QObject::disconnect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
QObject::connect(sa->horizontalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
+ sa, SLOT(update()), Qt::UniqueConnection);
QObject::connect(sa->verticalScrollBar(), SIGNAL(valueChanged(int)),
- sa, SLOT(update()));
+ sa, SLOT(update()), Qt::UniqueConnection);
}
}
#endif
@@ -2876,12 +2719,6 @@ void QStyleSheetStyle::polish(QWidget *w)
QRenderRule rule = renderRule(w, PseudoElement_None, PseudoClass_Any);
if (rule.hasDrawable() || rule.hasBox()) {
if (w->metaObject() == &QWidget::staticMetaObject
-#ifndef QT_NO_MENUBAR
- || qobject_cast<QMenuBar *>(w)
-#endif
-#ifndef QT_NO_MENU
- || qobject_cast<QMenu *>(w)
-#endif
#ifndef QT_NO_ITEMVIEWS
|| qobject_cast<QHeaderView *>(w)
#endif
@@ -3013,7 +2850,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
rule.drawBackgroundImage(p, cmbOpt.rect);
rule.configurePalette(&cmbOpt.palette, QPalette::ButtonText, QPalette::Button);
bool customDropDown = (opt->subControls & QStyle::SC_ComboBoxArrow)
- && hasStyleRule(w, PseudoElement_ComboBoxDropDown);
+ && (hasStyleRule(w, PseudoElement_ComboBoxDropDown) || hasStyleRule(w, PseudoElement_ComboBoxArrow));
if (customDropDown)
cmbOpt.subControls &= ~QStyle::SC_ComboBoxArrow;
if (rule.baseStyleCanDraw()) {
@@ -3059,11 +2896,11 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (rule.hasNativeBorder() && !upRuleMatch && !downRuleMatch) {
rule.drawBackgroundImage(p, spinOpt.rect);
customUp = (opt->subControls & QStyle::SC_SpinBoxUp)
- && hasStyleRule(w, PseudoElement_SpinBoxUpButton);
+ && (hasStyleRule(w, PseudoElement_SpinBoxUpButton) || hasStyleRule(w, PseudoElement_UpArrow));
if (customUp)
spinOpt.subControls &= ~QStyle::SC_SpinBoxUp;
customDown = (opt->subControls & QStyle::SC_SpinBoxDown)
- && hasStyleRule(w, PseudoElement_SpinBoxDownButton);
+ && (hasStyleRule(w, PseudoElement_SpinBoxDownButton) || hasStyleRule(w, PseudoElement_DownArrow));
if (customDown)
spinOpt.subControls &= ~QStyle::SC_SpinBoxDown;
if (rule.baseStyleCanDraw()) {
@@ -3189,6 +3026,7 @@ void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionC
if (const QStyleOptionToolButton *tool = qstyleoption_cast<const QStyleOptionToolButton *>(opt)) {
QStyleOptionToolButton toolOpt(*tool);
rule.configurePalette(&toolOpt.palette, QPalette::ButtonText, QPalette::Button);
+ toolOpt.font = rule.font.resolve(toolOpt.font);
toolOpt.rect = rule.borderRect(opt->rect);
bool customArrow = (tool->features & (QStyleOptionToolButton::HasMenu | QStyleOptionToolButton::MenuButtonPopup));
bool customDropDown = tool->features & QStyleOptionToolButton::MenuButtonPopup;
@@ -3735,7 +3573,7 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
mi.rect = positionRect(w, subRule, subRule2, PseudoElement_MenuRightArrow, opt->rect, mi.direction);
drawPrimitive(arrow, &mi, p, w);
}
- } else if (hasStyleRule(w, PseudoElement_MenuCheckMark)) {
+ } else if (hasStyleRule(w, PseudoElement_MenuCheckMark) || hasStyleRule(w, PseudoElement_MenuRightArrow)) {
QWindowsStyle::drawControl(ce, &mi, p, w);
} else {
if (rule.hasDrawable() && !subRule.hasDrawable() && !(opt->state & QStyle::State_Selected)) {
@@ -4164,9 +4002,8 @@ void QStyleSheetStyle::drawControl(ControlElement ce, const QStyleOption *opt, Q
rule.configurePalette(&frmOpt.palette, QPalette::Text, QPalette::Base);
frmOpt.rect = rule.borderRect(frmOpt.rect);
baseStyle()->drawControl(ce, &frmOpt, p, w);
- } else {
- rule.drawBorder(p, rule.borderRect(opt->rect));
}
+ // else, borders are already drawn in PE_Widget
}
return;
@@ -4220,12 +4057,6 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
QRect rect = opt->rect;
switch (pe) {
- case PE_PanelStatusBar:
- if (rule.hasDrawable()) {
- rule.drawRule(p, opt->rect);
- return;
- }
- break;
case PE_FrameStatusBar: {
QRenderRule subRule = renderRule(w->parentWidget(), opt, PseudoElement_Item);
@@ -4337,36 +4168,34 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
return;
case PE_Widget:
- if (!rule.hasBackground()) {
+ if (!rule.hasDrawable()) {
QWidget *container = containerWidget(w);
if (autoFillDisabledWidgets->contains(container)
- && (container == w || !renderRule(container, opt).hasBackground())) {
+ && (container == w || !renderRule(container, opt).hasDrawable())) {
//we do not have a background, but we disabled the autofillbackground anyway. so fill the background now.
// (this may happen if we have rules like :focus)
p->fillRect(opt->rect, opt->palette.brush(w->backgroundRole()));
}
break;
}
-
#ifndef QT_NO_SCROLLAREA
if (const QAbstractScrollArea *sa = qobject_cast<const QAbstractScrollArea *>(w)) {
const QAbstractScrollAreaPrivate *sap = sa->d_func();
rule.drawBackground(p, opt->rect, sap->contentsOffset());
- } else
-#endif
- {
- rule.drawBackground(p, opt->rect);
+ if (rule.hasBorder())
+ rule.drawBorder(p, rule.borderRect(opt->rect));
+ break;
}
-
- return;
-
- case PE_FrameMenu:
+#endif
+ //fall tghought
+ case PE_PanelMenu:
case PE_PanelMenuBar:
- if (!rule.hasNativeBorder()) {
- rule.drawBorder(p, rule.borderRect(opt->rect));
+ case PE_PanelStatusBar:
+ if(rule.hasDrawable()) {
+ rule.drawRule(p, opt->rect);
return;
}
- break;
+ break;
case PE_IndicatorToolBarSeparator:
case PE_IndicatorToolBarHandle: {
@@ -4510,6 +4339,16 @@ void QStyleSheetStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *op
pseudoElement = PseudoElement_ScrollAreaCorner;
break;
+ case PE_IndicatorSpinDown:
+ case PE_IndicatorSpinMinus:
+ pseudoElement = PseudoElement_SpinBoxDownArrow;
+ break;
+
+ case PE_IndicatorSpinUp:
+ case PE_IndicatorSpinPlus:
+ pseudoElement = PseudoElement_SpinBoxUpArrow;
+ break;
+
default:
break;
}
@@ -4973,13 +4812,10 @@ QSize QStyleSheetStyle::sizeFromContents(ContentsType ct, const QStyleOption *op
if ((pe == PseudoElement_MenuSeparator) && subRule.hasContentsSize()) {
return QSize(sz.width(), subRule.size().height());
} else if ((pe == PseudoElement_Item) && (subRule.hasBox() || subRule.hasBorder())) {
- int width = csz.width(), height = qMax(csz.height(), mi->fontMetrics.height());
- if (!mi->icon.isNull()) {
- int iconExtent = pixelMetric(PM_SmallIconSize);
- height = qMax(height, mi->icon.actualSize(QSize(iconExtent, iconExtent)).height());
- }
- width += mi->tabWidth;
- return subRule.boxSize(csz.expandedTo(subRule.minimumContentsSize()));
+ int width = csz.width();
+ if (mi->text.contains(QLatin1Char('\t')))
+ width += 12; //as in QCommonStyle
+ return subRule.boxSize(subRule.adjustSize(QSize(width, csz.height())));
}
}
break;
@@ -5890,13 +5726,11 @@ void QStyleSheetStyle::clearWidgetFont(QWidget* w) const
w->setProperty("_q_styleSheetWidgetFont", QVariant(QVariant::Invalid));
}
-// Returns the palette that should be used when the particular widget is focused.
-// This needs to be called by some widgets that do drawing themselves instead
-// of through the style.
-// ### This should be removed ideally by Qt 4.5, and at least by Qt 5, and fixed
-// for good by letting the style draw everything.
+// Polish palette that should be used for a particular widget, with particular states
+// (eg. :focus, :hover, ...)
+// this is called by widgets that paint themself in their paint event
// Returns true if there is a new palette in pal.
-bool QStyleSheetStyle::focusPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal)
+bool QStyleSheetStyle::styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal)
{
if (!w || !opt || !pal)
return false;
diff --git a/src/gui/styles/qstylesheetstyle_p.h b/src/gui/styles/qstylesheetstyle_p.h
index 1f61445..e057274 100644
--- a/src/gui/styles/qstylesheetstyle_p.h
+++ b/src/gui/styles/qstylesheetstyle_p.h
@@ -131,7 +131,7 @@ public:
void saveWidgetFont(QWidget* w, const QFont& font) const;
void clearWidgetFont(QWidget* w) const;
- bool focusPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal);
+ bool styleSheetPalette(const QWidget* w, const QStyleOption* opt, QPalette* pal);
protected Q_SLOTS:
QIcon standardIconImplementation(StandardPixmap standardIcon, const QStyleOption *opt = 0,
diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp
index 1c03b9e..f56d46c 100644
--- a/src/gui/styles/qwindowsmobilestyle.cpp
+++ b/src/gui/styles/qwindowsmobilestyle.cpp
@@ -72,12 +72,12 @@
#include "qdebug.h"
#include "qtabwidget.h"
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qt_windows.h"
#include "qguifunctions_wince.h"
extern bool qt_wince_is_high_dpi(); //defined in qguifunctions_wince.cpp
extern bool qt_wince_is_smartphone(); //defined in qguifunctions_wince.cpp
-#endif // Q_OS_WINCE
+#endif // Q_WS_WINCE
QT_BEGIN_NAMESPACE
@@ -685,13 +685,13 @@ QWindowsMobileStyle::QWindowsMobileStyle() : QWindowsStyle(*new QWindowsMobileSt
QWindowsMobileStylePrivate::QWindowsMobileStylePrivate() :QWindowsStylePrivate() {
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
doubleControls = qt_wince_is_high_dpi();
smartphone = qt_wince_is_smartphone();
#else
doubleControls = false;
smartphone = false;
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
#ifndef QT_NO_IMAGEFORMAT_XPM
diff --git a/src/gui/styles/qwindowsstyle.cpp b/src/gui/styles/qwindowsstyle.cpp
index 00c3f99..c816907 100644
--- a/src/gui/styles/qwindowsstyle.cpp
+++ b/src/gui/styles/qwindowsstyle.cpp
@@ -67,6 +67,9 @@
#include "qpixmapcache.h"
#include "qwizard.h"
#include "qlistview.h"
+#include <private/qmath_p.h>
+#include <qmath.h>
+
#ifdef Q_WS_X11
#include "qfileinfo.h"
@@ -301,7 +304,7 @@ void QWindowsStyle::polish(QApplication *app)
QCommonStyle::polish(app);
QWindowsStylePrivate *d = const_cast<QWindowsStylePrivate*>(d_func());
// We only need the overhead when shortcuts are sometimes hidden
- if (!styleHint(SH_UnderlineShortcut, 0) && app)
+ if (!proxy()->styleHint(SH_UnderlineShortcut, 0) && app)
app->installEventFilter(this);
d->activeCaptionColor = app->palette().highlight().color();
@@ -424,7 +427,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
int thick = 6; // Magic constant to get 5 + 16 + 5
if (ticks != QSlider::TicksBothSides && ticks != QSlider::NoTicks)
- thick += pixelMetric(PM_SliderLength, sl, widget) / 4;
+ thick += proxy()->pixelMetric(PM_SliderLength, sl, widget) / 4;
space -= thick;
if (space > 0)
@@ -458,7 +461,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
break;
case PM_IconViewIconSize:
- ret = pixelMetric(PM_LargeIconSize, opt, widget);
+ ret = proxy()->pixelMetric(PM_LargeIconSize, opt, widget);
break;
case PM_ToolBarIconSize:
@@ -1420,8 +1423,8 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
int bsy = 0;
if (opt->state & State_Sunken) {
- bsx = pixelMetric(PM_ButtonShiftHorizontal, opt, w);
- bsy = pixelMetric(PM_ButtonShiftVertical, opt, w);
+ bsx = proxy()->pixelMetric(PM_ButtonShiftHorizontal, opt, w);
+ bsy = proxy()->pixelMetric(PM_ButtonShiftVertical, opt, w);
}
QRect bounds = a.boundingRect();
@@ -1510,7 +1513,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
case PE_FrameFocusRect:
if (const QStyleOptionFocusRect *fropt = qstyleoption_cast<const QStyleOptionFocusRect *>(opt)) {
//### check for d->alt_down
- if (!(fropt->state & State_KeyboardFocusChange) && !styleHint(SH_UnderlineShortcut, opt))
+ if (!(fropt->state & State_KeyboardFocusChange) && !proxy()->styleHint(SH_UnderlineShortcut, opt))
return;
QRect r = opt->rect;
p->save();
@@ -1577,8 +1580,8 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
//center when rect is larger than indicator size
int xOffset = 0;
int yOffset = 0;
- int indicatorWidth = pixelMetric(PM_ExclusiveIndicatorWidth);
- int indicatorHeight = pixelMetric(PM_ExclusiveIndicatorWidth);
+ int indicatorWidth = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth);
+ int indicatorHeight = proxy()->pixelMetric(PM_ExclusiveIndicatorWidth);
if (ir.width() > indicatorWidth)
xOffset += (ir.width() - indicatorWidth)/2;
if (ir.height() > indicatorHeight)
@@ -1735,7 +1738,7 @@ void QWindowsStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt,
break; }
case PE_FrameDockWidget:
if (qstyleoption_cast<const QStyleOptionFrame *>(opt)) {
- drawPrimitive(QStyle::PE_FrameWindow, opt, p, w);
+ proxy()->drawPrimitive(QStyle::PE_FrameWindow, opt, p, w);
}
break;
#endif // QT_NO_DOCKWIDGET
@@ -1754,7 +1757,7 @@ case PE_FrameDockWidget:
}
int space = 2;
- int chunksize = pixelMetric(PM_ProgressBarChunkWidth, opt, w) - space;
+ int chunksize = proxy()->pixelMetric(PM_ProgressBarChunkWidth, opt, w) - space;
if (!vertical) {
if (opt->rect.width() <= chunksize)
space = 0;
@@ -1813,7 +1816,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->save();
QRect r = opt->rect;
QStyleHintReturnMask mask;
- if (styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
+ if (proxy()->styleHint(QStyle::SH_RubberBand_Mask, opt, widget, &mask))
p->setClipRegion(mask.region);
p->drawTiledPixmap(r.x(), r.y(), r.width(), r.height(), tiledPixmap);
p->restore();
@@ -1882,9 +1885,9 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
mode = QIcon::Active;
QPixmap pixmap;
if (checked)
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode, QIcon::On);
else
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, opt, widget), mode);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, opt, widget), mode);
int pixw = pixmap.width();
int pixh = pixmap.height();
if (act && !dis && !checked)
@@ -1903,7 +1906,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
newMi.state |= State_On;
newMi.rect = visualRect(opt->direction, menuitem->rect, QRect(menuitem->rect.x() + windowsItemFrame, menuitem->rect.y() + windowsItemFrame,
checkcol - 2 * windowsItemFrame, menuitem->rect.height() - 2*windowsItemFrame));
- drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
}
p->setPen(act ? menuitem->palette.highlightedText().color() : menuitem->palette.buttonText().color());
@@ -1922,13 +1925,13 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
p->save();
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
text_flags |= Qt::AlignLeft;
if (t >= 0) {
QRect vShortcutRect = visualRect(opt->direction, menuitem->rect,
QRect(textRect.topRight(), QPoint(menuitem->rect.right(), textRect.bottom())));
- if (dis && !act && styleHint(SH_EtchDisabledText, opt, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1));
p->setPen(discol);
@@ -1940,7 +1943,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
font.setBold(true);
p->setFont(font);
- if (dis && !act && styleHint(SH_EtchDisabledText, opt, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, opt, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t));
p->setPen(discol);
@@ -1960,7 +1963,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
if (act)
newMI.palette.setColor(QPalette::ButtonText,
newMI.palette.highlightedText().color());
- drawPrimitive(arrow, &newMI, p, widget);
+ proxy()->drawPrimitive(arrow, &newMI, p, widget);
}
}
@@ -1982,8 +1985,8 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
qDrawShadeRect(p, mbi->rect.x(), mbi->rect.y(), mbi->rect.width(),
mbi->rect.height(), mbi->palette, active && down, 1, 0, &b);
if (active && down) {
- newMbi.rect.translate(pixelMetric(PM_ButtonShiftHorizontal, mbi, widget),
- pixelMetric(PM_ButtonShiftVertical, mbi, widget));
+ newMbi.rect.translate(proxy()->pixelMetric(PM_ButtonShiftHorizontal, mbi, widget),
+ proxy()->pixelMetric(PM_ButtonShiftVertical, mbi, widget));
p->setBrushOrigin(p->brushOrigin() - QPoint(1, 1));
}
}
@@ -2017,7 +2020,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
|| (rtlHorTabs
&& tab->selectedPosition
== QStyleOptionTab::PreviousIsSelected));
- int tabBarAlignment = styleHint(SH_TabBar_Alignment, tab, widget);
+ int tabBarAlignment = proxy()->styleHint(SH_TabBar_Alignment, tab, widget);
bool leftAligned = (!rtlHorTabs && tabBarAlignment == Qt::AlignLeft)
|| (rtlHorTabs
&& tabBarAlignment == Qt::AlignRight);
@@ -2031,7 +2034,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
QColor dark = tab->palette.dark().color();
QColor shadow = tab->palette.shadow().color();
QColor background = tab->palette.background().color();
- int borderThinkness = pixelMetric(PM_TabBarBaseOverlap, tab, widget);
+ int borderThinkness = proxy()->pixelMetric(PM_TabBarBaseOverlap, tab, widget);
if (selected)
borderThinkness /= 2;
QRect r2(opt->rect);
@@ -2263,7 +2266,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
}
QStyleOption arrowOpt = *opt;
arrowOpt.rect = opt->rect.adjusted(4, 4, -4, -4);
- drawPrimitive(arrow, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(arrow, &arrowOpt, p, widget);
break; }
case CE_ScrollBarAddPage:
case CE_ScrollBarSubPage: {
@@ -2449,7 +2452,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
int w = rect.width();
if (pb->minimum == 0 && pb->maximum == 0) {
Q_D(const QWindowsStyle);
- const int unit_width = pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
+ const int unit_width = proxy()->pixelMetric(PM_ProgressBarChunkWidth, pb, widget);
QStyleOptionProgressBarV2 pbBits = *pb;
Q_ASSERT(unit_width >0);
@@ -2473,7 +2476,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
for (int i = 0; i < chunksToDraw ; ++i) {
pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
x += reverse ? -unit_width : unit_width;
}
//Draw wrap-around chunks
@@ -2484,7 +2487,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
for (int i = 0; i < chunksToDraw ; ++i) {
pbBits.rect.setRect(x0 + x, myY, unit_width, myHeight);
pbBits.rect = m.mapRect(QRectF(pbBits.rect)).toRect();
- drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorProgressChunk, &pbBits, p, widget);
x += reverse ? -unit_width : unit_width;
}
}
@@ -2572,7 +2575,7 @@ void QWindowsStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPai
r.top() + titleRect.left() - rect.left(),
titleRect.height(), titleRect.width());
}
- drawItemText(p, titleRect,
+ proxy()->drawItemText(p, titleRect,
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextShowMnemonic, palette,
dwOpt->state & State_Enabled, dwOpt->title,
floating ? (active ? QPalette::BrightText : QPalette::Window) : QPalette::WindowText);
@@ -2602,7 +2605,7 @@ QRect QWindowsStyle::subElementRect(SubElement sr, const QStyleOption *opt, cons
const QStyleOptionDockWidgetV2 *v2
= qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt);
bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar;
- int m = pixelMetric(PM_DockWidgetTitleMargin, opt, w);
+ int m = proxy()->pixelMetric(PM_DockWidgetTitleMargin, opt, w);
if (verticalTitleBar) {
r.adjust(0, 0, 0, -m);
} else {
@@ -2636,11 +2639,11 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
#ifndef QT_NO_SLIDER
case CC_Slider:
if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider *>(opt)) {
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
int ticks = slider->tickPosition;
- QRect groove = subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
- QRect handle = subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
+ QRect groove = proxy()->subControlRect(CC_Slider, slider, SC_SliderGroove, widget);
+ QRect handle = proxy()->subControlRect(CC_Slider, slider, SC_SliderHandle, widget);
if ((slider->subControls & SC_SliderGroove) && groove.isValid()) {
int mid = thickness / 2;
@@ -2711,7 +2714,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
if ((tickAbove && tickBelow) || (!tickAbove && !tickBelow)) {
@@ -3034,7 +3037,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
if (cmb->subControls & SC_ComboBoxArrow) {
State flags = State_None;
- QRect ar = subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
+ QRect ar = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxArrow, widget);
bool sunkenArrow = cmb->activeSubControls == SC_ComboBoxArrow
&& cmb->state & State_Sunken;
if (sunkenArrow) {
@@ -3060,11 +3063,11 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
arrowOpt.rect = ar.adjusted(1, 1, -1, -1);
arrowOpt.palette = cmb->palette;
arrowOpt.state = flags;
- drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &arrowOpt, p, widget);
}
if (cmb->subControls & SC_ComboBoxEditField) {
- QRect re = subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
+ QRect re = proxy()->subControlRect(CC_ComboBox, cmb, SC_ComboBoxEditField, widget);
if (cmb->state & State_HasFocus && !cmb->editable)
p->fillRect(re.x(), re.y(), re.width(), re.height(),
cmb->palette.brush(QPalette::Highlight));
@@ -3084,7 +3087,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
focus.rect = subElementRect(SE_ComboBoxFocusRect, cmb, widget);
focus.state |= State_FocusAtBorder;
focus.backgroundColor = cmb->palette.highlight().color();
- drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &focus, p, widget);
}
}
}
@@ -3098,7 +3101,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
bool enabled = opt->state & State_Enabled;
if (sb->frame && (sb->subControls & SC_SpinBoxFrame)) {
QBrush editBrush = sb->palette.brush(QPalette::Base);
- QRect r = subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
+ QRect r = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxFrame, widget);
QPalette shadePal = sb->palette;
if (use2000style)
shadePal.setColor(QPalette::Midlight, shadePal.button().color());
@@ -3129,7 +3132,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinPlus
: PE_IndicatorSpinUp);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxUp, widget);
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 1, -5, -1);
@@ -3137,9 +3140,9 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
- drawPrimitive(pe, &lightCopy, p, widget);
+ proxy()->drawPrimitive(pe, &lightCopy, p, widget);
}
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
if (sb->subControls & SC_SpinBoxDown) {
@@ -3162,7 +3165,7 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
pe = (sb->buttonSymbols == QAbstractSpinBox::PlusMinus ? PE_IndicatorSpinMinus
: PE_IndicatorSpinDown);
- copy.rect = subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
+ copy.rect = proxy()->subControlRect(CC_SpinBox, sb, SC_SpinBoxDown, widget);
qDrawWinButton(p, copy.rect, shadePal, copy.state & (State_Sunken | State_On),
&copy.palette.brush(QPalette::Button));
copy.rect.adjust(4, 0, -5, -1);
@@ -3170,13 +3173,14 @@ void QWindowsStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComp
QStyleOptionSpinBox lightCopy = copy;
lightCopy.rect.adjust(1, 1, 1, 1);
lightCopy.palette.setBrush(QPalette::ButtonText, copy.palette.light());
- drawPrimitive(pe, &lightCopy, p, widget);
+ proxy()->drawPrimitive(pe, &lightCopy, p, widget);
}
- drawPrimitive(pe, &copy, p, widget);
+ proxy()->drawPrimitive(pe, &copy, p, widget);
}
}
break;
#endif // QT_NO_SPINBOX
+
default:
QCommonStyle::drawComplexControl(cc, opt, p, widget);
}
@@ -3195,7 +3199,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
h = sz.height();
int defwidth = 0;
if (btn->features & QStyleOptionButton::AutoDefaultButton)
- defwidth = 2 * pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
+ defwidth = 2 * proxy()->pixelMetric(PM_ButtonDefaultIndicator, btn, widget);
#ifndef QT_QWS_SMALL_PUSHBUTTON
if (w < 75 + defwidth && !btn->text.isEmpty())
w = 75 + defwidth;
@@ -3220,7 +3224,7 @@ QSize QWindowsStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt,
}
if (mi->menuItemType != QStyleOptionMenuItem::Separator && !mi->icon.isNull()) {
- int iconExtent = pixelMetric(PM_SmallIconSize, opt, widget);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize, opt, widget);
sz.setHeight(qMax(sz.height(),
mi->icon.actualSize(QSize(iconExtent, iconExtent)).height()
+ 2 * windowsItemFrame));
@@ -3380,7 +3384,7 @@ QIcon QWindowsStyle::standardIconImplementation(StandardPixmap standardIcon, con
&& QSysInfo::WindowsVersion < QSysInfo::WV_NT_based
&& pSHGetStockIconInfo)
{
- icon.addPixmap(standardPixmap(SP_VistaShield, option, widget)); //fetches small icon
+ icon.addPixmap(proxy()->standardPixmap(SP_VistaShield, option, widget)); //fetches small icon
QSHSTOCKICONINFO iconInfo; //append large icon
memset(&iconInfo, 0, sizeof(iconInfo));
iconInfo.cbSize = sizeof(iconInfo);
diff --git a/src/gui/styles/qwindowsvistastyle.cpp b/src/gui/styles/qwindowsvistastyle.cpp
index 013ca1e..be76b24 100644
--- a/src/gui/styles/qwindowsvistastyle.cpp
+++ b/src/gui/styles/qwindowsvistastyle.cpp
@@ -403,7 +403,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
// pulsating default button into the intended target state.
if (!anim)
- drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
+ proxy()->drawPrimitive(element, &opt, &startPainter, 0); // Note that the widget pointer is intentionally 0
else // this ensures that we do not recurse in the animation logic above
anim->paint(&startPainter, &opt);
@@ -417,7 +417,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
endImage.fill(0);
QStyleOption opt2 = opt;
opt2.state = option->state;
- drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
+ proxy()->drawPrimitive(element, &opt2, &endPainter, 0); // Note that the widget pointer is intentionally 0
// this ensures that we do not recurse in the animation logic above
t->setEndImage(endImage);
@@ -645,7 +645,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
}
}
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, painter, widget);
return;
}
break;
@@ -934,7 +934,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QPainter startPainter(&startImage);
if (!anim) {
- drawControl(element, &opt, &startPainter, 0 /* Intentional */);
+ proxy()->drawControl(element, &opt, &startPainter, 0 /* Intentional */);
} else {
anim->paint(&startPainter, &opt);
d->stopAnimation(widget);
@@ -945,7 +945,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
endImage.fill(0);
QPainter endPainter(&endImage);
- drawControl(element, option, &endPainter, 0 /* Intentional */);
+ proxy()->drawControl(element, option, &endPainter, 0 /* Intentional */);
t->setEndImage(endImage);
int duration = 0;
HTHEME theme = pOpenThemeData(0, L"Button");
@@ -1049,7 +1049,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
newBtn.rect = QStyle::visualRect(option->direction, option->rect,
QRect(ir.right() - mbiw - 2, (option->rect.height()/2) - (mbih/2),
mbiw + 1, mbih + 1));
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, painter, widget);
}
return;
}
@@ -1197,10 +1197,10 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
break;
QPalette::ColorRole textRole = disabled ? QPalette::Text : QPalette::ButtonText;
- QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
+ QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
//The rect adjustment is a workaround for the menu not really filling its background.
@@ -1292,9 +1292,9 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
mode = QIcon::Active;
QPixmap pixmap;
if (checked)
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On);
else
- pixmap = menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode);
+ pixmap = menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
int pixw = pixmap.width();
int pixh = pixmap.height();
QRect pmr(0, 0, pixw, pixh);
@@ -1320,7 +1320,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
painter->save();
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
text_flags |= Qt::AlignLeft;
if (t >= 0) {
@@ -1346,7 +1346,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
QStyleOptionMenuItem newMI = *menuitem;
newMI.rect = vSubMenuRect;
newMI.state = dis ? State_None : State_Enabled;
- drawPrimitive(arrow, &newMI, painter, widget);
+ proxy()->drawPrimitive(arrow, &newMI, painter, widget);
}
}
break;
@@ -1416,8 +1416,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
painter->drawRect(rect.adjusted(0, 1, -1, -3));
int buttonMargin = 4;
- int mw = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
- int fw = pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
+ int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
+ int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
const QDockWidget *dw = qobject_cast<const QDockWidget *>(widget);
bool isFloating = dw != 0 && dw->isFloating();
@@ -1436,7 +1436,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (isFloating) {
titleRect.adjust(0, -fw, 0, 0);
- if (widget != 0 && widget->windowIcon().cacheKey() != qApp->windowIcon().cacheKey())
+ if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
} else {
titleRect.adjust(mw, 0, 0, 0);
@@ -1556,7 +1556,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
if (qstyleoption_cast<const QStyleOptionSlider *>(option)) {
QRect oldSliderPos = w->property("_q_stylesliderpos").toRect();
- QRect currentPos = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ QRect currentPos = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
w->setProperty("_q_stylesliderpos", currentPos);
if (oldSliderPos != currentPos) {
doTransition = false;
@@ -1587,7 +1587,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
QStyleOptionComboBox startCombo = *combo;
startCombo.state = (QStyle::State)oldState;
startCombo.activeSubControls = (QStyle::SubControl)oldActiveControls;
- drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
+ proxy()->drawComplexControl(control, &startCombo, &startPainter, 0 /* Intentional */);
t->setStartImage(startImage);
} else if (const QStyleOptionSlider *slider = qstyleoption_cast<const QStyleOptionSlider*>(option)) {
//This is a workaround for the direct3d engine as it currently has some issues with grabWindow
@@ -1596,7 +1596,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
QStyleOptionSlider startSlider = *slider;
startSlider.state = (QStyle::State)oldState;
startSlider.activeSubControls = (QStyle::SubControl)oldActiveControls;
- drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
+ proxy()->drawComplexControl(control, &startSlider, &startPainter, 0 /* Intentional */);
t->setStartImage(startImage);
} else {
QPoint offset(0, 0);
@@ -1614,7 +1614,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->startAnimation(t);
endImage.fill(0);
QPainter endPainter(&endImage);
- drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
+ proxy()->drawComplexControl(control, option, &endPainter, 0 /* Intentional */);
t->setEndImage(endImage);
t->setStartTime(QTime::currentTime());
@@ -1653,9 +1653,9 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ComboBoxArrow) {
- QRect subRect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ QRect subRect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
XPThemeData theme(widget, painter, QLatin1String("COMBOBOX"));
- theme.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
partId = option->direction == Qt::RightToLeft ? CP_DROPDOWNBUTTONLEFT : CP_DROPDOWNBUTTONRIGHT;
if (!(cmb->state & State_Enabled))
@@ -1679,7 +1679,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
btn.rect = option->rect.adjusted(-1, -1, 1, 1);
if (sub & SC_ComboBoxArrow)
btn.features = QStyleOptionButton::HasMenu;
- drawControl(QStyle::CE_PushButton, &btn, painter, widget);
+ proxy()->drawControl(QStyle::CE_PushButton, &btn, painter, widget);
}
}
}
@@ -1696,7 +1696,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
bool isHorz = flags & State_Horizontal;
bool isRTL = option->direction == Qt::RightToLeft;
if (sub & SC_ScrollBarAddLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
@@ -1713,7 +1713,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSubLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
@@ -1730,9 +1730,9 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (maxedOut) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
stateId = SCRBS_DISABLED;
theme.partId = partId;
@@ -1740,7 +1740,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
} else {
if (sub & SC_ScrollBarSubPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -1755,7 +1755,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ScrollBarAddPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -1770,7 +1770,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSlider) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
@@ -1783,7 +1783,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
stateId = SCRBS_NORMAL;
// Draw handle
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
theme.stateId = stateId;
d->drawBackground(theme);
@@ -1851,7 +1851,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(ftheme);
}
if (sub & SC_SpinBoxUp) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget).adjusted(0, 0, 0, 1);
partId = SPNP_UP;
if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
stateId = UPS_DISABLED;
@@ -1866,7 +1866,7 @@ void QWindowsVistaStyle::drawComplexControl(ComplexControl control, const QStyle
d->drawBackground(theme);
}
if (sub & SC_SpinBoxDown) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
partId = SPNP_DOWN;
if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
stateId = DNS_DISABLED;
@@ -1947,7 +1947,7 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption
{
//Spinbox adds frame twice
sz = QWindowsStyle::sizeFromContents(type, option, size, widget);
- int border = pixelMetric(PM_SpinBoxFrameWidth, option, widget);
+ int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
sz -= QSize(2*border, 2*border);
}
return sz;
@@ -1985,7 +1985,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
else
stateId = PBS_NORMAL;
- int border = pixelMetric(PM_DefaultFrameWidth, btn, widget);
+ int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
rect = option->rect.adjusted(border, border, -border, -border);
int result = pGetThemeMargins(theme,
@@ -2012,7 +2012,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
int w = option->rect.width();
int x = option->rect.x();
int y = option->rect.y();
- int margin = pixelMetric(QStyle::PM_HeaderMargin, option, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
XPThemeData theme(widget, 0, QLatin1String("HEADER"), HP_HEADERSORTARROW, HSAS_SORTEDDOWN, option->rect);
@@ -2038,7 +2038,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
case SE_HeaderLabel:
{
- int margin = pixelMetric(QStyle::PM_HeaderMargin, option, widget);
+ int margin = proxy()->pixelMetric(QStyle::PM_HeaderMargin, option, widget);
QRect r = option->rect;
r.setRect(option->rect.x() + margin, option->rect.y() + margin,
option->rect.width() - margin * 2, option->rect.height() - margin * 2);
@@ -2214,7 +2214,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
const int width = tb->rect.width();
int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
- const int frameWidth = pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
+ const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
@@ -2251,7 +2251,7 @@ QRect QWindowsVistaStyle::subControlRect(ComplexControl control, const QStyleOpt
{
const int controlTop = 6;
const int controlHeight = height - controlTop - 3;
- int iconExtent = pixelMetric(PM_SmallIconSize);
+ int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
iconSize = QSize(controlHeight, controlHeight);
@@ -2435,7 +2435,7 @@ void QWindowsVistaStyle::unpolish(QWidget *widget)
else if (QTreeView *tree = qobject_cast<QTreeView *> (widget)) {
tree->viewport()->setAttribute(Qt::WA_Hover, false);
} else if (qobject_cast<QCommandLinkButton*>(widget)) {
- QFont font = qApp->font("QCommandLinkButton");
+ QFont font = QApplication::font("QCommandLinkButton");
QFont widgetFont = widget->font();
widgetFont.setFamily(font.family()); //Only family set by polish
widget->setFont(widgetFont);
diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp
index 2f4254e..c8a4441 100644
--- a/src/gui/styles/qwindowsxpstyle.cpp
+++ b/src/gui/styles/qwindowsxpstyle.cpp
@@ -46,6 +46,7 @@
#include <private/qobject_p.h>
#include <private/qpaintengine_raster_p.h>
#include <private/qapplication_p.h>
+#include <private/qstylehelper_p.h>
#include <qlibrary.h>
#include <qpainter.h>
#include <qpaintengine.h>
@@ -260,7 +261,7 @@ void QWindowsXPStylePrivate::cleanup(bool force)
use_xp = false;
cleanupHandleMap();
if (limboWidget) {
- if (qApp->closingDown())
+ if (QApplication::closingDown())
delete limboWidget;
else
limboWidget->deleteLater();
@@ -1025,7 +1026,7 @@ void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
Most of the functions are documented in the base classes
QWindowsStyle, QCommonStyle, and QStyle, but the
QWindowsXPStyle overloads of drawComplexControl(), drawControl(),
- drawControlMask(), drawPrimitive(), subControlRect(), and
+ drawControlMask(), drawPrimitive(), proxy()->subControlRect(), and
sizeFromContents(), are documented here.
\img qwindowsxpstyle.png
@@ -1192,8 +1193,8 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option,
QStyleOptionTab otherOption;
otherOption.shape = (twfOption->shape == QTabBar::RoundedNorth
? QTabBar::RoundedEast : QTabBar::RoundedSouth);
- int overlap = pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget);
- int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget);
+ int overlap = proxy()->pixelMetric(PM_TabBarBaseOverlap, &otherOption, widget);
+ int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
rect.adjust(-overlap + borderThickness, 0, -overlap + borderThickness, 0);
}
break;}
@@ -1216,7 +1217,7 @@ QRect QWindowsXPStyle::subElementRect(SubElement sr, const QStyleOption *option,
else
stateId = PBS_NORMAL;
- int border = pixelMetric(PM_DefaultFrameWidth, btn, widget);
+ int border = proxy()->pixelMetric(PM_DefaultFrameWidth, btn, widget);
rect = option->rect.adjusted(border, border, -border, -border);
int result = pGetThemeMargins(theme,
@@ -1532,7 +1533,7 @@ case PE_Frame:
}
if (panel->lineWidth > 0)
- drawPrimitive(PE_FrameLineEdit, panel, p, widget);
+ proxy()->drawPrimitive(PE_FrameLineEdit, panel, p, widget);
return;
}
break;
@@ -1617,7 +1618,7 @@ case PE_Frame:
else
stateId = FS_INACTIVE;
- int fwidth = pixelMetric(PM_DockWidgetFrameWidth, frm, widget);
+ int fwidth = proxy()->pixelMetric(PM_DockWidgetFrameWidth, frm, widget);
XPThemeData theme(widget, p, name, 0, stateId);
if (!theme.isValid())
@@ -1791,7 +1792,12 @@ case PE_Frame:
return;
case PE_IndicatorToolBarSeparator:
-
+ if (option->rect.height() < 3) {
+ // XP style requires a few pixels for the separator
+ // to be visible.
+ QWindowsStyle::drawPrimitive(pe, option, p, widget);
+ return;
+ }
name = QLatin1String("TOOLBAR");
partId = TP_SEPARATOR;
@@ -1820,7 +1826,7 @@ case PE_Frame:
QStyleOptionButton button;
button.QStyleOption::operator=(*option);
button.state &= ~State_MouseOver;
- drawPrimitive(PE_IndicatorCheckBox, &button, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorCheckBox, &button, p, widget);
return;
}
@@ -1948,7 +1954,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QRect ir = btn->rect;
QStyleOptionButton newBtn = *btn;
newBtn.rect = QRect(ir.right() - mbiw - 1, 1 + (ir.height()/2) - (mbih/2), mbiw, mbih);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
return;
}
@@ -1971,10 +1977,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
bool lastTab = tab->position == QStyleOptionTab::End;
bool firstTab = tab->position == QStyleOptionTab::Beginning;
bool onlyOne = tab->position == QStyleOptionTab::OnlyOneTab;
- bool leftAligned = styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft;
- bool centerAligned = styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter;
- int borderThickness = pixelMetric(PM_DefaultFrameWidth, option, widget);
- int tabOverlap = pixelMetric(PM_TabBarTabOverlap, option, widget);
+ bool leftAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignLeft;
+ bool centerAligned = proxy()->styleHint(SH_TabBar_Alignment, tab, widget) == Qt::AlignCenter;
+ int borderThickness = proxy()->pixelMetric(PM_DefaultFrameWidth, option, widget);
+ int tabOverlap = proxy()->pixelMetric(PM_TabBarTabOverlap, option, widget);
if (isDisabled)
stateId = TIS_DISABLED;
@@ -2119,8 +2125,8 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
if (act && !dis)
mode = QIcon::Active;
QPixmap pixmap = checked ?
- menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) :
- menuitem->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), mode);
+ menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode, QIcon::On) :
+ menuitem->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), mode);
int pixw = pixmap.width();
int pixh = pixmap.height();
QRect iconRect(0, 0, pixw, pixh);
@@ -2146,7 +2152,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
checkcol - 2 * windowsItemFrame,
menuitem->rect.height() - 2*windowsItemFrame);
newMi.rect = visualRect(option->direction, option->rect, checkMarkRect);
- drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorMenuCheckMark, &newMi, p, widget);
}
QColor textColor = dis ? menuitem->palette.text().color() :
@@ -2163,12 +2169,12 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
p->save();
int t = s.indexOf(QLatin1Char('\t'));
int text_flags = Qt::AlignVCenter|Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine | Qt::AlignLeft;
- if (!styleHint(SH_UnderlineShortcut, menuitem, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, menuitem, widget))
text_flags |= Qt::TextHideMnemonic;
// draw tab text ----------------
if (t >= 0) {
QRect vShortcutRect = visualRect(option->direction, option->rect, QRect(textRect.topRight(), menuitem->rect.bottomRight()));
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vShortcutRect.adjusted(1,1,1,1), text_flags, s.mid(t + 1));
p->setPen(textColor);
@@ -2180,7 +2186,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
if (menuitem->menuItemType == QStyleOptionMenuItem::DefaultItem)
font.setBold(true);
p->setFont(font);
- if (dis && !act && styleHint(SH_EtchDisabledText, option, widget)) {
+ if (dis && !act && proxy()->styleHint(SH_EtchDisabledText, option, widget)) {
p->setPen(menuitem->palette.light().color());
p->drawText(vTextRect.adjusted(1,1,1,1), text_flags, s.left(t));
p->setPen(textColor);
@@ -2201,7 +2207,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
newMI.state = dis ? State_None : State_Enabled;
if (act)
newMI.palette.setColor(QPalette::ButtonText, newMI.palette.highlightedText().color());
- drawPrimitive(arrow, &newMI, p, widget);
+ proxy()->drawPrimitive(arrow, &newMI, p, widget);
}
}
return;
@@ -2218,10 +2224,10 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QBrush fill = mbi->palette.brush(act ? QPalette::Highlight : QPalette::Button);
QPalette::ColorRole textRole = dis ? QPalette::Text:
act ? QPalette::HighlightedText : QPalette::ButtonText;
- QPixmap pix = mbi->icon.pixmap(pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
+ QPixmap pix = mbi->icon.pixmap(proxy()->pixelMetric(PM_SmallIconSize, option, widget), QIcon::Normal);
uint alignment = Qt::AlignCenter | Qt::TextShowMnemonic | Qt::TextDontClip | Qt::TextSingleLine;
- if (!styleHint(SH_UnderlineShortcut, mbi, widget))
+ if (!proxy()->styleHint(SH_UnderlineShortcut, mbi, widget))
alignment |= Qt::TextHideMnemonic;
p->fillRect(rect, fill);
@@ -2236,8 +2242,8 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
if (const QStyleOptionDockWidget *dwOpt = qstyleoption_cast<const QStyleOptionDockWidget *>(option))
{
int buttonMargin = 4;
- int mw = pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
- int fw = pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
+ int mw = proxy()->pixelMetric(QStyle::PM_DockWidgetTitleMargin, dwOpt, widget);
+ int fw = proxy()->pixelMetric(PM_DockWidgetFrameWidth, dwOpt, widget);
bool isFloating = widget && widget->isWindow();
bool isActive = dwOpt->state & State_Active;
@@ -2258,18 +2264,18 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
QRect titleRect = r;
if (dwOpt->closable) {
- QSize sz = standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
+ QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarCloseButton, dwOpt, widget).actualSize(QSize(10, 10));
titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
}
if (dwOpt->floatable) {
- QSize sz = standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
+ QSize sz = proxy()->standardIcon(QStyle::SP_TitleBarMaxButton, dwOpt, widget).actualSize(QSize(10, 10));
titleRect.adjust(0, 0, -sz.width() - mw - buttonMargin, 0);
}
if (isFloating) {
titleRect.adjust(0, -fw, 0, 0);
- if (widget != 0 && widget->windowIcon().cacheKey() != qApp->windowIcon().cacheKey())
+ if (widget != 0 && widget->windowIcon().cacheKey() != QApplication::windowIcon().cacheKey())
titleRect.adjust(titleRect.height() + mw, 0, 0, 0);
} else {
titleRect.adjust(mw, 0, 0, 0);
@@ -2316,7 +2322,7 @@ void QWindowsXPStyle::drawControl(ControlElement element, const QStyleOption *op
// Figure out maximal button space on title bar
QIcon ico = widget->windowIcon();
- bool hasIcon = (ico.cacheKey() != qApp->windowIcon().cacheKey());
+ bool hasIcon = (ico.cacheKey() != QApplication::windowIcon().cacheKey());
if (hasIcon) {
QPixmap pxIco = ico.pixmap(titleHeight);
if (!verticalTitleBar && QApplication::layoutDirection() == Qt::RightToLeft)
@@ -2449,7 +2455,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(ftheme);
}
if (sub & SC_SpinBoxUp) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxUp, widget);
partId = SPNP_UP;
if (!(sb->stepEnabled & QAbstractSpinBox::StepUpEnabled) || !(flags & State_Enabled))
stateId = UPS_DISABLED;
@@ -2464,7 +2470,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_SpinBoxDown) {
- theme.rect = subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
+ theme.rect = proxy()->subControlRect(CC_SpinBox, option, SC_SpinBoxDown, widget);
partId = SPNP_DOWN;
if (!(sb->stepEnabled & QAbstractSpinBox::StepDownEnabled) || !(flags & State_Enabled))
stateId = DNS_DISABLED;
@@ -2501,7 +2507,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
p->fillRect(option->rect, editBrush);
}
if (!cmb->editable) {
- QRect re = subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
+ QRect re = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxEditField, widget);
if (option->state & State_HasFocus) {
p->fillRect(re, option->palette.highlight());
p->setPen(option->palette.highlightedText().color());
@@ -2516,7 +2522,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (sub & SC_ComboBoxArrow) {
XPThemeData theme(widget, p, QLatin1String("COMBOBOX"));
- theme.rect = subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
+ theme.rect = proxy()->subControlRect(CC_ComboBox, option, SC_ComboBoxArrow, widget);
partId = CP_DROPDOWNBUTTON;
if (!(flags & State_Enabled))
stateId = CBXS_DISABLED;
@@ -2544,7 +2550,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
bool isHorz = flags & State_Horizontal;
bool isRTL = option->direction == Qt::RightToLeft;
if (sub & SC_ScrollBarAddLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_LEFTDISABLED : ABS_RIGHTDISABLED) : ABS_DOWNDISABLED);
@@ -2559,7 +2565,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSubLine) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubLine, widget);
partId = SBP_ARROWBTN;
if (!(flags & State_Enabled))
stateId = (isHorz ? (isRTL ? ABS_RIGHTDISABLED : ABS_LEFTDISABLED) : ABS_UPDISABLED);
@@ -2574,9 +2580,9 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (maxedOut) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
- theme.rect = theme.rect.united(subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget));
+ theme.rect = theme.rect.united(proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget));
partId = scrollbar->orientation == Qt::Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
stateId = SCRBS_DISABLED;
theme.partId = partId;
@@ -2584,7 +2590,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
} else {
if (sub & SC_ScrollBarSubPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSubPage, widget);
partId = flags & State_Horizontal ? SBP_UPPERTRACKHORZ : SBP_UPPERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -2599,7 +2605,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_ScrollBarAddPage) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarAddPage, widget);
partId = flags & State_Horizontal ? SBP_LOWERTRACKHORZ : SBP_LOWERTRACKVERT;
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
@@ -2614,7 +2620,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_ScrollBarSlider) {
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
if (!(flags & State_Enabled))
stateId = SCRBS_DISABLED;
else if (scrollbar->activeSubControls & SC_ScrollBarSlider && (scrollbar->state & State_Sunken))
@@ -2625,7 +2631,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
stateId = SCRBS_NORMAL;
// Draw handle
- theme.rect = subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
+ theme.rect = proxy()->subControlRect(CC_ScrollBar, option, SC_ScrollBarSlider, widget);
theme.partId = flags & State_Horizontal ? SBP_THUMBBTNHORZ : SBP_THUMBBTNVERT;
theme.stateId = stateId;
d->drawBackground(theme);
@@ -2681,7 +2687,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
QRect slrect = slider->rect;
QRegion tickreg = slrect;
if (sub & SC_SliderGroove) {
- theme.rect = subControlRect(CC_Slider, option, SC_SliderGroove, widget);
+ theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderGroove, widget);
if (slider->orientation == Qt::Horizontal) {
partId = TKP_TRACK;
stateId = TRS_NORMAL;
@@ -2697,11 +2703,11 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
tickreg -= theme.rect;
}
if (sub & SC_SliderTickmarks) {
- int tickOffset = pixelMetric(PM_SliderTickmarkOffset, slider, widget);
+ int tickOffset = proxy()->pixelMetric(PM_SliderTickmarkOffset, slider, widget);
int ticks = slider->tickPosition;
- int thickness = pixelMetric(PM_SliderControlThickness, slider, widget);
- int len = pixelMetric(PM_SliderLength, slider, widget);
- int available = pixelMetric(PM_SliderSpaceAvailable, slider, widget);
+ int thickness = proxy()->pixelMetric(PM_SliderControlThickness, slider, widget);
+ int len = proxy()->pixelMetric(PM_SliderLength, slider, widget);
+ int available = proxy()->pixelMetric(PM_SliderSpaceAvailable, slider, widget);
int interval = slider->tickInterval;
if (interval <= 0) {
interval = slider->singleStep;
@@ -2757,7 +2763,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
if (sub & SC_SliderHandle) {
- theme.rect = subControlRect(CC_Slider, option, SC_SliderHandle, widget);
+ theme.rect = proxy()->subControlRect(CC_Slider, option, SC_SliderHandle, widget);
if (slider->orientation == Qt::Horizontal) {
if (slider->tickPosition == QSlider::TicksAbove)
partId = TKP_THUMBTOP;
@@ -2803,7 +2809,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
QStyleOptionFocusRect fropt;
fropt.QStyleOption::operator=(*slider);
fropt.rect = subElementRect(SE_SliderFocusRect, slider, widget);
- drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fropt, p, widget);
}
}
break;
@@ -2813,8 +2819,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (const QStyleOptionToolButton *toolbutton
= qstyleoption_cast<const QStyleOptionToolButton *>(option)) {
QRect button, menuarea;
- button = subControlRect(cc, toolbutton, SC_ToolButton, widget);
- menuarea = subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
+ button = proxy()->subControlRect(cc, toolbutton, SC_ToolButton, widget);
+ menuarea = proxy()->subControlRect(cc, toolbutton, SC_ToolButtonMenu, widget);
State bflags = toolbutton->state & ~State_Sunken;
State mflags = bflags;
@@ -2862,9 +2868,9 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
tool.state = bflags;
if (widget && !qobject_cast<QToolBar*>(widget->parentWidget())
&& !(bflags & State_AutoRaise))
- drawPrimitive(PE_PanelButtonBevel, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonBevel, &tool, p, widget);
else
- drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
+ proxy()->drawPrimitive(PE_PanelButtonTool, &tool, p, widget);
}
}
}
@@ -2874,26 +2880,26 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
fr.QStyleOption::operator=(*toolbutton);
fr.rect.adjust(3, 3, -3, -3);
if (toolbutton->features & QStyleOptionToolButton::MenuButtonPopup)
- fr.rect.adjust(0, 0, -pixelMetric(QStyle::PM_MenuButtonIndicator,
+ fr.rect.adjust(0, 0, -proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator,
toolbutton, widget), 0);
- drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
+ proxy()->drawPrimitive(PE_FrameFocusRect, &fr, p, widget);
}
QStyleOptionToolButton label = *toolbutton;
label.state = bflags;
int fw = 2;
label.rect = button.adjusted(fw, fw, -fw, -fw);
- drawControl(CE_ToolButtonLabel, &label, p, widget);
+ proxy()->drawControl(CE_ToolButtonLabel, &label, p, widget);
if (toolbutton->subControls & SC_ToolButtonMenu) {
tool.rect = menuarea;
tool.state = mflags;
- drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorButtonDropDown, &tool, p, widget);
} else if (toolbutton->features & QStyleOptionToolButton::HasMenu) {
- int mbi = pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
+ int mbi = proxy()->pixelMetric(PM_MenuButtonIndicator, toolbutton, widget);
QRect ir = toolbutton->rect;
QStyleOptionToolButton newBtn = *toolbutton;
newBtn.rect = QRect(ir.right() + 4 - mbi, ir.height() - mbi + 4, mbi - 5, mbi - 5);
- drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
+ proxy()->drawPrimitive(PE_IndicatorArrowDown, &newBtn, p, widget);
}
}
break;
@@ -2925,7 +2931,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
theme.stateId = stateId;
d->drawBackground(theme);
- QRect ir = subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
+ QRect ir = proxy()->subControlRect(CC_TitleBar, tb, SC_TitleBarLabel, widget);
int result = TST_NONE;
pGetThemeEnumValue(theme.handle(), WP_CAPTION, isActive ? CS_ACTIVE : CS_INACTIVE, TMT_TEXTSHADOWTYPE, &result);
@@ -2944,7 +2950,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
Qt::AlignLeft | Qt::AlignVCenter | Qt::TextSingleLine, tb->text);
}
if (sub & SC_TitleBarSysMenu && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarSysMenu, widget);
partId = WP_SYSBUTTON;
if ((widget && !widget->isEnabled()) || !isActive)
stateId = SBS_DISABLED;
@@ -2962,8 +2968,8 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
SIZE sz;
pGetThemePartSize(theme.handle(), qt_win_display_dc(), theme.partId, theme.stateId, 0, TS_TRUE, &sz);
if (sz.cx == 0 || sz.cy == 0) {
- int iconSize = pixelMetric(PM_SmallIconSize, tb, widget);
- QPixmap pm = standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize);
+ int iconSize = proxy()->pixelMetric(PM_SmallIconSize, tb, widget);
+ QPixmap pm = proxy()->standardIcon(SP_TitleBarMenuButton, tb, widget).pixmap(iconSize, iconSize);
p->save();
drawItemPixmap(p, theme.rect, Qt::AlignCenter, pm);
p->restore();
@@ -2975,7 +2981,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
if (sub & SC_TitleBarMinButton && tb->titleBarFlags & Qt::WindowMinimizeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMinButton, widget);
partId = WP_MINBUTTON;
if (widget && !widget->isEnabled())
stateId = MINBS_DISABLED;
@@ -2993,7 +2999,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarMaxButton && tb->titleBarFlags & Qt::WindowMaximizeButtonHint
&& !(tb->titleBarState & Qt::WindowMaximized)) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarMaxButton, widget);
partId = WP_MAXBUTTON;
if (widget && !widget->isEnabled())
stateId = MAXBS_DISABLED;
@@ -3011,7 +3017,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarContextHelpButton
&& tb->titleBarFlags & Qt::WindowContextHelpButtonHint) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarContextHelpButton, widget);
partId = WP_HELPBUTTON;
if (widget && !widget->isEnabled())
stateId = MINBS_DISABLED;
@@ -3033,7 +3039,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
|| ((tb->titleBarFlags & Qt::WindowMaximizeButtonHint)
&& (tb->titleBarState & Qt::WindowMaximized)));
if (drawNormalButton) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarNormalButton, widget);
partId = WP_RESTOREBUTTON;
if (widget && !widget->isEnabled())
stateId = RBS_DISABLED;
@@ -3051,7 +3057,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarShadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
&& !(tb->titleBarState & Qt::WindowMinimized)) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarShadeButton, widget);
partId = WP_MINBUTTON;
if (widget && !widget->isEnabled())
stateId = MINBS_DISABLED;
@@ -3069,7 +3075,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
if (sub & SC_TitleBarUnshadeButton && tb->titleBarFlags & Qt::WindowShadeButtonHint
&& tb->titleBarState & Qt::WindowMinimized) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarUnshadeButton, widget);
partId = WP_RESTOREBUTTON;
if (widget && !widget->isEnabled())
stateId = RBS_DISABLED;
@@ -3086,7 +3092,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
d->drawBackground(theme);
}
if (sub & SC_TitleBarCloseButton && tb->titleBarFlags & Qt::WindowSystemMenuHint) {
- theme.rect = subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget);
+ theme.rect = proxy()->subControlRect(CC_TitleBar, option, SC_TitleBarCloseButton, widget);
//partId = titlebar->testWFlags(Qt::WA_WState_Tool) ? WP_SMALLCLOSEBUTTON : WP_CLOSEBUTTON;
partId = WP_CLOSEBUTTON;
if (widget && !widget->isEnabled())
@@ -3114,7 +3120,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
XPThemeData theme(widget, p, QLatin1String("WINDOW"), WP_MDICLOSEBUTTON, CBS_NORMAL);
if (option->subControls & SC_MdiCloseButton) {
- buttonRect = subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget);
+ buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiCloseButton, widget);
if (theme.isValid()) {
theme.partId = WP_MDICLOSEBUTTON;
theme.rect = buttonRect;
@@ -3130,7 +3136,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
if (option->subControls & SC_MdiNormalButton) {
- buttonRect = subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget);
+ buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiNormalButton, widget);
if (theme.isValid()) {
theme.partId = WP_MDIRESTOREBUTTON;
theme.rect = buttonRect;
@@ -3146,7 +3152,7 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
}
if (option->subControls & QStyle::SC_MdiMinButton) {
- buttonRect = subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget);
+ buttonRect = proxy()->subControlRect(CC_MdiControls, option, SC_MdiMinButton, widget);
if (theme.isValid()) {
theme.partId = WP_MDIMINBUTTON;
theme.rect = buttonRect;
@@ -3164,6 +3170,12 @@ void QWindowsXPStyle::drawComplexControl(ComplexControl cc, const QStyleOptionCo
}
break;
#endif //QT_NO_WORKSPACE
+#ifndef QT_NO_DIAL
+ case CC_Dial:
+ if (const QStyleOptionSlider *dial = qstyleoption_cast<const QStyleOptionSlider *>(option))
+ QStyleHelper::drawDial(dial, p);
+ break;
+#endif // QT_NO_DIAL
default:
QWindowsStyle::drawComplexControl(cc, option, p, widget);
break;
@@ -3427,7 +3439,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
int buttonWidth = GetSystemMetrics(SM_CXSIZE) - 4;
const int delta = buttonWidth + 2;
int controlTop = option->rect.bottom() - buttonHeight - 2;
- const int frameWidth = pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
+ const int frameWidth = proxy()->pixelMetric(PM_MdiSubWindowFrameWidth, option, widget);
const bool sysmenuHint = (tb->titleBarFlags & Qt::WindowSystemMenuHint) != 0;
const bool minimizeHint = (tb->titleBarFlags & Qt::WindowMinimizeButtonHint) != 0;
const bool maximizeHint = (tb->titleBarFlags & Qt::WindowMaximizeButtonHint) != 0;
@@ -3512,7 +3524,7 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
{
const int controlTop = 6;
const int controlHeight = height - controlTop - 3;
- const int iconExtent = pixelMetric(PM_SmallIconSize);
+ const int iconExtent = proxy()->pixelMetric(PM_SmallIconSize);
QSize iconSize = tb->icon.actualSize(QSize(iconExtent, iconExtent));
if (tb->icon.isNull())
iconSize = QSize(controlHeight, controlHeight);
@@ -3633,7 +3645,7 @@ QSize QWindowsXPStyle::sizeFromContents(ContentsType ct, const QStyleOption *opt
{
//Spinbox adds frame twice
sz = QWindowsStyle::sizeFromContents(ct, option, contentsSize, widget);
- int border = pixelMetric(PM_SpinBoxFrameWidth, option, widget);
+ int border = proxy()->pixelMetric(PM_SpinBoxFrameWidth, option, widget);
sz -= QSize(2*border, 2*border);
}
break;
diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri
index 050d81d..fcc9125 100644
--- a/src/gui/styles/styles.pri
+++ b/src/gui/styles/styles.pri
@@ -7,13 +7,19 @@ HEADERS += \
styles/qstyleplugin.h \
styles/qcommonstylepixmaps_p.h \
styles/qcommonstyle.h \
+ styles/qstylehelper_p.h \
+ styles/qproxystyle.h \
+ styles/qproxystyle_p.h \
styles/qstylesheetstyle_p.h
+
SOURCES += \
styles/qstyle.cpp \
styles/qstylefactory.cpp \
styles/qstyleoption.cpp \
styles/qstyleplugin.cpp \
+ styles/qstylehelper.cpp \
styles/qcommonstyle.cpp \
+ styles/qproxystyle.cpp \
styles/qstylesheetstyle.cpp \
styles/qstylesheetstyle_default.cpp
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index 0bd2d9a..e1b39a0 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -58,46 +58,6 @@ QT_BEGIN_NAMESPACE
using namespace QCss;
-const char *Scanner::tokenName(QCss::TokenType t)
-{
- switch (t) {
- case NONE: return "NONE";
- case S: return "S";
- case CDO: return "CDO";
- case CDC: return "CDC";
- case INCLUDES: return "INCLUDES";
- case DASHMATCH: return "DASHMATCH";
- case LBRACE: return "LBRACE";
- case PLUS: return "PLUS";
- case GREATER: return "GREATER";
- case COMMA: return "COMMA";
- case STRING: return "STRING";
- case INVALID: return "INVALID";
- case IDENT: return "IDENT";
- case HASH: return "HASH";
- case ATKEYWORD_SYM: return "ATKEYWORD_SYM";
- case EXCLAMATION_SYM: return "EXCLAMATION_SYM";
- case LENGTH: return "LENGTH";
- case PERCENTAGE: return "PERCENTAGE";
- case NUMBER: return "NUMBER";
- case FUNCTION: return "FUNCTION";
- case COLON: return "COLON";
- case SEMICOLON: return "SEMICOLON";
- case RBRACE: return "RBRACE";
- case SLASH: return "SLASH";
- case MINUS: return "MINUS";
- case DOT: return "DOT";
- case STAR: return "STAR";
- case LBRACKET: return "LBRACKET";
- case RBRACKET: return "RBRACKET";
- case EQUAL: return "EQUAL";
- case LPAREN: return "LPAREN";
- case RPAREN: return "RPAREN";
- case OR: return "OR";
- }
- return "";
-}
-
struct QCssKnownValue
{
const char *name;
@@ -280,7 +240,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
};
//Map id to strings as they appears in the 'values' array above
-static const int indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46,
+static const short indexOfId[NumKnownValues] = { 0, 40, 47, 41, 48, 53, 34, 26, 68, 69, 25, 42, 5, 62, 46,
29, 57, 58, 27, 50, 60, 6, 10, 38, 55, 19, 13, 17, 18, 20, 21, 49, 24, 45, 65, 36, 3, 2, 39, 61, 16,
11, 56, 14, 32, 63, 54, 64, 33, 67, 8, 28, 37, 12, 35, 59, 7, 9, 4, 66, 52, 22, 23, 30, 31, 1, 15, 0,
51, 44, 43 };
@@ -1509,7 +1469,7 @@ QRect Declaration::rectValue() const
QStringList func = v.variant.toStringList();
if (func.count() != 2 || func.at(0).compare(QLatin1String("rect")) != 0)
return QRect();
- QStringList args = func[1].split(QLatin1String(" "), QString::SkipEmptyParts);
+ QStringList args = func[1].split(QLatin1Char(' '), QString::SkipEmptyParts);
if (args.count() != 4)
return QRect();
QRect rect(args[0].toInt(), args[1].toInt(), args[2].toInt(), args[3].toInt());
@@ -2154,7 +2114,7 @@ void Parser::init(const QString &css, bool isFile)
if (isFile) {
QFile file(css);
if (file.open(QFile::ReadOnly)) {
- sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1String("/");
+ sourcePath = QFileInfo(styleSheet).absolutePath() + QLatin1Char('/');
QTextStream stream(&file);
styleSheet = stream.readAll();
} else {
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index 97a0aef..81f306d 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -403,7 +403,7 @@ struct BorderData {
// 4. QVector<Declaration> - { prop1: value1; prop2: value2; }
// 5. Declaration - prop1: value1;
-struct Q_GUI_EXPORT Declaration
+struct Q_AUTOTEST_EXPORT Declaration
{
struct DeclarationData : public QSharedData
{
@@ -495,7 +495,7 @@ const quint64 PseudoClass_Alternate = Q_UINT64_C(0x0000100000000000);
const quint64 PseudoClass_Any = Q_UINT64_C(0x0000ffffffffffff);
const int NumPseudos = 46;
-struct Q_GUI_EXPORT Pseudo
+struct Pseudo
{
Pseudo() : negated(false) { }
quint64 type;
@@ -504,7 +504,7 @@ struct Q_GUI_EXPORT Pseudo
bool negated;
};
-struct Q_GUI_EXPORT AttributeSelector
+struct AttributeSelector
{
enum ValueMatchType {
NoMatch,
@@ -519,7 +519,7 @@ struct Q_GUI_EXPORT AttributeSelector
ValueMatchType valueMatchCriterium;
};
-struct Q_GUI_EXPORT BasicSelector
+struct BasicSelector
{
inline BasicSelector() : relationToNext(NoRelation) {}
@@ -539,7 +539,7 @@ struct Q_GUI_EXPORT BasicSelector
Relation relationToNext;
};
-struct Q_GUI_EXPORT Selector
+struct Q_AUTOTEST_EXPORT Selector
{
QVector<BasicSelector> basicSelectors;
int specificity() const;
@@ -552,7 +552,7 @@ struct MediaRule;
struct PageRule;
struct ImportRule;
-struct Q_GUI_EXPORT ValueExtractor
+struct Q_AUTOTEST_EXPORT ValueExtractor
{
ValueExtractor(const QVector<Declaration> &declarations, const QPalette & = QPalette());
@@ -586,7 +586,7 @@ private:
QPalette pal;
};
-struct Q_GUI_EXPORT StyleRule
+struct StyleRule
{
StyleRule() : order(0) { }
QVector<Selector> selectors;
@@ -594,19 +594,19 @@ struct Q_GUI_EXPORT StyleRule
int order;
};
-struct Q_GUI_EXPORT MediaRule
+struct MediaRule
{
QStringList media;
QVector<StyleRule> styleRules;
};
-struct Q_GUI_EXPORT PageRule
+struct PageRule
{
QString selector;
QVector<Declaration> declarations;
};
-struct Q_GUI_EXPORT ImportRule
+struct ImportRule
{
QString href;
QStringList media;
@@ -620,7 +620,7 @@ enum StyleSheetOrigin {
StyleSheetOrigin_Inline
};
-struct Q_GUI_EXPORT StyleSheet
+struct StyleSheet
{
StyleSheet() : origin(StyleSheetOrigin_Unspecified), depth(0) { }
QVector<StyleRule> styleRules; //only contains rules that are not indexed
@@ -731,7 +731,6 @@ class Q_AUTOTEST_EXPORT Scanner
public:
static QString preprocess(const QString &input, bool *hasEscapeSequences = 0);
static void scan(const QString &preprocessedInput, QVector<Symbol> *symbols);
- static const char *tokenName(TokenType t);
};
class Q_GUI_EXPORT Parser
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 416017d..76f5c39 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -94,34 +94,34 @@ static int getFontWeight(const QString &weightString)
// Test in decreasing order of commonness
if (s == QLatin1String("medium") ||
s == QLatin1String("normal")
- || s.compare(qApp->translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Normal"), Qt::CaseInsensitive) == 0)
return QFont::Normal;
if (s == QLatin1String("bold")
- || s.compare(qApp->translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive) == 0)
return QFont::Bold;
if (s == QLatin1String("demibold") || s == QLatin1String("demi bold")
- || s.compare(qApp->translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Demi Bold"), Qt::CaseInsensitive) == 0)
return QFont::DemiBold;
if (s == QLatin1String("black")
- || s.compare(qApp->translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
return QFont::Black;
if (s == QLatin1String("light"))
return QFont::Light;
if (s.contains(QLatin1String("bold"))
- || s.contains(qApp->translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
+ || s.contains(QApplication::translate("QFontDatabase", "Bold"), Qt::CaseInsensitive)) {
if (s.contains(QLatin1String("demi"))
- || s.compare(qApp->translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Demi"), Qt::CaseInsensitive) == 0)
return (int) QFont::DemiBold;
return (int) QFont::Bold;
}
if (s.contains(QLatin1String("light"))
- || s.compare(qApp->translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Light"), Qt::CaseInsensitive) == 0)
return (int) QFont::Light;
if (s.contains(QLatin1String("black"))
- || s.compare(qApp->translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
+ || s.compare(QApplication::translate("QFontDatabase", "Black"), Qt::CaseInsensitive) == 0)
return (int) QFont::Black;
return (int) QFont::Normal;
@@ -261,10 +261,10 @@ QtFontStyle::Key::Key(const QString &styleString)
weight = getFontWeight(styleString);
if (styleString.contains(QLatin1String("Italic"))
- || styleString.contains(qApp->translate("QFontDatabase", "Italic")))
+ || styleString.contains(QApplication::translate("QFontDatabase", "Italic")))
style = QFont::StyleItalic;
else if (styleString.contains(QLatin1String("Oblique"))
- || styleString.contains(qApp->translate("QFontDatabase", "Oblique")))
+ || styleString.contains(QApplication::translate("QFontDatabase", "Oblique")))
style = QFont::StyleOblique;
}
@@ -951,7 +951,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe
if (! desc.foundry->name.isEmpty() && desc.family->count > 1) {
fontDef->family += QString::fromLatin1(" [");
fontDef->family += desc.foundry->name;
- fontDef->family += QString::fromLatin1("]");
+ fontDef->family += QLatin1Char(']');
}
if (desc.style->smoothScalable)
@@ -1408,21 +1408,21 @@ static QString styleStringHelper(int weight, QFont::Style style)
{
QString result;
if (weight >= QFont::Black)
- result = qApp->translate("QFontDatabase", "Black");
+ result = QApplication::translate("QFontDatabase", "Black");
else if (weight >= QFont::Bold)
- result = qApp->translate("QFontDatabase", "Bold");
+ result = QApplication::translate("QFontDatabase", "Bold");
else if (weight >= QFont::DemiBold)
- result = qApp->translate("QFontDatabase", "Demi Bold");
+ result = QApplication::translate("QFontDatabase", "Demi Bold");
else if (weight < QFont::Normal)
- result = qApp->translate("QFontDatabase", "Light");
+ result = QApplication::translate("QFontDatabase", "Light");
if (style == QFont::StyleItalic)
- result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Italic");
+ result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Italic");
else if (style == QFont::StyleOblique)
- result += QLatin1Char(' ') + qApp->translate("QFontDatabase", "Oblique");
+ result += QLatin1Char(' ') + QApplication::translate("QFontDatabase", "Oblique");
if (result.isEmpty())
- result = qApp->translate("QFontDatabase", "Normal");
+ result = QApplication::translate("QFontDatabase", "Normal");
return result.simplified();
}
@@ -1654,7 +1654,7 @@ QStringList QFontDatabase::families(WritingSystem writingSystem) const
if (!foundry.isEmpty()) {
str += QLatin1String(" [");
str += foundry;
- str += QLatin1String("]");
+ str += QLatin1Char(']');
}
flist.append(str);
}
@@ -2226,7 +2226,7 @@ QString QFontDatabase::writingSystemName(WritingSystem writingSystem)
Q_ASSERT_X(false, "QFontDatabase::writingSystemName", "invalid 'writingSystem' parameter");
break;
}
- return qApp ? qApp->translate("QFontDatabase", name) : QString::fromLatin1(name);
+ return QApplication::translate("QFontDatabase", name);
}
diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp
index 978ff8e..7f97cf2 100644
--- a/src/gui/text/qfontdatabase_qws.cpp
+++ b/src/gui/text/qfontdatabase_qws.cpp
@@ -57,6 +57,7 @@
#include "qabstractfontengine_qws.h"
#include "qabstractfontengine_p.h"
#include <qdatetime.h>
+#include "qplatformdefs.h"
// for mmap
#include <stdlib.h>
@@ -89,7 +90,7 @@ void QFontDatabasePrivate::addQPF2File(const QByteArray &file)
struct stat st;
if (stat(file.constData(), &st))
return;
- int f = ::open(file, O_RDONLY);
+ int f = ::open(file, O_RDONLY, 0);
if (f < 0)
return;
const uchar *data = (const uchar *)mmap(0, st.st_size, PROT_READ, MAP_SHARED, f, 0);
@@ -572,7 +573,7 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
qDebug() << "Resource not valid" << size->fileName;
}
#else
- int f = ::open(size->fileName, O_RDONLY);
+ int f = ::open(size->fileName, O_RDONLY, 0);
if (f >= 0) {
QFontEngineQPF *fe = new QFontEngineQPF(request, f);
if (fe->isValid())
@@ -660,8 +661,8 @@ QFontEngine *loadSingleEngine(int script, const QFontPrivate *fp,
QString fn = qwsFontPath();
fn += QLatin1Char('/');
fn += family->name.toLower()
- + QLatin1String("_") + QString::number(pixelSize*10)
- + QLatin1String("_") + QString::number(style->key.weight)
+ + QLatin1Char('_') + QString::number(pixelSize*10)
+ + QLatin1Char('_') + QString::number(style->key.weight)
+ (style->key.style == QFont::StyleItalic ?
QLatin1String("i.qpf") : QLatin1String(".qpf"));
//###rotation ###
diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp
index 780ae28..fe1c08c 100644
--- a/src/gui/text/qfontdatabase_win.cpp
+++ b/src/gui/text/qfontdatabase_win.cpp
@@ -364,7 +364,7 @@ void addFontToDatabase(QString familyName, const QString &scriptName,
signature->fsUsb[0], signature->fsUsb[1],
signature->fsUsb[2], signature->fsUsb[3]
};
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (signature->fsUsb[0] == 0) {
// If the unicode ranges bit mask is zero then
// EnumFontFamiliesEx failed to determine it properly.
@@ -715,7 +715,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
f = deffnt;
else if (fam == QLatin1String("system"))
f = SYSTEM_FONT;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
else if (fam == QLatin1String("system_fixed"))
f = SYSTEM_FIXED_FONT;
else if (fam == QLatin1String("ansi_fixed"))
@@ -774,7 +774,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
int strat = OUT_DEFAULT_PRECIS;
if (request.styleStrategy & QFont::PreferBitmap) {
strat = OUT_RASTER_PRECIS;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
} else if (request.styleStrategy & QFont::PreferDevice) {
strat = OUT_DEVICE_PRECIS;
} else if (request.styleStrategy & QFont::PreferOutline) {
@@ -794,7 +794,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
if (request.styleStrategy & QFont::PreferMatch)
qual = DRAFT_QUALITY;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
else if (request.styleStrategy & QFont::PreferQuality)
qual = PROOF_QUALITY;
#endif
@@ -872,7 +872,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, const QFontDef &requ
qErrnoWarning("QFontEngine::loadEngine: CreateFontIndirect with stretch failed");
}
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
if (hfont == 0) {
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
stockFont = true;
diff --git a/src/gui/text/qfontdatabase_x11.cpp b/src/gui/text/qfontdatabase_x11.cpp
index 70e1599..8f67cec 100644
--- a/src/gui/text/qfontdatabase_x11.cpp
+++ b/src/gui/text/qfontdatabase_x11.cpp
@@ -392,7 +392,7 @@ int qt_mib_for_xlfd_encoding(const char *encoding)
int id = qt_xlfd_encoding_id(encoding);
if (id != -1) return xlfd_encoding[id].mib;
return 0;
-};
+}
int qt_encoding_id_for_mib(int mib)
{
@@ -509,9 +509,9 @@ bool qt_fillFontDef(const QByteArray &xlfd, QFontDef *fd, int dpi, QtFontDesc *d
fd->styleStrategy |= QFont::NoAntialias;
fd->family = QString::fromLatin1(tokens[Family]);
QString foundry = QString::fromLatin1(tokens[Foundry]);
- if (! foundry.isEmpty() && foundry != QString::fromLatin1("*") && (!desc || desc->family->count > 1))
+ if (! foundry.isEmpty() && foundry != QLatin1String("*") && (!desc || desc->family->count > 1))
fd->family +=
- QString::fromLatin1(" [") + foundry + QString::fromLatin1("]");
+ QLatin1String(" [") + foundry + QLatin1Char(']');
if (qstrlen(tokens[AddStyle]) > 0)
fd->addStyle = QString::fromLatin1(tokens[AddStyle]);
@@ -1802,30 +1802,30 @@ QFontEngine *QFontDatabase::loadXlfd(int screen, int script, const QFontDef &req
QByteArray xlfd("-");
xlfd += desc.foundry->name.isEmpty() ? QByteArray("*") : desc.foundry->name.toLatin1();
- xlfd += "-";
+ xlfd += '-';
xlfd += desc.family->name.isEmpty() ? QByteArray("*") : desc.family->name.toLatin1();
- xlfd += "-";
+ xlfd += '-';
xlfd += desc.style->weightName ? desc.style->weightName : "*";
- xlfd += "-";
+ xlfd += '-';
xlfd += (desc.style->key.style == QFont::StyleItalic
- ? "i"
- : (desc.style->key.style == QFont::StyleOblique ? "o" : "r"));
- xlfd += "-";
+ ? 'i'
+ : (desc.style->key.style == QFont::StyleOblique ? 'o' : 'r'));
+ xlfd += '-';
xlfd += desc.style->setwidthName ? desc.style->setwidthName : "*";
// ### handle add-style
xlfd += "-*-";
xlfd += QByteArray::number(px);
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->xpoint);
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->xres);
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->yres);
- xlfd += "-";
+ xlfd += '-';
xlfd += desc.encoding->pitch;
- xlfd += "-";
+ xlfd += '-';
xlfd += QByteArray::number(desc.encoding->avgwidth);
- xlfd += "-";
+ xlfd += '-';
xlfd += xlfd_for_id(desc.encoding->encoding);
FM_DEBUG(" using XLFD: %s\n", xlfd.data());
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index 2f96984..f09e726 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -70,12 +70,6 @@ static inline bool qtransform_equals_no_translate(const QTransform &a, const QTr
}
}
-
-
-QFontEngineGlyphCache::~QFontEngineGlyphCache()
-{
-}
-
// Harfbuzz helper functions
static HB_Bool hb_stringToGlyphs(HB_Font font, const HB_UChar16 *string, hb_uint32 length, HB_Glyph *glyphs, hb_uint32 *numGlyphs, HB_Bool rightToLeft)
@@ -917,7 +911,7 @@ void QFontEngine::loadKerningPairs(QFixed scalingFactor)
end:
qSort(kerning_pairs);
// for (int i = 0; i < kerning_pairs.count(); ++i)
-// qDebug() << "i" << i << "left_right" << hex << kerning_pairs.at(i).left_right;
+// qDebug() << 'i' << i << "left_right" << hex << kerning_pairs.at(i).left_right;
}
#else
@@ -1660,12 +1654,6 @@ bool QFontEngineMulti::canRender(const QChar *string, int len)
return allExist;
}
-QFontEngine *QFontEngineMulti::engine(int at) const
-{
- Q_ASSERT(at < engines.size());
- return engines.at(at);
-}
-
QImage QFontEngineMulti::alphaMapForGlyph(glyph_t)
{
Q_ASSERT(false);
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index f1dac96..ef0cdca 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -54,8 +54,6 @@
#include <private/qpdf_p.h>
#include <private/qharfbuzz_p.h>
-#include <private/qpdf_p.h>
-
#include "qfontengine_ft_p.h"
#include <ft2build.h>
#include FT_FREETYPE_H
diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm
index d397e4a..2e62086 100644
--- a/src/gui/text/qfontengine_mac.mm
+++ b/src/gui/text/qfontengine_mac.mm
@@ -135,12 +135,12 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con
symbolicTraits |= kCTFontItalicTrait;
break;
}
-
+
QCFString name;
ATSFontGetName(atsFontRef, kATSOptionFlagsDefault, &name);
- QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pixelSize);
- QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pixelSize, 0);
- ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pixelSize, 0, symbolicTraits, symbolicTraits);
+ QCFType<CTFontDescriptorRef> descriptor = CTFontDescriptorCreateWithNameAndSize(name, fontDef.pointSize);
+ QCFType<CTFontRef> baseFont = CTFontCreateWithFontDescriptor(descriptor, fontDef.pointSize, 0);
+ ctfont = CTFontCreateCopyWithSymbolicTraits(baseFont, fontDef.pointSize, 0, symbolicTraits, symbolicTraits);
// CTFontCreateCopyWithSymbolicTraits returns NULL if we ask for a trait that does
// not exist for the given font. (for example italic)
@@ -162,7 +162,7 @@ QCoreTextFontEngineMulti::QCoreTextFontEngineMulti(const ATSFontFamilyRef &, con
QCoreTextFontEngine *fe = new QCoreTextFontEngine(ctfont, fontDef, this);
fe->ref.ref();
engines.append(fe);
-
+
}
QCoreTextFontEngineMulti::~QCoreTextFontEngineMulti()
@@ -176,7 +176,7 @@ uint QCoreTextFontEngineMulti::fontIndexForFont(CTFontRef id) const
if (CFEqual(engineAt(i)->ctfont, id))
return i;
}
-
+
QCoreTextFontEngineMulti *that = const_cast<QCoreTextFontEngineMulti *>(this);
QCoreTextFontEngine *fe = new QCoreTextFontEngine(id, fontDef, that);
fe->ref.ref();
@@ -227,7 +227,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
CTFontRef runFont = static_cast<CTFontRef>(CFDictionaryGetValue(runAttribs, NSFontAttributeName));
const uint fontIndex = (fontIndexForFont(runFont) << 24);
//NSLog(@"Run Font Name = %@", CTFontCopyFamilyName(runFont));
- QVarLengthArray<CGGlyph, 512> cgglyphs(0);
+ QVarLengthArray<CGGlyph, 512> cgglyphs(0);
const CGGlyph *tmpGlyphs = CTRunGetGlyphsPtr(run);
if (!tmpGlyphs) {
cgglyphs.resize(glyphCount);
@@ -260,7 +260,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay
CFIndex k = 0;
CFIndex i = 0;
- for (i = stringRange.location;
+ for (i = stringRange.location;
(i < stringRange.location + stringRange.length) && (k < glyphCount); ++i) {
if (tmpIndices[k * rtlSign + rtlOffset] == i || i == stringRange.location) {
logClusters[i] = k + firstGlyphIndex;
@@ -425,28 +425,28 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
if (glyphs.size() == 0)
return;
-
+
CGContextSetFontSize(ctx, fontDef.pixelSize);
-
+
CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
-
+
CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, -1, 0, -paintDeviceHeight);
-
+
CGAffineTransformConcat(cgMatrix, oldTextMatrix);
-
+
if (synthesisFlags & QFontEngine::SynthesizedItalic)
cgMatrix = CGAffineTransformConcat(cgMatrix, CGAffineTransformMake(1, 0, -tanf(14 * acosf(0) / 90), 1, 0, 0));
-
+
// ### cgMatrix = CGAffineTransformConcat(cgMatrix, transform);
-
+
CGContextSetTextMatrix(ctx, cgMatrix);
-
+
CGContextSetTextDrawingMode(ctx, kCGTextFill);
-
-
+
+
QVarLengthArray<CGSize> advances(glyphs.size());
QVarLengthArray<CGGlyph> cgGlyphs(glyphs.size());
-
+
for (int i = 0; i < glyphs.size() - 1; ++i) {
advances[i].width = (positions[i + 1].x - positions[i].x).toReal();
advances[i].height = (positions[i + 1].y - positions[i].y).toReal();
@@ -455,21 +455,21 @@ void QCoreTextFontEngine::draw(CGContextRef ctx, qreal x, qreal y, const QTextIt
advances[glyphs.size() - 1].width = 0;
advances[glyphs.size() - 1].height = 0;
cgGlyphs[glyphs.size() - 1] = glyphs[glyphs.size() - 1];
-
+
CGContextSetFont(ctx, cgFont);
//NSLog(@"Font inDraw %@ ctfont %@", CGFontCopyFullName(cgFont), CTFontCopyFamilyName(ctfont));
-
+
CGContextSetTextPosition(ctx, positions[0].x.toReal(), positions[0].y.toReal());
-
+
CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
-
+
if (synthesisFlags & QFontEngine::SynthesizedBold) {
CGContextSetTextPosition(ctx, positions[0].x.toReal() + 0.5 * lineThickness().toReal(),
positions[0].y.toReal());
-
+
CGContextShowGlyphsWithAdvances(ctx, cgGlyphs.data(), advances.data(), glyphs.size());
}
-
+
CGContextSetTextMatrix(ctx, oldTextMatrix);
}
@@ -624,7 +624,7 @@ QFontEngine::FaceId QCoreTextFontEngine::faceId() const
bool QCoreTextFontEngine::canRender(const QChar *string, int len)
{
- QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
+ QCFType<CTFontRef> retFont = CTFontCreateForString(ctfont,
QCFType<CFStringRef>(CFStringCreateWithCharactersNoCopy(0,
reinterpret_cast<const UniChar *>(string),
len, kCFAllocatorNull)),
@@ -674,7 +674,7 @@ QFontEngineMacMulti::QFontEngineMacMulti(const ATSFontFamilyRef &atsFamily, cons
} else {
if (fontDef.weight >= QFont::Bold)
fntStyle |= ::bold;
- if (fontDef.style != QFont::StyleNormal)
+ if (fontDef.style != QFont::StyleNormal)
fntStyle |= ::italic;
FMFontStyle intrinsicStyle;
@@ -957,7 +957,7 @@ bool QFontEngineMacMulti::stringToCMap(const QChar *str, int len, QGlyphLayout *
tmpItem.length = charCount;
tmpItem.glyphs = shaperItem.glyphs.mid(glyphIdx, glyphCount);
tmpItem.log_clusters = shaperItem.log_clusters + charIdx;
- if (!stringToCMapInternal(tmpItem.string + tmpItem.from, tmpItem.length,
+ if (!stringToCMapInternal(tmpItem.string + tmpItem.from, tmpItem.length,
&tmpItem.glyphs, &glyphCount, flags,
&tmpItem)) {
*nglyphs = glyphIdx + glyphCount;
@@ -1223,12 +1223,12 @@ QFontEngineMac::QFontEngineMac(ATSUStyle baseStyle, ATSUFontID fontID, const QFo
transform = multiEngine->transform;
else
transform = CGAffineTransformIdentity;
-
+
ATSUTextMeasurement metric;
ATSUGetAttribute(style, kATSUAscentTag, sizeof(metric), &metric, 0);
m_ascent = FixRound(metric);
-
+
ATSUGetAttribute(style, kATSUDescentTag, sizeof(metric), &metric, 0);
m_descent = FixRound(metric);
@@ -1424,11 +1424,16 @@ void QFontEngineMac::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in
addGlyphsToPathHelper(style, glyphs, positions, numGlyphs, path);
}
-QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
+
+/*!
+ Helper function for alphaMapForGlyph and alphaRGBMapForGlyph. The two are identical, except for
+ the subpixel antialiasing...
+*/
+QImage QFontEngineMac::imageForGlyph(glyph_t glyph, int margin, bool colorful)
{
const glyph_metrics_t br = boundingBox(glyph);
QImage im(qRound(br.width)+2, qRound(br.height)+4, QImage::Format_RGB32);
- im.fill(0);
+ im.fill(0xff000000);
CGColorSpaceRef colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace();
#if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
@@ -1446,7 +1451,7 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
CGContextSetFontSize(ctx, fontDef.pixelSize);
CGContextSetShouldAntialias(ctx, fontDef.pointSize > qt_antialiasing_threshold && !(fontDef.styleStrategy & QFont::NoAntialias));
// turn off sub-pixel hinting - no support for that in OpenGL
- CGContextSetShouldSmoothFonts(ctx, false);
+ CGContextSetShouldSmoothFonts(ctx, colorful);
CGAffineTransform oldTextMatrix = CGContextGetTextMatrix(ctx);
CGAffineTransform cgMatrix = CGAffineTransformMake(1, 0, 0, 1, 0, 0);
CGAffineTransformConcat(cgMatrix, oldTextMatrix);
@@ -1478,6 +1483,13 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
CGContextRelease(ctx);
+ return im;
+}
+
+QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
+{
+ QImage im = imageForGlyph(glyph, 2, false);
+
QImage indexed(im.width(), im.height(), QImage::Format_Indexed8);
QVector<QRgb> colors(256);
for (int i=0; i<256; ++i)
@@ -1497,6 +1509,32 @@ QImage QFontEngineMac::alphaMapForGlyph(glyph_t glyph)
return indexed;
}
+QImage QFontEngineMac::alphaRGBMapForGlyph(glyph_t glyph, int margin, const QTransform &t)
+{
+ QImage im = imageForGlyph(glyph, margin, true);
+
+ if (t.type() >= QTransform::TxScale) {
+ im = im.transformed(t);
+ }
+
+ extern uchar qt_pow_rgb_gamma[256];
+
+ // gamma correct the pixels back to linear color space...
+ for (int y=0; y<im.height(); ++y) {
+ uint *pixels = (uint *) im.scanLine(y);
+ for (int x=0; x<im.width(); ++x) {
+ uint p = pixels[x];
+ uint r = qt_pow_rgb_gamma[qRed(p)];
+ uint g = qt_pow_rgb_gamma[qGreen(p)];
+ uint b = qt_pow_rgb_gamma[qBlue(p)];
+ pixels[x] = (r << 16) | (g << 8) | b | 0xff000000;
+ }
+ }
+
+ return im;
+}
+
+
bool QFontEngineMac::canRender(const QChar *string, int len)
{
Q_ASSERT(false);
@@ -1650,7 +1688,7 @@ QFontEngine::Properties QFontEngineMac::properties() const
if (ATSFontGetTable(atsFont, MAKE_TAG('p', 'o', 's', 't'), 10, 2, &lw, 0) == noErr)
lw = qFromBigEndian<quint16>(lw);
props.lineWidth = lw;
-
+
// CTFontCopyPostScriptName
QCFString psName;
if (ATSFontGetPostScriptName(FMGetATSFontRefFromFont(fontID), kATSOptionFlagsDefault, &psName) == noErr)
@@ -1665,7 +1703,7 @@ void QFontEngineMac::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m
ATSUCreateAndCopyStyle(style, &unscaledStyle);
int emSquare = properties().emSquare.toInt();
-
+
const int maxAttributeCount = 4;
ATSUAttributeTag tags[maxAttributeCount + 1];
ByteCount sizes[maxAttributeCount + 1];
@@ -1677,7 +1715,7 @@ void QFontEngineMac::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_m
sizes[attributeCount] = sizeof(size);
values[attributeCount] = &size;
++attributeCount;
-
+
Q_ASSERT(attributeCount < maxAttributeCount + 1);
OSStatus err = ATSUSetAttributes(unscaledStyle, attributeCount, tags, sizes, values);
Q_ASSERT(err == noErr);
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index a5aa097..fc5ff20 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -93,7 +93,6 @@ struct QGlyphLayout;
class Q_GUI_EXPORT QFontEngine : public QObject
{
- Q_OBJECT
public:
enum Type {
Box,
@@ -360,7 +359,7 @@ private:
int _size;
};
-class Q_GUI_EXPORT QFontEngineMulti : public QFontEngine
+class QFontEngineMulti : public QFontEngine
{
public:
explicit QFontEngineMulti(int engineCount);
@@ -396,7 +395,9 @@ public:
inline virtual const char *name() const
{ return "Multi"; }
- QFontEngine *engine(int at) const;
+ QFontEngine *engine(int at) const
+ {Q_ASSERT(at < engines.size()); return engines.at(at); }
+
protected:
friend class QPSPrintEnginePrivate;
@@ -532,8 +533,11 @@ public:
virtual Properties properties() const;
virtual void getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_metrics_t *metrics);
virtual QImage alphaMapForGlyph(glyph_t);
+ virtual QImage alphaRGBMapForGlyph(glyph_t, int margin, const QTransform &t);
private:
+ QImage imageForGlyph(glyph_t glyph, int margin, bool colorful);
+
ATSUFontID fontID;
QCFType<CGFontRef> cgFont;
ATSUStyle style;
diff --git a/src/gui/text/qfontengine_qpf.cpp b/src/gui/text/qfontengine_qpf.cpp
index 435a102..97d3847 100644
--- a/src/gui/text/qfontengine_qpf.cpp
+++ b/src/gui/text/qfontengine_qpf.cpp
@@ -252,7 +252,7 @@ QList<QByteArray> QFontEngineQPF::cleanUpAfterClientCrash(const QList<int> &cras
for (int i = 0; i < int(dir.count()); ++i) {
const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i]));
- int fd = ::open(fileName.constData(), O_RDONLY);
+ int fd = ::open(fileName.constData(), O_RDONLY, 0);
if (fd >= 0) {
void *header = ::mmap(0, sizeof(QFontEngineQPF::Header), PROT_READ, MAP_SHARED, fd, 0);
if (header && header != MAP_FAILED) {
@@ -308,7 +308,7 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
readOnly = true;
#if defined(DEBUG_FONTENGINE)
- qDebug() << "QFontEngineQPF::QFontEngineQPF( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ")";
+ qDebug() << "QFontEngineQPF::QFontEngineQPF( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')';
#endif
#ifndef QT_FONTS_ARE_RESOURCES
@@ -316,9 +316,9 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
if (!renderingFontEngine)
return;
- fileName = fontDef.family.toLower() + QLatin1String("_")
+ fileName = fontDef.family.toLower() + QLatin1Char('_')
+ QString::number(fontDef.pixelSize)
- + QLatin1String("_") + QString::number(fontDef.weight)
+ + QLatin1Char('_') + QString::number(fontDef.weight)
+ (fontDef.style != QFont::StyleNormal ?
QLatin1String("_italic") : QLatin1String(""))
+ QLatin1String(".qsf");
@@ -331,9 +331,9 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
qDebug() << "found existing qpf:" << fileName;
#endif
if (::access(encodedFileName, W_OK | R_OK) == 0)
- fd = ::open(encodedFileName, O_RDWR);
+ fd = ::open(encodedFileName, O_RDWR, 0);
else if (::access(encodedFileName, R_OK) == 0)
- fd = ::open(encodedFileName, O_RDONLY);
+ fd = ::open(encodedFileName, O_RDONLY, 0);
} else {
#if defined(DEBUG_FONTENGINE)
qDebug() << "creating qpf on the fly:" << fileName;
@@ -347,7 +347,7 @@ QFontEngineQPF::QFontEngineQPF(const QFontDef &def, int fileDescriptor, QFontEng
generator.generate();
buffer.close();
const QByteArray &data = buffer.data();
- ::write(fd, data.constData(), data.size());
+ QT_WRITE(fd, data.constData(), data.size());
}
}
}
@@ -556,7 +556,7 @@ bool QFontEngineQPF::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
#if 0 && defined(DEBUG_FONTENGINE)
QChar c(uc);
if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c))
- qDebug() << "glyph for character" << c << "/" << hex << uc << "is" << dec << glyphs[glyph_pos].glyph;
+ qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph;
seenGlyphs.insert(c);
#endif
@@ -899,8 +899,8 @@ void QFontEngineQPF::loadGlyph(glyph_t glyph)
g.y = qRound(metrics.y);
g.advance = qRound(metrics.xoff);
- ::write(fd, &g, sizeof(g));
- ::write(fd, img.bits(), img.numBytes());
+ QT_WRITE(fd, &g, sizeof(g));
+ QT_WRITE(fd, img.bits(), img.numBytes());
glyphPos = oldSize - glyphDataOffset;
#if 0 && defined(DEBUG_FONTENGINE)
diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp
index d776329..10aef4c 100644
--- a/src/gui/text/qfontengine_qws.cpp
+++ b/src/gui/text/qfontengine_qws.cpp
@@ -387,7 +387,7 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn)
{
cache_cost = 1;
- int f = ::open( QFile::encodeName(fn), O_RDONLY );
+ int f = ::open( QFile::encodeName(fn), O_RDONLY, 0);
Q_ASSERT(f>=0);
QT_STATBUF st;
if ( QT_FSTAT( f, &st ) )
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index dc2e1ff..4d3633b 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -65,7 +65,7 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qnativeimage_p.h>
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
#include "qguifunctions_wince.h"
#endif
@@ -205,7 +205,7 @@ QFixed QFontEngineWin::lineThickness() const
return QFontEngine::lineThickness();
}
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
static OUTLINETEXTMETRICW *getOutlineTextMetric(HDC hdc)
{
int size;
@@ -249,7 +249,7 @@ void QFontEngineWin::getCMap()
designToDevice = 1;
_faceId.index = 0;
if(cmap) {
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
OUTLINETEXTMETRICW *otm = getOutlineTextMetric(hdc);
#else
OUTLINETEXTMETRICA *otm = getOutlineTextMetric(hdc);
@@ -286,7 +286,7 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
int i = 0;
int glyph_pos = 0;
if (mirrored) {
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
{
#else
if (symbol) {
@@ -314,7 +314,7 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
for (; i < numChars; ++i, ++glyph_pos) {
uint ucs = QChar::mirroredChar(getChar(str, i, numChars));
if (
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
tm.w.tmFirstChar > 60000 || // see line 375
#endif
ucs >= first && ucs <= last)
@@ -324,7 +324,7 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
}
}
} else {
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
{
#else
if (symbol) {
@@ -352,7 +352,7 @@ int QFontEngineWin::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout
for (; i < numChars; ++i, ++glyph_pos) {
uint uc = getChar(str, i, numChars);
if (
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
tm.w.tmFirstChar > 60000 || // see comment in QFontEngineWin
#endif
uc >= first && uc <= last)
@@ -482,7 +482,7 @@ bool QFontEngineWin::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
if (flags & QTextEngine::GlyphIndicesOnly)
return true;
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
HDC hdc = shared_dc();
if (flags & QTextEngine::DesignMetrics) {
HGDIOBJ oldFont = 0;
@@ -585,7 +585,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
designAdvances[glyph] = QFixed(width) / designToDevice;
} else {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GLYPHMETRICS gm;
DWORD res = GDI_ERROR;
MAT2 mat;
@@ -647,7 +647,7 @@ void QFontEngineWin::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla
width -= overhang;
} else {
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GLYPHMETRICS gm;
DWORD res = GDI_ERROR;
MAT2 mat;
@@ -693,14 +693,14 @@ glyph_metrics_t QFontEngineWin::boundingBox(const QGlyphLayout &glyphs)
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
typedef HRESULT (WINAPI *pGetCharABCWidthsFloat)(HDC, UINT, UINT, LPABCFLOAT);
static pGetCharABCWidthsFloat qt_GetCharABCWidthsFloat = 0;
#endif
glyph_metrics_t QFontEngineWin::boundingBox(glyph_t glyph, const QTransform &t)
{
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
GLYPHMETRICS gm;
HDC hdc = shared_dc();
@@ -871,7 +871,7 @@ qreal QFontEngineWin::minLeftBearing() const
qreal QFontEngineWin::minRightBearing() const
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (rbearing == SHRT_MIN) {
int ml = 0;
int mr = 0;
@@ -1047,7 +1047,7 @@ static inline QPointF qt_to_qpointf(const POINTFX &pt, qreal scale) {
static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
QPainterPath *path, bool ttf, glyph_metrics_t *metric = 0, qreal scale = 1)
{
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
Q_UNUSED(glyph);
Q_UNUSED(hdc);
#endif
@@ -1064,7 +1064,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
GLYPHMETRICS gMetric;
memset(&gMetric, 0, sizeof(GLYPHMETRICS));
int bufferSize = GDI_ERROR;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QT_WA( {
bufferSize = GetGlyphOutlineW(hdc, glyph, glyphFormat, &gMetric, 0, 0, &mat);
}, {
@@ -1077,7 +1077,7 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
void *dataBuffer = new char[bufferSize];
DWORD ret = GDI_ERROR;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
QT_WA( {
ret = GetGlyphOutlineW(hdc, glyph, glyphFormat, &gMetric, bufferSize,
dataBuffer, &mat);
@@ -1199,7 +1199,7 @@ void QFontEngineWin::addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, in
void QFontEngineWin::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
if(tm.w.tmPitchAndFamily & (TMPF_TRUETYPE | TMPF_VECTOR)) {
hasOutline = true;
QFontEngine::addOutlineToPath(x, y, glyphs, path, flags);
@@ -1267,7 +1267,7 @@ QFontEngine::Properties QFontEngineWin::properties() const
});
HDC hdc = shared_dc();
HGDIOBJ oldfont = SelectObject(hdc, hf);
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
OUTLINETEXTMETRICW *otm = getOutlineTextMetric(hdc);
#else
OUTLINETEXTMETRICA *otm = getOutlineTextMetric(hdc);
@@ -1333,6 +1333,7 @@ bool QFontEngineWin::getSfntTableData(uint tag, uchar *buffer, uint *length) con
# define CLEARTYPE_QUALITY 5
#endif
+extern bool qt_cleartype_enabled;
QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin,
const QTransform &t, QImage::Format mask_format)
@@ -1351,7 +1352,7 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
bool has_transformation = t.type() > QTransform::TxTranslate;
-#ifndef Q_OS_WINCE
+#ifndef Q_WS_WINCE
unsigned int options = ttf ? ETO_GLYPH_INDEX : 0;
XFORM xform;
@@ -1408,7 +1409,11 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
QNativeImage *ni = new QNativeImage(iw + 2 * margin + 4,
ih + 2 * margin + 4,
- mask_format, true);
+ QNativeImage::systemFormat(), !qt_cleartype_enabled);
+
+ /*If cleartype is enabled we use the standard system format even on Windows CE
+ and not the special textbuffer format we have to use if cleartype is disabled*/
+
ni->image.fill(0xffffffff);
HDC hdc = ni->hdc;
@@ -1437,7 +1442,6 @@ QNativeImage *QFontEngineWin::drawGDIGlyph(HFONT font, glyph_t glyph, int margin
}
-extern bool qt_cleartype_enabled;
extern uint qt_pow_gamma[256];
QImage QFontEngineWin::alphaMapForGlyph(glyph_t glyph, const QTransform &xform)
diff --git a/src/gui/text/qfontengine_x11.cpp b/src/gui/text/qfontengine_x11.cpp
index 0972b2b..bafc99d 100644
--- a/src/gui/text/qfontengine_x11.cpp
+++ b/src/gui/text/qfontengine_x11.cpp
@@ -227,7 +227,7 @@ static QFontEngine::FaceId fontFile(const QByteArray &_xname, QFreetypeFace **fr
QByteArray best_mapping;
for (QStringList::ConstIterator it = fontpath.constBegin(); it != fontpath.constEnd(); ++it) {
- if ((*it).left(1) != QLatin1String("/"))
+ if (!(*it).startsWith(QLatin1Char('/')))
continue; // not a path name, a font server
QString fontmapname;
int num = 0;
@@ -693,9 +693,8 @@ QFontEngine::FaceId QFontEngineXLFD::faceId() const
if (freetype) {
const_cast<QFontEngineXLFD *>(this)->fsType = freetype->fsType();
} else {
- QFontEngine::Properties properties = QFontEngine::properties();
face_id.index = 0;
- face_id.filename = "-" + properties.postscriptName;
+ face_id.filename = '-' + QFontEngine::properties().postscriptName;
}
}
#endif
diff --git a/src/gui/text/qfontengineglyphcache_p.h b/src/gui/text/qfontengineglyphcache_p.h
index 8589cc6..ca67e3f 100644
--- a/src/gui/text/qfontengineglyphcache_p.h
+++ b/src/gui/text/qfontengineglyphcache_p.h
@@ -72,7 +72,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QFontEngineGlyphCache
+class QFontEngineGlyphCache
{
public:
QFontEngineGlyphCache(const QTransform &matrix) : m_transform(matrix) { }
@@ -83,7 +83,7 @@ public:
Raster_Mono
};
- virtual ~QFontEngineGlyphCache();
+ virtual ~QFontEngineGlyphCache() { }
QTransform m_transform;
};
diff --git a/src/gui/text/qfontsubset.cpp b/src/gui/text/qfontsubset.cpp
index 0d1a884..e4d813d 100644
--- a/src/gui/text/qfontsubset.cpp
+++ b/src/gui/text/qfontsubset.cpp
@@ -333,17 +333,17 @@ QByteArray QFontSubset::glyphName(unsigned int glyph, const QVector<int> reverse
name[0] = 0;
}
if (name[0]) {
- s << "/" << name;
+ s << '/' << name;
} else
#endif
#if defined(Q_WS_X11)
if (fontEngine->type() == QFontEngine::XLFD) {
uint uc = static_cast<QFontEngineXLFD *>(fontEngine)->toUnicode(glyphIndex);
- s << "/" << glyphName(uc, false /* ### */);
+ s << '/' << glyphName(uc, false /* ### */);
} else
#endif
if (reverseMap[glyphIndex] && reverseMap[glyphIndex] < 0x10000) {
- s << "/" << glyphName(reverseMap[glyphIndex], false);
+ s << '/' << glyphName(reverseMap[glyphIndex], false);
} else {
s << "/gl" << (int)glyphIndex;
}
@@ -395,13 +395,13 @@ QByteArray QFontSubset::widthArray() const
int endnonlinear = startLinear ? startLinear : g;
// qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
if (endnonlinear > start) {
- s << start << "[";
+ s << start << '[';
for (int i = start; i < endnonlinear; ++i)
s << (widths[i]*scale).toInt();
s << "]\n";
}
if (startLinear)
- s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << "\n";
+ s << startLinear << g - 1 << (widths[startLinear]*scale).toInt() << '\n';
}
s << "]\n";
}
@@ -488,14 +488,14 @@ QByteArray QFontSubset::createToUnicodeMap() const
int endnonlinear = startLinear ? startLinear : g;
// qDebug(" startLinear=%x endnonlinear=%x", startLinear,endnonlinear);
if (endnonlinear > start) {
- s << "<" << QPdf::toHex((ushort)start, buf) << "> <";
+ s << '<' << QPdf::toHex((ushort)start, buf) << "> <";
s << QPdf::toHex((ushort)(endnonlinear - 1), buf) << "> ";
if (endnonlinear == start + 1) {
- s << "<" << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
+ s << '<' << QPdf::toHex((ushort)reverseMap[start], buf) << ">\n";
} else {
- s << "[";
+ s << '[';
for (int i = start; i < endnonlinear; ++i) {
- s << "<" << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
+ s << '<' << QPdf::toHex((ushort)reverseMap[i], buf) << "> ";
}
s << "]\n";
}
@@ -508,9 +508,9 @@ QByteArray QFontSubset::createToUnicodeMap() const
int uc_end = uc_start + len - 1;
if ((uc_end >> 8) != (uc_start >> 8))
len = 256 - (uc_start & 0xff);
- s << "<" << QPdf::toHex((ushort)startLinear, buf) << "> <";
+ s << '<' << QPdf::toHex((ushort)startLinear, buf) << "> <";
s << QPdf::toHex((ushort)(startLinear + len - 1), buf) << "> ";
- s << "<" << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";
+ s << '<' << QPdf::toHex((ushort)reverseMap[startLinear], buf) << ">\n";
checkRanges(ts, ranges, nranges);
startLinear += len;
}
@@ -1655,7 +1655,7 @@ QByteArray QFontSubset::toType1() const
QByteArray id = QByteArray::number(object_id);
QByteArray psname = properties.postscriptName;
- psname.replace(" ", "");
+ psname.replace(' ', "");
standard_font = false;
@@ -1681,12 +1681,12 @@ QByteArray QFontSubset::toType1() const
#endif
s << "/F" << id << "-Base\n";
if (standard_font) {
- s << "/" << psname << " findfont\n"
+ s << '/' << psname << " findfont\n"
"0 dict copy dup /NumGlyphs 0 put dup /CMap 256 array put def\n";
} else {
s << "<<\n";
if(!psname.isEmpty())
- s << "/FontName /" << psname << "\n";
+ s << "/FontName /" << psname << '\n';
s << "/FontInfo <</FsType " << (int)fontEngine->fsType << ">>\n"
"/FontType 1\n"
"/PaintType 0\n"
@@ -1722,7 +1722,7 @@ QByteArray QFontSubset::type1AddedGlyphs() const
int nGlyphs = glyph_indices.size();
QByteArray id = QByteArray::number(object_id);
- s << "F" << id << "-Base [\n";
+ s << 'F' << id << "-Base [\n";
for (int i = downloaded_glyphs; i < nGlyphs; ++i) {
glyph_t g = glyph_indices.at(i);
QPainterPath path;
diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp
index 69e1ee4..a3b6085 100644
--- a/src/gui/text/qtextcontrol.cpp
+++ b/src/gui/text/qtextcontrol.cpp
@@ -82,7 +82,7 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include <qkeysequence.h>
-#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1String("\t") + QString(QKeySequence(k)) : QString())
+#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString())
#else
#define ACCEL_KEY(k) QString()
#endif
@@ -394,7 +394,7 @@ void QTextControlPrivate::init(Qt::TextFormat format, const QString &text, QText
Q_Q(QTextControl);
setContent(format, text, document);
- QWidget *parentWidget = qobject_cast<QWidget*>(q->parent());
+ QWidget *parentWidget = qobject_cast<QWidget*>(parent);
if (parentWidget) {
QTextOption opt = doc->defaultTextOption();
opt.setTextDirection(parentWidget->layoutDirection());
@@ -1715,7 +1715,7 @@ void QTextControlPrivate::mouseDoubleClickEvent(QEvent *e, Qt::MouseButton butto
selectedWordOnDoubleClick = cursor;
trippleClickPoint = pos;
- trippleClickTimer.start(qApp->doubleClickInterval(), q);
+ trippleClickTimer.start(QApplication::doubleClickInterval(), q);
if (doEmit) {
selectionChanged();
#ifndef QT_NO_CLIPBOARD
diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h
index e50540a..4dac4f7 100644
--- a/src/gui/text/qtextcontrol_p.h
+++ b/src/gui/text/qtextcontrol_p.h
@@ -83,7 +83,7 @@ class QAbstractScrollArea;
class QEvent;
class QTimerEvent;
-class Q_GUI_EXPORT QTextControl : public QObject
+class Q_AUTOTEST_EXPORT QTextControl : public QObject
{
Q_OBJECT
Q_DECLARE_PRIVATE(QTextControl)
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index 48963bb..b9e1c89 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -145,7 +145,6 @@ void QTextCursorPrivate::remove()
{
if (anchor == position)
return;
- priv->beginEditBlock();
currentCharFormat = -1;
int pos1 = position;
int pos2 = adjusted_anchor;
@@ -159,15 +158,18 @@ void QTextCursorPrivate::remove()
// deleting inside table? -> delete only content
QTextTable *table = complexSelectionTable();
if (table) {
+ priv->beginEditBlock();
int startRow, startCol, numRows, numCols;
selectedTableCells(&startRow, &numRows, &startCol, &numCols);
clearCells(table, startRow, startCol, numRows, numCols, op);
+ adjusted_anchor = anchor = position;
+ priv->endEditBlock();
} else {
priv->remove(pos1, pos2-pos1, op);
+ adjusted_anchor = anchor = position;
+ priv->finishEdit();
}
- adjusted_anchor = anchor = position;
- priv->endEditBlock();
}
void QTextCursorPrivate::clearCells(QTextTable *table, int startRow, int startCol, int numRows, int numCols, QTextUndoCommand::Operation op)
@@ -1291,9 +1293,14 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
QTextCharFormat format = _format;
format.clearProperty(QTextFormat::ObjectIndex);
- d->priv->beginEditBlock();
+ bool hasEditBlock = false;
+
+ if (d->anchor != d->position) {
+ hasEditBlock = true;
+ d->priv->beginEditBlock();
+ d->remove();
+ }
- d->remove();
if (!text.isEmpty()) {
QTextFormatCollection *formats = d->priv->formatCollection();
int formatIdx = formats->indexForFormat(format);
@@ -1323,6 +1330,11 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
|| ch == QChar::ParagraphSeparator
|| ch == QLatin1Char('\r')) {
+ if (!hasEditBlock) {
+ hasEditBlock = true;
+ d->priv->beginEditBlock();
+ }
+
if (blockEnd > blockStart)
d->priv->insert(d->position, textStart + blockStart, blockEnd - blockStart, formatIdx);
@@ -1333,7 +1345,8 @@ void QTextCursor::insertText(const QString &text, const QTextCharFormat &_format
if (textStart + blockStart < textEnd)
d->priv->insert(d->position, textStart + blockStart, textEnd - textStart - blockStart, formatIdx);
}
- d->priv->endEditBlock();
+ if (hasEditBlock)
+ d->priv->endEditBlock();
d->setX();
}
@@ -1348,12 +1361,15 @@ void QTextCursor::deleteChar()
if (!d || !d->priv)
return;
- if (d->position == d->anchor) {
- if (!d->canDelete(d->position))
- return;
- d->adjusted_anchor = d->anchor =
- d->priv->nextCursorPosition(d->anchor, QTextLayout::SkipCharacters);
+ if (d->position != d->anchor) {
+ removeSelectedText();
+ return;
}
+
+ if (!d->canDelete(d->position))
+ return;
+ d->adjusted_anchor = d->anchor =
+ d->priv->nextCursorPosition(d->anchor, QTextLayout::SkipCharacters);
d->remove();
d->setX();
}
@@ -1368,27 +1384,29 @@ void QTextCursor::deletePreviousChar()
{
if (!d || !d->priv)
return;
-
- if (d->position == d->anchor) {
- if (d->anchor < 1 || !d->canDelete(d->anchor-1))
- return;
- d->anchor--;
-
- QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor);
- const QTextFragmentData * const frag = fragIt.value();
- int fpos = fragIt.position();
- QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
- if (d->anchor > fpos && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
- // second half of a surrogate, check if we have the first half as well,
- // if yes delete both at once
- uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
- if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00)
- --d->anchor;
- }
-
- d->adjusted_anchor = d->anchor;
+
+ if (d->position != d->anchor) {
+ removeSelectedText();
+ return;
}
-
+
+ if (d->anchor < 1 || !d->canDelete(d->anchor-1))
+ return;
+ d->anchor--;
+
+ QTextDocumentPrivate::FragmentIterator fragIt = d->priv->find(d->anchor);
+ const QTextFragmentData * const frag = fragIt.value();
+ int fpos = fragIt.position();
+ QChar uc = d->priv->buffer().at(d->anchor - fpos + frag->stringPosition);
+ if (d->anchor > fpos && uc.unicode() >= 0xdc00 && uc.unicode() < 0xe000) {
+ // second half of a surrogate, check if we have the first half as well,
+ // if yes delete both at once
+ uc = d->priv->buffer().at(d->anchor - 1 - fpos + frag->stringPosition);
+ if (uc.unicode() >= 0xd800 && uc.unicode() < 0xdc00)
+ --d->anchor;
+ }
+
+ d->adjusted_anchor = d->anchor;
d->remove();
d->setX();
}
@@ -1504,7 +1522,9 @@ void QTextCursor::removeSelectedText()
if (!d || !d->priv || d->position == d->anchor)
return;
+ d->priv->beginEditBlock();
d->remove();
+ d->priv->endEditBlock();
d->setX();
}
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 873f846..23c3c20 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -2201,7 +2201,7 @@ void QTextHtmlExporter::emitTextLength(const char *attribute, const QTextLength
if (length.type() == QTextLength::PercentageLength)
html += QLatin1String("%\"");
else
- html += QLatin1String("\"");
+ html += QLatin1Char('\"');
}
void QTextHtmlExporter::emitAlignment(Qt::Alignment align)
diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp
index 05ddf47..7700c14 100644
--- a/src/gui/text/qtextdocument_p.cpp
+++ b/src/gui/text/qtextdocument_p.cpp
@@ -193,6 +193,8 @@ QTextDocumentPrivate::QTextDocumentPrivate()
undoEnabled = true;
inContentsChange = false;
+ inEdit = false;
+
defaultTextOption.setTabStop(80); // same as in qtextengine.cpp
defaultTextOption.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
@@ -404,7 +406,7 @@ int QTextDocumentPrivate::insertBlock(const QChar &blockSeparator,
int b = blocks.findNode(pos);
QTextBlockData *B = blocks.fragment(b);
- QTextUndoCommand c = { QTextUndoCommand::BlockInserted, true,
+ QTextUndoCommand c = { QTextUndoCommand::BlockInserted, editBlock != 0,
op, charFormat, strPos, pos, { blockFormat },
B->revision };
@@ -439,20 +441,20 @@ void QTextDocumentPrivate::insert(int pos, int strPos, int strLength, int format
Q_ASSERT(pos >= 0 && pos < fragments.length());
Q_ASSERT(formats.format(format).isCharFormat());
- beginEditBlock();
+ beginEdit();
insert_string(pos, strPos, strLength, format, QTextUndoCommand::MoveCursor);
if (undoEnabled) {
int b = blocks.findNode(pos);
QTextBlockData *B = blocks.fragment(b);
- QTextUndoCommand c = { QTextUndoCommand::Inserted, true,
+ QTextUndoCommand c = { QTextUndoCommand::Inserted, editBlock != 0,
QTextUndoCommand::MoveCursor, format, strPos, pos, { strLength },
B->revision };
appendUndoItem(c);
B->revision = undoState;
Q_ASSERT(undoState == undoStack.size());
}
- endEditBlock();
+ finishEdit();
}
void QTextDocumentPrivate::insert(int pos, const QString &str, int format)
@@ -565,6 +567,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
if (pos == to)
return;
+ beginEdit();
const bool needsInsert = to != -1;
#if !defined(QT_NO_DEBUG)
@@ -584,8 +587,6 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
Q_ASSERT(startAndEndInSameFrame || endIsEndOfChildFrame || startIsStartOfFrameAndEndIsEndOfFrameWithCommonParent || isFirstTableCell);
#endif
- beginEditBlock();
-
split(pos);
split(pos+length);
@@ -605,10 +606,10 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
int blockRevision = B->revision;
QTextFragmentData *X = fragments.fragment(x);
- QTextUndoCommand c = { QTextUndoCommand::Removed, true,
+ QTextUndoCommand c = { QTextUndoCommand::Removed, editBlock != 0,
op, X->format, X->stringPosition, key, { X->size_array[0] },
blockRevision };
- QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, true,
+ QTextUndoCommand cInsert = { QTextUndoCommand::Inserted, editBlock != 0,
op, X->format, X->stringPosition, dstKey, { X->size_array[0] },
blockRevision };
@@ -648,7 +649,7 @@ void QTextDocumentPrivate::move(int pos, int to, int length, QTextUndoCommand::O
Q_ASSERT(blocks.length() == fragments.length());
- endEditBlock();
+ finishEdit();
}
void QTextDocumentPrivate::remove(int pos, int length, QTextUndoCommand::Operation op)
@@ -1004,8 +1005,12 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
if (!undoStack.isEmpty() && modified) {
QTextUndoCommand &last = undoStack[undoState - 1];
- if (last.tryMerge(c))
- return;
+ if ( (last.block && c.block) // part of the same block => can merge
+ || (!c.block && !last.block // two single undo items => can merge
+ && (undoState < 2 || !undoStack[undoState-2].block))) {
+ if (last.tryMerge(c))
+ return;
+ }
}
if (modifiedState > undoState)
modifiedState = -1;
@@ -1013,6 +1018,9 @@ void QTextDocumentPrivate::appendUndoItem(const QTextUndoCommand &c)
undoState++;
emitUndoAvailable(true);
emitRedoAvailable(false);
+
+ if (!c.block)
+ emit document()->undoCommandAdded();
}
void QTextDocumentPrivate::truncateUndoStack()
@@ -1082,7 +1090,6 @@ void QTextDocumentPrivate::joinPreviousEditBlock()
void QTextDocumentPrivate::endEditBlock()
{
- Q_Q(QTextDocument);
if (--editBlock)
return;
@@ -1093,6 +1100,18 @@ void QTextDocumentPrivate::endEditBlock()
emit document()->undoCommandAdded();
}
+ finishEdit();
+}
+
+void QTextDocumentPrivate::finishEdit()
+{
+ Q_Q(QTextDocument);
+
+ if (editBlock)
+ return;
+
+ inEdit = false;
+
if (framesDirty)
scan_frames(docChangeFrom, docChangeOldLength, docChangeLength);
@@ -1162,7 +1181,7 @@ void QTextDocumentPrivate::adjustDocumentChangesAndCursors(int from, int addedOr
for (int i = 0; i < cursors.size(); ++i) {
QTextCursorPrivate *curs = cursors.at(i);
if (curs->adjustPosition(from, addedOrRemoved, op) == QTextCursorPrivate::CursorMoved) {
- if (editBlock) {
+ if (editBlock || inEdit) {
if (!changedCursors.contains(curs))
changedCursors.append(curs);
} else {
@@ -1279,7 +1298,7 @@ void QTextDocumentPrivate::changeObjectFormat(QTextObject *obj, int format)
if (f)
documentChange(f->firstPosition(), f->lastPosition() - f->firstPosition());
- QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, true, QTextUndoCommand::MoveCursor, oldFormatIndex,
+ QTextUndoCommand c = { QTextUndoCommand::GroupFormatChange, editBlock != 0, QTextUndoCommand::MoveCursor, oldFormatIndex,
0, 0, { obj->d_func()->objectIndex }, 0 };
appendUndoItem(c);
diff --git a/src/gui/text/qtextdocument_p.h b/src/gui/text/qtextdocument_p.h
index 25763e1..e10e7ae 100644
--- a/src/gui/text/qtextdocument_p.h
+++ b/src/gui/text/qtextdocument_p.h
@@ -139,7 +139,7 @@ public:
MoveCursor = 1
};
quint16 command;
- quint8 block; ///< All undo commands that have this set to zero/false are combined with the preceding command on undo/redo.
+ quint8 block; ///< All undo commands that have this set to true are combined with the preceding command on undo/redo.
quint8 operation;
int format;
quint32 strPos;
@@ -202,6 +202,8 @@ public:
inline void beginEditBlock() { editBlock++; }
void joinPreviousEditBlock();
void endEditBlock();
+ inline void beginEdit() { inEdit = true; }
+ void finishEdit();
inline bool isInEditBlock() const { return editBlock; }
void enableUndoRedo(bool enable);
inline bool isUndoRedoEnabled() const { return undoEnabled; }
@@ -334,8 +336,9 @@ public:
QCss::StyleSheet parsedDefaultStyleSheet;
#endif
int maximumBlockCount;
- bool needsEnsureMaximumBlockCount;
- bool inContentsChange;
+ uint needsEnsureMaximumBlockCount : 1;
+ uint inContentsChange : 1;
+ uint inEdit : 1; // between beginEdit() and finishEdit()
QSizeF pageSize;
QString title;
QString url;
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index c66d0c1..1cb806d 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -855,6 +855,24 @@ void QTextDocumentLayoutPrivate::drawBorder(QPainter *painter, const QRectF &rec
void QTextDocumentLayoutPrivate::drawFrameDecoration(QPainter *painter, QTextFrame *frame, QTextFrameData *fd, const QRectF &clip, const QRectF &rect) const
{
+
+ const QBrush bg = frame->frameFormat().background();
+ if (bg != Qt::NoBrush) {
+ QRectF bgRect = rect;
+ bgRect.adjust((fd->leftMargin + fd->border).toReal(),
+ (fd->topMargin + fd->border).toReal(),
+ - (fd->rightMargin + fd->border).toReal(),
+ - (fd->bottomMargin + fd->border).toReal());
+
+ QRectF gradientRect; // invalid makes it default to bgRect
+ QPointF origin = bgRect.topLeft();
+ if (!frame->parentFrame()) {
+ bgRect = clip;
+ gradientRect.setWidth(painter->device()->width());
+ gradientRect.setHeight(painter->device()->height());
+ }
+ fillBackground(painter, bgRect, bg, origin, gradientRect);
+ }
if (fd->border != 0) {
painter->save();
painter->setBrush(Qt::lightGray);
@@ -875,24 +893,6 @@ void QTextDocumentLayoutPrivate::drawFrameDecoration(QPainter *painter, QTextFra
painter->restore();
}
-
- const QBrush bg = frame->frameFormat().background();
- if (bg != Qt::NoBrush) {
- QRectF bgRect = rect;
- bgRect.adjust((fd->leftMargin + fd->border).toReal(),
- (fd->topMargin + fd->border).toReal(),
- - (fd->rightMargin + fd->border).toReal(),
- - (fd->bottomMargin + fd->border).toReal());
-
- QRectF gradientRect; // invalid makes it default to bgRect
- QPointF origin = bgRect.topLeft();
- if (!frame->parentFrame()) {
- bgRect = clip;
- gradientRect.setWidth(painter->device()->width());
- gradientRect.setHeight(painter->device()->height());
- }
- fillBackground(painter, bgRect, bg, origin, gradientRect);
- }
}
static void adjustContextSelectionsForCell(QAbstractTextDocumentLayout::PaintContext &cell_context,
@@ -2500,7 +2500,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
LDEBUG << "layoutBlock from=" << layoutFrom << "to=" << layoutTo;
-// qDebug() << "layoutBlock; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ")";
+// qDebug() << "layoutBlock; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ')';
if (previousBlockFormat) {
qreal margin = qMax(blockFormat.topMargin(), previousBlockFormat->bottomMargin());
@@ -3205,18 +3205,16 @@ bool QTextDocumentLayout::contentHasAlignment() const
qreal QTextDocumentLayoutPrivate::scaleToDevice(qreal value) const
{
- QPaintDevice *dev = q_func()->paintDevice();
- if (!dev)
+ if (!paintDevice)
return value;
- return value * dev->logicalDpiY() / qreal(qt_defaultDpi());
+ return value * paintDevice->logicalDpiY() / qreal(qt_defaultDpi());
}
QFixed QTextDocumentLayoutPrivate::scaleToDevice(QFixed value) const
{
- QPaintDevice *dev = q_func()->paintDevice();
- if (!dev)
+ if (!paintDevice)
return value;
- return value * QFixed(dev->logicalDpiY()) / QFixed(qt_defaultDpi());
+ return value * QFixed(paintDevice->logicalDpiY()) / QFixed(qt_defaultDpi());
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 0c55ce5..3b102c3 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -363,7 +363,7 @@ static bool bidiItemize(QTextEngine *engine, QScriptAnalysis *analysis, QBidiCon
#if (BIDI_DEBUG >= 2)
// qDebug() << "pos=" << current << " dir=" << directions[dir]
// << " current=" << directions[dirCurrent] << " last=" << directions[status.last]
-// << " eor=" << eor << "/" << directions[status.eor]
+// << " eor=" << eor << '/' << directions[status.eor]
// << " sor=" << sor << " lastStrong="
// << directions[status.lastStrong]
// << " level=" << (int)control.level << " override=" << (bool)control.override;
@@ -868,7 +868,7 @@ void QTextEngine::shapeText(int item) const
#if defined(Q_WS_MAC)
shapeTextMac(item);
-#elif defined(Q_OS_WINCE)
+#elif defined(Q_WS_WINCE)
shapeTextWithCE(item);
#else
shapeTextWithHarfbuzz(item);
@@ -923,7 +923,7 @@ void QTextEngine::shapeText(int item) const
si.width += glyphs.advances_x[i];
}
-#if defined(Q_OS_WINCE) //TODO
+#if defined(Q_WS_WINCE) //TODO
// set the glyph attributes heuristically. Assumes a 1 to 1 relationship between chars and glyphs
// and no reordering.
// also computes logClusters heuristically
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index cf241fa..6be525f 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -581,7 +581,7 @@ private:
void addRequiredBoundaries() const;
void shapeText(int item) const;
void shapeTextWithHarfbuzz(int item) const;
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
void shapeTextWithCE(int item) const;
#endif
#if defined(Q_WS_MAC)
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 38ac4ca..d93f084 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -142,6 +142,7 @@ QTextLength::operator QVariant() const
return QVariant(QVariant::TextLength, this);
}
+#ifndef QT_NO_DATASTREAM
QDataStream &operator<<(QDataStream &stream, const QTextLength &length)
{
return stream << qint32(length.lengthType) << double(length.fixedValueOrPercentage);
@@ -156,6 +157,7 @@ QDataStream &operator>>(QDataStream &stream, QTextLength &length)
length.lengthType = QTextLength::Type(type);
return stream;
}
+#endif // QT_NO_DATASTREAM
class QTextFormatPrivate : public QSharedData
{
@@ -374,6 +376,7 @@ void QTextFormatPrivate::recalcFont() const
fontDirty = false;
}
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFormat &fmt)
{
stream << fmt.format_type << fmt.properties();
@@ -396,6 +399,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextFormat &fmt)
return stream;
}
+#endif // QT_NO_DATASTREAM
/*!
\class QTextFormat
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index 8eaeeb1..96c0739 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -76,8 +76,10 @@ class QTextCursor;
class QTextDocument;
class QTextLength;
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextLength &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextLength &);
+#endif
class Q_GUI_EXPORT QTextLength
{
@@ -119,8 +121,10 @@ private:
inline QTextLength::QTextLength(Type atype, qreal avalue)
: lengthType(atype), fixedValueOrPercentage(avalue) {}
+#ifndef QT_NO_DATASTREAM
Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QTextFormat &);
Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QTextFormat &);
+#endif
class Q_GUI_EXPORT QTextFormat
{
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index b1f1b75..76c59c3 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -343,7 +343,7 @@ static QChar resolveEntity(const QString &entity)
return e->code;
}
-static const uint windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
+static const ushort windowsLatin1ExtendedCharacters[0xA0 - 0x80] = {
0x20ac, // 0x80
0x0081, // 0x81 direct mapping
0x201a, // 0x82
@@ -499,7 +499,7 @@ void QTextHtmlParser::dumpHtml()
{
for (int i = 0; i < count(); ++i) {
qDebug().nospace() << qPrintable(QString(depth(i)*4, QLatin1Char(' ')))
- << qPrintable(at(i).tag) << ":"
+ << qPrintable(at(i).tag) << ':'
<< quoteNewline(at(i).text);
;
}
diff --git a/src/gui/text/qtextimagehandler_p.h b/src/gui/text/qtextimagehandler_p.h
index f5426b5..1f29642 100644
--- a/src/gui/text/qtextimagehandler_p.h
+++ b/src/gui/text/qtextimagehandler_p.h
@@ -60,7 +60,7 @@ QT_BEGIN_NAMESPACE
class QTextImageFormat;
-class Q_GUI_EXPORT QTextImageHandler : public QObject,
+class QTextImageHandler : public QObject,
public QTextObjectInterface
{
Q_OBJECT
@@ -72,7 +72,7 @@ public:
virtual void drawObject(QPainter *p, const QRectF &rect, QTextDocument *doc, int posInDocument, const QTextFormat &format);
typedef QImage (*ExternalImageLoaderFunction)(const QString &name, const QString &context);
- static ExternalImageLoaderFunction externalLoader;
+ static Q_GUI_EXPORT ExternalImageLoaderFunction externalLoader; //this is needed by Qt3Support
};
QT_END_NAMESPACE
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp
index 1edc3b8..bc8ac5b 100644
--- a/src/gui/text/qtextodfwriter.cpp
+++ b/src/gui/text/qtextodfwriter.cpp
@@ -295,28 +295,13 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
writer.writeAttribute(textNS, QString::fromLatin1("style-name"), QString::fromLatin1("c%1")
.arg(frag.fragment().charFormatIndex()));
bool escapeNextSpace = true;
- int precedingSpaces = 0, precedingTabs = 0;
+ int precedingSpaces = 0;
int exportedIndex = 0;
for (int i=0; i <= fragmentText.count(); ++i) {
- bool isTab = false, isSpace = false;
- if (i < fragmentText.count()) {
+ bool isSpace = false;
QChar character = fragmentText[i];
- isTab = character.unicode() == '\t';
isSpace = character.unicode() == ' ';
- if (character.unicode() == 0x2028) { // soft-return
- writer.writeCharacters(fragmentText.mid(exportedIndex, i));
- writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
- exportedIndex = i+1;
- continue;
- }
- if (isSpace) {
- ++precedingSpaces;
- escapeNextSpace = true;
- }
- else if (isTab) {
- precedingTabs++;
- }
- }
+
// find more than one space. -> <text:s text:c="2" />
if (!isSpace && escapeNextSpace && precedingSpaces > 1) {
const bool startParag = exportedIndex == 0 && i == precedingSpaces;
@@ -329,17 +314,27 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
precedingSpaces = 0;
exportedIndex = i;
}
- // find tabs. -> <text:tab text:tab-ref="3" /> or <text:tab/>
- if (!isTab && precedingTabs) {
- writer.writeCharacters(fragmentText.mid(exportedIndex, i - precedingTabs - exportedIndex));
- writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
- if (precedingTabs > 1)
- writer.writeAttribute(textNS, QString::fromLatin1("tab-ref"), QString::number(precedingTabs));
- precedingTabs = 0;
- exportedIndex = i;
+
+ if (i < fragmentText.count()) {
+ if (character.unicode() == 0x2028) { // soft-return
+ //if (exportedIndex < i)
+ writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
+ writer.writeEmptyElement(textNS, QString::fromLatin1("line-break"));
+ exportedIndex = i+1;
+ continue;
+ } else if (character.unicode() == '\t') { // Tab
+ //if (exportedIndex < i)
+ writer.writeCharacters(fragmentText.mid(exportedIndex, i - exportedIndex));
+ writer.writeEmptyElement(textNS, QString::fromLatin1("tab"));
+ exportedIndex = i+1;
+ precedingSpaces = 0;
+ } else if (isSpace) {
+ ++precedingSpaces;
+ escapeNextSpace = true;
+ } else if (!isSpace) {
+ precedingSpaces = 0;
+ }
}
- if (!isSpace && !isTab)
- precedingSpaces = 0;
}
writer.writeCharacters(fragmentText.mid(exportedIndex));
@@ -477,7 +472,7 @@ void QTextOdfWriter::writeBlockFormat(QXmlStreamWriter &writer, QTextBlockFormat
if (format.hasProperty(QTextFormat::BlockRightMargin))
writer.writeAttribute(foNS, QString::fromLatin1("margin-right"), pixelToPoint(qMax(qreal(0.), format.rightMargin())) );
if (format.hasProperty(QTextFormat::TextIndent))
- writer.writeAttribute(foNS, QString::fromLatin1("text-indent"), QString::number(format.textIndent()));
+ writer.writeAttribute(foNS, QString::fromLatin1("text-indent"), pixelToPoint(format.textIndent()));
if (format.hasProperty(QTextFormat::PageBreakPolicy)) {
if (format.pageBreakPolicy() & QTextFormat::PageBreak_AlwaysBefore)
writer.writeAttribute(foNS, QString::fromLatin1("break-before"), QString::fromLatin1("page"));
diff --git a/src/gui/util/qcompleter.cpp b/src/gui/util/qcompleter.cpp
index 8410a69..aba0245 100644
--- a/src/gui/util/qcompleter.cpp
+++ b/src/gui/util/qcompleter.cpp
@@ -1667,7 +1667,7 @@ QStringList QCompleter::splitPath(const QString& path) const
doubleSlash.clear();
#endif
- QRegExp re(QLatin1String("[") + QRegExp::escape(sep) + QLatin1String("]"));
+ QRegExp re(QLatin1Char('[') + QRegExp::escape(sep) + QLatin1Char(']'));
QStringList parts = pathCopy.split(re);
#if defined(Q_OS_SYMBIAN)
diff --git a/src/gui/util/qdesktopservices_mac.cpp b/src/gui/util/qdesktopservices_mac.cpp
index 5124068..4f730b7 100644
--- a/src/gui/util/qdesktopservices_mac.cpp
+++ b/src/gui/util/qdesktopservices_mac.cpp
@@ -96,7 +96,7 @@ OSType translateLocation(QDesktopServices::StandardLocation type)
static bool lsOpen(const QUrl &url)
{
- if (!url.isValid())
+ if (!url.isValid() || url.scheme().isEmpty())
return false;
QCFType<CFURLRef> cfUrl = CFURLCreateWithString(0, QCFString(QString::fromLatin1(url.toEncoded())), 0);
@@ -134,13 +134,15 @@ static QString getFullPath(const FSRef &ref)
QString QDesktopServices::storageLocation(StandardLocation type)
{
- if (QDesktopServices::HomeLocation == type)
+ if (type == HomeLocation)
return QDir::homePath();
+ if (type == TempLocation)
+ return QDir::tempPath();
+
short domain = kOnAppropriateDisk;
- if (QDesktopServices::DataLocation == type
- || QDesktopServices::CacheLocation == type)
+ if (type == DataLocation || type == CacheLocation)
domain = kUserDomain;
// http://developer.apple.com/documentation/Carbon/Reference/Folder_Manager/Reference/reference.html
@@ -152,9 +154,8 @@ QString QDesktopServices::storageLocation(StandardLocation type)
QString path = getFullPath(ref);
QString appName = QCoreApplication::applicationName();
- if (!appName.isEmpty() &&
- (QDesktopServices::DataLocation == type || QDesktopServices::CacheLocation == type))
- path += QLatin1String("/") + appName;
+ if (!appName.isEmpty() && (type == DataLocation || type == CacheLocation))
+ path += QLatin1Char('/') + appName;
return path;
}
diff --git a/src/gui/util/qdesktopservices_win.cpp b/src/gui/util/qdesktopservices_win.cpp
index 0449cba..a8aa11c 100644
--- a/src/gui/util/qdesktopservices_win.cpp
+++ b/src/gui/util/qdesktopservices_win.cpp
@@ -98,32 +98,35 @@ static bool launchWebBrowser(const QUrl &url)
{
if (url.scheme() == QLatin1String("mailto")) {
//Retrieve the commandline for the default mail client
- //the key used below is the command line for the mailto: shell command
+ //the default key used below is the command line for the mailto: shell command
DWORD bufferSize = 2 * MAX_PATH;
long returnValue = -1;
QString command;
HKEY handle;
LONG res;
- QT_WA ({
- res = RegOpenKeyExW(HKEY_CLASSES_ROOT, L"mailto\\Shell\\Open\\Command", 0, KEY_READ, &handle);
- if (res != ERROR_SUCCESS)
- return false;
-
- wchar_t keyValue[2 * MAX_PATH] = {0};
- returnValue = RegQueryValueExW(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
- if (!returnValue)
- command = QString::fromRawData((QChar*)keyValue, bufferSize);
- }, {
- res = RegOpenKeyExA(HKEY_CLASSES_ROOT, "mailto\\Shell\\Open\\Command", 0, KEY_READ, &handle);
- if (res != ERROR_SUCCESS)
- return false;
-
- char keyValue[2 * MAX_PATH] = {0};
- returnValue = RegQueryValueExA(handle, "", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
+ wchar_t keyValue[2 * MAX_PATH] = {0};
+ QString keyName(QLatin1String("mailto"));
+
+ //Check if user has set preference, otherwise use default.
+ res = RegOpenKeyExW(HKEY_CURRENT_USER,
+ L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\mailto\\UserChoice",
+ 0, KEY_READ, &handle);
+ if (res == ERROR_SUCCESS) {
+ returnValue = RegQueryValueEx(handle, L"Progid", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
if (!returnValue)
- command = QString::fromLocal8Bit(keyValue);
- });
+ keyName = QString::fromUtf16((const ushort*)keyValue);
+ RegCloseKey(handle);
+ }
+ keyName += QLatin1String("\\Shell\\Open\\Command");
+ res = RegOpenKeyExW(HKEY_CLASSES_ROOT, (const wchar_t*)keyName.utf16(), 0, KEY_READ, &handle);
+ if (res != ERROR_SUCCESS)
+ return false;
+
+ bufferSize = 2 * MAX_PATH;
+ returnValue = RegQueryValueExW(handle, L"", 0, 0, reinterpret_cast<unsigned char*>(keyValue), &bufferSize);
+ if (!returnValue)
+ command = QString::fromRawData((QChar*)keyValue, bufferSize);
RegCloseKey(handle);
if(returnValue)
@@ -145,19 +148,11 @@ static bool launchWebBrowser(const QUrl &url)
//start the process
PROCESS_INFORMATION pi;
ZeroMemory(&pi, sizeof(pi));
- QT_WA ({
- STARTUPINFO si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
-
- returnValue = CreateProcess(NULL, (TCHAR*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
- }, {
- STARTUPINFOA si;
- ZeroMemory(&si, sizeof(si));
- si.cb = sizeof(si);
+ STARTUPINFO si;
+ ZeroMemory(&si, sizeof(si));
+ si.cb = sizeof(si);
- returnValue = CreateProcessA(NULL, command.toLocal8Bit().data(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
- });
+ returnValue = CreateProcess(NULL, (TCHAR*)command.utf16(), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
if (!returnValue)
return false;
@@ -170,12 +165,12 @@ static bool launchWebBrowser(const QUrl &url)
if (!url.isValid())
return false;
+ if (url.scheme().isEmpty())
+ return openDocument(url);
+
quintptr returnValue;
- QT_WA ({
- returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *) QString::fromUtf8(url.toEncoded().constData()).utf16(), 0, 0, SW_SHOWNORMAL);
- } , {
- returnValue = (quintptr)ShellExecuteA(0, 0, url.toEncoded().constData(), 0, 0, SW_SHOWNORMAL);
- });
+ returnValue = (quintptr)ShellExecute(0, 0, (TCHAR *) QString::fromUtf8(url.toEncoded().constData()).utf16(),
+ 0, 0, SW_SHOWNORMAL);
return (returnValue > 32);
}
diff --git a/src/gui/util/qdesktopservices_x11.cpp b/src/gui/util/qdesktopservices_x11.cpp
index b3486e8..8c4a597 100644
--- a/src/gui/util/qdesktopservices_x11.cpp
+++ b/src/gui/util/qdesktopservices_x11.cpp
@@ -164,8 +164,8 @@ QString QDesktopServices::storageLocation(StandardLocation type)
QString key = lst.at(1);
QString value = lst.at(2);
if (value.length() > 2
- && value.startsWith(QLatin1String("\""))
- && value.endsWith(QLatin1String("\"")))
+ && value.startsWith(QLatin1Char('\"'))
+ && value.endsWith(QLatin1Char('\"')))
value = value.mid(1, value.length() - 2);
// Store the key and value: "DESKTOP", "$HOME/Desktop"
lines[key] = value;
diff --git a/src/gui/util/qsystemtrayicon.cpp b/src/gui/util/qsystemtrayicon.cpp
index 2e072c5..bfafe44 100644
--- a/src/gui/util/qsystemtrayicon.cpp
+++ b/src/gui/util/qsystemtrayicon.cpp
@@ -434,13 +434,13 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
titleLabel->setText(title);
QFont f = titleLabel->font();
f.setBold(true);
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
f.setPointSize(f.pointSize() - 2);
#endif
titleLabel->setFont(f);
titleLabel->setTextFormat(Qt::PlainText); // to maintain compat with windows
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
const int iconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
const int closeButtonSize = style()->pixelMetric(QStyle::PM_SmallIconSize) - 2;
#else
@@ -456,7 +456,7 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
QObject::connect(closeButton, SIGNAL(clicked()), this, SLOT(close()));
QLabel *msgLabel = new QLabel;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
f.setBold(false);
msgLabel->setFont(f);
#endif
@@ -466,7 +466,7 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
msgLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
// smart size for the message label
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 2;
#else
int limit = QApplication::desktop()->availableGeometry(msgLabel).size().width() / 3;
@@ -481,7 +481,7 @@ QBalloonTip::QBalloonTip(QSystemTrayIcon::MessageIcon icon, const QString& title
control->document()->setDefaultTextOption(opt);
}
}
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// Make sure that the text isn't wrapped "somewhere" in the balloon widget
// in the case that we have a long title label.
setMaximumWidth(limit);
diff --git a/src/gui/util/qsystemtrayicon_win.cpp b/src/gui/util/qsystemtrayicon_win.cpp
index 84f9de4..f79f135 100644
--- a/src/gui/util/qsystemtrayicon_win.cpp
+++ b/src/gui/util/qsystemtrayicon_win.cpp
@@ -62,13 +62,13 @@
#include <QDesktopWidget>
#include <QSettings>
-#if defined(Q_OS_WINCE) && !defined(STANDARDSHELL_UI_MODEL)
+#if defined(Q_WS_WINCE) && !defined(STANDARDSHELL_UI_MODEL)
# include <streams.h>
#endif
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WINCE)
+#if defined(Q_WS_WINCE)
static const UINT q_uNOTIFYICONID = 13; // IDs from 0 to 12 are reserved on WinCE.
#else
static const UINT q_uNOTIFYICONID = 0;
@@ -331,7 +331,7 @@ bool QSystemTrayIconSys::showMessageA(const QString &title, const QString &messa
bool QSystemTrayIconSys::trayMessageA(DWORD msg)
{
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
NOTIFYICONDATAA tnd;
memset(&tnd, 0, notifyIconSizeA);
tnd.uID = q_uNOTIFYICONID;
@@ -462,7 +462,7 @@ bool QSystemTrayIconSys::winEvent( MSG *m, long *result )
emit q->activated(QSystemTrayIcon::Trigger);
break;
-#if !defined(Q_OS_WINCE)
+#if !defined(Q_WS_WINCE)
case WM_LBUTTONDBLCLK:
emit q->activated(QSystemTrayIcon::DoubleClick);
break;
@@ -518,7 +518,7 @@ void QSystemTrayIconPrivate::install_sys()
QRect QSystemTrayIconSys::findTrayGeometry()
{
//Use lower right corner as fallback
- QPoint brCorner = qApp->desktop()->screenGeometry().bottomRight();
+ QPoint brCorner = QApplication::desktop()->screenGeometry().bottomRight();
QRect ret(brCorner.x() - 10, brCorner.y() - 10, 10, 10);
#if defined(Q_OS_WINCE)
HWND trayHandle = FindWindowW(L"Shell_TrayWnd", NULL);
@@ -662,7 +662,7 @@ void QSystemTrayIconPrivate::showMessage_sys(const QString &title, const QString
//message is limited to 255 chars + NULL
QString messageString;
if (message.isEmpty() && !title.isEmpty())
- messageString = QLatin1String(" "); //ensures that the message shows when only title is set
+ messageString = QLatin1Char(' '); //ensures that the message shows when only title is set
else
messageString = message.left(255) + QChar();
@@ -726,7 +726,7 @@ void QSystemTrayIconPrivate::updateMenu_sys()
void QSystemTrayIconPrivate::updateToolTip_sys()
{
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
// Calling sys->trayMessage(NIM_MODIFY) on an existing icon is broken on Windows CE.
// So we need to call updateIcon_sys() which creates a new icon handle.
updateIcon_sys();
diff --git a/src/gui/widgets/qabstractbutton.cpp b/src/gui/widgets/qabstractbutton.cpp
index 61ed0ea..6337b5c 100644
--- a/src/gui/widgets/qabstractbutton.cpp
+++ b/src/gui/widgets/qabstractbutton.cpp
@@ -215,11 +215,8 @@ void QButtonGroup::setExclusive(bool exclusive)
d->exclusive = exclusive;
}
-/*!
- Adds the given \a button to the end of the group's internal list of buttons.
- \sa removeButton()
-*/
+// TODO: Qt 5: Merge with addButton(QAbstractButton *button, int id)
void QButtonGroup::addButton(QAbstractButton *button)
{
addButton(button, -1);
@@ -232,8 +229,18 @@ void QButtonGroup::addButton(QAbstractButton *button, int id)
previous->removeButton(button);
button->d_func()->group = this;
d->buttonList.append(button);
- if (id != -1)
+ if (id == -1) {
+ QList<int> ids = d->mapping.values();
+ if (ids.isEmpty())
+ d->mapping[button] = -2;
+ else {
+ qSort(ids);
+ d->mapping[button] = ids.first()-1;
+ }
+ } else {
d->mapping[button] = id;
+ }
+
if (d->exclusive && button->isChecked())
button->d_func()->notifyChecked();
}
@@ -312,20 +319,16 @@ QList<QAbstractButton *>QAbstractButtonPrivate::queryButtonList() const
return group->d_func()->buttonList;
#endif
- Q_Q(const QAbstractButton);
- QList<QAbstractButton*>candidates;
- if (q->parentWidget()) {
- candidates = qFindChildren<QAbstractButton *>(q->parentWidget());
- if (autoExclusive) {
- for (int i = candidates.count() - 1; i >= 0; --i) {
- QAbstractButton *candidate = candidates.at(i);
- if (!candidate->autoExclusive()
+ QList<QAbstractButton*>candidates = qFindChildren<QAbstractButton *>(parent);
+ if (autoExclusive) {
+ for (int i = candidates.count() - 1; i >= 0; --i) {
+ QAbstractButton *candidate = candidates.at(i);
+ if (!candidate->autoExclusive()
#ifndef QT_NO_BUTTONGROUP
- || candidate->group()
+ || candidate->group()
#endif
- )
- candidates.removeAt(i);
- }
+ )
+ candidates.removeAt(i);
}
}
return candidates;
@@ -376,7 +379,7 @@ void QAbstractButtonPrivate::moveFocus(int key)
#else
bool exclusive = autoExclusive;
#endif
- QWidget *f = qApp->focusWidget();
+ QWidget *f = QApplication::focusWidget();
QAbstractButton *fb = qobject_cast<QAbstractButton *>(f);
if (!fb || !buttonList.contains(fb))
return;
@@ -1236,7 +1239,9 @@ void QAbstractButton::timerEvent(QTimerEvent *e)
d->repeatTimer.start(d->autoRepeatInterval, this);
if (d->down) {
QPointer<QAbstractButton> guard(this);
- d->emitReleased();
+ nextCheckState();
+ if (guard)
+ d->emitReleased();
if (guard)
d->emitClicked();
if (guard)
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 1ff56e8..de43616 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -884,21 +884,22 @@ bool QAbstractScrollArea::event(QEvent *e)
case QEvent::Resize:
d->layoutChildren();
break;
- case QEvent::Paint:
+ case QEvent::Paint: {
+ QStyleOption option;
+ option.initFrom(this);
if (d->cornerPaintingRect.isValid()) {
- QStyleOption option;
option.rect = d->cornerPaintingRect;
QPainter p(this);
style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
}
#ifdef Q_WS_MAC
if (d->reverseCornerPaintingRect.isValid()) {
- QStyleOption option;
option.rect = d->reverseCornerPaintingRect;
QPainter p(this);
style()->drawPrimitive(QStyle::PE_PanelScrollAreaCorner, &option, &p, this);
}
#endif
+ }
QFrame::paintEvent((QPaintEvent*)e);
break;
#ifndef QT_NO_CONTEXTMENU
@@ -1275,6 +1276,12 @@ QSize QAbstractScrollArea::minimumSizeHint() const
int hsbExt = d->hbar->sizeHint().height();
int vsbExt = d->vbar->sizeHint().width();
int extra = 2 * d->frameWidth;
+ QStyleOption opt;
+ opt.initFrom(this);
+ if ((d->frameStyle != QFrame::NoFrame)
+ && style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, &opt, this)) {
+ extra += style()->pixelMetric(QStyle::PM_ScrollView_ScrollBarSpacing, &opt, this);
+ }
return QSize(d->scrollBarContainers[Qt::Horizontal]->sizeHint().width() + vsbExt + extra,
d->scrollBarContainers[Qt::Vertical]->sizeHint().height() + hsbExt + extra);
}
diff --git a/src/gui/widgets/qabstractscrollarea_p.h b/src/gui/widgets/qabstractscrollarea_p.h
index 999bdfc..ebdd281 100644
--- a/src/gui/widgets/qabstractscrollarea_p.h
+++ b/src/gui/widgets/qabstractscrollarea_p.h
@@ -62,7 +62,7 @@ QT_BEGIN_NAMESPACE
class QScrollBar;
class QAbstractScrollAreaScrollBarContainer;
-class Q_GUI_EXPORT QAbstractScrollAreaPrivate: public QFramePrivate
+class QAbstractScrollAreaPrivate: public QFramePrivate
{
Q_DECLARE_PUBLIC(QAbstractScrollArea)
diff --git a/src/gui/widgets/qabstractspinbox.cpp b/src/gui/widgets/qabstractspinbox.cpp
index 2bf1cda..d52af19 100644
--- a/src/gui/widgets/qabstractspinbox.cpp
+++ b/src/gui/widgets/qabstractspinbox.cpp
@@ -193,6 +193,7 @@ void QAbstractSpinBox::setButtonSymbols(ButtonSymbols buttonSymbols)
Q_D(QAbstractSpinBox);
if (d->buttonSymbols != buttonSymbols) {
d->buttonSymbols = buttonSymbols;
+ d->updateEditFieldGeometry();
update();
}
}
@@ -1791,8 +1792,8 @@ void QAbstractSpinBoxPrivate::interpret(EmitPolicy ep)
q->fixup(tmp);
QASBDEBUG() << "QAbstractSpinBoxPrivate::interpret() text '"
<< edit->displayText()
- << "' >> '" << copy << "'"
- << "' >> '" << tmp << "'";
+ << "' >> '" << copy << '\''
+ << "' >> '" << tmp << '\'';
doInterpret = tmp != copy && (q->validate(tmp, pos) == QValidator::Acceptable);
if (!doInterpret) {
diff --git a/src/gui/widgets/qbuttongroup.cpp b/src/gui/widgets/qbuttongroup.cpp
index 06bcf1e..1003523 100644
--- a/src/gui/widgets/qbuttongroup.cpp
+++ b/src/gui/widgets/qbuttongroup.cpp
@@ -176,11 +176,22 @@
*/
/*!
- \fn void QButtonGroup::addButton(QAbstractButton *button, int id = -1);
+ \fn void QButtonGroup::addButton(QAbstractButton *button);
+
+ Adds the given \a button to the end of the group's internal list
+ of buttons. An id will be assigned to the button by this
+ QButtonGroup. Automatically assigned ids are guaranteed to be
+ negative, starting with -2. If you are also assigning your own
+ ids, use positive values to avoid conflicts.
+
+ \sa removeButton() buttons()
+*/
+
+/*!
+ \fn void QButtonGroup::addButton(QAbstractButton *button, int id);
Adds the given \a button to the button group, with the given \a
- id. If \a id is -1 (the default), an id will be assigned to the
- button by this QButtonGroup.
+ id. It is recommended to assign only positive ids.
\sa removeButton() buttons()
*/
diff --git a/src/gui/widgets/qcalendarwidget.cpp b/src/gui/widgets/qcalendarwidget.cpp
index 4436c04..8703139 100644
--- a/src/gui/widgets/qcalendarwidget.cpp
+++ b/src/gui/widgets/qcalendarwidget.cpp
@@ -198,7 +198,7 @@ QString QCalendarDayValidator::text() const
{
QString str;
if (m_day / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
str += QString::number(m_day);
return highlightString(str, m_pos);
}
@@ -210,7 +210,7 @@ QString QCalendarDayValidator::text(const QDate &date, int repeat) const
} else if (repeat == 2) {
QString str;
if (date.day() / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
return str + QString::number(date.day());
} else if (repeat == 3) {
return m_locale.dayName(date.dayOfWeek(), QLocale::ShortFormat);
@@ -316,7 +316,7 @@ QString QCalendarMonthValidator::text() const
{
QString str;
if (m_month / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
str += QString::number(m_month);
return highlightString(str, m_pos);
}
@@ -328,7 +328,7 @@ QString QCalendarMonthValidator::text(const QDate &date, int repeat) const
} else if (repeat == 2) {
QString str;
if (date.month() / 10 == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
return str + QString::number(date.month());
} else if (repeat == 3) {
return m_locale.standaloneMonthName(date.month(), QLocale::ShortFormat);
@@ -432,7 +432,7 @@ QString QCalendarYearValidator::text() const
int pow = 10;
for (int i = 0; i < 3; i++) {
if (m_year / pow == 0)
- str += QLatin1String("0");
+ str += QLatin1Char('0');
pow *= 10;
}
str += QString::number(m_year);
@@ -445,7 +445,7 @@ QString QCalendarYearValidator::text(const QDate &date, int repeat) const
QString str;
int year = date.year() % 100;
if (year / 10 == 0)
- str = QLatin1String("0");
+ str = QLatin1Char('0');
return str + QString::number(year);
}
return QString::number(date.year());
@@ -577,7 +577,7 @@ void QCalendarDateValidator::setFormat(const QString &format)
clear();
int pos = 0;
- const QLatin1String quote("'");
+ const QLatin1Char quote('\'');
bool quoting = false;
QString separator;
while (pos < format.size()) {
diff --git a/src/gui/widgets/qcombobox.cpp b/src/gui/widgets/qcombobox.cpp
index a6a5e08..bd01da0 100644
--- a/src/gui/widgets/qcombobox.cpp
+++ b/src/gui/widgets/qcombobox.cpp
@@ -953,6 +953,7 @@ QComboBoxPrivateContainer* QComboBoxPrivate::viewContainer()
container->itemView()->setTextElideMode(Qt::ElideMiddle);
updateDelegate(true);
updateLayoutDirection();
+ updateViewContainerPaletteAndOpacity();
QObject::connect(container, SIGNAL(itemSelected(QModelIndex)),
q, SLOT(_q_itemSelected(QModelIndex)));
QObject::connect(container->itemView()->selectionModel(),
@@ -1055,6 +1056,27 @@ void QComboBoxPrivate::_q_rowsRemoved(const QModelIndex &parent, int /*start*/,
}
+void QComboBoxPrivate::updateViewContainerPaletteAndOpacity()
+{
+ if (!container)
+ return;
+ Q_Q(QComboBox);
+ QStyleOptionComboBox opt;
+ q->initStyleOption(&opt);
+#ifndef QT_NO_MENU
+ if (q->style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, q)) {
+ QMenu menu;
+ menu.ensurePolished();
+ container->setPalette(menu.palette());
+ container->setWindowOpacity(menu.windowOpacity());
+ } else
+#endif
+ {
+ container->setPalette(q->palette());
+ container->setWindowOpacity(1.0);
+ }
+}
+
/*!
Initialize \a option with the values from this QComboBox. This method
is useful for subclasses when they need a QStyleOptionComboBox, but don't want
@@ -2591,20 +2613,7 @@ void QComboBox::changeEvent(QEvent *e)
hidePopup();
break;
case QEvent::PaletteChange: {
- QStyleOptionComboBox opt;
- initStyleOption(&opt);
-#ifndef QT_NO_MENU
- if (style()->styleHint(QStyle::SH_ComboBox_Popup, &opt, this)) {
- QMenu menu;
- menu.ensurePolished();
- d->viewContainer()->setPalette(menu.palette());
- d->viewContainer()->setWindowOpacity(menu.windowOpacity());
- } else
-#endif
- {
- d->viewContainer()->setPalette(palette());
- d->viewContainer()->setWindowOpacity(1.0);
- }
+ d->updateViewContainerPaletteAndOpacity();
break;
}
case QEvent::FontChange:
diff --git a/src/gui/widgets/qcombobox_p.h b/src/gui/widgets/qcombobox_p.h
index a55b439..0998e52 100644
--- a/src/gui/widgets/qcombobox_p.h
+++ b/src/gui/widgets/qcombobox_p.h
@@ -290,7 +290,7 @@ public:
QComboBoxDelegate(QObject *parent, QComboBox *cmb) : QItemDelegate(parent), mCombo(cmb) {}
static bool isSeparator(const QModelIndex &index) {
- return index.data(Qt::AccessibleDescriptionRole).toString() == QString::fromLatin1("separator");
+ return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
}
static void setSeparator(QAbstractItemModel *model, const QModelIndex &index) {
model->setData(index, QString::fromLatin1("separator"), Qt::AccessibleDescriptionRole);
@@ -370,6 +370,7 @@ public:
void updateDelegate(bool force = false);
void keyboardSearchString(const QString &text);
void modelChanged();
+ void updateViewContainerPaletteAndOpacity();
QAbstractItemModel *model;
QLineEdit *lineEdit;
diff --git a/src/gui/widgets/qcommandlinkbutton.cpp b/src/gui/widgets/qcommandlinkbutton.cpp
index 13ee6af..92d89a1 100644
--- a/src/gui/widgets/qcommandlinkbutton.cpp
+++ b/src/gui/widgets/qcommandlinkbutton.cpp
@@ -140,10 +140,12 @@ QFont QCommandLinkButtonPrivate::titleFont() const
Q_Q(const QCommandLinkButton);
QFont font = q->font();
if (usingVistaStyle()) {
- font.setPointSizeF(12.0);
+ if (!q->testAttribute(Qt::WA_SetFont))
+ font.setPointSizeF(12.0);
} else {
font.setBold(true);
- font.setPointSizeF(9.0);
+ if (!q->testAttribute(Qt::WA_SetFont))
+ font.setPointSizeF(9.0);
}
return font;
}
@@ -152,7 +154,8 @@ QFont QCommandLinkButtonPrivate::descriptionFont() const
{
Q_Q(const QCommandLinkButton);
QFont font = q->font();
- font.setPointSizeF(9.0);
+ if (!q->testAttribute(Qt::WA_SetFont))
+ font.setPointSizeF(9.0);
return font;
}
diff --git a/src/gui/widgets/qdatetimeedit.cpp b/src/gui/widgets/qdatetimeedit.cpp
index 4d34691..4d47a50 100644
--- a/src/gui/widgets/qdatetimeedit.cpp
+++ b/src/gui/widgets/qdatetimeedit.cpp
@@ -220,6 +220,9 @@ QDateTimeEdit::QDateTimeEdit(const QVariant &var, QVariant::Type parserType, QWi
\property QDateTimeEdit::dateTime
\brief the QDateTime that is set in the QDateTimeEdit
+ When setting this property the timespec of the QDateTimeEdit remains the same
+ and the timespec of the new QDateTime is ignored.
+
By default, this property contains a date that refers to January 1,
2000 and a time of 00:00:00 and 0 milliseconds.
@@ -239,7 +242,7 @@ void QDateTimeEdit::setDateTime(const QDateTime &datetime)
d->clearCache();
if (!(d->sections & DateSections_Mask))
setDateRange(datetime.date(), datetime.date());
- d->setValue(QVariant(datetime), EmitIfChanged);
+ d->setValue(QDateTime(datetime.date(), datetime.time(), d->spec), EmitIfChanged);
}
}
@@ -932,9 +935,6 @@ void QDateTimeEdit::setCalendarPopup(bool enable)
\property QDateTimeEdit::timeSpec
\brief the current timespec used by the date time edit.
\since 4.4
-
- All dates/passed to the date time edit will be converted to this
- timespec.
*/
Qt::TimeSpec QDateTimeEdit::timeSpec() const
diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp
index 4f0ec1e..58e8f9c 100644
--- a/src/gui/widgets/qdockarealayout.cpp
+++ b/src/gui/widgets/qdockarealayout.cpp
@@ -2202,8 +2202,8 @@ QSet<QWidget*> QDockAreaLayoutInfo::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- foreach (QWidget *sepWidget, separatorWidgets)
- result << sepWidget;
+ for (int i = 0; i < separatorWidgets.count(); ++i)
+ result << separatorWidgets.at(i);
for (int i = 0; i < item_list.count(); ++i) {
const QDockAreaLayoutItem &item = item_list.at(i);
@@ -3244,8 +3244,8 @@ QSet<QWidget*> QDockAreaLayout::usedSeparatorWidgets() const
{
QSet<QWidget*> result;
- foreach (QWidget *sepWidget, separatorWidgets)
- result << sepWidget;
+ for (int i = 0; i < separatorWidgets.count(); ++i)
+ result << separatorWidgets.at(i);
for (int i = 0; i < QInternal::DockCount; ++i) {
const QDockAreaLayoutInfo &dock = docks[i];
result += dock.usedSeparatorWidgets();
diff --git a/src/gui/widgets/qdockwidget.cpp b/src/gui/widgets/qdockwidget.cpp
index a5be5f8..e20fedd 100644
--- a/src/gui/widgets/qdockwidget.cpp
+++ b/src/gui/widgets/qdockwidget.cpp
@@ -69,6 +69,9 @@ extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); /
extern QHash<QByteArray, QFont> *qt_app_fonts_hash(); // qapplication.cpp
+static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature)
+{ return (priv->features & feature) == feature; }
+
static inline bool hasFeature(const QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature)
{ return (dockwidget->features() & feature) == feature; }
@@ -203,7 +206,7 @@ bool QDockWidgetLayout::nativeWindowDeco() const
bool QDockWidgetLayout::nativeWindowDeco(bool floating) const
{
-#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_WINCE)
+#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_WINCE)
Q_UNUSED(floating);
return false;
#else
@@ -221,7 +224,8 @@ void QDockWidgetLayout::addItem(QLayoutItem*)
QLayoutItem *QDockWidgetLayout::itemAt(int index) const
{
int cnt = 0;
- foreach (QLayoutItem *item, item_list) {
+ for (int i = 0; i < item_list.count(); ++i) {
+ QLayoutItem *item = item_list.at(i);
if (item == 0)
continue;
if (index == cnt++)
@@ -250,8 +254,8 @@ QLayoutItem *QDockWidgetLayout::takeAt(int index)
int QDockWidgetLayout::count() const
{
int result = 0;
- foreach (QLayoutItem *item, item_list) {
- if (item != 0)
+ for (int i = 0; i < item_list.count(); ++i) {
+ if (item_list.at(i))
++result;
}
return result;
@@ -646,25 +650,25 @@ void QDockWidgetPrivate::_q_toggleView(bool b)
void QDockWidgetPrivate::updateButtons()
{
Q_Q(QDockWidget);
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
QStyleOptionDockWidget opt;
q->initStyleOption(&opt);
- bool customTitleBar = layout->widgetForRole(QDockWidgetLayout::TitleBar) != 0;
- bool nativeDeco = layout->nativeWindowDeco();
+ bool customTitleBar = dwLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0;
+ bool nativeDeco = dwLayout->nativeWindowDeco();
bool hideButtons = nativeDeco || customTitleBar;
- bool canClose = hasFeature(q, QDockWidget::DockWidgetClosable);
- bool canFloat = hasFeature(q, QDockWidget::DockWidgetFloatable);
+ bool canClose = hasFeature(this, QDockWidget::DockWidgetClosable);
+ bool canFloat = hasFeature(this, QDockWidget::DockWidgetFloatable);
QAbstractButton *button
- = qobject_cast<QAbstractButton*>(layout->widgetForRole(QDockWidgetLayout::FloatButton));
+ = qobject_cast<QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::FloatButton));
button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarNormalButton, &opt, q));
button->setVisible(canFloat && !hideButtons);
button
- = qobject_cast <QAbstractButton*>(layout->widgetForRole(QDockWidgetLayout::CloseButton));
+ = qobject_cast <QAbstractButton*>(dwLayout->widgetForRole(QDockWidgetLayout::CloseButton));
button->setIcon(q->style()->standardIcon(QStyle::SP_TitleBarCloseButton, &opt, q));
button->setVisible(canClose && !hideButtons);
@@ -687,7 +691,7 @@ void QDockWidgetPrivate::initDrag(const QPoint &pos, bool nca)
if (state != 0)
return;
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
@@ -740,15 +744,15 @@ void QDockWidgetPrivate::endDrag(bool abort)
q->releaseMouse();
if (state->dragging) {
- QMainWindowLayout *layout =
+ QMainWindowLayout *mwLayout =
qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
- Q_ASSERT(layout != 0);
+ Q_ASSERT(mwLayout != 0);
- if (abort || !layout->plug(state->widgetItem)) {
- if (hasFeature(q, QDockWidget::DockWidgetFloatable)) {
+ if (abort || !mwLayout->plug(state->widgetItem)) {
+ if (hasFeature(this, QDockWidget::DockWidgetFloatable)) {
if (state->ownWidgetItem)
delete state->widgetItem;
- layout->restore();
+ mwLayout->restore();
#ifdef Q_WS_X11
// get rid of the X11BypassWindowManager window flag and activate the resizer
Qt::WindowFlags flags = q->windowFlags();
@@ -758,14 +762,14 @@ void QDockWidgetPrivate::endDrag(bool abort)
q->show();
#else
QDockWidgetLayout *myLayout
- = qobject_cast<QDockWidgetLayout*>(q->layout());
+ = qobject_cast<QDockWidgetLayout*>(layout);
resizer->setActive(QWidgetResizeHandler::Resize,
myLayout->widgetForRole(QDockWidgetLayout::TitleBar) != 0);
#endif
undockedGeometry = q->geometry();
q->activateWindow();
} else {
- layout->revert(state->widgetItem);
+ mwLayout->revert(state->widgetItem);
}
}
}
@@ -777,7 +781,7 @@ bool QDockWidgetPrivate::isAnimating() const
{
Q_Q(const QDockWidget);
- QMainWindow *mainWin = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *mainWin = qobject_cast<QMainWindow*>(parent);
if (mainWin == 0)
return false;
@@ -794,18 +798,18 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
#if !defined(QT_NO_MAINWINDOW)
Q_Q(QDockWidget);
- QDockWidgetLayout *layout
- = qobject_cast<QDockWidgetLayout*>(q->layout());
+ QDockWidgetLayout *dwLayout
+ = qobject_cast<QDockWidgetLayout*>(layout);
- if (!layout->nativeWindowDeco()) {
- QRect titleArea = layout->titleArea();
+ if (!dwLayout->nativeWindowDeco()) {
+ QRect titleArea = dwLayout->titleArea();
if (event->button() != Qt::LeftButton ||
!titleArea.contains(event->pos()) ||
// check if the tool window is movable... do nothing if it
// is not (but allow moving if the window is floating)
- (!hasFeature(q, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
- qobject_cast<QMainWindow*>(q->parentWidget()) == 0 ||
+ (!hasFeature(this, QDockWidget::DockWidgetMovable) && !q->isFloating()) ||
+ qobject_cast<QMainWindow*>(parent) == 0 ||
isAnimating() || state != 0) {
return false;
}
@@ -813,7 +817,7 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
initDrag(event->pos(), false);
if (state)
- state->ctrlDrag = hasFeature(q, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier;
+ state->ctrlDrag = hasFeature(this, QDockWidget::DockWidgetFloatable) && event->modifiers() & Qt::ControlModifier;
return true;
}
@@ -824,15 +828,13 @@ bool QDockWidgetPrivate::mousePressEvent(QMouseEvent *event)
bool QDockWidgetPrivate::mouseDoubleClickEvent(QMouseEvent *event)
{
- Q_Q(QDockWidget);
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
-
- if (!layout->nativeWindowDeco()) {
- QRect titleArea = layout->titleArea();
+ if (!dwLayout->nativeWindowDeco()) {
+ QRect titleArea = dwLayout->titleArea();
if (event->button() == Qt::LeftButton && titleArea.contains(event->pos()) &&
- hasFeature(q, QDockWidget::DockWidgetFloatable)) {
+ hasFeature(this, QDockWidget::DockWidgetFloatable)) {
_q_toggleTopLevel();
return true;
}
@@ -850,7 +852,7 @@ bool QDockWidgetPrivate::mouseMoveEvent(QMouseEvent *event)
return ret;
QDockWidgetLayout *dwlayout
- = qobject_cast<QDockWidgetLayout*>(q->layout());
+ = qobject_cast<QDockWidgetLayout*>(layout);
QMainWindowLayout *mwlayout
= qobject_cast<QMainWindowLayout*>(q->parentWidget()->layout());
if (!dwlayout->nativeWindowDeco()) {
@@ -923,7 +925,7 @@ void QDockWidgetPrivate::nonClientAreaMouseEvent(QMouseEvent *event)
break;
if (state != 0)
break;
- if (qobject_cast<QMainWindow*>(q->parentWidget()) == 0)
+ if (qobject_cast<QMainWindow*>(parent) == 0)
break;
if (isAnimating())
break;
@@ -996,9 +998,9 @@ void QDockWidgetPrivate::unplug(const QRect &rect)
Q_Q(QDockWidget);
QRect r = rect;
r.moveTopLeft(q->mapToGlobal(QPoint(0, 0)));
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
- if (layout->nativeWindowDeco(true))
- r.adjust(0, layout->titleHeight(), 0, 0);
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
+ if (dwLayout->nativeWindowDeco(true))
+ r.adjust(0, dwLayout->titleHeight(), 0, 0);
setWindowState(true, true, r);
}
@@ -1019,12 +1021,12 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
Qt::WindowFlags flags = floating ? Qt::Tool : Qt::Widget;
- QDockWidgetLayout *layout = qobject_cast<QDockWidgetLayout*>(q->layout());
- const bool nativeDeco = layout->nativeWindowDeco(floating);
+ QDockWidgetLayout *dwLayout = qobject_cast<QDockWidgetLayout*>(layout);
+ const bool nativeDeco = dwLayout->nativeWindowDeco(floating);
if (nativeDeco) {
flags |= Qt::CustomizeWindowHint | Qt::WindowTitleHint;
- if (hasFeature(q, QDockWidget::DockWidgetClosable))
+ if (hasFeature(this, QDockWidget::DockWidgetClosable))
flags |= Qt::WindowCloseButtonHint;
} else {
flags |= Qt::FramelessWindowHint;
@@ -1051,7 +1053,7 @@ void QDockWidgetPrivate::setWindowState(bool floating, bool unplug, const QRect
if (floating != wasFloating) {
emit q->topLevelChanged(floating);
- if (!floating && q->parentWidget()) {
+ if (!floating && parent) {
QMainWindowLayout *mwlayout = qobject_cast<QMainWindowLayout *>(q->parentWidget()->layout());
if (mwlayout)
emit q->dockLocationChanged(mwlayout->dockWidgetArea(q));
diff --git a/src/gui/widgets/qeffects.cpp b/src/gui/widgets/qeffects.cpp
index 140953d..19cdf89 100644
--- a/src/gui/widgets/qeffects.cpp
+++ b/src/gui/widgets/qeffects.cpp
@@ -588,8 +588,8 @@ void qScrollEffect(QWidget* w, QEffects::DirFlags orient, int time)
if (!w)
return;
- qApp->sendPostedEvents(w, QEvent::Move);
- qApp->sendPostedEvents(w, QEvent::Resize);
+ QApplication::sendPostedEvents(w, QEvent::Move);
+ QApplication::sendPostedEvents(w, QEvent::Resize);
Qt::WindowFlags flags = Qt::ToolTip;
// those can be popups - they would steal the focus, but are disabled
@@ -610,8 +610,8 @@ void qFadeEffect(QWidget* w, int time)
if (!w)
return;
- qApp->sendPostedEvents(w, QEvent::Move);
- qApp->sendPostedEvents(w, QEvent::Resize);
+ QApplication::sendPostedEvents(w, QEvent::Move);
+ QApplication::sendPostedEvents(w, QEvent::Resize);
Qt::WindowFlags flags = Qt::ToolTip;
diff --git a/src/gui/widgets/qframe.cpp b/src/gui/widgets/qframe.cpp
index 6f81331..22a990b 100644
--- a/src/gui/widgets/qframe.cpp
+++ b/src/gui/widgets/qframe.cpp
@@ -59,8 +59,7 @@ QFramePrivate::QFramePrivate()
midLineWidth(0),
frameWidth(0),
leftFrameWidth(0), rightFrameWidth(0),
- topFrameWidth(0), bottomFrameWidth(0),
- oldFrameStyle(QFrame::NoFrame | QFrame::Plain)
+ topFrameWidth(0), bottomFrameWidth(0)
{
}
@@ -333,7 +332,6 @@ void QFrame::setFrameStyle(int style)
d->frameStyle = (short)style;
update();
d->updateFrameWidth();
- d->oldFrameStyle = (short)style;
}
/*!
diff --git a/src/gui/widgets/qframe_p.h b/src/gui/widgets/qframe_p.h
index 4fd341d..537f5bf 100644
--- a/src/gui/widgets/qframe_p.h
+++ b/src/gui/widgets/qframe_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class Q_GUI_EXPORT QFramePrivate : public QWidgetPrivate
+class QFramePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QFrame)
public:
@@ -74,7 +74,6 @@ public:
short frameWidth;
short leftFrameWidth, rightFrameWidth;
short topFrameWidth, bottomFrameWidth;
- short oldFrameStyle;
inline void init();
diff --git a/src/gui/widgets/qgroupbox.cpp b/src/gui/widgets/qgroupbox.cpp
index 6a82483..876c5d6 100644
--- a/src/gui/widgets/qgroupbox.cpp
+++ b/src/gui/widgets/qgroupbox.cpp
@@ -644,15 +644,11 @@ bool QGroupBox::isChecked() const
void QGroupBox::setChecked(bool b)
{
Q_D(QGroupBox);
- if (d->checkable) {
- if (d->checked != b)
- update();
- bool wasToggled = (b != d->checked);
+ if (d->checkable && b != d->checked) {
+ update();
d->checked = b;
- if (wasToggled) {
- d->_q_setChildrenEnabled(b);
- emit toggled(b);
- }
+ d->_q_setChildrenEnabled(b);
+ emit toggled(b);
}
}
diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp
index 63c1315..1aef133 100644
--- a/src/gui/widgets/qlabel.cpp
+++ b/src/gui/widgets/qlabel.cpp
@@ -971,6 +971,13 @@ void QLabel::paintEvent(QPaintEvent *)
#endif
if (d->isTextLabel) {
QRectF lr = d->layoutRect();
+ QStyleOption opt;
+ opt.initFrom(this);
+#ifndef QT_NO_STYLE_STYLESHEET
+ if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
+ cssStyle->styleSheetPalette(this, &opt, &opt.palette);
+ }
+#endif
if (d->control) {
#ifndef QT_NO_SHORTCUT
const bool underline = (bool)style->styleHint(QStyle::SH_UnderlineShortcut, 0, this, 0);
@@ -984,11 +991,9 @@ void QLabel::paintEvent(QPaintEvent *)
d->ensureTextLayouted();
QAbstractTextDocumentLayout::PaintContext context;
- QStyleOption opt(0);
- opt.init(this);
if (!isEnabled() && style->styleHint(QStyle::SH_EtchDisabledText, &opt, this)) {
- context.palette = palette();
+ context.palette = opt.palette;
context.palette.setColor(QPalette::Text, context.palette.light().color());
painter.save();
painter.translate(lr.x() + 1, lr.y() + 1);
@@ -999,12 +1004,7 @@ void QLabel::paintEvent(QPaintEvent *)
}
// Adjust the palette
- context.palette = palette();
-#ifndef QT_NO_STYLE_STYLESHEET
- if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style)) {
- cssStyle->focusPalette(this, &opt, &context.palette);
- }
-#endif
+ context.palette = opt.palette;
if (foregroundRole() != QPalette::Text && isEnabled())
context.palette.setColor(QPalette::Text, context.palette.color(foregroundRole()));
@@ -1019,12 +1019,10 @@ void QLabel::paintEvent(QPaintEvent *)
int flags = align;
if (d->hasShortcut) {
flags |= Qt::TextShowMnemonic;
- QStyleOption opt;
- opt.initFrom(this);
if (!style->styleHint(QStyle::SH_UnderlineShortcut, &opt, this))
flags |= Qt::TextHideMnemonic;
}
- style->drawItemText(&painter, lr.toRect(), flags, palette(), isEnabled(), d->text, foregroundRole());
+ style->drawItemText(&painter, lr.toRect(), flags, opt.palette, isEnabled(), d->text, foregroundRole());
}
} else
#ifndef QT_NO_PICTURE
@@ -1172,7 +1170,7 @@ void QLabelPrivate::updateShortcut()
shortcutCursor.deleteChar(); // remove the ampersand
shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
} else {
- if (!text.contains(QLatin1String("&")))
+ if (!text.contains(QLatin1Char('&')))
return;
hasShortcut = true;
shortcutId = q->grabShortcut(QKeySequence::mnemonic(text));
diff --git a/src/gui/widgets/qlcdnumber.cpp b/src/gui/widgets/qlcdnumber.cpp
index af80963..6686d7e 100644
--- a/src/gui/widgets/qlcdnumber.cpp
+++ b/src/gui/widgets/qlcdnumber.cpp
@@ -403,7 +403,7 @@ QLCDNumber::QLCDNumber(QWidget *parent)
Constructs an LCD number, sets the number of digits to \a
numDigits, the base to decimal, the decimal point mode to 'small'
and the frame style to a raised box. The segmentStyle() is set to
- \c Outline.
+ \c Filled.
The \a parent argument is passed to the QFrame constructor.
@@ -427,7 +427,7 @@ void QLCDNumberPrivate::init()
base = QLCDNumber::Dec;
smallPoint = false;
q->setNumDigits(ndigits);
- q->setSegmentStyle(QLCDNumber::Outline);
+ q->setSegmentStyle(QLCDNumber::Filled);
q->setSizePolicy(QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum));
}
@@ -756,6 +756,10 @@ void QLCDNumber::paintEvent(QPaintEvent *)
Q_D(QLCDNumber);
QPainter p(this);
drawFrame(&p);
+ p.setRenderHint(QPainter::Antialiasing);
+ if (d->shadow)
+ p.translate(0.5, 0.5);
+
if (d->smallPoint)
d->drawString(d->digitStr, p, &d->points, false);
else
@@ -1070,7 +1074,7 @@ void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter
q->objectName().toLocal8Bit().constData(), segmentNo);
}
// End exact copy
- p.setPen(fgColor);
+ p.setPen(Qt::NoPen);
p.setBrush(fgColor);
p.drawPolygon(a);
p.setBrush(Qt::NoBrush);
@@ -1218,8 +1222,8 @@ void QLCDNumberPrivate::drawSegment(const QPoint &pos, char segmentNo, QPainter
\header \i Style \i Result
\row \i \c Outline
\i Produces raised segments filled with the background color
- (this is the default).
\row \i \c Filled
+ (this is the default).
\i Produces raised segments filled with the foreground color.
\row \i \c Flat
\i Produces flat segments filled with the foreground color.
diff --git a/src/gui/widgets/qlineedit.cpp b/src/gui/widgets/qlineedit.cpp
index a95d2f2..1778308 100644
--- a/src/gui/widgets/qlineedit.cpp
+++ b/src/gui/widgets/qlineedit.cpp
@@ -79,7 +79,7 @@
#include "private/qapplication_p.h"
#include "private/qshortcutmap_p.h"
#include "qkeysequence.h"
-#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1String("\t") + QString(QKeySequence(k)) : QString())
+#define ACCEL_KEY(k) (!qApp->d_func()->shortcutMap.hasShortcutForKeySequence(k) ? QLatin1Char('\t') + QString(QKeySequence(k)) : QString())
#else
#define ACCEL_KEY(k) QString()
#endif
@@ -2571,7 +2571,7 @@ void QLineEdit::paintEvent(QPaintEvent *)
// draw text, selections and cursors
#ifndef QT_NO_STYLE_STYLESHEET
if (QStyleSheetStyle* cssStyle = qobject_cast<QStyleSheetStyle*>(style())) {
- cssStyle->focusPalette(this, &panel, &pal);
+ cssStyle->styleSheetPalette(this, &panel, &pal);
}
#endif
p.setPen(pal.text().color());
@@ -3577,6 +3577,8 @@ void QLineEditPrivate::redo() {
case RemoveSelection:
case DeleteSelection:
text.remove(cmd.pos, 1);
+ selstart = cmd.selStart;
+ selend = cmd.selEnd;
cursor = cmd.pos;
break;
case Separator:
diff --git a/src/gui/widgets/qmainwindowlayout_mac.mm b/src/gui/widgets/qmainwindowlayout_mac.mm
index c807afb..53e1ad5 100644
--- a/src/gui/widgets/qmainwindowlayout_mac.mm
+++ b/src/gui/widgets/qmainwindowlayout_mac.mm
@@ -502,11 +502,11 @@ void QMainWindowLayout::fixSizeInUnifiedToolbar(QToolBar *tb) const
QMacCocoaAutoReleasePool pool;
QWidgetItem layoutItem(tb);
QSize size = layoutItem.maximumSize();
- NSSize nssize = NSMakeSize(size.width(), size.height());
+ NSSize nssize = NSMakeSize(size.width(), size.height() - 2);
[item setMaxSize:nssize];
size = layoutItem.minimumSize();
nssize.width = size.width();
- nssize.height = size.height();
+ nssize.height = size.height() - 2;
[item setMinSize:nssize];
}
}
diff --git a/src/gui/widgets/qmainwindowlayout_p.h b/src/gui/widgets/qmainwindowlayout_p.h
index 1159aac..24a58a6 100644
--- a/src/gui/widgets/qmainwindowlayout_p.h
+++ b/src/gui/widgets/qmainwindowlayout_p.h
@@ -341,34 +341,4 @@ QT_END_NAMESPACE
#endif // QT_NO_MAINWINDOW
-QT_BEGIN_NAMESPACE
-static inline int pick(Qt::Orientation o, const QPoint &pos)
-{ return o == Qt::Horizontal ? pos.x() : pos.y(); }
-
-static inline int pick(Qt::Orientation o, const QSize &size)
-{ return o == Qt::Horizontal ? size.width() : size.height(); }
-
-static inline int &rpick(Qt::Orientation o, QPoint &pos)
-{ return o == Qt::Horizontal ? pos.rx() : pos.ry(); }
-
-static inline int &rpick(Qt::Orientation o, QSize &size)
-{ return o == Qt::Horizontal ? size.rwidth() : size.rheight(); }
-
-static inline QSizePolicy::Policy pick(Qt::Orientation o, const QSizePolicy &policy)
-{ return o == Qt::Horizontal ? policy.horizontalPolicy() : policy.verticalPolicy(); }
-
-static inline int perp(Qt::Orientation o, const QPoint &pos)
-{ return o == Qt::Vertical ? pos.x() : pos.y(); }
-
-static inline int perp(Qt::Orientation o, const QSize &size)
-{ return o == Qt::Vertical ? size.width() : size.height(); }
-
-static inline int &rperp(Qt::Orientation o, QPoint &pos)
-{ return o == Qt::Vertical ? pos.rx() : pos.ry(); }
-
-static inline int &rperp(Qt::Orientation o, QSize &size)
-{ return o == Qt::Vertical ? size.rwidth() : size.rheight(); }
-
-QT_END_NAMESPACE
-
#endif // QDYNAMICMAINWINDOWLAYOUT_P_H
diff --git a/src/gui/widgets/qmdiarea.cpp b/src/gui/widgets/qmdiarea.cpp
index 6acd977..efaa2d3 100644
--- a/src/gui/widgets/qmdiarea.cpp
+++ b/src/gui/widgets/qmdiarea.cpp
@@ -800,12 +800,12 @@ void QMdiAreaPrivate::appendChild(QMdiSubWindow *child)
Q_Q(QMdiArea);
Q_ASSERT(child && childWindows.indexOf(child) == -1);
- if (child->parent() != q->viewport())
- child->setParent(q->viewport(), child->windowFlags());
+ if (child->parent() != viewport)
+ child->setParent(viewport, child->windowFlags());
childWindows.append(QPointer<QMdiSubWindow>(child));
if (!child->testAttribute(Qt::WA_Resized) && q->isVisible()) {
- QSize newSize(child->sizeHint().boundedTo(q->viewport()->size()));
+ QSize newSize(child->sizeHint().boundedTo(viewport->size()));
child->resize(newSize.expandedTo(qSmartMinSize(child)));
}
@@ -931,7 +931,7 @@ void QMdiAreaPrivate::rearrange(Rearranger *rearranger)
widgets.move(indexToActive, 0);
}
- QRect domain = q->viewport()->rect();
+ QRect domain = viewport->rect();
if (rearranger->type() == Rearranger::RegularTiler && !widgets.isEmpty())
domain = resizeToMinimumTileSize(minSubWindowSize, widgets.count());
@@ -1212,7 +1212,7 @@ void QMdiAreaPrivate::internalRaise(QMdiSubWindow *mdiChild) const
QMdiSubWindow *stackUnderChild = 0;
if (!windowStaysOnTop(mdiChild)) {
- foreach (QObject *object, q_func()->viewport()->children()) {
+ foreach (QObject *object, viewport->children()) {
QMdiSubWindow *child = qobject_cast<QMdiSubWindow *>(object);
if (!child || !childWindows.contains(child))
continue;
@@ -1236,7 +1236,7 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
{
Q_Q(QMdiArea);
if (!minSubWindowSize.isValid() || subWindowCount <= 0)
- return q->viewport()->rect();
+ return viewport->rect();
// Calculate minimum size.
const int columns = qMax(qCeil(qSqrt(qreal(subWindowCount))), 1);
@@ -1255,10 +1255,10 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
// We don't want sub-subwindows to be placed at the edge, thus add 2 pixels.
int minAreaWidth = minWidth + left + right + 2;
int minAreaHeight = minHeight + top + bottom + 2;
- if (q->horizontalScrollBar()->isVisible())
- minAreaHeight += q->horizontalScrollBar()->height();
- if (q->verticalScrollBar()->isVisible())
- minAreaWidth += q->verticalScrollBar()->width();
+ if (hbar->isVisible())
+ minAreaHeight += hbar->height();
+ if (vbar->isVisible())
+ minAreaWidth += vbar->width();
if (q->style()->styleHint(QStyle::SH_ScrollView_FrameOnlyAroundContents, 0, q)) {
const int frame = q->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, q);
minAreaWidth += 2 * frame;
@@ -1268,23 +1268,23 @@ QRect QMdiAreaPrivate::resizeToMinimumTileSize(const QSize &minSubWindowSize, in
topLevel->resize(topLevel->size() + diff);
}
- QRect domain = q->viewport()->rect();
+ QRect domain = viewport->rect();
// Adjust domain width and provide horizontal scroll bar.
if (domain.width() < minWidth) {
domain.setWidth(minWidth);
- if (q->horizontalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
+ if (hbarpolicy == Qt::ScrollBarAlwaysOff)
q->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- else if (q->horizontalScrollBar()->value() != 0)
- q->horizontalScrollBar()->setValue(0);
+ else
+ hbar->setValue(0);
}
// Adjust domain height and provide vertical scroll bar.
if (domain.height() < minHeight) {
domain.setHeight(minHeight);
- if (q->verticalScrollBarPolicy() == Qt::ScrollBarAlwaysOff)
+ if (vbarpolicy == Qt::ScrollBarAlwaysOff)
q->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
- else if (q->verticalScrollBar()->value() != 0)
- q->verticalScrollBar()->setValue(0);
+ else
+ vbar->setValue(0);
}
return domain;
}
diff --git a/src/gui/widgets/qmdisubwindow.cpp b/src/gui/widgets/qmdisubwindow.cpp
index 6bf7633..e5cc6b6 100644
--- a/src/gui/widgets/qmdisubwindow.cpp
+++ b/src/gui/widgets/qmdisubwindow.cpp
@@ -1006,7 +1006,7 @@ void QMdiSubWindowPrivate::removeBaseWidget()
Q_Q(QMdiSubWindow);
baseWidget->removeEventFilter(q);
- if (QLayout *layout = q->layout())
+ if (layout)
layout->removeWidget(baseWidget);
if (baseWidget->windowTitle() == q->windowTitle()) {
ignoreWindowTitleChange = true;
@@ -1102,7 +1102,7 @@ void QMdiSubWindowPrivate::updateCursor()
void QMdiSubWindowPrivate::updateDirtyRegions()
{
// No update necessary
- if (!q_func()->parent())
+ if (!parent)
return;
foreach (Operation operation, operationMap.keys())
@@ -1115,7 +1115,7 @@ void QMdiSubWindowPrivate::updateDirtyRegions()
void QMdiSubWindowPrivate::updateGeometryConstraints()
{
Q_Q(QMdiSubWindow);
- if (!q->parent())
+ if (!parent)
return;
internalMinimumSize = (!q->isMinimized() && !q->minimumSize().isNull())
@@ -1145,7 +1145,7 @@ void QMdiSubWindowPrivate::updateMask()
if (!q->mask().isEmpty())
q->clearMask();
- if (!q->parent())
+ if (!parent)
return;
if ((q->isMaximized() && !drawTitleBarWhenMaximized())
@@ -1168,7 +1168,7 @@ void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
{
Q_Q(QMdiSubWindow);
Q_ASSERT(currentOperation != None);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
uint cflags = operationMap.find(currentOperation).value().changeFlags;
int posX = pos.x();
@@ -1235,7 +1235,7 @@ void QMdiSubWindowPrivate::setNewGeometry(const QPoint &pos)
void QMdiSubWindowPrivate::setMinimizeMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
ensureWindowState(Qt::WindowMinimized);
isShadeRequestFromMinimizeMode = true;
@@ -1263,7 +1263,7 @@ void QMdiSubWindowPrivate::setMinimizeMode()
void QMdiSubWindowPrivate::setNormalMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
isShadeMode = false;
isMaximizeMode = false;
@@ -1334,7 +1334,7 @@ void QMdiSubWindowPrivate::setNormalMode()
void QMdiSubWindowPrivate::setMaximizeMode()
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
ensureWindowState(Qt::WindowMaximized);
isShadeMode = false;
@@ -1423,7 +1423,7 @@ void QMdiSubWindowPrivate::setMaximizeMode()
void QMdiSubWindowPrivate::setActive(bool activate, bool changeFocus)
{
Q_Q(QMdiSubWindow);
- if (!q->parent() || !activationEnabled)
+ if (!parent || !activationEnabled)
return;
if (activate && !isActive && q->isEnabled()) {
@@ -1711,7 +1711,7 @@ void QMdiSubWindowPrivate::ensureWindowState(Qt::WindowState state)
int QMdiSubWindowPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint
|| (q->isMaximized() && !drawTitleBarWhenMaximized())) {
return 0;
}
@@ -1734,7 +1734,7 @@ void QMdiSubWindowPrivate::sizeParameters(int *margin, int *minWidth) const
{
Q_Q(const QMdiSubWindow);
Qt::WindowFlags flags = q->windowFlags();
- if (!q->parent() || flags & Qt::FramelessWindowHint) {
+ if (!parent || flags & Qt::FramelessWindowHint) {
*margin = 0;
*minWidth = 0;
return;
@@ -1772,7 +1772,7 @@ bool QMdiSubWindowPrivate::drawTitleBarWhenMaximized() const
if (isChildOfTabbedQMdiArea(q))
return false;
-#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) || defined(Q_OS_WINCE_WM)
+#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC) || defined(Q_WS_WINCE_WM)
return true;
#else
if (q->style()->styleHint(QStyle::SH_Workspace_FillSpaceOnMaximize, 0, q))
@@ -1893,7 +1893,7 @@ void QMdiSubWindowPrivate::enterRubberBandMode()
if (q->isMaximized())
return;
Q_ASSERT(oldGeometry.isValid());
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
if (!rubberBand) {
rubberBand = new QRubberBand(QRubberBand::Rectangle, q->parentWidget());
// For accessibility to identify this special widget.
@@ -2079,7 +2079,7 @@ void QMdiSubWindowPrivate::restoreFocus()
void QMdiSubWindowPrivate::setWindowFlags(Qt::WindowFlags windowFlags)
{
Q_Q(QMdiSubWindow);
- if (!q->parent()) {
+ if (!parent) {
q->setWindowFlags(windowFlags);
return;
}
@@ -2164,7 +2164,7 @@ void QMdiSubWindowPrivate::addToSystemMenu(WindowStateAction action, const QStri
QSize QMdiSubWindowPrivate::iconSize() const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint)
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint)
return QSize(-1, -1);
return QSize(q->style()->pixelMetric(QStyle::PM_MdiSubWindowMinimizedWidth, 0, q), titleBarHeight());
}
@@ -2180,17 +2180,17 @@ void QMdiSubWindowPrivate::setSizeGrip(QSizeGrip *newSizeGrip)
if (!newSizeGrip || sizeGrip || q->windowFlags() & Qt::FramelessWindowHint)
return;
- if (q->layout() && q->layout()->indexOf(newSizeGrip) != -1)
+ if (layout && layout->indexOf(newSizeGrip) != -1)
return;
newSizeGrip->setFixedSize(newSizeGrip->sizeHint());
- bool putSizeGripInLayout = q->layout() ? true : false;
+ bool putSizeGripInLayout = layout ? true : false;
#if defined(Q_WS_MAC) && !defined(QT_NO_STYLE_MAC)
if (qobject_cast<QMacStyle *>(q->style()))
putSizeGripInLayout = false;
#endif
if (putSizeGripInLayout) {
- q->layout()->addWidget(newSizeGrip);
- q->layout()->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
+ layout->addWidget(newSizeGrip);
+ layout->setAlignment(newSizeGrip, Qt::AlignBottom | Qt::AlignRight);
} else {
newSizeGrip->setParent(q);
newSizeGrip->move(q->isLeftToRight() ? q->width() - newSizeGrip->width() : 0,
diff --git a/src/gui/widgets/qmdisubwindow_p.h b/src/gui/widgets/qmdisubwindow_p.h
index 2e672d6..d706546 100644
--- a/src/gui/widgets/qmdisubwindow_p.h
+++ b/src/gui/widgets/qmdisubwindow_p.h
@@ -287,7 +287,7 @@ public:
inline int titleBarHeight() const
{
Q_Q(const QMdiSubWindow);
- if (!q->parent() || q->windowFlags() & Qt::FramelessWindowHint
+ if (!parent || q->windowFlags() & Qt::FramelessWindowHint
|| (q->isMaximized() && !drawTitleBarWhenMaximized())) {
return 0;
}
@@ -308,7 +308,7 @@ public:
inline void setNewGeometry(QRect *geometry)
{
Q_Q(QMdiSubWindow);
- Q_ASSERT(q->parent());
+ Q_ASSERT(parent);
geometry->setSize(geometry->size().expandedTo(internalMinimumSize));
#ifndef QT_NO_RUBBERBAND
if (isInRubberBandMode)
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index 6d4dcf2..278a6cd 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -206,7 +206,6 @@ void QMenuPrivate::calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAc
actionRects.clear();
actionList.clear();
- QList<QAction*> items = filterActions(q->actions());
int max_column_width = 0,
dh = popupGeometry(QApplication::desktop()->screenNumber(q)).height(),
ncols = 1,
@@ -219,6 +218,7 @@ void QMenuPrivate::calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAc
tabWidth = 0;
maxIconWidth = 0;
hasCheckableItems = false;
+ QList<QAction*> items = filteredActions();
for(int i = 0; i < items.count(); i++) {
QAction *action = items.at(i);
if (widgetItems.value(action))
@@ -349,7 +349,7 @@ void QMenuPrivate::updateActions()
itemsDirty = 0;
}
-QList<QAction *> QMenuPrivate::filterActions(const QList<QAction *> &actions) const
+QList<QAction *> QMenuPrivate::filteredActions() const
{
QList<QAction *> visibleActions;
int i = 0;
@@ -399,9 +399,12 @@ QRect QMenuPrivate::actionRect(QAction *act) const
return ret;
}
+static const qreal MenuFadeTimeInSec = 0.150;
+
void QMenuPrivate::hideUpToMenuBar()
{
Q_Q(QMenu);
+ bool fadeMenus = q->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide);
if (!tornoff) {
QWidget *caused = causedPopup.widget;
hideMenu(q); //hide after getting causedPopup
@@ -416,8 +419,9 @@ void QMenuPrivate::hideUpToMenuBar()
if (QMenu *m = qobject_cast<QMenu*>(caused)) {
caused = m->d_func()->causedPopup.widget;
if (!m->d_func()->tornoff)
- hideMenu(m);
- m->d_func()->setCurrentAction(0);
+ hideMenu(m, fadeMenus);
+ if (!fadeMenus) // Mac doesn't clear the action until after hidden.
+ m->d_func()->setCurrentAction(0);
} else {
#ifndef QT_NO_TOOLBUTTON
if (qobject_cast<QToolButton*>(caused) == 0)
@@ -426,26 +430,32 @@ void QMenuPrivate::hideUpToMenuBar()
caused = 0;
}
}
+#if defined(Q_WS_MAC)
+ if (fadeMenus) {
+ QEventLoop eventLoop;
+ QTimer::singleShot(int(MenuFadeTimeInSec * 1000), &eventLoop, SLOT(quit()));
+ QMacWindowFader::currentFader()->performFade();
+ eventLoop.exec();
+ }
+#endif
}
setCurrentAction(0);
}
-void QMenuPrivate::hideMenu(QMenu *menu)
+void QMenuPrivate::hideMenu(QMenu *menu, bool justRegister)
{
if (!menu)
return;
-
#if !defined(QT_NO_EFFECTS)
menu->blockSignals(true);
aboutToHide = true;
// Flash item which is about to trigger (if any).
if (menu->style()->styleHint(QStyle::SH_Menu_FlashTriggeredItem)
- && currentAction && currentAction == actionAboutToTrigger) {
-
+ && currentAction && currentAction == actionAboutToTrigger
+ && menu->actions().contains(currentAction)) {
QEventLoop eventLoop;
QAction *activeAction = currentAction;
- // Deselect and wait 60 ms.
menu->setActiveAction(0);
QTimer::singleShot(60, &eventLoop, SLOT(quit()));
eventLoop.exec();
@@ -459,22 +469,24 @@ void QMenuPrivate::hideMenu(QMenu *menu)
// Fade out.
if (menu->style()->styleHint(QStyle::SH_Menu_FadeOutOnHide)) {
// ### Qt 4.4:
- // Should be something like: q->transitionWindow(Qt::FadeOutTransition, 150);
+ // Should be something like: q->transitionWindow(Qt::FadeOutTransition, MenuFadeTimeInSec);
// Hopefully we'll integrate qt/research/windowtransitions into main before 4.4.
// Talk to Richard, Trenton or Bjoern.
#if defined(Q_WS_MAC)
- macWindowFade(qt_mac_window_for(menu)); // FIXME - what is the default duration for view animations
+ if (justRegister) {
+ QMacWindowFader::currentFader()->setFadeDuration(MenuFadeTimeInSec);
+ QMacWindowFader::currentFader()->registerWindowToFade(menu);
+ } else {
+ macWindowFade(qt_mac_window_for(menu), MenuFadeTimeInSec);
+ }
- // Wait for the transition to complete.
- QEventLoop eventLoop;
- QTimer::singleShot(150, &eventLoop, SLOT(quit()));
- eventLoop.exec();
#endif // Q_WS_MAC
}
aboutToHide = false;
menu->blockSignals(false);
#endif // QT_NO_EFFECTS
- menu->hide();
+ if (!justRegister)
+ menu->hide();
}
void QMenuPrivate::popupAction(QAction *action, int delay, bool activateFirst)
@@ -536,10 +548,12 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
{
Q_Q(QMenu);
tearoffHighlighted = 0;
- if (action == currentAction && !(action && action->menu() && action->menu() != activeMenu)) {
- if(QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
- if(causedPopup.action && menu->d_func()->activeMenu == q)
- menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
+ if (action == currentAction) {
+ if (!action || !action->menu() || action->menu() == activeMenu) {
+ if(QMenu *menu = qobject_cast<QMenu*>(causedPopup.widget)) {
+ if(causedPopup.action && menu->d_func()->activeMenu == q)
+ menu->d_func()->setCurrentAction(causedPopup.action, 0, reason, false);
+ }
}
return;
}
@@ -554,7 +568,7 @@ void QMenuPrivate::setCurrentAction(QAction *action, int popup, SelectionReason
QAction *previousAction = currentAction;
#endif
#ifdef QT3_SUPPORT
- emitHighlighted = (action && action != currentAction);
+ emitHighlighted = action;
#endif
currentAction = action;
if (action) {
@@ -1041,7 +1055,7 @@ void QMenuPrivate::activateAction(QAction *action, QAction::ActionEvent action_e
if (q->testAttribute(Qt::WA_DontShowOnScreen)) {
hideUpToMenuBar();
} else {
- for(QWidget *widget = qApp->activePopupWidget(); widget; ) {
+ for(QWidget *widget = QApplication::activePopupWidget(); widget; ) {
if (QMenu *qmenu = qobject_cast<QMenu*>(widget)) {
if(qmenu == q)
hideUpToMenuBar();
@@ -1852,7 +1866,7 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
if (adjustToDesktop) {
//handle popup falling "off screen"
- if (qApp->layoutDirection() == Qt::RightToLeft) {
+ if (QApplication::layoutDirection() == Qt::RightToLeft) {
if(snapToMouse) //position flowing left from the mouse
pos.setX(mouse.x()-size.width());
@@ -1890,9 +1904,9 @@ void QMenu::popup(const QPoint &p, QAction *atAction)
}
setGeometry(QRect(pos, size));
#ifndef QT_NO_EFFECTS
- int hGuess = qApp->layoutDirection() == Qt::RightToLeft ? QEffects::LeftScroll : QEffects::RightScroll;
+ int hGuess = QApplication::layoutDirection() == Qt::RightToLeft ? QEffects::LeftScroll : QEffects::RightScroll;
int vGuess = QEffects::DownScroll;
- if (qApp->layoutDirection() == Qt::RightToLeft) {
+ if (QApplication::layoutDirection() == Qt::RightToLeft) {
if ((snapToMouse && (pos.x() + size.width()/2 > mouse.x())) ||
(qobject_cast<QMenu*>(d->causedPopup.widget) && pos.x() + size.width()/2 > d->causedPopup.widget->x()))
hGuess = QEffects::RightScroll;
@@ -2587,7 +2601,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
{
d->hideMenu(this);
#ifndef QT_NO_MENUBAR
- if (QMenuBar *mb = qobject_cast<QMenuBar*>(qApp->focusWidget())) {
+ if (QMenuBar *mb = qobject_cast<QMenuBar*>(QApplication::focusWidget())) {
mb->d_func()->setKeyboardMode(false);
}
#endif
@@ -2732,7 +2746,7 @@ void QMenu::keyPressEvent(QKeyEvent *e)
#ifdef Q_OS_WIN32
if (key_consumed && (e->key() == Qt::Key_Control || e->key() == Qt::Key_Shift || e->key() == Qt::Key_Meta))
- qApp->beep();
+ QApplication::beep();
#endif // Q_OS_WIN32
}
if (key_consumed)
@@ -2864,7 +2878,7 @@ void QMenu::actionEvent(QActionEvent *e)
}
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
if (!d->wce_menu)
d->wce_menu = new QMenuPrivate::QWceMenuPrivate;
if (e->type() == QEvent::ActionAdded)
diff --git a/src/gui/widgets/qmenu.h b/src/gui/widgets/qmenu.h
index bf1c39f..d26dd76 100644
--- a/src/gui/widgets/qmenu.h
+++ b/src/gui/widgets/qmenu.h
@@ -149,7 +149,7 @@ public:
OSMenuRef macMenu(OSMenuRef merge=0);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
HMENU wceMenu(bool create = false);
#endif
@@ -181,7 +181,7 @@ protected:
bool focusNextPrevChild(bool next);
void initStyleOption(QStyleOptionMenuItem *option, const QAction *action) const;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
QAction* wceCommands(uint command);
#endif
diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm
index 2560cfa..67656b4 100644
--- a/src/gui/widgets/qmenu_mac.mm
+++ b/src/gui/widgets/qmenu_mac.mm
@@ -71,7 +71,6 @@ QT_BEGIN_NAMESPACE
/*****************************************************************************
QMenu globals
*****************************************************************************/
-bool qt_mac_no_native_menubar = false;
bool qt_mac_no_menubar_merge = false;
bool qt_mac_quit_menu_item_enabled = true;
int qt_mac_menus_open_count = 0;
@@ -143,6 +142,39 @@ static int qt_mac_CountMenuItems(OSMenuRef menu)
return 0;
}
+static quint32 constructModifierMask(quint32 accel_key)
+{
+ quint32 ret = 0;
+ const bool dontSwap = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta);
+#ifndef QT_MAC_USE_COCOA
+ if ((accel_key & Qt::ALT) == Qt::ALT)
+ ret |= kMenuOptionModifier;
+ if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
+ ret |= kMenuShiftModifier;
+ if (dontSwap) {
+ if ((accel_key & Qt::META) != Qt::META)
+ ret |= kMenuNoCommandModifier;
+ if ((accel_key & Qt::CTRL) == Qt::CTRL)
+ ret |= kMenuControlModifier;
+ } else {
+ if ((accel_key & Qt::CTRL) != Qt::CTRL)
+ ret |= kMenuNoCommandModifier;
+ if ((accel_key & Qt::META) == Qt::META)
+ ret |= kMenuControlModifier;
+ }
+#else
+ if ((accel_key & Qt::CTRL) == Qt::CTRL)
+ ret |= (dontSwap ? NSControlKeyMask : NSCommandKeyMask);
+ if ((accel_key & Qt::META) == Qt::META)
+ ret |= (dontSwap ? NSCommandKeyMask : NSControlKeyMask);
+ if ((accel_key & Qt::ALT) == Qt::ALT)
+ ret |= NSAlternateKeyMask;
+ if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
+ ret |= NSShiftKeyMask;
+#endif
+ return ret;
+}
+
static bool actualMenuItemVisibility(const QMenuBarPrivate::QMacMenuBarPrivate *mbp,
const QMacMenuAction *action)
{
@@ -166,7 +198,7 @@ bool qt_mac_activate_action(MenuRef menu, uint command, QAction::ActionEvent act
QMenuMergeList *list = 0;
GetMenuItemProperty(menu, 0, kMenuCreatorQt, kMenuPropertyMergeList,
sizeof(list), 0, &list);
- if (!list && qt_mac_current_menubar.qmenubar) {
+ if (!list && qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
MenuRef apple_menu = qt_mac_current_menubar.qmenubar->d_func()->mac_menubar->apple_menu;
GetMenuItemProperty(apple_menu, 0, kMenuCreatorQt, kMenuPropertyMergeList, sizeof(list), 0, &list);
if (list)
@@ -526,15 +558,7 @@ static bool qt_mac_auto_apple_menu(MenuCommand cmd)
static void qt_mac_get_accel(quint32 accel_key, quint32 *modif, quint32 *key) {
if (modif) {
- *modif = 0;
- if ((accel_key & Qt::CTRL) != Qt::CTRL)
- *modif |= kMenuNoCommandModifier;
- if ((accel_key & Qt::META) == Qt::META)
- *modif |= kMenuControlModifier;
- if ((accel_key & Qt::ALT) == Qt::ALT)
- *modif |= kMenuOptionModifier;
- if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- *modif |= kMenuShiftModifier;
+ *modif = constructModifierMask(accel_key);
}
accel_key &= ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL);
@@ -599,7 +623,7 @@ static inline QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *getMenuLoader()
static NSMenuItem *createNSMenuItem(const QString &title)
{
NSMenuItem *item = [[NSMenuItem alloc]
- initWithTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(title)))
+ initWithTitle:qt_mac_QStringToNSString(title)
action:@selector(qtDispatcherToQAction:) keyEquivalent:@""];
[item setTarget:getMenuLoader()];
return item;
@@ -728,6 +752,18 @@ QMacMenuAction::~QMacMenuAction()
{
#ifdef QT_MAC_USE_COCOA
[menu release];
+ if (action) {
+ QAction::MenuRole role = action->menuRole();
+ // Check if the item is owned by Qt, and should be hidden to keep it from causing
+ // problems. Do it for everything but the quit menu item since that should always
+ // be visible.
+ if (role > QAction::ApplicationSpecificRole && role < QAction::QuitRole) {
+ [menuItem setHidden:YES];
+ } else if (role == QAction::TextHeuristicRole
+ && menuItem != [getMenuLoader() quitMenuItem]) {
+ [menuItem setHidden:YES];
+ }
+ }
[menuItem setTag:nil];
[menuItem release];
#endif
@@ -915,21 +951,22 @@ static QKeySequence qt_mac_menu_merge_accel(QMacMenuAction *action)
ret = action->action->shortcut();
#ifndef QT_MAC_USE_COCOA
else if (action->command == kHICommandPreferences)
- ret = QKeySequence(Qt::CTRL+Qt::Key_Comma);
+ ret = QKeySequence(QKeySequence::Preferences);
else if (action->command == kHICommandQuit)
- ret = QKeySequence(Qt::CTRL+Qt::Key_Q);
+ ret = QKeySequence(QKeySequence::Quit);
#else
else if (action->menuItem == [loader preferencesMenuItem])
- ret = QKeySequence(Qt::CTRL+Qt::Key_Comma);
+ ret = QKeySequence(QKeySequence::Preferences);
else if (action->menuItem == [loader quitMenuItem])
- ret = QKeySequence(Qt::CTRL+Qt::Key_Q);
+ ret = QKeySequence(QKeySequence::Quit);
#endif
return ret;
}
void Q_GUI_EXPORT qt_mac_set_menubar_icons(bool b)
{ QApplication::instance()->setAttribute(Qt::AA_DontShowIconsInMenus, !b); }
-void Q_GUI_EXPORT qt_mac_set_native_menubar(bool b) { qt_mac_no_native_menubar = !b; }
+void Q_GUI_EXPORT qt_mac_set_native_menubar(bool b)
+{ QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, !b); }
void Q_GUI_EXPORT qt_mac_set_menubar_merge(bool b) { qt_mac_no_menubar_merge = !b; }
/*****************************************************************************
@@ -1206,58 +1243,21 @@ QMenuPrivate::QMacMenuPrivate::addAction(QMacMenuAction *action, QMacMenuAction
NSString *keySequenceToKeyEqivalent(const QKeySequence &accel)
{
quint32 accel_key = (accel[0] & ~(Qt::MODIFIER_MASK | Qt::UNICODE_ACCEL));
- unichar keyEquiv[1] = { 0 };
- if (accel_key == Qt::Key_Return)
- keyEquiv[0] = kReturnCharCode;
- else if (accel_key == Qt::Key_Enter)
- keyEquiv[0] = kEnterCharCode;
- else if (accel_key == Qt::Key_Tab)
- keyEquiv[0] = kTabCharCode;
- else if (accel_key == Qt::Key_Backspace)
- keyEquiv[0] = kBackspaceCharCode;
- else if (accel_key == Qt::Key_Delete)
- keyEquiv[0] = NSDeleteFunctionKey;
- else if (accel_key == Qt::Key_Escape)
- keyEquiv[0] = kEscapeCharCode;
- else if (accel_key == Qt::Key_PageUp)
- keyEquiv[0] = NSPageUpFunctionKey;
- else if (accel_key == Qt::Key_PageDown)
- keyEquiv[0] = NSPageDownFunctionKey;
- else if (accel_key == Qt::Key_Up)
- keyEquiv[0] = NSUpArrowFunctionKey;
- else if (accel_key == Qt::Key_Down)
- keyEquiv[0] = NSDownArrowFunctionKey;
- else if (accel_key == Qt::Key_Left)
- keyEquiv[0] = NSLeftArrowFunctionKey;
- else if (accel_key == Qt::Key_Right)
- keyEquiv[0] = NSRightArrowFunctionKey;
- else if (accel_key == Qt::Key_CapsLock)
- keyEquiv[0] = kMenuCapsLockGlyph; // ### Cocoa has no equivalent
- else if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15)
- keyEquiv[0] = (accel_key - Qt::Key_F1) + NSF1FunctionKey;
- else if (accel_key == Qt::Key_Home)
- keyEquiv[0] = NSHomeFunctionKey;
- else if (accel_key == Qt::Key_End)
- keyEquiv[0] = NSEndFunctionKey;
- else
- keyEquiv[0] = unichar(QChar(accel_key).toLower().unicode());
- return [NSString stringWithCharacters:keyEquiv length:1];
+ extern QChar qt_macSymbolForQtKey(int key); // qkeysequence.cpp
+ QChar keyEquiv = qt_macSymbolForQtKey(accel_key);
+ if (keyEquiv.isNull()) {
+ if (accel_key >= Qt::Key_F1 && accel_key <= Qt::Key_F15)
+ keyEquiv = (accel_key - Qt::Key_F1) + NSF1FunctionKey;
+ else
+ keyEquiv = unichar(QChar(accel_key).toLower().unicode());
+ }
+ return [NSString stringWithCharacters:&keyEquiv.unicode() length:1];
}
// return the cocoa modifier mask for the QKeySequence (currently only looks at the first one).
NSUInteger keySequenceModifierMask(const QKeySequence &accel)
{
- NSUInteger ret = 0;
- quint32 accel_key = accel[0];
- if ((accel_key & Qt::CTRL) == Qt::CTRL)
- ret |= NSCommandKeyMask;
- if ((accel_key & Qt::META) == Qt::META)
- ret |= NSControlKeyMask;
- if ((accel_key & Qt::ALT) == Qt::ALT)
- ret |= NSAlternateKeyMask;
- if ((accel_key & Qt::SHIFT) == Qt::SHIFT)
- ret |= NSShiftKeyMask;
- return ret;
+ return constructModifierMask(accel[0]);
}
void
@@ -1379,18 +1379,18 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action)
// Cocoa Font and title
if (action->action->font().resolve()) {
const QFont &actionFont = action->action->font();
- NSFont *customMenuFont = [NSFont fontWithName:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(actionFont.family())))
+ NSFont *customMenuFont = [NSFont fontWithName:qt_mac_QStringToNSString(actionFont.family())
size:actionFont.pointSize()];
NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
- NSAttributedString *str = [[[NSAttributedString alloc] initWithString:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(finalString)))
+ NSAttributedString *str = [[[NSAttributedString alloc] initWithString:qt_mac_QStringToNSString(finalString)
attributes:attributes] autorelease];
[item setAttributedTitle: str];
} else {
- [item setTitle: reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(finalString)))];
+ [item setTitle: qt_mac_QStringToNSString(finalString)];
}
- [item setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(qt_mac_removeMnemonics(text))))];
+ [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))];
// Cocoa Enabled
[item setEnabled: action->action->isEnabled()];
@@ -1699,7 +1699,7 @@ QMenuBarPrivate::QMacMenuBarPrivate::syncAction(QMacMenuAction *action)
ChangeMenuAttributes(submenu, kMenuAttrHidden, 0);
#else
[item setSubmenu: submenu];
- [submenu setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(qt_mac_removeMnemonics(action->action->text()))))];
+ [submenu setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(action->action->text()))];
syncNSMenuItemVisiblity(item, visible);
#endif
if (release_submenu) { //no pointers to it
@@ -1733,9 +1733,14 @@ QMenuBarPrivate::macCreateMenuBar(QWidget *parent)
{
Q_Q(QMenuBar);
static int checkEnv = -1;
+ // We call the isNativeMenuBar function here
+ // becasue that will make sure that local overrides
+ // are dealt with correctly.
+ bool qt_mac_no_native_menubar = !q->isNativeMenuBar();
if (qt_mac_no_native_menubar == false && checkEnv < 0) {
checkEnv = !qgetenv("QT_MAC_NO_NATIVE_MENUBAR").isEmpty();
- qt_mac_no_native_menubar = checkEnv;
+ QApplication::instance()->setAttribute(Qt::AA_DontUseNativeMenuBar, checkEnv);
+ qt_mac_no_native_menubar = !q->isNativeMenuBar();
}
if (!qt_mac_no_native_menubar) {
extern void qt_event_request_menubarupdate(); //qapplication_mac.cpp
@@ -1770,7 +1775,7 @@ void QMenuBarPrivate::macDestroyMenuBar()
OSMenuRef QMenuBarPrivate::macMenu()
{
Q_Q(QMenuBar);
- if (!mac_menubar) {
+ if (!q->isNativeMenuBar() || !mac_menubar) {
return 0;
} else if (!mac_menubar->menu) {
mac_menubar->menu = qt_mac_create_menu(q);
@@ -1786,7 +1791,7 @@ OSMenuRef QMenuBarPrivate::macMenu()
SetMenuItemHierarchicalMenu(mac_menubar->menu, index, mac_menubar->apple_menu);
SetMenuItemProperty(mac_menubar->apple_menu, 0, kMenuCreatorQt, kMenuPropertyQWidget, sizeof(q), &q);
#else
- [mac_menubar->apple_menu setTitle:reinterpret_cast<const NSString *>(static_cast<CFStringRef>(QCFString(QString(QChar(0x14)))))];
+ [mac_menubar->apple_menu setTitle:qt_mac_QStringToNSString(QString(QChar(0x14)))];
NSMenuItem *apple_menuItem = [[NSMenuItem alloc] init];
[apple_menuItem setSubmenu:mac_menubar->menu];
[mac_menubar->apple_menu addItem:apple_menuItem];
@@ -1829,6 +1834,9 @@ OSMenuRef QMenuBar::macMenu() { return d_func()->macMenu(); }
*/
static bool qt_mac_is_ancestor(QWidget* possibleAncestor, QWidget *child)
{
+ if (!possibleAncestor)
+ return false;
+
QWidget * current = child->parentWidget();
while (current != 0) {
if (current == possibleAncestor)
@@ -1847,22 +1855,19 @@ static bool qt_mac_should_disable_menu(QMenuBar *menuBar, QWidget *modalWidget)
{
if (modalWidget == 0 || menuBar == 0)
return false;
- const Qt::WindowModality modality = modalWidget->windowModality();
- if (modality == Qt::ApplicationModal) {
- return true;
- } else if (modality == Qt::WindowModal) {
- QWidget * parent = menuBar->parentWidget();
-
- // Special case for the global menu bar: It's not associated
- // with a window so don't disable it.
- if (parent == 0)
- return false;
- // Disable menu entries in menu bars that belong to ancestors of
- // the modal widget, leave entries in unrelated menu bars enabled.
- return qt_mac_is_ancestor(parent, modalWidget);
+ // If there is an application modal window on
+ // screen, the entries of the menubar should be disabled:
+ QWidget *w = modalWidget;
+ while (w) {
+ if (w->isVisible() && w->windowModality() == Qt::ApplicationModal)
+ return true;
+ w = w->parentWidget();
}
- return false; // modality == NonModal
+
+ // INVARIANT: modalWidget is window modal. Disable menu entries
+ // if the menu bar belongs to an ancestor of modalWidget:
+ return qt_mac_is_ancestor(menuBar->parentWidget(), modalWidget);
}
static void cancelAllMenuTracking()
@@ -1891,9 +1896,6 @@ static void cancelAllMenuTracking()
*/
bool QMenuBar::macUpdateMenuBar()
{
- if (qt_mac_no_native_menubar) //nothing to be done..
- return true;
-
cancelAllMenuTracking();
QMenuBar *mb = 0;
//find a menu bar
@@ -1927,7 +1929,7 @@ bool QMenuBar::macUpdateMenuBar()
mb = fallback;
//now set it
bool ret = false;
- if (mb) {
+ if (mb && mb->isNativeMenuBar()) {
#ifdef QT_MAC_USE_COCOA
QMacCocoaAutoReleasePool pool;
#endif
@@ -1965,7 +1967,7 @@ bool QMenuBar::macUpdateMenuBar()
qt_mac_current_menubar.qmenubar = mb;
qt_mac_current_menubar.modal = QApplicationPrivate::modalState();
ret = true;
- } else if (qt_mac_current_menubar.qmenubar) {
+ } else if (qt_mac_current_menubar.qmenubar && qt_mac_current_menubar.qmenubar->isNativeMenuBar()) {
const bool modal = QApplicationPrivate::modalState();
if (modal != qt_mac_current_menubar.modal) {
ret = true;
diff --git a/src/gui/widgets/qmenu_p.h b/src/gui/widgets/qmenu_p.h
index aafc945..d5674c8 100644
--- a/src/gui/widgets/qmenu_p.h
+++ b/src/gui/widgets/qmenu_p.h
@@ -115,7 +115,7 @@ struct QMenuMergeItem
typedef QList<QMenuMergeItem> QMenuMergeList;
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
struct QWceMenuAction {
uint command;
QPointer<QAction> action;
@@ -144,7 +144,7 @@ public:
#ifdef Q_WS_MAC
,mac_menu(0)
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
,wce_menu(0)
#endif
#ifdef Q_OS_SYMBIAN
@@ -160,7 +160,7 @@ public:
#ifdef Q_WS_MAC
delete mac_menu;
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
delete wce_menu;
#endif
#ifdef Q_OS_SYMBIAN
@@ -180,7 +180,7 @@ public:
void calcActionRects(QMap<QAction*, QRect> &actionRects, QList<QAction*> &actionList) const;
void updateActions();
QRect popupGeometry(int screen=-1) const;
- QList<QAction *> filterActions(const QList<QAction *> &actions) const;
+ QList<QAction *> filteredActions() const;
uint ncols : 4; //4 bits is probably plenty
uint collapsibleSeparators : 1;
@@ -239,7 +239,7 @@ public:
virtual QList<QPointer<QWidget> > calcCausedStack() const;
QMenuCaused causedPopup;
void hideUpToMenuBar();
- void hideMenu(QMenu *menu);
+ void hideMenu(QMenu *menu, bool justRegister = false);
//index mappings
inline QAction *actionAt(int i) const { return q_func()->actions().at(i); }
@@ -312,7 +312,7 @@ public:
bool emitHighlighted;
#endif
-#if defined(Q_OS_WINCE) && !defined(QT_NO_MENUBAR)
+#if defined(Q_WS_WINCE) && !defined(QT_NO_MENUBAR)
struct QWceMenuPrivate {
QList<QWceMenuAction*> actionItems;
HMENU menuHandle;
diff --git a/src/gui/widgets/qmenu_wince.cpp b/src/gui/widgets/qmenu_wince.cpp
index 42a4e0b..2ce89f9 100644
--- a/src/gui/widgets/qmenu_wince.cpp
+++ b/src/gui/widgets/qmenu_wince.cpp
@@ -40,7 +40,7 @@
****************************************************************************/
//Native menubars are only supported for Windows Mobile not the standard SDK/generic WinCE
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qmenu.h"
#include "qt_windows.h"
#include "qapplication.h"
@@ -621,4 +621,4 @@ void QMenuBarPrivate::QWceMenuBarPrivate::rebuild() {
QT_END_NAMESPACE
#endif //QT_NO_MENUBAR
-#endif //Q_OS_WINCE
+#endif //Q_WS_WINCE
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index fb8a69b..09742d2 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -67,7 +67,7 @@
#include "qmenubar_p.h"
#include "qdebug.h"
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
extern bool qt_wince_is_mobile(); //defined in qguifunctions_wce.cpp
#endif
@@ -116,11 +116,9 @@ QSize QMenuBarExtension::sizeHint() const
*/
QAction *QMenuBarPrivate::actionAt(QPoint p) const
{
- Q_Q(const QMenuBar);
- QList<QAction*> items = q->actions();
- for(int i = 0; i < items.size(); ++i) {
- if(actionRect(items.at(i)).contains(p))
- return items.at(i);
+ for(int i = 0; i < actions.size(); ++i) {
+ if(actionRect(actions.at(i)).contains(p))
+ return actions.at(i);
}
return 0;
}
@@ -194,7 +192,7 @@ void QMenuBarPrivate::updateGeometries()
}
#ifdef Q_WS_MAC
- if(mac_menubar) {//nothing to see here folks, move along..
+ if(q->isNativeMenuBar()) {//nothing to see here folks, move along..
itemsDirty = false;
return;
}
@@ -220,7 +218,8 @@ void QMenuBarPrivate::updateGeometries()
//we try to see if the actions will fit there
bool hasHiddenActions = false;
- foreach(QAction *action, actionList) {
+ for (int i = 0; i < actionList.count(); ++i) {
+ QAction *action = actionList.at(i);
if (!menuRect.contains(actionRect(action))) {
hasHiddenActions = true;
break;
@@ -230,7 +229,8 @@ void QMenuBarPrivate::updateGeometries()
//...and if not, determine the ones that fit on the menu with the extension visible
if (hasHiddenActions) {
menuRect = this->menuRect(true);
- foreach(QAction *action, actionList) {
+ for (int i = 0; i < actionList.count(); ++i) {
+ QAction *action = actionList.at(i);
if (!menuRect.contains(actionRect(action))) {
hiddenActions.append(action);
}
@@ -257,9 +257,9 @@ void QMenuBarPrivate::updateGeometries()
}
q->updateGeometry();
#ifdef QT3_SUPPORT
- if (q->parentWidget() != 0) {
+ if (parent) {
QMenubarUpdatedEvent menubarUpdated(q);
- QApplication::sendEvent(q->parentWidget(), &menubarUpdated);
+ QApplication::sendEvent(parent, &menubarUpdated);
}
#endif
}
@@ -282,7 +282,7 @@ void QMenuBarPrivate::setKeyboardMode(bool b)
}
keyboardState = b;
if(b) {
- QWidget *fw = qApp->focusWidget();
+ QWidget *fw = QApplication::focusWidget();
if (fw != q)
keyboardFocusWidget = fw;
if(!currentAction && !actionList.isEmpty())
@@ -292,7 +292,7 @@ void QMenuBarPrivate::setKeyboardMode(bool b)
if(!popupState)
setCurrentAction(0);
if(keyboardFocusWidget) {
- if (qApp->focusWidget() == q)
+ if (QApplication::focusWidget() == q)
keyboardFocusWidget->setFocus(Qt::MenuBarFocusReason);
keyboardFocusWidget = 0;
}
@@ -411,15 +411,14 @@ void QMenuBarPrivate::calcActionRects(int max_width, int start, QMap<QAction*, Q
actionList.clear();
const int itemSpacing = q->style()->pixelMetric(QStyle::PM_MenuBarItemSpacing, 0, q);
int max_item_height = 0, separator = -1, separator_start = 0, separator_len = 0;
- QList<QAction*> items = q->actions();
//calculate size
const QFontMetrics fm = q->fontMetrics();
const int hmargin = q->style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, q),
vmargin = q->style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, q),
icone = q->style()->pixelMetric(QStyle::PM_SmallIconSize, 0, q);
- for(int i = 0; i < items.count(); i++) {
- QAction *action = items.at(i);
+ for(int i = 0; i < actions.count(); i++) {
+ QAction *action = actions.at(i);
if(!action->isVisible())
continue;
@@ -532,7 +531,6 @@ void QMenuBarPrivate::_q_actionHovered()
emit q->hovered(action);
#ifndef QT_NO_ACCESSIBILITY
if (QAccessible::isActive()) {
- QList<QAction*> actions = q->actions();
int actionIndex = actions.indexOf(action);
++actionIndex;
QAccessible::updateAccessibility(q, actionIndex, QAccessible::Focus);
@@ -725,7 +723,7 @@ void QMenuBarPrivate::init()
if(mac_menubar)
q->hide();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile()) {
wceCreateMenuBar(q->parentWidget());
if(wce_menubar)
@@ -782,7 +780,7 @@ QMenuBar::~QMenuBar()
Q_D(QMenuBar);
d->macDestroyMenuBar();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_D(QMenuBar);
if (qt_wince_is_mobile())
d->wceDestroyMenuBar();
@@ -1035,14 +1033,8 @@ void QMenuBar::paintEvent(QPaintEvent *e)
*/
void QMenuBar::setVisible(bool visible)
{
-#ifdef Q_WS_MAC
- Q_D(QMenuBar);
- if(d->mac_menubar)
- return;
-#endif
-#ifdef Q_OS_WINCE
- Q_D(QMenuBar);
- if(d->wce_menubar)
+#if defined(Q_WS_MAC) || defined(Q_OS_WINCE)
+ if (isNativeMenuBar())
return;
#endif
#ifdef Q_OS_SYMBIAN
@@ -1288,24 +1280,21 @@ void QMenuBar::actionEvent(QActionEvent *e)
{
Q_D(QMenuBar);
d->itemsDirty = true;
+#if defined (Q_WS_MAC) || defined(Q_OS_WINCE)
+ if (isNativeMenuBar()) {
#ifdef Q_WS_MAC
- if(d->mac_menubar) {
- if(e->type() == QEvent::ActionAdded)
- d->mac_menubar->addAction(e->action(), d->mac_menubar->findAction(e->before()));
- else if(e->type() == QEvent::ActionRemoved)
- d->mac_menubar->removeAction(e->action());
- else if(e->type() == QEvent::ActionChanged)
- d->mac_menubar->syncAction(e->action());
- }
+ QMenuBarPrivate::QMacMenuBarPrivate *nativeMenuBar = d->mac_menubar;
+#else
+ QMenuBarPrivate::QWceMenuBarPrivate *nativeMenuBar = d->wce_menubar;
#endif
-#ifdef Q_OS_WINCE
- if(d->wce_menubar) {
+ if (!nativeMenuBar)
+ return;
if(e->type() == QEvent::ActionAdded)
- d->wce_menubar->addAction(e->action(), d->wce_menubar->findAction(e->before()));
+ nativeMenuBar->addAction(e->action(), nativeMenuBar->findAction(e->before()));
else if(e->type() == QEvent::ActionRemoved)
- d->wce_menubar->removeAction(e->action());
+ nativeMenuBar->removeAction(e->action());
else if(e->type() == QEvent::ActionChanged)
- d->wce_menubar->syncAction(e->action());
+ nativeMenuBar->syncAction(e->action());
}
#endif
#ifdef Q_OS_SYMBIAN
@@ -1401,7 +1390,7 @@ void QMenuBarPrivate::handleReparent()
macCreateMenuBar(newParent);
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile() && wce_menubar)
wce_menubar->rebuild();
#endif
@@ -1644,12 +1633,8 @@ QRect QMenuBar::actionGeometry(QAction *act) const
QSize QMenuBar::minimumSizeHint() const
{
Q_D(const QMenuBar);
-#ifdef Q_WS_MAC
- const bool as_gui_menubar = !d->mac_menubar;
-#elif defined (Q_OS_WINCE)
- const bool as_gui_menubar = !d->wce_menubar;
-#elif defined (Q_OS_SYMBIAN)
- const bool as_gui_menubar = !d->symbian_menubar;
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
+ const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
#endif
@@ -1706,16 +1691,13 @@ QSize QMenuBar::minimumSizeHint() const
QSize QMenuBar::sizeHint() const
{
Q_D(const QMenuBar);
-#ifdef Q_WS_MAC
- const bool as_gui_menubar = !d->mac_menubar;
-#elif defined (Q_OS_WINCE)
- const bool as_gui_menubar = !d->wce_menubar;
-#elif defined (Q_OS_SYMBIAN)
- const bool as_gui_menubar = !d->symbian_menubar;
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
+ const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
#endif
+
ensurePolished();
QSize ret(0, 0);
const int hmargin = style()->pixelMetric(QStyle::PM_MenuBarHMargin, 0, this);
@@ -1771,15 +1753,12 @@ QSize QMenuBar::sizeHint() const
int QMenuBar::heightForWidth(int) const
{
Q_D(const QMenuBar);
-#ifdef Q_WS_MAC
- const bool as_gui_menubar = !d->mac_menubar;
-#elif defined (Q_OS_WINCE)
- const bool as_gui_menubar = !d->wce_menubar;
-#elif defined (Q_OS_SYMBIAN)
- const bool as_gui_menubar = !d->symbian_menubar;
+#if defined(Q_WS_MAC) || defined(Q_WS_WINCE) || defined(Q_OS_SYMBIAN)
+ const bool as_gui_menubar = !isNativeMenuBar();
#else
const bool as_gui_menubar = true;
#endif
+
int height = 0;
const int vmargin = style()->pixelMetric(QStyle::PM_MenuBarVMargin, 0, this);
int fw = style()->pixelMetric(QStyle::PM_MenuBarPanelWidth, 0, this);
@@ -1894,6 +1873,60 @@ QWidget *QMenuBar::cornerWidget(Qt::Corner corner) const
}
/*!
+ \property QMenuBar::nativeMenuBar
+ \brief Whether or not a menubar will be used as a native menubar on platforms that support it
+ \since 4.6
+
+ This property specifies whether or not the menubar should be used as a native menubar on platforms
+ that support it. The currently supported platforms are Mac OS X and Windows CE. On these platforms
+ if this property is true, the menubar is used in the native menubar and is not in the window of
+ its parent, if false the menubar remains in the window. On other platforms the value of this
+ attribute has no effect.
+
+ The default is to follow whether the Qt::AA_DontUseNativeMenuBar attribute
+ is set for the application. Explicitly settings this property overrides
+ the presence (or abscence) of the attribute.
+*/
+
+void QMenuBar::setNativeMenuBar(bool nativeMenuBar)
+{
+ Q_D(QMenuBar);
+ if (d->nativeMenuBar == -1 || (nativeMenuBar != bool(d->nativeMenuBar))) {
+ d->nativeMenuBar = nativeMenuBar;
+#ifdef Q_WS_MAC
+ if (!d->nativeMenuBar) {
+ extern void qt_mac_clear_menubar();
+ qt_mac_clear_menubar();
+ d->macDestroyMenuBar();
+ const QList<QAction *> &menubarActions = actions();
+ for (int i = 0; i < menubarActions.size(); ++i) {
+ const QAction *action = menubarActions.at(i);
+ if (QMenu *menu = action->menu()) {
+ delete menu->d_func()->mac_menu;
+ menu->d_func()->mac_menu = 0;
+ }
+ }
+ } else {
+ d->macCreateMenuBar(parentWidget());
+ }
+ macUpdateMenuBar();
+ updateGeometry();
+ setVisible(false);
+ setVisible(true);
+#endif
+ }
+}
+
+bool QMenuBar::isNativeMenuBar() const
+{
+ Q_D(const QMenuBar);
+ if (d->nativeMenuBar == -1) {
+ return !QApplication::instance()->testAttribute(Qt::AA_DontUseNativeMenuBar);
+ }
+ return d->nativeMenuBar;
+}
+
+/*!
\since 4.4
Sets the default action to \a act.
@@ -1907,13 +1940,13 @@ QWidget *QMenuBar::cornerWidget(Qt::Corner corner) const
\sa defaultAction()
*/
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void QMenuBar::setDefaultAction(QAction *act)
{
Q_D(QMenuBar);
if (d->defaultAction == act)
return;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (d->defaultAction) {
disconnect(d->defaultAction, SIGNAL(changed()), this, SLOT(_q_updateDefaultAction()));
@@ -1921,7 +1954,7 @@ void QMenuBar::setDefaultAction(QAction *act)
}
#endif
d->defaultAction = act;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
if (qt_wince_is_mobile())
if (d->defaultAction) {
connect(d->defaultAction, SIGNAL(changed()), this, SLOT(_q_updateDefaultAction()));
diff --git a/src/gui/widgets/qmenubar.h b/src/gui/widgets/qmenubar.h
index 42f0c0c..58a03ff 100644
--- a/src/gui/widgets/qmenubar.h
+++ b/src/gui/widgets/qmenubar.h
@@ -64,6 +64,7 @@ class Q_GUI_EXPORT QMenuBar : public QWidget
Q_OBJECT
Q_PROPERTY(bool defaultUp READ isDefaultUp WRITE setDefaultUp)
+ Q_PROPERTY(bool nativeMenuBar READ isNativeMenuBar WRITE setNativeMenuBar)
public:
explicit QMenuBar(QWidget *parent = 0);
@@ -110,7 +111,7 @@ public:
static bool macUpdateMenuBar();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void setDefaultAction(QAction *);
QAction *defaultAction() const;
@@ -118,6 +119,9 @@ public:
static void wceRefresh();
#endif
+ bool isNativeMenuBar() const;
+ void setNativeMenuBar(bool nativeMenuBar);
+
public Q_SLOTS:
virtual void setVisible(bool visible);
@@ -339,7 +343,7 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_internalShortcutActivated(int))
Q_PRIVATE_SLOT(d_func(), void _q_updateLayout())
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
Q_PRIVATE_SLOT(d_func(), void _q_updateDefaultAction())
#endif
diff --git a/src/gui/widgets/qmenubar_p.h b/src/gui/widgets/qmenubar_p.h
index 9e7d511..0421736 100644
--- a/src/gui/widgets/qmenubar_p.h
+++ b/src/gui/widgets/qmenubar_p.h
@@ -57,7 +57,7 @@
#include "QtGui/qstyleoption.h"
#include <private/qmenu_p.h> // Mac needs what in this file!
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
#include "qguifunctions_wince.h"
#endif
@@ -77,12 +77,13 @@ class QMenuBarPrivate : public QWidgetPrivate
Q_DECLARE_PUBLIC(QMenuBar)
public:
QMenuBarPrivate() : itemsDirty(0), itemsWidth(0), itemsStart(-1), currentAction(0), mouseDown(0),
- closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0)
+ closePopupMode(0), defaultPopDown(1), popupState(0), keyboardState(0), altPressed(0),
+ nativeMenuBar(-1)
#ifdef Q_WS_MAC
, mac_menubar(0)
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
, wce_menubar(0), wceClassicMenu(false)
#endif
#ifdef Q_OS_SYMBIAN
@@ -95,7 +96,7 @@ public:
#ifdef Q_WS_MAC
delete mac_menubar;
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
delete wce_menubar;
#endif
#ifdef Q_OS_SYMBIAN
@@ -133,6 +134,8 @@ public:
uint keyboardState : 1, altPressed : 1;
QPointer<QWidget> keyboardFocusWidget;
+
+ int nativeMenuBar : 3; // Only has values -1, 0, and 1
//firing of events
void activateAction(QAction *, QAction::ActionEvent);
@@ -141,7 +144,7 @@ public:
void _q_internalShortcutActivated(int);
void _q_updateLayout();
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void _q_updateDefaultAction();
#endif
@@ -195,7 +198,7 @@ public:
void macDestroyMenuBar();
OSMenuRef macMenu();
#endif
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
void wceCreateMenuBar(QWidget *);
void wceDestroyMenuBar();
struct QWceMenuBarPrivate {
diff --git a/src/gui/widgets/qplaintextedit.cpp b/src/gui/widgets/qplaintextedit.cpp
index 3d2c4f5..36bac84 100644
--- a/src/gui/widgets/qplaintextedit.cpp
+++ b/src/gui/widgets/qplaintextedit.cpp
@@ -375,11 +375,16 @@ void QPlainTextDocumentLayout::layoutBlock(const QTextBlock &block)
extraMargin += fm.width(QChar(0x21B5));
}
tl->beginLayout();
+ qreal availableWidth = d->width;
+ if (availableWidth <= 0) {
+ availableWidth = INT_MAX; // similar to text edit with pageSize.width == 0
+ }
+ availableWidth -= 2*margin + extraMargin;
while (1) {
QTextLine line = tl->createLine();
if (!line.isValid())
break;
- line.setLineWidth(d->width - 2*margin - extraMargin);
+ line.setLineWidth(availableWidth);
height += leading;
line.setPosition(QPointF(margin, height));
@@ -444,7 +449,7 @@ QPlainTextEditControl::QPlainTextEditControl(QPlainTextEdit *parent)
void QPlainTextEditPrivate::_q_cursorPositionChanged()
{
pageUpDownLastCursorYIsValid = false;
-};
+}
void QPlainTextEditPrivate::_q_verticalScrollbarActionTriggered(int action) {
if (action == QAbstractSlider::SliderPageStepAdd) {
@@ -560,7 +565,8 @@ QRectF QPlainTextEditControl::blockBoundingRect(const QTextBlock &block) const {
if (!currentBlock.isValid())
return QRectF();
Q_ASSERT(currentBlock.blockNumber() == currentBlockNumber);
- QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(document()->documentLayout());
+ QTextDocument *doc = document();
+ QPlainTextDocumentLayout *documentLayout = qobject_cast<QPlainTextDocumentLayout*>(doc->documentLayout());
Q_ASSERT(documentLayout);
QPointF offset;
@@ -571,13 +577,22 @@ QRectF QPlainTextEditControl::blockBoundingRect(const QTextBlock &block) const {
offset.ry() += r.height();
currentBlock = currentBlock.next();
++currentBlockNumber;
+ if (!currentBlock.isVisible()) {
+ currentBlock = doc->findBlockByLineNumber(currentBlock.firstLineNumber());
+ currentBlockNumber = currentBlock.blockNumber();
+ }
r = documentLayout->blockBoundingRect(currentBlock);
}
while (currentBlockNumber > blockNumber && offset.y() >= -textEdit->viewport()->height()) {
currentBlock = currentBlock.previous();
+ --currentBlockNumber;
+ while (!currentBlock.isVisible()) {
+ currentBlock = currentBlock.previous();
+ --currentBlockNumber;
+ }
if (!currentBlock.isValid())
break;
- --currentBlockNumber;
+
r = documentLayout->blockBoundingRect(currentBlock);
offset.ry() -= r.height();
}
@@ -1747,7 +1762,7 @@ void QPlainTextEdit::paintEvent(QPaintEvent *e)
QTextBlock block = firstVisibleBlock();
qreal maximumWidth = document()->documentLayout()->documentSize().width();
-
+
// keep right margin clean from full-width selection
int maxX = offset.x() + qMax((qreal)viewportRect.width(), maximumWidth)
- document()->documentMargin();
diff --git a/src/gui/widgets/qprintpreviewwidget.cpp b/src/gui/widgets/qprintpreviewwidget.cpp
index 80c1271..24d81e0 100644
--- a/src/gui/widgets/qprintpreviewwidget.cpp
+++ b/src/gui/widgets/qprintpreviewwidget.cpp
@@ -99,29 +99,8 @@ void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QRectF paperRect(0,0, paperSize.width(), paperSize.height());
- painter->setClipRect(paperRect & option->exposedRect);
- painter->fillRect(paperRect, Qt::white);
- if (!pagePicture)
- return;
- painter->drawPicture(pageRect.topLeft(), *pagePicture);
-
- // Effect: make anything drawn in the margins look washed out.
- QPainterPath path;
- path.addRect(paperRect);
- path.addRect(pageRect);
- painter->setPen(QPen(Qt::NoPen));
- painter->setBrush(QColor(255, 255, 255, 180));
- painter->drawPath(path);
-
- painter->setClipRect(option->exposedRect);
-#if 0
- // Draw frame around paper.
- painter->setPen(QPen(Qt::black, 0));
- painter->setBrush(Qt::NoBrush);
- painter->drawRect(paperRect);
-#endif
-
// Draw shadow
+ painter->setClipRect(option->exposedRect);
qreal shWidth = paperRect.width()/100;
QRectF rshadow(paperRect.topRight() + QPointF(0, shWidth),
paperRect.bottomRight() + QPointF(shWidth, 0));
@@ -142,6 +121,27 @@ void PageItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
cgrad.setColorAt(1.0, QColor(0,0,0,0));
painter->fillRect(cshadow, QBrush(cgrad));
+ painter->setClipRect(paperRect & option->exposedRect);
+ painter->fillRect(paperRect, Qt::white);
+ if (!pagePicture)
+ return;
+ painter->drawPicture(pageRect.topLeft(), *pagePicture);
+
+ // Effect: make anything drawn in the margins look washed out.
+ QPainterPath path;
+ path.addRect(paperRect);
+ path.addRect(pageRect);
+ painter->setPen(QPen(Qt::NoPen));
+ painter->setBrush(QColor(255, 255, 255, 180));
+ painter->drawPath(path);
+
+#if 0
+ // Draw frame around paper.
+ painter->setPen(QPen(Qt::black, 0));
+ painter->setBrush(Qt::NoBrush);
+ painter->drawRect(paperRect);
+#endif
+
// todo: drawtext "Page N" below paper
}
diff --git a/src/gui/widgets/qprogressbar.cpp b/src/gui/widgets/qprogressbar.cpp
index 1a7f878..adc3582 100644
--- a/src/gui/widgets/qprogressbar.cpp
+++ b/src/gui/widgets/qprogressbar.cpp
@@ -450,19 +450,19 @@ QString QProgressBar::text() const
qint64 totalSteps = qint64(d->maximum) - qint64(d->minimum);
QString result = d->format;
- result.replace(QLatin1String("%m"), QString::fromLatin1("%1").arg(totalSteps));
- result.replace(QLatin1String("%v"), QString::fromLatin1("%1").arg(d->value));
+ result.replace(QLatin1String("%m"), QString::number(totalSteps));
+ result.replace(QLatin1String("%v"), QString::number(d->value));
// If max and min are equal and we get this far, it means that the
// progress bar has one step and that we are on that step. Return
// 100% here in order to avoid division by zero further down.
if (totalSteps == 0) {
- result.replace(QLatin1String("%p"), QString::fromLatin1("%1").arg(100));
+ result.replace(QLatin1String("%p"), QString::number(100));
return result;
}
int progress = int(((qreal(d->value) - qreal(d->minimum)) * 100.0) / totalSteps);
- result.replace(QLatin1String("%p"), QString::fromLatin1("%1").arg(progress));
+ result.replace(QLatin1String("%p"), QString::number(progress));
return result;
}
diff --git a/src/gui/widgets/qpushbutton.cpp b/src/gui/widgets/qpushbutton.cpp
index 03ca751..b526f02 100644
--- a/src/gui/widgets/qpushbutton.cpp
+++ b/src/gui/widgets/qpushbutton.cpp
@@ -527,8 +527,7 @@ void QPushButton::setMenu(QMenu* menu)
return;
if (menu && !d->menu) {
- disconnect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()));
- connect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()));
+ connect(this, SIGNAL(pressed()), this, SLOT(_q_popupPressed()), Qt::UniqueConnection);
}
if (d->menu)
removeAction(d->menu->menuAction());
@@ -577,7 +576,7 @@ void QPushButtonPrivate::_q_popupPressed()
menu->setNoReplayFor(q);
bool horizontal = true;
#if !defined(QT_NO_TOOLBAR)
- QToolBar *tb = qobject_cast<QToolBar*>(q->parentWidget());
+ QToolBar *tb = qobject_cast<QToolBar*>(parent);
if (tb && tb->orientation() == Qt::Vertical)
horizontal = false;
#endif
@@ -590,7 +589,7 @@ void QPushButtonPrivate::_q_popupPressed()
int x = globalPos.x();
int y = globalPos.y();
if (horizontal) {
- if (globalPos.y() + rect.height() + menuSize.height() <= qApp->desktop()->height()) {
+ if (globalPos.y() + rect.height() + menuSize.height() <= QApplication::desktop()->height()) {
y += rect.height();
} else {
y -= menuSize.height();
@@ -598,7 +597,7 @@ void QPushButtonPrivate::_q_popupPressed()
if (q->layoutDirection() == Qt::RightToLeft)
x += rect.width() - menuSize.width();
} else {
- if (globalPos.x() + rect.width() + menu->sizeHint().width() <= qApp->desktop()->width())
+ if (globalPos.x() + rect.width() + menu->sizeHint().width() <= QApplication::desktop()->width())
x += rect.width();
else
x -= menuSize.width();
diff --git a/src/gui/widgets/qsizegrip.cpp b/src/gui/widgets/qsizegrip.cpp
index 6458b15..244d34a 100644
--- a/src/gui/widgets/qsizegrip.cpp
+++ b/src/gui/widgets/qsizegrip.cpp
@@ -139,7 +139,7 @@ public:
void QSizeGripPrivate::updateMacSizer(bool hide) const
{
Q_Q(const QSizeGrip);
- if (QApplication::closingDown() || !q->parentWidget())
+ if (QApplication::closingDown() || !parent)
return;
QWidget *topLevelWindow = qt_sizegrip_topLevelWidget(const_cast<QSizeGrip *>(q));
if(topLevelWindow && topLevelWindow->isWindow())
diff --git a/src/gui/widgets/qslider.cpp b/src/gui/widgets/qslider.cpp
index 32b9021..5b9c8a4 100644
--- a/src/gui/widgets/qslider.cpp
+++ b/src/gui/widgets/qslider.cpp
@@ -62,7 +62,6 @@ public:
int tickInterval;
QSlider::TickPosition tickPosition;
int clickOffset;
- int snapBackPosition;
void init();
void resetLayoutItemMargins();
int pixelPosToRangeValue(int pos) const;
@@ -493,7 +492,6 @@ void QSlider::mousePressEvent(QMouseEvent *ev)
setRepeatAction(SliderNoAction);
QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
d->clickOffset = d->pick(ev->pos() - sr.topLeft());
- d->snapBackPosition = d->position;
update(sr);
setSliderDown(true);
}
@@ -513,14 +511,6 @@ void QSlider::mouseMoveEvent(QMouseEvent *ev)
int newPosition = d->pixelPosToRangeValue(d->pick(ev->pos()) - d->clickOffset);
QStyleOptionSlider opt;
initStyleOption(&opt);
- int m = style()->pixelMetric(QStyle::PM_MaximumDragDistance, &opt, this);
- if (m >= 0) {
- QRect r = rect();
- r.adjust(-m, -m, m, m);
- if (!r.contains(ev->pos())) {
- newPosition = d->snapBackPosition;
- }
- }
setSliderPosition(newPosition);
}
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp
index 295bf48..7906022 100644
--- a/src/gui/widgets/qspinbox.cpp
+++ b/src/gui/widgets/qspinbox.cpp
@@ -992,7 +992,7 @@ QVariant QSpinBoxPrivate::valueFromText(const QString &text) const
bool QSpinBoxPrivate::isIntermediateValue(const QString &str) const
{
- const int num = q_func()->locale().toInt(str, 0, 10);
+ const int num = locale.toInt(str, 0, 10);
const int min = minimum.toInt();
const int max = maximum.toInt();
@@ -1039,7 +1039,7 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
{
if (cachedText == input && !input.isEmpty()) {
state = cachedState;
- QSBDEBUG() << "cachedText was" << "'" << cachedText << "'" << "state was "
+ QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
<< state << " and value was " << cachedValue;
return cachedValue;
@@ -1057,18 +1057,18 @@ QVariant QSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
|| (min >= 0 && copy == QLatin1String("+")))) {
state = QValidator::Intermediate;
QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
- } else if (copy.startsWith(QLatin1String("-")) && min >= 0) {
+ } else if (copy.startsWith(QLatin1Char('-')) && min >= 0) {
state = QValidator::Invalid; // special-case -0 will be interpreted as 0 and thus not be invalid with a range from 0-100
} else {
bool ok = false;
bool removedThousand = false;
- num = q_func()->locale().toInt(copy, &ok, 10);
+ num = locale.toInt(copy, &ok, 10);
if (!ok && copy.contains(thousand) && (max >= 1000 || min <= -1000)) {
const int s = copy.size();
copy.remove(thousand);
pos = qMax(0, pos - (s - copy.size()));
removedThousand = true;
- num = q_func()->locale().toInt(copy, &ok, 10);
+ num = locale.toInt(copy, &ok, 10);
}
QSBDEBUG() << __FILE__ << __LINE__<< "num is set to" << num;
if (!ok) {
@@ -1263,9 +1263,7 @@ QVariant QDoubleSpinBoxPrivate::valueFromText(const QString &f) const
double QDoubleSpinBoxPrivate::round(double value) const
{
- Q_Q(const QDoubleSpinBox);
- const QString strDbl = q->locale().toString(value, 'f', decimals);
- return q->locale().toDouble(strDbl);
+ return QString::number(value, 'f', decimals).toDouble();
}
@@ -1280,7 +1278,7 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
{
if (cachedText == input && !input.isEmpty()) {
state = cachedState;
- QSBDEBUG() << "cachedText was" << "'" << cachedText << "'" << "state was "
+ QSBDEBUG() << "cachedText was '" << cachedText << "' state was "
<< state << " and value was " << cachedValue;
return cachedValue;
}
@@ -1357,9 +1355,8 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
{
bool ok = false;
- QLocale loc(q_func()->locale());
- num = loc.toDouble(copy, &ok);
- QSBDEBUG() << __FILE__ << __LINE__ << loc << copy << num << ok;
+ num = locale.toDouble(copy, &ok);
+ QSBDEBUG() << __FILE__ << __LINE__ << locale << copy << num << ok;
bool notAcceptable = false;
if (!ok) {
@@ -1384,7 +1381,7 @@ QVariant QDoubleSpinBoxPrivate::validateAndInterpret(QString &input, int &pos,
pos = qMax(0, pos - (s - copy.size()));
- num = loc.toDouble(copy, &ok);
+ num = locale.toDouble(copy, &ok);
QSBDEBUG() << thousand << num << copy << ok;
if (!ok) {
diff --git a/src/gui/widgets/qsplitter.cpp b/src/gui/widgets/qsplitter.cpp
index 45e838f..24a8b6c 100644
--- a/src/gui/widgets/qsplitter.cpp
+++ b/src/gui/widgets/qsplitter.cpp
@@ -119,7 +119,6 @@ QSplitterHandle::QSplitterHandle(Qt::Orientation orientation, QSplitter *parent)
{
Q_D(QSplitterHandle);
d->s = parent;
- d->hover = false;
setOrientation(orientation);
}
@@ -269,8 +268,11 @@ void QSplitterHandle::mouseMoveEvent(QMouseEvent *e)
void QSplitterHandle::mousePressEvent(QMouseEvent *e)
{
Q_D(QSplitterHandle);
- if (e->button() == Qt::LeftButton)
+ if (e->button() == Qt::LeftButton) {
d->mouseOffset = d->pick(e->pos());
+ d->pressed = true;
+ update();
+ }
}
/*!
@@ -285,6 +287,10 @@ void QSplitterHandle::mouseReleaseEvent(QMouseEvent *e)
d->s->setRubberBand(-1);
moveSplitter(pos);
}
+ if (e->button() == Qt::LeftButton) {
+ d->pressed = false;
+ update();
+ }
}
/*!
@@ -303,6 +309,8 @@ void QSplitterHandle::paintEvent(QPaintEvent *)
opt.state = QStyle::State_None;
if (d->hover)
opt.state |= QStyle::State_MouseOver;
+ if (d->pressed)
+ opt.state |= QStyle::State_Sunken;
if (isEnabled())
opt.state |= QStyle::State_Enabled;
parentWidget()->style()->drawControl(QStyle::CE_Splitter, &opt, &p, d->s);
@@ -389,7 +397,7 @@ void QSplitterPrivate::recalc(bool update)
}
if (empty) {
- if (qobject_cast<QSplitter *>(q->parentWidget())) {
+ if (qobject_cast<QSplitter *>(parent)) {
// nested splitters; be nice
maxl = maxt = 0;
} else {
diff --git a/src/gui/widgets/qsplitter_p.h b/src/gui/widgets/qsplitter_p.h
index 5cc43af..9f6fe0c 100644
--- a/src/gui/widgets/qsplitter_p.h
+++ b/src/gui/widgets/qsplitter_p.h
@@ -131,16 +131,17 @@ class QSplitterHandlePrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QSplitterHandle)
public:
- QSplitterHandlePrivate() : orient(Qt::Horizontal), opaq(false), s(0), mouseOffset(0) {}
+ QSplitterHandlePrivate() : s(0), orient(Qt::Horizontal), mouseOffset(0), opaq(false), hover(false), pressed(false) {}
inline int pick(const QPoint &pos) const
{ return orient == Qt::Horizontal ? pos.x() : pos.y(); }
- Qt::Orientation orient;
- bool opaq;
QSplitter *s;
- bool hover;
+ Qt::Orientation orient;
int mouseOffset;
+ bool opaq : 1;
+ bool hover : 1;
+ bool pressed : 1;
};
QT_END_NAMESPACE
diff --git a/src/gui/widgets/qstatusbar.cpp b/src/gui/widgets/qstatusbar.cpp
index c970838..a248346 100644
--- a/src/gui/widgets/qstatusbar.cpp
+++ b/src/gui/widgets/qstatusbar.cpp
@@ -144,7 +144,7 @@ QRect QStatusBarPrivate::messageRect() const
if (rtl)
left = qMax(left, item->w->x() + item->w->width() + 2);
else
- right = qMin(right, item->w->x()-1);
+ right = qMin(right, item->w->x() - 2);
}
break;
}
@@ -728,7 +728,7 @@ void QStatusBar::paintEvent(QPaintEvent *event)
QStatusBarPrivate::SBItem* item = d->items.at(i);
if (item && item->w->isVisible() && (!haveMessage || item->p)) {
QRect ir = item->w->geometry().adjusted(-2, -1, 2, 1);
- if (event->rect().contains(ir)) {
+ if (event->rect().intersects(ir)) {
QStyleOption opt(0);
opt.rect = ir;
opt.palette = palette();
diff --git a/src/gui/widgets/qtabbar.cpp b/src/gui/widgets/qtabbar.cpp
index 785d772..bd8a1b0 100644
--- a/src/gui/widgets/qtabbar.cpp
+++ b/src/gui/widgets/qtabbar.cpp
@@ -176,12 +176,11 @@ void QTabBar::initStyleOption(QStyleOptionTab *option, int tabIndex) const
if (tw->cornerWidget(Qt::TopRightCorner) || tw->cornerWidget(Qt::BottomRightCorner))
option->cornerWidgets |= QStyleOptionTab::RightCornerWidget;
}
+#endif
QRect textRect = style()->subElementRect(QStyle::SE_TabBarTabText, option, this);
-
option->text = fontMetrics().elidedText(option->text, d->elideMode, textRect.width(),
Qt::TextShowMnemonic);
-#endif
}
/*!
@@ -1944,8 +1943,10 @@ void QTabBar::changeEvent(QEvent *event)
if (event->type() == QEvent::StyleChange) {
d->elideMode = Qt::TextElideMode(style()->styleHint(QStyle::SH_TabBar_ElideMode, 0, this));
d->useScrollButtons = !style()->styleHint(QStyle::SH_TabBar_PreferNoArrows, 0, this);
+ d->refresh();
+ } else if (event->type() == QEvent::FontChange) {
+ d->refresh();
}
- d->refresh();
QWidget::changeEvent(event);
}
diff --git a/src/gui/widgets/qtabwidget.cpp b/src/gui/widgets/qtabwidget.cpp
index 43b2f54..c97154c 100644
--- a/src/gui/widgets/qtabwidget.cpp
+++ b/src/gui/widgets/qtabwidget.cpp
@@ -1057,7 +1057,7 @@ void QTabWidget::keyPressEvent(QKeyEvent *e)
break;
}
}
- if (!qApp->focusWidget())
+ if (!QApplication::focusWidget())
d->tabs->setFocus();
} else {
e->ignore();
diff --git a/src/gui/widgets/qtextbrowser.cpp b/src/gui/widgets/qtextbrowser.cpp
index a1f4d34..d849184 100644
--- a/src/gui/widgets/qtextbrowser.cpp
+++ b/src/gui/widgets/qtextbrowser.cpp
@@ -263,7 +263,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
Q_Q(QTextBrowser);
#ifndef QT_NO_CURSOR
if (q->isVisible())
- qApp->setOverrideCursor(Qt::WaitCursor);
+ QApplication::setOverrideCursor(Qt::WaitCursor);
#endif
textOrSourceChanged = true;
@@ -295,9 +295,9 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
if (q->isVisible()) {
QString firstTag = txt.left(txt.indexOf(QLatin1Char('>')) + 1);
- if (firstTag.left(3) == QLatin1String("<qt") && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
+ if (firstTag.startsWith(QLatin1String("<qt")) && firstTag.contains(QLatin1String("type")) && firstTag.contains(QLatin1String("detail"))) {
#ifndef QT_NO_CURSOR
- qApp->restoreOverrideCursor();
+ QApplication::restoreOverrideCursor();
#endif
#ifndef QT_NO_WHATSTHIS
QWhatsThis::showText(QCursor::pos(), txt, q);
@@ -342,7 +342,7 @@ void QTextBrowserPrivate::setSource(const QUrl &url)
#ifndef QT_NO_CURSOR
if (q->isVisible())
- qApp->restoreOverrideCursor();
+ QApplication::restoreOverrideCursor();
#endif
emit q->sourceChanged(url);
}
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index 1babb6d..7787a66 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -198,7 +198,7 @@ void QToolBarPrivate::initDrag(const QPoint &pos)
if (state != 0)
return;
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
@@ -224,7 +224,7 @@ void QToolBarPrivate::startDrag(bool moving)
if ((moving && state->moving) || state->dragging)
return;
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
Q_ASSERT(win != 0);
QMainWindowLayout *layout = qobject_cast<QMainWindowLayout*>(win->layout());
Q_ASSERT(layout != 0);
@@ -274,14 +274,16 @@ void QToolBarPrivate::endDrag()
bool QToolBarPrivate::mousePressEvent(QMouseEvent *event)
{
- if (layout->handleRect().contains(event->pos()) == false) {
+ Q_Q(QToolBar);
+ QStyleOptionToolBar opt;
+ q->initStyleOption(&opt);
+ if (q->style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, q).contains(event->pos()) == false) {
#ifdef Q_WS_MAC
- Q_Q(QToolBar);
// When using the unified toolbar on Mac OS X the user can can click and
// drag between toolbar contents to move the window. Make this work by
// implementing the standard mouse-dragging code and then call
// window->move() in mouseMoveEvent below.
- if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(q->parentWidget())) {
+ if (QMainWindow *mainWindow = qobject_cast<QMainWindow *>(parent)) {
if (mainWindow->toolBarArea(q) == Qt::TopToolBarArea
&& mainWindow->unifiedTitleAndToolBarOnMac()
&& q->childAt(event->pos()) == 0) {
@@ -335,7 +337,7 @@ bool QToolBarPrivate::mouseMoveEvent(QMouseEvent *event)
return false;
}
- QMainWindow *win = qobject_cast<QMainWindow*>(q->parentWidget());
+ QMainWindow *win = qobject_cast<QMainWindow*>(parent);
if (win == 0)
return true;
@@ -1041,7 +1043,7 @@ void QToolBar::paintEvent(QPaintEvent *)
style->drawControl(QStyle::CE_ToolBar, &opt, &p, this);
}
- opt.rect = d->layout->handleRect();
+ opt.rect = style->subElementRect(QStyle::SE_ToolBarHandle, &opt, this);
if (opt.rect.isValid())
style->drawPrimitive(QStyle::PE_IndicatorToolBarHandle, &opt, &p, this);
}
@@ -1142,7 +1144,9 @@ bool QToolBar::event(QEvent *event)
case QEvent::HoverMove: {
#ifndef QT_NO_CURSOR
QHoverEvent *e = static_cast<QHoverEvent*>(event);
- if (d->layout->handleRect().contains(e->pos()))
+ QStyleOptionToolBar opt;
+ initStyleOption(&opt);
+ if (style()->subElementRect(QStyle::SE_ToolBarHandle, &opt, this).contains(e->pos()))
setCursor(Qt::SizeAllCursor);
else
unsetCursor();
@@ -1153,7 +1157,7 @@ bool QToolBar::event(QEvent *event)
if (d->mouseMoveEvent(static_cast<QMouseEvent*>(event)))
return true;
break;
-#ifdef Q_OS_WINCE
+#ifdef Q_WS_WINCE
case QEvent::ContextMenu:
{
QContextMenuEvent* contextMenuEvent = static_cast<QContextMenuEvent*>(event);
@@ -1177,7 +1181,7 @@ bool QToolBar::event(QEvent *event)
if (!d->layout->expanded)
break;
- QWidget *w = qApp->activePopupWidget();
+ QWidget *w = QApplication::activePopupWidget();
if (waitForPopup(this, w)) {
d->waitForPopupTimer->start();
break;
@@ -1197,7 +1201,7 @@ void QToolBarPrivate::_q_waitForPopup()
{
Q_Q(QToolBar);
- QWidget *w = qApp->activePopupWidget();
+ QWidget *w = QApplication::activePopupWidget();
if (!waitForPopup(q, w)) {
waitForPopupTimer->stop();
if (!q->underMouse())
diff --git a/src/gui/widgets/qtoolbararealayout.cpp b/src/gui/widgets/qtoolbararealayout.cpp
index 49f4a9e..b1b743e 100644
--- a/src/gui/widgets/qtoolbararealayout.cpp
+++ b/src/gui/widgets/qtoolbararealayout.cpp
@@ -113,7 +113,7 @@ QSize QToolBarAreaLayoutLine::sizeHint() const
continue;
QSize sh = item.sizeHint();
- a += pick(o, sh) + item.extraSpace;
+ a += item.preferredSize > 0 ? item.preferredSize : pick(o, sh);
b = qMax(b, perp(o, sh));
}
@@ -163,12 +163,17 @@ void QToolBarAreaLayoutLine::fitLayout()
int itemMin = pick(o, item.minimumSize());
int itemHint = pick(o, item.sizeHint());
//we ensure the extraspace is not too low
- item.extraSpace = qMax(itemMin - itemHint, item.extraSpace);
- itemHint += item.extraSpace;
- int itemExtra = qMin(itemHint - itemMin, extra);
+ item.size = qMax(item.size, itemHint);
+ if (item.preferredSize > 0) {
+ //preferredSize would be the default size
+ item.size = item.preferredSize;
+ }
+
+ //the extraspace is the space above the item minimum sizehint
+ int extraSpace = qMin(item.size - itemMin, extra);
+ item.size = itemMin + extraSpace; //that is the real size
- item.size = itemMin + itemExtra;
- extra -= itemExtra;
+ extra -= extraSpace;
last = i;
}
@@ -395,17 +400,15 @@ void QToolBarAreaLayoutInfo::removeToolBarBreak(QToolBar *before)
void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
{
- if (dirty) {
+ if (dirty)
fitLayout();
- }
dirty = true;
- if (o == Qt::Vertical) {
+ if (o == Qt::Vertical)
pos -= rect.top();
- }
- //here we actually update the extraSpace for the line containing the toolbar so that we move it
+ //here we actually update the preferredSize for the line containing the toolbar so that we move it
for (int j = 0; j < lines.count(); ++j) {
QToolBarAreaLayoutLine &line = lines[j];
@@ -432,22 +435,22 @@ void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
newPos = qMin(pos, maxPos);
}
- //let's update the previous extra space
+ //extra is the number of pixels to add to the previous toolbar
int extra = newPos - current.pos;
- if (qAbs(previous.extraSpace + extra) < QApplication::startDragDistance()) {
- //we stick to the default space
- extra = 0;
+ //we check if the previous is near its size hint
+ //in which case we try to stick to it
+ const int diff = pick(o, previous.sizeHint()) - (previous.size + extra);
+ if (qAbs(diff) < QApplication::startDragDistance()) {
+ //we stick to the default place and size
+ extra += diff;
}
//update for the current item
- current.extraSpace -= extra;
- //this ensures the toolbars to be pushed to the right when necessary
- current.extraSpace = qMax(pick(o,current.minimumSize())- pick(o,current.sizeHint()), current.extraSpace);
-
- if (extra >= 0) {
- previous.extraSpace += extra;
+ current.extendSize(line.o, -extra);
+ if (extra >= 0) {
+ previous.extendSize(line.o, extra);
} else {
//we need to push the toolbars on the left starting with previous
extra = -extra; // we just need to know the number of pixels
@@ -455,13 +458,13 @@ void QToolBarAreaLayoutInfo::moveToolBar(QToolBar *toolbar, int pos)
for(int l = previousIndex; l >=0; --l) {
QToolBarAreaLayoutItem &item = line.toolBarItems[l];
if (!item.skip()) {
- const int minExtraSpace = pick(o, item.minimumSize()) - pick(o, item.sizeHint());
- const int margin = item.extraSpace - minExtraSpace;
+ const int minPreferredSize = pick(o, item.minimumSize());
+ const int margin = item.size - minPreferredSize;
if (margin < extra) {
- item.extraSpace = minExtraSpace;
+ item.resize(line.o, minPreferredSize);
extra -= margin;
} else {
- item.extraSpace -= extra;
+ item.extendSize(line.o, -extra);
extra = 0;
}
}
@@ -536,13 +539,22 @@ bool QToolBarAreaLayoutInfo::insertGap(QList<int> path, QLayoutItem *item)
gap_item.gap = true;
gap_item.widgetItem = item;
- //update the previous item's extra space
+ //update the previous item's preferred size
for(int p = k - 1 ; p >= 0; --p) {
QToolBarAreaLayoutItem &previous = line.toolBarItems[p];
if (!previous.skip()) {
//we found the previous one
- gap_item.extraSpace = qMax(0, previous.extraSpace - pick(o, gap_item.sizeHint()));
- previous.extraSpace = qMin(previous.extraSpace, 0);
+ int previousSizeHint = pick(line.o, previous.sizeHint());
+ int previousExtraSpace = previous.size - previousSizeHint;
+
+ if (previousExtraSpace > 0) {
+ //in this case we reset the space
+ previous.preferredSize = -1;
+ previous.size = previousSizeHint;
+
+ gap_item.resize(o, previousExtraSpace);
+ }
+
break;
}
}
@@ -1132,15 +1144,22 @@ QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *oth
//update the leading space here
QToolBarAreaLayoutInfo &info = docks[path.at(0)];
QToolBarAreaLayoutLine &line = info.lines[path.at(1)];
- if (item.extraSpace != 0) {
+ if (item.size != pick(line.o, item.realSizeHint())) {
+ //the item doesn't have its default size
+ //so we'll give this to the next item
int newExtraSpace = 0;
+ //let's iterate over the siblings of the current item that pare placed before it
+ //we need to find just the one before
for (int i = path.at(2) - 1; i >= 0; --i) {
QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
if (!previous.skip()) {
+ //we need to check if it has a previous element and a next one
+ //the previous will get its size changed
for (int j = path.at(2) + 1; j < line.toolBarItems.count(); ++j) {
const QToolBarAreaLayoutItem &next = line.toolBarItems.at(j);
if (!next.skip()) {
- newExtraSpace = previous.extraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
+ newExtraSpace = next.pos - previous.pos - pick(line.o, previous.sizeHint());
+ previous.resize(line.o, next.pos - previous.pos);
}
break;
}
@@ -1154,7 +1173,7 @@ QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *oth
for (int i = path.at(2) - 1; i >= 0; --i) {
QToolBarAreaLayoutItem &previous = line.toolBarItems[i];
if (!previous.skip()) {
- previous.extraSpace = newExtraSpace;
+ previous.resize(line.o, pick(line.o, previous.sizeHint()) + newExtraSpace);
break;
}
}
@@ -1162,7 +1181,6 @@ QLayoutItem *QToolBarAreaLayout::unplug(QList<int> path, QToolBarAreaLayout *oth
}
}
-
Q_ASSERT(!item.gap);
item.gap = true;
return item.widgetItem;
@@ -1253,8 +1271,8 @@ void QToolBarAreaLayout::saveState(QDataStream &stream) const
}
stream << shownOrientation;
stream << item.pos;
- //if extraSpace is 0 the item has its "normal" size, so no need to store the size (we store -1)
- stream << (item.extraSpace == 0 ? -1 : (pick(line.o, item.realSizeHint()) + item.extraSpace));
+ //we store the preferred size. If the use rdidn't resize the toolbars it will be -1
+ stream << item.preferredSize;
uint geom0, geom1;
packRect(&geom0, &geom1, widget->geometry(), widget->isWindow());
@@ -1339,10 +1357,7 @@ bool QToolBarAreaLayout::restoreState(QDataStream &stream, const QList<QToolBar*
toolBar->setVisible(shown & 1);
toolBar->d_func()->setWindowState(floating, true, rect);
- //if it is -1, it means we should use the default size
- item.extraSpace = (item.size == -1) ? 0 : item.size - pick(line.o, item.realSizeHint());
-
-
+ item.preferredSize = item.size;
line.toolBarItems.append(item);
}
}
diff --git a/src/gui/widgets/qtoolbararealayout_p.h b/src/gui/widgets/qtoolbararealayout_p.h
index 574e366..5662ffc 100644
--- a/src/gui/widgets/qtoolbararealayout_p.h
+++ b/src/gui/widgets/qtoolbararealayout_p.h
@@ -59,6 +59,33 @@
QT_BEGIN_NAMESPACE
+static inline int pick(Qt::Orientation o, const QPoint &pos)
+{ return o == Qt::Horizontal ? pos.x() : pos.y(); }
+
+static inline int pick(Qt::Orientation o, const QSize &size)
+{ return o == Qt::Horizontal ? size.width() : size.height(); }
+
+static inline int &rpick(Qt::Orientation o, QPoint &pos)
+{ return o == Qt::Horizontal ? pos.rx() : pos.ry(); }
+
+static inline int &rpick(Qt::Orientation o, QSize &size)
+{ return o == Qt::Horizontal ? size.rwidth() : size.rheight(); }
+
+static inline QSizePolicy::Policy pick(Qt::Orientation o, const QSizePolicy &policy)
+{ return o == Qt::Horizontal ? policy.horizontalPolicy() : policy.verticalPolicy(); }
+
+static inline int perp(Qt::Orientation o, const QPoint &pos)
+{ return o == Qt::Vertical ? pos.x() : pos.y(); }
+
+static inline int perp(Qt::Orientation o, const QSize &size)
+{ return o == Qt::Vertical ? size.width() : size.height(); }
+
+static inline int &rperp(Qt::Orientation o, QPoint &pos)
+{ return o == Qt::Vertical ? pos.rx() : pos.ry(); }
+
+static inline int &rperp(Qt::Orientation o, QSize &size)
+{ return o == Qt::Vertical ? size.rwidth() : size.rheight(); }
+
#ifndef QT_NO_TOOLBAR
class QToolBar;
@@ -70,17 +97,41 @@ class QToolBarAreaLayoutItem
{
public:
QToolBarAreaLayoutItem(QLayoutItem *item = 0)
- : widgetItem(item), pos(0), size(-1), extraSpace(0), gap(false) {}
+ : widgetItem(item), pos(0), size(-1), preferredSize(-1), gap(false) {}
bool skip() const;
QSize minimumSize() const;
QSize sizeHint() const;
- QSize realSizeHint() const;
+ QSize realSizeHint() const;
+
+ void resize(Qt::Orientation o, int newSize)
+ {
+ newSize = qMax(pick(o, minimumSize()), newSize);
+ int sizeh = pick(o, sizeHint());
+ if (newSize == sizeh) {
+ preferredSize = -1;
+ size = sizeh;
+ } else {
+ preferredSize = newSize;
+ }
+ }
+
+ void extendSize(Qt::Orientation o, int extent)
+ {
+ int newSize = qMax(pick(o, minimumSize()), (preferredSize > 0 ? preferredSize : size) + extent);
+ int sizeh = pick(o, sizeHint());
+ if (newSize == sizeh) {
+ preferredSize = -1;
+ size = sizeh;
+ } else {
+ preferredSize = newSize;
+ }
+ }
QLayoutItem *widgetItem;
int pos;
int size;
- int extraSpace;
+ int preferredSize;
bool gap;
};
diff --git a/src/gui/widgets/qtoolbarlayout.cpp b/src/gui/widgets/qtoolbarlayout.cpp
index 7771f46..0af2b65 100644
--- a/src/gui/widgets/qtoolbarlayout.cpp
+++ b/src/gui/widgets/qtoolbarlayout.cpp
@@ -128,7 +128,7 @@ void QToolBarLayout::setUsePopupMenu(bool set)
invalidate();
if (!set) {
QObject::connect(extension, SIGNAL(clicked(bool)),
- this, SLOT(setExpanded(bool)));
+ this, SLOT(setExpanded(bool)), Qt::UniqueConnection);
extension->setPopupMode(QToolButton::DelayedPopup);
extension->setMenu(0);
delete popupMenu;
@@ -334,7 +334,7 @@ void QToolBarLayout::updateGeomArray() const
if (QMainWindow *mw = qobject_cast<QMainWindow *>(parentWidget()->parentWidget())) {
if (mw->unifiedTitleAndToolBarOnMac()
&& mw->toolBarArea(static_cast<QToolBar *>(parentWidget())) == Qt::TopToolBarArea) {
- if (that->expandFlag) {
+ if (expandFlag) {
tb->setMaximumSize(0xFFFFFF, 0xFFFFFF);
} else {
tb->setMaximumSize(hint);
@@ -360,23 +360,11 @@ void QToolBarLayout::setGeometry(const QRect &rect)
QStyle *style = tb->style();
QStyleOptionToolBar opt;
tb->initStyleOption(&opt);
- const int handleExtent = movable()
- ? style->pixelMetric(QStyle::PM_ToolBarHandleExtent, &opt, tb) : 0;
const int margin = this->margin();
const int extensionExtent = style->pixelMetric(QStyle::PM_ToolBarExtensionExtent, &opt, tb);
Qt::Orientation o = tb->orientation();
QLayout::setGeometry(rect);
- if (movable()) {
- if (o == Qt::Horizontal) {
- handRect = QRect(margin, margin, handleExtent, rect.height() - 2*margin);
- handRect = QStyle::visualRect(parentWidget()->layoutDirection(), rect, handRect);
- } else {
- handRect = QRect(margin, margin, rect.width() - 2*margin, handleExtent);
- }
- } else {
- handRect = QRect();
- }
bool ranOutOfSpace = false;
if (!animating)
@@ -742,11 +730,6 @@ QToolBarItem *QToolBarLayout::createItem(QAction *action)
return result;
}
-QRect QToolBarLayout::handleRect() const
-{
- return handRect;
-}
-
QT_END_NAMESPACE
#endif // QT_NO_TOOLBAR
diff --git a/src/gui/widgets/qtoolbarlayout_p.h b/src/gui/widgets/qtoolbarlayout_p.h
index 2eca773..37755b1 100644
--- a/src/gui/widgets/qtoolbarlayout_p.h
+++ b/src/gui/widgets/qtoolbarlayout_p.h
@@ -65,7 +65,7 @@ class QAction;
class QToolBarExtension;
class QMenu;
-class Q_GUI_EXPORT QToolBarItem : public QWidgetItem
+class QToolBarItem : public QWidgetItem
{
public:
QToolBarItem(QWidget *widget);
@@ -75,7 +75,7 @@ public:
bool customWidget;
};
-class Q_GUI_EXPORT QToolBarLayout : public QLayout
+class QToolBarLayout : public QLayout
{
Q_OBJECT
@@ -100,8 +100,6 @@ public:
int indexOf(QAction *action) const;
int indexOf(QWidget *widget) const { return QLayout::indexOf(widget); }
- QRect handleRect() const;
-
bool layoutActions(const QSize &size);
QSize expandedSize(const QSize &size) const;
bool expanded, animating;
diff --git a/src/gui/widgets/qtoolbutton.cpp b/src/gui/widgets/qtoolbutton.cpp
index 7390d04..d26cf5b 100644
--- a/src/gui/widgets/qtoolbutton.cpp
+++ b/src/gui/widgets/qtoolbutton.cpp
@@ -104,10 +104,9 @@ public:
#ifndef QT_NO_MENU
bool QToolButtonPrivate::hasMenu() const
{
- Q_Q(const QToolButton);
return ((defaultAction && defaultAction->menu())
|| (menuAction && menuAction->menu())
- || q->actions().size() > (defaultAction ? 1 : 0));
+ || actions.size() > (defaultAction ? 1 : 0));
}
#endif
@@ -278,7 +277,7 @@ void QToolButtonPrivate::init()
#endif
defaultAction = 0;
#ifndef QT_NO_TOOLBAR
- if (qobject_cast<QToolBar*>(q->parentWidget()))
+ if (qobject_cast<QToolBar*>(parent))
autoRaise = true;
else
#endif
@@ -859,8 +858,7 @@ void QToolButtonPrivate::_q_buttonPressed()
Q_Q(QToolButton);
if (!hasMenu())
return; // no menu to show
-
- if (delay > 0 && popupMode == QToolButton::DelayedPopup)
+ if (delay > 0 && !popupTimer.isActive() && popupMode == QToolButton::DelayedPopup)
popupTimer.start(delay, q);
else if (delay == 0 || popupMode == QToolButton::InstantPopup)
q->showMenu();
@@ -883,7 +881,6 @@ void QToolButtonPrivate::popupTimerDone()
} else {
actualMenu = new QMenu(q);
mustDeleteActualMenu = true;
- QList<QAction*> actions = q->actions();
for(int i = 0; i < actions.size(); i++)
actualMenu->addAction(actions.at(i));
}
@@ -891,12 +888,12 @@ void QToolButtonPrivate::popupTimerDone()
q->setAutoRepeat(false);
bool horizontal = true;
#if !defined(QT_NO_TOOLBAR)
- QToolBar *tb = qobject_cast<QToolBar*>(q->parentWidget());
+ QToolBar *tb = qobject_cast<QToolBar*>(parent);
if (tb && tb->orientation() == Qt::Vertical)
horizontal = false;
#endif
QPoint p;
- QRect screen = qApp->desktop()->availableGeometry(q);
+ QRect screen = QApplication::desktop()->availableGeometry(q);
QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
QRect rect = q->rect();
if (horizontal) {
diff --git a/src/gui/widgets/qvalidator.cpp b/src/gui/widgets/qvalidator.cpp
index 3aca13d..0a7c43c 100644
--- a/src/gui/widgets/qvalidator.cpp
+++ b/src/gui/widgets/qvalidator.cpp
@@ -370,7 +370,7 @@ static int numDigits(qlonglong n)
if (n == 0)
return 1;
return (int)log10(double(n)) + 1;
-};
+}
static qlonglong pow10(int exp)
{
diff --git a/src/gui/widgets/qwidgetresizehandler.cpp b/src/gui/widgets/qwidgetresizehandler.cpp
index 9171244..0e5b28a 100644
--- a/src/gui/widgets/qwidgetresizehandler.cpp
+++ b/src/gui/widgets/qwidgetresizehandler.cpp
@@ -258,7 +258,7 @@ void QWidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
#ifdef Q_WS_X11
// Workaround for window managers which refuse to move a tool window partially offscreen.
- QRect desktop = qApp->desktop()->availableGeometry(widget);
+ QRect desktop = QApplication::desktop()->availableGeometry(widget);
pp.rx() = qMax(pp.x(), desktop.left());
pp.ry() = qMax(pp.y(), desktop.top());
p.rx() = qMin(p.x(), desktop.right());
diff --git a/src/network/access/qhttp.cpp b/src/network/access/qhttp.cpp
index 332c67b..3e3540e 100644
--- a/src/network/access/qhttp.cpp
+++ b/src/network/access/qhttp.cpp
@@ -1412,6 +1412,7 @@ QString QHttpRequestHeader::toString() const
****************************************************/
/*!
\class QHttp
+ \obsolete
\reentrant
\brief The QHttp class provides an implementation of the HTTP protocol.
@@ -1421,10 +1422,11 @@ QString QHttpRequestHeader::toString() const
\mainclass
This class provides a direct interface to HTTP that allows you to
- have more control over the requests and that allows you to access
- the response header fields. However, for new applications, it is
+ download and upload data with the HTTP protocol.
+ However, for new applications, it is
recommended to use QNetworkAccessManager and QNetworkReply, as
- those classes possess a simpler, yet more powerful API.
+ those classes possess a simpler, yet more powerful API
+ and a more modern protocol implementation.
The class works asynchronously, so there are no blocking
functions. If an operation cannot be executed immediately, the
@@ -1445,7 +1447,7 @@ QString QHttpRequestHeader::toString() const
that indicates if the request finished with an error.
To make an HTTP request you must set up suitable HTTP headers. The
- following example demonstrates, how to request the main HTML page
+ following example demonstrates how to request the main HTML page
from the Trolltech home page (i.e., the URL
\c http://qtsoftware.com/index.html):
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index cec9c87..359cab9 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qhttpnetworkconnection_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#include <private/qnetworkrequest_p.h>
#include <private/qobject_p.h>
#include <private/qauthenticator_p.h>
@@ -63,7 +64,7 @@
QT_BEGIN_NAMESPACE
-const int QHttpNetworkConnectionPrivate::channelCount = 2;
+const int QHttpNetworkConnectionPrivate::channelCount = 6;
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt)
: hostName(hostName), port(port), encrypt(encrypt),
@@ -71,7 +72,9 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host
#ifndef QT_NO_NETWORKPROXY
, networkProxy(QNetworkProxy::NoProxy)
#endif
+
{
+ channels = new Channel[channelCount];
}
QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
@@ -82,6 +85,7 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
delete channels[i].socket;
}
}
+ delete []channels;
}
void QHttpNetworkConnectionPrivate::connectSignals(QAbstractSocket *socket)
@@ -207,12 +211,19 @@ void QHttpNetworkConnectionPrivate::prepareRequest(HttpMessagePair &messagePair)
// add missing fields for the request
QByteArray value;
// check if Content-Length is provided
- QIODevice *data = request.data();
- if (data && request.contentLength() == -1) {
- if (!data->isSequential())
- request.setContentLength(data->size());
- else
- bufferData(messagePair); // ### or do chunked upload
+ QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice();
+ if (uploadByteDevice) {
+ if (request.contentLength() != -1 && uploadByteDevice->size() != -1) {
+ // both values known, take the smaller one.
+ request.setContentLength(qMin(uploadByteDevice->size(), request.contentLength()));
+ } else if (request.contentLength() == -1 && uploadByteDevice->size() != -1) {
+ // content length not supplied by user, but the upload device knows it
+ request.setContentLength(uploadByteDevice->size());
+ } else if (request.contentLength() != -1 && uploadByteDevice->size() == -1) {
+ // everything OK, the user supplied us the contentLength
+ } else if (request.contentLength() == -1 && uploadByteDevice->size() == -1) {
+ qFatal("QHttpNetworkConnectionPrivate: Neither content-length nor upload device size were given");
+ }
}
// set the Connection/Proxy-Connection: Keep-Alive headers
#ifndef QT_NO_NETWORKPROXY
@@ -363,18 +374,12 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket)
false);
#endif
socket->write(header);
- QIODevice *data = channels[i].request.d->data;
- QHttpNetworkReply *reply = channels[i].reply;
- if (reply && reply->d_func()->requestDataBuffer.size())
- data = &channels[i].reply->d_func()->requestDataBuffer;
- if (data && (data->isOpen() || data->open(QIODevice::ReadOnly))) {
- if (data->isSequential()) {
- channels[i].bytesTotal = -1;
- QObject::connect(data, SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadNoBuffer()));
- QObject::connect(data, SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadNoBuffer()));
- } else {
- channels[i].bytesTotal = data->size();
- }
+ QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice();
+ if (uploadByteDevice) {
+ // connect the signals so this function gets called again
+ QObject::connect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead()));
+
+ channels[i].bytesTotal = channels[i].request.contentLength();
} else {
channels[i].state = WaitingState;
break;
@@ -382,30 +387,81 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket)
// write the initial chunk together with the headers
// fall through
}
- case WritingState: { // write the data
- QIODevice *data = channels[i].request.d->data;
- if (channels[i].reply->d_func()->requestDataBuffer.size())
- data = &channels[i].reply->d_func()->requestDataBuffer;
- if (!data || channels[i].bytesTotal == channels[i].written) {
+ case WritingState:
+ {
+ // write the data
+ QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice();
+ if (!uploadByteDevice || channels[i].bytesTotal == channels[i].written) {
+ if (uploadByteDevice)
+ emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal);
channels[i].state = WaitingState; // now wait for response
+ sendRequest(socket);
break;
}
- QByteArray chunk;
- chunk.resize(ChunkSize);
- qint64 readSize = data->read(chunk.data(), ChunkSize);
- if (readSize == -1) {
- // source has reached EOF
- channels[i].state = WaitingState; // now wait for response
- } else if (readSize > 0) {
- // source gave us something useful
- channels[i].written += socket->write(chunk.data(), readSize);
- if (channels[i].reply)
- emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal);
+ // only feed the QTcpSocket buffer when there is less than 32 kB in it
+ const qint64 socketBufferFill = 32*1024;
+ const qint64 socketWriteMaxSize = 16*1024;
+
+
+#ifndef QT_NO_OPENSSL
+ QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket);
+ while ((sslSocket->encryptedBytesToWrite() + sslSocket->bytesToWrite()) <= socketBufferFill
+ && channels[i].bytesTotal != channels[i].written)
+#else
+ while (socket->bytesToWrite() <= socketBufferFill
+ && channels[i].bytesTotal != channels[i].written)
+#endif
+ {
+ // get pointer to upload data
+ qint64 currentReadSize;
+ qint64 desiredReadSize = qMin(socketWriteMaxSize, channels[i].bytesTotal - channels[i].written);
+ const char *readPointer = uploadByteDevice->readPointer(desiredReadSize, currentReadSize);
+
+ if (currentReadSize == -1) {
+ // premature eof happened
+ emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError);
+ return false;
+ break;
+ } else if (readPointer == 0 || currentReadSize == 0) {
+ // nothing to read currently, break the loop
+ break;
+ } else {
+ qint64 currentWriteSize = socket->write(readPointer, currentReadSize);
+ if (currentWriteSize == -1 || currentWriteSize != currentReadSize) {
+ // socket broke down
+ emitReplyError(socket, channels[i].reply, QNetworkReply::UnknownNetworkError);
+ return false;
+ } else {
+ channels[i].written += currentWriteSize;
+ uploadByteDevice->advanceReadPointer(currentWriteSize);
+
+ emit channels[i].reply->dataSendProgress(channels[i].written, channels[i].bytesTotal);
+
+ if (channels[i].written == channels[i].bytesTotal) {
+ // make sure this function is called once again
+ channels[i].state = WaitingState;
+ sendRequest(socket);
+ break;
+ }
+ }
+ }
}
break;
}
+
case WaitingState:
+ {
+ QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice();
+ if (uploadByteDevice) {
+ QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead()));
+ }
+ // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called
+ // this is needed if the sends an reply before we have finished sending the request. In that
+ // case receiveReply had been called before but ignored the server reply
+ receiveReply(socket, channels[i].reply);
+ break;
+ }
case ReadingState:
case Wait4AuthState:
// ignore _q_bytesWritten in these states
@@ -416,7 +472,7 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket)
return true;
}
-bool QHttpNetworkConnectionPrivate::emitSignals(QHttpNetworkReply *reply)
+bool QHttpNetworkConnectionPrivate::shouldEmitSignals(QHttpNetworkReply *reply)
{
// for 401 & 407 don't emit the data signals. Content along with these
// responses are send only if the authentication fails.
@@ -432,7 +488,7 @@ bool QHttpNetworkConnectionPrivate::expectContent(QHttpNetworkReply *reply)
|| reply->d_func()->statusCode == 204 || reply->d_func()->statusCode == 304)
return false;
if (reply->d_func()->request.operation() == QHttpNetworkRequest::Head)
- return !emitSignals(reply);
+ return !shouldEmitSignals(reply);
if (reply->d_func()->contentLength() == 0)
return false;
return true;
@@ -476,11 +532,14 @@ bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetwork
if (inflated.size()) {
reply->d_func()->totalProgress += inflated.size();
appendData(*reply, inflated, false);
- if (emitSignals(reply)) {
+ if (shouldEmitSignals(reply)) {
emit reply->readyRead();
// make sure that the reply is valid
if (channels[i].reply != reply)
return true;
+ // emit dataReadProgress signal (signal is currently not connected
+ // to the rest of QNAM) since readProgress of the
+ // QNonContiguousByteDevice is used
emit reply->dataReadProgress(reply->d_func()->totalProgress, 0);
// make sure that the reply is valid
if (channels[i].reply != reply)
@@ -558,7 +617,7 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN
reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
break; // ignore
}
- if (emitSignals(reply))
+ if (shouldEmitSignals(reply))
emit reply->headerChanged();
if (!expectContent(reply)) {
reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
@@ -576,11 +635,14 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN
appendData(*reply, fragment.data(), reply->d_func()->autoDecompress);
if (!reply->d_func()->autoDecompress) {
reply->d_func()->totalProgress += fragment.size();
- if (emitSignals(reply)) {
+ if (shouldEmitSignals(reply)) {
emit reply->readyRead();
// make sure that the reply is valid
if (channels[i].reply != reply)
return;
+ // emit dataReadProgress signal (signal is currently not connected
+ // to the rest of QNAM) since readProgress of the
+ // QNonContiguousByteDevice is used
emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength);
// make sure that the reply is valid
if (channels[i].reply != reply)
@@ -615,7 +677,7 @@ void QHttpNetworkConnectionPrivate::allDone(QAbstractSocket *socket, QHttpNetwor
expand(socket, reply, true); // ### if expand returns false, its an error
#endif
// while handling 401 & 407, we might reset the status code, so save this.
- bool emitFinished = emitSignals(reply);
+ bool emitFinished = shouldEmitSignals(reply);
handleStatus(socket, reply);
// ### at this point there should be no more data on the socket
// close if server requested
@@ -647,8 +709,24 @@ void QHttpNetworkConnectionPrivate::handleStatus(QAbstractSocket *socket, QHttpN
case 407:
if (handleAuthenticateChallenge(socket, reply, (statusCode == 407), resend)) {
if (resend) {
+ int i = indexOf(socket);
+
+ QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice();
+ if (uploadByteDevice) {
+ if (uploadByteDevice->reset()) {
+ channels[i].written = 0;
+ } else {
+ emitReplyError(socket, reply, QNetworkReply::ContentReSendError);
+ break;
+ }
+ }
+
eraseData(reply);
- sendRequest(socket);
+
+ // also use async _q_startNextRequest so we dont break with closed
+ // proxy or server connections..
+ channels[i].resendCurrent = true;
+ QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
}
} else {
int i = indexOf(socket);
@@ -754,7 +832,7 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
if (priv->phase != QAuthenticatorPrivate::Done) {
// send any pending requests
copyCredentials(i, auth, isProxy);
- QMetaObject::invokeMethod(q, "_q_restartPendingRequest", Qt::QueuedConnection);
+ QMetaObject::invokeMethod(q, "_q_restartAuthPendingRequests", Qt::QueuedConnection);
}
}
// changing values in QAuthenticator will reset the 'phase'
@@ -833,7 +911,7 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
return reply;
}
-void QHttpNetworkConnectionPrivate::unqueueRequest(QAbstractSocket *socket)
+void QHttpNetworkConnectionPrivate::unqueueAndSendRequest(QAbstractSocket *socket)
{
Q_ASSERT(socket);
@@ -844,13 +922,12 @@ void QHttpNetworkConnectionPrivate::unqueueRequest(QAbstractSocket *socket)
HttpMessagePair &messagePair = highPriorityQueue[j];
if (!messagePair.second->d_func()->requestIsPrepared)
prepareRequest(messagePair);
- if (!messagePair.second->d_func()->requestIsBuffering) {
- channels[i].request = messagePair.first;
- channels[i].reply = messagePair.second;
- sendRequest(socket);
- highPriorityQueue.removeAt(j);
- return;
- }
+
+ channels[i].request = messagePair.first;
+ channels[i].reply = messagePair.second;
+ sendRequest(socket);
+ highPriorityQueue.removeAt(j);
+ return;
}
}
@@ -859,13 +936,11 @@ void QHttpNetworkConnectionPrivate::unqueueRequest(QAbstractSocket *socket)
HttpMessagePair &messagePair = lowPriorityQueue[j];
if (!messagePair.second->d_func()->requestIsPrepared)
prepareRequest(messagePair);
- if (!messagePair.second->d_func()->requestIsBuffering) {
- channels[i].request = messagePair.first;
- channels[i].reply = messagePair.second;
- sendRequest(socket);
- lowPriorityQueue.removeAt(j);
- return;
- }
+ channels[i].request = messagePair.first;
+ channels[i].reply = messagePair.second;
+ sendRequest(socket);
+ lowPriorityQueue.removeAt(j);
+ return;
}
}
}
@@ -992,6 +1067,7 @@ void QHttpNetworkConnectionPrivate::_q_bytesWritten(qint64 bytes)
QAbstractSocket *socket = qobject_cast<QAbstractSocket*>(q->sender());
if (!socket)
return; // ### error
+ // bytes have been written to the socket. write even more of them :)
if (isSocketWriting(socket))
sendRequest(socket);
// otherwise we do nothing
@@ -1018,29 +1094,30 @@ void QHttpNetworkConnectionPrivate::_q_disconnected()
void QHttpNetworkConnectionPrivate::_q_startNextRequest()
{
- // send the current request again
- if (channels[0].resendCurrent || channels[1].resendCurrent) {
- int i = channels[0].resendCurrent ? 0:1;
- QAbstractSocket *socket = channels[i].socket;
- channels[i].resendCurrent = false;
- channels[i].state = IdleState;
- if (channels[i].reply)
- sendRequest(socket);
- return;
+ //resend the necessary ones.
+ for (int i = 0; i < channelCount; ++i) {
+ if (channels[i].resendCurrent) {
+ channels[i].resendCurrent = false;
+ channels[i].state = IdleState;
+ if (channels[i].reply)
+ sendRequest(channels[i].socket);
+ }
}
- // send the request using the idle socket
- QAbstractSocket *socket = channels[0].socket;
- if (isSocketBusy(socket)) {
- socket = (isSocketBusy(channels[1].socket) ? 0 :channels[1].socket);
+ QAbstractSocket *socket = 0;
+ for (int i = 0; i < channelCount; ++i) {
+ QAbstractSocket *chSocket = channels[i].socket;
+ // send the request using the idle socket
+ if (!isSocketBusy(chSocket)) {
+ socket = chSocket;
+ break;
+ }
}
-
- if (!socket) {
+ if (!socket)
return; // this will be called after finishing current request.
- }
- unqueueRequest(socket);
+ unqueueAndSendRequest(socket);
}
-void QHttpNetworkConnectionPrivate::_q_restartPendingRequest()
+void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests()
{
// send the request using the idle socket
for (int i = 0 ; i < channelCount; ++i) {
@@ -1150,80 +1227,21 @@ void QHttpNetworkConnectionPrivate::_q_proxyAuthenticationRequired(const QNetwor
}
#endif
-void QHttpNetworkConnectionPrivate::_q_dataReadyReadNoBuffer()
+void QHttpNetworkConnectionPrivate::_q_uploadDataReadyRead()
{
Q_Q(QHttpNetworkConnection);
- // data emitted either readyRead()
+ // upload data emitted readyRead()
// find out which channel it is for
- QIODevice *sender = qobject_cast<QIODevice *>(q->sender());
+ QObject *sender = q->sender();
- // won't match anything if the qobject_cast above failed
for (int i = 0; i < channelCount; ++i) {
- if (sender == channels[i].request.data()) {
+ if (sender == channels[i].request.uploadByteDevice()) {
sendRequest(channels[i].socket);
break;
}
}
}
-void QHttpNetworkConnectionPrivate::_q_dataReadyReadBuffer()
-{
- Q_Q(QHttpNetworkConnection);
- QIODevice *sender = qobject_cast<QIODevice *>(q->sender());
- HttpMessagePair *thePair = 0;
- for (int i = 0; !thePair && i < lowPriorityQueue.size(); ++i)
- if (lowPriorityQueue.at(i).first.data() == sender)
- thePair = &lowPriorityQueue[i];
-
- for (int i = 0; !thePair && i < highPriorityQueue.size(); ++i)
- if (highPriorityQueue.at(i).first.data() == sender)
- thePair = &highPriorityQueue[i];
-
- if (thePair) {
- bufferData(*thePair);
-
- // are we finished buffering?
- if (!thePair->second->d_func()->requestIsBuffering)
- _q_startNextRequest();
- }
-}
-
-void QHttpNetworkConnectionPrivate::bufferData(HttpMessagePair &messagePair)
-{
- Q_Q(QHttpNetworkConnection);
- QHttpNetworkRequest &request = messagePair.first;
- QHttpNetworkReply *reply = messagePair.second;
- Q_ASSERT(request.data());
- if (!reply->d_func()->requestIsBuffering) { // first time
- QObject::connect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer()));
- QObject::connect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer()));
- reply->d_func()->requestIsBuffering = true;
- reply->d_func()->requestDataBuffer.open(QIODevice::ReadWrite);
- }
-
- // always try to read at least one byte
- // ### FIXME! use a QRingBuffer
- qint64 bytesToRead = qMax<qint64>(1, request.data()->bytesAvailable());
- QByteArray newData;
- newData.resize(bytesToRead);
- qint64 bytesActuallyRead = request.data()->read(newData.data(), bytesToRead);
-
- if (bytesActuallyRead > 0) {
- // we read something
- newData.chop(bytesToRead - bytesActuallyRead);
- reply->d_func()->requestDataBuffer.write(newData);
- } else if (bytesActuallyRead == -1) { // last time
- QObject::disconnect(request.data(), SIGNAL(readyRead()), q, SLOT(_q_dataReadyReadBuffer()));
- QObject::disconnect(request.data(), SIGNAL(readChannelFinished()), q, SLOT(_q_dataReadyReadBuffer()));
-
- request.setContentLength(reply->d_func()->requestDataBuffer.size());
- reply->d_func()->requestDataBuffer.seek(0);
- reply->d_func()->requestIsBuffering = false;
- }
-}
-
-// QHttpNetworkConnection
-
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent)
: QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent)
{
diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h
index 0f80bd9..37ce388 100644
--- a/src/network/access/qhttpnetworkconnection_p.h
+++ b/src/network/access/qhttpnetworkconnection_p.h
@@ -140,14 +140,13 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_readyRead())
Q_PRIVATE_SLOT(d_func(), void _q_disconnected())
Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
- Q_PRIVATE_SLOT(d_func(), void _q_restartPendingRequest())
+ Q_PRIVATE_SLOT(d_func(), void _q_restartAuthPendingRequests())
Q_PRIVATE_SLOT(d_func(), void _q_connected())
Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError))
#ifndef QT_NO_NETWORKPROXY
Q_PRIVATE_SLOT(d_func(), void _q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*))
#endif
- Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadBuffer())
- Q_PRIVATE_SLOT(d_func(), void _q_dataReadyReadNoBuffer())
+ Q_PRIVATE_SLOT(d_func(), void _q_uploadDataReadyRead())
#ifndef QT_NO_OPENSSL
Q_PRIVATE_SLOT(d_func(), void _q_encrypted())
@@ -190,7 +189,7 @@ public:
bool isSocketReading(QAbstractSocket *socket) const;
QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request);
- void unqueueRequest(QAbstractSocket *socket);
+ void unqueueAndSendRequest(QAbstractSocket *socket);
void prepareRequest(HttpMessagePair &request);
bool sendRequest(QAbstractSocket *socket);
void receiveReply(QAbstractSocket *socket, QHttpNetworkReply *reply);
@@ -203,14 +202,14 @@ public:
void _q_readyRead(); // pending data to read
void _q_disconnected(); // disconnected from host
void _q_startNextRequest(); // send the next request from the queue
- void _q_restartPendingRequest(); // send the currently blocked request
+ void _q_restartAuthPendingRequests(); // send the currently blocked request
void _q_connected(); // start sending request
void _q_error(QAbstractSocket::SocketError); // error from socket
#ifndef QT_NO_NETWORKPROXY
void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy
#endif
- void _q_dataReadyReadNoBuffer();
- void _q_dataReadyReadBuffer();
+
+ void _q_uploadDataReadyRead();
void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
bool ensureConnection(QAbstractSocket *socket);
@@ -219,7 +218,6 @@ public:
#ifndef QT_NO_COMPRESS
bool expand(QAbstractSocket *socket, QHttpNetworkReply *reply, bool dataComplete);
#endif
- void bufferData(HttpMessagePair &request);
void removeReply(QHttpNetworkReply *reply);
QString hostName;
@@ -252,7 +250,7 @@ public:
{}
};
static const int channelCount;
- Channel channels[2]; // maximum of 2 socket connections to the server
+ Channel *channels; // parallel connections to the server
bool pendingAuthSignal; // there is an incomplete authentication signal
bool pendingProxyAuthSignal; // there is an incomplete proxy authentication signal
@@ -263,7 +261,7 @@ public:
bool handleAuthenticateChallenge(QAbstractSocket *socket, QHttpNetworkReply *reply, bool isProxy, bool &resend);
void allDone(QAbstractSocket *socket, QHttpNetworkReply *reply);
void handleStatus(QAbstractSocket *socket, QHttpNetworkReply *reply);
- inline bool emitSignals(QHttpNetworkReply *reply);
+ inline bool shouldEmitSignals(QHttpNetworkReply *reply);
inline bool expectContent(QHttpNetworkReply *reply);
#ifndef QT_NO_OPENSSL
@@ -285,9 +283,6 @@ public:
QT_END_NAMESPACE
-//Q_DECLARE_METATYPE(QHttpNetworkRequest)
-//Q_DECLARE_METATYPE(QHttpNetworkReply)
-
#endif // QT_NO_HTTP
#endif
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 69e0a4c..88b1a44 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -187,7 +187,7 @@ QHttpNetworkReplyPrivate::QHttpNetworkReplyPrivate(const QUrl &newUrl)
: QHttpNetworkHeaderPrivate(newUrl), state(NothingDoneState), statusCode(100),
majorVersion(0), minorVersion(0), bodyLength(0), contentRead(0), totalProgress(0),
currentChunkSize(0), currentChunkRead(0), connection(0), initInflate(false),
- autoDecompress(false), requestIsBuffering(false), requestIsPrepared(false)
+ autoDecompress(false), requestIsPrepared(false)
{
}
@@ -544,13 +544,13 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou
{
qint64 bytes = 0;
if (isChunked()) {
- bytes += transferChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6)
+ bytes += readReplyBodyChunked(socket, out); // chunked transfer encoding (rfc 2616, sec 3.6)
} else if (bodyLength > 0) { // we have a Content-Length
- bytes += transferRaw(socket, out, bodyLength - contentRead);
+ bytes += readReplyBodyRaw(socket, out, bodyLength - contentRead);
if (contentRead + bytes == bodyLength)
state = AllDoneState;
} else {
- bytes += transferRaw(socket, out, socket->bytesAvailable());
+ bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable());
}
if (state == AllDoneState)
socket->readAll(); // Read the rest to clean (CRLF)
@@ -558,7 +558,7 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou
return bytes;
}
-qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint64 size)
+qint64 QHttpNetworkReplyPrivate::readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size)
{
qint64 bytes = 0;
Q_ASSERT(in);
@@ -584,7 +584,7 @@ qint64 QHttpNetworkReplyPrivate::transferRaw(QIODevice *in, QIODevice *out, qint
}
-qint64 QHttpNetworkReplyPrivate::transferChunked(QIODevice *in, QIODevice *out)
+qint64 QHttpNetworkReplyPrivate::readReplyBodyChunked(QIODevice *in, QIODevice *out)
{
qint64 bytes = 0;
while (in->bytesAvailable()) { // while we can read from input
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index cb4d34f..eff1da3 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -139,7 +139,7 @@ Q_SIGNALS:
void finishedWithError(QNetworkReply::NetworkError errorCode, const QString &detail = QString());
void headerChanged();
void dataReadProgress(int done, int total);
- void dataSendProgress(int done, int total);
+ void dataSendProgress(qint64 done, qint64 total);
private:
Q_DECLARE_PRIVATE(QHttpNetworkReply)
@@ -162,8 +162,8 @@ public:
QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const;
void clear();
- qint64 transferRaw(QIODevice *in, QIODevice *out, qint64 size);
- qint64 transferChunked(QIODevice *in, QIODevice *out);
+ qint64 readReplyBodyRaw(QIODevice *in, QIODevice *out, qint64 size);
+ qint64 readReplyBodyChunked(QIODevice *in, QIODevice *out);
qint64 getChunkSize(QIODevice *in, qint64 *chunkSize);
qint64 bytesAvailable() const;
@@ -206,8 +206,6 @@ public:
QByteArray responseData; // uncompressed body
QByteArray compressedData; // compressed body (temporary)
- QBuffer requestDataBuffer;
- bool requestIsBuffering;
bool requestIsPrepared;
};
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index 420cb69..b9b9d84 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -40,12 +40,13 @@
****************************************************************************/
#include "qhttpnetworkrequest_p.h"
+#include "private/qnoncontiguousbytedevice_p.h"
QT_BEGIN_NAMESPACE
QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
- : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), data(0),
+ : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
autoDecompress(false)
{
}
@@ -55,7 +56,7 @@ QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequest
{
operation = other.operation;
priority = other.priority;
- data = other.data;
+ uploadByteDevice = other.uploadByteDevice;
autoDecompress = other.autoDecompress;
}
@@ -67,7 +68,7 @@ bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &ot
{
return QHttpNetworkHeaderPrivate::operator==(other)
&& (operation == other.operation)
- && (data == other.data);
+ && (uploadByteDevice == other.uploadByteDevice);
}
QByteArray QHttpNetworkRequestPrivate::methodName() const
@@ -109,7 +110,7 @@ QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const
QUrl::FormattingOptions format(QUrl::RemoveFragment);
// for POST, query data is send as content
- if (operation == QHttpNetworkRequest::Post && !data)
+ if (operation == QHttpNetworkRequest::Post && !uploadByteDevice)
format |= QUrl::RemoveQuery;
// for requests through proxy, the Request-URI contains full url
if (throughProxy)
@@ -126,11 +127,11 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request
{
QByteArray ba = request.d->methodName();
QByteArray uri = request.d->uri(throughProxy);
- ba += " " + uri;
+ ba += ' ' + uri;
QString majorVersion = QString::number(request.majorVersion());
QString minorVersion = QString::number(request.minorVersion());
- ba += " HTTP/" + majorVersion.toLatin1() + "." + minorVersion.toLatin1() + "\r\n";
+ ba += " HTTP/" + majorVersion.toLatin1() + '.' + minorVersion.toLatin1() + "\r\n";
QList<QPair<QByteArray, QByteArray> > fields = request.header();
QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
@@ -140,7 +141,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request
// add content type, if not set in the request
if (request.headerField("content-type").isEmpty())
ba += "Content-Type: application/x-www-form-urlencoded\r\n";
- if (!request.d->data && request.d->url.hasQuery()) {
+ if (!request.d->uploadByteDevice && request.d->url.hasQuery()) {
QByteArray query = request.d->url.encodedQuery();
ba += "Content-Length: "+ QByteArray::number(query.size()) + "\r\n";
ba += "\r\n";
@@ -236,14 +237,14 @@ void QHttpNetworkRequest::setPriority(Priority priority)
d->priority = priority;
}
-QIODevice *QHttpNetworkRequest::data() const
+void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd)
{
- return d->data;
+ d->uploadByteDevice = bd;
}
-void QHttpNetworkRequest::setData(QIODevice *data)
+QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const
{
- d->data = data;
+ return d->uploadByteDevice;
}
int QHttpNetworkRequest::majorVersion() const
diff --git a/src/network/access/qhttpnetworkrequest_p.h b/src/network/access/qhttpnetworkrequest_p.h
index d18e116..ed4325a 100644
--- a/src/network/access/qhttpnetworkrequest_p.h
+++ b/src/network/access/qhttpnetworkrequest_p.h
@@ -58,6 +58,8 @@
QT_BEGIN_NAMESPACE
+class QNonContiguousByteDevice;
+
class QHttpNetworkRequestPrivate;
class Q_AUTOTEST_EXPORT QHttpNetworkRequest: public QHttpNetworkHeader
{
@@ -104,8 +106,8 @@ public:
Priority priority() const;
void setPriority(Priority priority);
- QIODevice *data() const;
- void setData(QIODevice *data);
+ void setUploadByteDevice(QNonContiguousByteDevice *bd);
+ QNonContiguousByteDevice* uploadByteDevice() const;
private:
QSharedDataPointer<QHttpNetworkRequestPrivate> d;
@@ -113,7 +115,6 @@ private:
friend class QHttpNetworkConnectionPrivate;
};
-
class QHttpNetworkRequestPrivate : public QHttpNetworkHeaderPrivate
{
public:
@@ -129,7 +130,7 @@ public:
QHttpNetworkRequest::Operation operation;
QHttpNetworkRequest::Priority priority;
- mutable QIODevice *data;
+ mutable QNonContiguousByteDevice* uploadByteDevice;
bool autoDecompress;
};
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index df468b8..b9d1b85 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -50,6 +50,8 @@
#include "qnetworkaccesscachebackend_p.h"
#include "qabstractnetworkcache.h"
+#include "private/qnoncontiguousbytedevice_p.h"
+
QT_BEGIN_NAMESPACE
static bool factoryDataShutdown = false;
@@ -109,17 +111,43 @@ QNetworkAccessBackend *QNetworkAccessManagerPrivate::findBackend(QNetworkAccessM
return 0;
}
-QNetworkAccessBackend::QNetworkAccessBackend()
+
+QNonContiguousByteDevice* QNetworkAccessBackend::createUploadByteDevice()
{
+ QNonContiguousByteDevice* device = 0;
+
+ if (reply->outgoingDataBuffer)
+ device = QNonContiguousByteDeviceFactory::create(reply->outgoingDataBuffer);
+ else
+ device = QNonContiguousByteDeviceFactory::create(reply->outgoingData);
+
+ bool bufferDisallowed =
+ reply->request.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute,
+ QVariant(false)) == QVariant(true);
+ if (bufferDisallowed)
+ device->disableReset();
+
+ // make sure we delete this later
+ device->setParent(this);
+
+ connect(device, SIGNAL(readProgress(qint64,qint64)), this, SLOT(emitReplyUploadProgress(qint64,qint64)));
+
+ return device;
}
-QNetworkAccessBackend::~QNetworkAccessBackend()
+// need to have this function since the reply is a private member variable
+// and the special backends need to access this.
+void QNetworkAccessBackend::emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
+ reply->emitUploadProgress(bytesSent, bytesTotal);
}
-void QNetworkAccessBackend::upstreamReadyRead()
+QNetworkAccessBackend::QNetworkAccessBackend()
+{
+}
+
+QNetworkAccessBackend::~QNetworkAccessBackend()
{
- // do nothing
}
void QNetworkAccessBackend::downstreamReadyWrite()
@@ -184,23 +212,6 @@ bool QNetworkAccessBackend::isCachingEnabled() const
return reply->isCachingEnabled();
}
-qint64 QNetworkAccessBackend::upstreamBytesAvailable() const
-{
- return reply->writeBuffer.size();
-}
-
-void QNetworkAccessBackend::upstreamBytesConsumed(qint64 count)
-{
- // remove count bytes from the write buffer
- reply->consume(count);
-}
-
-QByteArray QNetworkAccessBackend::readUpstream()
-{
- // ### this is expensive. Consider making QRingBuffer::peekAll keep the buffer it returns
- return reply->writeBuffer.peek(upstreamBytesAvailable());
-}
-
qint64 QNetworkAccessBackend::nextDownstreamBlockSize() const
{
return reply->nextDownstreamBlockSize();
@@ -213,12 +224,12 @@ qint64 QNetworkAccessBackend::downstreamBytesToConsume() const
void QNetworkAccessBackend::writeDownstreamData(const QByteArray &data)
{
- reply->feed(data);
+ reply->appendDownstreamData(data);
}
void QNetworkAccessBackend::writeDownstreamData(QIODevice *data)
{
- reply->feed(data);
+ reply->appendDownstreamData(data);
}
QVariant QNetworkAccessBackend::header(QNetworkRequest::KnownHeaders header) const
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 9012396..6035f3a 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -70,6 +70,8 @@ class QNetworkAccessManagerPrivate;
class QNetworkReplyImplPrivate;
class QAbstractNetworkCache;
class QNetworkCacheMetaData;
+class QNetworkAccessBackendUploadIODevice;
+class QNonContiguousByteDevice;
// Should support direct file upload from disk or download to disk.
//
@@ -86,14 +88,13 @@ public:
// have different names. The Connection has two streams:
//
// - Upstream:
- // Upstream is data that is being written into this connection,
- // from the user. Upstream operates in a "pull" mechanism: the
- // connection will be notified that there is more data available
- // by a call to "upstreamReadyRead". The number of bytes
- // available is given by upstreamBytesAvailable(). A call to
- // readUpstream() always yields the entire upstream buffer. When
- // the connection has processed a certain amount of bytes from
- // that buffer, it should call upstreamBytesConsumed().
+ // The upstream uses a QNonContiguousByteDevice provided
+ // by the backend. This device emits the usual readyRead()
+ // signal when the backend has data available for the connection
+ // to write. The different backends can listen on this signal
+ // and then pull upload data from the QNonContiguousByteDevice and
+ // deal with it.
+ //
//
// - Downstream:
// Downstream is the data that is being read from this
@@ -111,12 +112,9 @@ public:
virtual void open() = 0;
virtual void closeDownstreamChannel() = 0;
- virtual void closeUpstreamChannel() = 0;
virtual bool waitForDownstreamReadyRead(int msecs) = 0;
- virtual bool waitForUpstreamBytesWritten(int msecs) = 0;
// slot-like:
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
virtual void copyFinished(QIODevice *);
virtual void ignoreSslErrors();
@@ -155,18 +153,24 @@ public:
QVariant attribute(QNetworkRequest::Attribute code) const;
void setAttribute(QNetworkRequest::Attribute code, const QVariant &value);
+ // return true if the QNonContiguousByteDevice of the upload
+ // data needs to support reset(). Currently needed for HTTP.
+ // This will possibly enable buffering of the upload data.
+ virtual bool needsResetableUploadData() {return false;};
+
protected:
- // these functions control the upstream mechanism
- // that is, data coming into the backend and out via the connection
- qint64 upstreamBytesAvailable() const;
- void upstreamBytesConsumed(qint64 count);
- QByteArray readUpstream();
+ // Create the device used for reading the upload data
+ QNonContiguousByteDevice* createUploadByteDevice();
+
// these functions control the downstream mechanism
// that is, data that has come via the connection and is going out the backend
qint64 nextDownstreamBlockSize() const;
qint64 downstreamBytesToConsume() const;
void writeDownstreamData(const QByteArray &data);
+
+public slots:
+ // for task 251801, needs to be a slot to be called asynchronously
void writeDownstreamData(QIODevice *data);
protected slots:
@@ -179,10 +183,12 @@ protected slots:
void metaDataChanged();
void redirectionRequested(const QUrl &destination);
void sslErrors(const QList<QSslError> &errors);
+ void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal);
private:
friend class QNetworkAccessManager;
friend class QNetworkAccessManagerPrivate;
+ friend class QNetworkAccessBackendUploadIODevice;
QNetworkAccessManagerPrivate *manager;
QNetworkReplyImplPrivate *reply;
};
diff --git a/src/network/access/qnetworkaccessdebugpipebackend.cpp b/src/network/access/qnetworkaccessdebugpipebackend.cpp
index 2e5f1b1..d4bda9a 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend.cpp
+++ b/src/network/access/qnetworkaccessdebugpipebackend.cpp
@@ -41,6 +41,8 @@
#include "qnetworkaccessdebugpipebackend_p.h"
#include "QtCore/qdatastream.h"
+#include <QCoreApplication>
+#include "private/qnoncontiguousbytedevice_p.h"
QT_BEGIN_NAMESPACE
@@ -51,12 +53,6 @@ enum {
WriteBufferSize = ReadBufferSize
};
-struct QNetworkAccessDebugPipeBackend::DataPacket
-{
- QList<QPair<QByteArray, QByteArray> > headers;
- QByteArray data;
-};
-
QNetworkAccessBackend *
QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation op,
const QNetworkRequest &request) const
@@ -79,12 +75,14 @@ QNetworkAccessDebugPipeBackendFactory::create(QNetworkAccessManager::Operation o
}
QNetworkAccessDebugPipeBackend::QNetworkAccessDebugPipeBackend()
- : incomingPacketSize(0), bareProtocol(false)
+ : bareProtocol(false), hasUploadFinished(false), hasDownloadFinished(false),
+ hasEverythingFinished(false), bytesDownloaded(0), bytesUploaded(0)
{
}
QNetworkAccessDebugPipeBackend::~QNetworkAccessDebugPipeBackend()
{
+ // this is signals disconnect, not network!
socket.disconnect(this); // we're not interested in the signals at this point
}
@@ -92,160 +90,150 @@ void QNetworkAccessDebugPipeBackend::open()
{
socket.connectToHost(url().host(), url().port(12345));
socket.setReadBufferSize(ReadBufferSize);
+
+ // socket ready read -> we can push from socket to downstream
connect(&socket, SIGNAL(readyRead()), SLOT(socketReadyRead()));
- connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), SLOT(socketError()));
connect(&socket, SIGNAL(disconnected()), SLOT(socketDisconnected()));
+ connect(&socket, SIGNAL(connected()), SLOT(socketConnected()));
+ // socket bytes written -> we can push more from upstream to socket
+ connect(&socket, SIGNAL(bytesWritten(qint64)), SLOT(socketBytesWritten(qint64)));
bareProtocol = url().queryItemValue(QLatin1String("bare")) == QLatin1String("1");
- if (!bareProtocol) {
- // "Handshake":
- // send outgoing metadata and the URL being requested
- DataPacket packet;
- //packet.metaData = request().metaData();
- packet.data = url().toEncoded();
- send(packet);
+ if (operation() == QNetworkAccessManager::PutOperation) {
+ uploadByteDevice = createUploadByteDevice();
+ QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
+ QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
}
}
-void QNetworkAccessDebugPipeBackend::closeDownstreamChannel()
+void QNetworkAccessDebugPipeBackend::socketReadyRead()
{
- if (operation() == QNetworkAccessManager::GetOperation)
- socket.disconnectFromHost();
+ pushFromSocketToDownstream();
}
-void QNetworkAccessDebugPipeBackend::closeUpstreamChannel()
+void QNetworkAccessDebugPipeBackend::downstreamReadyWrite()
{
- if (operation() == QNetworkAccessManager::PutOperation)
- socket.disconnectFromHost();
- else if (operation() == QNetworkAccessManager::PostOperation) {
- send(DataPacket());
- }
+ pushFromSocketToDownstream();
}
-bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
+void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
{
- readyReadEmitted = false;
- if (socket.bytesAvailable()) {
- socketReadyRead();
- if (readyReadEmitted)
- return true;
- }
- socket.waitForReadyRead(ms);
- return readyReadEmitted;
+ pushFromUpstreamToSocket();
}
-bool QNetworkAccessDebugPipeBackend::waitForUpstreamBytesWritten(int ms)
+void QNetworkAccessDebugPipeBackend::uploadReadyReadSlot()
{
- bytesWrittenEmitted = false;
- upstreamReadyRead();
- if (bytesWrittenEmitted)
- return true;
-
- socket.waitForBytesWritten(ms);
- return bytesWrittenEmitted;
+ pushFromUpstreamToSocket();
}
-void QNetworkAccessDebugPipeBackend::upstreamReadyRead()
+void QNetworkAccessDebugPipeBackend::pushFromSocketToDownstream()
{
- int maxWrite = WriteBufferSize - socket.bytesToWrite();
- if (maxWrite <= 0)
- return; // can't write yet, wait for the socket to write
-
- if (bareProtocol) {
- QByteArray data = readUpstream();
- if (data.isEmpty())
- return;
+ QByteArray buffer;
- socket.write(data);
- upstreamBytesConsumed(data.size());
- bytesWrittenEmitted = true;
+ if (socket.state() == QAbstractSocket::ConnectingState) {
return;
}
- DataPacket packet;
- packet.data = readUpstream();
- if (packet.data.isEmpty())
- return; // we'll be called again when there's data
- if (packet.data.size() > maxWrite)
- packet.data.truncate(maxWrite);
-
- if (!send(packet)) {
- QString msg = QObject::tr("Write error writing to %1: %2")
- .arg(url().toString(), socket.errorString());
- error(QNetworkReply::ProtocolFailure, msg);
+ forever {
+ if (hasDownloadFinished)
+ return;
- finished();
- return;
+ buffer.resize(ReadBufferSize);
+ qint64 haveRead = socket.read(buffer.data(), ReadBufferSize);
+
+ if (haveRead == -1) {
+ hasDownloadFinished = true;
+ // this ensures a good last downloadProgress is emitted
+ setHeader(QNetworkRequest::ContentLengthHeader, QVariant());
+ possiblyFinish();
+ break;
+ } else if (haveRead == 0) {
+ break;
+ } else {
+ // have read something
+ buffer.resize(haveRead);
+ bytesDownloaded += haveRead;
+ writeDownstreamData(buffer);
+ }
}
- upstreamBytesConsumed(packet.data.size());
- bytesWrittenEmitted = true;
}
-void QNetworkAccessDebugPipeBackend::downstreamReadyWrite()
+void QNetworkAccessDebugPipeBackend::pushFromUpstreamToSocket()
{
- socketReadyRead();
-}
+ // FIXME
+ if (operation() == QNetworkAccessManager::PutOperation) {
+ if (hasUploadFinished)
+ return;
-void QNetworkAccessDebugPipeBackend::socketReadyRead()
-{
- if (bareProtocol) {
- qint64 bytesToRead = socket.bytesAvailable();
- if (bytesToRead) {
- QByteArray buffer;
- buffer.resize(bytesToRead);
- qint64 bytesRead = socket.read(buffer.data(), bytesToRead);
- if (bytesRead < bytesToRead)
- buffer.truncate(bytesRead);
- writeDownstreamData(buffer);
- readyReadEmitted = true;
+ forever {
+ if (socket.bytesToWrite() >= WriteBufferSize)
+ return;
+
+ qint64 haveRead;
+ const char *readPointer = uploadByteDevice->readPointer(WriteBufferSize, haveRead);
+ if (haveRead == -1) {
+ // EOF
+ hasUploadFinished = true;
+ emitReplyUploadProgress(bytesUploaded, bytesUploaded);
+ possiblyFinish();
+ break;
+ } else if (haveRead == 0 || readPointer == 0) {
+ // nothing to read right now, we will be called again later
+ break;
+ } else {
+ qint64 haveWritten;
+ haveWritten = socket.write(readPointer, haveRead);
+
+ if (haveWritten < 0) {
+ // write error!
+ QString msg = QCoreApplication::translate("QNetworkAccessDebugPipeBackend", "Write error writing to %1: %2")
+ .arg(url().toString(), socket.errorString());
+ error(QNetworkReply::ProtocolFailure, msg);
+ finished();
+ return;
+ } else {
+ uploadByteDevice->advanceReadPointer(haveWritten);
+ bytesUploaded += haveWritten;
+ emitReplyUploadProgress(bytesUploaded, -1);
+ }
+
+ //QCoreApplication::processEvents();
+
+ }
}
- return;
}
+}
- while (canReceive() &&
- (socket.state() == QAbstractSocket::UnconnectedState || nextDownstreamBlockSize())) {
- DataPacket packet;
- if (receive(packet)) {
- if (!packet.headers.isEmpty()) {
- QList<QPair<QByteArray, QByteArray> >::ConstIterator
- it = packet.headers.constBegin(),
- end = packet.headers.constEnd();
- for ( ; it != end; ++it)
- setRawHeader(it->first, it->second);
- metaDataChanged();
- }
+void QNetworkAccessDebugPipeBackend::possiblyFinish()
+{
+ if (hasEverythingFinished)
+ return;
+ hasEverythingFinished = true;
- if (!packet.data.isEmpty()) {
- writeDownstreamData(packet.data);
- readyReadEmitted = true;
- }
+ if ((operation() == QNetworkAccessManager::GetOperation) && hasDownloadFinished) {
+ socket.close();
+ finished();
+ } else if ((operation() == QNetworkAccessManager::PutOperation) && hasUploadFinished) {
+ socket.close();
+ finished();
+ }
- if (packet.headers.isEmpty() && packet.data.isEmpty()) {
- // it's an eof
- socket.close();
- readyReadEmitted = true;
- }
- } else {
- // got an error
- QString msg = QObject::tr("Read error reading from %1: %2")
- .arg(url().toString(), socket.errorString());
- error(QNetworkReply::ProtocolFailure, msg);
- finished();
- return;
- }
- }
}
-void QNetworkAccessDebugPipeBackend::socketBytesWritten(qint64)
+void QNetworkAccessDebugPipeBackend::closeDownstreamChannel()
{
- upstreamReadyRead();
+ qWarning() << "QNetworkAccessDebugPipeBackend::closeDownstreamChannel()" << operation();
+ //if (operation() == QNetworkAccessManager::GetOperation)
+ // socket.disconnectFromHost();
}
+
void QNetworkAccessDebugPipeBackend::socketError()
{
+ qWarning() << "QNetworkAccessDebugPipeBackend::socketError()" << socket.error();
QNetworkReply::NetworkError code;
switch (socket.error()) {
case QAbstractSocket::RemoteHostClosedError:
@@ -269,76 +257,27 @@ void QNetworkAccessDebugPipeBackend::socketError()
void QNetworkAccessDebugPipeBackend::socketDisconnected()
{
- socketReadyRead();
- if (incomingPacketSize == 0 && socket.bytesToWrite() == 0) {
+ pushFromSocketToDownstream();
+
+ if (socket.bytesToWrite() == 0) {
// normal close
- finished();
} else {
// abnormal close
QString msg = QObject::tr("Remote host closed the connection prematurely on %1")
.arg(url().toString());
error(QNetworkReply::RemoteHostClosedError, msg);
-
finished();
}
}
-bool QNetworkAccessDebugPipeBackend::send(const DataPacket &packet)
-{
- QByteArray ba;
- {
- QDataStream stream(&ba, QIODevice::WriteOnly);
- stream.setVersion(QDataStream::Qt_4_4);
-
- stream << packet.headers << packet.data;
- }
-
- qint32 outgoingPacketSize = ba.size();
- qint64 written = socket.write((const char*)&outgoingPacketSize, sizeof outgoingPacketSize);
- written += socket.write(ba);
- return quint64(written) == (outgoingPacketSize + sizeof outgoingPacketSize);
-}
-
-bool QNetworkAccessDebugPipeBackend::receive(DataPacket &packet)
+void QNetworkAccessDebugPipeBackend::socketConnected()
{
- if (!canReceive())
- return false;
-
- // canReceive() does the setting up for us
- Q_ASSERT(socket.bytesAvailable() >= incomingPacketSize);
- QByteArray incomingPacket = socket.read(incomingPacketSize);
- QDataStream stream(&incomingPacket, QIODevice::ReadOnly);
- stream.setVersion(QDataStream::Qt_4_4);
- stream >> packet.headers >> packet.data;
-
- // reset for next packet:
- incomingPacketSize = 0;
- socket.setReadBufferSize(ReadBufferSize);
- return true;
}
-bool QNetworkAccessDebugPipeBackend::canReceive()
+bool QNetworkAccessDebugPipeBackend::waitForDownstreamReadyRead(int ms)
{
- if (incomingPacketSize == 0) {
- // read the packet size
- if (quint64(socket.bytesAvailable()) >= sizeof incomingPacketSize)
- socket.read((char*)&incomingPacketSize, sizeof incomingPacketSize);
- else
- return false;
- }
-
- if (incomingPacketSize == 0) {
- QString msg = QObject::tr("Protocol error: packet of size 0 received");
- error(QNetworkReply::ProtocolFailure, msg);
- finished();
-
- socket.blockSignals(true);
- socket.abort();
- socket.blockSignals(false);
- return false;
- }
-
- return socket.bytesAvailable() >= incomingPacketSize;
+ qCritical("QNetworkAccess: Debug pipe backend does not support waitForReadyRead()");
+ return false;
}
#endif
diff --git a/src/network/access/qnetworkaccessdebugpipebackend_p.h b/src/network/access/qnetworkaccessdebugpipebackend_p.h
index 73a35cf..a13edc4 100644
--- a/src/network/access/qnetworkaccessdebugpipebackend_p.h
+++ b/src/network/access/qnetworkaccessdebugpipebackend_p.h
@@ -66,35 +66,38 @@ class QNetworkAccessDebugPipeBackend: public QNetworkAccessBackend
{
Q_OBJECT
public:
- struct DataPacket;
QNetworkAccessDebugPipeBackend();
virtual ~QNetworkAccessDebugPipeBackend();
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
+protected:
+ void pushFromSocketToDownstream();
+ void pushFromUpstreamToSocket();
+ void possiblyFinish();
+ QNonContiguousByteDevice *uploadByteDevice;
+
private slots:
+ void uploadReadyReadSlot();
void socketReadyRead();
void socketBytesWritten(qint64 bytes);
void socketError();
void socketDisconnected();
+ void socketConnected();
private:
QTcpSocket socket;
- qint32 incomingPacketSize;
- bool readyReadEmitted;
- bool bytesWrittenEmitted;
bool bareProtocol;
+ bool hasUploadFinished;
+ bool hasDownloadFinished;
+ bool hasEverythingFinished;
- bool send(const DataPacket &packet);
- bool canReceive();
- bool receive(DataPacket &packet);
+ qint64 bytesDownloaded;
+ qint64 bytesUploaded;
};
class QNetworkAccessDebugPipeBackendFactory: public QNetworkAccessBackendFactory
diff --git a/src/network/access/qnetworkaccessfilebackend.cpp b/src/network/access/qnetworkaccessfilebackend.cpp
index 8a5a665..d905b70 100644
--- a/src/network/access/qnetworkaccessfilebackend.cpp
+++ b/src/network/access/qnetworkaccessfilebackend.cpp
@@ -43,6 +43,7 @@
#include "qfileinfo.h"
#include "qurlinfo.h"
#include "qdir.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#include <QtCore/QCoreApplication>
@@ -77,7 +78,7 @@ QNetworkAccessFileBackendFactory::create(QNetworkAccessManager::Operation op,
}
QNetworkAccessFileBackend::QNetworkAccessFileBackend()
- : totalBytes(0)
+ : uploadByteDevice(0), totalBytes(0), hasUploadFinished(false)
{
}
@@ -108,7 +109,7 @@ void QNetworkAccessFileBackend::open()
QString fileName = url.toLocalFile();
if (fileName.isEmpty()) {
if (url.scheme() == QLatin1String("qrc"))
- fileName = QLatin1String(":") + url.path();
+ fileName = QLatin1Char(':') + url.path();
else
fileName = url.toString(QUrl::RemoveAuthority | QUrl::RemoveFragment | QUrl::RemoveQuery);
}
@@ -126,6 +127,9 @@ void QNetworkAccessFileBackend::open()
break;
case QNetworkAccessManager::PutOperation:
mode = QIODevice::WriteOnly | QIODevice::Truncate;
+ uploadByteDevice = createUploadByteDevice();
+ QObject::connect(uploadByteDevice, SIGNAL(readyRead()), this, SLOT(uploadReadyReadSlot()));
+ QMetaObject::invokeMethod(this, "uploadReadyReadSlot", Qt::QueuedConnection);
break;
default:
Q_ASSERT_X(false, "QNetworkAccessFileBackend::open",
@@ -152,19 +156,50 @@ void QNetworkAccessFileBackend::open()
}
}
-void QNetworkAccessFileBackend::closeDownstreamChannel()
+void QNetworkAccessFileBackend::uploadReadyReadSlot()
{
- if (operation() == QNetworkAccessManager::GetOperation) {
- file.close();
- //downstreamChannelClosed();
+ if (hasUploadFinished)
+ return;
+
+ forever {
+ qint64 haveRead;
+ const char *readPointer = uploadByteDevice->readPointer(-1, haveRead);
+ if (haveRead == -1) {
+ // EOF
+ hasUploadFinished = true;
+ file.flush();
+ file.close();
+ finished();
+ break;
+ } else if (haveRead == 0 || readPointer == 0) {
+ // nothing to read right now, we will be called again later
+ break;
+ } else {
+ qint64 haveWritten;
+ haveWritten = file.write(readPointer, haveRead);
+
+ if (haveWritten < 0) {
+ // write error!
+ QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
+ .arg(url().toString(), file.errorString());
+ error(QNetworkReply::ProtocolFailure, msg);
+
+ finished();
+ return;
+ } else {
+ uploadByteDevice->advanceReadPointer(haveWritten);
+ }
+
+
+ file.flush();
+ }
}
}
-void QNetworkAccessFileBackend::closeUpstreamChannel()
+void QNetworkAccessFileBackend::closeDownstreamChannel()
{
- if (operation() == QNetworkAccessManager::PutOperation) {
+ if (operation() == QNetworkAccessManager::GetOperation) {
file.close();
- finished();
}
}
@@ -174,40 +209,6 @@ bool QNetworkAccessFileBackend::waitForDownstreamReadyRead(int)
return readMoreFromFile();
}
-bool QNetworkAccessFileBackend::waitForUpstreamBytesWritten(int)
-{
- Q_ASSERT_X(false, "QNetworkAccessFileBackend::waitForUpstreamBytesWritten",
- "This function should never have been called, since there is never anything "
- "left to be written!");
- return false;
-}
-
-void QNetworkAccessFileBackend::upstreamReadyRead()
-{
- Q_ASSERT_X(operation() == QNetworkAccessManager::PutOperation, "QNetworkAccessFileBackend",
- "We're being told to upload data but operation isn't PUT!");
-
- // there's more data to be written to the file
- while (upstreamBytesAvailable()) {
- // write everything and let QFile handle it
- int written = file.write(readUpstream());
-
- if (written < 0) {
- // write error!
- QString msg = QCoreApplication::translate("QNetworkAccessFileBackend", "Write error writing to %1: %2")
- .arg(url().toString(), file.errorString());
- error(QNetworkReply::ProtocolFailure, msg);
-
- finished();
- return;
- }
-
- // successful write
- file.flush();
- upstreamBytesConsumed(written);
- }
-}
-
void QNetworkAccessFileBackend::downstreamReadyWrite()
{
Q_ASSERT_X(operation() == QNetworkAccessManager::GetOperation, "QNetworkAccessFileBackend",
diff --git a/src/network/access/qnetworkaccessfilebackend_p.h b/src/network/access/qnetworkaccessfilebackend_p.h
index ce7d351..4615c5f 100644
--- a/src/network/access/qnetworkaccessfilebackend_p.h
+++ b/src/network/access/qnetworkaccessfilebackend_p.h
@@ -62,22 +62,25 @@ QT_BEGIN_NAMESPACE
class QNetworkAccessFileBackend: public QNetworkAccessBackend
{
+ Q_OBJECT
public:
QNetworkAccessFileBackend();
virtual ~QNetworkAccessFileBackend();
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
+public slots:
+ void uploadReadyReadSlot();
+protected:
+ QNonContiguousByteDevice *uploadByteDevice;
private:
QFile file;
qint64 totalBytes;
+ bool hasUploadFinished;
bool loadFileInfo();
bool readMoreFromFile();
diff --git a/src/network/access/qnetworkaccessftpbackend.cpp b/src/network/access/qnetworkaccessftpbackend.cpp
index ea39dec..ad55b85 100644
--- a/src/network/access/qnetworkaccessftpbackend.cpp
+++ b/src/network/access/qnetworkaccessftpbackend.cpp
@@ -42,6 +42,7 @@
#include "qnetworkaccessftpbackend_p.h"
#include "qnetworkaccessmanager_p.h"
#include "QtNetwork/qauthenticator.h"
+#include "private/qnoncontiguousbytedevice_p.h"
#ifndef QT_NO_FTP
@@ -81,41 +82,6 @@ QNetworkAccessFtpBackendFactory::create(QNetworkAccessManager::Operation op,
return 0;
}
-class QNetworkAccessFtpIODevice: public QIODevice
-{
- //Q_OBJECT
-public:
- QNetworkAccessFtpBackend *backend;
- bool eof;
-
- inline QNetworkAccessFtpIODevice(QNetworkAccessFtpBackend *parent)
- : QIODevice(parent), backend(parent), eof(false)
- { open(ReadOnly); }
-
- bool isSequential() const { return true; }
- bool atEnd() const { return backend->upstreamBytesAvailable() == 0; }
-
- qint64 bytesAvailable() const { return backend->upstreamBytesAvailable(); }
- qint64 bytesToWrite() const { return backend->downstreamBytesToConsume(); }
-protected:
- qint64 readData(char *data, qint64 maxlen)
- {
- const QByteArray toSend = backend->readUpstream();
- maxlen = qMin<qint64>(maxlen, toSend.size());
- if (!maxlen)
- return eof ? -1 : 0;
-
- backend->upstreamBytesConsumed(maxlen);
- memcpy(data, toSend.constData(), maxlen);
- return maxlen;
- }
-
- qint64 writeData(const char *, qint64)
- { return -1; }
-
- friend class QNetworkAccessFtpBackend;
-};
-
class QNetworkAccessFtpFtp: public QFtp, public QNetworkAccessCache::CacheableObject
{
// Q_OBJECT
@@ -198,7 +164,11 @@ void QNetworkAccessFtpBackend::open()
ftpConnectionReady(ftp);
}
- uploadDevice = new QNetworkAccessFtpIODevice(this);
+ // Put operation
+ if (operation() == QNetworkAccessManager::PutOperation) {
+ uploadDevice = QNonContiguousByteDeviceFactory::wrap(createUploadByteDevice());
+ uploadDevice->setParent(this);
+ }
}
void QNetworkAccessFtpBackend::closeDownstreamChannel()
@@ -212,16 +182,6 @@ void QNetworkAccessFtpBackend::closeDownstreamChannel()
#endif
}
-void QNetworkAccessFtpBackend::closeUpstreamChannel()
-{
- if (operation() == QNetworkAccessManager::PutOperation) {
- Q_ASSERT(uploadDevice);
- uploadDevice->eof = true;
- if (!upstreamBytesAvailable())
- emit uploadDevice->readyRead();
- }
-}
-
bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms)
{
if (!ftp)
@@ -239,18 +199,6 @@ bool QNetworkAccessFtpBackend::waitForDownstreamReadyRead(int ms)
return false;
}
-bool QNetworkAccessFtpBackend::waitForUpstreamBytesWritten(int ms)
-{
- Q_UNUSED(ms);
- qCritical("QNetworkAccess: FTP backend does not support waitForBytesWritten()");
- return false;
-}
-
-void QNetworkAccessFtpBackend::upstreamReadyRead()
-{
- // uh... how does QFtp operate?
-}
-
void QNetworkAccessFtpBackend::downstreamReadyWrite()
{
if (state == Transferring && ftp && ftp->bytesAvailable())
diff --git a/src/network/access/qnetworkaccessftpbackend_p.h b/src/network/access/qnetworkaccessftpbackend_p.h
index 9ec2dd8..1bb7ff2 100644
--- a/src/network/access/qnetworkaccessftpbackend_p.h
+++ b/src/network/access/qnetworkaccessftpbackend_p.h
@@ -87,11 +87,8 @@ public:
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
void disconnectFromFtp();
@@ -105,7 +102,7 @@ public slots:
private:
friend class QNetworkAccessFtpIODevice;
QPointer<QNetworkAccessFtpFtp> ftp;
- QNetworkAccessFtpIODevice *uploadDevice;
+ QIODevice *uploadDevice;
qint64 totalBytes;
int helpId, sizeId, mdtmId;
bool supportsSize, supportsMdtm;
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 4874d9d..8d02fcb 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -212,6 +212,7 @@ QNetworkAccessHttpBackendFactory::create(QNetworkAccessManager::Operation op,
case QNetworkAccessManager::PostOperation:
case QNetworkAccessManager::HeadOperation:
case QNetworkAccessManager::PutOperation:
+ case QNetworkAccessManager::DeleteOperation:
break;
default:
@@ -244,6 +245,10 @@ static QNetworkReply::NetworkError statusCodeFromHttp(int httpStatusCode, const
code = QNetworkReply::ContentNotFoundError;
break;
+ case 405: // Method Not Allowed
+ code = QNetworkReply::ContentOperationNotPermittedError;
+ break;
+
case 407:
code = QNetworkReply::ProxyAuthenticationRequiredError;
break;
@@ -286,37 +291,6 @@ public:
}
};
-class QNetworkAccessHttpBackendIODevice: public QIODevice
-{
- // Q_OBJECT
-public:
- bool eof;
- QNetworkAccessHttpBackendIODevice(QNetworkAccessHttpBackend *parent)
- : QIODevice(parent), eof(false)
- {
- setOpenMode(ReadOnly);
- }
- bool isSequential() const { return true; }
- qint64 bytesAvailable() const
- { return static_cast<QNetworkAccessHttpBackend *>(parent())->upstreamBytesAvailable(); }
-
-protected:
- virtual qint64 readData(char *buffer, qint64 maxlen)
- {
- qint64 ret = static_cast<QNetworkAccessHttpBackend *>(parent())->deviceReadData(buffer, maxlen);
- if (!ret && eof)
- return -1;
- return ret;
- }
-
- virtual qint64 writeData(const char *, qint64)
- {
- return -1; // cannot write
- }
-
- friend class QNetworkAccessHttpBackend;
-};
-
QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
: QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0)
#ifndef QT_NO_OPENSSL
@@ -507,20 +481,24 @@ void QNetworkAccessHttpBackend::postRequest()
case QNetworkAccessManager::PostOperation:
invalidateCache();
httpRequest.setOperation(QHttpNetworkRequest::Post);
- uploadDevice = new QNetworkAccessHttpBackendIODevice(this);
+ httpRequest.setUploadByteDevice(createUploadByteDevice());
break;
case QNetworkAccessManager::PutOperation:
invalidateCache();
httpRequest.setOperation(QHttpNetworkRequest::Put);
- uploadDevice = new QNetworkAccessHttpBackendIODevice(this);
+ httpRequest.setUploadByteDevice(createUploadByteDevice());
+ break;
+
+ case QNetworkAccessManager::DeleteOperation:
+ invalidateCache();
+ httpRequest.setOperation(QHttpNetworkRequest::Delete);
break;
default:
break; // can't happen
}
- httpRequest.setData(uploadDevice);
httpRequest.setUrl(url());
QList<QByteArray> headers = request().rawHeaderList();
@@ -528,7 +506,9 @@ void QNetworkAccessHttpBackend::postRequest()
httpRequest.setHeaderField(header, request().rawHeader(header));
if (loadedFromCache) {
- QNetworkAccessBackend::finished();
+ // commented this out since it will be called later anyway
+ // by copyFinished()
+ //QNetworkAccessBackend::finished();
return; // no need to send the request! :)
}
@@ -625,14 +605,6 @@ void QNetworkAccessHttpBackend::closeDownstreamChannel()
// this indicates that the user closed the stream while the reply isn't finished yet
}
-void QNetworkAccessHttpBackend::closeUpstreamChannel()
-{
- // this indicates that the user finished uploading the data for POST
- Q_ASSERT(uploadDevice);
- uploadDevice->eof = true;
- emit uploadDevice->readChannelFinished();
-}
-
bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs)
{
Q_ASSERT(http);
@@ -652,38 +624,6 @@ bool QNetworkAccessHttpBackend::waitForDownstreamReadyRead(int msecs)
return false;
}
-bool QNetworkAccessHttpBackend::waitForUpstreamBytesWritten(int msecs)
-{
-
- // ### FIXME: not implemented in QHttpNetworkAccess
- Q_UNUSED(msecs);
- qCritical("QNetworkAccess: HTTP backend does not support waitForBytesWritten()");
- return false;
-}
-
-void QNetworkAccessHttpBackend::upstreamReadyRead()
-{
- // There is more data available from the user to be uploaded
- // QHttpNetworkAccess implements the upload rate control:
- // we simply tell QHttpNetworkAccess that there is more data available
- // it'll pull from us when it can (through uploadDevice)
-
- Q_ASSERT(uploadDevice);
- emit uploadDevice->readyRead();
-}
-
-qint64 QNetworkAccessHttpBackend::deviceReadData(char *buffer, qint64 maxlen)
-{
- QByteArray toBeUploaded = readUpstream();
- if (toBeUploaded.isEmpty())
- return 0; // nothing to be uploaded
-
- maxlen = qMin<qint64>(maxlen, toBeUploaded.length());
-
- memcpy(buffer, toBeUploaded.constData(), maxlen);
- upstreamBytesConsumed(maxlen);
- return maxlen;
-}
void QNetworkAccessHttpBackend::downstreamReadyWrite()
{
@@ -910,7 +850,14 @@ bool QNetworkAccessHttpBackend::sendCacheContents(const QNetworkCacheMetaData &m
checkForRedirect(status);
- writeDownstreamData(contents);
+ emit metaDataChanged();
+
+ // invoke this asynchronously, else Arora/QtDemoBrowser don't like cached downloads
+ // see task 250221 / 251801
+ qRegisterMetaType<QIODevice*>("QIODevice*");
+ QMetaObject::invokeMethod(this, "writeDownstreamData", Qt::QueuedConnection, Q_ARG(QIODevice*, contents));
+
+
#if defined(QNETWORKACCESSHTTPBACKEND_DEBUG)
qDebug() << "Successfully sent cache:" << url() << contents->size() << "bytes";
#endif
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index 02915e7..225f944 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -79,11 +79,8 @@ public:
virtual void open();
virtual void closeDownstreamChannel();
- virtual void closeUpstreamChannel();
virtual bool waitForDownstreamReadyRead(int msecs);
- virtual bool waitForUpstreamBytesWritten(int msecs);
- virtual void upstreamReadyRead();
virtual void downstreamReadyWrite();
virtual void copyFinished(QIODevice *);
#ifndef QT_NO_OPENSSL
@@ -96,6 +93,9 @@ public:
qint64 deviceReadData(char *buffer, qint64 maxlen);
+ // we return true since HTTP needs to send PUT/POST data again after having authenticated
+ bool needsResetableUploadData() {return true;};
+
private slots:
void replyReadyRead();
void replyFinished();
@@ -108,7 +108,8 @@ private:
QHttpNetworkReply *httpReply;
QPointer<QNetworkAccessHttpBackendCache> http;
QByteArray cacheKey;
- QNetworkAccessHttpBackendIODevice *uploadDevice;
+ QNetworkAccessBackendUploadIODevice *uploadDevice;
+
#ifndef QT_NO_OPENSSL
QSslConfiguration *pendingSslConfiguration;
bool pendingIgnoreSslErrors;
@@ -122,8 +123,6 @@ private:
void postRequest();
void readFromHttp();
void checkForRedirect(const int statusCode);
-
- friend class QNetworkAccessHttpBackendIODevice;
};
class QNetworkAccessHttpBackendFactory : public QNetworkAccessBackendFactory
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 38e8af9..c3241d0 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -148,6 +148,9 @@ static void ensureInitialized()
\value PostOperation send the contents of an HTML form for
processing via HTTP POST (created with post())
+ \value DeleteOperation delete contents operation (created with
+ deleteResource())
+
\omitvalue UnknownOperation
\sa QNetworkReply::operation()
@@ -555,7 +558,7 @@ QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
a new QNetworkReply object opened for reading which emits its
QIODevice::readyRead() signal whenever new data arrives.
- \sa post(), put()
+ \sa post(), put(), deleteResource()
*/
QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
{
@@ -577,7 +580,7 @@ QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
Note: sending a POST request on protocols other than HTTP and
HTTPS is undefined and will probably fail.
- \sa get(), put()
+ \sa get(), put(), deleteResource()
*/
QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
{
@@ -642,6 +645,20 @@ QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const
}
/*!
+ \since 4.6
+
+ This function is used to send a request to delete the resource
+ identified by the URL of \a request.
+ This feature is currently available for HTTP only, performing an HTTP DELETE request.
+
+ \sa get(), post(), put()
+*/
+QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
+{
+ return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
+}
+
+/*!
Returns a new QNetworkReply object to handle the operation \a op
and request \a req. The device \a outgoingData is always 0 for Get and
Head requests, but is the value passed to post() and put() in
@@ -686,7 +703,10 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
priv->urlForLastAuthentication = url;
}
- // third step: setup the reply
+ // third step: find a backend
+ priv->backend = d->findBackend(op, request);
+
+ // fourth step: setup the reply
priv->setup(op, request, outgoingData);
if (request.attribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferNetwork).toInt() !=
QNetworkRequest::AlwaysNetwork)
@@ -695,9 +715,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
priv->proxyList = proxyList;
#endif
-
- // fourth step: find a backend
- priv->backend = d->findBackend(op, request);
if (priv->backend) {
priv->backend->setParent(reply);
priv->backend->reply = priv;
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 4fe218e..79f512c 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -74,6 +74,7 @@ public:
GetOperation,
PutOperation,
PostOperation,
+ DeleteOperation,
UnknownOperation = 0
};
@@ -100,6 +101,7 @@ public:
QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data);
QNetworkReply *put(const QNetworkRequest &request, QIODevice *data);
QNetworkReply *put(const QNetworkRequest &request, const QByteArray &data);
+ QNetworkReply *deleteResource(const QNetworkRequest &request);
Q_SIGNALS:
#ifndef QT_NO_NETWORKPROXY
diff --git a/src/network/access/qnetworkcookie.cpp b/src/network/access/qnetworkcookie.cpp
index e31621c..fb7be8d 100644
--- a/src/network/access/qnetworkcookie.cpp
+++ b/src/network/access/qnetworkcookie.cpp
@@ -1063,7 +1063,7 @@ QList<QNetworkCookie> QNetworkCookiePrivate::parseSetCookieHeaderLine(const QByt
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug s, const QNetworkCookie &cookie)
{
- s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ")";
+ s.nospace() << "QNetworkCookie(" << cookie.toRawForm(QNetworkCookie::Full) << ')';
return s.space();
}
#endif
diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp
index daa2335..4e4004b 100644
--- a/src/network/access/qnetworkdiskcache.cpp
+++ b/src/network/access/qnetworkdiskcache.cpp
@@ -41,6 +41,8 @@
//#define QNETWORKDISKCACHE_DEBUG
+#ifndef QT_NO_NETWORKDISKCACHE
+
#include "qnetworkdiskcache.h"
#include "qnetworkdiskcache_p.h"
#include "QtCore/qscopedpointer.h"
@@ -669,3 +671,5 @@ bool QCacheItem::read(QFile *device, bool readData)
}
QT_END_NAMESPACE
+
+#endif // QT_NO_NETWORKDISKCACHE
diff --git a/src/network/access/qnetworkdiskcache.h b/src/network/access/qnetworkdiskcache.h
index ca4bb94..78e3f6b 100644
--- a/src/network/access/qnetworkdiskcache.h
+++ b/src/network/access/qnetworkdiskcache.h
@@ -50,6 +50,8 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Network)
+#ifndef QT_NO_NETWORKDISKCACHE
+
class QNetworkDiskCachePrivate;
class Q_NETWORK_EXPORT QNetworkDiskCache : public QAbstractNetworkCache
{
@@ -86,9 +88,10 @@ private:
Q_DISABLE_COPY(QNetworkDiskCache)
};
+#endif // QT_NO_NETWORKDISKCACHE
+
QT_END_NAMESPACE
QT_END_HEADER
#endif // QNETWORKDISKCACHE_H
-
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index f4dad3c..0990b17 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -151,6 +151,10 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
authentication to serve the content but the credentials provided
were not accepted (if any)
+ \value ContentReSendError the request needed to be sent
+ again, but this failed for example because the upload data
+ could not be read a second time.
+
\value ProtocolUnknownError the Network Access API cannot
honor the request because the protocol is not known
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 6f763b3..2f864fe 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -92,6 +92,7 @@ public:
ContentOperationNotPermittedError,
ContentNotFoundError,
AuthenticationRequiredError,
+ ContentReSendError,
UnknownContentError = 299,
// protocol errors
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 6f715e5..a146358 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -46,13 +46,15 @@
#include "QtCore/qcoreapplication.h"
#include "QtCore/qdatetime.h"
#include "QtNetwork/qsslconfiguration.h"
+#include "qnetworkaccesshttpbackend_p.h"
#include <QtCore/QCoreApplication>
QT_BEGIN_NAMESPACE
inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
- : copyDevice(0), networkCache(0),
+ : backend(0), outgoingData(0), outgoingDataBuffer(0),
+ copyDevice(0), networkCache(0),
cacheEnabled(false), cacheSaveDevice(0),
bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1),
state(Idle)
@@ -61,8 +63,13 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
void QNetworkReplyImplPrivate::_q_startOperation()
{
- // This function is called exactly once
+ // ensure this function is only being called once
+ if (state == Working) {
+ qDebug("QNetworkReplyImpl::_q_startOperation was called more than once");
+ return;
+ }
state = Working;
+
if (!backend) {
error(QNetworkReplyImpl::ProtocolUnknownError,
QCoreApplication::translate("QNetworkReply", "Protocol \"%1\" is unknown").arg(url.scheme())); // not really true!;
@@ -74,57 +81,11 @@ void QNetworkReplyImplPrivate::_q_startOperation()
if (state != Finished) {
if (operation == QNetworkAccessManager::GetOperation)
pendingNotifications.append(NotifyDownstreamReadyWrite);
- if (outgoingData) {
- _q_sourceReadyRead();
-#if 0 // ### FIXME
- if (outgoingData->atEndOfStream() && writeBuffer.isEmpty())
- // empty upload
- emit q->uploadProgress(0, 0);
-#endif
- }
handleNotifications();
}
}
-void QNetworkReplyImplPrivate::_q_sourceReadyRead()
-{
- // read data from the outgoingData QIODevice into our internal buffer
- enum { DesiredBufferSize = 32 * 1024 };
-
- if (writeBuffer.size() >= DesiredBufferSize)
- return; // don't grow the buffer too much
-
- // read as many bytes are available or up until we fill up the buffer
- // but always read at least one byte
- qint64 bytesToRead = qBound<qint64>(1, outgoingData->bytesAvailable(),
- DesiredBufferSize - writeBuffer.size());
- char *ptr = writeBuffer.reserve(bytesToRead);
- qint64 bytesActuallyRead = outgoingData->read(ptr, bytesToRead);
- if (bytesActuallyRead == -1) {
- // EOF
- writeBuffer.chop(bytesToRead);
- backendNotify(NotifyCloseUpstreamChannel);
- return;
- }
-
- if (bytesActuallyRead < bytesToRead)
- writeBuffer.chop(bytesToRead - bytesActuallyRead);
-
- // if we did read anything, let the backend know and handle it
- if (bytesActuallyRead)
- backendNotify(NotifyUpstreamReadyRead);
-
- // check for EOF again
- if (!outgoingData->isSequential() && outgoingData->atEnd())
- backendNotify(NotifyCloseUpstreamChannel);
-}
-
-void QNetworkReplyImplPrivate::_q_sourceReadChannelFinished()
-{
- _q_sourceReadyRead();
-}
-
void QNetworkReplyImplPrivate::_q_copyReadyRead()
{
Q_Q(QNetworkReplyImpl);
@@ -143,7 +104,7 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
if (bytesActuallyRead == -1) {
readBuffer.chop(bytesToRead);
backendNotify(NotifyCopyFinished);
- return;
+ break;
}
if (bytesActuallyRead != bytesToRead)
@@ -151,6 +112,7 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
if (!copyDevice->isSequential() && copyDevice->atEnd()) {
backendNotify(NotifyCopyFinished);
+ bytesDownloaded += bytesActuallyRead;
break;
}
@@ -174,6 +136,67 @@ void QNetworkReplyImplPrivate::_q_copyReadChannelFinished()
_q_copyReadyRead();
}
+void QNetworkReplyImplPrivate::_q_bufferOutgoingDataFinished()
+{
+ Q_Q(QNetworkReplyImpl);
+
+ // 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 QNetworkReplyImplPrivate::_q_bufferOutgoingData()
+{
+ Q_Q(QNetworkReplyImpl);
+
+ if (!outgoingDataBuffer) {
+ // first call, create our buffer
+ outgoingDataBuffer = 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);
+ }
+ }
+}
+
+
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
QIODevice *data)
{
@@ -184,13 +207,42 @@ void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const
url = request.url();
operation = op;
- if (outgoingData) {
- q->connect(outgoingData, SIGNAL(readyRead()), SLOT(_q_sourceReadyRead()));
- q->connect(outgoingData, SIGNAL(readChannelFinished()), SLOT(_q_sourceReadChannelFinished()));
+ if (outgoingData && backend) {
+ // there is data to be uploaded, e.g. HTTP POST.
+
+ if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) {
+ // backend does not need upload buffering or
+ // fixed size non-sequential
+ // just start the operation
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ } else {
+ bool bufferingDisallowed =
+ req.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 (req.header(QNetworkRequest::ContentLengthHeader).isValid()) {
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ } else {
+ state = Buffering;
+ QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection);
+ }
+ } else {
+ // _q_startOperation will be called when the buffering has finished.
+ state = Buffering;
+ QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection);
+ }
+ }
+ } else {
+ // No outgoing data (e.g. HTTP GET request)
+ // or no backend
+ // if no backend, _q_startOperation will handle the error of this
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
q->QIODevice::open(QIODevice::ReadOnly);
- QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
}
void QNetworkReplyImplPrivate::setNetworkCache(QAbstractNetworkCache *nc)
@@ -226,18 +278,10 @@ void QNetworkReplyImplPrivate::handleNotifications()
backend->downstreamReadyWrite();
break;
- case NotifyUpstreamReadyRead:
- backend->upstreamReadyRead();
- break;
-
case NotifyCloseDownstreamChannel:
backend->closeDownstreamChannel();
break;
- case NotifyCloseUpstreamChannel:
- backend->closeUpstreamChannel();
- break;
-
case NotifyCopyFinished: {
QIODevice *dev = copyDevice;
copyDevice = 0;
@@ -299,29 +343,14 @@ void QNetworkReplyImplPrivate::completeCacheSave()
cacheEnabled = false;
}
-void QNetworkReplyImplPrivate::consume(qint64 count)
+void QNetworkReplyImplPrivate::emitUploadProgress(qint64 bytesSent, qint64 bytesTotal)
{
Q_Q(QNetworkReplyImpl);
- if (count <= 0) {
- qWarning("QNetworkConnection: backend signalled that it consumed %ld bytes", long(count));
- return;
- }
-
- if (outgoingData)
- // schedule another read from the source
- QMetaObject::invokeMethod(q_func(), "_q_sourceReadyRead", Qt::QueuedConnection);
-
- writeBuffer.skip(count);
- if (bytesUploaded == -1)
- bytesUploaded = count;
- else
- bytesUploaded += count;
-
- QVariant totalSize = request.header(QNetworkRequest::ContentLengthHeader);
- emit q->uploadProgress(bytesUploaded,
- totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
+ bytesUploaded = bytesSent;
+ emit q->uploadProgress(bytesSent, bytesTotal);
}
+
qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const
{
enum { DesiredBufferSize = 32 * 1024 };
@@ -331,7 +360,9 @@ qint64 QNetworkReplyImplPrivate::nextDownstreamBlockSize() const
return qMax<qint64>(0, readBufferMaxSize - readBuffer.size());
}
-void QNetworkReplyImplPrivate::feed(const QByteArray &data)
+// we received downstream data and send this to the cache
+// and to our readBuffer (which in turn gets read by the user of QNetworkReply)
+void QNetworkReplyImplPrivate::appendDownstreamData(const QByteArray &data)
{
Q_Q(QNetworkReplyImpl);
if (!q->isOpen())
@@ -379,7 +410,8 @@ void QNetworkReplyImplPrivate::feed(const QByteArray &data)
}
}
-void QNetworkReplyImplPrivate::feed(QIODevice *data)
+// this is used when it was fetched from the cache, right?
+void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data)
{
Q_Q(QNetworkReplyImpl);
if (!q->isOpen())
@@ -410,9 +442,11 @@ void QNetworkReplyImplPrivate::finished()
pendingNotifications.clear();
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
- if (bytesDownloaded != lastBytesDownloaded || totalSize.isNull())
+ if (totalSize.isNull() || totalSize == -1) {
emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
- if (bytesUploaded == -1 && outgoingData)
+ }
+
+ if (bytesUploaded == -1 && (outgoingData || outgoingDataBuffer))
emit q->uploadProgress(0, 0);
completeCacheSave();
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index ad06f78..8d3c90e 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -59,6 +59,7 @@
#include "qnetworkproxy.h"
#include "QtCore/qmap.h"
#include "QtCore/qqueue.h"
+#include "QtCore/qbuffer.h"
#include "private/qringbuffer_p.h"
QT_BEGIN_NAMESPACE
@@ -91,10 +92,10 @@ public:
Q_DECLARE_PRIVATE(QNetworkReplyImpl)
Q_PRIVATE_SLOT(d_func(), void _q_startOperation())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceReadyRead())
- Q_PRIVATE_SLOT(d_func(), void _q_sourceReadChannelFinished())
Q_PRIVATE_SLOT(d_func(), void _q_copyReadyRead())
Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished())
+ Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
+ Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
};
class QNetworkReplyImplPrivate: public QNetworkReplyPrivate
@@ -102,15 +103,13 @@ class QNetworkReplyImplPrivate: public QNetworkReplyPrivate
public:
enum InternalNotifications {
NotifyDownstreamReadyWrite,
- NotifyUpstreamReadyRead,
NotifyCloseDownstreamChannel,
- NotifyCloseUpstreamChannel,
NotifyCopyFinished
};
enum State {
Idle,
- Opening,
+ Buffering,
Working,
Finished,
Aborted
@@ -125,6 +124,8 @@ public:
void _q_sourceReadChannelFinished();
void _q_copyReadyRead();
void _q_copyReadChannelFinished();
+ void _q_bufferOutgoingData();
+ void _q_bufferOutgoingDataFinished();
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
@@ -138,9 +139,10 @@ public:
void setCachingEnabled(bool enable);
bool isCachingEnabled() const;
void consume(qint64 count);
+ void emitUploadProgress(qint64 bytesSent, qint64 bytesTotal);
qint64 nextDownstreamBlockSize() const;
- void feed(const QByteArray &data);
- void feed(QIODevice *data);
+ void appendDownstreamData(const QByteArray &data);
+ void appendDownstreamData(QIODevice *data);
void finished();
void error(QNetworkReply::NetworkError code, const QString &errorString);
void metaDataChanged();
@@ -149,6 +151,7 @@ public:
QNetworkAccessBackend *backend;
QIODevice *outgoingData;
+ QRingBuffer *outgoingDataBuffer;
QIODevice *copyDevice;
QAbstractNetworkCache *networkCache;
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 2ff561a..ecb0604 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -162,6 +162,13 @@ QT_BEGIN_NAMESPACE
Indicates whether the data was obtained from cache
or not.
+ \value DoNotBufferUploadDataAttribute
+ Requests only, type: QVariant::Bool (default: false)
+ Indicates whether the QNetworkAccessManager code is
+ allowed to buffer the upload data, e.g. when doing a HTTP POST.
+ When using this flag with sequential upload data, the ContentLengthHeader
+ header must be set.
+
\value User
Special type. Additional information can be passed in
QVariants with types ranging from User to UserMax. The default
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index 4c4159d..a8187b9 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -75,6 +75,7 @@ public:
CacheLoadControlAttribute,
CacheSaveControlAttribute,
SourceIsFromCacheAttribute,
+ DoNotBufferUploadDataAttribute,
User = 1000,
UserMax = 32767
diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp
index 33795aa..cae3024 100644
--- a/src/network/kernel/qauthenticator.cpp
+++ b/src/network/kernel/qauthenticator.cpp
@@ -46,6 +46,7 @@
#include <qbytearray.h>
#include <qcryptographichash.h>
#include <qhttp.h>
+#include <qiodevice.h>
#include <qdatastream.h>
#include <qendian.h>
#include <qstring.h>
@@ -511,13 +512,13 @@ QByteArray QAuthenticatorPrivate::digestMd5Response(const QByteArray &challenge,
credentials += "uri=\"" + path + "\", ";
if (!opaque.isEmpty())
credentials += "opaque=\"" + opaque + "\", ";
- credentials += "response=\"" + response + "\"";
+ credentials += "response=\"" + response + '\"';
if (!options.value("algorithm").isEmpty())
credentials += ", algorithm=" + options.value("algorithm");
if (!options.value("qop").isEmpty()) {
credentials += ", qop=" + qop + ", ";
credentials += "nc=" + nonceCountString + ", ";
- credentials += "cnonce=\"" + cnonce + "\"";
+ credentials += "cnonce=\"" + cnonce + '\"';
}
return credentials;
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index a3634ce..aa20b61 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -1077,7 +1077,7 @@ QPair<QHostAddress, int> QHostAddress::parseSubnet(const QString &subnet)
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug d, const QHostAddress &address)
{
- d.maybeSpace() << "QHostAddress(" << address.toString() << ")";
+ d.maybeSpace() << "QHostAddress(" << address.toString() << ')';
return d.space();
}
#endif
diff --git a/src/network/kernel/qnetworkinterface.cpp b/src/network/kernel/qnetworkinterface.cpp
index f8fff88..fa87553 100644
--- a/src/network/kernel/qnetworkinterface.cpp
+++ b/src/network/kernel/qnetworkinterface.cpp
@@ -593,7 +593,7 @@ static inline QDebug operator<<(QDebug debug, const QNetworkAddressEntry &entry)
debug.nospace() << ", netmask = " << entry.netmask();
if (!entry.broadcast().isNull())
debug.nospace() << ", broadcast = " << entry.broadcast();
- debug.nospace() << ")";
+ debug.nospace() << ')';
return debug.space();
}
diff --git a/src/network/kernel/qnetworkproxy.cpp b/src/network/kernel/qnetworkproxy.cpp
index fd3a85a..a5fd60e 100644
--- a/src/network/kernel/qnetworkproxy.cpp
+++ b/src/network/kernel/qnetworkproxy.cpp
@@ -324,7 +324,7 @@ QList<QNetworkProxy> QGlobalNetworkProxy::proxyForQuery(const QNetworkProxyQuery
return result;
}
-Q_GLOBAL_STATIC(QGlobalNetworkProxy, globalNetworkProxy);
+Q_GLOBAL_STATIC(QGlobalNetworkProxy, globalNetworkProxy)
namespace {
template<bool> struct StaticAssertTest;
diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp
index b6f91e4..61b5f14 100644
--- a/src/network/socket/qabstractsocket.cpp
+++ b/src/network/socket/qabstractsocket.cpp
@@ -852,7 +852,7 @@ void QAbstractSocketPrivate::_q_startConnecting(const QHostInfo &hostInfo)
if (i != 0) s += ", ";
s += addresses.at(i).toString();
}
- s += "}";
+ s += '}';
qDebug("QAbstractSocketPrivate::_q_startConnecting(hostInfo == %s)", s.toLatin1().constData());
#endif
@@ -2597,7 +2597,7 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, QAbstractSocket::SocketError er
debug << "QAbstractSocket::ProxyProtocolError";
break;
default:
- debug << "QAbstractSocket::SocketError(" << int(error) << ")";
+ debug << "QAbstractSocket::SocketError(" << int(error) << ')';
break;
}
return debug;
@@ -2628,7 +2628,7 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, QAbstractSocket::SocketState st
debug << "QAbstractSocket::ClosingState";
break;
default:
- debug << "QAbstractSocket::SocketState(" << int(state) << ")";
+ debug << "QAbstractSocket::SocketState(" << int(state) << ')';
break;
}
return debug;
diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp
index 35701a7..03c1f69 100644
--- a/src/network/socket/qlocalserver.cpp
+++ b/src/network/socket/qlocalserver.cpp
@@ -280,9 +280,13 @@ QLocalSocket *QLocalServer::nextPendingConnection()
if(!d->socketNotifier)
return nextSocket;
#endif
+#ifndef QT_LOCALSOCKET_TCP
+ if (d->pendingConnections.size() <= d->maxPendingConnections)
#ifndef Q_OS_WIN
- d->socketNotifier->setEnabled(d->pendingConnections.size()
- <= d->maxPendingConnections);
+ d->socketNotifier->setEnabled(true);
+#else
+ d->connectionEventNotifier->setEnabled(true);
+#endif
#endif
return nextSocket;
}
diff --git a/src/network/socket/qlocalserver.h b/src/network/socket/qlocalserver.h
index 8e8babd..1488a75 100644
--- a/src/network/socket/qlocalserver.h
+++ b/src/network/socket/qlocalserver.h
@@ -86,15 +86,7 @@ protected:
private:
Q_DISABLE_COPY(QLocalServer)
-#if defined(QT_LOCALSOCKET_TCP)
Q_PRIVATE_SLOT(d_func(), void _q_onNewConnection())
-#elif defined(Q_OS_WIN)
- Q_PRIVATE_SLOT(d_func(), void _q_openSocket(HANDLE handle))
- Q_PRIVATE_SLOT(d_func(), void _q_stoppedListening())
- Q_PRIVATE_SLOT(d_func(), void _q_setError(QAbstractSocket::SocketError error, const QString &errorString))
-#else
- Q_PRIVATE_SLOT(d_func(), void _q_socketActivated())
-#endif
};
#endif // QT_NO_LOCALSERVER
diff --git a/src/network/socket/qlocalserver_p.h b/src/network/socket/qlocalserver_p.h
index 8e96401..7b31082 100644
--- a/src/network/socket/qlocalserver_p.h
+++ b/src/network/socket/qlocalserver_p.h
@@ -63,7 +63,7 @@
# include <qtcpserver.h>
#elif defined(Q_OS_WIN)
# include <qt_windows.h>
-# include <qthread.h>
+# include <private/qwineventnotifier_p.h>
#else
# include <private/qnativesocketengine_p.h>
# include <qsocketnotifier.h>
@@ -71,52 +71,13 @@
QT_BEGIN_NAMESPACE
-#if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
-
-/*!
- \internal
- QLocalServerThread exists because Windows does not have a
- way to provide notifications when there is a new connections to
- the server.
- */
-class QLocalServerThread : public QThread
-{
- Q_OBJECT
-
-Q_SIGNALS:
- void connected(HANDLE newSocket);
- void error(QAbstractSocket::SocketError error, const QString &errorString);
-
-public:
- QLocalServerThread(QObject *parent = 0);
- ~QLocalServerThread();
- void closeServer();
-
-public:
- QString setName(const QString &name);
- void run();
- void stop();
- bool makeHandle();
-
- HANDLE gotConnectionEvent;
- QQueue<HANDLE> pendingHandles;
- int maxPendingConnections;
-private:
- HANDLE stopEvent;
- QString fullServerName;
-};
-
-#endif
-
class QLocalServerPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QLocalServer)
public:
QLocalServerPrivate() :
-#if defined(Q_OS_WIN) && !defined(QT_LOCALSOCKET_TCP)
- inWaitingFunction(false),
-#elif !defined(QT_LOCALSOCKET_TCP)
+#if !defined(QT_LOCALSOCKET_TCP) && !defined(Q_OS_WIN)
listenSocket(-1), socketNotifier(0),
#endif
maxPendingConnections(30), error(QAbstractSocket::UnknownSocketError)
@@ -128,22 +89,26 @@ public:
static bool removeServer(const QString &name);
void closeServer();
void waitForNewConnection(int msec, bool *timedOut);
+ void _q_onNewConnection();
#if defined(QT_LOCALSOCKET_TCP)
- void _q_onNewConnection();
QTcpServer tcpServer;
QMap<quintptr, QTcpSocket*> socketMap;
#elif defined(Q_OS_WIN)
- void _q_openSocket(HANDLE socket);
- void _q_stoppedListening();
- void _q_setError(QAbstractSocket::SocketError error, const QString &errorString);
+ struct Listener {
+ HANDLE handle;
+ OVERLAPPED overlapped;
+ };
+
+ void setError(const QString &function);
+ bool addListener();
- QLocalServerThread waitForConnection;
- bool inWaitingFunction;
+ QList<Listener> listeners;
+ HANDLE eventHandle;
+ QWinEventNotifier *connectionEventNotifier;
#else
void setError(const QString &function);
- void _q_socketActivated();
int listenSocket;
QSocketNotifier *socketNotifier;
diff --git a/src/network/socket/qlocalserver_unix.cpp b/src/network/socket/qlocalserver_unix.cpp
index d3ccb69..4dfeaef 100644
--- a/src/network/socket/qlocalserver_unix.cpp
+++ b/src/network/socket/qlocalserver_unix.cpp
@@ -150,7 +150,7 @@ bool QLocalServerPrivate::listen(const QString &requestedServerName)
socketNotifier = new QSocketNotifier(listenSocket,
QSocketNotifier::Read, q);
q->connect(socketNotifier, SIGNAL(activated(int)),
- q, SLOT(_q_socketActivated()));
+ q, SLOT(_q_onNewConnection()));
socketNotifier->setEnabled(maxPendingConnections > 0);
return true;
}
@@ -182,7 +182,7 @@ void QLocalServerPrivate::closeServer()
We have received a notification that we can read on the listen socket.
Accept the new socket.
*/
-void QLocalServerPrivate::_q_socketActivated()
+void QLocalServerPrivate::_q_onNewConnection()
{
Q_Q(QLocalServer);
if (-1 == listenSocket)
@@ -227,7 +227,7 @@ void QLocalServerPrivate::waitForNewConnection(int msec, bool *timedOut)
break;
}
if (result > 0)
- _q_socketActivated();
+ _q_onNewConnection();
}
if (timedOut)
*timedOut = (result == 0);
diff --git a/src/network/socket/qlocalserver_win.cpp b/src/network/socket/qlocalserver_win.cpp
index 880cd7e..b14bbf7 100644
--- a/src/network/socket/qlocalserver_win.cpp
+++ b/src/network/socket/qlocalserver_win.cpp
@@ -44,68 +44,26 @@
#include "qlocalsocket.h"
#include <qdebug.h>
-#include <qdatetime.h>
-#include <qcoreapplication.h>
-#include <QMetaType>
// The buffer size need to be 0 otherwise data could be
// lost if the socket that has written data closes the connection
// before it is read. Pipewriter is used for write buffering.
#define BUFSIZE 0
-QT_BEGIN_NAMESPACE
-
-QLocalServerThread::QLocalServerThread(QObject *parent) : QThread(parent),
- maxPendingConnections(1)
-{
- stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- gotConnectionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
-}
+// ###: This should be a property. Should replace the insane 50 on unix as well.
+#define SYSTEM_MAX_PENDING_SOCKETS 8
-QLocalServerThread::~QLocalServerThread()
-{
- stop();
- closeServer();
- CloseHandle(stopEvent);
- CloseHandle(gotConnectionEvent);
-}
-
-void QLocalServerThread::stop()
-{
- if (isRunning()) {
- SetEvent(stopEvent);
- wait();
- ResetEvent(stopEvent);
- }
-}
-
-void QLocalServerThread::closeServer()
-{
- while (!pendingHandles.isEmpty())
- CloseHandle(pendingHandles.dequeue());
-}
-
-QString QLocalServerThread::setName(const QString &name)
-{
- QString pipePath = QLatin1String("\\\\.\\pipe\\");
- if (name.startsWith(pipePath))
- fullServerName = name;
- else
- fullServerName = pipePath + name;
- for (int i = pendingHandles.count(); i < maxPendingConnections; ++i)
- if (!makeHandle())
- break;
- return fullServerName;
-}
+QT_BEGIN_NAMESPACE
-bool QLocalServerThread::makeHandle()
+bool QLocalServerPrivate::addListener()
{
- if (pendingHandles.count() >= maxPendingConnections)
- return false;
+ // The object must not change its address once the
+ // contained OVERLAPPED struct is passed to Windows.
+ listeners << Listener();
+ Listener &listener = listeners.last();
- HANDLE handle = INVALID_HANDLE_VALUE;
QT_WA({
- handle = CreateNamedPipeW(
+ listener.handle = CreateNamedPipeW(
(TCHAR*)fullServerName.utf16(), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
@@ -117,7 +75,7 @@ bool QLocalServerThread::makeHandle()
3000, // client time-out
NULL);
}, {
- handle = CreateNamedPipeA(
+ listener.handle = CreateNamedPipeA(
fullServerName.toLocal8Bit().constData(), // pipe name
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, // read/write access
PIPE_TYPE_MESSAGE | // message type pipe
@@ -129,68 +87,43 @@ bool QLocalServerThread::makeHandle()
3000, // client time-out
NULL);
});
-
- if (INVALID_HANDLE_VALUE == handle) {
+ if (listener.handle == INVALID_HANDLE_VALUE) {
+ setError(QLatin1String("QLocalServerPrivate::addListener"));
+ listeners.removeLast();
return false;
}
- pendingHandles.enqueue(handle);
+
+ memset(&listener.overlapped, 0, sizeof(listener.overlapped));
+ listener.overlapped.hEvent = eventHandle;
+ if (!ConnectNamedPipe(listener.handle, &listener.overlapped)) {
+ switch (GetLastError()) {
+ case ERROR_IO_PENDING:
+ break;
+ case ERROR_PIPE_CONNECTED:
+ SetEvent(eventHandle);
+ break;
+ default:
+ CloseHandle(listener.handle);
+ setError(QLatin1String("QLocalServerPrivate::addListener"));
+ listeners.removeLast();
+ return false;
+ }
+ } else {
+ Q_ASSERT_X(false, "QLocalServerPrivate::addListener", "The impossible happened");
+ SetEvent(eventHandle);
+ }
return true;
}
-void QLocalServerThread::run()
+void QLocalServerPrivate::setError(const QString &function)
{
- OVERLAPPED op;
- HANDLE handleArray[2];
- memset(&op, 0, sizeof(op));
- handleArray[0] = op.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- handleArray[1] = stopEvent;
- HANDLE handle = INVALID_HANDLE_VALUE;
-
- forever {
- if (INVALID_HANDLE_VALUE == handle) {
- makeHandle();
- if (!pendingHandles.isEmpty())
- handle = pendingHandles.dequeue();
- }
- if (INVALID_HANDLE_VALUE == handle) {
- int windowsError = GetLastError();
- QString function = QLatin1String("QLocalServer::run");
- QString errorString = QLocalServer::tr("%1: Unknown error %2").arg(function).arg(windowsError);
- emit error(QAbstractSocket::UnknownSocketError, errorString);
- CloseHandle(handleArray[0]);
- SetEvent(gotConnectionEvent);
- return;
- }
-
- BOOL isConnected = ConnectNamedPipe(handle, &op) ? TRUE : (GetLastError() == ERROR_PIPE_CONNECTED);
- if (!isConnected) {
- switch (WaitForMultipleObjects(2, handleArray, FALSE, INFINITE))
- {
- case WAIT_OBJECT_0 + 1:
- CloseHandle(handle);
- CloseHandle(handleArray[0]);
- return;
- }
- }
- emit connected(handle);
- handle = INVALID_HANDLE_VALUE;
- ResetEvent(handleArray[0]);
- SetEvent(gotConnectionEvent);
- }
+ int windowsError = GetLastError();
+ errorString = QString::fromLatin1("%1: %2").arg(function).arg(qt_error_string(windowsError));
+ error = QAbstractSocket::UnknownSocketError;
}
void QLocalServerPrivate::init()
{
- Q_Q(QLocalServer);
- qRegisterMetaType<HANDLE>("HANDLE");
- q->connect(&waitForConnection, SIGNAL(connected(HANDLE)),
- q, SLOT(_q_openSocket(HANDLE)), Qt::QueuedConnection);
- q->connect(&waitForConnection, SIGNAL(finished()),
- q, SLOT(_q_stoppedListening()), Qt::QueuedConnection);
- q->connect(&waitForConnection, SIGNAL(terminated()),
- q, SLOT(_q_stoppedListening()), Qt::QueuedConnection);
- q->connect(&waitForConnection, SIGNAL(error(QAbstractSocket::SocketError, const QString &)),
- q, SLOT(_q_setError(QAbstractSocket::SocketError, const QString &)));
}
bool QLocalServerPrivate::removeServer(const QString &name)
@@ -201,35 +134,71 @@ bool QLocalServerPrivate::removeServer(const QString &name)
bool QLocalServerPrivate::listen(const QString &name)
{
- fullServerName = waitForConnection.setName(name);
- serverName = name;
- waitForConnection.start();
- return true;
-}
+ Q_Q(QLocalServer);
-void QLocalServerPrivate::_q_setError(QAbstractSocket::SocketError e, const QString &eString)
-{
- error = e;
- errorString = eString;
-}
+ QString pipePath = QLatin1String("\\\\.\\pipe\\");
+ if (name.startsWith(pipePath))
+ fullServerName = name;
+ else
+ fullServerName = pipePath + name;
-void QLocalServerPrivate::_q_stoppedListening()
-{
- Q_Q(QLocalServer);
- if (!inWaitingFunction)
- q->close();
+ // Use only one event for all listeners of one socket.
+ // The idea is that listener events are rare, so polling all listeners once in a while is
+ // cheap compared to waiting for N additional events in each iteration of the main loop.
+ eventHandle = CreateEvent(NULL, TRUE, FALSE, NULL);
+ connectionEventNotifier = new QWinEventNotifier(eventHandle , q);
+ q->connect(connectionEventNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_onNewConnection()));
+
+ for (int i = 0; i < SYSTEM_MAX_PENDING_SOCKETS; ++i)
+ if (!addListener())
+ return false;
+ return true;
}
-void QLocalServerPrivate::_q_openSocket(HANDLE handle)
+void QLocalServerPrivate::_q_onNewConnection()
{
Q_Q(QLocalServer);
- q->incomingConnection((int)handle);
+ DWORD dummy;
+
+ // Reset first, otherwise we could reset an event which was asserted
+ // immediately after we checked the conn status.
+ ResetEvent(eventHandle);
+
+ // Testing shows that there is indeed absolutely no guarantee which listener gets
+ // a client connection first, so there is no way around polling all of them.
+ for (int i = 0; i < listeners.size(); ) {
+ HANDLE handle = listeners[i].handle;
+ if (GetOverlappedResult(handle, &listeners[i].overlapped, &dummy, FALSE)) {
+ listeners.removeAt(i);
+
+ addListener();
+
+ if (pendingConnections.size() > maxPendingConnections)
+ connectionEventNotifier->setEnabled(false);
+
+ // Make this the last thing so connected slots can wreak the least havoc
+ q->incomingConnection((quintptr)handle);
+ } else {
+ if (GetLastError() != ERROR_IO_INCOMPLETE) {
+ setError(QLatin1String("QLocalServerPrivate::_q_onNewConnection"));
+ closeServer();
+ return;
+ }
+
+ ++i;
+ }
+ }
}
void QLocalServerPrivate::closeServer()
{
- waitForConnection.stop();
- waitForConnection.closeServer();
+ connectionEventNotifier->setEnabled(false); // Otherwise, closed handle is checked before deleter runs
+ connectionEventNotifier->deleteLater();
+ connectionEventNotifier = 0;
+ CloseHandle(eventHandle);
+ for (int i = 0; i < listeners.size(); ++i)
+ CloseHandle(listeners[i].handle);
+ listeners.clear();
}
void QLocalServerPrivate::waitForNewConnection(int msecs, bool *timedOut)
@@ -238,14 +207,12 @@ void QLocalServerPrivate::waitForNewConnection(int msecs, bool *timedOut)
if (!pendingConnections.isEmpty() || !q->isListening())
return;
- DWORD result = WaitForSingleObject(waitForConnection.gotConnectionEvent,
- (msecs == -1) ? INFINITE : msecs);
+ DWORD result = WaitForSingleObject(eventHandle, (msecs == -1) ? INFINITE : msecs);
if (result == WAIT_TIMEOUT) {
if (timedOut)
*timedOut = true;
} else {
- ResetEvent(waitForConnection.gotConnectionEvent);
- QCoreApplication::instance()->processEvents();
+ _q_onNewConnection();
}
}
diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp
index 327bfc6..9411130 100644
--- a/src/network/socket/qlocalsocket.cpp
+++ b/src/network/socket/qlocalsocket.cpp
@@ -468,7 +468,7 @@ QDebug operator<<(QDebug debug, QLocalSocket::LocalSocketError error)
debug << "QLocalSocket::UnknownSocketError";
break;
default:
- debug << "QLocalSocket::SocketError(" << int(error) << ")";
+ debug << "QLocalSocket::SocketError(" << int(error) << ')';
break;
}
return debug;
@@ -490,7 +490,7 @@ QDebug operator<<(QDebug debug, QLocalSocket::LocalSocketState state)
debug << "QLocalSocket::ClosingState";
break;
default:
- debug << "QLocalSocket::SocketState(" << int(state) << ")";
+ debug << "QLocalSocket::SocketState(" << int(state) << ')';
break;
}
return debug;
diff --git a/src/network/socket/qsocks5socketengine.cpp b/src/network/socket/qsocks5socketengine.cpp
index 98666c2..75b0ad9 100644
--- a/src/network/socket/qsocks5socketengine.cpp
+++ b/src/network/socket/qsocks5socketengine.cpp
@@ -157,7 +157,7 @@ static inline QString dump(const QByteArray &) { return QString(); }
*/
static bool qt_socks5_set_host_address_and_port(const QHostAddress &address, quint16 port, QByteArray *pBuf)
{
- QSOCKS5_DEBUG << "setting [" << address << ":" << port << "]";
+ QSOCKS5_DEBUG << "setting [" << address << ':' << port << ']';
union {
quint16 port;
@@ -190,7 +190,7 @@ static bool qt_socks5_set_host_address_and_port(const QHostAddress &address, qui
*/
static bool qt_socks5_set_host_name_and_port(const QString &hostname, quint16 port, QByteArray *pBuf)
{
- QSOCKS5_DEBUG << "setting [" << hostname << ":" << port << "]";
+ QSOCKS5_DEBUG << "setting [" << hostname << ':' << port << ']';
QByteArray encodedHostName = QUrl::toAce(hostname);
QByteArray &buf = *pBuf;
@@ -269,7 +269,7 @@ static bool qt_socks5_get_host_address_and_port(const QByteArray &buf, QHostAddr
}
if (ret) {
- QSOCKS5_DEBUG << "got [" << address << ":" << port << "]";
+ QSOCKS5_DEBUG << "got [" << address << ':' << port << ']';
*pAddress = address;
*pPort = port;
*pPos = pos;
@@ -1128,7 +1128,7 @@ bool QSocks5SocketEngine::connectInternal()
bool QSocks5SocketEngine::connectToHost(const QHostAddress &address, quint16 port)
{
Q_D(QSocks5SocketEngine);
- QSOCKS5_DEBUG << "connectToHost" << address << ":" << port;
+ QSOCKS5_DEBUG << "connectToHost" << address << ':' << port;
setPeerAddress(address);
setPeerPort(port);
@@ -1383,7 +1383,7 @@ bool QSocks5SocketEngine::bind(const QHostAddress &address, quint16 port)
//### reset and error
return false;
}
- QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ":" << d->localPort;
+ QSOCKS5_DEBUG << "udp actual address and port" << d->localAddress << ':' << d->localPort;
return true;
#endif // QT_NO_UDPSOCKET
}
@@ -1482,7 +1482,7 @@ qint64 QSocks5SocketEngine::bytesAvailable() const
qint64 QSocks5SocketEngine::read(char *data, qint64 maxlen)
{
Q_D(QSocks5SocketEngine);
- QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ")";
+ QSOCKS5_Q_DEBUG << "read( , maxlen = " << maxlen << ')';
if (d->mode == QSocks5SocketEnginePrivate::ConnectMode) {
if (d->connectData->readBuffer.size() == 0) {
if (d->data->controlSocket->state() == QAbstractSocket::UnconnectedState) {
@@ -1770,7 +1770,7 @@ void QSocks5SocketEngine::setReadNotificationEnabled(bool enable)
{
Q_D(QSocks5SocketEngine);
- QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ")";
+ QSOCKS5_Q_DEBUG << "setReadNotificationEnabled(" << enable << ')';
bool emitSignal = false;
if (!d->readNotificationEnabled
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index c4aa43e..d9f710e 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -355,7 +355,7 @@ QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubje
if (!d->x509)
return result;
- STACK *altNames = (STACK *)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
+ STACK_OF(GENERAL_NAME) *altNames = (STACK_OF(GENERAL_NAME)*)q_X509_get_ext_d2i(d->x509, NID_subject_alt_name, 0, 0);
if (altNames) {
for (int i = 0; i < q_sk_GENERAL_NAME_num(altNames); ++i) {
@@ -376,7 +376,7 @@ QMultiMap<QSsl::AlternateNameEntryType, QString> QSslCertificate::alternateSubje
else if (genName->type == GEN_EMAIL)
result.insert(QSsl::EmailEntry, altName);
}
- q_sk_free(altNames);
+ q_sk_free((STACK*)altNames);
}
return result;
@@ -759,16 +759,16 @@ QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
{
debug << "QSslCertificate("
<< certificate.version()
- << "," << certificate.serialNumber()
- << "," << certificate.digest().toBase64()
- << "," << certificate.issuerInfo(QSslCertificate::Organization)
- << "," << certificate.subjectInfo(QSslCertificate::Organization)
- << "," << certificate.alternateSubjectNames()
+ << ',' << certificate.serialNumber()
+ << ',' << certificate.digest().toBase64()
+ << ',' << certificate.issuerInfo(QSslCertificate::Organization)
+ << ',' << certificate.subjectInfo(QSslCertificate::Organization)
+ << ',' << certificate.alternateSubjectNames()
#ifndef QT_NO_TEXTSTREAM
- << "," << certificate.effectiveDate()
- << "," << certificate.expiryDate()
+ << ',' << certificate.effectiveDate()
+ << ',' << certificate.expiryDate()
#endif
- << ")";
+ << ')';
return debug;
}
QDebug operator<<(QDebug debug, QSslCertificate::SubjectInfo info)
diff --git a/src/network/ssl/qsslcipher.cpp b/src/network/ssl/qsslcipher.cpp
index a72879d..2a6ddeb 100644
--- a/src/network/ssl/qsslcipher.cpp
+++ b/src/network/ssl/qsslcipher.cpp
@@ -230,7 +230,7 @@ QDebug operator<<(QDebug debug, const QSslCipher &cipher)
debug << "QSslCipher(name=" << qPrintable(cipher.name())
<< ", bits=" << cipher.usedBits()
<< ", proto=" << qPrintable(cipher.protocolString())
- << ")";
+ << ')';
return debug;
}
#endif
diff --git a/src/network/ssl/qsslkey.cpp b/src/network/ssl/qsslkey.cpp
index d076112..71e6ff7 100644
--- a/src/network/ssl/qsslkey.cpp
+++ b/src/network/ssl/qsslkey.cpp
@@ -461,7 +461,7 @@ QDebug operator<<(QDebug debug, const QSslKey &key)
<< (key.type() == QSsl::PublicKey ? "PublicKey" : "PrivateKey")
<< ", " << (key.algorithm() == QSsl::Rsa ? "RSA" : "DSA")
<< ", " << key.length()
- << ")";
+ << ')';
return debug;
}
#endif
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index ea64042..4a50c5b 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -113,8 +113,8 @@
readLine(), or getChar() to read decrypted data from QSslSocket's
internal buffer, and you can call write() or putChar() to write
data back to the peer. QSslSocket will automatically encrypt the
- written data for you, and emit bytesWritten() once the data has
- been written to the peer.
+ written data for you, and emit encryptedBytesWritten() once
+ the data has been written to the peer.
As a convenience, QSslSocket supports QTcpSocket's blocking
functions waitForConnected(), waitForReadyRead(),
@@ -397,6 +397,36 @@ void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port, O
}
/*!
+ \since 4.6
+ \overload
+
+ In addition to the original behaviour of connectToHostEncrypted,
+ this overloaded method enables the usage of a different hostname
+ (\a sslPeerName) for the certificate validation instead of
+ the one used for the TCP connection (\a hostName).
+
+ \sa connectToHostEncrypted()
+*/
+void QSslSocket::connectToHostEncrypted(const QString &hostName, quint16 port,
+ const QString &sslPeerName, OpenMode mode)
+{
+ Q_D(QSslSocket);
+ if (d->state == ConnectedState || d->state == ConnectingState) {
+ qWarning("QSslSocket::connectToHostEncrypted() called when already connecting/connected");
+ return;
+ }
+
+ d->init();
+ d->autoStartHandshake = true;
+ d->initialized = true;
+ d->verificationPeerName = sslPeerName;
+
+ // Note: When connecting to localhost, some platforms (e.g., HP-UX and some BSDs)
+ // establish the connection immediately (i.e., first attempt).
+ connectToHost(hostName, port, mode);
+}
+
+/*!
Initializes QSslSocket with the native socket descriptor \a
socketDescriptor. Returns true if \a socketDescriptor is accepted
as a valid socket descriptor; otherwise returns false.
@@ -412,8 +442,8 @@ bool QSslSocket::setSocketDescriptor(int socketDescriptor, SocketState state, Op
{
Q_D(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ","
- << state << "," << openMode << ")";
+ qDebug() << "QSslSocket::setSocketDescriptor(" << socketDescriptor << ','
+ << state << ',' << openMode << ')';
#endif
if (!d->plainSocket)
d->createPlainSocket(openMode);
@@ -450,7 +480,7 @@ QSslSocket::SslMode QSslSocket::mode() const
Returns true if the socket is encrypted; otherwise, false is returned.
An encrypted socket encrypts all data that is written by calling write()
- or putChar() before the data is written to the network, and descrypts all
+ or putChar() before the data is written to the network, and decrypts all
incoming data as the data is received from the network, before you call
read(), readLine() or getChar().
@@ -1527,7 +1557,7 @@ void QSslSocket::startServerEncryption()
{
Q_D(QSslSocket);
if (d->mode != UnencryptedMode) {
- qWarning("QSslSocket::startClientEncryption: cannot start handshake on non-plain connection");
+ qWarning("QSslSocket::startServerEncryption: cannot start handshake on non-plain connection");
return;
}
#ifdef QSSLSOCKET_DEBUG
@@ -1578,7 +1608,7 @@ void QSslSocket::connectToHostImplementation(const QString &hostName, quint16 po
#ifdef QSSLSOCKET_DEBUG
qDebug() << "QSslSocket::connectToHostImplementation("
- << hostName << "," << port << "," << openMode << ")";
+ << hostName << ',' << port << ',' << openMode << ')';
#endif
if (!d->plainSocket) {
#ifdef QSSLSOCKET_DEBUG
@@ -1652,7 +1682,7 @@ qint64 QSslSocket::readData(char *data, qint64 maxlen)
} while (!d->readBuffer.isEmpty() && readBytes < maxlen);
}
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::readData(" << (void *)data << "," << maxlen << ") ==" << readBytes;
+ qDebug() << "QSslSocket::readData(" << (void *)data << ',' << maxlen << ") ==" << readBytes;
#endif
return readBytes;
}
@@ -1664,7 +1694,7 @@ qint64 QSslSocket::writeData(const char *data, qint64 len)
{
Q_D(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::writeData(" << (void *)data << "," << len << ")";
+ qDebug() << "QSslSocket::writeData(" << (void *)data << ',' << len << ')';
#endif
if (d->mode == UnencryptedMode && !d->autoStartHandshake)
return d->plainSocket->write(data, len);
@@ -1969,7 +1999,7 @@ void QSslSocketPrivate::_q_stateChangedSlot(QAbstractSocket::SocketState state)
{
Q_Q(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::_q_stateChangedSlot(" << state << ")";
+ qDebug() << "QSslSocket::_q_stateChangedSlot(" << state << ')';
#endif
q->setSocketState(state);
emit q->stateChanged(state);
@@ -1982,7 +2012,7 @@ void QSslSocketPrivate::_q_errorSlot(QAbstractSocket::SocketError error)
{
Q_Q(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::_q_errorSlot(" << error << ")";
+ qDebug() << "QSslSocket::_q_errorSlot(" << error << ')';
qDebug() << "\tstate =" << q->state();
qDebug() << "\terrorString =" << q->errorString();
#endif
@@ -2017,7 +2047,7 @@ void QSslSocketPrivate::_q_bytesWrittenSlot(qint64 written)
{
Q_Q(QSslSocket);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocket::_q_bytesWrittenSlot(" << written << ")";
+ qDebug() << "QSslSocket::_q_bytesWrittenSlot(" << written << ')';
#endif
if (mode == QSslSocket::UnencryptedMode)
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index b8db654..e4c683a 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -86,6 +86,7 @@ public:
// Autostarting the SSL client handshake.
void connectToHostEncrypted(const QString &hostName, quint16 port, OpenMode mode = ReadWrite);
+ void connectToHostEncrypted(const QString &hostName, quint16 port, const QString &sslPeerName, OpenMode mode = ReadWrite);
bool setSocketDescriptor(int socketDescriptor, SocketState state = ConnectedState,
OpenMode openMode = ReadWrite);
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index cb101af..d71682a 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -276,7 +276,7 @@ init_context:
if (first)
first = false;
else
- cipherString.append(":");
+ cipherString.append(':');
cipherString.append(cipher.name().toLatin1());
}
@@ -500,7 +500,7 @@ void QSslSocketBackendPrivate::startClientEncryption()
// Start connecting. This will place outgoing data in the BIO, so we
// follow up with calling transmit().
- testConnection();
+ startHandshake();
transmit();
}
@@ -513,7 +513,7 @@ void QSslSocketBackendPrivate::startServerEncryption()
// Start connecting. This will place outgoing data in the BIO, so we
// follow up with calling transmit().
- testConnection();
+ startHandshake();
transmit();
}
@@ -601,7 +601,7 @@ void QSslSocketBackendPrivate::transmit()
#ifdef QSSLSOCKET_DEBUG
qDebug() << "QSslSocketBackendPrivate::transmit: testing encryption";
#endif
- if (testConnection()) {
+ if (startHandshake()) {
#ifdef QSSLSOCKET_DEBUG
qDebug() << "QSslSocketBackendPrivate::transmit: encryption established";
#endif
@@ -620,7 +620,7 @@ void QSslSocketBackendPrivate::transmit()
}
// If the request is small and the remote host closes the transmission
- // after sending, there's a chance that testConnection() will already
+ // after sending, there's a chance that startHandshake() will already
// have triggered a shutdown.
if (!ssl)
continue;
@@ -720,7 +720,7 @@ static QSslError _q_OpenSSL_to_QSslError(int errorCode, const QSslCertificate &c
return error;
}
-bool QSslSocketBackendPrivate::testConnection()
+bool QSslSocketBackendPrivate::startHandshake()
{
Q_Q(QSslSocket);
@@ -761,7 +761,7 @@ bool QSslSocketBackendPrivate::testConnection()
q->setErrorString(QSslSocket::tr("Error during SSL handshake: %1").arg(SSL_ERRORSTR()));
q->setSocketError(QAbstractSocket::SslHandshakeFailedError);
#ifdef QSSLSOCKET_DEBUG
- qDebug() << "QSslSocketBackendPrivate::testConnection: error!" << q->errorString();
+ qDebug() << "QSslSocketBackendPrivate::startHandshake: error!" << q->errorString();
#endif
emit q->error(QAbstractSocket::SslHandshakeFailedError);
q->abort();
@@ -792,7 +792,7 @@ bool QSslSocketBackendPrivate::testConnection()
// but only if we're a client connecting to a server
// if we're the server, don't check CN
if (mode == QSslSocket::SslClientMode) {
- QString peerName = q->peerName();
+ QString peerName = (verificationPeerName.isEmpty () ? q->peerName() : verificationPeerName);
QString commonName = configuration.peerCertificate.subjectInfo(QSslCertificate::CommonName);
QRegExp regexp(commonName, Qt::CaseInsensitive, QRegExp::Wildcard);
@@ -888,7 +888,14 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
{
if (!ssl || !ctx)
return QSslCipher();
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+ // FIXME This is fairly evil, but needed to keep source level compatibility
+ // with the OpenSSL 0.9.x implementation at maximum -- some other functions
+ // don't take a const SSL_CIPHER* when they should
+ SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
+#else
SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
+#endif
return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
}
diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
index 968fdc0..a023a93 100644
--- a/src/network/ssl/qsslsocket_openssl_p.h
+++ b/src/network/ssl/qsslsocket_openssl_p.h
@@ -82,6 +82,10 @@
#include <openssl/rsa.h>
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+typedef _STACK STACK;
+#endif
+
QT_BEGIN_NAMESPACE
class QSslSocketBackendPrivate : public QSslSocketPrivate
@@ -106,7 +110,7 @@ public:
void startClientEncryption();
void startServerEncryption();
void transmit();
- bool testConnection();
+ bool startHandshake();
void disconnectFromHost();
void disconnected();
QSslCipher sessionCipher() const;
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index 0723822..55e9569 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -144,7 +144,11 @@ DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
+#else
DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
+#endif
DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
@@ -157,7 +161,11 @@ DEFINEFUNC(int, SSL_CTX_check_private_key, SSL_CTX *a, a, return -1, return)
#endif
DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
DEFINEFUNC(void, SSL_CTX_free, SSL_CTX *a, a, return, DUMMYARG)
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+DEFINEFUNC(SSL_CTX *, SSL_CTX_new, const SSL_METHOD *a, a, return 0, return)
+#else
DEFINEFUNC(SSL_CTX *, SSL_CTX_new, SSL_METHOD *a, a, return 0, return)
+#endif
DEFINEFUNC2(int, SSL_CTX_set_cipher_list, SSL_CTX *a, a, const char *b, b, return -1, return)
DEFINEFUNC(int, SSL_CTX_set_default_verify_paths, SSL_CTX *a, a, return -1, return)
DEFINEFUNC3(void, SSL_CTX_set_verify, SSL_CTX *a, a, int b, b, int (*c)(int, X509_STORE_CTX *), c, return, DUMMYARG)
@@ -174,7 +182,11 @@ DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, const SSL *a, a, return 0, r
#else
DEFINEFUNC(STACK_OF(SSL_CIPHER) *, SSL_get_ciphers, SSL *a, a, return 0, return)
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
+#else
DEFINEFUNC(SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return 0, return)
+#endif
DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return)
DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return 0, return)
DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return 0, return)
@@ -192,6 +204,16 @@ DEFINEFUNC3(void, SSL_set_bio, SSL *a, a, BIO *b, b, BIO *c, c, return, DUMMYARG
DEFINEFUNC(void, SSL_set_accept_state, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(void, SSL_set_connect_state, SSL *a, a, return, DUMMYARG)
DEFINEFUNC(int, SSL_shutdown, SSL *a, a, return -1, return)
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#else
DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
@@ -200,6 +222,7 @@ DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, retu
DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+#endif
DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
#ifndef SSLEAY_MACROS
diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
index c6ae91e..bf5cfbb 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
+++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
@@ -256,7 +256,11 @@ int q_RAND_status();
void q_RSA_free(RSA *a);
void q_sk_free(STACK *a);
int q_sk_num(STACK *a);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+void * q_sk_value(STACK *a, int b);
+#else
char * q_sk_value(STACK *a, int b);
+#endif
int q_SSL_accept(SSL *a);
int q_SSL_clear(SSL *a);
char *q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c);
@@ -269,7 +273,11 @@ int q_SSL_CTX_check_private_key(SSL_CTX *a);
#endif
long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
void q_SSL_CTX_free(SSL_CTX *a);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+SSL_CTX *q_SSL_CTX_new(const SSL_METHOD *a);
+#else
SSL_CTX *q_SSL_CTX_new(SSL_METHOD *a);
+#endif
int q_SSL_CTX_set_cipher_list(SSL_CTX *a, const char *b);
int q_SSL_CTX_set_default_verify_paths(SSL_CTX *a);
void q_SSL_CTX_set_verify(SSL_CTX *a, int b, int (*c)(int, X509_STORE_CTX *));
@@ -286,7 +294,11 @@ STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(const SSL *a);
#else
STACK_OF(SSL_CIPHER) *q_SSL_get_ciphers(SSL *a);
#endif
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
+#else
SSL_CIPHER *q_SSL_get_current_cipher(SSL *a);
+#endif
int q_SSL_get_error(SSL *a, int b);
STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
X509 *q_SSL_get_peer_certificate(SSL *a);
@@ -304,6 +316,16 @@ void q_SSL_set_bio(SSL *a, BIO *b, BIO *c);
void q_SSL_set_accept_state(SSL *a);
void q_SSL_set_connect_state(SSL *a);
int q_SSL_shutdown(SSL *a);
+#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+const SSL_METHOD *q_SSLv2_client_method();
+const SSL_METHOD *q_SSLv3_client_method();
+const SSL_METHOD *q_SSLv23_client_method();
+const SSL_METHOD *q_TLSv1_client_method();
+const SSL_METHOD *q_SSLv2_server_method();
+const SSL_METHOD *q_SSLv3_server_method();
+const SSL_METHOD *q_SSLv23_server_method();
+const SSL_METHOD *q_TLSv1_server_method();
+#else
SSL_METHOD *q_SSLv2_client_method();
SSL_METHOD *q_SSLv3_client_method();
SSL_METHOD *q_SSLv23_client_method();
@@ -312,6 +334,7 @@ SSL_METHOD *q_SSLv2_server_method();
SSL_METHOD *q_SSLv3_server_method();
SSL_METHOD *q_SSLv23_server_method();
SSL_METHOD *q_TLSv1_server_method();
+#endif
int q_SSL_write(SSL *a, const void *b, int c);
int q_X509_cmp(X509 *a, X509 *b);
#ifdef SSLEAY_MACROS
diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h
index 825df46..69d3cf3 100644
--- a/src/network/ssl/qsslsocket_p.h
+++ b/src/network/ssl/qsslsocket_p.h
@@ -88,6 +88,10 @@ public:
QSslConfigurationPrivate configuration;
QList<QSslError> sslErrors;
+ // if set, this hostname is used for certificate validation instead of the hostname
+ // that was used for connecting to.
+ QString verificationPeerName;
+
static bool ensureInitialized();
static void deinitialize();
static QList<QSslCipher> defaultCiphers();
diff --git a/src/opengl/gl2paintengineex/glgc_shader_source.h b/src/opengl/gl2paintengineex/glgc_shader_source.h
deleted file mode 100644
index 5b9d28b..0000000
--- a/src/opengl/gl2paintengineex/glgc_shader_source.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef GLGC_SHADER_SOURCE_H
-#define GLGC_SHADER_SOURCE_H
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-QT_MODULE(OpenGL)
-
-static const char* qglslImageVertexShader = "\
- attribute highp vec4 inputVertex; \
- attribute lowp vec2 textureCoord; \
- uniform highp mat4 pmvMatrix; \
- varying lowp vec2 fragTextureCoord; \
- void main(void) \
- {\
- gl_Position = pmvMatrix * inputVertex;\
- fragTextureCoord = textureCoord; \
- }";
-
-static const char* qglslImageFragmentShader = "\
- varying lowp vec2 fragTextureCoord;\
- uniform sampler2D textureSampler;\
- uniform lowp float opacity; \
- void main(void) \
- {\
- gl_FragColor = texture2D(textureSampler, fragTextureCoord) * opacity; \
- }";
-
-static const char* qglslTextFragmentShader = "\
- varying lowp vec2 fragTextureCoord;\
- uniform mediump vec4 fragmentColor;\
- uniform sampler2D textureSampler;\
- void main(void) \
- {\
- highp vec4 tex = texture2D(textureSampler, fragTextureCoord); \
- tex = fragmentColor * tex.r; \
- gl_FragColor = tex; \
- }";
-
-static const char* qglslDefaultVertexShader = "\
- attribute highp vec4 inputVertex;\
- uniform highp mat4 pmvMatrix;\
- void main(void)\
- {\
- gl_Position = pmvMatrix * inputVertex;\
- }";
-
-static const char* qglslSimpleFragmentShader = "\
- void main (void)\
- {\
- gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);\
- }";
-
-
-/**** FRAGMENT SHADER MAIN FUNCTIONS ****/
-// NOTE: Currently, the engine assumes brushes return colors already in pre-multiplied
-// format. However, this may change if we add support for non-premultiplied
-
-static const char* qglslNoOpacityFragmentShaderMain = "\n\
- mediump vec4 brush();\
- void main (void)\
- {\
- gl_FragColor = brush();\
- }\n";
-
-static const char* qglslFragmentShaderMain = "\n\
- mediump vec4 brush();\
- uniform lowp float opacity; \
- void main (void)\
- {\
- gl_FragColor = brush() * opacity;\
- }\n";
-
-
-
-/**** BRUSH SHADERS ****/
-
-// This should never actually be used
-static const char* qglslNoBrushFragmentShader = "\n\
- mediump vec4 brush() { \
- discard; \
- return vec4(1.0, 0.8, 0.8, 1.0);\
- }\n";
-
-// Solid Fill Brush
-static const char* qglslSolidBrushFragmentShader = "\n\
- uniform mediump vec4 fragmentColor; \
- mediump vec4 brush() { \
- return fragmentColor;\
- }\n";
-
-// Texture Brush
-static const char* qglslTextureBrushVertexShader = "\
- attribute highp vec4 inputVertex; \
- uniform highp mat4 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform mediump vec2 invertedTextureSize; \
- uniform mediump mat3 brushTransform; \
- varying mediump vec2 texCoords; \
- void main(void) { \
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- texCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \
- texCoords.y = -texCoords.y; \
- }";
-
-static const char* qglslTextureBrushFragmentShader = "\n\
- varying mediump vec2 texCoords;\
- uniform sampler2D brushTexture;\
- mediump vec4 brush() { \
- return texture2D(brushTexture, texCoords); \
- }\n";
-
-
-// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
-static const char* qglslPatternBrushVertexShader = "\
- attribute highp vec4 inputVertex; \
- uniform highp mat4 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform mediump vec2 invertedTextureSize; \
- uniform mediump mat3 brushTransform; \
- varying mediump vec2 texCoords; \
- void main(void) { \
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- texCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \
- texCoords.y = -texCoords.y; \
- }";
-
-static const char* qglslPatternBrushFragmentShader = "\n\
- uniform sampler2D brushTexture;\
- uniform lowp vec4 patternColor; \
- varying mediump vec2 texCoords;\
- mediump vec4 brush() { \
- return patternColor * texture2D(brushTexture, texCoords).r; \
- }\n";
-
-
-// Linear Gradient Brush
-static const char* qglslLinearGradientBrushVertexShader = "\
- attribute highp vec4 inputVertex; \
- uniform highp mat4 pmvMatrix; \
- uniform mediump vec2 halfViewportSize; \
- uniform highp vec3 linearData; \
- uniform mediump mat3 brushTransform; \
- varying mediump float index ; \
- void main() { \
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \
- }";
-
-static const char* qglslLinearGradientBrushFragmentShader = "\n\
- uniform sampler2D brushTexture; \
- varying mediump float index; \
- mediump vec4 brush() { \
- mediump vec2 val = vec2(index, 0.5); \
- return texture2D(brushTexture, val); \
- }\n";
-
-
-static const char* qglslRadialGradientBrushVertexShader = "\
- attribute highp vec4 inputVertex;\
- uniform highp mat4 pmvMatrix;\
- uniform mediump vec2 halfViewportSize; \
- uniform highp mat3 brushTransform; \
- uniform highp vec2 fmp; \
- varying highp float b; \
- varying highp vec2 A; \
- void main(void) \
- {\
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- A = hTexCoords.xy * invertedHTexCoordsZ; \
- b = 2.0 * fmp * (A.x + A.y); \
-\
- }";
-
-static const char* qglslRadialGradientBrushFragmentShader = "\n\
- uniform sampler2D brushTexture; \
- uniform highp float fmp2_m_radius2; \
- uniform highp float inverse_2_fmp2_m_radius2; \
- varying highp float b; \
- varying highp vec2 A; \
-\
- mediump vec4 brush() { \
- highp float c = -dot(A, A); \
- highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \
- return texture2D(brushTexture, val); \
- }\n";
-
-static const char* qglslConicalGradientBrushVertexShader = "\
- attribute highp vec4 inputVertex;\
- uniform highp mat4 pmvMatrix;\
- uniform mediump vec2 halfViewportSize; \
- uniform highp mat3 brushTransform; \
- varying highp vec2 A; \
- void main(void)\
- {\
- gl_Position = pmvMatrix * inputVertex;\
- gl_Position.xy = gl_Position.xy / gl_Position.w; \
- mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
- mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
- mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
- gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
- gl_Position.w = invertedHTexCoordsZ; \
- A = hTexCoords.xy * invertedHTexCoordsZ; \
- }";
-
-static const char* qglslConicalGradientBrushFragmentShader = "\n\
- #define INVERSE_2PI 0.1591549430918953358 \n\
- uniform sampler2D brushTexture; \
- uniform mediump float angle; \
- varying highp vec2 A; \
- mediump vec4 brush() { \
- if (abs(A.y) == abs(A.x)) \
- A.y += 0.002; \
- highp float t = (atan2(-A.y, A.x) + angle) * INVERSE_2PI; \
- return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \
- }\n";
-
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
index 0352d39..560ad3a 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
+++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray.cpp
@@ -43,6 +43,8 @@
#include <private/qbezier_p.h>
+QT_BEGIN_NAMESPACE
+
void QGL2PEXVertexArray::clear()
{
vertexArray.reset();
@@ -59,6 +61,12 @@ QGLRect QGL2PEXVertexArray::boundingRect() const
return QGLRect(minX, minY, maxX, maxY);
}
+void QGL2PEXVertexArray::addRect(const QRectF &rect)
+{
+ vertexArray << rect.topLeft() << rect.topRight() << rect.bottomRight()
+ << rect.bottomRight() << rect.bottomLeft() << rect.topLeft();
+}
+
void QGL2PEXVertexArray::addPath(const QVectorPath &path, GLfloat curveInverseScale)
{
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
@@ -154,3 +162,5 @@ void QGL2PEXVertexArray::curveToArray(const QGLPoint &cp1, const QGLPoint &cp2,
}
}
}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
index c205022..d7a9f73 100644
--- a/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
+++ b/src/opengl/gl2paintengineex/qgl2pexvertexarray_p.h
@@ -50,19 +50,24 @@
// We mean it.
//
+#ifndef QGL2PEXVERTEXARRAY_P_H
+#define QGL2PEXVERTEXARRAY_P_H
+
#include <QRectF>
#include <private/qdatabuffer_p.h>
#include <private/qvectorpath_p.h>
#include <private/qgl_p.h>
+QT_BEGIN_NAMESPACE
+
class QGLPoint
{
public:
QGLPoint(GLfloat new_x, GLfloat new_y) :
x(new_x), y(new_y) {};
- QGLPoint(QPointF p) :
+ QGLPoint(const QPointF &p) :
x(p.x()), y(p.y()) {};
QGLPoint(const QPointF* p) :
@@ -77,7 +82,7 @@ public:
struct QGLRect
{
- QGLRect(QRectF r)
+ QGLRect(const QRectF &r)
: left(r.left()), top(r.top()), right(r.right()), bottom(r.bottom()) {}
QGLRect(GLfloat l, GLfloat t, GLfloat r, GLfloat b)
@@ -98,6 +103,7 @@ public:
maxX(-2e10), maxY(-2e10), minX(2e10), minY(2e10),
boundingRectDirty(true) {}
+ void addRect(const QRectF &rect);
void addPath(const QVectorPath &path, GLfloat curveInverseScale);
void clear();
@@ -119,3 +125,7 @@ private:
inline void curveToArray(const QGLPoint &cp1, const QGLPoint &cp2, const QGLPoint &ep, GLfloat inverseScale);
};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
new file mode 100644
index 0000000..b71c4c1
--- /dev/null
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp
@@ -0,0 +1,507 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglengineshadermanager_p.h"
+#include "qglengineshadersource_p.h"
+
+#if defined(QT_DEBUG)
+#include <QMetaEnum>
+#endif
+
+
+QT_BEGIN_NAMESPACE
+
+const char* QGLEngineShaderManager::qglEngineShaderSourceCode[] = {
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0
+};
+
+QGLEngineShaderManager::QGLEngineShaderManager(QGLContext* context)
+ : ctx(context),
+ shaderProgNeedsChanging(true),
+ srcPixelType(Qt::NoBrush),
+ useGlobalOpacity(false),
+ maskType(NoMask),
+ useTextureCoords(false),
+ compositionMode(QPainter::CompositionMode_SourceOver),
+ blitShaderProg(0),
+ simpleShaderProg(0),
+ currentShaderProg(0)
+{
+ memset(compiledShaders, 0, sizeof(compiledShaders));
+
+/*
+ Rather than having the shader source array statically initialised, it is initialised
+ here instead. This is to allow new shader names to be inserted or existing names moved
+ around without having to change the order of the glsl strings. It is hoped this will
+ make future hard-to-find runtime bugs more obvious and generally give more solid code.
+*/
+ static bool qglEngineShaderSourceCodePopulated = false;
+ if (!qglEngineShaderSourceCodePopulated) {
+
+ const char** code = qglEngineShaderSourceCode; // shortcut
+
+ code[MainVertexShader] = qglslMainVertexShader;
+ code[MainWithTexCoordsVertexShader] = qglslMainWithTexCoordsVertexShader;
+
+ code[UntransformedPositionVertexShader] = qglslUntransformedPositionVertexShader;
+ code[PositionOnlyVertexShader] = qglslPositionOnlyVertexShader;
+ code[PositionWithPatternBrushVertexShader] = qglslPositionWithPatternBrushVertexShader;
+ code[PositionWithLinearGradientBrushVertexShader] = qglslPositionWithLinearGradientBrushVertexShader;
+ code[PositionWithConicalGradientBrushVertexShader] = qglslPositionWithConicalGradientBrushVertexShader;
+ code[PositionWithRadialGradientBrushVertexShader] = qglslPositionWithRadialGradientBrushVertexShader;
+ code[PositionWithTextureBrushVertexShader] = qglslPositionWithTextureBrushVertexShader;
+ code[AffinePositionWithPatternBrushVertexShader] = qglslAffinePositionWithPatternBrushVertexShader;
+ code[AffinePositionWithLinearGradientBrushVertexShader] = qglslAffinePositionWithLinearGradientBrushVertexShader;
+ code[AffinePositionWithConicalGradientBrushVertexShader] = qglslAffinePositionWithConicalGradientBrushVertexShader;
+ code[AffinePositionWithRadialGradientBrushVertexShader] = qglslAffinePositionWithRadialGradientBrushVertexShader;
+ code[AffinePositionWithTextureBrushVertexShader] = qglslAffinePositionWithTextureBrushVertexShader;
+
+ code[MainFragmentShader_CMO] = qglslMainFragmentShader_CMO;
+ code[MainFragmentShader_CM] = qglslMainFragmentShader_CM;
+ code[MainFragmentShader_MO] = qglslMainFragmentShader_MO;
+ code[MainFragmentShader_M] = qglslMainFragmentShader_M;
+ code[MainFragmentShader_CO] = qglslMainFragmentShader_CO;
+ code[MainFragmentShader_C] = qglslMainFragmentShader_C;
+ code[MainFragmentShader_O] = qglslMainFragmentShader_O;
+ code[MainFragmentShader] = qglslMainFragmentShader;
+
+ code[ImageSrcFragmentShader] = qglslImageSrcFragmentShader;
+ code[ImageSrcWithPatternFragmentShader] = qglslImageSrcWithPatternFragmentShader;
+ code[NonPremultipliedImageSrcFragmentShader] = qglslNonPremultipliedImageSrcFragmentShader;
+ code[SolidBrushSrcFragmentShader] = qglslSolidBrushSrcFragmentShader;
+ code[TextureBrushSrcFragmentShader] = qglslTextureBrushSrcFragmentShader;
+ code[TextureBrushSrcWithPatternFragmentShader] = qglslTextureBrushSrcWithPatternFragmentShader;
+ code[PatternBrushSrcFragmentShader] = qglslPatternBrushSrcFragmentShader;
+ code[LinearGradientBrushSrcFragmentShader] = qglslLinearGradientBrushSrcFragmentShader;
+ code[RadialGradientBrushSrcFragmentShader] = qglslRadialGradientBrushSrcFragmentShader;
+ code[ConicalGradientBrushSrcFragmentShader] = qglslConicalGradientBrushSrcFragmentShader;
+ code[ShockingPinkSrcFragmentShader] = qglslShockingPinkSrcFragmentShader;
+
+ code[MaskFragmentShader] = qglslMaskFragmentShader;
+ code[RgbMaskFragmentShader] = ""; //###
+ code[RgbMaskWithGammaFragmentShader] = ""; //###
+
+ code[MultiplyCompositionModeFragmentShader] = ""; //###
+ code[ScreenCompositionModeFragmentShader] = ""; //###
+ code[OverlayCompositionModeFragmentShader] = ""; //###
+ code[DarkenCompositionModeFragmentShader] = ""; //###
+ code[LightenCompositionModeFragmentShader] = ""; //###
+ code[ColorDodgeCompositionModeFragmentShader] = ""; //###
+ code[ColorBurnCompositionModeFragmentShader] = ""; //###
+ code[HardLightCompositionModeFragmentShader] = ""; //###
+ code[SoftLightCompositionModeFragmentShader] = ""; //###
+ code[DifferenceCompositionModeFragmentShader] = ""; //###
+ code[ExclusionCompositionModeFragmentShader] = ""; //###
+
+#if defined(QT_DEBUG)
+ // Check that all the elements have been filled:
+ for (int i = 0; i < TotalShaderCount; ++i) {
+ if (qglEngineShaderSourceCode[i] == 0) {
+ int enumIndex = staticMetaObject.indexOfEnumerator("ShaderName");
+ QMetaEnum m = staticMetaObject.enumerator(enumIndex);
+
+ qCritical() << "qglEngineShaderSourceCode: Source for" << m.valueToKey(i)
+ << "(shader" << i << ") missing!";
+ }
+ }
+#endif
+ qglEngineShaderSourceCodePopulated = true;
+ }
+
+ // Compile up the simple shader:
+ simpleShaderProg = new QGLShaderProgram(ctx, this);
+ compileNamedShader(MainVertexShader, QGLShader::PartialVertexShader);
+ compileNamedShader(PositionOnlyVertexShader, QGLShader::PartialVertexShader);
+ compileNamedShader(MainFragmentShader, QGLShader::PartialFragmentShader);
+ compileNamedShader(ShockingPinkSrcFragmentShader, QGLShader::PartialFragmentShader);
+ simpleShaderProg->addShader(compiledShaders[MainVertexShader]);
+ simpleShaderProg->addShader(compiledShaders[PositionOnlyVertexShader]);
+ simpleShaderProg->addShader(compiledShaders[MainFragmentShader]);
+ simpleShaderProg->addShader(compiledShaders[ShockingPinkSrcFragmentShader]);
+ simpleShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ simpleShaderProg->link();
+ if (!simpleShaderProg->isLinked()) {
+ qCritical() << "Errors linking simple shader:"
+ << simpleShaderProg->log();
+ }
+
+ // Compile the blit shader:
+ blitShaderProg = new QGLShaderProgram(ctx, this);
+ compileNamedShader(MainWithTexCoordsVertexShader, QGLShader::PartialVertexShader);
+ compileNamedShader(UntransformedPositionVertexShader, QGLShader::PartialVertexShader);
+ compileNamedShader(MainFragmentShader, QGLShader::PartialFragmentShader);
+ compileNamedShader(ImageSrcFragmentShader, QGLShader::PartialFragmentShader);
+ blitShaderProg->addShader(compiledShaders[MainWithTexCoordsVertexShader]);
+ blitShaderProg->addShader(compiledShaders[UntransformedPositionVertexShader]);
+ blitShaderProg->addShader(compiledShaders[MainFragmentShader]);
+ blitShaderProg->addShader(compiledShaders[ImageSrcFragmentShader]);
+ blitShaderProg->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+ blitShaderProg->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ blitShaderProg->link();
+ if (!blitShaderProg->isLinked()) {
+ qCritical() << "Errors linking blit shader:"
+ << blitShaderProg->log();
+ }
+}
+
+QGLEngineShaderManager::~QGLEngineShaderManager()
+{
+ //###
+}
+
+
+
+
+
+void QGLEngineShaderManager::optimiseForBrushTransform(const QTransform &transform)
+{
+ Q_UNUSED(transform); // Currently ignored
+}
+
+void QGLEngineShaderManager::setDirty()
+{
+ shaderProgNeedsChanging = true;
+}
+
+void QGLEngineShaderManager::setSrcPixelType(Qt::BrushStyle style)
+{
+ srcPixelType = style;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setSrcPixelType(PixelSrcType type)
+{
+ srcPixelType = type;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setTextureCoordsEnabled(bool enabled)
+{
+ useTextureCoords = enabled;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setUseGlobalOpacity(bool useOpacity)
+{
+ useGlobalOpacity = useOpacity;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setMaskType(MaskType type)
+{
+ maskType = type;
+ shaderProgNeedsChanging = true; //###
+}
+
+void QGLEngineShaderManager::setCompositionMode(QPainter::CompositionMode mode)
+{
+ compositionMode = mode;
+ shaderProgNeedsChanging = true; //###
+}
+
+QGLShaderProgram* QGLEngineShaderManager::currentProgram()
+{
+ return currentShaderProg;
+}
+
+QGLShaderProgram* QGLEngineShaderManager::simpleProgram()
+{
+ return simpleShaderProg;
+}
+
+QGLShaderProgram* QGLEngineShaderManager::blitProgram()
+{
+ return blitShaderProg;
+}
+
+
+
+// Select & use the correct shader program using the current state.
+// Returns true if program needed changing.
+bool QGLEngineShaderManager::useCorrectShaderProg()
+{
+ if (!shaderProgNeedsChanging)
+ return false;
+
+ QGLEngineShaderProg requiredProgram;
+ requiredProgram.program = 0;
+
+ // Choose vertex shader main function
+ QGLEngineShaderManager::ShaderName mainVertexShaderName = InvalidShaderName;
+ if (useTextureCoords)
+ mainVertexShaderName = MainWithTexCoordsVertexShader;
+ else
+ mainVertexShaderName = MainVertexShader;
+ compileNamedShader(mainVertexShaderName, QGLShader::PartialVertexShader);
+ requiredProgram.mainVertexShader = compiledShaders[mainVertexShaderName];
+
+ // Choose vertex shader shader position function (which typically also sets
+ // varyings) and the source pixel (srcPixel) fragment shader function:
+ QGLEngineShaderManager::ShaderName positionVertexShaderName = InvalidShaderName;
+ QGLEngineShaderManager::ShaderName srcPixelFragShaderName = InvalidShaderName;
+ bool isAffine = brushTransform.isAffine();
+ if ( (srcPixelType >= Qt::Dense1Pattern) && (srcPixelType <= Qt::DiagCrossPattern) ) {
+ if (isAffine)
+ positionVertexShaderName = AffinePositionWithPatternBrushVertexShader;
+ else
+ positionVertexShaderName = PositionWithPatternBrushVertexShader;
+
+ srcPixelFragShaderName = PatternBrushSrcFragmentShader;
+ }
+ else switch (srcPixelType) {
+ default:
+ case Qt::NoBrush:
+ qCritical("QGLEngineShaderManager::useCorrectShaderProg() - I'm scared, Qt::NoBrush style is set");
+ break;
+ case QGLEngineShaderManager::ImageSrc:
+ srcPixelFragShaderName = ImageSrcFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case QGLEngineShaderManager::PatternSrc:
+ srcPixelFragShaderName = ImageSrcWithPatternFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case QGLEngineShaderManager::TextureSrcWithPattern:
+ srcPixelFragShaderName = TextureBrushSrcWithPatternFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithTextureBrushVertexShader
+ : PositionWithTextureBrushVertexShader;
+ break;
+ case QGLEngineShaderManager::NonPremultipliedImageSrc:
+ srcPixelFragShaderName = NonPremultipliedImageSrcFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case Qt::SolidPattern:
+ srcPixelFragShaderName = SolidBrushSrcFragmentShader;
+ positionVertexShaderName = PositionOnlyVertexShader;
+ break;
+ case Qt::LinearGradientPattern:
+ srcPixelFragShaderName = LinearGradientBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithLinearGradientBrushVertexShader
+ : PositionWithLinearGradientBrushVertexShader;
+ break;
+ case Qt::ConicalGradientPattern:
+ srcPixelFragShaderName = ConicalGradientBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithConicalGradientBrushVertexShader
+ : PositionWithConicalGradientBrushVertexShader;
+ break;
+ case Qt::RadialGradientPattern:
+ srcPixelFragShaderName = RadialGradientBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithRadialGradientBrushVertexShader
+ : PositionWithRadialGradientBrushVertexShader;
+ break;
+ case Qt::TexturePattern:
+ srcPixelFragShaderName = TextureBrushSrcFragmentShader;
+ positionVertexShaderName = isAffine ? AffinePositionWithTextureBrushVertexShader
+ : PositionWithTextureBrushVertexShader;
+ break;
+ };
+ compileNamedShader(positionVertexShaderName, QGLShader::PartialVertexShader);
+ compileNamedShader(srcPixelFragShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.positionVertexShader = compiledShaders[positionVertexShaderName];
+ requiredProgram.srcPixelFragShader = compiledShaders[srcPixelFragShaderName];
+
+
+ const bool hasCompose = compositionMode > QPainter::CompositionMode_Plus;
+ const bool hasMask = maskType != QGLEngineShaderManager::NoMask;
+
+ // Choose fragment shader main function:
+ QGLEngineShaderManager::ShaderName mainFragShaderName;
+
+ if (hasCompose && hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_CMO;
+ if (hasCompose && hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_CM;
+ if (!hasCompose && hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_MO;
+ if (!hasCompose && hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_M;
+ if (hasCompose && !hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_CO;
+ if (hasCompose && !hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_C;
+ if (!hasCompose && !hasMask && useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader_O;
+ if (!hasCompose && !hasMask && !useGlobalOpacity)
+ mainFragShaderName = MainFragmentShader;
+
+ compileNamedShader(mainFragShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.mainFragShader = compiledShaders[mainFragShaderName];
+
+ if (hasMask) {
+ QGLEngineShaderManager::ShaderName maskShaderName = QGLEngineShaderManager::InvalidShaderName;
+ if (maskType == PixelMask)
+ maskShaderName = MaskFragmentShader;
+ else if (maskType == SubPixelMask)
+ maskShaderName = RgbMaskFragmentShader;
+ else if (maskType == SubPixelWithGammaMask)
+ maskShaderName = RgbMaskWithGammaFragmentShader;
+ else
+ qCritical("QGLEngineShaderManager::useCorrectShaderProg() - Unknown mask type");
+
+ compileNamedShader(maskShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.maskFragShader = compiledShaders[maskShaderName];
+ }
+ else
+ requiredProgram.maskFragShader = 0;
+
+ if (hasCompose) {
+ QGLEngineShaderManager::ShaderName compositionShaderName = QGLEngineShaderManager::InvalidShaderName;
+ switch (compositionMode) {
+ case QPainter::CompositionMode_Multiply:
+ compositionShaderName = MultiplyCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Screen:
+ compositionShaderName = ScreenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Overlay:
+ compositionShaderName = OverlayCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Darken:
+ compositionShaderName = DarkenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Lighten:
+ compositionShaderName = LightenCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorDodge:
+ compositionShaderName = ColorDodgeCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_ColorBurn:
+ compositionShaderName = ColorBurnCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_HardLight:
+ compositionShaderName = HardLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_SoftLight:
+ compositionShaderName = SoftLightCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Difference:
+ compositionShaderName = DifferenceCompositionModeFragmentShader;
+ break;
+ case QPainter::CompositionMode_Exclusion:
+ compositionShaderName = ExclusionCompositionModeFragmentShader;
+ break;
+ default:
+ qWarning("QGLEngineShaderManager::useCorrectShaderProg() - Unsupported composition mode");
+ }
+ compileNamedShader(compositionShaderName, QGLShader::PartialFragmentShader);
+ requiredProgram.compositionFragShader = compiledShaders[compositionShaderName];
+ }
+ else
+ requiredProgram.compositionFragShader = 0;
+
+
+ // At this point, requiredProgram is fully populated so try to find the program in the cache
+ foreach (const QGLEngineShaderProg &prog, cachedPrograms) {
+ if ( (prog.mainVertexShader == requiredProgram.mainVertexShader)
+ && (prog.positionVertexShader == requiredProgram.positionVertexShader)
+ && (prog.mainFragShader == requiredProgram.mainFragShader)
+ && (prog.srcPixelFragShader == requiredProgram.srcPixelFragShader)
+ && (prog.compositionFragShader == requiredProgram.compositionFragShader) )
+ {
+ currentShaderProg = prog.program;
+ currentShaderProg->enable();
+ shaderProgNeedsChanging = false;
+ return true;
+ }
+ }
+
+ // Shader program not found in cache, create it now.
+ requiredProgram.program = new QGLShaderProgram(ctx, this);
+ requiredProgram.program->addShader(requiredProgram.mainVertexShader);
+ requiredProgram.program->addShader(requiredProgram.positionVertexShader);
+ requiredProgram.program->addShader(requiredProgram.mainFragShader);
+ requiredProgram.program->addShader(requiredProgram.srcPixelFragShader);
+ requiredProgram.program->addShader(requiredProgram.maskFragShader);
+ requiredProgram.program->addShader(requiredProgram.compositionFragShader);
+
+ // We have to bind the vertex attribute names before the program is linked:
+ requiredProgram.program->bindAttributeLocation("vertexCoordsArray", QT_VERTEX_COORDS_ATTR);
+ if (useTextureCoords)
+ requiredProgram.program->bindAttributeLocation("textureCoordArray", QT_TEXTURE_COORDS_ATTR);
+
+ requiredProgram.program->link();
+ if (!requiredProgram.program->isLinked()) {
+ QString error;
+ qWarning() << "Shader program failed to link,"
+#if defined(QT_DEBUG)
+ << '\n'
+ << " Shaders Used:" << '\n'
+ << " mainVertexShader = " << requiredProgram.mainVertexShader->objectName() << '\n'
+ << " positionVertexShader = " << requiredProgram.positionVertexShader->objectName() << '\n'
+ << " mainFragShader = " << requiredProgram.mainFragShader->objectName() << '\n'
+ << " srcPixelFragShader = " << requiredProgram.srcPixelFragShader->objectName() << '\n'
+ << " maskFragShader = " << requiredProgram.maskFragShader->objectName() << '\n'
+ << " compositionFragShader = "<< requiredProgram.compositionFragShader->objectName() << '\n'
+#endif
+ << " Error Log:" << '\n'
+ << " " << requiredProgram.program->log();
+ qWarning() << error;
+ }
+ else {
+ cachedPrograms.append(requiredProgram);
+ currentShaderProg = requiredProgram.program;
+ currentShaderProg->enable();
+ }
+ shaderProgNeedsChanging = false;
+ return true;
+}
+
+void QGLEngineShaderManager::compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type)
+{
+ if (compiledShaders[name])
+ return;
+
+ QGLShader *newShader = new QGLShader(type, ctx, this);
+ newShader->compile(qglEngineShaderSourceCode[name]);
+
+#if defined(QT_DEBUG)
+ // Name the shader for easier debugging
+ QMetaEnum m = staticMetaObject.enumerator(staticMetaObject.indexOfEnumerator("ShaderName"));
+ newShader->setObjectName(QLatin1String(m.valueToKey(name)));
+#endif
+
+ compiledShaders[name] = newShader;
+}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager_p.h b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
new file mode 100644
index 0000000..4a55eca
--- /dev/null
+++ b/src/opengl/gl2paintengineex/qglengineshadermanager_p.h
@@ -0,0 +1,395 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+/*
+ VERTEX SHADERS
+ ==============
+
+ Vertex shaders are specified as multiple (partial) shaders. On desktop,
+ this works fine. On ES, QGLShader & QGLShaderProgram will make partial
+ shaders work by concatenating the source in each QGLShader and compiling
+ it as a single shader. This is abstracted nicely by QGLShaderProgram and
+ the GL2 engine doesn't need to worry about it.
+
+ Generally, there's two vertex shader objects. The position shaders are
+ the ones which set gl_Position. There's also two "main" vertex shaders,
+ one which just calls the position shader and another which also passes
+ through some texture coordinates from a vertex attribute array to a
+ varying. These texture coordinates are used for mask position in text
+ rendering and for the source coordinates in drawImage/drawPixmap. There's
+ also a "Simple" vertex shader for rendering a solid colour (used to render
+ into the stencil buffer where the actual colour value is discarded).
+
+ The position shaders for brushes look scary. This is because many of the
+ calculations which logically belong in the fragment shader have been moved
+ into the vertex shader to improve performance. This is why the position
+ calculation is in a seperate shader. Not only does it calculate the
+ position, but it also calculates some data to be passed to the fragment
+ shader as a varying. It is optimal to move as much of the calculation as
+ possible into the vertex shader as this is executed less often.
+
+ The varyings passed to the fragment shaders are interpolated (which is
+ cheap). Unfortunately, GL will apply perspective correction to the
+ interpolation calusing errors. To get around this, the vertex shader must
+ apply perspective correction itself and set the w-value of gl_Position to
+ zero. That way, GL will be tricked into thinking it doesn't need to apply a
+ perspective correction and use linear interpolation instead (which is what
+ we want). Of course, if the brush transform is affeine, no perspective
+ correction is needed and a simpler vertex shader can be used instead.
+
+ So there are the following "main" vertex shaders:
+ qglslMainVertexShader
+ qglslMainWithTexCoordsVertexShader
+
+ And the the following position vertex shaders:
+ qglslPositionOnlyVertexShader
+ qglslPositionWithTextureBrushVertexShader
+ qglslPositionWithPatternBrushVertexShader
+ qglslPositionWithLinearGradientBrushVertexShader
+ qglslPositionWithRadialGradientBrushVertexShader
+ qglslPositionWithConicalGradientBrushVertexShader
+ qglslAffinePositionWithTextureBrushVertexShader
+ qglslAffinePositionWithPatternBrushVertexShader
+ qglslAffinePositionWithLinearGradientBrushVertexShader
+ qglslAffinePositionWithRadialGradientBrushVertexShader
+ qglslAffinePositionWithConicalGradientBrushVertexShader
+
+ Leading to 23 possible vertex shaders
+
+
+ FRAGMENT SHADERS
+ ================
+
+ Fragment shaders are also specified as multiple (partial) shaders. The
+ different fragment shaders represent the different stages in Qt's fragment
+ pipeline. There are 1-3 stages in this pipeline: First stage is to get the
+ fragment's colour value. The next stage is to get the fragment's mask value
+ (coverage value for anti-aliasing) and the final stage is to blend the
+ incoming fragment with the background (for composition modes not supported
+ by GL).
+
+ Of these, the first stage will always be present. If Qt doesn't need to
+ apply anti-aliasing (because it's off or handled by multisampling) then
+ the coverage value doesn't need to be applied. (Note: There are two types
+ of mask, one for regular anti-aliasing and one for sub-pixel anti-
+ aliasing.) If the composition mode is one which GL supports natively then
+ the blending stage doesn't need to be applied.
+
+ As eash stage can have multiple implementations, they are abstracted as
+ GLSL function calls with the following signatures:
+
+ Brushes & image drawing are implementations of "qcolorp vec4 srcPixel()":
+ qglslImageSrcFragShader
+ qglslImageSrcWithPatternFragShader
+ qglslNonPremultipliedImageSrcFragShader
+ qglslSolidBrushSrcFragShader
+ qglslTextureBrushSrcFragShader
+ qglslTextureBrushWithPatternFragShader
+ qglslPatternBrushSrcFragShader
+ qglslLinearGradientBrushSrcFragShader
+ qglslRadialGradientBrushSrcFragShader
+ qglslConicalGradientBrushSrcFragShader
+ NOTE: It is assumed the colour returned by srcPixel() is pre-multiplied
+
+ Masks are implementations of "qcolorp vec4 applyMask(qcolorp vec4 src)":
+ qglslMaskFragmentShader
+ qglslRgbMaskFragmentShader
+ qglslRgbMaskWithGammaFragmentShader
+
+ Composition modes are "qcolorp vec4 compose(qcolorp vec4 src)":
+ qglslColorBurnCompositionModeFragmentShader
+ qglslColorDodgeCompositionModeFragmentShader
+ qglslDarkenCompositionModeFragmentShader
+ qglslDifferenceCompositionModeFragmentShader
+ qglslExclusionCompositionModeFragmentShader
+ qglslHardLightCompositionModeFragmentShader
+ qglslLightenCompositionModeFragmentShader
+ qglslMultiplyCompositionModeFragmentShader
+ qglslOverlayCompositionModeFragmentShader
+ qglslScreenCompositionModeFragmentShader
+ qglslSoftLightCompositionModeFragmentShader
+
+
+ Note: In the future, some GLSL compilers will support an extension allowing
+ a new 'color' precision specifier. To support this, qcolorp is used for
+ all color components so it can be defined to colorp or lowp depending upon
+ the implementation.
+
+ So there are differnt frament shader main functions, depending on the
+ number & type of pipelines the fragment needs to go through.
+
+ The choice of which main() fragment shader string to use depends on:
+ - Use of global opacity
+ - Brush style (some brushes apply opacity themselves)
+ - Use & type of mask (TODO: Need to support high quality anti-aliasing & text)
+ - Use of non-GL Composition mode
+
+ Leading to the following fragment shader main functions:
+ gl_FragColor = compose(applyMask(srcPixel()*globalOpacity));
+ gl_FragColor = compose(applyMask(srcPixel()));
+ gl_FragColor = applyMask(srcPixel()*globalOpacity);
+ gl_FragColor = applyMask(srcPixel());
+ gl_FragColor = compose(srcPixel()*globalOpacity);
+ gl_FragColor = compose(srcPixel());
+ gl_FragColor = srcPixel()*globalOpacity;
+ gl_FragColor = srcPixel();
+
+ Called:
+ qglslMainFragmentShader_CMO
+ qglslMainFragmentShader_CM
+ qglslMainFragmentShader_MO
+ qglslMainFragmentShader_M
+ qglslMainFragmentShader_CO
+ qglslMainFragmentShader_C
+ qglslMainFragmentShader_O
+ qglslMainFragmentShader
+
+ Where:
+ M = Mask
+ C = Composition
+ O = Global Opacity
+
+
+ CUSTOM SHADER CODE (idea, depricated)
+ ==================
+
+ The use of custom shader code is supported by the engine for drawImage and
+ drawPixmap calls. This is implemented via hooks in the fragment pipeline.
+ The custom shader is passed to the engine as a partial fragment shader
+ (QGLCustomizedShader). The shader will implement a pre-defined method name
+ which Qt's fragment pipeline will call. There are two different hooks which
+ can be implemented as custom shader code:
+
+ mediump vec4 customShader(sampler2d src, vec2 srcCoords)
+ mediump vec4 customShaderWithDest(sampler2d dest, sampler2d src, vec2 srcCoords)
+
+*/
+
+#ifndef QGLENGINE_SHADER_MANAGER_H
+#define QGLENGINE_SHADER_MANAGER_H
+
+#include <QGLShader>
+#include <QGLShaderProgram>
+#include <QPainter>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+
+struct QGLEngineShaderProg
+{
+ QGLShader* mainVertexShader;
+ QGLShader* positionVertexShader;
+ QGLShader* mainFragShader;
+ QGLShader* srcPixelFragShader;
+ QGLShader* maskFragShader; // Can be null for no mask
+ QGLShader* compositionFragShader; // Can be null for GL-handled mode
+ QGLShaderProgram* program;
+};
+
+/*
+struct QGLEngineCachedShaderProg
+{
+ QGLEngineCachedShaderProg(QGLEngineShaderManager::ShaderName vertexMain,
+ QGLEngineShaderManager::ShaderName vertexPosition,
+ QGLEngineShaderManager::ShaderName fragMain,
+ QGLEngineShaderManager::ShaderName pixelSrc,
+ QGLEngineShaderManager::ShaderName mask,
+ QGLEngineShaderManager::ShaderName composition);
+
+ int cacheKey;
+ QGLShaderProgram* program;
+}
+*/
+
+static const GLuint QT_VERTEX_COORDS_ATTR = 0;
+static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
+
+class QGLEngineShaderManager : public QObject
+{
+ Q_OBJECT
+public:
+ QGLEngineShaderManager(QGLContext* context);
+ ~QGLEngineShaderManager();
+
+ enum MaskType {NoMask, PixelMask, SubPixelMask, SubPixelWithGammaMask};
+ enum PixelSrcType {
+ ImageSrc = Qt::TexturePattern+1,
+ NonPremultipliedImageSrc = Qt::TexturePattern+2,
+ PatternSrc = Qt::TexturePattern+3,
+ TextureSrcWithPattern = Qt::TexturePattern+4
+ };
+
+ // There are optimisations we can do, depending on the brush transform:
+ // 1) May not have to apply perspective-correction
+ // 2) Can use lower precision for matrix
+ void optimiseForBrushTransform(const QTransform &transform);
+ void setSrcPixelType(Qt::BrushStyle);
+ void setSrcPixelType(PixelSrcType); // For non-brush sources, like pixmaps & images
+ void setTextureCoordsEnabled(bool); // For images & text glyphs
+ void setUseGlobalOpacity(bool);
+ void setMaskType(MaskType);
+ void setCompositionMode(QPainter::CompositionMode);
+
+ void setDirty(); // someone has manually changed the current shader program
+ bool useCorrectShaderProg(); // returns true if the shader program needed to be changed
+
+ QGLShaderProgram* currentProgram(); // Returns pointer to the shader the manager has chosen
+ QGLShaderProgram* simpleProgram(); // Used to draw into e.g. stencil buffers
+ QGLShaderProgram* blitProgram(); // Used to blit a texture into the framebuffer
+
+ enum ShaderName {
+ MainVertexShader,
+ MainWithTexCoordsVertexShader,
+
+ UntransformedPositionVertexShader,
+ PositionOnlyVertexShader,
+ PositionWithPatternBrushVertexShader,
+ PositionWithLinearGradientBrushVertexShader,
+ PositionWithConicalGradientBrushVertexShader,
+ PositionWithRadialGradientBrushVertexShader,
+ PositionWithTextureBrushVertexShader,
+ AffinePositionWithPatternBrushVertexShader,
+ AffinePositionWithLinearGradientBrushVertexShader,
+ AffinePositionWithConicalGradientBrushVertexShader,
+ AffinePositionWithRadialGradientBrushVertexShader,
+ AffinePositionWithTextureBrushVertexShader,
+
+ MainFragmentShader_CMO,
+ MainFragmentShader_CM,
+ MainFragmentShader_MO,
+ MainFragmentShader_M,
+ MainFragmentShader_CO,
+ MainFragmentShader_C,
+ MainFragmentShader_O,
+ MainFragmentShader,
+
+ ImageSrcFragmentShader,
+ ImageSrcWithPatternFragmentShader,
+ NonPremultipliedImageSrcFragmentShader,
+ SolidBrushSrcFragmentShader,
+ TextureBrushSrcFragmentShader,
+ TextureBrushSrcWithPatternFragmentShader,
+ PatternBrushSrcFragmentShader,
+ LinearGradientBrushSrcFragmentShader,
+ RadialGradientBrushSrcFragmentShader,
+ ConicalGradientBrushSrcFragmentShader,
+ ShockingPinkSrcFragmentShader,
+
+ MaskFragmentShader,
+ RgbMaskFragmentShader,
+ RgbMaskWithGammaFragmentShader,
+
+ MultiplyCompositionModeFragmentShader,
+ ScreenCompositionModeFragmentShader,
+ OverlayCompositionModeFragmentShader,
+ DarkenCompositionModeFragmentShader,
+ LightenCompositionModeFragmentShader,
+ ColorDodgeCompositionModeFragmentShader,
+ ColorBurnCompositionModeFragmentShader,
+ HardLightCompositionModeFragmentShader,
+ SoftLightCompositionModeFragmentShader,
+ DifferenceCompositionModeFragmentShader,
+ ExclusionCompositionModeFragmentShader,
+
+ TotalShaderCount, InvalidShaderName
+ };
+
+/*
+ // These allow the ShaderName enum to be used as a cache key
+ const int mainVertexOffset = 0;
+ const int positionVertexOffset = (1<<2) - PositionOnlyVertexShader;
+ const int mainFragOffset = (1<<6) - MainFragmentShader_CMO;
+ const int srcPixelOffset = (1<<10) - ImageSrcFragmentShader;
+ const int maskOffset = (1<<14) - NoMaskShader;
+ const int compositionOffset = (1 << 16) - MultiplyCompositionModeFragmentShader;
+*/
+
+#if defined (QT_DEBUG)
+ Q_ENUMS(ShaderName)
+#endif
+
+
+private:
+ QGLContext* ctx;
+ bool shaderProgNeedsChanging;
+
+ // Current state variables which influence the choice of shader:
+ QTransform brushTransform;
+ int srcPixelType;
+ bool useGlobalOpacity;
+ MaskType maskType;
+ bool useTextureCoords;
+ QPainter::CompositionMode compositionMode;
+
+ QGLShaderProgram* blitShaderProg;
+ QGLShaderProgram* simpleShaderProg;
+ QGLShaderProgram* currentShaderProg;
+
+ // TODO: Possibly convert to a LUT
+ QList<QGLEngineShaderProg> cachedPrograms;
+
+ QGLShader* compiledShaders[TotalShaderCount];
+
+ void compileNamedShader(QGLEngineShaderManager::ShaderName name, QGLShader::ShaderType type);
+
+ static const char* qglEngineShaderSourceCode[TotalShaderCount];
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QGLENGINE_SHADER_MANAGER_H
diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
new file mode 100644
index 0000000..61cc63e
--- /dev/null
+++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h
@@ -0,0 +1,417 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#ifndef QGL_ENGINE_SHADER_SOURCE_H
+#define QGL_ENGINE_SHADER_SOURCE_H
+
+#include "qglengineshadermanager_p.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+
+static const char* const qglslMainVertexShader = "\
+ void setPosition();\
+ void main(void)\
+ {\
+ setPosition();\
+ }";
+
+static const char* const qglslMainWithTexCoordsVertexShader = "\
+ attribute lowp vec2 textureCoordArray; \
+ varying lowp vec2 textureCoords; \
+ void setPosition();\
+ void main(void) \
+ {\
+ setPosition();\
+ textureCoords = textureCoordArray; \
+ }";
+
+
+static const char* const qglslPositionOnlyVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp mat4 pmvMatrix;\
+ uniform highp float depth;\
+ void setPosition(void)\
+ {\
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.z = depth;\
+ }";
+
+static const char* const qglslUntransformedPositionVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp float depth;\
+ void setPosition(void)\
+ {\
+ gl_Position = vertexCoordsArray;\
+ gl_Position.z = depth;\
+ }";
+
+// Pattern Brush - This assumes the texture size is 8x8 and thus, the inverted size is 0.125
+static const char* const qglslPositionWithPatternBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray; \
+ uniform highp mat4 pmvMatrix; \
+ uniform mediump vec2 halfViewportSize; \
+ uniform mediump vec2 invertedTextureSize; \
+ uniform mediump mat3 brushTransform; \
+ varying mediump vec2 patternTexCoords; \
+ uniform highp float depth;\
+ void setPosition(void) { \
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth;\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ patternTexCoords.xy = (hTexCoords.xy * 0.125) * invertedHTexCoordsZ; \
+ patternTexCoords.y = -patternTexCoords.y; \
+ }";
+
+static const char* const qglslAffinePositionWithPatternBrushVertexShader
+ = qglslPositionWithPatternBrushVertexShader;
+
+static const char* const qglslPatternBrushSrcFragmentShader = "\
+ uniform sampler2D brushTexture;\
+ uniform lowp vec4 patternColor; \
+ varying mediump vec2 patternTexCoords;\
+ lowp vec4 srcPixel() { \
+ return patternColor * (1.0 - texture2D(brushTexture, patternTexCoords).r); \
+ }\n";
+
+
+// Linear Gradient Brush
+static const char* const qglslPositionWithLinearGradientBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray; \
+ uniform highp mat4 pmvMatrix; \
+ uniform mediump vec2 halfViewportSize; \
+ uniform highp vec3 linearData; \
+ uniform highp mat3 brushTransform; \
+ varying mediump float index ; \
+ uniform highp float depth;\
+ void setPosition() { \
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth;\
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ index = (dot(linearData.xy, hTexCoords.xy) * linearData.z) * invertedHTexCoordsZ; \
+ }";
+
+static const char* const qglslAffinePositionWithLinearGradientBrushVertexShader
+ = qglslPositionWithLinearGradientBrushVertexShader;
+
+static const char* const qglslLinearGradientBrushSrcFragmentShader = "\
+ uniform sampler2D brushTexture; \
+ varying mediump float index; \
+ lowp vec4 srcPixel() { \
+ mediump vec2 val = vec2(index, 0.5); \
+ return texture2D(brushTexture, val); \
+ }\n";
+
+
+// Conical Gradient Brush
+static const char* const qglslPositionWithConicalGradientBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp mat4 pmvMatrix;\
+ uniform mediump vec2 halfViewportSize; \
+ uniform highp mat3 brushTransform; \
+ varying highp vec2 A; \
+ uniform highp float depth;\
+ void setPosition(void)\
+ {\
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ A = hTexCoords.xy * invertedHTexCoordsZ; \
+ }";
+
+static const char* const qglslAffinePositionWithConicalGradientBrushVertexShader
+ = qglslPositionWithConicalGradientBrushVertexShader;
+
+static const char* const qglslConicalGradientBrushSrcFragmentShader = "\n\
+ #define INVERSE_2PI 0.1591549430918953358 \n\
+ uniform sampler2D brushTexture; \n\
+ uniform mediump float angle; \
+ varying highp vec2 A; \
+ lowp vec4 srcPixel() { \
+ highp float t; \
+ if (abs(A.y) == abs(A.x)) \
+ t = (atan(-A.y + 0.002, A.x) + angle) * INVERSE_2PI; \
+ else \
+ t = (atan(-A.y, A.x) + angle) * INVERSE_2PI; \
+ return texture2D(brushTexture, vec2(t - floor(t), 0.5)); \
+ }";
+
+
+// Radial Gradient Brush
+static const char* const qglslPositionWithRadialGradientBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray;\
+ uniform highp mat4 pmvMatrix;\
+ uniform mediump vec2 halfViewportSize; \
+ uniform highp mat3 brushTransform; \
+ uniform highp vec2 fmp; \
+ varying highp float b; \
+ varying highp vec2 A; \
+ uniform highp float depth;\
+ void setPosition(void) \
+ {\
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ A = hTexCoords.xy * invertedHTexCoordsZ; \
+ b = 2.0 * dot(A, fmp); \
+ }";
+
+static const char* const qglslAffinePositionWithRadialGradientBrushVertexShader
+ = qglslPositionWithRadialGradientBrushVertexShader;
+
+static const char* const qglslRadialGradientBrushSrcFragmentShader = "\
+ uniform sampler2D brushTexture; \
+ uniform highp float fmp2_m_radius2; \
+ uniform highp float inverse_2_fmp2_m_radius2; \
+ varying highp float b; \
+ varying highp vec2 A; \
+ lowp vec4 srcPixel() { \
+ highp float c = -dot(A, A); \
+ highp vec2 val = vec2((-b + sqrt(b*b - 4.0*fmp2_m_radius2*c)) * inverse_2_fmp2_m_radius2, 0.5); \
+ return texture2D(brushTexture, val); \
+ }";
+
+
+// Texture Brush
+static const char* const qglslPositionWithTextureBrushVertexShader = "\
+ attribute highp vec4 vertexCoordsArray; \
+ uniform highp mat4 pmvMatrix; \
+ uniform mediump vec2 halfViewportSize; \
+ uniform mediump vec2 invertedTextureSize; \
+ uniform mediump mat3 brushTransform; \
+ varying mediump vec2 brushTextureCoords; \
+ uniform highp float depth;\
+ void setPosition(void) { \
+ gl_Position = pmvMatrix * vertexCoordsArray;\
+ gl_Position.xy = gl_Position.xy / gl_Position.w; \
+ gl_Position.z = depth; \
+ mediump vec2 viewportCoords = (gl_Position.xy + 1.0) * halfViewportSize; \
+ mediump vec3 hTexCoords = brushTransform * vec3(viewportCoords, 1); \
+ mediump float invertedHTexCoordsZ = 1.0 / hTexCoords.z; \
+ gl_Position.xy = gl_Position.xy * invertedHTexCoordsZ; \
+ gl_Position.w = invertedHTexCoordsZ; \
+ brushTextureCoords.xy = (hTexCoords.xy * invertedTextureSize) * gl_Position.w; \
+ brushTextureCoords.y = -brushTextureCoords.y; \
+ }";
+
+static const char* const qglslAffinePositionWithTextureBrushVertexShader
+ = qglslPositionWithTextureBrushVertexShader;
+
+static const char* const qglslTextureBrushSrcFragmentShader = "\
+ varying mediump vec2 brushTextureCoords; \
+ uniform sampler2D brushTexture; \
+ lowp vec4 srcPixel() { \
+ return texture2D(brushTexture, brushTextureCoords); \
+ }";
+
+static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\
+ varying mediump vec2 brushTextureCoords; \
+ uniform lowp vec4 patternColor; \
+ uniform sampler2D brushTexture; \
+ lowp vec4 srcPixel() { \
+ return patternColor * (1.0 - texture2D(brushTexture, brushTextureCoords).r); \
+ }";
+
+// Solid Fill Brush
+static const char* const qglslSolidBrushSrcFragmentShader = "\
+ uniform lowp vec4 fragmentColor; \
+ lowp vec4 srcPixel() { \
+ return fragmentColor; \
+ }";
+
+static const char* const qglslImageSrcFragmentShader = "\
+ varying highp vec2 textureCoords; \
+ uniform sampler2D imageTexture; \
+ lowp vec4 srcPixel() { \
+ return texture2D(imageTexture, textureCoords); \
+ }";
+
+static const char* const qglslImageSrcWithPatternFragmentShader = "\
+ varying highp vec2 textureCoords; \
+ uniform lowp vec4 patternColor; \
+ uniform sampler2D imageTexture; \
+ lowp vec4 srcPixel() { \
+ return patternColor * (1.0 - texture2D(imageTexture, textureCoords).r); \
+ }\n";
+
+static const char* const qglslNonPremultipliedImageSrcFragmentShader = "\
+ varying highp vec2 textureCoords; \
+ uniform sampler2D imageTexture; \
+ lowp vec4 srcPixel() { \
+ lowp vec4 sample = texture2D(imageTexture, textureCoords); \
+ sample.rgb = sample.rgb * sample.a; \
+ return sample; \
+ }";
+
+static const char* const qglslShockingPinkSrcFragmentShader = "\
+ lowp vec4 srcPixel() { \
+ return vec4(0.98, 0.06, 0.75, 1.0); \
+ }";
+
+
+static const char* const qglslMainFragmentShader_CMO = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = applyMask(compose(srcPixel()*globalOpacity))); \
+ }";
+
+static const char* const qglslMainFragmentShader_CM = "\
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = applyMask(compose(srcPixel())); \
+ }";
+
+static const char* const qglslMainFragmentShader_MO = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ void main() { \
+ gl_FragColor = applyMask(srcPixel()*globalOpacity); \
+ }";
+
+static const char* const qglslMainFragmentShader_M = "\
+ lowp vec4 srcPixel(); \
+ lowp vec4 applyMask(lowp vec4); \
+ void main() { \
+ gl_FragColor = applyMask(srcPixel()); \
+ }";
+
+static const char* const qglslMainFragmentShader_CO = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = compose(srcPixel()*globalOpacity); \
+ }";
+
+static const char* const qglslMainFragmentShader_C = "\
+ lowp vec4 srcPixel(); \
+ lowp vec4 compose(lowp vec4); \
+ void main() { \
+ gl_FragColor = compose(srcPixel()); \
+ }";
+
+static const char* const qglslMainFragmentShader_O = "\
+ uniform lowp float globalOpacity; \
+ lowp vec4 srcPixel(); \
+ void main() { \
+ gl_FragColor = srcPixel()*globalOpacity; \
+ }";
+
+static const char* const qglslMainFragmentShader = "\
+ lowp vec4 srcPixel(); \
+ void main() { \
+ gl_FragColor = srcPixel(); \
+ }";
+
+static const char* const qglslMaskFragmentShader = "\
+ varying highp vec2 textureCoords;\
+ uniform sampler2D maskTexture;\
+ lowp vec4 applyMask(lowp vec4 src) \
+ {\
+ lowp vec4 mask = texture2D(maskTexture, textureCoords); \
+ return src * mask.a; \
+ }";
+
+/*
+ Left to implement:
+ RgbMaskFragmentShader,
+ RgbMaskWithGammaFragmentShader,
+
+ MultiplyCompositionModeFragmentShader,
+ ScreenCompositionModeFragmentShader,
+ OverlayCompositionModeFragmentShader,
+ DarkenCompositionModeFragmentShader,
+ LightenCompositionModeFragmentShader,
+ ColorDodgeCompositionModeFragmentShader,
+ ColorBurnCompositionModeFragmentShader,
+ HardLightCompositionModeFragmentShader,
+ SoftLightCompositionModeFragmentShader,
+ DifferenceCompositionModeFragmentShader,
+ ExclusionCompositionModeFragmentShader,
+*/
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // GLGC_SHADER_SOURCE_H
diff --git a/src/opengl/gl2paintengineex/qglgradientcache.cpp b/src/opengl/gl2paintengineex/qglgradientcache.cpp
index b4591b2..f1a8850 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache.cpp
+++ b/src/opengl/gl2paintengineex/qglgradientcache.cpp
@@ -44,7 +44,9 @@
#include "qglgradientcache_p.h"
-void QGLGradientCache::cleanCache() {
+QT_BEGIN_NAMESPACE
+
+void QGL2GradientCache::cleanCache() {
QGLGradientColorTableHash::const_iterator it = cache.constBegin();
for (; it != cache.constEnd(); ++it) {
const CacheInfo &cache_info = it.value();
@@ -53,7 +55,7 @@ void QGLGradientCache::cleanCache() {
cache.clear();
}
-GLuint QGLGradientCache::getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx)
+GLuint QGL2GradientCache::getBuffer(const QGradient &gradient, qreal opacity, const QGLContext *ctx)
{
if (buffer_ctx && !qgl_share_reg()->checkSharing(buffer_ctx, ctx))
cleanCache();
@@ -84,7 +86,7 @@ GLuint QGLGradientCache::getBuffer(const QGradient &gradient, qreal opacity, con
}
-GLuint QGLGradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
+GLuint QGL2GradientCache::addCacheElement(quint64 hash_val, const QGradient &gradient, qreal opacity)
{
if (cache.size() == maxCacheSize()) {
int elem_to_remove = qrand() % maxCacheSize();
@@ -109,34 +111,31 @@ GLuint QGLGradientCache::addCacheElement(quint64 hash_val, const QGradient &grad
}
-// GL's expects pixels in RGBA, bin-endian (ABGR on x86).
-// Qt stores in ARGB using whatever byte-order the mancine uses.
+// GL's expects pixels in RGBA (when using GL_RGBA), bin-endian (ABGR on x86).
+// Qt always stores in ARGB reguardless of the byte-order the mancine uses.
static inline uint qtToGlColor(uint c)
{
uint o;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- o = c & 0xFF00FF00; // alpha & green already in the right place
- o |= (c >> 16) & 0x000000FF; // red
- o |= (c << 16) & 0x00FF0000; // blue
-
+ o = (c & 0xff00ff00) // alpha & green already in the right place
+ | ((c >> 16) & 0x000000ff) // red
+ | ((c << 16) & 0x00ff0000); // blue
#else //Q_BIG_ENDIAN
- o = c & 0x00FF00FF; // alpha & green already in the right place
- o |= (c << 16) & 0xFF000000; // red
- o |= (c >> 16) & 0x0000FF00; // blue
-#error big endian not tested with QGLGraphicsContext
+ o = (c << 8)
+ | ((c >> 24) & 0x000000ff);
#endif // Q_BYTE_ORDER
return o;
}
//TODO: Let GL generate the texture using an FBO
-void QGLGradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
+void QGL2GradientCache::generateGradientColorTable(const QGradient& gradient, uint *colorTable, int size, qreal opacity) const
{
int pos = 0;
QGradientStops s = gradient.stops();
QVector<uint> colors(s.size());
for (int i = 0; i < s.size(); ++i)
- colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB
+ colors[i] = s[i].second.rgba(); // Qt LIES! It returns ARGB (on little-endian AND on big-endian)
bool colorInterpolation = (gradient.interpolationMode() == QGradient::ColorInterpolation);
@@ -183,3 +182,5 @@ void QGLGradientCache::generateGradientColorTable(const QGradient& gradient, uin
// Make sure the last color stop is represented at the end of the table
colorTable[size-1] = last_color;
}
+
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglgradientcache_p.h b/src/opengl/gl2paintengineex/qglgradientcache_p.h
index 346ea13..f088359 100644
--- a/src/opengl/gl2paintengineex/qglgradientcache_p.h
+++ b/src/opengl/gl2paintengineex/qglgradientcache_p.h
@@ -52,9 +52,11 @@
#include <QMultiHash>
#include <QObject>
-#include <QtOpenGL>
+#include <QtOpenGL/QtOpenGL>
-class QGLGradientCache : public QObject
+QT_BEGIN_NAMESPACE
+
+class QGL2GradientCache : public QObject
{
Q_OBJECT
struct CacheInfo
@@ -71,7 +73,7 @@ class QGLGradientCache : public QObject
typedef QMultiHash<quint64, CacheInfo> QGLGradientColorTableHash;
public:
- QGLGradientCache() : QObject(), buffer_ctx(0)
+ QGL2GradientCache() : QObject(), buffer_ctx(0)
{
/*
connect(QGLSignalProxy::instance(),
@@ -104,5 +106,5 @@ public slots:
}
};
-
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qglpexshadermanager.cpp b/src/opengl/gl2paintengineex/qglpexshadermanager.cpp
deleted file mode 100644
index e460e08..0000000
--- a/src/opengl/gl2paintengineex/qglpexshadermanager.cpp
+++ /dev/null
@@ -1,450 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qglpexshadermanager_p.h"
-
-#include "glgc_shader_source.h"
-
-QGLPEXShaderManager::QGLPEXShaderManager(const QGLContext* context)
-{
- ctx = const_cast<QGLContext*>(context);
-
- defaultVertexShader= new QGLShader(QGLShader::VertexShader, context);
- defaultVertexShader->addSource(QLatin1String(qglslDefaultVertexShader));
- if (!defaultVertexShader->compile())
- qWarning() << "Default vertex shader failed to compile: " << defaultVertexShader->log();
-
- noBrushShader = new QGLShader(QGLShader::FragmentShader, context);
- noBrushShader->addSource(QLatin1String(qglslFragmentShaderMain));
- noBrushShader->addSource(QLatin1String(qglslNoBrushFragmentShader));
- if (!noBrushShader->compile())
- qWarning() << "No brush shader failed to compile:" << noBrushShader->log();
-
-
- // Create a program for noBrush:
- QGLShaderProgram* noBrushProg = new QGLShaderProgram(ctx);
- noBrushProg->addShader(defaultVertexShader);
- noBrushProg->addShader(noBrushShader);
- if (!noBrushProg->link())
- qWarning() << "NoBrush shader program failed to link:" << noBrushProg->log();
-
- // Add noBrush Program to cache:
- QGLCachedShaderProg cachedProg;
- cachedProg.vertexShader = defaultVertexShader;
- cachedProg.brushShader = noBrushShader;
- cachedProg.compositionShader = 0;
- cachedProg.shader = noBrushProg;
- cachedPrograms.append(cachedProg);
-
-
- // Set state
- useGlobalOpacity = true;
- currentBrushStyle = Qt::NoBrush;
- currentTransformType = FullTransform;
- shaderProgNeedsChanging = false;
- activeProgram = noBrushProg;
-
- solidBrushShader = 0;
-
- conicalBrushVertexShader = 0;
- conicalBrushFragmentShader = 0;
-
- radialBrushVertexShader = 0;
- radialBrushFragmentShader = 0;
-
- linearBrushVertexShader = 0;
- linearBrushFragmentShader = 0;
-
- patternBrushVertexShader = 0;
- patternBrushFragmentShader = 0;
-
- textureBrushFragmentShader = 0;
- textureBrushVertexShader = 0;
-
- simpleFragmentShader = 0;
- simpleShaderProgram = 0;
-
- imageVertexShader = 0;
- imageFragmentShader = 0;
- imageShaderProgram = 0;
-
- textVertexShader = 0;
- textFragmentShader = 0;
- textShaderProgram = 0;
-}
-
-QGLPEXShaderManager::~QGLPEXShaderManager()
-{
- delete defaultVertexShader;
- delete imageVertexShader;
- delete imageFragmentShader;
- delete imageShaderProgram;
- delete textVertexShader;
- delete textFragmentShader;
- delete textShaderProgram;
- delete noBrushShader;
- delete solidBrushShader;
-
- delete conicalBrushVertexShader;
- delete conicalBrushFragmentShader;
-
- delete radialBrushVertexShader;
- delete radialBrushFragmentShader;
-
- delete linearBrushFragmentShader;
- delete linearBrushVertexShader;
-
- delete patternBrushFragmentShader;
- delete patternBrushVertexShader;
-
- delete textureBrushFragmentShader;
- delete textureBrushVertexShader;
-
- delete simpleFragmentShader;
- delete simpleShaderProgram;
-}
-
-void QGLPEXShaderManager::setUseGlobalOpacity(bool value)
-{
- if (value != useGlobalOpacity)
- shaderProgNeedsChanging = true;
-
- useGlobalOpacity = value;
-}
-
-void QGLPEXShaderManager::setBrushStyle(Qt::BrushStyle style)
-{
- if (currentBrushStyle != style)
- shaderProgNeedsChanging = true;
-
- currentBrushStyle = style;
-}
-
-void QGLPEXShaderManager::setAffineOnlyBrushTransform(bool value)
-{
- Q_UNUSED(value);
- // TODO
-}
-
-bool QGLPEXShaderManager::useCorrectShaderProg()
-{
- if (!shaderProgNeedsChanging) {
- activeProgram->use();
- return false;
- }
-
- const char* fragmentShaderMainSrc = qglslFragmentShaderMain;
- QGLShader* vertexShader = defaultVertexShader;
- QGLShader* fragmentShader = noBrushShader;
-
- // Make sure we compile up the correct brush shader
- switch (currentBrushStyle) {
- case Qt::NoBrush:
- break;
- case Qt::SolidPattern:
- if (!solidBrushShader) {
- qDebug("Compiling qglslSolidBrushFragmentShader");
- solidBrushShader = new QGLShader(QGLShader::FragmentShader, ctx);
- solidBrushShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain));
- solidBrushShader->addSource(QLatin1String(qglslSolidBrushFragmentShader));
- if (!solidBrushShader->compile())
- qWarning() << "qglslSolidBrush failed to compile:" << solidBrushShader->log();
- }
- fragmentShader = solidBrushShader;
- break;
- case Qt::TexturePattern:
- if (!textureBrushVertexShader) {
- qDebug("Compiling qglslTextureBrushVertexShader");
- textureBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- textureBrushVertexShader->addSource(QLatin1String(qglslTextureBrushVertexShader));
- if (!textureBrushVertexShader->compile()) {
- qWarning() << "qglslTextureBrushVertexShader failed to compile: "
- << textureBrushVertexShader->log();
- }
- }
- vertexShader = textureBrushVertexShader;
-
- if (!textureBrushFragmentShader) {
- qDebug("Compiling qglslTextureBrushFragmentShader");
- textureBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- textureBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- textureBrushFragmentShader->addSource(QLatin1String(qglslTextureBrushFragmentShader));
- if (!textureBrushFragmentShader->compile()) {
- qWarning() << "qglslTextureBrushFragmentShader failed to compile:"
- << textureBrushFragmentShader->log();
- }
- }
- fragmentShader = textureBrushFragmentShader;
- break;
- case Qt::LinearGradientPattern:
- if (!linearBrushVertexShader) {
- qDebug("Compiling qglslLinearGradientBrushVertexShader");
- linearBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- linearBrushVertexShader->addSource(QLatin1String(qglslLinearGradientBrushVertexShader));
- if (!linearBrushVertexShader->compile()) {
- qWarning() << "qglslLinearGradientBrushVertexShader failed to compile: "
- << linearBrushVertexShader->log();
- }
- }
- vertexShader = linearBrushVertexShader;
-
- if (!linearBrushFragmentShader) {
- qDebug("Compiling qglslLinearGradientBrushFragmentShader");
- linearBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- linearBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- linearBrushFragmentShader->addSource(QLatin1String(qglslLinearGradientBrushFragmentShader));
- if (!linearBrushFragmentShader->compile()) {
- qWarning() << "qglslLinearGradientBrushFragmentShader failed to compile:"
- << linearBrushFragmentShader->log();
- }
- }
- fragmentShader = linearBrushFragmentShader;
- break;
- case Qt::RadialGradientPattern:
- if (!radialBrushVertexShader) {
- qDebug("Compiling qglslRadialGradientBrushVertexShader");
- radialBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- radialBrushVertexShader->addSource(QLatin1String(qglslRadialGradientBrushVertexShader));
- if (!radialBrushVertexShader->compile()) {
- qWarning() << "qglslRadialGradientBrushVertexShader failed to compile: "
- << radialBrushVertexShader->log();
- }
- }
- vertexShader = radialBrushVertexShader;
-
- if (!radialBrushFragmentShader) {
- qDebug("Compiling qglslRadialGradientBrushFragmentShader");
- radialBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- radialBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- radialBrushFragmentShader->addSource(QLatin1String(qglslRadialGradientBrushFragmentShader));
- if (!radialBrushFragmentShader->compile()) {
- qWarning() << "qglslRadialGradientBrushFragmentShader failed to compile:"
- << radialBrushFragmentShader->log();
- }
- }
- fragmentShader = radialBrushFragmentShader;
- break;
- case Qt::ConicalGradientPattern:
- // FIXME: We currently use the same vertex shader as radial brush
- if (!conicalBrushVertexShader) {
- qDebug("Compiling qglslConicalGradientBrushVertexShader");
- conicalBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- conicalBrushVertexShader->addSource(QLatin1String(qglslConicalGradientBrushVertexShader));
- if (!conicalBrushVertexShader->compile()) {
- qWarning() << "qglslConicalGradientBrushVertexShader failed to compile: "
- << conicalBrushVertexShader->log();
- }
- }
- vertexShader = conicalBrushVertexShader;
-
- if (!conicalBrushFragmentShader) {
- qDebug("Compiling qglslConicalGradientBrushFragmentShader");
- conicalBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- conicalBrushFragmentShader->addSource(QLatin1String(fragmentShaderMainSrc));
- conicalBrushFragmentShader->addSource(QLatin1String(qglslConicalGradientBrushFragmentShader));
- if (!conicalBrushFragmentShader->compile()) {
- qWarning() << "qglslConicalGradientBrushFragmentShader failed to compile:"
- << conicalBrushFragmentShader->log();
- }
- }
- fragmentShader = conicalBrushFragmentShader;
- break;
- case Qt::Dense1Pattern:
- case Qt::Dense2Pattern:
- case Qt::Dense3Pattern:
- case Qt::Dense4Pattern:
- case Qt::Dense5Pattern:
- case Qt::Dense6Pattern:
- case Qt::Dense7Pattern:
- case Qt::HorPattern:
- case Qt::VerPattern:
- case Qt::CrossPattern:
- case Qt::BDiagPattern:
- case Qt::FDiagPattern:
- case Qt::DiagCrossPattern:
- if (!patternBrushVertexShader) {
- qDebug("Compiling qglslPatternBrushVertexShader");
- patternBrushVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- patternBrushVertexShader->addSource(QLatin1String(qglslPatternBrushVertexShader));
- if (!patternBrushVertexShader->compile()) {
- qWarning() << "qglslPatternBrushVertexShader failed to compile: "
- << patternBrushVertexShader->log();
- }
- }
- vertexShader = patternBrushVertexShader;
-
- if (!patternBrushFragmentShader) {
- qDebug("Compiling qglslPatternBrushFragmentShader");
- patternBrushFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- patternBrushFragmentShader->addSource(QLatin1String(qglslNoOpacityFragmentShaderMain));
- patternBrushFragmentShader->addSource(QLatin1String(qglslPatternBrushFragmentShader));
- if (!patternBrushFragmentShader->compile()) {
- qWarning() << "qglslPatternBrushFragmentShader failed to compile:"
- << patternBrushFragmentShader->log();
- }
- }
- fragmentShader = patternBrushFragmentShader;
- break;
- default:
- qWarning("Unimplemented brush style (%d)", currentBrushStyle);
- }
-
- // Now newBrushShader is set correctly, check to see if we already have the program
- // already linked and ready to go in the cache:
- bool foundProgram = false;
- foreach (QGLCachedShaderProg cachedProg, cachedPrograms) {
- if ((cachedProg.vertexShader == vertexShader) &&
- (cachedProg.brushShader == fragmentShader) &&
- (cachedProg.compositionShader == 0) ) {
-
- activeProgram = cachedProg.shader;
- foundProgram = true;
- break;
- }
- }
-
- if (!foundProgram) {
- qDebug() << "Linking shader program for " << currentBrushStyle;
- // Required program not found - create it.
- QGLShaderProgram* newProg = new QGLShaderProgram(ctx);
-
- newProg->addShader(vertexShader);
- newProg->addShader(fragmentShader);
-
- if (!newProg->link())
- qWarning() << "Shader program for " << currentBrushStyle << "failed to link:" << newProg->log();
-
- QGLCachedShaderProg cachedProg;
- cachedProg.vertexShader = vertexShader;
- cachedProg.brushShader = fragmentShader;
- cachedProg.compositionShader = 0;
- cachedProg.shader = newProg;
-
- cachedPrograms.append(cachedProg);
- activeProgram = newProg;
- }
-
- activeProgram->use();
- shaderProgNeedsChanging = false;
- return true;
-}
-
-QGLShaderProgram* QGLPEXShaderManager::brushShader()
-{
- return activeProgram;
-}
-
-// The only uniform the simple shader has is the PMV matrix
-QGLShaderProgram* QGLPEXShaderManager::simpleShader()
-{
- if (!simpleShaderProgram) {
- simpleShaderProgram = new QGLShaderProgram(ctx);
-
- if (!simpleFragmentShader) {
- simpleFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- simpleFragmentShader->addSource(QLatin1String(qglslSimpleFragmentShader));
- if (!simpleFragmentShader->compile())
- qWarning() << "qglslSimpleFragmentShader failed to compile:" << simpleFragmentShader->log();
- }
-
- simpleShaderProgram->addShader(defaultVertexShader);
- simpleShaderProgram->addShader(simpleFragmentShader);
- if (!simpleShaderProgram->link())
- qWarning() << "Simple shader program failed to link:" << simpleShaderProgram->log();
- }
-
- return simpleShaderProgram;
-}
-
-QGLShaderProgram* QGLPEXShaderManager::imageShader()
-{
- if (!imageShaderProgram) {
- if (!imageVertexShader) {
- imageVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- imageVertexShader->addSource(QLatin1String(qglslImageVertexShader));
- if (!imageVertexShader->compile())
- qWarning() << "Image/Pixmap vertex shader failed to compile:" << imageVertexShader->log();
- }
-
- if (!imageFragmentShader) {
- imageFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- imageFragmentShader->addSource(QLatin1String(qglslImageFragmentShader));
- if (!imageFragmentShader->compile())
- qWarning() << "Image/Pixmap fragment shader failed to compile:" << imageFragmentShader->log();
- }
-
- imageShaderProgram = new QGLShaderProgram(ctx);
- imageShaderProgram->addShader(imageVertexShader);
- imageShaderProgram->addShader(imageFragmentShader);
- if (!imageShaderProgram->link())
- qWarning() << "Image/Pixmap shader program failed to link:" << imageShaderProgram->log();
- }
-
- return imageShaderProgram;
-}
-
-QGLShaderProgram* QGLPEXShaderManager::textShader()
-{
- if (!textShaderProgram) {
- if (!textVertexShader) {
- textVertexShader = new QGLShader(QGLShader::VertexShader, ctx);
- textVertexShader->addSource(QLatin1String(qglslImageVertexShader));
- if (!textVertexShader->compile())
- qWarning() << "Text vertex shader failed to compile:" << textVertexShader->log();
- }
-
- if (!textFragmentShader) {
- textFragmentShader = new QGLShader(QGLShader::FragmentShader, ctx);
- textFragmentShader->addSource(QLatin1String(qglslTextFragmentShader));
- if (!textFragmentShader->compile())
- qWarning() << "Text fragment shader failed to compile:" << textFragmentShader->log();
- }
-
- textShaderProgram = new QGLShaderProgram(ctx);
- textShaderProgram->addShader(textVertexShader);
- textShaderProgram->addShader(textFragmentShader);
- if (!textShaderProgram->link())
- qWarning() << "Text shader program failed to link:" << textShaderProgram->log();
- }
-
- return textShaderProgram;
-}
-
diff --git a/src/opengl/gl2paintengineex/qglpexshadermanager_p.h b/src/opengl/gl2paintengineex/qglpexshadermanager_p.h
deleted file mode 100644
index c8f47b2..0000000
--- a/src/opengl/gl2paintengineex/qglpexshadermanager_p.h
+++ /dev/null
@@ -1,156 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qglshader_p.h"
-
-
-// Worstcase combo: Brush->Mask->Composition
-
-/*
- Vertex shader source is specified with a single string. This string
- contains the main function and sets the gl_Position. The choice of
- which vertex shader to use depends on:
- - Brush style
- - Brush transform->isAffine()
-
- Fragment shaders are specified as multiple strings, one for the main
- function, one for the brush calculation and optionally one for the
- extended composition mode. Brushes are implementations of
- "mediump vec4 brush()"
- Composition modes are implemented as a
- "mediump vec4 compose(mediump vec4 color)"
- NOTE: Precision may change in future.
-
- The choice of which main() fragment shader string to use depends on:
- - Global opacity
- - Brush style (some brushes apply opacity themselves)
- - Use of mask (TODO: Need to support high quality anti-aliasing & text)
- - Composition mode
-
- The choice of which brush() fragment shader to use depends on:
- - Brush style
-
-*/
-
-
-struct QGLCachedShaderProg
-{
- QGLShader* vertexShader;
- QGLShader* brushShader;
- QGLShader* compositionShader;
- QGLShaderProgram* shader;
-};
-
-class QGLPEXShaderManager
-{
-public:
- QGLPEXShaderManager(const QGLContext* context);
- ~QGLPEXShaderManager();
-
- enum TransformType {IdentityTransform, ScaleTransform, TranslateTransform, FullTransform};
-
- void optimiseForBrushTransform(const QTransform& transform);
- void setBrushStyle(Qt::BrushStyle style);
- void setUseGlobalOpacity(bool value);
- void setAffineOnlyBrushTransform(bool value); // I.e. Do we need to apply perspective-correction?
- // Not doing so saves some vertex shader calculations.
-
- bool useCorrectShaderProg(); // returns true if the shader program has changed
-
- QGLShaderProgram* brushShader();
- QGLShaderProgram* simpleShader(); // Used to draw into e.g. stencil buffers
- QGLShaderProgram* imageShader();
- QGLShaderProgram* textShader();
-
-private:
- QGLShader* defaultVertexShader;
-
- QGLShader* imageVertexShader;
- QGLShader* imageFragmentShader;
- QGLShaderProgram* imageShaderProgram;
-
- QGLShader* textVertexShader;
- QGLShader* textFragmentShader;
- QGLShaderProgram* textShaderProgram;
-
- QGLShader* noBrushShader;
- QGLShader* solidBrushShader;
-
- QGLShader* conicalBrushVertexShader;
- QGLShader* conicalBrushFragmentShader;
-
- QGLShader* radialBrushVertexShader;
- QGLShader* radialBrushFragmentShader;
-
- QGLShader* linearBrushVertexShader;
- QGLShader* linearBrushFragmentShader;
-
- QGLShader* patternBrushVertexShader;
- QGLShader* patternBrushFragmentShader;
-
- QGLShader* textureBrushFragmentShader;
- QGLShader* textureBrushVertexShader;
-
- QGLShader* simpleFragmentShader;
- QGLShaderProgram* simpleShaderProgram;
-
- QGLShaderProgram* activeProgram;
-
- Qt::BrushStyle currentBrushStyle;
- bool useGlobalOpacity;
- TransformType currentTransformType;
- bool shaderProgNeedsChanging;
-
- QList<QGLCachedShaderProg> cachedPrograms;
-
- QGLContext* ctx;
-};
diff --git a/src/opengl/gl2paintengineex/qglshader.cpp b/src/opengl/gl2paintengineex/qglshader.cpp
deleted file mode 100644
index 634be84..0000000
--- a/src/opengl/gl2paintengineex/qglshader.cpp
+++ /dev/null
@@ -1,605 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qglshader_p.h"
-
-
-// Windows needs to resolve OpenGL 2.0 function pointers for each context. The
-// QGL OpenGL 2.0 functions are actually macros, which take a "ctx" parameter.
-#define Q_CTX QGLContext* ctx = d->ctx; \
- if (!ctx) \
- return false; \
- ctx->makeCurrent(); \
-
-
-
-
-class QGLShaderPrivate
-{
-public:
- QGLShaderPrivate() : shaderId(0), valid(false), ctx(0) {}
-
- GLuint shaderId;
- QString source;
- bool valid;
- QGLShader::ShaderType type;
- QGLContext* ctx;
-};
-
-
-QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext* ctx)
- : d_ptr(new QGLShaderPrivate)
-{
- Q_D(QGLShader);
-
- if (!ctx)
- ctx = QGLContext::currentContext();
-
- if (!ctx) {
- qWarning("QGLShader being created without a context");
- return;
- }
-
- d->ctx = const_cast<QGLContext*>(ctx);
- d->ctx->makeCurrent();
-
- if (type == QGLShader::FragmentShader)
- d->shaderId = glCreateShader(GL_FRAGMENT_SHADER);
- else
- d->shaderId = glCreateShader(GL_VERTEX_SHADER);
-
- if (d->shaderId == 0) {
- qWarning("Error creating shader object");
- return;
- }
-
- d->type = type;
-}
-
-GLuint QGLShader::id()
-{
- Q_D(QGLShader);
- return d->shaderId;
-}
-
-const QGLContext* QGLShader::context()
-{
- Q_D(QGLShader);
- return d->ctx;
-}
-
-void QGLShader::clearSource()
-{
- Q_D(QGLShader);
- d->source.clear();
- d->valid = false;
-}
-
-void QGLShader::addSource(const QLatin1String& newSource)
-{
- Q_D(QGLShader);
- d->source += newSource;
- d->valid = false;
-}
-
-
-bool QGLShader::compile()
-{
- Q_D(QGLShader);
-
- d->valid = false;
-
- if (d->source.size() == 0)
- return false;
-
- const QByteArray src_ba = d->source.toAscii();
- const char* src = src_ba.constData();
-
- glShaderSource(d->shaderId, 1, &src, 0);
-
- glCompileShader(d->shaderId);
-
- GLint shaderCompiled;
- glGetShaderiv(d->shaderId, GL_COMPILE_STATUS, &shaderCompiled);
- if (!shaderCompiled)
- return false;
-
- d->valid = true;
- return true;
-}
-
-bool QGLShader::isValid()
-{
- Q_D(QGLShader);
- return d->valid;
-}
-
-QString QGLShader::log()
-{
- Q_D(QGLShader);
-
- char* logData;
- GLint logSize;
- GLint logLength;
-
- glGetShaderiv(d->shaderId, GL_INFO_LOG_LENGTH, &logSize);
-
- if (!logSize)
- return QString();
-
- logData = new char[logSize];
- glGetShaderInfoLog(d->shaderId, logSize, &logLength, logData);
- QString result = QString::fromAscii(logData);
- delete [] logData;
-
- return result;
-}
-
-
-
-
-
-
-
-
-
-
-
-
-class QGLShaderProgramPrivate
-{
-public:
- QGLShaderProgramPrivate() : valid(false), programId(0), ctx(0) {}
- void populateVariableLists();
-
- QVector<QGLShader*> shaders;
- QGLUniformList uniforms;
- QGLVertexAttributeList attributeArrays;
- bool valid;
- GLuint programId;
- QGLContext* ctx;
-};
-
-
-
-void QGLShaderProgramPrivate::populateVariableLists()
-{
- attributeArrays.clear();
- uniforms.clear();
-
- int count;
- int sizeOfNameBuff;
- char* name;
- GLint nameLength;
- GLenum type;
- GLint size;
- GLint location;
-
- glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTES, &count);
- glGetProgramiv(programId, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &sizeOfNameBuff);
- name = new char[sizeOfNameBuff];
-
- for (int i = 0; i < count; ++i) {
- nameLength = -1;
- glGetActiveAttrib(programId, i, sizeOfNameBuff, &nameLength, &size, &type, name);
- if (nameLength == -1)
- continue;
-
- location = glGetAttribLocation(programId, name);
- attributeArrays.insert(QString::fromAscii(name), QGLVertexAttribute(type, location, ctx));
- }
-
- delete [] name;
-
-
- glGetProgramiv(programId, GL_ACTIVE_UNIFORMS, &count);
- glGetProgramiv(programId, GL_ACTIVE_UNIFORM_MAX_LENGTH, &sizeOfNameBuff);
-
- name = new char[sizeOfNameBuff];
-
- for (int i = 0; i < count; ++i) {
- nameLength = -1;
- glGetActiveUniform(programId, i, sizeOfNameBuff, &nameLength, &size, &type, name);
- if (nameLength == -1)
- continue;
-
- location = glGetUniformLocation(programId, name);
- uniforms.insert(QString::fromAscii(name), QGLUniform(type, location, ctx));
- }
-}
-
-
-QGLShaderProgram::QGLShaderProgram(const QGLContext* ctx)
- : d_ptr(new QGLShaderProgramPrivate)
-{
- Q_D(QGLShaderProgram);
- if (!ctx)
- ctx = QGLContext::currentContext();
-
- if (!ctx) {
- qWarning("QGLShaderProgram being created without a context");
- return;
- }
-
- d->ctx = const_cast<QGLContext*>(ctx);
- d->ctx->makeCurrent();
-
- d->programId = glCreateProgram();
-
- d->valid = false;
-}
-
-
-const QGLUniformList & QGLShaderProgram::uniforms()
-{
- Q_D(QGLShaderProgram);
- return const_cast<const QGLUniformList&>(d->uniforms);
-}
-
-
-const QGLVertexAttributeList& QGLShaderProgram::vertexAttributes()
-{
- Q_D(QGLShaderProgram);
- return const_cast<const QGLVertexAttributeList&>(d->attributeArrays);
-}
-
-
-bool QGLShaderProgram::addShader(QGLShader* newShader)
-{
- Q_D(QGLShaderProgram);
- if (!newShader || !d->ctx)
- return false;
-
- if (newShader->context() != d->ctx) {
- qWarning("Shader object's context does not match program's context");
- return false;
- }
-
- if (!newShader->isValid())
- return false;
-
- QGLContext* ctx = d->ctx;
- if (!ctx)
- return false;
- ctx->makeCurrent();
-
- glAttachShader(d->programId, newShader->id());
-
- d->shaders.append(newShader);
- return true;
-}
-
-
-bool QGLShaderProgram::removeShader(QGLShader* oldShader)
-{
- Q_D(QGLShaderProgram);
-
- int idx = d->shaders.indexOf(oldShader);
-
- if (idx == -1)
- return false;
-
- d->shaders.remove(idx);
-
- QGLContext* ctx = d->ctx;
- if (!ctx)
- return false;
- ctx->makeCurrent();
-
- glDetachShader(d->programId, oldShader->id());
- return true;
-}
-
-
-bool QGLShaderProgram::removeAllShaders()
-{
- Q_D(QGLShaderProgram);
-
- QGLContext* ctx = d->ctx;
- if (!ctx)
- return false;
- ctx->makeCurrent();
-
- foreach (QGLShader* shader, d->shaders)
- glDetachShader(d->programId, shader->id());
-
- d->shaders.clear();
- return true;
-}
-
-#include <stdio.h>
-
-bool QGLShaderProgram::link()
-{
- Q_D(QGLShaderProgram);
-
- QGLContext* ctx = d->ctx;
- if (!ctx)
- return false;
- ctx->makeCurrent();
-
- glLinkProgram(d->programId);
-
-
- GLint linked;
- glGetProgramiv(d->programId, GL_LINK_STATUS, &linked);
-
- if (!linked)
- return false;
-
- d->populateVariableLists();
-
- d->valid = true;
- return true;
-}
-
-void QGLShaderProgram::use()
-{
- Q_D(QGLShaderProgram);
- if (!d->valid)
- return;
-
- glUseProgram(d->programId);
-}
-
-
-QString QGLShaderProgram::log()
-{
- Q_D(QGLShaderProgram);
-
- QGLContext* ctx = d->ctx;
- if (!ctx)
- return QString();
- ctx->makeCurrent();
-
- GLint logSize = -666;
- glGetProgramiv(d->programId, GL_INFO_LOG_LENGTH, &logSize);
-
- char* logData = new char[logSize];
- GLint logLength;
-
- glGetProgramInfoLog(d->programId, logSize, &logLength, logData);
-
- QString result = QString::fromAscii(logData);
- delete [] logData;
-
- return result;
-}
-
-GLuint QGLShaderProgram::id()
-{
- Q_D(QGLShaderProgram);
- return d->programId;
-}
-
-/////////////////////////////////////////////////////////////////////////
-
-
-
-
-QGLUniform::QGLUniform()
- : m_id(0), m_type(QGLInvalidType), ctx(0)
-{
- qWarning("Unknown uniform! Either the uniform doesn't exist or it was removed at shader link");
-}
-
-const QGLUniform& QGLUniform::operator=(const GLfloat& rhs) const
-{
- if (m_type != QGLFloatType)
- return *this;
-
- glUniform1f(m_id, rhs);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const QGLVec2& rhs) const
-{
- if (m_type != QGLVec2Type)
- return *this;
-
- glUniform2fv(m_id, 1, (const GLfloat*)&rhs);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const QSizeF& rhs) const
-{
- if (m_type != QGLVec2Type)
- return *this;
-
- glUniform2f(m_id, rhs.width(), rhs.height());
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const QPointF& rhs) const
-{
- if (m_type != QGLVec2Type)
- return *this;
-
- glUniform2f(m_id, rhs.x(), rhs.y());
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const QGLVec3& rhs) const
-{
- if (m_type != QGLVec3Type)
- return *this;
-
- glUniform3fv(m_id, 1, (const GLfloat*)&rhs);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const QGLVec4& rhs) const
-{
- if (m_type != QGLVec4Type)
- return *this;
-
- glUniform4fv(m_id, 1, (const GLfloat*)&rhs);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const QColor& rhs) const
-{
- if (m_type != QGLVec4Type)
- return *this;
-
- glUniform4f(m_id, rhs.redF(), rhs.greenF(), rhs.blueF(), rhs.alphaF());
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const GLfloat rhs[2][2]) const
-{
- if (m_type != QGLMat2Type)
- return *this;
-
- glUniformMatrix2fv(m_id, 1, GL_FALSE, (GLfloat*)rhs);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const GLfloat rhs[3][3]) const
-{
- if (m_type != QGLMat3Type)
- return *this;
-
- glUniformMatrix3fv(m_id, 1, GL_FALSE, (GLfloat*)rhs);
-
- return *this;
-}
-
-// Transposes ready for GL
-const QGLUniform& QGLUniform::operator=(const QTransform& rhs) const
-{
- if (m_type != QGLMat3Type)
- return *this;
-
- GLfloat mat3[3][3] = {
- {rhs.m11(), rhs.m12(), rhs.m13()},
- {rhs.m21(), rhs.m22(), rhs.m23()},
- {rhs.m31(), rhs.m32(), rhs.m33()}
- };
-
- glUniformMatrix3fv(m_id, 1, GL_FALSE, (GLfloat*)mat3);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const GLfloat rhs[4][4]) const
-{
- if (m_type != QGLMat4Type)
- return *this;
-
- glUniformMatrix4fv(m_id, 1, GL_FALSE, (GLfloat*)rhs);
-
- return *this;
-}
-
-const QGLUniform& QGLUniform::operator=(const GLuint& rhs) const
-{
- if ((m_type != QGLSampler2DType) || (m_type != QGLSamplerCubeType))
- return *this;
-
- glUniform1i(m_id, rhs);
-
- return *this;
-}
-
-
-
-
-/////////////////////////////////////////////////////////////////////////
-
-QGLVertexAttribute::QGLVertexAttribute()
- : m_id(0), m_type(QGLInvalidType), ctx(0)
-{
- qWarning("Unknown vertex attribute!");
-}
-
-void QGLVertexAttribute::enable() const
-{
- glEnableVertexAttribArray(m_id);
-}
-
-void QGLVertexAttribute::disable() const
-{
- glDisableVertexAttribArray(m_id);
-}
-
-// NOTE: Under PC emulation, QGLVec4Type is _always_ returned as the type, so this
-// method isn't very useful. I.e. The datatypes are needed to distinguish the different
-// sizes for the function signatures.
-const QGLVertexAttribute& QGLVertexAttribute::operator=(const GLfloat* rhs) const
-{
- int size = -1;
- if (m_type == QGLFloatType)
- size = 1;
- else if (m_type == QGLVec2Type)
- size = 2;
- else if (m_type == QGLVec3Type)
- size = 3;
- else if (m_type == QGLVec4Type)
- size = 4;
- else if (m_type == QGLMat2Type) //### Not sure if this is right for matrix attributes...
- size = 4;
- else if (m_type == QGLMat3Type) //### Not sure if this is right for matrix attributes...
- size = 9;
- else if (m_type == QGLMat4Type) //### Not sure if this is right for matrix attributes...
- size = 16;
- else
- return *this;
-
- glVertexAttribPointer(m_id, size, GL_FLOAT, GL_FALSE, 0, rhs);
-
- return *this;
-}
-
-const QGLVertexAttribute& QGLVertexAttribute::operator=(const QGLVec3* rhs) const
-{
- glVertexAttribPointer(m_id, 3, GL_FLOAT, GL_FALSE, 0, (GLfloat*)rhs);
-
- return *this;
-}
diff --git a/src/opengl/gl2paintengineex/qglshader_p.h b/src/opengl/gl2paintengineex/qglshader_p.h
deleted file mode 100644
index 1625b84..0000000
--- a/src/opengl/gl2paintengineex/qglshader_p.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the QtOpenGL module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-/*
-Uniform Types in OpenGL ES 2.0
-==============================
-GL_FLOAT GLfloat GLfloat
-GL_FLOAT_VEC2 QGLVec2 GLfloat[2]
-GL_FLOAT_VEC3 QGLVec3 GLfloat[3]
-GL_FLOAT_VEC4 QGLVec4 GLfloat[4]
-GL_INT GLint GLint
-GL_INT_VEC2 QGLIVec2 GLint[2]
-GL_INT_VEC3 QGLIVec3 GLint[3]
-GL_INT_VEC4 QGLIVec4 GLint[4]
-GL_BOOL GLbool GLbool
-GL_BOOL_VEC2 QGLBVec2 GLbool[2]
-GL_BOOL_VEC3 QGLBVec3 GLbool[3]
-GL_BOOL_VEC4 QGLBVec4 GLbool[4]
-GL_FLOAT_MAT2 QGLMat2 GLfloat[2][2]
-GL_FLOAT_MAT3 QGLMat3 GLfloat[3][3]
-GL_FLOAT_MAT4 QGLMat4 GLfloat[4][4]
-GL_SAMPLER_2D QGLSampler2D GLuint
-GL_SAMPLER_CUBE QGLSamplerCube GLuint
-
-Additional Types in Desktop OpenGL 2.0
-======================================
-SAMPLER_1D,
-SAMPLER_3D,
-SAMPLER_1D_SHADOW,
-SAMPLER_2D_SHADOW.
-*/
-
-#include <QtOpenGL>
-
-
-typedef struct {
- GLfloat a;
- GLfloat b;
-} QGLVec2;
-
-typedef struct {
- GLfloat a;
- GLfloat b;
- GLfloat c;
-} QGLVec3;
-
-typedef struct {
- GLfloat a;
- GLfloat b;
- GLfloat c;
- GLfloat d;
-} QGLVec4;
-
-
-class QGLShaderProgram;
-
-class QGLShaderPrivate;
-
-class QGLShader : QObject
-{
- Q_OBJECT
-public:
- enum ShaderType {VertexShader, FragmentShader};
-
- QGLShader(ShaderType type, const QGLContext* ctx = 0);
-
- GLuint id();
- void clearSource();
- void addSource(const QLatin1String& newSource);
- bool compile();
- bool isValid();
- QString log();
- const QGLContext* context(); //maybe make private with prog a friend?
-
-private:
- QGLShaderPrivate* d_ptr;
- Q_DECLARE_PRIVATE(QGLShader);
-
-/*
-public slots:
- void cleanupGLContextRefs(const QGLContext *context);
-*/
-};
-
-
-enum QGLType {
- QGLInvalidType = 0,
- QGLFloatType = GL_FLOAT,
- QGLVec2Type = GL_FLOAT_VEC2,
- QGLVec3Type = GL_FLOAT_VEC3,
- QGLVec4Type = GL_FLOAT_VEC4,
- QGLIntType = GL_INT,
- QGLIVec2Type = GL_INT_VEC2,
- QGLIVec3Type = GL_INT_VEC3,
- QGLIVec4Type = GL_INT_VEC4,
- QGLBoolType = GL_BOOL,
- QGLBVec2Type = GL_BOOL_VEC2,
- QGLBVec3Type = GL_BOOL_VEC3,
- QGLBVec4Type = GL_BOOL_VEC4,
- QGLMat2Type = GL_FLOAT_MAT2,
- QGLMat3Type = GL_FLOAT_MAT3,
- QGLMat4Type = GL_FLOAT_MAT4,
- QGLSampler2DType = GL_SAMPLER_2D,
- QGLSamplerCubeType = GL_SAMPLER_CUBE
-};
-
-class QGLUniform
-{
-public:
-
- QGLUniform(GLenum glType, GLint location, QGLContext* context)
- : m_id(location), m_type(QGLType(glType)), ctx(context) {}
-
- QGLUniform(); // Called by QMap when there's no match on the name
-
- QGLType type() const {return m_type;}
- GLuint id() const {return m_id;}
-
- // Seems odd to be const, but it doesn't actually modify any of the
- // class members, only the GL state!
- const QGLUniform& operator=(const GLfloat&) const;
-
- const QGLUniform& operator=(const QGLVec2&) const;
- const QGLUniform& operator=(const QSizeF&) const;
- const QGLUniform& operator=(const QPointF&) const;
-
- const QGLUniform& operator=(const QGLVec3&) const;
-
- const QGLUniform& operator=(const QGLVec4&) const;
- const QGLUniform& operator=(const QColor&) const;
-
- const QGLUniform& operator=(const GLfloat[2][2]) const;
-
- const QGLUniform& operator=(const GLfloat[3][3]) const;
- const QGLUniform& operator=(const QTransform&) const;
-
- const QGLUniform& operator=(const GLfloat[4][4]) const;
-
- const QGLUniform& operator=(const GLuint&) const; // sampler2d, specifying a texture unit
-
-
-protected:
- GLuint m_id;
- QGLType m_type;
- QGLContext* ctx;
-};
-
-typedef QMap<QString, QGLUniform> QGLUniformList;
-typedef QMapIterator<QString, QGLUniform> QGLUniformListIterator;
-
-
-class QGLVertexAttribute
-{
-public:
- QGLVertexAttribute(GLenum glType, GLuint location, QGLContext* context)
- : m_id(location), m_type(QGLType(glType)), ctx(context) {}
-
- QGLVertexAttribute(); // Called by QMap when there's no match on the name
-
- QGLType type() const {return m_type;}
- GLuint id() const {return m_id;}
- void enable() const;
- void disable() const;
-
- const QGLVertexAttribute& operator=(const GLfloat* rhs) const;
- const QGLVertexAttribute& operator=(const QGLVec3* rhs) const;
-
-protected:
- GLuint m_id;
- QGLType m_type;
- QGLContext* ctx;
-};
-
-//TODO: Convert into setter overloads on QGLShaderProgram
-typedef QMap<QString, QGLVertexAttribute> QGLVertexAttributeList;
-typedef QMapIterator<QString, QGLVertexAttribute> QGLVertexAttributeListIterator;
-
-
-
-class QGLShaderProgramPrivate;
-
-class QGLShaderProgram : QObject
-{
- Q_OBJECT
-public:
- QGLShaderProgram(const QGLContext* ctx = 0);
-
- const QGLUniformList & uniforms();
- const QGLVertexAttributeList& vertexAttributes();
-
- bool addShader(QGLShader* newShader);
- bool removeShader(QGLShader* oldShader);
- bool removeAllShaders();
-
- bool link();
- QString log();
- bool isValid();
- void use();
-
- GLuint id();
-
-private:
- QGLShaderProgramPrivate* d_ptr;
- Q_DECLARE_PRIVATE(QGLShaderProgram);
-
-/*
-public slots:
- void cleanupGLContextRefs(const QGLContext *context);
-*/
-};
-
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index beb4da6..19cb02a 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -62,7 +62,6 @@
and use the correct program when we really need it.
*/
-
#include "qpaintengineex_opengl2_p.h"
#include <string.h> //for memcpy
@@ -77,93 +76,167 @@
#include <private/qtextureglyphcache_p.h>
#include "qglgradientcache_p.h"
-#include "qglpexshadermanager_p.h"
+#include "qglengineshadermanager_p.h"
#include "qgl2pexvertexarray_p.h"
+#include <QDebug>
-extern QImage qt_imageForBrush(int brushStyle, bool invert); //in qbrush.cpp
+QT_BEGIN_NAMESPACE
+static const GLuint QT_BRUSH_TEXTURE_UNIT = 0;
+static const GLuint QT_IMAGE_TEXTURE_UNIT = 0; //Can be the same as brush texture unit
+static const GLuint QT_MASK_TEXTURE_UNIT = 1;
+static const GLuint QT_BACKGROUND_TEXTURE_UNIT = 2;
-#include <QDebug>
+class QGLTextureGlyphCache : public QTextureGlyphCache
+{
+public:
+ QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix);
+ ~QGLTextureGlyphCache();
+
+ virtual void createTextureData(int width, int height);
+ virtual void resizeTextureData(int width, int height);
+ virtual void fillTexture(const Coord &c, glyph_t glyph);
+
+ inline GLuint texture() const { return m_texture; }
+
+ inline int width() const { return m_width; }
+ inline int height() const { return m_height; }
+
+ inline void setPaintEnginePrivate(QGL2PaintEngineExPrivate *p) { pex = p; }
+
+private:
+ QGLContext *ctx;
+ QGL2PaintEngineExPrivate *pex;
-static const GLuint QT_VERTEX_COORDS_ATTR = 0;
-static const GLuint QT_TEXTURE_COORDS_ATTR = 1;
-static const GLuint QT_BRUSH_TEXTURE_UNIT = 0;
+ GLuint m_texture;
+ GLuint m_fbo;
-class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
+ int m_width;
+ int m_height;
+
+ QGLShaderProgram *m_program;
+};
+
+QGLTextureGlyphCache::QGLTextureGlyphCache(QGLContext *context, QFontEngineGlyphCache::Type type, const QTransform &matrix)
+ : QTextureGlyphCache(type, matrix)
+ , ctx(context)
+ , m_width(0)
+ , m_height(0)
{
- Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
-public:
- QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
- q(q_ptr),
- width(0), height(0),
- ctx(0),
- currentBrush( &(q->state()->brush) ),
- inverseScale(1),
- shaderManager(0)
- { }
+ glGenFramebuffers(1, &m_fbo);
+}
+
+QGLTextureGlyphCache::~QGLTextureGlyphCache()
+{
+ glDeleteFramebuffers(1, &m_fbo);
+
+ if (m_width || m_height)
+ glDeleteTextures(1, &m_texture);
+}
- ~QGL2PaintEngineExPrivate();
+void QGLTextureGlyphCache::createTextureData(int width, int height)
+{
+ glGenTextures(1, &m_texture);
+ glBindTexture(GL_TEXTURE_2D, m_texture);
- void updateBrushTexture();
- void updateBrushUniforms();
- void updateMatrix();
- void updateCompositionMode();
- void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform);
+ m_width = width;
+ m_height = height;
- void setBrush(const QBrush* brush);
+ QVarLengthArray<uchar> data(width * height);
+ for (int i = 0; i < width * height; ++i)
+ data[i] = 0;
- void drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight);
+ if (m_type == QFontEngineGlyphCache::Raster_RGBMask)
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
+ else
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, &data[0]);
- void fill(const QVectorPath &path);
- void drawOutline(const QVectorPath& path);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+}
+
+void QGLTextureGlyphCache::resizeTextureData(int width, int height)
+{
+ // ### the QTextureGlyphCache API needs to be reworked to allow
+ // ### resizeTextureData to fail
- void drawVertexArrays(QGL2PEXVertexArray& vertexArray, GLenum primitive);
- // ^ draws whatever is in the vertex array
- void composite(const QGLRect& boundingRect);
- // ^ Composites the bounding rect onto dest buffer
- void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill);
- // ^ Calls drawVertexArrays to render into stencil buffer
- void cleanStencilBuffer(const QGLRect& area);
+ int oldWidth = m_width;
+ int oldHeight = m_height;
- void prepareForDraw();
+ GLuint oldTexture = m_texture;
+ createTextureData(width, height);
- inline void useSimpleShader();
- inline QColor premultiplyColor(QColor c, GLfloat opacity);
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, m_fbo);
- QGL2PaintEngineEx* q;
+ GLuint colorBuffer;
+ glGenRenderbuffers(1, &colorBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, colorBuffer);
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_RGBA, oldWidth, oldHeight);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, colorBuffer);
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, 0);
- //### Move into QGLDrawable
- int width, height;
- QGLContext* ctx;
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ glBindTexture(GL_TEXTURE_2D, oldTexture);
- // Dirty flags
- bool matrixDirty; // Implies matrix uniforms are also dirty
- bool compositionModeDirty;
- bool brushTextureDirty;
- bool brushUniformsDirty;
- bool simpleShaderMatrixUniformDirty;
- bool brushShaderMatrixUniformDirty;
- bool imageShaderMatrixUniformDirty;
- bool textShaderMatrixUniformDirty;
- bool stencilBuferDirty;
+ pex->transferMode(BrushDrawingMode);
- const QBrush* currentBrush; // May not be the state's brush!
+ glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
- GLfloat inverseScale;
+ glViewport(0, 0, oldWidth, oldHeight);
- QGL2PEXVertexArray pathVertexArray;
+ float vertexCoordinateArray[] = { -1, -1, 1, -1, 1, 1, -1, 1 };
+ float textureCoordinateArray[] = { 0, 0, 1, 0, 1, 1, 0, 1 };
- GLfloat pmvMatrix[4][4];
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- QGLPEXShaderManager* shaderManager;
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray);
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray);
- // Clipping & state stuff stolen from QOpenGLPaintEngine:
- void updateDepthClip();
- uint use_system_clip : 1;
-};
+ pex->shaderManager->blitProgram()->enable();
+ pex->shaderManager->blitProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
+ pex->shaderManager->setDirty();
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, oldWidth, oldHeight);
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, 0);
+ glDeleteRenderbuffers(1, &colorBuffer);
+ glDeleteTextures(1, &oldTexture);
+
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
+
+ glViewport(0, 0, pex->width, pex->height);
+ pex->updateDepthScissorTest();
+}
+
+void QGLTextureGlyphCache::fillTexture(const Coord &c, glyph_t glyph)
+{
+ QImage mask = textureMapForGlyph(glyph);
+
+ const uint maskWidth = mask.width();
+ const uint maskHeight = mask.height();
+
+ glBindTexture(GL_TEXTURE_2D, m_texture);
+ if (mask.format() == QImage::Format_RGB32) {
+ glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, m_height - c.y, maskWidth, maskHeight, GL_BGRA, GL_UNSIGNED_BYTE, mask.bits());
+ } else {
+ mask = mask.convertToFormat(QImage::Format_Indexed8);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, c.x, c.y, maskWidth, maskHeight, GL_ALPHA, GL_UNSIGNED_BYTE, mask.bits());
+ }
+}
+
+extern QImage qt_imageForBrush(int brushStyle, bool invert);
////////////////////////////////// Private Methods //////////////////////////////////////////
@@ -177,7 +250,7 @@ QGL2PaintEngineExPrivate::~QGL2PaintEngineExPrivate()
void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform)
{
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+// glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT); //### Is it always this texture unit?
if (smoothPixmapTransform) {
glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
@@ -193,11 +266,11 @@ void QGL2PaintEngineExPrivate::updateTextureFilter(GLenum target, GLenum wrapMod
QColor QGL2PaintEngineExPrivate::premultiplyColor(QColor c, GLfloat opacity)
{
- uint alpha = qRound(c.alpha() * opacity);
- return QColor ( ((c.red() * alpha + 128) >> 8),
- ((c.green() * alpha + 128) >> 8),
- ((c.blue() * alpha + 128) >> 8),
- alpha);
+ qreal alpha = c.alphaF() * opacity;
+ c.setRedF(c.redF() * alpha);
+ c.setGreenF(c.greenF() * alpha);
+ c.setBlueF(c.blueF() * alpha);
+ return c;
}
@@ -206,27 +279,39 @@ void QGL2PaintEngineExPrivate::setBrush(const QBrush* brush)
currentBrush = brush;
brushTextureDirty = true;
brushUniformsDirty = true;
- shaderManager->setBrushStyle(currentBrush->style());
- shaderManager->setAffineOnlyBrushTransform(currentBrush->transform().isAffine());
+ if (currentBrush->style() == Qt::TexturePattern
+ && qHasPixmapTexture(*brush) && brush->texture().isQBitmap())
+ {
+ shaderManager->setSrcPixelType(QGLEngineShaderManager::TextureSrcWithPattern);
+ } else {
+ shaderManager->setSrcPixelType(currentBrush->style());
+ }
+ shaderManager->optimiseForBrushTransform(currentBrush->transform());
}
// Unless this gets used elsewhere, it's probably best to merge it into fillStencilWithVertexArray
void QGL2PaintEngineExPrivate::useSimpleShader()
{
- shaderManager->simpleShader()->use();
+ shaderManager->simpleProgram()->enable();
+ shaderManager->setDirty();
if (matrixDirty)
updateMatrix();
if (simpleShaderMatrixUniformDirty) {
- shaderManager->simpleShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
+ shaderManager->simpleProgram()->setUniformValue("pmvMatrix", pmvMatrix);
simpleShaderMatrixUniformDirty = false;
}
+
+ if (simpleShaderDepthUniformDirty) {
+ shaderManager->simpleProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth);
+ simpleShaderDepthUniformDirty = false;
+ }
}
-Q_GLOBAL_STATIC(QGLGradientCache, qt_opengl_gradient_cache)
+Q_GLOBAL_STATIC(QGL2GradientCache, qt_opengl_gradient_cache)
void QGL2PaintEngineExPrivate::updateBrushTexture()
{
@@ -235,9 +320,9 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
if ( (style >= Qt::Dense1Pattern) && (style <= Qt::DiagCrossPattern) ) {
// Get the image data for the pattern
- QImage texImage = qt_imageForBrush(style, true);
+ QImage texImage = qt_imageForBrush(style, false);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
ctx->d_func()->bindTexture(texImage, GL_TEXTURE_2D, GL_RGBA, true);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
}
@@ -257,12 +342,13 @@ void QGL2PaintEngineExPrivate::updateBrushTexture()
else
updateTextureFilter(GL_TEXTURE_2D, GL_CLAMP_TO_EDGE, true);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
glBindTexture(GL_TEXTURE_2D, texId);
}
else if (style == Qt::TexturePattern) {
const QPixmap& texPixmap = currentBrush->texture();
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ glActiveTexture(GL_TEXTURE0 + QT_BRUSH_TEXTURE_UNIT);
ctx->d_func()->bindTexture(texPixmap, GL_TEXTURE_2D, GL_RGBA, true);
updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, true);
}
@@ -278,17 +364,11 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style == Qt::NoBrush)
return;
- GLfloat opacity = 1.0;
- if (q->state()->opacity < 0.99f)
- opacity = (GLfloat)q->state()->opacity;
- bool setOpacity = true;
-
QTransform brushQTransform = currentBrush->transform();
if (style == Qt::SolidPattern) {
- QColor col = premultiplyColor(currentBrush->color(), opacity);
- shaderManager->brushShader()->uniforms()[QLatin1String("fragmentColor")] = col;
- setOpacity = false;
+ QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
+ shaderManager->currentProgram()->setUniformValue("fragmentColor", col);
}
else {
// All other brushes have a transform and thus need the translation point:
@@ -297,13 +377,12 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
if (style <= Qt::DiagCrossPattern) {
translationPoint = q->state()->brushOrigin;
- QColor col = premultiplyColor(currentBrush->color(), opacity);
+ QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
- shaderManager->brushShader()->uniforms()[QLatin1String("patternColor")] = col;
- setOpacity = false; //So code below doesn't try to set the opacity uniform
+ shaderManager->currentProgram()->setUniformValue("patternColor", col);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::LinearGradientPattern) {
const QLinearGradient *g = static_cast<const QLinearGradient *>(currentBrush->gradient());
@@ -314,17 +393,16 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QPointF l = realFinal - realStart;
- // ###
- QGLVec3 linearData = {
+ QVector3D linearData(
l.x(),
l.y(),
1.0f / (l.x() * l.x() + l.y() * l.y())
- };
+ );
- shaderManager->brushShader()->uniforms()[QLatin1String("linearData")] = linearData;
+ shaderManager->currentProgram()->setUniformValue("linearData", linearData);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::ConicalGradientPattern) {
const QConicalGradient *g = static_cast<const QConicalGradient *>(currentBrush->gradient());
@@ -332,10 +410,10 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
GLfloat angle = -(g->angle() * 2 * Q_PI) / 360.0;
- shaderManager->brushShader()->uniforms()[QLatin1String("angle")] = angle;
+ shaderManager->currentProgram()->setUniformValue("angle", angle);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::RadialGradientPattern) {
const QRadialGradient *g = static_cast<const QRadialGradient *>(currentBrush->gradient());
@@ -345,27 +423,31 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
translationPoint = realFocal;
QPointF fmp = realCenter - realFocal;
- shaderManager->brushShader()->uniforms()[QLatin1String("fmp")] = fmp;
+ shaderManager->currentProgram()->setUniformValue("fmp", fmp);
GLfloat fmp2_m_radius2 = -fmp.x() * fmp.x() - fmp.y() * fmp.y() + realRadius*realRadius;
- shaderManager->brushShader()->uniforms()[QLatin1String("fmp2_m_radius2")] = fmp2_m_radius2;
-
- shaderManager->brushShader()->uniforms()[QLatin1String("inverse_2_fmp2_m_radius2")] =
- GLfloat(1.0 / (2.0*fmp2_m_radius2));
+ shaderManager->currentProgram()->setUniformValue("fmp2_m_radius2", fmp2_m_radius2);
+ shaderManager->currentProgram()->setUniformValue("inverse_2_fmp2_m_radius2",
+ GLfloat(1.0 / (2.0*fmp2_m_radius2)));
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else if (style == Qt::TexturePattern) {
translationPoint = q->state()->brushOrigin;
const QPixmap& texPixmap = currentBrush->texture();
+ if (qHasPixmapTexture(*currentBrush) && currentBrush->texture().isQBitmap()) {
+ QColor col = premultiplyColor(currentBrush->color(), (GLfloat)q->state()->opacity);
+ shaderManager->currentProgram()->setUniformValue("patternColor", col);
+ }
+
QSizeF invertedTextureSize( 1.0 / texPixmap.width(), 1.0 / texPixmap.height() );
- shaderManager->brushShader()->uniforms()[QLatin1String("invertedTextureSize")] = invertedTextureSize;
+ shaderManager->currentProgram()->setUniformValue("invertedTextureSize", invertedTextureSize);
- QGLVec2 halfViewportSize = { width*0.5, height*0.5 };
- shaderManager->brushShader()->uniforms()[QLatin1String("halfViewportSize")] = halfViewportSize;
+ QVector2D halfViewportSize(width*0.5, height*0.5);
+ shaderManager->currentProgram()->setUniformValue("halfViewportSize", halfViewportSize);
}
else
qWarning("QGL2PaintEngineEx: Unimplemented fill style");
@@ -374,11 +456,8 @@ void QGL2PaintEngineExPrivate::updateBrushUniforms()
QTransform gl_to_qt(1, 0, 0, -1, 0, height);
QTransform inv_matrix = gl_to_qt * (brushQTransform * q->state()->matrix).inverted() * translate;
- shaderManager->brushShader()->uniforms()[QLatin1String("brushTransform")] = inv_matrix;
- shaderManager->brushShader()->uniforms()[QLatin1String("brushTexture")] = QT_BRUSH_TEXTURE_UNIT;
-
- if (setOpacity)
- shaderManager->brushShader()->uniforms()[QLatin1String("opacity")] = opacity;
+ shaderManager->currentProgram()->setUniformValue("brushTransform", inv_matrix);
+ shaderManager->currentProgram()->setUniformValue("brushTexture", QT_BRUSH_TEXTURE_UNIT);
}
brushUniformsDirty = false;
}
@@ -397,38 +476,51 @@ void QGL2PaintEngineExPrivate::updateMatrix()
{0.0, 0.0, 0.0, 1.0}
};
- // Use the (3x3) transform for the Model~View matrix:
const QTransform& transform = q->state()->matrix;
- GLfloat MV[4][4] = {
- {transform.m11(), transform.m21(), 0.0, transform.dx() + 0.5},
- {transform.m12(), transform.m22(), 0.0, transform.dy() + 0.5},
- {0.0, 0.0, 1.0, 0.0},
- {transform.m13(), transform.m23(), 0.0, transform.m33()}
- };
- // NOTE: OpenGL ES works with column-major matrices, so when we multiply the matrices,
- // we also transpose them ready for GL.
- for (int row = 0; row < 4; ++row) {
- for (int col = 0; col < 4; ++col) {
- pmvMatrix[col][row] = 0.0;
- for (int n = 0; n < 4; ++n)
- pmvMatrix[col][row] += P[row][n] * MV[n][col];
+ if (mode == TextDrawingMode) {
+ // Text drawing mode is only used for non-scaling transforms
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ pmvMatrix[col][row] = P[row][col];
+
+ pmvMatrix[3][0] += P[0][0] * qRound(transform.dx());
+ pmvMatrix[3][1] += P[1][1] * qRound(transform.dy());
+
+ inverseScale = 1;
+ } else {
+ // Use the (3x3) transform for the Model~View matrix:
+ GLfloat MV[4][4] = {
+ {transform.m11(), transform.m21(), 0.0, transform.dx()},
+ {transform.m12(), transform.m22(), 0.0, transform.dy()},
+ {0.0, 0.0, 1.0, 0.0},
+ {transform.m13(), transform.m23(), 0.0, transform.m33()}
+ };
+
+ // NOTE: OpenGL ES works with column-major matrices, so when we multiply the matrices,
+ // we also transpose them ready for GL.
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ pmvMatrix[col][row] = 0.0;
+
+ // P[row][n] is 0.0 for n < row
+ for (int n = row; n < 4; ++n)
+ pmvMatrix[col][row] += P[row][n] * MV[n][col];
+ }
}
- }
- // 1/10000 == 0.0001, so we have good enough res to cover curves
- // that span the entire widget...
- inverseScale = qMax(1 / qMax( qMax(qAbs(transform.m11()), qAbs(transform.m22())),
- qMax(qAbs(transform.m12()), qAbs(transform.m21())) ),
- qreal(0.0001));
+ // 1/10000 == 0.0001, so we have good enough res to cover curves
+ // that span the entire widget...
+ inverseScale = qMax(1 / qMax( qMax(qAbs(transform.m11()), qAbs(transform.m22())),
+ qMax(qAbs(transform.m12()), qAbs(transform.m21())) ),
+ qreal(0.0001));
+ }
matrixDirty = false;
// The actual data has been updated so both shader program's uniforms need updating
simpleShaderMatrixUniformDirty = true;
- brushShaderMatrixUniformDirty = true;
- imageShaderMatrixUniformDirty = true;
- textShaderMatrixUniformDirty = true;
+ shaderMatrixUniformDirty = true;
}
@@ -485,120 +577,185 @@ void QGL2PaintEngineExPrivate::updateCompositionMode()
compositionModeDirty = false;
}
+static inline void setCoords(GLfloat *coords, const QGLRect &rect)
+{
+ coords[0] = rect.left;
+ coords[1] = rect.top;
+ coords[2] = rect.right;
+ coords[3] = rect.top;
+ coords[4] = rect.right;
+ coords[5] = rect.bottom;
+ coords[6] = rect.left;
+ coords[7] = rect.bottom;
+}
-void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, int txtWidth, int txtHeight)
+void QGL2PaintEngineExPrivate::drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern)
{
-// qDebug("QGL2PaintEngineExPrivate::drawImage()");
+ transferMode(ImageDrawingMode);
- // We have a shader specifically for drawPixmap/drawImage...
- shaderManager->imageShader()->use();
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, q->state()->renderHints & QPainter::SmoothPixmapTransform);
- updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+ // Setup for texture drawing
+ shaderManager->setSrcPixelType(pattern ? QGLEngineShaderManager::PatternSrc : QGLEngineShaderManager::ImageSrc);
+ shaderManager->setTextureCoordsEnabled(true);
+ prepareForDraw(opaque);
- if (compositionModeDirty)
- updateCompositionMode();
+ if (pattern) {
+ QColor col = premultiplyColor(q->state()->pen.color(), (GLfloat)q->state()->opacity);
+ shaderManager->currentProgram()->setUniformValue("patternColor", col);
+ }
- if (matrixDirty)
- updateMatrix();
+ shaderManager->currentProgram()->setUniformValue("imageTexture", QT_IMAGE_TEXTURE_UNIT);
- if (imageShaderMatrixUniformDirty) {
- shaderManager->imageShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
- imageShaderMatrixUniformDirty = false;
- }
+ GLfloat dx = 1.0 / textureSize.width();
+ GLfloat dy = 1.0 / textureSize.height();
- shaderManager->imageShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
+ QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
-// if (q->state()->opacity < 0.99f)
- shaderManager->imageShader()->uniforms()[QLatin1String("opacity")] = (GLfloat)q->state()->opacity;
+ setCoords(staticVertexCoordinateArray, dest);
+ setCoords(staticTextureCoordinateArray, srcTextureRect);
- GLfloat vertexCoords[] = {
- dest.left, dest.top,
- dest.left, dest.bottom,
- dest.right, dest.bottom,
- dest.right, dest.top
- };
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+}
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
+void QGL2PaintEngineEx::sync()
+{
+ Q_D(QGL2PaintEngineEx);
+ ensureActive();
+ d->transferMode(BrushDrawingMode);
- GLfloat dx = 1.0 / txtWidth;
- GLfloat dy = 1.0 / txtHeight;
+ QGLContext *ctx = d->ctx;
+ glUseProgram(0);
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
+#ifndef QT_OPENGL_ES_2
+ // be nice to people who mix OpenGL 1.x code with QPainter commands
+ // by setting modelview and projection matrices to mirror the GL 1
+ // paint engine
+ const QTransform& mtx = state()->matrix;
- GLfloat textureCoords[] = {
- srcTextureRect.left, srcTextureRect.top,
- srcTextureRect.left, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.top
+ float mv_matrix[4][4] =
+ {
+ { mtx.m11(), mtx.m12(), 0, mtx.m13() },
+ { mtx.m21(), mtx.m22(), 0, mtx.m23() },
+ { 0, 0, 1, 0 },
+ { mtx.dx(), mtx.dy(), 0, mtx.m33() }
};
- glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
+ const QSize sz = d->drawable.size();
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glOrtho(0, sz.width(), sz.height(), 0, -999999, 999999);
- glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glMatrixMode(GL_MODELVIEW);
+ glLoadMatrixf(&mv_matrix[0][0]);
+#endif
+
+ glDisable(GL_BLEND);
+ glActiveTexture(GL_TEXTURE0);
}
+void QGL2PaintEngineExPrivate::transferMode(EngineMode newMode)
+{
+ if (newMode == mode)
+ return;
+
+ if (mode == TextDrawingMode || mode == ImageDrawingMode) {
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ }
+
+ if (mode == TextDrawingMode)
+ matrixDirty = true;
+
+ if (newMode == TextDrawingMode) {
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
+
+ matrixDirty = true;
+ }
+
+ if (newMode == ImageDrawingMode) {
+ glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticVertexCoordinateArray);
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, staticTextureCoordinateArray);
+ }
+
+ // This needs to change when we implement high-quality anti-aliasing...
+ if (newMode != TextDrawingMode)
+ shaderManager->setMaskType(QGLEngineShaderManager::NoMask);
+
+ mode = newMode;
+}
void QGL2PaintEngineExPrivate::drawOutline(const QVectorPath& path)
{
-// qDebug("QGL2PaintEngineExPrivate::drawOutline()");
+ transferMode(BrushDrawingMode);
+
+ // Might need to call updateMatrix to re-calculate inverseScale
if (matrixDirty)
updateMatrix();
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
if (path.hasImplicitClose()) {
// Close the path's outline
- pathVertexArray.lineToArray(path.points()[0], path.points()[1]);
- pathVertexArray.stops().last() += 1;
+ vertexCoordinateArray.lineToArray(path.points()[0], path.points()[1]);
+ vertexCoordinateArray.stops().last() += 1;
}
- prepareForDraw();
- drawVertexArrays(pathVertexArray, GL_LINE_STRIP);
+ prepareForDraw(currentBrush->isOpaque());
+ drawVertexArrays(vertexCoordinateArray, GL_LINE_STRIP);
}
// Assumes everything is configured for the brush you want to use
void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
{
+ transferMode(BrushDrawingMode);
+
+ // Might need to call updateMatrix to re-calculate inverseScale
if (matrixDirty)
updateMatrix();
const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
-
// Check to see if there's any hints
if (path.shape() == QVectorPath::RectangleHint) {
QGLRect rect(points[0].x(), points[0].y(), points[2].x(), points[2].y());
- prepareForDraw();
+ prepareForDraw(currentBrush->isOpaque());
+
composite(rect);
}
else if (path.shape() == QVectorPath::EllipseHint) {
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
- prepareForDraw();
- drawVertexArrays(pathVertexArray, GL_TRIANGLE_FAN);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
+ prepareForDraw(currentBrush->isOpaque());
+ drawVertexArrays(vertexCoordinateArray, GL_TRIANGLE_FAN);
}
else {
// The path is too complicated & needs the stencil technique
- pathVertexArray.clear();
- pathVertexArray.addPath(path, inverseScale);
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
- fillStencilWithVertexArray(pathVertexArray, path.hasWindingFill());
+ fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
// Stencil the brush onto the dest buffer
glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
glEnable(GL_STENCIL_TEST);
- prepareForDraw();
- composite(pathVertexArray.boundingRect());
+ prepareForDraw(currentBrush->isOpaque());
+ composite(vertexCoordinateArray.boundingRect());
glDisable(GL_STENCIL_TEST);
- cleanStencilBuffer(pathVertexArray.boundingRect());
+ glStencilMask(0);
}
}
@@ -606,17 +763,17 @@ void QGL2PaintEngineExPrivate::fill(const QVectorPath& path)
void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill)
{
// qDebug("QGL2PaintEngineExPrivate::fillStencilWithVertexArray()");
- if (stencilBuferDirty) {
+ glStencilMask(0xFFFF); // Enable stencil writes
+
+ if (stencilBufferDirty) {
// Clear the stencil buffer to zeros
glDisable(GL_STENCIL_TEST);
- glStencilMask(0xFFFF); // Enable writing to stencil buffer, otherwise glClear wont do anything.
glClearStencil(0); // Clear to zero
glClear(GL_STENCIL_BUFFER_BIT);
- stencilBuferDirty = false;
+ stencilBufferDirty = false;
}
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
- glStencilMask(0xFFFF); // Enable stencil writes
glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test
// Setup the stencil op:
@@ -626,7 +783,7 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve
} else
glStencilOp(GL_KEEP, GL_KEEP, GL_INVERT); // Simply invert the stencil bit
- // No point in using a fancy gradiant shader for writing into the stencil buffer!
+ // No point in using a fancy gradient shader for writing into the stencil buffer!
useSimpleShader();
glEnable(GL_STENCIL_TEST); // For some reason, this has to happen _after_ the simple shader is use()'d
@@ -637,69 +794,62 @@ void QGL2PaintEngineExPrivate::fillStencilWithVertexArray(QGL2PEXVertexArray& ve
// Enable color writes & disable stencil writes
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilMask(0);
}
-void QGL2PaintEngineExPrivate::cleanStencilBuffer(const QGLRect& area)
+void QGL2PaintEngineExPrivate::prepareForDraw(bool srcPixelsAreOpaque)
{
-// qDebug("QGL2PaintEngineExPrivate::cleanStencilBuffer()");
- useSimpleShader();
-
- GLfloat rectVerts[] = {
- area.left, area.top,
- area.left, area.bottom,
- area.right, area.bottom,
- area.right, area.top
- };
-
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, rectVerts);
-
- glEnable(GL_STENCIL_TEST);
- glStencilFunc(GL_ALWAYS, 0, 0xFFFF); // Always pass the stencil test
-
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // Disable color writes
- glStencilMask(0xFFFF); // Enable writing to stencil buffer
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO); // Write 0's to stencil buffer
+ if (brushTextureDirty && mode != ImageDrawingMode)
+ updateBrushTexture();
- glDisable(GL_BLEND);
+ if (compositionModeDirty)
+ updateCompositionMode();
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ if (matrixDirty)
+ updateMatrix();
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ const bool stateHasOpacity = q->state()->opacity < 0.99f;
+ if (q->state()->compositionMode() == QPainter::CompositionMode_Source
+ || (q->state()->compositionMode() == QPainter::CompositionMode_SourceOver
+ && srcPixelsAreOpaque && !stateHasOpacity))
+ glDisable(GL_BLEND);
+ else
+ glEnable(GL_BLEND);
- // Enable color writes & disable stencil writes
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilMask(0);
- glDisable(GL_STENCIL_TEST);
-}
+ bool useGlobalOpacityUniform = stateHasOpacity;
+ if (stateHasOpacity && (mode != ImageDrawingMode)) {
+ // Using a brush
+ bool brushIsPattern = (currentBrush->style() >= Qt::Dense1Pattern) &&
+ (currentBrush->style() <= Qt::DiagCrossPattern);
-void QGL2PaintEngineExPrivate::prepareForDraw()
-{
- if (brushTextureDirty)
- updateBrushTexture();
+ if ((currentBrush->style() == Qt::SolidPattern) || brushIsPattern)
+ useGlobalOpacityUniform = false; // Global opacity handled by srcPixel shader
+ }
+ shaderManager->setUseGlobalOpacity(useGlobalOpacityUniform);
- if (compositionModeDirty)
- updateCompositionMode();
+ // If the shader program needs changing, we change it and mark all uniforms as dirty
if (shaderManager->useCorrectShaderProg()) {
// The shader program has changed so mark all uniforms as dirty:
brushUniformsDirty = true;
- brushShaderMatrixUniformDirty = true;
+ shaderMatrixUniformDirty = true;
+ depthUniformDirty = true;
}
- if (brushUniformsDirty)
+ if (brushUniformsDirty && mode != ImageDrawingMode)
updateBrushUniforms();
- if (brushShaderMatrixUniformDirty) {
- shaderManager->brushShader()->uniforms()[QLatin1String("pmvMatrix")] = pmvMatrix;
- brushShaderMatrixUniformDirty = false;
+ if (shaderMatrixUniformDirty) {
+ shaderManager->currentProgram()->setUniformValue("pmvMatrix", pmvMatrix);
+ shaderMatrixUniformDirty = false;
}
- if ((q->state()->opacity < 0.99f) || !currentBrush->isOpaque())
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
+ if (depthUniformDirty) {
+ shaderManager->currentProgram()->setUniformValue("depth", (GLfloat)q->state()->currentDepth);
+ depthUniformDirty = false;
+ }
+
+ if (useGlobalOpacityUniform)
+ shaderManager->currentProgram()->setUniformValue("globalOpacity", (GLfloat)q->state()->opacity);
}
void QGL2PaintEngineExPrivate::composite(const QGLRect& boundingRect)
@@ -749,8 +899,6 @@ void QGL2PaintEngineExPrivate::drawVertexArrays(QGL2PEXVertexArray& vertexArray,
QGL2PaintEngineEx::QGL2PaintEngineEx()
: QPaintEngineEx(*(new QGL2PaintEngineExPrivate(this)))
{
- qDebug("QGL2PaintEngineEx::QGL2PaintEngineEx()");
-
}
QGL2PaintEngineEx::~QGL2PaintEngineEx()
@@ -761,8 +909,10 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush)
{
Q_D(QGL2PaintEngineEx);
- QTime startTime = QTime::currentTime();
+ if (brush.style() == Qt::NoBrush)
+ return;
+ ensureActive();
d->setBrush(&brush);
d->fill(path);
d->setBrush(&(state()->brush)); // reset back to the state's brush
@@ -775,6 +925,8 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
if (pen.style() == Qt::NoPen)
return;
+ ensureActive();
+
if ( (pen.isCosmetic() && (pen.style() == Qt::SolidLine)) && (pen.widthF() < 2.5f) )
{
// We only handle solid, cosmetic pens with a width of 1 pixel
@@ -790,7 +942,6 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen)
d->setBrush(&(state()->brush));
} else
return QPaintEngineEx::stroke(path, pen);
-
}
void QGL2PaintEngineEx::penChanged()
@@ -819,7 +970,6 @@ void QGL2PaintEngineEx::opacityChanged()
Q_D(QGL2PaintEngineEx);
Q_ASSERT(d->shaderManager);
- d->shaderManager->setUseGlobalOpacity(state()->opacity > 0.999);
d->brushUniformsDirty = true;
}
@@ -845,45 +995,44 @@ void QGL2PaintEngineEx::transformChanged()
void QGL2PaintEngineEx::drawPixmap(const QRectF& dest, const QPixmap & pixmap, const QRectF & src)
{
Q_D(QGL2PaintEngineEx);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
+ ensureActive();
+ d->transferMode(ImageDrawingMode);
- d->ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
+ QGLContext *ctx = d->ctx;
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ ctx->d_func()->bindTexture(pixmap, GL_TEXTURE_2D, GL_RGBA, true);
- //FIXME: we should use hasAlpha() instead, but that's SLOW at the moment
- if ((state()->opacity < 0.99f) || pixmap.hasAlphaChannel())
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
+ bool isBitmap = pixmap.isQBitmap();
+ bool isOpaque = !isBitmap && !pixmap.hasAlphaChannel();
- d->drawTexture(dest, src, pixmap.width(), pixmap.height());
+ d->drawTexture(dest, src, pixmap.size(), isOpaque, isBitmap);
}
void QGL2PaintEngineEx::drawImage(const QRectF& dest, const QImage& image, const QRectF& src,
Qt::ImageConversionFlags)
{
Q_D(QGL2PaintEngineEx);
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
+ ensureActive();
+ d->transferMode(ImageDrawingMode);
- if ((state()->opacity < 0.99f) || image.hasAlphaChannel())
- glEnable(GL_BLEND);
- else
- glDisable(GL_BLEND);
+ QGLContext *ctx = d->ctx;
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
- d->drawTexture(dest, src, image.width(), image.height());
+ d->drawTexture(dest, src, image.size(), !image.hasAlphaChannel());
}
void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem)
{
- QOpenGLPaintEngineState *s = state();
+ Q_D(QGL2PaintEngineEx);
+
+ ensureActive();
+ QOpenGL2PaintEngineState *s = state();
const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
bool drawCached = true;
- if (state()->pen.brush().style() != Qt::SolidPattern)
- drawCached = false;
-
if (s->matrix.type() > QTransform::TxTranslate)
drawCached = false;
@@ -892,17 +1041,17 @@ void QGL2PaintEngineEx::drawTextItem(const QPointF &p, const QTextItem &textItem
drawCached = false;
if (drawCached) {
- drawCachedGlyphs(p, ti);
+ d->drawCachedGlyphs(p, ti);
return;
}
QPaintEngineEx::drawTextItem(p, ti);
}
-void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
+void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti)
{
- Q_D(QGL2PaintEngineEx);
- QOpenGLPaintEngineState *s = state();
+ Q_Q(QGL2PaintEngineEx);
+ QOpenGL2PaintEngineState *s = q->state();
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> glyphs;
@@ -914,81 +1063,67 @@ void QGL2PaintEngineEx::drawCachedGlyphs(const QPointF &p, const QTextItemInt &t
? QFontEngineGlyphCache::Type(ti.fontEngine->glyphFormat)
: QFontEngineGlyphCache::Raster_A8;
- QImageTextureGlyphCache *cache =
- (QImageTextureGlyphCache *) ti.fontEngine->glyphCache(glyphType, s->matrix);
+ QGLTextureGlyphCache *cache =
+ (QGLTextureGlyphCache *) ti.fontEngine->glyphCache(ctx, s->matrix);
if (!cache) {
- cache = new QImageTextureGlyphCache(glyphType, s->matrix);
- ti.fontEngine->setGlyphCache(glyphType, cache);
+ cache = new QGLTextureGlyphCache(ctx, glyphType, s->matrix);
+ ti.fontEngine->setGlyphCache(ctx, cache);
}
+ cache->setPaintEnginePrivate(this);
cache->populate(ti, glyphs, positions);
- const QImage &image = cache->image();
- int margin = cache->glyphMargin();
-
- if (image.isNull())
+ if (cache->width() == 0 || cache->height() == 0)
return;
- glActiveTexture(QT_BRUSH_TEXTURE_UNIT);
- d->ctx->d_func()->bindTexture(image, GL_TEXTURE_2D, GL_RGBA, true);
-
- glEnable(GL_BLEND);
+ transferMode(TextDrawingMode);
- d->shaderManager->textShader()->use();
- d->updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
+ if (glyphType == QFontEngineGlyphCache::Raster_A8)
+ shaderManager->setMaskType(QGLEngineShaderManager::PixelMask);
+ else if (glyphType == QFontEngineGlyphCache::Raster_RGBMask)
+ shaderManager->setMaskType(QGLEngineShaderManager::SubPixelMask);
+ //### TODO: Gamma correction
+ shaderManager->setTextureCoordsEnabled(true);
- if (d->compositionModeDirty)
- d->updateCompositionMode();
+ int margin = cache->glyphMargin();
- if (d->matrixDirty)
- d->updateMatrix();
+ GLfloat dx = 1.0 / cache->width();
+ GLfloat dy = 1.0 / cache->height();
- if (d->textShaderMatrixUniformDirty) {
- d->shaderManager->textShader()->uniforms()[QLatin1String("pmvMatrix")] = d->pmvMatrix;
- d->textShaderMatrixUniformDirty = false;
- }
+ QGLPoint *oldVertexCoordinateDataPtr = vertexCoordinateArray.data();
+ QGLPoint *oldTextureCoordinateDataPtr = textureCoordinateArray.data();
- d->shaderManager->textShader()->uniforms()[QLatin1String("textureSampler")] = QT_BRUSH_TEXTURE_UNIT;
- QColor col = d->premultiplyColor(state()->pen.color(), (GLfloat)state()->opacity);
- d->shaderManager->textShader()->uniforms()[QLatin1String("fragmentColor")] = col;
+ vertexCoordinateArray.clear();
+ textureCoordinateArray.clear();
- GLfloat dx = 1.0 / image.width();
- GLfloat dy = 1.0 / image.height();
-
- glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
- glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
for (int i=0; i<glyphs.size(); ++i) {
const QTextureGlyphCache::Coord &c = cache->coords.value(glyphs[i]);
int x = positions[i].x.toInt() + c.baseLineX - margin;
int y = positions[i].y.toInt() - c.baseLineY - margin;
- QGLRect dest = QRectF(x, y, c.w, c.h);
- QGLRect src = QRectF(c.x, c.y, c.w, c.h);
+ vertexCoordinateArray.addRect(QRectF(x, y, c.w, c.h));
+ textureCoordinateArray.addRect(QRectF(c.x*dx, c.y*dy, c.w * dx, c.h * dy));
+ }
+
+ glActiveTexture(GL_TEXTURE0 + QT_MASK_TEXTURE_UNIT);
+ glBindTexture(GL_TEXTURE_2D, cache->texture());
+ updateTextureFilter(GL_TEXTURE_2D, GL_REPEAT, false);
- GLfloat vertexCoords[] = {
- dest.left, dest.top,
- dest.left, dest.bottom,
- dest.right, dest.bottom,
- dest.right, dest.top
- };
+ QBrush pensBrush = q->state()->pen.brush();
+ setBrush(&pensBrush);
- glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoords);
+ prepareForDraw(false); // Text always causes src pixels to be transparent
- QGLRect srcTextureRect(src.left*dx, 1.0 - src.top*dy, src.right*dx, 1.0 - src.bottom*dy);
+ shaderManager->currentProgram()->setUniformValue("maskTexture", QT_MASK_TEXTURE_UNIT);
- GLfloat textureCoords[] = {
- srcTextureRect.left, srcTextureRect.top,
- srcTextureRect.left, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.bottom,
- srcTextureRect.right, srcTextureRect.top
- };
+ if (vertexCoordinateArray.data() != oldVertexCoordinateDataPtr)
+ glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinateArray.data());
+ if (textureCoordinateArray.data() != oldTextureCoordinateDataPtr)
+ glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data());
- glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoords);
+ glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size());
- glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
- }
- glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
- glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ setBrush(&(q->state()->brush)); //###
}
bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
@@ -996,15 +1131,31 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
Q_D(QGL2PaintEngineEx);
// qDebug("QGL2PaintEngineEx::begin()");
+ d->drawable.setDevice(pdev);
+ d->ctx = d->drawable.context();
+
+ if (d->ctx->d_ptr->active_engine) {
+ QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(d->ctx->d_ptr->active_engine);
+ QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr);
+ p->transferMode(BrushDrawingMode);
+ p->drawable.doneCurrent();
+ }
+
+ d->ctx->d_ptr->active_engine = this;
+ d->last_created_state = 0;
- QGLWidget* widget = static_cast<QGLWidget*>(pdev);
- d->ctx = const_cast<QGLContext*>(widget->context());
- d->ctx->makeCurrent();
- d->width = widget->width();
- d->height = widget->height();
+ d->drawable.makeCurrent();
+ QSize sz = d->drawable.size();
+ d->width = sz.width();
+ d->height = sz.height();
+ d->mode = BrushDrawingMode;
+
+#if !defined(QT_OPENGL_ES_2)
+ qt_resolve_version_2_0_functions(d->ctx);
+#endif
if (!d->shaderManager)
- d->shaderManager = new QGLPEXShaderManager(d->ctx);
+ d->shaderManager = new QGLEngineShaderManager(d->ctx);
glViewport(0, 0, d->width, d->height);
@@ -1018,264 +1169,378 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->brushUniformsDirty = true;
d->matrixDirty = true;
d->compositionModeDirty = true;
- d->stencilBuferDirty = true;
+ d->stencilBufferDirty = true;
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
d->use_system_clip = !systemClip().isEmpty();
glDisable(GL_DEPTH_TEST);
+ glDisable(GL_SCISSOR_TEST);
+ glDepthFunc(GL_LEQUAL);
+ glDepthMask(false);
+
+ QGLPixmapData *source = d->drawable.copyOnBegin();
+ if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) {
+ if (d->drawable.hasTransparentBackground())
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ else {
+ const QColor &c = d->drawable.backgroundColor();
+ float alpha = c.alphaF();
+ glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
+ }
+ glClear(GL_COLOR_BUFFER_BIT);
+ } else if (source) {
+ QGLContext *ctx = d->ctx;
+
+ d->transferMode(ImageDrawingMode);
+
+ glActiveTexture(GL_TEXTURE0 + QT_IMAGE_TEXTURE_UNIT);
+ source->bind(false);
+
+ QRect rect(0, 0, source->width(), source->height());
+ d->drawTexture(QRectF(rect), QRectF(rect), rect.size(), true);
+ }
+ d->systemStateChanged();
return true;
}
bool QGL2PaintEngineEx::end()
{
Q_D(QGL2PaintEngineEx);
- d->ctx->swapBuffers();
+ QGLContext *ctx = d->ctx;
+ if (ctx->d_ptr->active_engine != this) {
+ QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine);
+ if (engine && engine->isActive()) {
+ QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr);
+ p->transferMode(BrushDrawingMode);
+ p->drawable.doneCurrent();
+ }
+ d->drawable.makeCurrent();
+ }
+
+ glUseProgram(0);
+ d->transferMode(BrushDrawingMode);
+ d->drawable.swapBuffers();
+ d->drawable.doneCurrent();
+ d->ctx->d_ptr->active_engine = 0;
+
return false;
}
+void QGL2PaintEngineEx::ensureActive()
+{
+ Q_D(QGL2PaintEngineEx);
+ QGLContext *ctx = d->ctx;
+
+ if (isActive() && ctx->d_ptr->active_engine != this) {
+ QGL2PaintEngineEx *engine = static_cast<QGL2PaintEngineEx *>(ctx->d_ptr->active_engine);
+ if (engine && engine->isActive()) {
+ QGL2PaintEngineExPrivate *p = static_cast<QGL2PaintEngineExPrivate *>(engine->d_ptr);
+ p->transferMode(BrushDrawingMode);
+ p->drawable.doneCurrent();
+ }
+ d->drawable.makeCurrent();
+
+ ctx->d_ptr->active_engine = this;
+
+ glDisable(GL_DEPTH_TEST);
-/////////////////////////////////// State/Clipping stolen from QOpenGLPaintEngine //////////////////////////////////////////
+ glViewport(0, 0, d->width, d->height);
+
+ setState(state());
+ }
+}
+
+void QGL2PaintEngineExPrivate::updateDepthScissorTest()
+{
+ Q_Q(QGL2PaintEngineEx);
+ if (q->state()->depthTestEnabled)
+ glEnable(GL_DEPTH_TEST);
+ else
+ glDisable(GL_DEPTH_TEST);
+
+ if (q->state()->scissorTestEnabled)
+ glEnable(GL_SCISSOR_TEST);
+ else
+ glDisable(GL_SCISSOR_TEST);
+}
void QGL2PaintEngineEx::clipEnabledChanged()
{
Q_D(QGL2PaintEngineEx);
- d->updateDepthClip();
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
+
+ if (painter()->hasClipping()) {
+ d->regenerateDepthClip();
+ } else {
+ if (d->use_system_clip) {
+ state()->currentDepth = -0.5f;
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ state()->depthTestEnabled = false;
+ }
+ }
}
-void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
+void QGL2PaintEngineExPrivate::writeClip(const QVectorPath &path, float depth)
{
-// qDebug("QGL2PaintEngineEx::clip()");
- const qreal *points = path.points();
- const QPainterPath::ElementType *types = path.elements();
- if (!types && path.shape() == QVectorPath::RectangleHint) {
- QRectF r(points[0], points[1], points[4]-points[0], points[5]-points[1]);
- updateClipRegion(QRegion(r.toRect()), op);
- return;
- }
+ transferMode(BrushDrawingMode);
- 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 if (!path.isEmpty()) {
- 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 (matrixDirty)
+ updateMatrix();
+
+ if (q->state()->needsDepthBufferClear) {
+ glDepthMask(true);
+ glClearDepth(0.5);
+ glClear(GL_DEPTH_BUFFER_BIT);
+ q->state()->needsDepthBufferClear = false;
+ glDepthMask(false);
}
- if (path.hints() & QVectorPath::WindingFill)
- p.setFillRule(Qt::WindingFill);
- updateClipRegion(QRegion(p.toFillPolygon().toPolygon(), p.fillRule()), op);
- return;
+ if (path.isEmpty())
+ return;
+
+ glDisable(GL_BLEND);
+ glDepthMask(false);
+
+ vertexCoordinateArray.clear();
+ vertexCoordinateArray.addPath(path, inverseScale);
+
+ glDepthMask(GL_FALSE);
+ fillStencilWithVertexArray(vertexCoordinateArray, path.hasWindingFill());
+
+ // Stencil the clip onto the clip buffer
+ glColorMask(false, false, false, false);
+ glDepthMask(true);
+
+ shaderManager->simpleProgram()->setUniformValue("depth", depth);
+ simpleShaderDepthUniformDirty = true;
+
+ glEnable(GL_DEPTH_TEST);
+ glDepthFunc(GL_ALWAYS);
+
+ glStencilFunc(GL_NOTEQUAL, 0, 0xFFFF); // Pass if stencil buff value != 0
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
+
+ glEnable(GL_STENCIL_TEST);
+ composite(vertexCoordinateArray.boundingRect());
+ glDisable(GL_STENCIL_TEST);
+
+ glStencilMask(0);
+
+ glColorMask(true, true, true, true);
+ glDepthMask(false);
}
-void QGL2PaintEngineEx::updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op)
+void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op)
{
-// qDebug("QGL2PaintEngineEx::updateClipRegion()");
+// qDebug("QGL2PaintEngineEx::clip()");
Q_D(QGL2PaintEngineEx);
- QRegion sysClip = systemClip();
- if (op == Qt::NoClip && !d->use_system_clip) {
- state()->hasClipping = false;
- state()->clipRegion = QRegion();
- d->updateDepthClip();
- return;
- }
+ if (op == Qt::ReplaceClip && !d->hasClipOperations())
+ op = Qt::IntersectClip;
- bool isScreenClip = false;
- if (!d->use_system_clip) {
- QVector<QRect> untransformedRects = clipRegion.rects();
+ if (!path.isEmpty() && op == Qt::IntersectClip && (path.hints() & QVectorPath::RectangleHint)) {
+ const QPointF* const points = reinterpret_cast<const QPointF*>(path.points());
+ QRectF rect(points[0], points[2]);
- if (untransformedRects.size() == 1) {
- QPainterPath path;
- path.addRect(untransformedRects[0]);
- //path = d->matrix.map(path);
- path = state()->matrix.map(path);
-
-// if (path.contains(QRectF(QPointF(), d->drawable.size())))
-// isScreenClip = true;
- if (path.contains(QRectF(0.0, 0.0, d->width, d->height)))
- isScreenClip = true;
+ if (state()->matrix.type() <= QTransform::TxScale) {
+ rect = state()->matrix.mapRect(rect);
+
+ if (d->use_system_clip && rect.contains(d->systemClip.boundingRect())
+ || rect.contains(QRect(0, 0, d->width, d->height)))
+ return;
}
}
-// QRegion region = isScreenClip ? QRegion() : clipRegion * d->matrix;
- QRegion region = isScreenClip ? QRegion() : clipRegion * state()->matrix;
switch (op) {
case Qt::NoClip:
- if (!d->use_system_clip)
- break;
- state()->clipRegion = sysClip;
+ if (d->use_system_clip) {
+ glEnable(GL_DEPTH_TEST);
+ state()->depthTestEnabled = true;
+ state()->currentDepth = -0.5;
+ } else {
+ glDisable(GL_DEPTH_TEST);
+ state()->depthTestEnabled = false;
+ }
+ state()->canRestoreClip = false;
break;
case Qt::IntersectClip:
- if (isScreenClip)
- return;
- if (state()->hasClipping) {
- state()->clipRegion &= region;
- break;
- }
- // fall through
+ state()->maxDepth = (1.0f + state()->maxDepth) * 0.5;
+ d->writeClip(path, state()->maxDepth);
+ state()->currentDepth = 1.5 * state()->maxDepth - 0.5f;
+ state()->depthTestEnabled = true;
+ break;
case Qt::ReplaceClip:
- if (d->use_system_clip && !sysClip.isEmpty())
- state()->clipRegion = region & sysClip;
- else
- state()->clipRegion = region;
+ d->systemStateChanged();
+ state()->maxDepth = 0.5f;
+ glDepthFunc(GL_ALWAYS);
+ d->writeClip(path, state()->maxDepth);
+ state()->currentDepth = 0.25f;
+ state()->canRestoreClip = false;
+ state()->depthTestEnabled = true;
break;
case Qt::UniteClip:
- state()->clipRegion |= region;
- if (d->use_system_clip && !sysClip.isEmpty())
- state()->clipRegion &= sysClip;
- break;
- default:
+ glDepthFunc(GL_ALWAYS);
+ d->writeClip(path, state()->maxDepth);
+ state()->canRestoreClip = false;
+ state()->depthTestEnabled = true;
break;
}
- if (isScreenClip) {
- state()->hasClipping = false;
- state()->clipRegion = QRegion();
- } else {
- state()->hasClipping = op != Qt::NoClip || d->use_system_clip;
+ glDepthFunc(GL_LEQUAL);
+ if (state()->depthTestEnabled) {
+ glEnable(GL_DEPTH_TEST);
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
}
-
- if (state()->hasClipping && state()->clipRegion.rects().size() == 1)
- state()->fastClip = state()->clipRegion.rects().at(0);
- else
- state()->fastClip = QRect();
-
- d->updateDepthClip();
}
-
-void QGL2PaintEngineExPrivate::updateDepthClip()
+void QGL2PaintEngineExPrivate::regenerateDepthClip()
{
-// qDebug("QGL2PaintEngineExPrivate::updateDepthClip()");
+ systemStateChanged();
+ replayClipOperations();
+}
+void QGL2PaintEngineExPrivate::systemStateChanged()
+{
Q_Q(QGL2PaintEngineEx);
+ use_system_clip = !systemClip.isEmpty();
glDisable(GL_DEPTH_TEST);
+ q->state()->depthTestEnabled = false;
+ q->state()->scissorTestEnabled = false;
+ q->state()->needsDepthBufferClear = true;
+
glDisable(GL_SCISSOR_TEST);
- if (!q->state()->hasClipping)
- return;
+ q->state()->currentDepth = -0.5f;
+ q->state()->maxDepth = 0.5f;
- QRect fastClip;
- if (q->state()->clipEnabled) {
- fastClip = q->state()->fastClip;
- } else if (use_system_clip && q->systemClip().rects().count() == 1) {
- fastClip = q->systemClip().rects().at(0);
- }
+ if (use_system_clip) {
+ QRect bounds = systemClip.boundingRect();
+ if (systemClip.numRects() == 1
+ && bounds == QRect(0, 0, width, height))
+ {
+ q->state()->needsDepthBufferClear = true;
+ } else {
+ glEnable(GL_SCISSOR_TEST);
- if (!fastClip.isEmpty()) {
- glEnable(GL_SCISSOR_TEST);
+ const int left = bounds.left();
+ const int width = bounds.width();
+ const int bottom = height - (bounds.top() + bounds.height());
+ const int height = bounds.height();
- const int left = fastClip.left();
- const int width = fastClip.width();
- const int bottom = height - (fastClip.bottom() + 1);
- const int height = fastClip.height();
+ glScissor(left, bottom, width, height);
- glScissor(left, bottom, width, height);
- return;
- }
+ QTransform transform = q->state()->matrix;
+ q->state()->matrix = QTransform();
+ q->transformChanged();
- glClearDepthf(0x0);
- glDepthMask(true);
- glClear(GL_DEPTH_BUFFER_BIT);
- glClearDepthf(0x1);
+ q->state()->needsDepthBufferClear = false;
- const QVector<QRect> rects = q->state()->clipEnabled ? q->state()->clipRegion.rects() : q->systemClip().rects();
- glEnable(GL_SCISSOR_TEST);
- for (int i = 0; i < rects.size(); ++i) {
- QRect rect = rects.at(i);
+ glDepthMask(true);
- const int left = rect.left();
- const int width = rect.width();
- const int bottom = height - (rect.bottom() + 1);
- const int height = rect.height();
+ glClearDepth(0);
+ glClear(GL_DEPTH_BUFFER_BIT);
- glScissor(left, bottom, width, height);
+ QPainterPath path;
+ path.addRegion(systemClip);
- glClear(GL_DEPTH_BUFFER_BIT);
- }
- glDisable(GL_SCISSOR_TEST);
+ glDepthFunc(GL_ALWAYS);
+ writeClip(qtVectorPathForPath(path), 0.0f);
+ glDepthFunc(GL_LEQUAL);
- glDepthMask(false);
- glDepthFunc(GL_LEQUAL);
- glEnable(GL_DEPTH_TEST);
-}
+ glEnable(GL_DEPTH_TEST);
+ q->state()->depthTestEnabled = true;
+ q->state()->scissorTestEnabled = true;
+ q->state()->matrix = transform;
+ q->transformChanged();
+ }
+ q->state()->currentDepth = -0.5f;
+ simpleShaderDepthUniformDirty = true;
+ depthUniformDirty = true;
+ }
+}
-void QGL2PaintEngineEx::setState(QPainterState *s)
+void QGL2PaintEngineEx::setState(QPainterState *new_state)
{
-// qDebug("QGL2PaintEngineEx::setState()");
+ // qDebug("QGL2PaintEngineEx::setState()");
Q_D(QGL2PaintEngineEx);
+
+ QOpenGL2PaintEngineState *s = static_cast<QOpenGL2PaintEngineState *>(new_state);
+ QOpenGL2PaintEngineState *old_state = state();
+
QPaintEngineEx::setState(s);
- d->updateDepthClip();
+ if (s == d->last_created_state) {
+ d->last_created_state = 0;
+ return;
+ }
d->matrixDirty = true;
d->compositionModeDirty = true;
d->brushTextureDirty = true;
d->brushUniformsDirty = true;
+ d->simpleShaderDepthUniformDirty = true;
+ d->depthUniformDirty = true;
d->simpleShaderMatrixUniformDirty = true;
- d->brushShaderMatrixUniformDirty = true;
- d->imageShaderMatrixUniformDirty = true;
- d->textShaderMatrixUniformDirty = true;
+ d->shaderMatrixUniformDirty = true;
+
+ if (old_state && old_state != s && old_state->canRestoreClip) {
+ d->updateDepthScissorTest();
+ glDepthMask(false);
+ glDepthFunc(GL_LEQUAL);
+ s->maxDepth = old_state->maxDepth;
+ } else {
+ d->regenerateDepthClip();
+ }
}
QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const
{
- QOpenGLPaintEngineState *s;
+ Q_D(const QGL2PaintEngineEx);
+
+ QOpenGL2PaintEngineState *s;
if (!orig)
- s = new QOpenGLPaintEngineState();
+ s = new QOpenGL2PaintEngineState();
else
- s = new QOpenGLPaintEngineState(*static_cast<QOpenGLPaintEngineState *>(orig));
+ s = new QOpenGL2PaintEngineState(*static_cast<QOpenGL2PaintEngineState *>(orig));
+ d->last_created_state = s;
return s;
}
-QOpenGLPaintEngineState::QOpenGLPaintEngineState(QOpenGLPaintEngineState &other)
+QOpenGL2PaintEngineState::QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other)
: QPainterState(other)
{
- clipRegion = other.clipRegion;
- hasClipping = other.hasClipping;
- fastClip = other.fastClip;
+ needsDepthBufferClear = other.needsDepthBufferClear;
+ depthTestEnabled = other.depthTestEnabled;
+ scissorTestEnabled = other.scissorTestEnabled;
+ currentDepth = other.currentDepth;
+ maxDepth = other.maxDepth;
+ canRestoreClip = other.canRestoreClip;
}
-QOpenGLPaintEngineState::QOpenGLPaintEngineState()
+QOpenGL2PaintEngineState::QOpenGL2PaintEngineState()
{
- hasClipping = false;
+ needsDepthBufferClear = true;
+ depthTestEnabled = false;
+ scissorTestEnabled = false;
+ currentDepth = -0.5f;
+ maxDepth = 0.5f;
+ canRestoreClip = true;
}
-QOpenGLPaintEngineState::~QOpenGLPaintEngineState()
+QOpenGL2PaintEngineState::~QOpenGL2PaintEngineState()
{
}
+QT_END_NAMESPACE
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index ce66e4b..8a50096 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -53,21 +53,39 @@
// We mean it.
//
+#include <QDebug>
+
#include <private/qpaintengineex_p.h>
+#include <private/qglengineshadermanager_p.h>
+#include <private/qgl2pexvertexarray_p.h>
+
+enum EngineMode {
+ ImageDrawingMode,
+ TextDrawingMode,
+ BrushDrawingMode
+};
+
+QT_BEGIN_NAMESPACE
class QGL2PaintEngineExPrivate;
-class QOpenGLPaintEngineState : public QPainterState
+class QOpenGL2PaintEngineState : public QPainterState
{
public:
- QOpenGLPaintEngineState(QOpenGLPaintEngineState &other);
- QOpenGLPaintEngineState();
- ~QOpenGLPaintEngineState();
+ QOpenGL2PaintEngineState(QOpenGL2PaintEngineState &other);
+ QOpenGL2PaintEngineState();
+ ~QOpenGL2PaintEngineState();
- QRegion clipRegion;
- bool hasClipping;
- QRect fastClip;
+ bool needsDepthBufferClear;
+ qreal depthBufferClearValue;
+
+ bool depthTestEnabled;
+ bool scissorTestEnabled;
+ qreal currentDepth;
+ qreal maxDepth;
+
+ bool canRestoreClip;
};
@@ -81,6 +99,8 @@ public:
bool begin(QPaintDevice *device);
bool end();
+ void ensureActive();
+
virtual void fill(const QVectorPath &path, const QBrush &brush);
virtual void stroke(const QVectorPath &path, const QPen &pen);
virtual void clip(const QVectorPath &path, Qt::ClipOperation op);
@@ -100,26 +120,106 @@ public:
virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr,
Qt::ImageConversionFlags flags = Qt::AutoColor);
virtual void drawTextItem(const QPointF &p, const QTextItem &textItem);
- void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
Type type() const { return OpenGL; }
-
- // State stuff is just for clipping and ripped off from QGLPaintEngine
void setState(QPainterState *s);
QPainterState *createState(QPainterState *orig) const;
- inline QOpenGLPaintEngineState *state() {
- return static_cast<QOpenGLPaintEngineState *>(QPaintEngineEx::state());
+ inline QOpenGL2PaintEngineState *state() {
+ return static_cast<QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
- inline const QOpenGLPaintEngineState *state() const {
- return static_cast<const QOpenGLPaintEngineState *>(QPaintEngineEx::state());
+ inline const QOpenGL2PaintEngineState *state() const {
+ return static_cast<const QOpenGL2PaintEngineState *>(QPaintEngineEx::state());
}
- void updateClipRegion(const QRegion &clipRegion, Qt::ClipOperation op);
+ virtual void sync();
private:
Q_DISABLE_COPY(QGL2PaintEngineEx)
};
+class QGL2PaintEngineExPrivate : public QPaintEngineExPrivate
+{
+ Q_DECLARE_PUBLIC(QGL2PaintEngineEx)
+public:
+ QGL2PaintEngineExPrivate(QGL2PaintEngineEx *q_ptr) :
+ q(q_ptr),
+ width(0), height(0),
+ ctx(0),
+ currentBrush( &(q->state()->brush) ),
+ inverseScale(1),
+ shaderManager(0)
+ { }
+
+ ~QGL2PaintEngineExPrivate();
+
+ void updateBrushTexture();
+ void updateBrushUniforms();
+ void updateMatrix();
+ void updateCompositionMode();
+ void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform);
+
+ void setBrush(const QBrush* brush);
+
+ void transferMode(EngineMode newMode);
+
+ // fill, drawOutline, drawTexture & drawCachedGlyphs are the rendering entry points:
+ void fill(const QVectorPath &path);
+ void drawOutline(const QVectorPath& path);
+ void drawTexture(const QGLRect& dest, const QGLRect& src, const QSize &textureSize, bool opaque, bool pattern = false);
+ void drawCachedGlyphs(const QPointF &p, const QTextItemInt &ti);
+
+ void drawVertexArrays(QGL2PEXVertexArray& vertexArray, GLenum primitive);
+ // ^ draws whatever is in the vertex array
+ void composite(const QGLRect& boundingRect);
+ // ^ Composites the bounding rect onto dest buffer
+ void fillStencilWithVertexArray(QGL2PEXVertexArray& vertexArray, bool useWindingFill);
+ // ^ Calls drawVertexArrays to render into stencil buffer
+
+ void prepareForDraw(bool srcPixelsAreOpaque);
+
+ inline void useSimpleShader();
+ inline QColor premultiplyColor(QColor c, GLfloat opacity);
+
+ QGL2PaintEngineEx* q;
+ QGLDrawable drawable;
+ int width, height;
+ QGLContext *ctx;
+ EngineMode mode;
+
+ mutable QOpenGL2PaintEngineState *last_created_state;
+
+ // Dirty flags
+ bool matrixDirty; // Implies matrix uniforms are also dirty
+ bool compositionModeDirty;
+ bool brushTextureDirty;
+ bool brushUniformsDirty;
+ bool simpleShaderMatrixUniformDirty;
+ bool shaderMatrixUniformDirty;
+ bool stencilBufferDirty;
+ bool depthUniformDirty;
+ bool simpleShaderDepthUniformDirty;
+
+ const QBrush* currentBrush; // May not be the state's brush!
+
+ GLfloat inverseScale;
+
+ QGL2PEXVertexArray vertexCoordinateArray;
+ QGL2PEXVertexArray textureCoordinateArray;
+
+ GLfloat staticVertexCoordinateArray[8];
+ GLfloat staticTextureCoordinateArray[8];
+
+ GLfloat pmvMatrix[4][4];
+
+ QGLEngineShaderManager* shaderManager;
+
+ void writeClip(const QVectorPath &path, float depth);
+ void updateDepthScissorTest();
+ void regenerateDepthClip();
+ void systemStateChanged();
+ uint use_system_clip : 1;
+};
+QT_END_NAMESPACE
#endif
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 78aaddb..73af174 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -13,18 +13,15 @@ include(../qbase.pri)
!win32:!embedded:!mac:CONFIG += x11
contains(QT_CONFIG, opengl):CONFIG += opengl
contains(QT_CONFIG, opengles1):CONFIG += opengles1
+contains(QT_CONFIG, opengles1):CONFIG += opengles1cl
contains(QT_CONFIG, opengles2):CONFIG += opengles2
-!contains(QT_CONFIG, opengles2) {
- HEADERS += qgraphicssystem_gl_p.h qwindowsurface_gl_p.h qpixmapdata_gl_p.h
- SOURCES += qgraphicssystem_gl.cpp qwindowsurface_gl.cpp qpixmapdata_gl.cpp
-}
-
HEADERS += qgl.h \
qgl_p.h \
qglcolormap.h \
qglpixelbuffer.h \
qglframebufferobject.h \
+ qglextensions_p.h
SOURCES += qgl.cpp \
qglcolormap.cpp \
@@ -33,25 +30,34 @@ SOURCES += qgl.cpp \
qglextensions.cpp \
!contains(QT_CONFIG, opengles2) {
- HEADERS += qpaintengine_opengl_p.h qglpixmapfilter_p.h
- SOURCES += qpaintengine_opengl.cpp qglpixmapfilter.cpp
+ HEADERS += qpaintengine_opengl_p.h
+ SOURCES += qpaintengine_opengl.cpp
}
-contains(QT_CONFIG, opengles2) {
- SOURCES += gl2paintengineex/qglgradientcache.cpp \
- gl2paintengineex/qglpexshadermanager.cpp \
- gl2paintengineex/qglshader.cpp \
+!contains(QT_CONFIG, opengles1):!contains(QT_CONFIG, opengles1cl) {
+ HEADERS += qglshaderprogram.h \
+ qglpixmapfilter_p.h \
+ qgraphicssystem_gl_p.h \
+ qwindowsurface_gl_p.h \
+ qpixmapdata_gl_p.h \
+ gl2paintengineex/qglgradientcache_p.h \
+ gl2paintengineex/qglengineshadermanager_p.h \
+ gl2paintengineex/qgl2pexvertexarray_p.h \
+ gl2paintengineex/qpaintengineex_opengl2_p.h \
+ gl2paintengineex/qglengineshadersource_p.h
+
+ SOURCES += qglshaderprogram.cpp \
+ qglpixmapfilter.cpp \
+ qgraphicssystem_gl.cpp \
+ qwindowsurface_gl.cpp \
+ qpixmapdata_gl.cpp \
+ gl2paintengineex/qglgradientcache.cpp \
+ gl2paintengineex/qglengineshadermanager.cpp \
gl2paintengineex/qgl2pexvertexarray.cpp \
gl2paintengineex/qpaintengineex_opengl2.cpp
- HEADERS += gl2paintengineex/qglgradientcache_p.h \
- gl2paintengineex/qglpexshadermanager_p.h \
- gl2paintengineex/qglshader_p.h \
- gl2paintengineex/qgl2pexvertexarray_p.h \
- gl2paintengineex/qpaintengineex_opengl2_p.h
}
-
x11 {
contains(QT_CONFIG, opengles1)|contains(QT_CONFIG, opengles1cl)|contains(QT_CONFIG, opengles2) {
SOURCES += qgl_x11egl.cpp \
diff --git a/src/opengl/qegl.cpp b/src/opengl/qegl.cpp
index 165a0f3..290f77c 100644
--- a/src/opengl/qegl.cpp
+++ b/src/opengl/qegl.cpp
@@ -119,7 +119,7 @@ bool QEglContext::chooseConfig
if (red == props.value(EGL_RED_SIZE) &&
green == props.value(EGL_GREEN_SIZE) &&
blue == props.value(EGL_BLUE_SIZE) &&
- (props.value(EGL_ALPHA_SIZE) == EGL_DONT_CARE ||
+ (props.value(EGL_ALPHA_SIZE) == 0 ||
alpha == props.value(EGL_ALPHA_SIZE))) {
cfg = configs[index];
delete [] configs;
@@ -405,7 +405,62 @@ int QEglProperties::value(int name) const
if (props[index] == name)
return props[index + 1];
}
- return EGL_DONT_CARE;
+
+ // If the attribute has not been explicitly set, return the EGL default
+ // The following defaults were taken from the EGL 1.4 spec:
+ switch(name) {
+ case EGL_BUFFER_SIZE: return 0;
+ case EGL_RED_SIZE: return 0;
+ case EGL_GREEN_SIZE: return 0;
+ case EGL_BLUE_SIZE: return 0;
+ case EGL_ALPHA_SIZE: return 0;
+#if defined(EGL_LUMINANCE_SIZE)
+ case EGL_LUMINANCE_SIZE: return 0;
+#endif
+#if defined(EGL_ALPHA_MASK_SIZE)
+ case EGL_ALPHA_MASK_SIZE: return 0;
+#endif
+ case EGL_BIND_TO_TEXTURE_RGB: return EGL_DONT_CARE;
+ case EGL_BIND_TO_TEXTURE_RGBA: return EGL_DONT_CARE;
+#if defined(EGL_COLOR_BUFFER_TYPE)
+ case EGL_COLOR_BUFFER_TYPE: return EGL_RGB_BUFFER;
+#endif
+ case EGL_CONFIG_CAVEAT: return EGL_DONT_CARE;
+ case EGL_CONFIG_ID: return EGL_DONT_CARE;
+ case EGL_DEPTH_SIZE: return 0;
+ case EGL_LEVEL: return 0;
+ case EGL_NATIVE_RENDERABLE: return EGL_DONT_CARE;
+ case EGL_NATIVE_VISUAL_TYPE: return EGL_DONT_CARE;
+ case EGL_MAX_SWAP_INTERVAL: return EGL_DONT_CARE;
+ case EGL_MIN_SWAP_INTERVAL: return EGL_DONT_CARE;
+#if defined(EGL_RENDERABLE_TYPE)
+ case EGL_RENDERABLE_TYPE: return EGL_OPENGL_ES_BIT;
+#endif
+ case EGL_SAMPLE_BUFFERS: return 0;
+ case EGL_SAMPLES: return 0;
+ case EGL_STENCIL_SIZE: return 0;
+ case EGL_SURFACE_TYPE: return EGL_WINDOW_BIT;
+ case EGL_TRANSPARENT_TYPE: return EGL_NONE;
+ case EGL_TRANSPARENT_RED_VALUE: return EGL_DONT_CARE;
+ case EGL_TRANSPARENT_GREEN_VALUE: return EGL_DONT_CARE;
+ case EGL_TRANSPARENT_BLUE_VALUE: return EGL_DONT_CARE;
+
+#if defined(EGL_VERSION_1_3)
+ case EGL_CONFORMANT: return 0;
+ case EGL_MATCH_NATIVE_PIXMAP: return EGL_NONE;
+#endif
+
+ case EGL_MAX_PBUFFER_HEIGHT:
+ case EGL_MAX_PBUFFER_WIDTH:
+ case EGL_MAX_PBUFFER_PIXELS:
+ case EGL_NATIVE_VISUAL_ID:
+ case EGL_NONE:
+ qWarning("QEglProperties::value() - Attibute %d does not affect config selection", name);
+ return EGL_DONT_CARE;
+ default:
+ qWarning("QEglProperties::value() - Attibute %d is unknown in EGL <=1.4", name);
+ return EGL_DONT_CARE;
+ }
}
// Set the value associated with a property, replacing an existing
@@ -535,7 +590,7 @@ QString QEglProperties::toString() const
if (val != EGL_DONT_CARE) {
str += QLatin1String("id=");
str += QString::number(val);
- str += QLatin1String(" ");
+ str += QLatin1Char(' ');
}
#ifdef EGL_RENDERABLE_TYPE
@@ -570,11 +625,11 @@ QString QEglProperties::toString() const
bufferSize = EGL_DONT_CARE;
str += QLatin1String(" rgba=");
str += QString::number(red);
- str += QLatin1String(",");
+ str += QLatin1Char(',');
str += QString::number(green);
- str += QLatin1String(",");
+ str += QLatin1Char(',');
str += QString::number(blue);
- str += QLatin1String(",");
+ str += QLatin1Char(',');
str += QString::number(alpha);
if (bufferSize != EGL_DONT_CARE) {
// Only report buffer size if different than r+g+b+a.
@@ -593,13 +648,13 @@ QString QEglProperties::toString() const
#endif
val = value(EGL_DEPTH_SIZE);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" depth="));
str += QString::number(val);
}
val = value(EGL_STENCIL_SIZE);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" stencil="));
str += QString::number(val);
}
@@ -649,7 +704,7 @@ QString QEglProperties::toString() const
}
val = value(EGL_LEVEL);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" level="));
str += QString::number(val);
}
@@ -661,7 +716,7 @@ QString QEglProperties::toString() const
if (height != EGL_DONT_CARE || width != EGL_DONT_CARE) {
addTag(str, QLatin1String(" max-pbuffer-size="));
str += QString::number(width);
- str += QLatin1String("x");
+ str += QLatin1Char('x');
str += QString::number(height);
if (pixels != (width * height)) {
addTag(str, QLatin1String(" max-pbuffer-pixels="));
@@ -700,13 +755,13 @@ QString QEglProperties::toString() const
#endif
val = value(EGL_SAMPLES);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" samples="));
str += QString::number(val);
}
val = value(EGL_SAMPLE_BUFFERS);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" sample-buffers="));
str += QString::number(val);
}
@@ -715,9 +770,9 @@ QString QEglProperties::toString() const
if (val == EGL_TRANSPARENT_RGB) {
addTag(str, QLatin1String(" transparent-rgb="));
str += QString::number(value(EGL_TRANSPARENT_RED_VALUE));
- str += QLatin1String(",");
+ str += QLatin1Char(',');
str += QString::number(value(EGL_TRANSPARENT_GREEN_VALUE));
- str += QLatin1String(",");
+ str += QLatin1Char(',');
str += QString::number(value(EGL_TRANSPARENT_BLUE_VALUE));
}
@@ -755,7 +810,7 @@ QString QEglProperties::toString() const
#ifdef EGL_LUMINANCE_SIZE
val = value(EGL_LUMINANCE_SIZE);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" luminance="));
str += QString::number(val);
}
@@ -763,7 +818,7 @@ QString QEglProperties::toString() const
#ifdef EGL_ALPHA_MASK_SIZE
val = value(EGL_ALPHA_MASK_SIZE);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
addTag(str, QLatin1String(" alpha-mask="));
str += QString::number(val);
}
@@ -771,7 +826,7 @@ QString QEglProperties::toString() const
#ifdef EGL_CONFORMANT
val = value(EGL_CONFORMANT);
- if (val != EGL_DONT_CARE) {
+ if (val != 0) {
if (val)
addTag(str, QLatin1String(" conformant=true"));
else
diff --git a/src/opengl/qegl_x11egl.cpp b/src/opengl/qegl_x11egl.cpp
index 8efe7e7..c703900 100644
--- a/src/opengl/qegl_x11egl.cpp
+++ b/src/opengl/qegl_x11egl.cpp
@@ -42,6 +42,7 @@
#include <QtGui/qpaintdevice.h>
#include <QtGui/qpixmap.h>
#include <QtGui/qwidget.h>
+#include <QtCore/qdebug.h>
#include "qegl_p.h"
#if defined(QT_OPENGL_ES) || defined(QT_OPENVG)
@@ -80,8 +81,10 @@ bool QEglContext::createSurface(QPaintDevice *device)
surf = eglCreateWindowSurface(dpy, cfg, windowDrawable, 0);
else
surf = eglCreatePixmapSurface(dpy, cfg, pixmapDrawable, 0);
+
if (surf == EGL_NO_SURFACE) {
- qWarning("QEglContext::createSurface(): Unable to create EGL surface, error = 0x%x", eglGetError());
+ qWarning() << "QEglContext::createSurface(): Unable to create EGL surface:"
+ << errorString(eglGetError());
return false;
}
return true;
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index cd7a7f0..c0c7781 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -65,15 +65,27 @@
#include "qimage.h"
#include "qgl_p.h"
-#if defined(QT_OPENGL_ES_2)
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
#include "gl2paintengineex/qpaintengineex_opengl2_p.h"
-#else
+#endif
+
+#ifndef QT_OPENGL_ES_2
#include <private/qpaintengine_opengl_p.h>
#endif
+#ifdef Q_WS_QWS
+#include <private/qglpaintdevice_qws_p.h>
+#include <private/qglwindowsurface_qws_p.h>
+#endif
+
+#include <qglpixelbuffer.h>
+#include <qglframebufferobject.h>
+
#include <private/qimage_p.h>
#include <private/qpixmapdata_p.h>
#include <private/qpixmapdata_gl_p.h>
+#include <private/qglpixelbuffer_p.h>
+#include <private/qwindowsurface_gl_p.h>
#include "qcolormap.h"
#include "qcache.h"
#include "qfile.h"
@@ -1290,6 +1302,7 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
eglContext = 0;
#endif
pbo = 0;
+ fbo = 0;
crWin = false;
initDone = false;
sharing = false;
@@ -1297,6 +1310,8 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format)
max_texture_size = -1;
version_flags_cached = false;
version_flags = QGLFormat::OpenGL_Version_None;
+ current_fbo = 0;
+ active_engine = 0;
}
QGLContext* QGLContext::currentCtx = 0;
@@ -1307,12 +1322,8 @@ QGLContext* QGLContext::currentCtx = 0;
QGLFramebufferObject::toImage()
*/
-QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
+static void convertFromGLImage(QImage &img, int w, int h, bool alpha_format, bool include_alpha)
{
- QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
- int w = size.width();
- int h = size.height();
- glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
// OpenGL gives RGBA; Qt wants ARGB
uint *p = (uint*)img.bits();
@@ -1343,7 +1354,30 @@ QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include
}
}
- return img.mirrored();
+ img = img.mirrored();
+}
+
+QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
+{
+ QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
+ int w = size.width();
+ int h = size.height();
+ glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
+ convertFromGLImage(img, w, h, alpha_format, include_alpha);
+ return img;
+}
+
+QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha)
+{
+ QImage img(size, alpha_format ? QImage::Format_ARGB32 : QImage::Format_RGB32);
+ int w = size.width();
+ int h = size.height();
+#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ //### glGetTexImage not in GL ES 2.0, need to do something else here!
+ glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
+#endif
+ convertFromGLImage(img, w, h, alpha_format, include_alpha);
+ return img;
}
// returns the highest number closest to v, which is a power of 2
@@ -1429,7 +1463,7 @@ struct DDSFormat {
#define GL_GENERATE_MIPMAP_HINT_SGIS 0x8192
#endif
-Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg);
+Q_GLOBAL_STATIC(QGLShareRegister, _qgl_share_reg)
Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg()
{
return _qgl_share_reg();
@@ -1546,7 +1580,7 @@ void QGLContextPrivate::cleanup()
Q_Q(QGLContext);
if (pbo) {
QGLContext *ctx = q;
- glDeleteBuffersARB(1, &pbo);
+ glDeleteBuffers(1, &pbo);
pbo = 0;
}
}
@@ -1683,58 +1717,105 @@ static void qt_gl_clean_cache(qint64 cacheKey)
static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum texture_format)
{
- Q_ASSERT(dst.size() == img.size());
Q_ASSERT(dst.depth() == 32);
Q_ASSERT(img.depth() == 32);
- const int width = img.width();
- const int height = img.height();
- const uint *p = (const uint*) img.scanLine(img.height() - 1);
- uint *q = (uint*) dst.scanLine(0);
-
- if (texture_format == GL_BGRA) {
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- // mirror + swizzle
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = ((*p << 24) & 0xff000000)
- | ((*p >> 24) & 0x000000ff)
- | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00);
- p++;
- q++;
+ if (dst.size() != img.size()) {
+ int target_width = dst.width();
+ int target_height = dst.height();
+ qreal sx = target_width / qreal(img.width());
+ qreal sy = target_height / qreal(img.height());
+
+ quint32 *dest = (quint32 *) dst.scanLine(0); // NB! avoid detach here
+ uchar *srcPixels = (uchar *) img.scanLine(img.height() - 1);
+ int sbpl = img.bytesPerLine();
+ int dbpl = dst.bytesPerLine();
+
+ int ix = 0x00010000 / sx;
+ int iy = 0x00010000 / sy;
+
+ quint32 basex = int(0.5 * ix);
+ quint32 srcy = int(0.5 * iy);
+
+ // scale, swizzle and mirror in one loop
+ while (target_height--) {
+ const uint *src = (const quint32 *) (srcPixels - (srcy >> 16) * sbpl);
+ int srcx = basex;
+ for (int x=0; x<target_width; ++x) {
+ uint src_pixel = src[srcx >> 16];
+ if (texture_format == GL_BGRA) {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ dest[x] = ((src_pixel << 24) & 0xff000000)
+ | ((src_pixel >> 24) & 0x000000ff)
+ | ((src_pixel << 8) & 0x00ff0000)
+ | ((src_pixel >> 8) & 0x0000ff00);
+ } else {
+ dest[x] = src_pixel;
+ }
+ } else { // GL_RGBA
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ dest[x] = (src_pixel << 8) | ((src_pixel >> 24) & 0xff);
+ } else {
+ dest[x] = ((src_pixel << 16) & 0xff0000)
+ | ((src_pixel >> 16) & 0xff)
+ | (src_pixel & 0xff00ff00);
+ }
}
- p -= 2 * width;
- }
- } else {
- const uint bytesPerLine = img.bytesPerLine();
- for (int i=0; i < height; ++i) {
- memcpy(q, p, bytesPerLine);
- q += width;
- p -= width;
+ srcx += ix;
}
+ dest = (quint32 *)(((uchar *) dest) + dbpl);
+ srcy += iy;
}
} else {
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = (*p << 8) | ((*p >> 24) & 0xFF);
- p++;
- q++;
+ const int width = img.width();
+ const int height = img.height();
+ const uint *p = (const uint*) img.scanLine(img.height() - 1);
+ uint *q = (uint*) dst.scanLine(0);
+
+ if (texture_format == GL_BGRA) {
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ // mirror + swizzle
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = ((*p << 24) & 0xff000000)
+ | ((*p >> 24) & 0x000000ff)
+ | ((*p << 8) & 0x00ff0000)
+ | ((*p >> 8) & 0x0000ff00);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ } else {
+ const uint bytesPerLine = img.bytesPerLine();
+ for (int i=0; i < height; ++i) {
+ memcpy(q, p, bytesPerLine);
+ q += width;
+ p -= width;
}
- p -= 2 * width;
}
} else {
- for (int i=0; i < height; ++i) {
- const uint *end = p + width;
- while (p < end) {
- *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
- p++;
- q++;
+ if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = (*p << 8) | ((*p >> 24) & 0xff);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
+ }
+ } else {
+ for (int i=0; i < height; ++i) {
+ const uint *end = p + width;
+ while (p < end) {
+ *q = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
+ p++;
+ q++;
+ }
+ p -= 2 * width;
}
- p -= 2 * width;
}
}
}
@@ -1764,7 +1845,7 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint
use_pbo = qt_resolve_buffer_extensions(ctx);
if (use_pbo && pbo == 0)
- glGenBuffersARB(1, &pbo);
+ glGenBuffers(1, &pbo);
}
// the GL_BGRA format is only present in GL version >= 1.2
@@ -1777,19 +1858,18 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint
}
// Scale the pixmap if needed. GL textures needs to have the
- // dimensions 2^n+2(border) x 2^m+2(border).
+ // dimensions 2^n+2(border) x 2^m+2(border), unless we're using GL
+ // 2.0 or use the GL_TEXTURE_RECTANGLE texture target
int tx_w = qt_next_power_of_two(image.width());
int tx_h = qt_next_power_of_two(image.height());
+ bool scale = false;
- // Note: the clean param is only true when a texture is bound
- // from the QOpenGLPaintEngine - in that case we have to force
- // a premultiplied texture format
QImage img = image;
if (( !(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0) &&
!(QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_ES_Version_2_0) )
&& (target == GL_TEXTURE_2D && (tx_w != image.width() || tx_h != image.height())))
{
- img = image.scaled(tx_w, tx_h);
+ scale = true;
}
GLuint tx_id;
@@ -1816,28 +1896,35 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint
uchar *ptr = 0;
if (use_pbo) {
- glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
- glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, img.width() * img.height() * 4, 0, GL_STREAM_DRAW_ARB);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, pbo);
+ glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, img.width() * img.height() * 4, 0, GL_STREAM_DRAW_ARB);
ptr = reinterpret_cast<uchar *>(glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB));
}
- if (ptr) {
- QImage::Format target_format = img.format();
- if (clean || img.format() != QImage::Format_ARGB32)
- target_format = QImage::Format_ARGB32_Premultiplied;
+ QImage::Format target_format = img.format();
+ // Note: the clean param is only true when a texture is bound
+ // from the QOpenGLPaintEngine - in that case we have to force
+ // a premultiplied texture format
+ if (clean || img.format() != QImage::Format_ARGB32)
+ target_format = QImage::Format_ARGB32_Premultiplied;
+ if (img.format() != target_format)
+ img = img.convertToFormat(target_format);
+ if (ptr) {
QImage buffer(ptr, img.width(), img.height(), target_format);
- convertToGLFormatHelper(buffer, img.convertToFormat(target_format), texture_format);
+ convertToGLFormatHelper(buffer, img, texture_format);
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
- glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format, GL_UNSIGNED_BYTE, 0);
+ glTexImage2D(target, 0, format, img.width(), img.height(), 0, texture_format,
+ GL_UNSIGNED_BYTE, 0);
} else {
- QImage tx = convertToGLFormat(img, clean, texture_format);
+ QImage tx(scale ? QSize(tx_w, tx_h) : img.size(), target_format);
+ convertToGLFormatHelper(tx, img, texture_format);
glTexImage2D(target, 0, format, tx.width(), tx.height(), 0, texture_format,
GL_UNSIGNED_BYTE, tx.bits());
}
if (use_pbo)
- glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
// this assumes the size of a texture is always smaller than the max cache size
int cost = img.width()*img.height()*4/1024;
@@ -1889,11 +1976,13 @@ GLuint QGLContextPrivate::bindTexture(const QImage &image, GLenum target, GLint
/*! \internal */
GLuint QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, GLint format, bool clean)
{
-#if !defined(QT_OPENGL_ES_2)
- if (target == qt_gl_preferredTextureTarget() && pixmap.pixmapData()->classId() == QPixmapData::OpenGLClass) {
- const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pixmap.pixmapData());
+ Q_Q(QGLContext);
+ QPixmapData *pd = pixmap.pixmapData();
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ if (target == GL_TEXTURE_2D && pd->classId() == QPixmapData::OpenGLClass) {
+ const QGLPixmapData *data = static_cast<const QGLPixmapData *>(pd);
- if (data->isValidContext(QGLContext::currentContext()))
+ if (data->isValidContext(q))
return data->bind();
}
#endif
@@ -2045,12 +2134,34 @@ void QGLContext::deleteTexture(QMacCompatGLuint id)
}
#endif
-// qpaintengine_opengl.cpp
-#if !defined(QT_OPENGL_ES_2)
-extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
-#else
-void qt_add_rect_to_array(const QRectF &r, q_vertexType *array) {};
-#endif
+void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
+{
+ qreal left = r.left();
+ qreal right = r.right();
+ qreal top = r.top();
+ qreal bottom = r.bottom();
+
+ array[0] = f2vt(left);
+ array[1] = f2vt(top);
+ array[2] = f2vt(right);
+ array[3] = f2vt(top);
+ array[4] = f2vt(right);
+ array[5] = f2vt(bottom);
+ array[6] = f2vt(left);
+ array[7] = f2vt(bottom);
+}
+
+void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
+{
+ array[0] = f2vt(x1);
+ array[1] = f2vt(y1);
+ array[2] = f2vt(x2);
+ array[3] = f2vt(y1);
+ array[4] = f2vt(x2);
+ array[5] = f2vt(y2);
+ array[6] = f2vt(x1);
+ array[7] = f2vt(y2);
+}
static void qDrawTextureRect(const QRectF &target, GLint textureWidth, GLint textureHeight, GLenum textureTarget)
{
@@ -2504,7 +2615,7 @@ const QGLContext* QGLContext::currentContext()
*/
/*! \fn int QGLContext::choosePixelFormat(void* dummyPfd, HDC pdc)
-
+
\bold{Win32 only:} This virtual function chooses a pixel format
that matches the OpenGL \link setFormat() format\endlink.
Reimplement this function in a subclass if you need a custom
@@ -2518,7 +2629,7 @@ const QGLContext* QGLContext::currentContext()
*/
/*! \fn void *QGLContext::chooseVisual()
-
+
\bold{X11 only:} This virtual function tries to find a visual that
matches the format, reducing the demands if the original request
cannot be met.
@@ -3237,7 +3348,7 @@ bool QGLWidget::event(QEvent *e)
glFinish();
doneCurrent();
} else if (e->type() == QEvent::ParentChange) {
- if (d->glcx->d_func()->screen != d->xinfo.screen()) {
+ if (d->glcx->d_func()->screen != d->xinfo.screen() || testAttribute(Qt::WA_TranslucentBackground)) {
setContext(new QGLContext(d->glcx->requestedFormat(), this));
// ### recreating the overlay isn't supported atm
}
@@ -4093,14 +4204,16 @@ void QGLWidget::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QM
}
#endif
-#if defined(QT_OPENGL_ES_2)
-Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_engine)
-#else
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_2_engine)
+#endif
+
+#ifndef QT_OPENGL_ES_2
Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_engine)
#endif
#ifdef Q_WS_QWS
-Q_OPENGL_EXPORT QOpenGLPaintEngine* qt_qgl_paint_engine()
+Q_OPENGL_EXPORT QPaintEngine* qt_qgl_paint_engine()
{
#if !defined(QT_OPENGL_ES_2)
return qt_gl_engine();
@@ -4118,7 +4231,16 @@ Q_OPENGL_EXPORT QOpenGLPaintEngine* qt_qgl_paint_engine()
*/
QPaintEngine *QGLWidget::paintEngine() const
{
+#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
return qt_gl_engine();
+#elif defined(QT_OPENGL_ES_2)
+ return qt_gl_2_engine();
+#else
+ if (!qt_gl_preferGL2Engine())
+ return qt_gl_engine();
+ else
+ return qt_gl_2_engine();
+#endif
}
#ifdef QT3_SUPPORT
@@ -4207,6 +4329,8 @@ void QGLExtensions::init_extensions()
glExtensions |= FramebufferObject;
glExtensions |= GenerateMipmap;
#endif
+ if (extensions.contains(QLatin1String("EXT_framebuffer_blit")))
+ glExtensions |= FramebufferBlit;
QGLContext cx(QGLFormat::defaultFormat());
if (glExtensions & TextureCompression) {
@@ -4236,7 +4360,7 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi
}
#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS)
-Q_GLOBAL_STATIC(QString, qt_gl_lib_name);
+Q_GLOBAL_STATIC(QString, qt_gl_lib_name)
Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name)
{
@@ -4247,7 +4371,7 @@ Q_OPENGL_EXPORT const QString qt_gl_library_name()
{
if (qt_gl_lib_name()->isNull()) {
#if defined(Q_WS_X11) || defined(Q_WS_QWS)
- return QString(QLatin1String("GL"));
+ return QLatin1String("GL");
#else // Q_WS_MAC
return QLatin1String("/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib");
#endif
@@ -4256,4 +4380,234 @@ Q_OPENGL_EXPORT const QString qt_gl_library_name()
}
#endif
+void QGLDrawable::setDevice(QPaintDevice *pdev)
+{
+ wasBound = false;
+ widget = 0;
+ buffer = 0;
+ fbo = 0;
+#ifdef Q_WS_QWS
+ wsurf = 0;
+#endif
+
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ if (pdev->devType() == QInternal::Pixmap) {
+ QPixmapData *data = static_cast<QPixmap *>(pdev)->pixmapData();
+ Q_ASSERT(data->classId() == QPixmapData::OpenGLClass);
+ pixmapData = static_cast<QGLPixmapData *>(data);
+
+ fbo = pixmapData->fbo();
+ }
+#else
+ Q_ASSERT(pdev->devType() != QInternal::Pixmap);
+#endif
+
+ if (pdev->devType() == QInternal::Widget)
+ widget = static_cast<QGLWidget *>(pdev);
+ else if (pdev->devType() == QInternal::Pbuffer)
+ buffer = static_cast<QGLPixelBuffer *>(pdev);
+ else if (pdev->devType() == QInternal::FramebufferObject)
+ fbo = static_cast<QGLFramebufferObject *>(pdev);
+#ifdef Q_WS_QWS
+ else if (pdev->devType() == QInternal::UnknownDevice)
+ wsurf = static_cast<QWSGLPaintDevice*>(pdev)->windowSurface();
+#elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ else if (pdev->devType() == QInternal::UnknownDevice)
+ wsurf = static_cast<QGLWindowSurface *>(pdev);
+#endif
+}
+
+void QGLDrawable::swapBuffers()
+{
+ if (widget) {
+ if (widget->autoBufferSwap())
+ widget->swapBuffers();
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ } else if (pixmapData) {
+ pixmapData->swapBuffers();
+#endif
+ } else {
+ glFlush();
+ }
+}
+
+void QGLDrawable::makeCurrent()
+{
+ previous_fbo = 0;
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ if (!pixmapData && !fbo) {
+#else
+ if (!fbo) {
+#endif
+ QGLContext *ctx = context();
+ previous_fbo = ctx->d_ptr->current_fbo;
+ ctx->d_ptr->current_fbo = 0;
+ if (previous_fbo)
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0);
+ }
+
+ if (widget)
+ widget->makeCurrent();
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ else if (pixmapData)
+ pixmapData->makeCurrent();
+#endif
+ else if (buffer)
+ buffer->makeCurrent();
+#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
+ else if (wsurf)
+ wsurf->context()->makeCurrent();
+#endif
+ else if (fbo) {
+ wasBound = fbo->isBound();
+ if (!wasBound)
+ fbo->bind();
+ }
+}
+
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+QGLPixmapData *QGLDrawable::copyOnBegin() const
+{
+ if (!pixmapData || pixmapData->isUninitialized())
+ return 0;
+ return pixmapData;
+}
+#endif
+
+void QGLDrawable::doneCurrent()
+{
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ if (pixmapData) {
+ pixmapData->doneCurrent();
+ return;
+ }
+#endif
+
+ if (previous_fbo) {
+ QGLContext *ctx = context();
+ ctx->d_ptr->current_fbo = previous_fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, previous_fbo);
+ }
+
+ if (fbo && !wasBound)
+ fbo->release();
+}
+
+QSize QGLDrawable::size() const
+{
+ if (widget) {
+ return QSize(widget->d_func()->glcx->device()->width(),
+ widget->d_func()->glcx->device()->height());
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ } else if (pixmapData) {
+ return pixmapData->size();
+#endif
+ } else if (buffer) {
+ return buffer->size();
+ } else if (fbo) {
+ return fbo->size();
+ }
+#ifdef Q_WS_QWS
+ else if (wsurf)
+ return wsurf->window()->frameSize();
+#elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ else if (wsurf)
+ return QSize(wsurf->width(), wsurf->height());
+#endif
+ return QSize();
+}
+
+QGLFormat QGLDrawable::format() const
+{
+ if (widget)
+ return widget->format();
+ else if (buffer)
+ return buffer->format();
+#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
+ else if (wsurf)
+ return wsurf->context()->format();
+#endif
+ else if (fbo && QGLContext::currentContext()) {
+ QGLFormat fmt = QGLContext::currentContext()->format();
+ fmt.setStencil(fbo->attachment() == QGLFramebufferObject::CombinedDepthStencil);
+ fmt.setDepth(fbo->attachment() != QGLFramebufferObject::NoAttachment);
+ return fmt;
+ }
+
+ return QGLFormat();
+}
+
+GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
+{
+ if (widget)
+ return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
+ else if (buffer)
+ return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
+ else if (fbo && QGLContext::currentContext())
+ return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
+#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
+ else if (wsurf)
+ return wsurf->context()->d_func()->bindTexture(image, target, format, true);
+#endif
+ return 0;
+}
+
+GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
+{
+ if (widget)
+ return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true);
+ else if (buffer)
+ return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true);
+ else if (fbo && QGLContext::currentContext())
+ return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true);
+#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
+ else if (wsurf)
+ return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true);
+#endif
+ return 0;
+}
+
+QColor QGLDrawable::backgroundColor() const
+{
+ if (widget)
+ return widget->palette().brush(widget->backgroundRole()).color();
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ else if (pixmapData)
+ return pixmapData->fillColor();
+#endif
+ return QApplication::palette().brush(QPalette::Background).color();
+}
+
+bool QGLDrawable::hasTransparentBackground() const
+{
+ return widget && widget->testAttribute(Qt::WA_TranslucentBackground);
+}
+
+QGLContext *QGLDrawable::context() const
+{
+ if (widget)
+ return widget->d_func()->glcx;
+ else if (buffer)
+ return buffer->d_func()->qctx;
+ else if (fbo)
+ return const_cast<QGLContext *>(QGLContext::currentContext());
+#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
+ else if (wsurf)
+ return wsurf->context();
+#endif
+ return 0;
+}
+
+bool QGLDrawable::autoFillBackground() const
+{
+ if (widget)
+ return widget->autoFillBackground();
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ else if (pixmapData)
+ return pixmapData->needsFill();
+#endif
+ else
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/qgl.h b/src/opengl/qgl.h
index b7b2f36..2d987fe 100644
--- a/src/opengl/qgl.h
+++ b/src/opengl/qgl.h
@@ -364,6 +364,7 @@ private:
friend class QGLWindowSurface;
friend class QGLPixmapData;
friend class QGLPixmapFilterBase;
+ friend class QGLTextureGlyphCache;
friend QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags();
#ifdef Q_WS_MAC
public:
@@ -372,9 +373,9 @@ private:
friend class QMacGLWindowChangeEvent;
friend QGLContextPrivate *qt_phonon_get_dptr(const QGLContext *);
#endif
-#ifdef Q_WS_WIN
friend class QGLFramebufferObject;
friend class QGLFramebufferObjectPrivate;
+#ifdef Q_WS_WIN
friend bool qt_resolve_GLSL_functions(QGLContext *ctx);
friend bool qt_createGLSLProgram(QGLContext *ctx, GLuint &program, const char *shader_src, GLuint &shader);
#endif
diff --git a/src/opengl/qgl_egl.cpp b/src/opengl/qgl_egl.cpp
index 98c5710..287c537 100644
--- a/src/opengl/qgl_egl.cpp
+++ b/src/opengl/qgl_egl.cpp
@@ -57,14 +57,14 @@ void qt_egl_set_format(QEglProperties& props, int deviceType, const QGLFormat& f
// Set the pixel format to that contained in the QGLFormat
// if the system hasn't already chosen a fixed format to
// match the pixmap, widget, etc.
- if (props.value(EGL_RED_SIZE) == EGL_DONT_CARE || f.redBufferSize() != -1)
+ if (props.value(EGL_RED_SIZE) == 0 || f.redBufferSize() != -1)
props.setValue(EGL_RED_SIZE, f.redBufferSize() == -1 ? 1 : f.redBufferSize());
- if (props.value(EGL_GREEN_SIZE) == EGL_DONT_CARE || f.greenBufferSize() != -1)
+ if (props.value(EGL_GREEN_SIZE) == 0 || f.greenBufferSize() != -1)
props.setValue(EGL_GREEN_SIZE, f.greenBufferSize() == -1 ? 1 : f.greenBufferSize());
- if (props.value(EGL_BLUE_SIZE) == EGL_DONT_CARE || f.blueBufferSize() != -1)
+ if (props.value(EGL_BLUE_SIZE) == 0 || f.blueBufferSize() != -1)
props.setValue(EGL_BLUE_SIZE, f.blueBufferSize() == -1 ? 1 : f.blueBufferSize());
if (f.alpha()) {
- if (props.value(EGL_ALPHA_SIZE) == EGL_DONT_CARE || f.alphaBufferSize() != -1)
+ if (props.value(EGL_ALPHA_SIZE) == 0 || f.alphaBufferSize() != -1)
props.setValue(EGL_ALPHA_SIZE, f.alphaBufferSize() == -1 ? 1 : f.alphaBufferSize());
}
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 16aaa96..4af8598 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -61,6 +61,10 @@
#include "QtCore/qhash.h"
#include "private/qwidget_p.h"
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#include "private/qpixmapdata_gl_p.h"
+#endif
+
#ifndef QT_OPENGL_ES_1_CL
#define q_vertexType float
#define q_vertexTypeEnum GL_FLOAT
@@ -239,6 +243,7 @@ public:
QGLFormat glFormat;
QGLFormat reqFormat;
GLuint pbo;
+ GLuint fbo;
uint valid : 1;
uint sharing : 1;
@@ -255,6 +260,9 @@ public:
QGLExtensionFuncs extensionFuncs;
GLint max_texture_size;
+ GLuint current_fbo;
+ QPaintEngine *active_engine;
+
#ifdef Q_WS_WIN
static inline QGLExtensionFuncs& qt_get_extension_funcs(const QGLContext *ctx) { return ctx->d_ptr->extensionFuncs; }
#endif
@@ -268,7 +276,7 @@ public:
};
// ### make QGLContext a QObject in 5.0 and remove the proxy stuff
-class QGLSignalProxy : public QObject
+class Q_OPENGL_EXPORT QGLSignalProxy : public QObject
{
Q_OBJECT
public:
@@ -281,6 +289,54 @@ Q_SIGNALS:
void aboutToDestroyContext(const QGLContext *context);
};
+class QGLPixelBuffer;
+class QGLFramebufferObject;
+class QWSGLWindowSurface;
+class QGLWindowSurface;
+class QGLDrawable {
+public:
+ QGLDrawable() : widget(0), buffer(0), fbo(0)
+#if defined(Q_WS_QWS) || (!defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL))
+ , wsurf(0)
+#endif
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ , pixmapData(0)
+#endif
+ {}
+ void setDevice(QPaintDevice *pdev);
+ void swapBuffers();
+ void makeCurrent();
+ void doneCurrent();
+ QSize size() const;
+ QGLFormat format() const;
+ GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
+ GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
+ QColor backgroundColor() const;
+ QGLContext *context() const;
+ bool autoFillBackground() const;
+ bool hasTransparentBackground() const;
+
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ QGLPixmapData *copyOnBegin() const;
+#endif
+
+private:
+ bool wasBound;
+ QGLWidget *widget;
+ QGLPixelBuffer *buffer;
+ QGLFramebufferObject *fbo;
+#ifdef Q_WS_QWS
+ QWSGLWindowSurface *wsurf;
+#elif !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ QGLWindowSurface *wsurf;
+#endif
+
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+ QGLPixmapData *pixmapData;
+#endif
+ int previous_fbo;
+};
+
// GL extension definitions
class QGLExtensions {
public:
@@ -296,7 +352,8 @@ public:
StencilWrap = 0x00000100,
PackedDepthStencil = 0x00000200,
NVFloatBuffer = 0x00000400,
- PixelBufferObject = 0x00000800
+ PixelBufferObject = 0x00000800,
+ FramebufferBlit = 0x00001000
};
Q_DECLARE_FLAGS(Extensions, Extension)
@@ -371,12 +428,21 @@ private:
extern Q_OPENGL_EXPORT QGLShareRegister* qgl_share_reg();
#ifdef Q_WS_QWS
-class QOpenGLPaintEngine;
-extern QOpenGLPaintEngine* qt_qgl_paint_engine();
+extern QPaintEngine* qt_qgl_paint_engine();
extern EGLDisplay qt_qgl_egl_display();
#endif
+inline bool qt_gl_preferGL2Engine()
+{
+#if defined(QT_OPENGL_ES_2)
+ return true;
+#else
+ return (QGLFormat::openGLVersionFlags() & QGLFormat::OpenGL_Version_2_0)
+ && qgetenv("QT_GL_USE_OPENGL1ENGINE").isEmpty();
+#endif
+}
+
inline GLenum qt_gl_preferredTextureFormat()
{
return QSysInfo::ByteOrder == QSysInfo::BigEndian ? GL_RGBA : GL_BGRA;
@@ -384,12 +450,16 @@ inline GLenum qt_gl_preferredTextureFormat()
inline GLenum qt_gl_preferredTextureTarget()
{
+#if defined(QT_OPENGL_ES_2)
+ return GL_TEXTURE_2D;
+#else
return (QGLExtensions::glExtensions & QGLExtensions::TextureRectangle)
+ && !qt_gl_preferGL2Engine()
? GL_TEXTURE_RECTANGLE_NV
: GL_TEXTURE_2D;
+#endif
}
-
QT_END_NAMESPACE
#endif // QGL_P_H
diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp
index 7ed7a23..da61634 100644
--- a/src/opengl/qgl_x11.cpp
+++ b/src/opengl/qgl_x11.cpp
@@ -129,7 +129,7 @@ struct QGLCMapCleanupHandler {
CMapEntryHash *cmap_hash;
GLCMapHash *qglcmap_hash;
};
-Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler);
+Q_GLOBAL_STATIC(QGLCMapCleanupHandler, cmap_handler)
static void cleanup_cmaps()
{
@@ -433,7 +433,7 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
if (!d->gpm)
return false;
}
- QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)));
+ QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
if (d->glFormat.swapInterval() == -1)
d->glFormat.setSwapInterval(0);
@@ -515,11 +515,22 @@ void *QGLContext::chooseVisual()
void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
{
Q_D(QGLContext);
- int spec[40];
+ int spec[45];
int i = 0;
spec[i++] = GLX_LEVEL;
spec[i++] = f.plane();
const QX11Info *xinfo = qt_x11Info(d->paintDevice);
+ bool useFBConfig = false;
+
+#if defined(GLX_VERSION_1_3) && !defined(QT_NO_XRENDER)
+ QWidget* widget = 0;
+ if (d->paintDevice->devType() == QInternal::Widget)
+ widget = static_cast<QWidget*>(d->paintDevice);
+
+ // Only use glXChooseFBConfig for widgets if we're trying to get an ARGB visual
+ if (widget && widget->testAttribute(Qt::WA_TranslucentBackground) && X11->use_xrender)
+ useFBConfig = true;
+#endif
#if defined(GLX_VERSION_1_1) && defined(GLX_EXT_visual_info)
static bool useTranspExt = false;
@@ -547,28 +558,41 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
useTranspExtChecked = true;
}
- if (f.plane() && useTranspExt) {
+ if (f.plane() && useTranspExt && !useFBConfig) {
// Required to avoid non-transparent overlay visual(!) on some systems
spec[i++] = GLX_TRANSPARENT_TYPE_EXT;
spec[i++] = f.rgba() ? GLX_TRANSPARENT_RGB_EXT : GLX_TRANSPARENT_INDEX_EXT;
}
#endif
+#if defined(GLX_VERSION_1_3)
+ // GLX_RENDER_TYPE is only in glx >=1.3
+ if (useFBConfig) {
+ spec[i++] = GLX_RENDER_TYPE;
+ spec[i++] = f.rgba() ? GLX_RGBA_BIT : GLX_COLOR_INDEX_BIT;
+ }
+#endif
+
if (f.doubleBuffer())
spec[i++] = GLX_DOUBLEBUFFER;
+ if (useFBConfig)
+ spec[i++] = True;
if (f.depth()) {
spec[i++] = GLX_DEPTH_SIZE;
spec[i++] = f.depthBufferSize() == -1 ? 1 : f.depthBufferSize();
}
if (f.stereo()) {
spec[i++] = GLX_STEREO;
+ if (useFBConfig)
+ spec[i++] = True;
}
if (f.stencil()) {
spec[i++] = GLX_STENCIL_SIZE;
spec[i++] = f.stencilBufferSize() == -1 ? 1 : f.stencilBufferSize();
}
if (f.rgba()) {
- spec[i++] = GLX_RGBA;
+ if (!useFBConfig)
+ spec[i++] = GLX_RGBA;
spec[i++] = GLX_RED_SIZE;
spec[i++] = f.redBufferSize() == -1 ? 1 : f.redBufferSize();
spec[i++] = GLX_GREEN_SIZE;
@@ -603,8 +627,86 @@ void *QGLContext::tryVisual(const QGLFormat& f, int bufDepth)
spec[i++] = f.samples() == -1 ? 4 : f.samples();
}
+#if defined(GLX_VERSION_1_3)
+ if (useFBConfig) {
+ spec[i++] = GLX_DRAWABLE_TYPE;
+ switch(d->paintDevice->devType()) {
+ case QInternal::Pixmap:
+ spec[i++] = GLX_PIXMAP_BIT;
+ break;
+ case QInternal::Pbuffer:
+ spec[i++] = GLX_PBUFFER_BIT;
+ break;
+ default:
+ qWarning("QGLContext: Unknown paint device type %d", d->paintDevice->devType());
+ // Fall-through & assume it's a window
+ case QInternal::Widget:
+ spec[i++] = GLX_WINDOW_BIT;
+ break;
+ };
+ }
+#endif
+
spec[i] = XNone;
- return glXChooseVisual(xinfo->display(), xinfo->screen(), spec);
+
+
+ XVisualInfo* chosenVisualInfo = 0;
+
+#if defined(GLX_VERSION_1_3)
+ while (useFBConfig) {
+ GLXFBConfig *configs;
+ int configCount = 0;
+ configs = glXChooseFBConfig(xinfo->display(), xinfo->screen(), spec, &configCount);
+
+ if (!configs)
+ break; // fallback to trying glXChooseVisual
+
+ for (i = 0; i < configCount; ++i) {
+ XVisualInfo* vi;
+ vi = glXGetVisualFromFBConfig(xinfo->display(), configs[i]);
+ if (!vi)
+ continue;
+
+#if !defined(QT_NO_XRENDER)
+ QWidget* w = 0;
+ if (d->paintDevice->devType() == QInternal::Widget)
+ w = static_cast<QWidget*>(d->paintDevice);
+
+ if (w && w->testAttribute(Qt::WA_TranslucentBackground) && f.alpha()) {
+ // Attempt to find a config who's visual has a proper alpha channel
+ XRenderPictFormat *pictFormat;
+ pictFormat = XRenderFindVisualFormat(xinfo->display(), vi->visual);
+
+ if (pictFormat && (pictFormat->type == PictTypeDirect) && pictFormat->direct.alphaMask) {
+ // The pict format for the visual matching the FBConfig indicates ARGB
+ if (chosenVisualInfo)
+ XFree(chosenVisualInfo);
+ chosenVisualInfo = vi;
+ break;
+ }
+ } else
+#endif //QT_NO_XRENDER
+ if (chosenVisualInfo) {
+ // If we've got a visual we can use and we're not trying to find one with a
+ // real alpha channel, we might as well just use the one we've got
+ break;
+ }
+
+ if (!chosenVisualInfo)
+ chosenVisualInfo = vi; // Have something to fall back to
+ else
+ XFree(vi);
+ }
+
+ XFree(configs);
+ break;
+ }
+#endif // defined(GLX_VERSION_1_3)
+
+ if (!chosenVisualInfo)
+ chosenVisualInfo = glXChooseVisual(xinfo->display(), xinfo->screen(), spec);
+
+ return chosenVisualInfo;
}
@@ -685,7 +787,7 @@ void QGLContext::swapBuffers() const
static qt_glXWaitVideoSyncSGI glXWaitVideoSyncSGI = 0;
static bool resolved = false;
if (!resolved) {
- QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)));
+ QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
if (glxExt.contains(QLatin1String("GLX_SGI_video_sync"))) {
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
void *handle = dlopen(NULL, RTLD_LAZY);
@@ -930,7 +1032,7 @@ void *QGLContext::getProcAddress(const QString &proc) const
if (resolved && !glXGetProcAddressARB)
return 0;
if (!glXGetProcAddressARB) {
- QString glxExt = QString(QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS)));
+ QString glxExt = QLatin1String(glXGetClientString(QX11Info::display(), GLX_EXTENSIONS));
if (glxExt.contains(QLatin1String("GLX_ARB_get_proc_address"))) {
#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4)
void *handle = dlopen(NULL, RTLD_LAZY);
@@ -1173,6 +1275,12 @@ void QGLWidget::setContext(QGLContext *context,
d_func()->xinfo = parentWidget()->d_func()->xinfo;
}
+ // If the application has set WA_TranslucentBackground and not explicitly set
+ // the alpha buffer size to zero, modify the format so it have an alpha channel
+ QGLFormat& fmt = d->glcx->d_func()->glFormat;
+ if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1)
+ fmt.setAlphaBufferSize(1);
+
bool createFailed = false;
if (!d->glcx->isValid()) {
if (!d->glcx->create(shareContext ? shareContext : oldcx))
diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp
index 480a2dc..3c745b8 100644
--- a/src/opengl/qgl_x11egl.cpp
+++ b/src/opengl/qgl_x11egl.cpp
@@ -114,13 +114,6 @@ bool QGLContext::chooseContext(const QGLContext* shareContext)
eglSwapInterval(d->eglContext->display(), d->glFormat.swapInterval());
#endif
- // Create the EGL surface to draw into.
- if (!d->eglContext->createSurface(device())) {
- delete d->eglContext;
- d->eglContext = 0;
- return false;
- }
-
return true;
}
@@ -262,21 +255,125 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext,
d_func()->xinfo = parentWidget()->d_func()->xinfo;
}
+ // If the application has set WA_TranslucentBackground and not explicitly set
+ // the alpha buffer size to zero, modify the format so it have an alpha channel
+ QGLFormat& fmt = d->glcx->d_func()->glFormat;
+ if (testAttribute(Qt::WA_TranslucentBackground) && fmt.alphaBufferSize() == -1)
+ fmt.setAlphaBufferSize(1);
+
+ bool createFailed = false;
+ if (!d->glcx->isValid()) {
+ if (!d->glcx->create(shareContext ? shareContext : oldcx))
+ createFailed = true;
+ }
+ if (createFailed) {
+ if (deleteOldContext)
+ delete oldcx;
+ return;
+ }
+
+ if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
+ if (deleteOldContext)
+ delete oldcx;
+ return;
+ }
+
bool visible = isVisible();
if (visible)
hide();
XVisualInfo vi;
+ memset(&vi, 0, sizeof(XVisualInfo));
+
+ // Check to see if EGL is suggesting an appropriate visual id:
+ EGLint nativeVisualId;
+ QEglContext* qeglCtx = d->glcx->d_func()->eglContext;
+ qeglCtx->configAttrib(EGL_NATIVE_VISUAL_ID, &nativeVisualId);
+ vi.visualid = nativeVisualId;
+
+ if (vi.visualid) {
+ // EGL has suggested a visual id, so get the rest of the visual info for that id:
+ XVisualInfo *chosenVisualInfo;
+ int matchingCount = 0;
+ chosenVisualInfo = XGetVisualInfo(x11Info().display(), VisualIDMask, &vi, &matchingCount);
+ if (chosenVisualInfo) {
+ qDebug("Using X Visual ID (%d) provided by EGL", (int)vi.visualid);
+ vi = *chosenVisualInfo;
+ XFree(chosenVisualInfo);
+ }
+ else {
+ qWarning("Warning: EGL suggested using X visual ID %d for config %d, but this seems to be invalid!",
+ nativeVisualId, (int)qeglCtx->config());
+ vi.visualid = 0;
+ }
+ }
- int err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), x11Info().depth(), TrueColor, &vi);
- if (err == 0) {
- qWarning("Error: Couldn't get a matching X visual for format");
- return;
+ // If EGL does not know the visual ID, so try to select an appropriate one ourselves, first
+ // using XRender if we're supposed to have an alpha, then falling back to XGetVisualInfo
+
+ bool useArgb = context->format().alpha() && !context->deviceIsPixmap();
+#if !defined(QT_NO_XRENDER)
+ if (vi.visualid == 0 && useArgb) {
+ // Try to use XRender to find an ARGB visual we can use
+ vi.screen = x11Info().screen();
+ vi.depth = 32;
+ vi.c_class = TrueColor;
+ XVisualInfo *matchingVisuals;
+ int matchingCount = 0;
+ matchingVisuals = XGetVisualInfo(x11Info().display(),
+ VisualScreenMask|VisualDepthMask|VisualClassMask,
+ &vi, &matchingCount);
+
+ for (int i = 0; i < matchingCount; ++i) {
+ XRenderPictFormat *format;
+ format = XRenderFindVisualFormat(x11Info().display(), matchingVisuals[i].visual);
+ if (format->type == PictTypeDirect && format->direct.alphaMask) {
+ vi = matchingVisuals[i];
+ qDebug("Using X Visual ID (%d) for ARGB visual as provided by XRender", (int)vi.visualid);
+ break;
+ }
+ }
+ XFree(matchingVisuals);
+ }
+#endif
+
+ if (vi.visualid == 0) {
+ EGLint depth;
+ qeglCtx->configAttrib(EGL_BUFFER_SIZE, &depth);
+ int err;
+ err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), depth, TrueColor, &vi);
+ if (err == 0) {
+ qWarning("Warning: Can't find an X visual which matches the EGL config(%d)'s depth (%d)!",
+ (int)qeglCtx->config(), depth);
+ depth = x11Info().depth();
+ err = XMatchVisualInfo(x11Info().display(), x11Info().screen(), depth, TrueColor, &vi);
+ if (err == 0) {
+ qWarning("Error: Couldn't get any matching X visual!");
+ return;
+ } else
+ qWarning(" - Falling back to X11 suggested depth (%d)", depth);
+ } else
+ qDebug("Using X Visual ID (%d) for EGL provided depth (%d)", (int)vi.visualid, depth);
+
+ // Don't try to use ARGB now unless the visual is 32-bit - even then it might stil fail :-(
+ if (useArgb)
+ useArgb = vi.depth == 32;
}
+// qDebug("Visual Info:");
+// qDebug(" bits_per_rgb=%d", vi.bits_per_rgb);
+// qDebug(" red_mask=0x%x", vi.red_mask);
+// qDebug(" green_mask=0x%x", vi.green_mask);
+// qDebug(" blue_mask=0x%x", vi.blue_mask);
+// qDebug(" colormap_size=%d", vi.colormap_size);
+// qDebug(" c_class=%d", vi.c_class);
+// qDebug(" depth=%d", vi.depth);
+// qDebug(" screen=%d", vi.screen);
+// qDebug(" visualid=%d", vi.visualid);
+
XSetWindowAttributes a;
- Window p = RootWindow(X11->display, vi.screen);
+ Window p = RootWindow(x11Info().display(), x11Info().screen());
if (parentWidget())
p = parentWidget()->winId();
@@ -284,9 +381,14 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext,
a.background_pixel = colmap.pixel(palette().color(backgroundRole()));
a.border_pixel = colmap.pixel(Qt::black);
- Window w = XCreateWindow(X11->display, p, x(), y(), width(), height(),
- 0, vi.depth, InputOutput, vi.visual,
- CWBackPixel|CWBorderPixel, &a);
+ unsigned int valueMask = CWBackPixel|CWBorderPixel;
+ if(useArgb) {
+ a.colormap = XCreateColormap(x11Info().display(), p, vi.visual, AllocNone);
+ valueMask |= CWColormap;
+ }
+
+ Window w = XCreateWindow(x11Info().display(), p, x(), y(), width(), height(),
+ 0, vi.depth, InputOutput, vi.visual, valueMask, &a);
if (deleteOldContext)
delete oldcx;
@@ -294,28 +396,20 @@ void QGLWidget::setContext(QGLContext *context, const QGLContext* shareContext,
create(w); // Create with the ID of the window we've just created
- d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
-
- if (visible)
- show();
- bool createFailed = false;
- if (!d->glcx->isValid()) {
- if (!d->glcx->create(shareContext ? shareContext : oldcx))
- createFailed = true;
- }
- if (createFailed) {
- if (deleteOldContext)
- delete oldcx;
+ // Create the EGL surface to draw into.
+ if (!d->glcx->d_func()->eglContext->createSurface(this)) {
+ delete d->glcx->d_func()->eglContext;
+ d->glcx->d_func()->eglContext = 0;
return;
}
- if (d->glcx->windowCreated() || d->glcx->deviceIsPixmap()) {
- if (deleteOldContext)
- delete oldcx;
- return;
- }
+ d->eglSurfaceWindowId = w; // Remember the window id we created the surface for
+
+ if (visible)
+ show();
+ XFlush(X11->display);
d->glcx->setWindowCreated(true);
}
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 8357cf9..10ca613 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -45,9 +45,15 @@ QT_BEGIN_NAMESPACE
bool qt_resolve_framebufferobject_extensions(QGLContext *ctx)
{
-#if !defined(QT_OPENGL_ES_2)
- if (glIsRenderbufferEXT != 0)
+#if defined(QT_OPENGL_ES_2)
+ static bool have_resolved = false;
+ if (have_resolved)
+ return true;
+ have_resolved = true;
+#else
+ if (glIsRenderbuffer != 0)
return true;
+#endif
if (ctx == 0) {
qWarning("QGLFramebufferObject: Unable to resolve framebuffer object extensions -"
@@ -55,32 +61,37 @@ bool qt_resolve_framebufferobject_extensions(QGLContext *ctx)
return false;
}
- glIsRenderbufferEXT = (_glIsRenderbufferEXT) ctx->getProcAddress(QLatin1String("glIsRenderbufferEXT"));
- glBindRenderbufferEXT = (_glBindRenderbufferEXT) ctx->getProcAddress(QLatin1String("glBindRenderbufferEXT"));
- glDeleteRenderbuffersEXT = (_glDeleteRenderbuffersEXT) ctx->getProcAddress(QLatin1String("glDeleteRenderbuffersEXT"));
- glGenRenderbuffersEXT = (_glGenRenderbuffersEXT) ctx->getProcAddress(QLatin1String("glGenRenderbuffersEXT"));
- glRenderbufferStorageEXT = (_glRenderbufferStorageEXT) ctx->getProcAddress(QLatin1String("glRenderbufferStorageEXT"));
- glGetRenderbufferParameterivEXT =
- (_glGetRenderbufferParameterivEXT) ctx->getProcAddress(QLatin1String("glGetRenderbufferParameterivEXT"));
- glIsFramebufferEXT = (_glIsFramebufferEXT) ctx->getProcAddress(QLatin1String("glIsFramebufferEXT"));
- glBindFramebufferEXT = (_glBindFramebufferEXT) ctx->getProcAddress(QLatin1String("glBindFramebufferEXT"));
- glDeleteFramebuffersEXT = (_glDeleteFramebuffersEXT) ctx->getProcAddress(QLatin1String("glDeleteFramebuffersEXT"));
- glGenFramebuffersEXT = (_glGenFramebuffersEXT) ctx->getProcAddress(QLatin1String("glGenFramebuffersEXT"));
- glCheckFramebufferStatusEXT = (_glCheckFramebufferStatusEXT) ctx->getProcAddress(QLatin1String("glCheckFramebufferStatusEXT"));
- glFramebufferTexture1DEXT = (_glFramebufferTexture1DEXT) ctx->getProcAddress(QLatin1String("glFramebufferTexture1DEXT"));
- glFramebufferTexture2DEXT = (_glFramebufferTexture2DEXT) ctx->getProcAddress(QLatin1String("glFramebufferTexture2DEXT"));
- glFramebufferTexture3DEXT = (_glFramebufferTexture3DEXT) ctx->getProcAddress(QLatin1String("glFramebufferTexture3DEXT"));
- glFramebufferRenderbufferEXT = (_glFramebufferRenderbufferEXT) ctx->getProcAddress(QLatin1String("glFramebufferRenderbufferEXT"));
- glGetFramebufferAttachmentParameterivEXT =
- (_glGetFramebufferAttachmentParameterivEXT) ctx->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT"));
- glGenerateMipmapEXT = (_glGenerateMipmapEXT) ctx->getProcAddress(QLatin1String("glGenerateMipmapEXT"));
- return glIsRenderbufferEXT;
+
+ glBlitFramebufferEXT = (_glBlitFramebufferEXT) ctx->getProcAddress(QLatin1String("glBlitFramebufferEXT"));
+ glRenderbufferStorageMultisampleEXT =
+ (_glRenderbufferStorageMultisampleEXT) ctx->getProcAddress(QLatin1String("glRenderbufferStorageMultisampleEXT"));
+
+#if !defined(QT_OPENGL_ES_2)
+ glIsRenderbuffer = (_glIsRenderbuffer) ctx->getProcAddress(QLatin1String("glIsRenderbufferEXT"));
+ glBindRenderbuffer = (_glBindRenderbuffer) ctx->getProcAddress(QLatin1String("glBindRenderbufferEXT"));
+ glDeleteRenderbuffers = (_glDeleteRenderbuffers) ctx->getProcAddress(QLatin1String("glDeleteRenderbuffersEXT"));
+ glGenRenderbuffers = (_glGenRenderbuffers) ctx->getProcAddress(QLatin1String("glGenRenderbuffersEXT"));
+ glRenderbufferStorage = (_glRenderbufferStorage) ctx->getProcAddress(QLatin1String("glRenderbufferStorageEXT"));
+ glGetRenderbufferParameteriv =
+ (_glGetRenderbufferParameteriv) ctx->getProcAddress(QLatin1String("glGetRenderbufferParameterivEXT"));
+ glIsFramebuffer = (_glIsFramebuffer) ctx->getProcAddress(QLatin1String("glIsFramebufferEXT"));
+ glBindFramebuffer = (_glBindFramebuffer) ctx->getProcAddress(QLatin1String("glBindFramebufferEXT"));
+ glDeleteFramebuffers = (_glDeleteFramebuffers) ctx->getProcAddress(QLatin1String("glDeleteFramebuffersEXT"));
+ glGenFramebuffers = (_glGenFramebuffers) ctx->getProcAddress(QLatin1String("glGenFramebuffersEXT"));
+ glCheckFramebufferStatus = (_glCheckFramebufferStatus) ctx->getProcAddress(QLatin1String("glCheckFramebufferStatusEXT"));
+ glFramebufferTexture2D = (_glFramebufferTexture2D) ctx->getProcAddress(QLatin1String("glFramebufferTexture2DEXT"));
+ glFramebufferRenderbuffer = (_glFramebufferRenderbuffer) ctx->getProcAddress(QLatin1String("glFramebufferRenderbufferEXT"));
+ glGetFramebufferAttachmentParameteriv =
+ (_glGetFramebufferAttachmentParameteriv) ctx->getProcAddress(QLatin1String("glGetFramebufferAttachmentParameterivEXT"));
+ glGenerateMipmap = (_glGenerateMipmap) ctx->getProcAddress(QLatin1String("glGenerateMipmapEXT"));
+
+ return glIsRenderbuffer;
#else
- Q_UNUSED(ctx);
return true;
#endif
}
+#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_version_1_3_functions(QGLContext *ctx)
{
if (glMultiTexCoord4f != 0)
@@ -89,14 +100,12 @@ bool qt_resolve_version_1_3_functions(QGLContext *ctx)
QGLContext cx(QGLFormat::defaultFormat());
glMultiTexCoord4f = (_glMultiTexCoord4f) ctx->getProcAddress(QLatin1String("glMultiTexCoord4f"));
-#if defined(QT_OPENGL_ES_2)
- return glMultiTexCoord4f;
-#else
glActiveTexture = (_glActiveTexture) ctx->getProcAddress(QLatin1String("glActiveTexture"));
return glMultiTexCoord4f && glActiveTexture;
-#endif
}
+#endif
+#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_stencil_face_extension(QGLContext *ctx)
{
if (glActiveStencilFaceEXT != 0)
@@ -107,7 +116,10 @@ bool qt_resolve_stencil_face_extension(QGLContext *ctx)
return glActiveStencilFaceEXT;
}
+#endif
+
+#if !defined(QT_OPENGL_ES_2)
bool qt_resolve_frag_program_extensions(QGLContext *ctx)
{
if (glProgramStringARB != 0)
@@ -126,60 +138,218 @@ bool qt_resolve_frag_program_extensions(QGLContext *ctx)
&& glGenProgramsARB
&& glProgramLocalParameter4fvARB;
}
+#endif
+
bool qt_resolve_buffer_extensions(QGLContext *ctx)
{
- if (glBindBufferARB && glDeleteBuffersARB && glGenBuffersARB && glBufferDataARB
- && glMapBufferARB && glUnmapBufferARB)
+ if (glMapBufferARB && glUnmapBufferARB
+#if !defined(QT_OPENGL_ES_2)
+ && glBindBuffer && glDeleteBuffers && glGenBuffers && glBufferData
+#endif
+ )
return true;
- glBindBufferARB = (_glBindBufferARB) ctx->getProcAddress(QLatin1String("glBindBufferARB"));
- glDeleteBuffersARB = (_glDeleteBuffersARB) ctx->getProcAddress(QLatin1String("glDeleteBuffersARB"));
- glGenBuffersARB = (_glGenBuffersARB) ctx->getProcAddress(QLatin1String("glGenBuffersARB"));
- glBufferDataARB = (_glBufferDataARB) ctx->getProcAddress(QLatin1String("glBufferDataARB"));
+#if !defined(QT_OPENGL_ES_2)
+ glBindBuffer = (_glBindBuffer) ctx->getProcAddress(QLatin1String("glBindBufferARB"));
+ glDeleteBuffers = (_glDeleteBuffers) ctx->getProcAddress(QLatin1String("glDeleteBuffersARB"));
+ glGenBuffers = (_glGenBuffers) ctx->getProcAddress(QLatin1String("glGenBuffersARB"));
+ glBufferData = (_glBufferData) ctx->getProcAddress(QLatin1String("glBufferDataARB"));
+#endif
glMapBufferARB = (_glMapBufferARB) ctx->getProcAddress(QLatin1String("glMapBufferARB"));
glUnmapBufferARB = (_glUnmapBufferARB) ctx->getProcAddress(QLatin1String("glUnmapBufferARB"));
- return glBindBufferARB
- && glDeleteBuffersARB
- && glGenBuffersARB
- && glBufferDataARB
- && glMapBufferARB
- && glUnmapBufferARB;
+ return glMapBufferARB
+ && glUnmapBufferARB
+#if !defined(QT_OPENGL_ES_2)
+ && glBindBuffer
+ && glDeleteBuffers
+ && glGenBuffers
+ && glBufferData
+#endif
+ ;
}
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
+#if defined(QT_OPENGL_ES_2)
+ // The GLSL shader functions are always present in OpenGL/ES 2.0.
+ // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
+ if (!QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved) {
+ glGetProgramBinaryOES = (_glGetProgramBinaryOES) ctx->getProcAddress(QLatin1String("glGetProgramBinaryOES"));
+ glProgramBinaryOES = (_glProgramBinaryOES) ctx->getProcAddress(QLatin1String("glProgramBinaryOES"));
+ QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved = true;
+ }
+ return true;
+#else
if (glCreateShader)
return true;
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
- glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
- glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
- glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
-
- glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
- glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
- glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
- glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
- glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
- glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
-
- glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
- glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
- glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
-
- glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
- glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
- glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
- glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
- glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
- glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
-
- return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
- glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
- glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
- glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv;
+ if (glCreateShader) {
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinary"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
+ glIsShader = (_glIsShader) ctx->getProcAddress(QLatin1String("glIsShader"));
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
+ glIsProgram = (_glIsProgram) ctx->getProcAddress(QLatin1String("glIsProgram"));
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSource"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1iv"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fv"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fv"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fv"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fv"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fv"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fv"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocation"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fv"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fv"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fv"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fv"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
+
+ } else {
+ // We may not have the standard shader functions, but we might
+ // have the older ARB functions instead.
+ glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShaderObjectARB"));
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSourceARB"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinaryARB"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShaderARB"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsShader = 0;
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgramObjectARB"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachObjectARB"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachObjectARB"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgramARB"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgramObjectARB"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsProgram = 0;
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSourceARB"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fvARB"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1iARB"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1ivARB"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fvARB"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fvARB"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fvARB"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fvARB"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fvARB"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fvARB"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fvARB"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fvARB"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fvARB"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocationARB"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocationARB"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fvARB"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fvARB"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fvARB"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fvARB"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointerARB"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB"));
+ }
+
+ // Note: glShaderBinary(), glIsShader(), glIsProgram(), and
+ // glUniformMatrixNxMfv() are optional, but all other functions
+ // are required.
+
+ return glCreateShader &&
+ glShaderSource &&
+ glCompileShader &&
+ glDeleteProgram &&
+ glCreateProgram &&
+ glAttachShader &&
+ glDetachShader &&
+ glLinkProgram &&
+ glUseProgram &&
+ glDeleteProgram &&
+ glGetShaderInfoLog &&
+ glGetShaderiv &&
+ glGetShaderSource &&
+ glGetProgramiv &&
+ glGetProgramInfoLog &&
+ glGetUniformLocation &&
+ glUniform1fv &&
+ glUniform2fv &&
+ glUniform3fv &&
+ glUniform4fv &&
+ glUniform1i &&
+ glUniform1iv &&
+ glUniformMatrix2fv &&
+ glUniformMatrix3fv &&
+ glUniformMatrix4fv &&
+ glBindAttribLocation &&
+ glGetAttribLocation &&
+ glVertexAttrib1fv &&
+ glVertexAttrib2fv &&
+ glVertexAttrib3fv &&
+ glVertexAttrib4fv &&
+ glVertexAttribPointer &&
+ glDisableVertexAttribArray &&
+ glEnableVertexAttribArray;
+#endif
}
+#if !defined(QT_OPENGL_ES_2)
+bool qt_resolve_version_2_0_functions(QGLContext *ctx)
+{
+ bool gl2supported = true;
+ if (!qt_resolve_glsl_extensions(ctx))
+ gl2supported = false;
+
+ if (!qt_resolve_version_1_3_functions(ctx))
+ gl2supported = false;
+
+ if (!qt_resolve_framebufferobject_extensions(ctx))
+ gl2supported = false;
+
+ if (glStencilOpSeparate)
+ return gl2supported;
+
+ glStencilOpSeparate = (_glStencilOpSeparate) ctx->getProcAddress(QLatin1String("glStencilOpSeparate"));
+ if (!glStencilOpSeparate)
+ gl2supported = false;
+
+ return gl2supported;
+}
+#endif
+
+
QT_END_NAMESPACE
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index a0517f5..d6edfb6 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -74,11 +74,15 @@
typedef ptrdiff_t GLsizeiptrARB;
#endif
+#ifndef GL_VERSION_2_0
+typedef char GLchar;
+#endif
+
// ARB_pixel_buffer_object
-typedef void (APIENTRY *_glBindBufferARB) (GLenum, GLuint);
-typedef void (APIENTRY *_glDeleteBuffersARB) (GLsizei, const GLuint *);
-typedef void (APIENTRY *_glGenBuffersARB) (GLsizei, GLuint *);
-typedef void (APIENTRY *_glBufferDataARB) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
+typedef void (APIENTRY *_glBindBuffer) (GLenum, GLuint);
+typedef void (APIENTRY *_glDeleteBuffers) (GLsizei, const GLuint *);
+typedef void (APIENTRY *_glGenBuffers) (GLsizei, GLuint *);
+typedef void (APIENTRY *_glBufferData) (GLenum, GLsizeiptrARB, const GLvoid *, GLenum);
typedef GLvoid* (APIENTRY *_glMapBufferARB) (GLenum, GLenum);
typedef GLboolean (APIENTRY *_glUnmapBufferARB) (GLenum);
@@ -92,8 +96,10 @@ typedef void (APIENTRY *_glProgramLocalParameter4fvARB) (GLenum, GLuint, const G
// GLSL
typedef GLuint (APIENTRY *_glCreateShader) (GLenum);
typedef void (APIENTRY *_glShaderSource) (GLuint, GLsizei, const char **, const GLint *);
+typedef void (APIENTRY *_glShaderBinary) (GLint, const GLuint*, GLenum, const void*, GLint);
typedef void (APIENTRY *_glCompileShader) (GLuint);
typedef void (APIENTRY *_glDeleteShader) (GLuint);
+typedef GLboolean (APIENTRY *_glIsShader) (GLuint);
typedef GLuint (APIENTRY *_glCreateProgram) ();
typedef void (APIENTRY *_glAttachShader) (GLuint, GLuint);
@@ -101,62 +107,101 @@ typedef void (APIENTRY *_glDetachShader) (GLuint, GLuint);
typedef void (APIENTRY *_glLinkProgram) (GLuint);
typedef void (APIENTRY *_glUseProgram) (GLuint);
typedef void (APIENTRY *_glDeleteProgram) (GLuint);
+typedef GLboolean (APIENTRY *_glIsProgram) (GLuint);
typedef void (APIENTRY *_glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetShaderSource) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
+typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
+typedef void (APIENTRY *_glUniform1iv) (GLint, GLsizei, const GLint *);
+typedef void (APIENTRY *_glUniformMatrix2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+
+typedef void (APIENTRY *_glBindAttribLocation) (GLuint, GLuint, const char *);
+typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint, const char *);
+typedef void (APIENTRY *_glVertexAttrib1fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib2fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib3fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib4fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
+typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
+
+typedef void (APIENTRY *_glGetProgramBinaryOES) (GLuint, GLsizei, GLsizei *, GLenum *, void *);
+typedef void (APIENTRY *_glProgramBinaryOES) (GLuint, GLenum, const void *, GLint);
-typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
typedef void (APIENTRY *_glMultiTexCoord4f) (GLenum, GLfloat, GLfloat, GLfloat, GLfloat);
+typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
+
+// Needed for GL2 engine:
+typedef void (APIENTRY *_glStencilOpSeparate) (GLenum face, GLenum sfail, GLenum dpfail, GLenum dppass);
typedef void (APIENTRY *_glActiveTexture) (GLenum);
+
// EXT_GL_framebuffer_object
-typedef GLboolean (APIENTRY *_glIsRenderbufferEXT) (GLuint renderbuffer);
-typedef void (APIENTRY *_glBindRenderbufferEXT) (GLenum target, GLuint renderbuffer);
-typedef void (APIENTRY *_glDeleteRenderbuffersEXT) (GLsizei n, const GLuint *renderbuffers);
-typedef void (APIENTRY *_glGenRenderbuffersEXT) (GLsizei n, GLuint *renderbuffers);
-typedef void (APIENTRY *_glRenderbufferStorageEXT) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
-typedef void (APIENTRY *_glGetRenderbufferParameterivEXT) (GLenum target, GLenum pname, GLint *params);
-typedef GLboolean (APIENTRY *_glIsFramebufferEXT) (GLuint framebuffer);
-typedef void (APIENTRY *_glBindFramebufferEXT) (GLenum target, GLuint framebuffer);
-typedef void (APIENTRY *_glDeleteFramebuffersEXT) (GLsizei n, const GLuint *framebuffers);
-typedef void (APIENTRY *_glGenFramebuffersEXT) (GLsizei n, GLuint *framebuffers);
-typedef GLenum (APIENTRY *_glCheckFramebufferStatusEXT) (GLenum target);
-typedef void (APIENTRY *_glFramebufferTexture1DEXT) (GLenum target, GLenum attachment, GLenum textarget,
- GLuint texture, GLint level);
-typedef void (APIENTRY *_glFramebufferTexture2DEXT) (GLenum target, GLenum attachment, GLenum textarget,
+typedef GLboolean (APIENTRY *_glIsRenderbuffer) (GLuint renderbuffer);
+typedef void (APIENTRY *_glBindRenderbuffer) (GLenum target, GLuint renderbuffer);
+typedef void (APIENTRY *_glDeleteRenderbuffers) (GLsizei n, const GLuint *renderbuffers);
+typedef void (APIENTRY *_glGenRenderbuffers) (GLsizei n, GLuint *renderbuffers);
+typedef void (APIENTRY *_glRenderbufferStorage) (GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+typedef void (APIENTRY *_glGetRenderbufferParameteriv) (GLenum target, GLenum pname, GLint *params);
+typedef GLboolean (APIENTRY *_glIsFramebuffer) (GLuint framebuffer);
+typedef void (APIENTRY *_glBindFramebuffer) (GLenum target, GLuint framebuffer);
+typedef void (APIENTRY *_glDeleteFramebuffers) (GLsizei n, const GLuint *framebuffers);
+typedef void (APIENTRY *_glGenFramebuffers) (GLsizei n, GLuint *framebuffers);
+typedef GLenum (APIENTRY *_glCheckFramebufferStatus) (GLenum target);
+typedef void (APIENTRY *_glFramebufferTexture2D) (GLenum target, GLenum attachment, GLenum textarget,
GLuint texture, GLint level);
-typedef void (APIENTRY *_glFramebufferTexture3DEXT) (GLenum target, GLenum attachment, GLenum textarget,
- GLuint texture, GLint level, GLint zoffset);
-typedef void (APIENTRY *_glFramebufferRenderbufferEXT) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
+typedef void (APIENTRY *_glFramebufferRenderbuffer) (GLenum target, GLenum attachment, GLenum renderbuffertarget,
GLuint renderbuffer);
-typedef void (APIENTRY *_glGetFramebufferAttachmentParameterivEXT) (GLenum target, GLenum attachment, GLenum pname,
+typedef void (APIENTRY *_glGetFramebufferAttachmentParameteriv) (GLenum target, GLenum attachment, GLenum pname,
GLint *params);
-typedef void (APIENTRY *_glGenerateMipmapEXT) (GLenum target);
+typedef void (APIENTRY *_glGenerateMipmap) (GLenum target);
+
+// EXT_GL_framebuffer_blit
+typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1, int srcY1,
+ int dstX0, int dstY0, int dstX1, int dstY1,
+ GLbitfield mask, GLenum filter);
+
+// EXT_GL_framebuffer_multisample
+typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
QT_BEGIN_NAMESPACE
struct QGLExtensionFuncs
{
QGLExtensionFuncs() {
+#if !defined(QT_OPENGL_ES_2)
qt_glProgramStringARB = 0;
qt_glBindProgramARB = 0;
qt_glDeleteProgramsARB = 0;
qt_glGenProgramsARB = 0;
qt_glProgramLocalParameter4fvARB = 0;
+ // GLSL
qt_glCreateShader = 0;
qt_glShaderSource = 0;
+ qt_glShaderBinary = 0;
qt_glCompileShader = 0;
qt_glDeleteShader = 0;
+ qt_glIsShader = 0;
qt_glCreateProgram = 0;
qt_glAttachShader = 0;
@@ -164,10 +209,13 @@ struct QGLExtensionFuncs
qt_glLinkProgram = 0;
qt_glUseProgram = 0;
qt_glDeleteProgram = 0;
+ qt_glIsProgram = 0;
qt_glGetShaderInfoLog = 0;
qt_glGetShaderiv = 0;
+ qt_glGetShaderSource = 0;
qt_glGetProgramiv = 0;
+ qt_glGetProgramInfoLog = 0;
qt_glGetUniformLocation = 0;
qt_glUniform4fv = 0;
@@ -175,40 +223,74 @@ struct QGLExtensionFuncs
qt_glUniform2fv = 0;
qt_glUniform1fv = 0;
qt_glUniform1i = 0;
+ qt_glUniform1iv = 0;
+ qt_glUniformMatrix2fv = 0;
+ qt_glUniformMatrix3fv = 0;
+ qt_glUniformMatrix4fv = 0;
+ qt_glUniformMatrix2x3fv = 0;
+ qt_glUniformMatrix2x4fv = 0;
+ qt_glUniformMatrix3x2fv = 0;
+ qt_glUniformMatrix3x4fv = 0;
+ qt_glUniformMatrix4x2fv = 0;
+ qt_glUniformMatrix4x3fv = 0;
+
+ qt_glBindAttribLocation = 0;
+ qt_glGetAttribLocation = 0;
+ qt_glVertexAttrib1fv = 0;
+ qt_glVertexAttrib2fv = 0;
+ qt_glVertexAttrib3fv = 0;
+ qt_glVertexAttrib4fv = 0;
+ qt_glVertexAttribPointer = 0;
+ qt_glDisableVertexAttribArray = 0;
+ qt_glEnableVertexAttribArray = 0;
+
+ // Extras for GL2 engine:
+ qt_glActiveTexture = 0;
+ qt_glStencilOpSeparate = 0;
qt_glActiveStencilFaceEXT = 0;
-
qt_glMultiTexCoord4f = 0;
- qt_glActiveTexture = 0;
+#else
+ qt_glslResolved = false;
+
+ qt_glGetProgramBinaryOES = 0;
+ qt_glProgramBinaryOES = 0;
+#endif
+ // FBOs
#if !defined(QT_OPENGL_ES_2)
- qt_glIsRenderbufferEXT = 0;
- qt_glBindRenderbufferEXT = 0;
- qt_glDeleteRenderbuffersEXT = 0;
- qt_glGenRenderbuffersEXT = 0;
- qt_glRenderbufferStorageEXT = 0;
- qt_glGetRenderbufferParameterivEXT = 0;
- qt_glIsFramebufferEXT = 0;
- qt_glBindFramebufferEXT = 0;
- qt_glDeleteFramebuffersEXT = 0;
- qt_glGenFramebuffersEXT = 0;
- qt_glCheckFramebufferStatusEXT = 0;
- qt_glFramebufferTexture1DEXT = 0;
- qt_glFramebufferTexture2DEXT = 0;
- qt_glFramebufferTexture3DEXT = 0;
- qt_glFramebufferRenderbufferEXT = 0;
- qt_glGetFramebufferAttachmentParameterivEXT = 0;
- qt_glGenerateMipmapEXT = 0;
-#endif
-
- qt_glBindBufferARB = 0;
- qt_glDeleteBuffersARB = 0;
- qt_glGenBuffersARB = 0;
- qt_glBufferDataARB = 0;
+ qt_glIsRenderbuffer = 0;
+ qt_glBindRenderbuffer = 0;
+ qt_glDeleteRenderbuffers = 0;
+ qt_glGenRenderbuffers = 0;
+ qt_glRenderbufferStorage = 0;
+ qt_glGetRenderbufferParameteriv = 0;
+ qt_glIsFramebuffer = 0;
+ qt_glBindFramebuffer = 0;
+ qt_glDeleteFramebuffers = 0;
+ qt_glGenFramebuffers = 0;
+ qt_glCheckFramebufferStatus = 0;
+ qt_glFramebufferTexture2D = 0;
+ qt_glFramebufferRenderbuffer = 0;
+ qt_glGetFramebufferAttachmentParameteriv = 0;
+ qt_glGenerateMipmap = 0;
+#endif
+ qt_glBlitFramebufferEXT = 0;
+ qt_glRenderbufferStorageMultisampleEXT = 0;
+
+ // Buffer objects:
+#if !defined(QT_OPENGL_ES_2)
+ qt_glBindBuffer = 0;
+ qt_glDeleteBuffers = 0;
+ qt_glGenBuffers = 0;
+ qt_glBufferData = 0;
+#endif
qt_glMapBufferARB = 0;
qt_glUnmapBufferARB = 0;
}
+
+#if !defined(QT_OPENGL_ES_2)
_glProgramStringARB qt_glProgramStringARB;
_glBindProgramARB qt_glBindProgramARB;
_glDeleteProgramsARB qt_glDeleteProgramsARB;
@@ -218,8 +300,10 @@ struct QGLExtensionFuncs
// GLSL definitions
_glCreateShader qt_glCreateShader;
_glShaderSource qt_glShaderSource;
+ _glShaderBinary qt_glShaderBinary;
_glCompileShader qt_glCompileShader;
_glDeleteShader qt_glDeleteShader;
+ _glIsShader qt_glIsShader;
_glCreateProgram qt_glCreateProgram;
_glAttachShader qt_glAttachShader;
@@ -227,10 +311,13 @@ struct QGLExtensionFuncs
_glLinkProgram qt_glLinkProgram;
_glUseProgram qt_glUseProgram;
_glDeleteProgram qt_glDeleteProgram;
+ _glIsProgram qt_glIsProgram;
_glGetShaderInfoLog qt_glGetShaderInfoLog;
_glGetShaderiv qt_glGetShaderiv;
+ _glGetShaderSource qt_glGetShaderSource;
_glGetProgramiv qt_glGetProgramiv;
+ _glGetProgramInfoLog qt_glGetProgramInfoLog;
_glGetUniformLocation qt_glGetUniformLocation;
_glUniform4fv qt_glUniform4fv;
@@ -238,38 +325,74 @@ struct QGLExtensionFuncs
_glUniform2fv qt_glUniform2fv;
_glUniform1fv qt_glUniform1fv;
_glUniform1i qt_glUniform1i;
+ _glUniform1iv qt_glUniform1iv;
+ _glUniformMatrix2fv qt_glUniformMatrix2fv;
+ _glUniformMatrix3fv qt_glUniformMatrix3fv;
+ _glUniformMatrix4fv qt_glUniformMatrix4fv;
+ _glUniformMatrix2x3fv qt_glUniformMatrix2x3fv;
+ _glUniformMatrix2x4fv qt_glUniformMatrix2x4fv;
+ _glUniformMatrix3x2fv qt_glUniformMatrix3x2fv;
+ _glUniformMatrix3x4fv qt_glUniformMatrix3x4fv;
+ _glUniformMatrix4x2fv qt_glUniformMatrix4x2fv;
+ _glUniformMatrix4x3fv qt_glUniformMatrix4x3fv;
+
+ _glBindAttribLocation qt_glBindAttribLocation;
+ _glGetAttribLocation qt_glGetAttribLocation;
+ _glVertexAttrib1fv qt_glVertexAttrib1fv;
+ _glVertexAttrib2fv qt_glVertexAttrib2fv;
+ _glVertexAttrib3fv qt_glVertexAttrib3fv;
+ _glVertexAttrib4fv qt_glVertexAttrib4fv;
+ _glVertexAttribPointer qt_glVertexAttribPointer;
+ _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
+ _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
- _glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
+#else
+ bool qt_glslResolved;
+
+ _glGetProgramBinaryOES qt_glGetProgramBinaryOES;
+ _glProgramBinaryOES qt_glProgramBinaryOES;
+#endif
+ _glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
_glMultiTexCoord4f qt_glMultiTexCoord4f;
+
+#if !defined(QT_OPENGL_ES_2)
+ // Extras needed for GL2 engine:
_glActiveTexture qt_glActiveTexture;
+ _glStencilOpSeparate qt_glStencilOpSeparate;
+#endif
+ // FBOs
#if !defined(QT_OPENGL_ES_2)
- _glIsRenderbufferEXT qt_glIsRenderbufferEXT;
- _glBindRenderbufferEXT qt_glBindRenderbufferEXT;
- _glDeleteRenderbuffersEXT qt_glDeleteRenderbuffersEXT;
- _glGenRenderbuffersEXT qt_glGenRenderbuffersEXT;
- _glRenderbufferStorageEXT qt_glRenderbufferStorageEXT;
- _glGetRenderbufferParameterivEXT qt_glGetRenderbufferParameterivEXT;
- _glIsFramebufferEXT qt_glIsFramebufferEXT;
- _glBindFramebufferEXT qt_glBindFramebufferEXT;
- _glDeleteFramebuffersEXT qt_glDeleteFramebuffersEXT;
- _glGenFramebuffersEXT qt_glGenFramebuffersEXT;
- _glCheckFramebufferStatusEXT qt_glCheckFramebufferStatusEXT;
- _glFramebufferTexture1DEXT qt_glFramebufferTexture1DEXT;
- _glFramebufferTexture2DEXT qt_glFramebufferTexture2DEXT;
- _glFramebufferTexture3DEXT qt_glFramebufferTexture3DEXT;
- _glFramebufferRenderbufferEXT qt_glFramebufferRenderbufferEXT;
- _glGetFramebufferAttachmentParameterivEXT qt_glGetFramebufferAttachmentParameterivEXT;
- _glGenerateMipmapEXT qt_glGenerateMipmapEXT;
-#endif
-
- _glBindBufferARB qt_glBindBufferARB;
- _glDeleteBuffersARB qt_glDeleteBuffersARB;
- _glGenBuffersARB qt_glGenBuffersARB;
- _glBufferDataARB qt_glBufferDataARB;
+ _glIsRenderbuffer qt_glIsRenderbuffer;
+ _glBindRenderbuffer qt_glBindRenderbuffer;
+ _glDeleteRenderbuffers qt_glDeleteRenderbuffers;
+ _glGenRenderbuffers qt_glGenRenderbuffers;
+ _glRenderbufferStorage qt_glRenderbufferStorage;
+ _glGetRenderbufferParameteriv qt_glGetRenderbufferParameteriv;
+ _glIsFramebuffer qt_glIsFramebuffer;
+ _glBindFramebuffer qt_glBindFramebuffer;
+ _glDeleteFramebuffers qt_glDeleteFramebuffers;
+ _glGenFramebuffers qt_glGenFramebuffers;
+ _glCheckFramebufferStatus qt_glCheckFramebufferStatus;
+ _glFramebufferTexture2D qt_glFramebufferTexture2D;
+ _glFramebufferRenderbuffer qt_glFramebufferRenderbuffer;
+ _glGetFramebufferAttachmentParameteriv qt_glGetFramebufferAttachmentParameteriv;
+ _glGenerateMipmap qt_glGenerateMipmap;
+#endif
+ _glBlitFramebufferEXT qt_glBlitFramebufferEXT;
+ _glRenderbufferStorageMultisampleEXT qt_glRenderbufferStorageMultisampleEXT;
+
+ // Buffer objects
+#if !defined(QT_OPENGL_ES_2)
+ _glBindBuffer qt_glBindBuffer;
+ _glDeleteBuffers qt_glDeleteBuffers;
+ _glGenBuffers qt_glGenBuffers;
+ _glBufferData qt_glBufferData;
+#endif
_glMapBufferARB qt_glMapBufferARB;
_glUnmapBufferARB qt_glUnmapBufferARB;
+
};
@@ -397,6 +520,28 @@ struct QGLExtensionFuncs
#define GL_RENDERBUFFER_STENCIL_SIZE_EXT 0x8D55
#endif
+// GL_EXT_framebuffer_blit
+#ifndef GL_READ_FRAMEBUFFER_EXT
+#define GL_READ_FRAMEBUFFER_EXT 0x8CA8
+#endif
+
+// GL_EXT_framebuffer_multisample
+#ifndef GL_RENDERBUFFER_SAMPLES_EXT
+#define GL_RENDERBUFFER_SAMPLES_EXT 0x8CAB
+#endif
+
+#ifndef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT
+#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT 0x8D56
+#endif
+
+#ifndef GL_MAX_SAMPLES_EXT
+#define GL_MAX_SAMPLES_EXT 0x8D5
+#endif
+
+#ifndef GL_DRAW_FRAMEBUFFER_EXT
+#define GL_DRAW_FRAMEBUFFER_EXT 0x8CA9
+#endif
+
#ifndef GL_EXT_packed_depth_stencil
#define GL_DEPTH_STENCIL_EXT 0x84F9
#define GL_UNSIGNED_INT_24_8_EXT 0x84FA
@@ -416,6 +561,42 @@ struct QGLExtensionFuncs
#define GL_UNPACK_IMAGE_HEIGHT 0x806E
#endif
+#ifndef GL_VERSION_1_4
+#define GL_INCR_WRAP 0x8507
+#define GL_DECR_WRAP 0x8508
+#endif
+
+#ifndef GL_VERSION_2_0
+#define GL_FRAGMENT_SHADER 0x8B30
+#define GL_VERTEX_SHADER 0x8B31
+#define GL_FLOAT_VEC2 0x8B50
+#define GL_FLOAT_VEC3 0x8B51
+#define GL_FLOAT_VEC4 0x8B52
+#define GL_INT_VEC2 0x8B53
+#define GL_INT_VEC3 0x8B54
+#define GL_INT_VEC4 0x8B55
+#define GL_BOOL 0x8B56
+#define GL_BOOL_VEC2 0x8B57
+#define GL_BOOL_VEC3 0x8B58
+#define GL_BOOL_VEC4 0x8B59
+#define GL_FLOAT_MAT2 0x8B5A
+#define GL_FLOAT_MAT3 0x8B5B
+#define GL_FLOAT_MAT4 0x8B5C
+#define GL_SAMPLER_1D 0x8B5D
+#define GL_SAMPLER_2D 0x8B5E
+#define GL_SAMPLER_3D 0x8B5F
+#define GL_SAMPLER_CUBE 0x8B60
+#define GL_COMPILE_STATUS 0x8B81
+#define GL_LINK_STATUS 0x8B82
+#define GL_INFO_LOG_LENGTH 0x8B84
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#endif
+
+
+#if !defined(QT_OPENGL_ES_2)
#define glProgramStringARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramStringARB
#define glBindProgramARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindProgramARB
#define glDeleteProgramsARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgramsARB
@@ -426,63 +607,52 @@ struct QGLExtensionFuncs
#define glMultiTexCoord4f QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMultiTexCoord4f
-#if !defined(QT_OPENGL_ES_2)
#define glActiveTexture QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glActiveTexture
-#endif
-
-#if !defined(QT_OPENGL_ES_2)
-
-#define glIsRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsRenderbufferEXT
-#define glBindRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindRenderbufferEXT
-#define glDeleteRenderbuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteRenderbuffersEXT
-#define glGenRenderbuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenRenderbuffersEXT
-#define glRenderbufferStorageEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glRenderbufferStorageEXT
-#define glGetRenderbufferParameterivEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetRenderbufferParameterivEXT
-#define glIsFramebufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsFramebufferEXT
-#define glBindFramebufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindFramebufferEXT
-#define glDeleteFramebuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteFramebuffersEXT
-#define glGenFramebuffersEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenFramebuffersEXT
-#define glCheckFramebufferStatusEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCheckFramebufferStatusEXT
-#define glFramebufferTexture1DEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture1DEXT
-#define glFramebufferTexture2DEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture2DEXT
-#define glFramebufferTexture3DEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture3DEXT
-#define glFramebufferRenderbufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferRenderbufferEXT
-#define glGetFramebufferAttachmentParameterivEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetFramebufferAttachmentParameterivEXT
-#define glGenerateMipmapEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenerateMipmapEXT
-
-#else // QT_OPENGL_ES_2
+#endif // !defined(QT_OPENGL_ES_2)
-#define glIsRenderbufferEXT glIsRenderbuffer
-#define glBindRenderbufferEXT glBindRenderbuffer
-#define glDeleteRenderbuffersEXT glDeleteRenderbuffers
-#define glGenRenderbuffersEXT glGenRenderbuffers
-#define glRenderbufferStorageEXT glRenderbufferStorage
-#define glGetRenderbufferParameterivEXT glGetRenderbufferParameteriv
-#define glIsFramebufferEXT glIsFramebuffer
-#define glBindFramebufferEXT glBindFramebuffer
-#define glDeleteFramebuffersEXT glDeleteFramebuffers
-#define glGenFramebuffersEXT glGenFramebuffers
-#define glCheckFramebufferStatusEXT glCheckFramebufferStatus
-#define glFramebufferTexture1DEXT glFramebufferTexture1D
-#define glFramebufferTexture2DEXT glFramebufferTexture2D
-#define glFramebufferTexture3DEXT glFramebufferTexture3D
-#define glFramebufferRenderbufferEXT glFramebufferRenderbuffer
-#define glGetFramebufferAttachmentParameterivEXT glGetFramebufferAttachmentParameteriv
-#define glGenerateMipmapEXT glGenerateMipmap
+// FBOs
+#if !defined(QT_OPENGL_ES_2)
+#define glIsRenderbuffer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsRenderbuffer
+#define glBindRenderbuffer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindRenderbuffer
+#define glDeleteRenderbuffers QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteRenderbuffers
+#define glGenRenderbuffers QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenRenderbuffers
+#define glRenderbufferStorage QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glRenderbufferStorage
+#define glGetRenderbufferParameteriv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetRenderbufferParameteriv
+#define glIsFramebuffer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsFramebuffer
+#define glBindFramebuffer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindFramebuffer
+#define glDeleteFramebuffers QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteFramebuffers
+#define glGenFramebuffers QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenFramebuffers
+#define glCheckFramebufferStatus QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCheckFramebufferStatus
+#define glFramebufferTexture2D QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferTexture2D
+#define glFramebufferRenderbuffer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glFramebufferRenderbuffer
+#define glGetFramebufferAttachmentParameteriv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetFramebufferAttachmentParameteriv
+#define glGenerateMipmap QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenerateMipmap
#endif // QT_OPENGL_ES_2
+#define glBlitFramebufferEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBlitFramebufferEXT
+#define glRenderbufferStorageMultisampleEXT QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glRenderbufferStorageMultisampleEXT
+
-#define glBindBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindBufferARB
-#define glDeleteBuffersARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteBuffersARB
-#define glGenBuffersARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenBuffersARB
-#define glBufferDataARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBufferDataARB
+// Buffer objects
+#if !defined(QT_OPENGL_ES_2)
+#define glBindBuffer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindBuffer
+#define glDeleteBuffers QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteBuffers
+#define glGenBuffers QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGenBuffers
+#define glBufferData QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBufferData
+#endif
#define glMapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMapBufferARB
#define glUnmapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUnmapBufferARB
+
+// GLSL
+#if !defined(QT_OPENGL_ES_2)
+
#define glCreateShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateShader
#define glShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderSource
+#define glShaderBinary QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderBinary
#define glCompileShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCompileShader
#define glDeleteShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteShader
+#define glIsShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsShader
#define glCreateProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateProgram
#define glAttachShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glAttachShader
@@ -490,10 +660,13 @@ struct QGLExtensionFuncs
#define glLinkProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glLinkProgram
#define glUseProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUseProgram
#define glDeleteProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgram
+#define glIsProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsProgram
#define glGetShaderInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderInfoLog
#define glGetShaderiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderiv
+#define glGetShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderSource
#define glGetProgramiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramiv
+#define glGetProgramInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramInfoLog
#define glGetUniformLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetUniformLocation
#define glUniform4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform4fv
@@ -501,11 +674,48 @@ struct QGLExtensionFuncs
#define glUniform2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform2fv
#define glUniform1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1fv
#define glUniform1i QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1i
+#define glUniform1iv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1iv
+#define glUniformMatrix2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2fv
+#define glUniformMatrix3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3fv
+#define glUniformMatrix4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4fv
+#define glUniformMatrix2x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x3fv
+#define glUniformMatrix2x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x4fv
+#define glUniformMatrix3x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x2fv
+#define glUniformMatrix3x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x4fv
+#define glUniformMatrix4x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x2fv
+#define glUniformMatrix4x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x3fv
+
+#define glBindAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindAttribLocation
+#define glGetAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetAttribLocation
+#define glVertexAttrib1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib1fv
+#define glVertexAttrib2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib2fv
+#define glVertexAttrib3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib3fv
+#define glVertexAttrib4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib4fv
+#define glVertexAttribPointer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttribPointer
+#define glDisableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDisableVertexAttribArray
+#define glEnableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glEnableVertexAttribArray
+
+#else // QT_OPENGL_ES_2
+
+#define glGetProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramBinaryOES
+#define glProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramBinaryOES
+
+#endif // QT_OPENGL_ES_2
+
+
+#if !defined(QT_OPENGL_ES_2)
+#define glStencilOpSeparate QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glStencilOpSeparate
+#endif
+
+#if defined(QT_OPENGL_ES_2)
+#define glClearDepth glClearDepthf
+#endif
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool qt_resolve_buffer_extensions(QGLContext *ctx);
bool qt_resolve_version_1_3_functions(QGLContext *ctx);
+bool qt_resolve_version_2_0_functions(QGLContext *ctx);
bool qt_resolve_stencil_face_extension(QGLContext *ctx);
bool qt_resolve_frag_program_extensions(QGLContext *ctx);
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 6e908e2..159a00a 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -43,7 +43,14 @@
#include <qdebug.h>
#include <private/qgl_p.h>
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#include <private/qpaintengineex_opengl2_p.h>
+#endif
+
+#ifndef QT_OPENGL_ES_2
#include <private/qpaintengine_opengl_p.h>
+#endif
+
#include <qglframebufferobject.h>
#include <qlibrary.h>
#include <qimage.h>
@@ -67,29 +74,242 @@ extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
} \
}
+class QGLFramebufferObjectFormatPrivate
+{
+public:
+ int samples;
+ QGLFramebufferObject::Attachment attachment;
+ GLenum target;
+ GLenum internal_format;
+};
+
+/*!
+ \class QGLFramebufferObjectFormat
+ \brief The QGLFramebufferObjectFormat class specifies the format of an OpenGL
+ framebuffer object.
+
+ \since 4.6
+
+ \ingroup multimedia
+
+ A framebuffer object has several characteristics:
+ \list
+ \i \link setSamples() Number of samples per pixels.\endlink
+ \i \link setAttachment() Depth and/or stencil attachments.\endlink
+ \i \link setTextureTarget() Texture target.\endlink
+ \i \link setInternalFormat() Internal format.\endlink
+ \endlist
+
+ Note that the desired attachments or number of samples per pixels might not
+ be supported by the hardware driver. Call QGLFramebufferObject::format()
+ after creating a QGLFramebufferObject to find the exact format that was
+ used to create the frame buffer object.
+
+ \sa QGLFramebufferObject
+*/
+
+/*!
+ \since 4.6
+
+ Creates a QGLFramebufferObjectFormat object with properties specifying
+ the format of an OpenGL framebuffer object.
+
+ A multisample framebuffer object is specified by setting \a samples
+ to a value different from zero. If the desired amount of samples per pixel is
+ not supported by the hardware then the maximum number of samples per pixel
+ will be used. Note that multisample framebuffer objects can not be bound as
+ textures. Also, the \c{GL_EXT_framebuffer_multisample} extension is required
+ to create a framebuffer with more than one sample per pixel.
+
+ For multisample framebuffer objects a color render buffer is created,
+ otherwise a texture with the texture target \a target is created.
+ The color render buffer or texture will have the internal format
+ \a internalFormat, and will be bound to the \c GL_COLOR_ATTACHMENT0
+ attachment in the framebuffer object.
+
+ The \a attachment parameter describes the depth/stencil buffer
+ configuration.
+
+ \sa samples(), attachment(), target(), internalFormat()
+*/
+
+QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(int samples,
+ QGLFramebufferObject::Attachment attachment,
+ GLenum target,
+ GLenum internalFormat)
+{
+ d = new QGLFramebufferObjectFormatPrivate;
+ d->samples = samples;
+ d->attachment = attachment;
+ d->target = target;
+ d->internal_format = internalFormat;
+}
+
+/*!
+ \since 4.6
+
+ Constructs a copy of \a other.
+*/
+
+QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other)
+{
+ d = new QGLFramebufferObjectFormatPrivate;
+ *d = *other.d;
+}
+
+/*!
+ \since 4.6
+
+ Assigns \a other to this object.
+*/
+
+QGLFramebufferObjectFormat &QGLFramebufferObjectFormat::operator=(const QGLFramebufferObjectFormat &other)
+{
+ *d = *other.d;
+ return *this;
+}
+
+/*!
+ \since 4.6
+
+ Destroys the QGLFramebufferObjectFormat.
+*/
+QGLFramebufferObjectFormat::~QGLFramebufferObjectFormat()
+{
+ delete d;
+}
+
+/*!
+ \since 4.6
+
+ Sets the number of samples per pixel for a multisample framebuffer object
+ to \a samples.
+ A sample count of 0 represents a regular non-multisample framebuffer object.
+
+ \sa samples()
+*/
+void QGLFramebufferObjectFormat::setSamples(int samples)
+{
+ d->samples = samples;
+}
+
+/*!
+ \since 4.6
+
+ Returns the number of samples per pixel if a framebuffer object
+ is a multisample framebuffer object. Otherwise, returns 0.
+
+ \sa setSamples()
+*/
+int QGLFramebufferObjectFormat::samples() const
+{
+ return d->samples;
+}
+
+/*!
+ \since 4.6
+
+ Sets the attachments a framebuffer object should have to \a attachment.
+
+ \sa attachment()
+*/
+void QGLFramebufferObjectFormat::setAttachment(QGLFramebufferObject::Attachment attachment)
+{
+ d->attachment = attachment;
+}
+
+/*!
+ \since 4.6
+
+ Returns the status of the depth and stencil buffers attached to
+ a framebuffer object.
+
+ \sa setAttachment()
+*/
+QGLFramebufferObject::Attachment QGLFramebufferObjectFormat::attachment() const
+{
+ return d->attachment;
+}
+
+/*!
+ \since 4.6
+
+ Sets the texture target of the texture attached to a framebuffer object to
+ \a target. Ignored for multisample framebuffer objects.
+
+ \sa textureTarget(), samples()
+*/
+void QGLFramebufferObjectFormat::setTextureTarget(GLenum target)
+{
+ d->target = target;
+}
+
+/*!
+ \since 4.6
+
+ Returns the texture target of the texture attached to a framebuffer object.
+ Ignored for multisample framebuffer objects.
+
+ \sa setTextureTarget(), samples()
+*/
+GLenum QGLFramebufferObjectFormat::textureTarget() const
+{
+ return d->target;
+}
+
+/*!
+ \since 4.6
+
+ Sets the internal format of a framebuffer object's texture or multisample
+ framebuffer object's color buffer to \a internalFormat.
+
+ \sa internalFormat()
+*/
+void QGLFramebufferObjectFormat::setInternalFormat(GLenum internalFormat)
+{
+ d->internal_format = internalFormat;
+}
+
+/*!
+ \since 4.6
+
+ Returns the internal format of a framebuffer object's texture or
+ multisample framebuffer object's color buffer.
+
+ \sa setInternalFormat()
+*/
+GLenum QGLFramebufferObjectFormat::internalFormat() const
+{
+ return d->internal_format;
+}
+
class QGLFramebufferObjectPrivate
{
public:
- QGLFramebufferObjectPrivate() : depth_stencil_buffer(0), valid(false), bound(false), ctx(0) {}
+ QGLFramebufferObjectPrivate() : depth_stencil_buffer(0), valid(false), bound(false), ctx(0), previous_fbo(0) {}
~QGLFramebufferObjectPrivate() {}
void init(const QSize& sz, QGLFramebufferObject::Attachment attachment,
- GLenum internal_format, GLenum texture_target);
+ GLenum internal_format, GLenum texture_target, GLint samples = 0);
bool checkFramebufferStatus() const;
GLuint texture;
GLuint fbo;
GLuint depth_stencil_buffer;
+ GLuint color_buffer;
GLenum target;
QSize size;
+ QGLFramebufferObjectFormat format;
+ int samples;
uint valid : 1;
uint bound : 1;
QGLFramebufferObject::Attachment fbo_attachment;
QGLContext *ctx; // for Windows extension ptrs
+ GLuint previous_fbo;
};
bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
{
- GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
+ GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER_EXT);
switch(status) {
case GL_NO_ERROR:
case GL_FRAMEBUFFER_COMPLETE_EXT:
@@ -121,6 +341,9 @@ bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
break;
+ case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT:
+ qDebug("QGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
+ break;
default:
qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;
break;
@@ -129,7 +352,7 @@ bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
}
void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::Attachment attachment,
- GLenum texture_target, GLenum internal_format)
+ GLenum texture_target, GLenum internal_format, GLint samples)
{
ctx = const_cast<QGLContext *>(QGLContext::currentContext());
bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
@@ -141,81 +364,137 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
// texture dimensions
while (glGetError() != GL_NO_ERROR) {} // reset error state
- glGenFramebuffersEXT(1, &fbo);
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
+ glGenFramebuffers(1, &fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo);
QT_CHECK_GLERROR();
// init texture
- glGenTextures(1, &texture);
- glBindTexture(target, texture);
- glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
- GL_RGBA, GL_UNSIGNED_BYTE, NULL);
+ if (samples == 0) {
+ glGenTextures(1, &texture);
+ glBindTexture(target, texture);
+ glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, NULL);
#ifndef QT_OPENGL_ES
- glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#else
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
#endif
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
- target, texture, 0);
+ glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ target, texture, 0);
- QT_CHECK_GLERROR();
- valid = checkFramebufferStatus();
+ QT_CHECK_GLERROR();
+ valid = checkFramebufferStatus();
+
+ color_buffer = 0;
+ samples = 0;
+ } else {
+ GLint maxSamples;
+ glGetIntegerv(GL_MAX_SAMPLES_EXT, &maxSamples);
+
+ samples = qBound(1, int(samples), int(maxSamples));
+
+ glGenRenderbuffers(1, &color_buffer);
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, color_buffer);
+ if (glRenderbufferStorageMultisampleEXT) {
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ internal_format, size.width(), size.height());
+ } else {
+ samples = 0;
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT, internal_format,
+ size.width(), size.height());
+ }
+
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_RENDERBUFFER_EXT, color_buffer);
+
+ QT_CHECK_GLERROR();
+ valid = checkFramebufferStatus();
+
+ if (valid)
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_SAMPLES_EXT, &samples);
+ }
if (attachment == QGLFramebufferObject::CombinedDepthStencil
&& (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) {
// depth and stencil buffer needs another extension
- glGenRenderbuffersEXT(1, &depth_stencil_buffer);
- Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
+ glGenRenderbuffers(1, &depth_stencil_buffer);
+ Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
+ Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
+ if (samples != 0 && glRenderbufferStorageMultisampleEXT)
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
+ else
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT,
+ GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
+
GLint i = 0;
- glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_stencil_buffer);
fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
+
valid = checkFramebufferStatus();
if (!valid)
- glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
+ glDeleteRenderbuffers(1, &depth_stencil_buffer);
} else if (attachment == QGLFramebufferObject::Depth
|| attachment == QGLFramebufferObject::CombinedDepthStencil)
{
- glGenRenderbuffersEXT(1, &depth_stencil_buffer);
- Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
- glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
- Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
+ glGenRenderbuffers(1, &depth_stencil_buffer);
+ Q_ASSERT(!glIsRenderbuffer(depth_stencil_buffer));
+ glBindRenderbuffer(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
+ Q_ASSERT(glIsRenderbuffer(depth_stencil_buffer));
+ if (samples != 0 && glRenderbufferStorageMultisampleEXT) {
+#ifdef QT_OPENGL_ES
+#define GL_DEPTH_COMPONENT16 0x81A5
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_DEPTH_COMPONENT16, size.width(), size.height());
+#else
+ glRenderbufferStorageMultisampleEXT(GL_RENDERBUFFER_EXT, samples,
+ GL_DEPTH_COMPONENT, size.width(), size.height());
+#endif
+ } else {
#ifdef QT_OPENGL_ES
#define GL_DEPTH_COMPONENT16 0x81A5
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
#else
- glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
+ glRenderbufferStorage(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
#endif
+ }
GLint i = 0;
- glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
- glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, depth_stencil_buffer);
fbo_attachment = QGLFramebufferObject::Depth;
valid = checkFramebufferStatus();
if (!valid)
- glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
+ glDeleteRenderbuffers(1, &depth_stencil_buffer);
} else {
fbo_attachment = QGLFramebufferObject::NoAttachment;
}
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
if (!valid) {
- glDeleteTextures(1, &texture);
- glDeleteFramebuffersEXT(1, &fbo);
+ if (color_buffer)
+ glDeleteRenderbuffers(1, &color_buffer);
+ else
+ glDeleteTextures(1, &texture);
+ glDeleteFramebuffers(1, &fbo);
}
QT_CHECK_GLERROR();
+
+ format.setTextureTarget(target);
+ format.setSamples(int(samples));
+ format.setAttachment(fbo_attachment);
+ format.setInternalFormat(internal_format);
}
/*!
@@ -263,13 +542,18 @@ void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::At
framebuffer objects more portable.
\endlist
- Note that primitives drawn to a QGLFramebufferObject with QPainter
- will only be antialiased if the QPainter::HighQualityAntialiasing
- render hint is set. This is because there is currently no support
- for the \c{GL_EXT_framebuffer_multisample} extension, which is
- required to do multisample based antialiasing. Also note that the
- QPainter::HighQualityAntialiasing render hint requires the
- \c{GL_ARB_fragment_program} extension to work in OpenGL.
+ Note that you need to create a QGLFramebufferObject with more than one
+ sample per pixel for primitives to be antialiased when drawing using a
+ QPainter, unless if the QPainter::HighQualityAntialiasing render hint is
+ set. The QPainter::HighQualityAntialiasing render hint will enable
+ antialiasing as long as the \c{GL_ARB_fragment_program} extension is
+ present. To create a multisample framebuffer object you should use one of
+ the constructors that take a QGLFramebufferObject parameter, and set the
+ QGLFramebufferObject::samples() property to a non-zero value.
+
+ If you want to use a framebuffer object with multisampling enabled
+ as a texture, you first need to copy from it to a regular framebuffer
+ object using QGLContext::blitFramebuffer().
\sa {Framebuffer Object Example}
*/
@@ -357,6 +641,32 @@ QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target)
d->init(QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
}
+/*! \overload
+
+ Constructs an OpenGL framebuffer object of the given \a size based on the
+ supplied \a format.
+*/
+
+QGLFramebufferObject::QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format)
+ : d_ptr(new QGLFramebufferObjectPrivate)
+{
+ Q_D(QGLFramebufferObject);
+ d->init(size, format.attachment(), format.textureTarget(), format.internalFormat(), format.samples());
+}
+
+/*! \overload
+
+ Constructs an OpenGL framebuffer object of the given \a width and \a height
+ based on the supplied \a format.
+*/
+
+QGLFramebufferObject::QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format)
+ : d_ptr(new QGLFramebufferObjectPrivate)
+{
+ Q_D(QGLFramebufferObject);
+ d->init(QSize(width, height), format.attachment(), format.textureTarget(), format.internalFormat(), format.samples());
+}
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
/*! \internal */
QGLFramebufferObject::QGLFramebufferObject(int width, int height, QMacCompatGLenum target)
@@ -444,9 +754,11 @@ QGLFramebufferObject::~QGLFramebufferObject()
|| qgl_share_reg()->checkSharing(d->ctx, QGLContext::currentContext())))
{
glDeleteTextures(1, &d->texture);
+ if (d->color_buffer)
+ glDeleteRenderbuffers(1, &d->color_buffer);
if (d->depth_stencil_buffer)
- glDeleteRenderbuffersEXT(1, &d->depth_stencil_buffer);
- glDeleteFramebuffersEXT(1, &d->fbo);
+ glDeleteRenderbuffers(1, &d->depth_stencil_buffer);
+ glDeleteFramebuffers(1, &d->fbo);
}
}
@@ -472,6 +784,15 @@ bool QGLFramebufferObject::isValid() const
Switches rendering from the default, windowing system provided
framebuffer to this framebuffer object.
Returns true upon success, false otherwise.
+
+ Since 4.6: if another QGLFramebufferObject instance was already bound
+ to the current context, then its handle() will be remembered and
+ automatically restored when release() is called. This allows multiple
+ framebuffer rendering targets to be stacked up. It is important that
+ release() is called on the stacked framebuffer objects in the reverse
+ order of the calls to bind().
+
+ \sa release()
*/
bool QGLFramebufferObject::bind()
{
@@ -479,8 +800,16 @@ bool QGLFramebufferObject::bind()
return false;
Q_D(QGLFramebufferObject);
QGL_FUNC_CONTEXT;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, d->fbo);
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, d->fbo);
d->bound = d->valid = d->checkFramebufferStatus();
+ const QGLContext *context = QGLContext::currentContext();
+ if (d->valid && context) {
+ // Save the previous setting to automatically restore in release().
+ if (context->d_ptr->current_fbo != d->fbo) {
+ d->previous_fbo = context->d_ptr->current_fbo;
+ context->d_ptr->current_fbo = d->fbo;
+ }
+ }
return d->valid;
}
@@ -490,6 +819,12 @@ bool QGLFramebufferObject::bind()
Switches rendering back to the default, windowing system provided
framebuffer.
Returns true upon success, false otherwise.
+
+ Since 4.6: if another QGLFramebufferObject instance was already bound
+ to the current context when bind() was called, then this function will
+ automatically re-bind it to the current context.
+
+ \sa bind()
*/
bool QGLFramebufferObject::release()
{
@@ -497,10 +832,19 @@ bool QGLFramebufferObject::release()
return false;
Q_D(QGLFramebufferObject);
QGL_FUNC_CONTEXT;
- glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
- d->valid = d->checkFramebufferStatus();
d->bound = false;
- return d->valid;
+
+ const QGLContext *context = QGLContext::currentContext();
+ if (context) {
+ // Restore the previous setting for stacked framebuffer objects.
+ if (d->previous_fbo != context->d_ptr->current_fbo) {
+ context->d_ptr->current_fbo = d->previous_fbo;
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, d->previous_fbo);
+ }
+ d->previous_fbo = 0;
+ }
+
+ return true;
}
/*!
@@ -509,6 +853,9 @@ bool QGLFramebufferObject::release()
Returns the texture id for the texture attached as the default
rendering target in this framebuffer object. This texture id can
be bound as a normal texture in your own GL code.
+
+ If a multisample framebuffer object is used then the value returned
+ from this function will be invalid.
*/
GLuint QGLFramebufferObject::texture() const
{
@@ -529,6 +876,15 @@ QSize QGLFramebufferObject::size() const
}
/*!
+ Returns the format of this framebuffer object.
+*/
+const QGLFramebufferObjectFormat &QGLFramebufferObject::format() const
+{
+ Q_D(const QGLFramebufferObject);
+ return d->format;
+}
+
+/*!
\fn QImage QGLFramebufferObject::toImage() const
Returns the contents of this framebuffer object as a QImage.
@@ -546,17 +902,27 @@ QImage QGLFramebufferObject::toImage() const
return image;
}
-#if !defined(QT_OPENGL_ES_2)
-Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine)
+#endif
+
+#ifndef QT_OPENGL_ES_2
+Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine)
#endif
/*! \reimp */
QPaintEngine *QGLFramebufferObject::paintEngine() const
{
-#if !defined(QT_OPENGL_ES_2)
- return qt_buffer_paintengine();
+#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
+ return qt_buffer_engine();
+#elif defined(QT_OPENGL_ES_2)
+ return qt_buffer_2_engine();
#else
- return 0;
+ Q_D(const QGLFramebufferObject);
+ if (d->ctx->d_func()->internal_context || qt_gl_preferGL2Engine())
+ return qt_buffer_2_engine();
+ else
+ return qt_buffer_engine();
#endif
}
@@ -568,7 +934,8 @@ QPaintEngine *QGLFramebufferObject::paintEngine() const
*/
bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
{
- QGLWidget dmy; // needed to detect and init the QGLExtensions object
+ if (!QGLContext::currentContext())
+ QGLWidget dmy; // needed to detect and init the QGLExtensions object
return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
}
@@ -623,15 +990,16 @@ void QGLFramebufferObject::drawTexture(const QPointF &point, QMacCompatGLuint te
}
#endif
-extern int qt_defaultDpi();
+extern int qt_defaultDpiX();
+extern int qt_defaultDpiY();
/*! \reimp */
int QGLFramebufferObject::metric(PaintDeviceMetric metric) const
{
Q_D(const QGLFramebufferObject);
- float dpmx = qt_defaultDpi()*100./2.54;
- float dpmy = qt_defaultDpi()*100./2.54;
+ float dpmx = qt_defaultDpiX()*100./2.54;
+ float dpmy = qt_defaultDpiY()*100./2.54;
int w = d->size.width();
int h = d->size.height();
switch (metric) {
@@ -654,16 +1022,16 @@ int QGLFramebufferObject::metric(PaintDeviceMetric metric) const
return 32;//d->depth;
case PdmDpiX:
- return (int)(dpmx * 0.0254);
+ return qRound(dpmx * 0.0254);
case PdmDpiY:
- return (int)(dpmy * 0.0254);
+ return qRound(dpmy * 0.0254);
case PdmPhysicalDpiX:
- return (int)(dpmx * 0.0254);
+ return qRound(dpmx * 0.0254);
case PdmPhysicalDpiY:
- return (int)(dpmy * 0.0254);
+ return qRound(dpmy * 0.0254);
default:
qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
@@ -719,4 +1087,85 @@ bool QGLFramebufferObject::isBound() const
return d->bound;
}
+/*!
+ \fn bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
+
+ \since 4.6
+
+ Returns true if the OpenGL \c{GL_EXT_framebuffer_blit} extension
+ is present on this system; otherwise returns false.
+*/
+bool QGLFramebufferObject::hasOpenGLFramebufferBlit()
+{
+ if (!QGLContext::currentContext())
+ QGLWidget dmy; // needed to detect and init the QGLExtensions object
+ return (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit);
+}
+
+/*!
+ \since 4.6
+
+ Blits from the \a sourceRect rectangle in the \a source framebuffer
+ object to the \a targetRect rectangle in the \a target framebuffer object.
+
+ If \a source or \a target is 0, the default framebuffer will be used
+ instead of a framebuffer object as source or target respectively.
+
+ The \a buffers parameter should be a mask consisting of any combination of
+ COLOR_BUFFER_BIT, DEPTH_BUFFER_BIT, and STENCIL_BUFFER_BIT. Any buffer type
+ that is not present both in the source and target buffers is ignored.
+
+ The \a sourceRect and \a targetRect rectangles may have different sizes;
+ in this case \a buffers should not contain DEPTH_BUFFER_BIT or
+ STENCIL_BUFFER_BIT. The \a filter parameter should be set to GL_LINEAR or
+ GL_NEAREST, and specifies whether linear or nearest interpolation should
+ be used when scaling is performed.
+
+ If \a source equals \a target a copy is performed within the same buffer.
+ Results are undefined if the source and target rectangles overlap and
+ have different sizes. The sizes must also be the same if any of the
+ framebuffer objects are multisample framebuffers.
+
+ Note that the scissor test will restrict the blit area if enabled.
+
+ This function will have no effect unless hasOpenGLFramebufferBlit() returns
+ true.
+*/
+void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
+ QGLFramebufferObject *source, const QRect &sourceRect,
+ GLbitfield buffers,
+ GLenum filter)
+{
+ if (!(QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit))
+ return;
+
+ const QGLContext *ctx = QGLContext::currentContext();
+ if (!ctx)
+ return;
+
+ const int height = ctx->device()->height();
+
+ const int sh = source ? source->height() : height;
+ const int th = target ? target->height() : height;
+
+ const int sx0 = sourceRect.left();
+ const int sx1 = sourceRect.left() + sourceRect.width();
+ const int sy0 = sh - (sourceRect.top() + sourceRect.height());
+ const int sy1 = sh - sourceRect.top();
+
+ const int tx0 = targetRect.left();
+ const int tx1 = targetRect.left() + targetRect.width();
+ const int ty0 = th - (targetRect.top() + targetRect.height());
+ const int ty1 = th - targetRect.top();
+
+ glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, source ? source->handle() : 0);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, target ? target->handle() : 0);
+
+ glBlitFramebufferEXT(sx0, sy0, sx1, sy1,
+ tx0, ty0, tx1, ty1,
+ buffers, filter);
+
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
+}
+
QT_END_NAMESPACE
diff --git a/src/opengl/qglframebufferobject.h b/src/opengl/qglframebufferobject.h
index fea8920..935f4ee 100644
--- a/src/opengl/qglframebufferobject.h
+++ b/src/opengl/qglframebufferobject.h
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
QT_MODULE(OpenGL)
class QGLFramebufferObjectPrivate;
+class QGLFramebufferObjectFormat;
class Q_OPENGL_EXPORT QGLFramebufferObject : public QPaintDevice
{
@@ -77,6 +78,9 @@ public:
GLenum target = GL_TEXTURE_2D, GLenum internal_format = GL_RGBA);
#endif
+ QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format);
+ QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format);
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
QGLFramebufferObject(const QSize &size, QMacCompatGLenum target = GL_TEXTURE_2D);
QGLFramebufferObject(int width, int height, QMacCompatGLenum target = GL_TEXTURE_2D);
@@ -89,10 +93,13 @@ public:
virtual ~QGLFramebufferObject();
+ const QGLFramebufferObjectFormat &format() const;
+
bool isValid() const;
bool isBound() const;
bool bind();
bool release();
+
GLuint texture() const;
QSize size() const;
QImage toImage() const;
@@ -110,6 +117,12 @@ public:
void drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget = GL_TEXTURE_2D);
#endif
+ static bool hasOpenGLFramebufferBlit();
+ static void blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,
+ QGLFramebufferObject *source, const QRect &sourceRect,
+ GLbitfield buffers = GL_COLOR_BUFFER_BIT,
+ GLenum filter = GL_NEAREST);
+
protected:
int metric(PaintDeviceMetric metric) const;
int devType() const { return QInternal::FramebufferObject; }
@@ -120,6 +133,42 @@ private:
friend class QGLDrawable;
};
+class QGLFramebufferObjectFormatPrivate;
+class Q_OPENGL_EXPORT QGLFramebufferObjectFormat
+{
+public:
+#if !defined(QT_OPENGL_ES) || defined(Q_QDOC)
+ QGLFramebufferObjectFormat(int samples = 0,
+ QGLFramebufferObject::Attachment attachment = QGLFramebufferObject::NoAttachment,
+ GLenum target = GL_TEXTURE_2D,
+ GLenum internalFormat = GL_RGBA8);
+#else
+ QGLFramebufferObjectFormat(int samples = 0,
+ QGLFramebufferObject::Attachment attachment = QGLFramebufferObject::NoAttachment,
+ GLenum target = GL_TEXTURE_2D,
+ GLenum internalFormat = GL_RGBA);
+#endif
+
+ QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other);
+ QGLFramebufferObjectFormat &operator=(const QGLFramebufferObjectFormat &other);
+ ~QGLFramebufferObjectFormat();
+
+ void setSamples(int samples);
+ int samples() const;
+
+ void setAttachment(QGLFramebufferObject::Attachment attachment);
+ QGLFramebufferObject::Attachment attachment() const;
+
+ void setTextureTarget(GLenum target);
+ GLenum textureTarget() const;
+
+ void setInternalFormat(GLenum internalFormat);
+ GLenum internalFormat() const;
+
+private:
+ QGLFramebufferObjectFormatPrivate *d;
+};
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 8ff2e1d..dbd76a2 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -76,12 +76,17 @@
\sa {opengl/pbuffers}{Pbuffers Example}
*/
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+#include <private/qpaintengineex_opengl2_p.h>
+#endif
#include <qglpixelbuffer.h>
#include <private/qglpixelbuffer_p.h>
#include <qimage.h>
-#if !defined(QT_OPENGL_ES_2)
+#ifndef QT_OPENGL_ES_2
#include <private/qpaintengine_opengl_p.h>
#endif
@@ -362,29 +367,39 @@ bool QGLPixelBuffer::isValid() const
return !d->invalid;
}
-#if !defined(QT_OPENGL_ES_2)
-Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_buffer_2_engine)
+#endif
+
+#ifndef QT_OPENGL_ES_2
+Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_engine)
#endif
/*! \reimp */
QPaintEngine *QGLPixelBuffer::paintEngine() const
{
-#if !defined(QT_OPENGL_ES_2)
- return qt_buffer_paintengine();
+#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_1_CL)
+ return qt_buffer_engine();
+#elif defined(QT_OPENGL_ES_2)
+ return qt_buffer_2_engine();
#else
- return 0;
+ if (d_ptr->qctx->d_func()->internal_context || qt_gl_preferGL2Engine())
+ return qt_buffer_2_engine();
+ else
+ return qt_buffer_engine();
#endif
}
-extern int qt_defaultDpi();
+extern int qt_defaultDpiX();
+extern int qt_defaultDpiY();
/*! \reimp */
int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
{
Q_D(const QGLPixelBuffer);
- float dpmx = qt_defaultDpi()*100./2.54;
- float dpmy = qt_defaultDpi()*100./2.54;
+ float dpmx = qt_defaultDpiX()*100./2.54;
+ float dpmy = qt_defaultDpiY()*100./2.54;
int w = d->req_size.width();
int h = d->req_size.height();
switch (metric) {
@@ -407,16 +422,16 @@ int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
return 32;//d->depth;
case PdmDpiX:
- return (int)(dpmx * 0.0254);
+ return qRound(dpmx * 0.0254);
case PdmDpiY:
- return (int)(dpmy * 0.0254);
+ return qRound(dpmy * 0.0254);
case PdmPhysicalDpiX:
- return (int)(dpmx * 0.0254);
+ return qRound(dpmx * 0.0254);
case PdmPhysicalDpiY:
- return (int)(dpmy * 0.0254);
+ return qRound(dpmy * 0.0254);
default:
qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index ff23948..275bbed 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -45,27 +45,12 @@
#include "qpaintengine_opengl_p.h"
#include "qglpixelbuffer.h"
-#include "qglextensions_p.h"
+#include "qglshaderprogram.h"
#include "qgl_p.h"
#include "private/qapplication_p.h"
-#ifndef GL_FRAGMENT_SHADER
-#define GL_FRAGMENT_SHADER 0x8B30
-#endif
-
-#ifndef GL_COMPILE_STATUS
-#define GL_COMPILE_STATUS 0x8B81
-#endif
-
-#ifndef GL_LINK_STATUS
-#define GL_LINK_STATUS 0x8B82
-#endif
-
-
-
-
QT_BEGIN_NAMESPACE
@@ -79,117 +64,6 @@ void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const
processGL(painter, pos, src, source);
}
-QGLSLProgram::QGLSLProgram(const QString &src)
- : ctx(QGLContext::currentContext())
-{
- if (!qt_resolve_glsl_extensions(const_cast<QGLContext *>(ctx))) {
- qWarning("Failed to resolve GLSL functions");
- m_valid = false;
- return;
- }
-
- m_shader = glCreateShader(GL_FRAGMENT_SHADER);
-
- const QByteArray src_ba = src.toAscii();
- const char *src_cstr = src_ba.constData();
-
- glShaderSource(m_shader, 1, &src_cstr, 0);
- glCompileShader(m_shader);
- glGetShaderiv(m_shader, GL_COMPILE_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to compile GLSL shader:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-
- m_program = glCreateProgram();
- glAttachShader(m_program, m_shader);
- glLinkProgram(m_program);
- glGetProgramiv(m_program, GL_LINK_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to link GLSL program:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-}
-
-QGLSLProgram::~QGLSLProgram()
-{
- glDeleteProgram(m_program);
- glDeleteShader(m_shader);
-}
-
-bool QGLSLProgram::success() const
-{
- return m_valid;
-}
-
-void QGLSLProgram::enable()
-{
- glUseProgram(m_program);
-}
-
-void QGLSLProgram::disable()
-{
- glUseProgram(0);
-}
-
-typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
-
-int QGLSLProgram::getUniformLocation(const QString &name)
-{
- return glGetUniformLocation(m_program, name.toAscii().constData());
-}
-
-void QGLSLProgram::setUniform(int uniform, int value)
-{
- enable();
- glUniform1i(uniform, value);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal value)
-{
- enable();
- GLfloat v[] = { value };
- glUniform1fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2)
-{
- enable();
- GLfloat v[] = { v1, v2 };
- glUniform2fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3)
-{
- enable();
- GLfloat v[] = { v1, v2, v3 };
- glUniform3fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4)
-{
- enable();
- GLfloat v[] = { v1, v2, v3, v4 };
- glUniform4fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, int count, float *v)
-{
- enable();
- glUniform1fv(uniform, count, v);
-}
-
class QGLPixmapColorizeFilter: public QGLPixmapFilter<QPixmapColorizeFilter>
{
public:
@@ -199,8 +73,8 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &pixmap, const QRectF &srcRect) const;
private:
- mutable QGLSLProgram m_program;
- uint m_colorUniform;
+ mutable QGLShaderProgram m_program;
+ int m_colorUniform;
};
class QGLPixmapConvolutionFilter: public QGLPixmapFilter<QPixmapConvolutionFilter>
@@ -213,11 +87,11 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
private:
- QString generateConvolutionShader() const;
+ QByteArray generateConvolutionShader() const;
- mutable QGLSLProgram *m_program;
- mutable uint m_scaleUniform;
- mutable uint m_matrixUniform;
+ mutable QGLShaderProgram *m_program;
+ mutable int m_scaleUniform;
+ mutable int m_matrixUniform;
mutable int m_kernelWidth;
mutable int m_kernelHeight;
@@ -242,10 +116,8 @@ QPixmapFilter *QGLContextPrivate::createPixmapFilter(int type) const
return 0;
}
-#if !defined(QT_OPENGL_ES_2)
extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
-#endif
static void qgl_drawTexture(const QRectF &rect, int tx_width, int tx_height, const QRectF & src)
{
@@ -294,10 +166,12 @@ static const char *qt_gl_colorize_filter =
"}";
QGLPixmapColorizeFilter::QGLPixmapColorizeFilter()
- : m_program(QLatin1String(qt_gl_colorize_filter))
{
- m_program.setUniform(m_program.getUniformLocation(QLatin1String("texture")), 0); // GL_TEXTURE_0
- m_colorUniform = m_program.getUniformLocation(QLatin1String("color"));
+ m_program.addShader(QGLShader::FragmentShader, qt_gl_colorize_filter);
+ m_program.link();
+ m_program.enable();
+ m_program.setUniformValue(m_program.uniformLocation("texture"), GLint(0)); // GL_TEXTURE_0
+ m_colorUniform = m_program.uniformLocation("color");
}
bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
@@ -305,10 +179,10 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
bindTexture(src);
QColor col = color();
- m_program.setUniform(m_colorUniform, col.redF(), col.greenF(), col.blueF());
+ m_program.enable();
+ m_program.setUniformValue(m_colorUniform, col.redF(), col.greenF(), col.blueF());
QRectF target = (srcRect.isNull() ? QRectF(src.rect()) : srcRect).translated(pos);
- m_program.enable();
qgl_drawTexture(target, src.width(), src.height(), srcRect);
m_program.disable();
@@ -316,17 +190,17 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
}
// generates convolution filter code for arbitrary sized kernel
-QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
+QByteArray QGLPixmapConvolutionFilter::generateConvolutionShader() const {
QByteArray code;
- code.append("uniform sampler2D texture;\n");
- code.append("uniform vec2 inv_texture_size;\n");
- code.append("uniform float matrix[");
+ code.append("uniform sampler2D texture;\n"
+ "uniform vec2 inv_texture_size;\n"
+ "uniform float matrix[");
code.append(QByteArray::number(m_kernelWidth * m_kernelHeight));
- code.append("];\n");
- code.append("vec2 offset[");
+ code.append("];\n"
+ "vec2 offset[");
code.append(QByteArray::number(m_kernelWidth*m_kernelHeight));
- code.append("];\n");
- code.append("void main(void) {\n");
+ code.append("];\n"
+ "void main(void) {\n");
for(int y = 0; y < m_kernelHeight; y++) {
for(int x = 0; x < m_kernelWidth; x++) {
@@ -336,23 +210,22 @@ QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
code.append(QByteArray::number(x-(int)(m_kernelWidth/2)));
code.append(".0, inv_texture_size.y * ");
code.append(QByteArray::number((int)(m_kernelHeight/2)-y));
- code.append(".0)");
- code.append(";\n");
+ code.append(".0);\n");
}
}
- code.append(" int i = 0;\n");
- code.append(" vec2 coords = gl_TexCoord[0].st;\n");
- code.append(" vec4 sum = vec4(0.0);\n");
- code.append(" for (i = 0; i < ");
+ code.append(" int i = 0;\n"
+ " vec2 coords = gl_TexCoord[0].st;\n"
+ " vec4 sum = vec4(0.0);\n"
+ " for (i = 0; i < ");
code.append(QByteArray::number(m_kernelWidth * m_kernelHeight));
- code.append("; i++) {\n");
- code.append(" vec4 tmp = texture2D(texture,coords+offset[i]);\n");
- code.append(" sum += matrix[i] * tmp;\n");
- code.append(" }\n");
- code.append(" gl_FragColor = sum;\n");
- code.append("}");
- return QLatin1String(code);
+ code.append("; i++) {\n"
+ " vec4 tmp = texture2D(texture,coords+offset[i]);\n"
+ " sum += matrix[i] * tmp;\n"
+ " }\n"
+ " gl_FragColor = sum;\n"
+ "}");
+ return code;
}
QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
@@ -384,10 +257,12 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
m_kernelWidth = columns();
m_kernelHeight = rows();
- QString code = generateConvolutionShader();
- m_program = new QGLSLProgram(code);
- m_scaleUniform = m_program->getUniformLocation(QLatin1String("inv_texture_size"));
- m_matrixUniform = m_program->getUniformLocation(QLatin1String("matrix"));
+ QByteArray code = generateConvolutionShader();
+ m_program = new QGLShaderProgram();
+ m_program->addShader(QGLShader::FragmentShader, code);
+ m_program->link();
+ m_scaleUniform = m_program->uniformLocation("inv_texture_size");
+ m_matrixUniform = m_program->uniformLocation("matrix");
}
const qreal *kernel = convolutionKernel();
@@ -397,10 +272,10 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
const qreal iw = 1.0 / src.width();
const qreal ih = 1.0 / src.height();
- m_program->setUniform(m_scaleUniform, iw, ih);
- m_program->setUniform(m_matrixUniform, m_kernelWidth * m_kernelHeight, conv);
-
m_program->enable();
+ m_program->setUniformValue(m_scaleUniform, iw, ih);
+ m_program->setUniformValueArray(m_matrixUniform, conv, m_kernelWidth * m_kernelHeight, 1);
+
qgl_drawTexture(target, src.width(), src.height(), boundingRectFor(srcRect));
m_program->disable();
return true;
diff --git a/src/opengl/qglpixmapfilter_p.h b/src/opengl/qglpixmapfilter_p.h
index dc2eea6..d6742fc 100644
--- a/src/opengl/qglpixmapfilter_p.h
+++ b/src/opengl/qglpixmapfilter_p.h
@@ -87,35 +87,6 @@ public:
}
};
-class Q_OPENGL_EXPORT QGLSLProgram
-{
-public:
- QGLSLProgram(const QString &src);
- ~QGLSLProgram();
-
- bool success() const;
-
- void enable();
- void disable();
-
- int getUniformLocation(const QString &name);
-
- void setUniform(int uniform, int value);
- void setUniform(int uniform, qreal value);
- void setUniform(int uniform, qreal v1, qreal v2);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4);
- void setUniform(int uniform, int count, float *v);
-
-private:
- GLuint m_shader;
- GLuint m_program;
-
- GLint m_valid;
-
- const QGLContext *ctx;
-};
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
new file mode 100644
index 0000000..37732dd
--- /dev/null
+++ b/src/opengl/qglshaderprogram.cpp
@@ -0,0 +1,2986 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qglshaderprogram.h"
+#include "qglextensions_p.h"
+#include "qgl_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+/*!
+ \class QGLShaderProgram
+ \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
+ \since 4.6
+
+ \section1 Introduction
+
+ This class supports shader programs written in the OpenGL Shading
+ Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ The following example creates a vertex shader program using the
+ supplied source \c{code}. Once compiled and linked, the shader
+ program is activated in the current QGLContext by calling
+ QGLShaderProgram::enable():
+
+ \code
+ QGLShader shader(QGLShader::VertexShader);
+ shader.compile(code);
+
+ QGLShaderProgram program(context);
+ program.addShader(shader);
+ program.link();
+
+ program.enable();
+ \endcode
+
+ \section1 Writing portable shaders
+
+ Shader programs can be difficult to reuse across OpenGL implementations
+ because of varying levels of support for standard vertex attributes and
+ uniform variables. In particular, GLSL/ES lacks all of the
+ standard variables that are present on desktop OpenGL systems:
+ \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL
+ lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
+
+ The QGLShaderProgram class makes the process of writing portable shaders
+ easier by prefixing all shader programs with the following lines on
+ desktop OpenGL:
+
+ \code
+ #define highp
+ #define mediump
+ #define lowp
+ \endcode
+
+ This makes it possible to run most GLSL/ES shader programs
+ on desktop systems. The programmer should restrict themselves
+ to just features that are present in GLSL/ES, and avoid
+ standard variable names that only work on the desktop.
+
+ \section1 Simple shader example
+
+ \code
+ program.addShader(QGLShader::VertexShader,
+ "attribute highp vec4 vertex;\n"
+ "attribute mediump mat4 matrix;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = matrix * vertex;\n"
+ "}");
+ program.addShader(QGLShader::FragmentShader,
+ "uniform mediump vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}");
+ program.link();
+ program.enable();
+
+ int vertexLocation = program.attributeLocation("vertex");
+ int matrixLocation = program.attributeLocation("matrix");
+ int colorLocation = program.uniformLocation("color");
+ \endcode
+
+ With the above shader program active, we can draw a green triangle
+ as follows:
+
+ \code
+ static GLfloat const triangleVertices[] = {
+ 60.0f, 10.0f, 0.0f,
+ 110.0f, 110.0f, 0.0f,
+ 10.0f, 110.0f, 0.0f
+ };
+
+ QColor color(0, 255, 0, 255);
+
+ QMatrix4x4 pmvMatrix;
+ pmvMatrix.ortho(rect());
+
+ program.setAttributeArray(vertexLocation, triangleVertices, 3);
+ program.setUniformValue(matrixLocation, pmvMatrix);
+ program.setUniformValue(colorLocation, color);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ \endcode
+
+ \section1 Partial shaders
+
+ Desktop GLSL can attach an arbitrary number of vertex and fragment
+ shaders to a shader program. Embedded GLSL/ES on the other hand
+ supports only a single shader of each type on a shader program.
+
+ Multiple shaders of the same type can be useful when large libraries
+ of shaders are needed. Common functions can be factored out into
+ library shaders that can be reused in multiple shader programs.
+
+ To support this use of shaders, the application programmer can
+ create shaders with the QGLShader::PartialVertexShader and
+ QGLShader::PartialFragmentShader types. These types direct
+ QGLShader and QGLShaderProgram to delay shader compilation until
+ link time.
+
+ When link() is called, the sources for the partial shaders are
+ concatenated, and a single vertex or fragment shader is compiled
+ and linked into the shader program.
+
+ It is more efficient to use the QGLShader::VertexShader and
+ QGLShader::FragmentShader when there is only one shader of that
+ type in the program.
+
+ \sa QGLShader
+*/
+
+/*!
+ \class QGLShader
+ \brief The QGLShader class allows OpenGL shaders to be compiled.
+ \since 4.6
+
+ This class supports shaders written in the OpenGL Shading Language (GLSL)
+ and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ \sa QGLShaderProgram
+*/
+
+/*!
+ \enum QGLShader::ShaderType
+ This enum specifies the type of QGLShader that is being created.
+
+ \value VertexShader Vertex shader written in the OpenGL Shading Language (GLSL).
+ \value FragmentShader Fragment shader written in the OpenGL Shading Language (GLSL).
+ \value PartialVertexShader Partial vertex shader that will be concatenated with all other partial vertex shaders at link time.
+ \value PartialFragmentShader Partial fragment shader that will be concatenated with all other partial fragment shaders at link time.
+*/
+
+#ifndef GL_FRAGMENT_SHADER
+#define GL_FRAGMENT_SHADER 0x8B30
+#endif
+#ifndef GL_VERTEX_SHADER
+#define GL_VERTEX_SHADER 0x8B31
+#endif
+#ifndef GL_COMPILE_STATUS
+#define GL_COMPILE_STATUS 0x8B81
+#endif
+#ifndef GL_LINK_STATUS
+#define GL_LINK_STATUS 0x8B82
+#endif
+#ifndef GL_INFO_LOG_LENGTH
+#define GL_INFO_LOG_LENGTH 0x8B84
+#endif
+#ifndef GL_ACTIVE_UNIFORMS
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#endif
+#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTES
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#endif
+#ifndef GL_CURRENT_VERTEX_ATTRIB
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#endif
+#ifndef GL_SHADER_SOURCE_LENGTH
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#endif
+#ifndef GL_SHADER_BINARY_FORMATS
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#endif
+#ifndef GL_NUM_SHADER_BINARY_FORMATS
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#endif
+
+class QGLShaderPrivate
+{
+public:
+ QGLShaderPrivate(QGLShader::ShaderType type, const QGLContext *ctx)
+ : context(ctx)
+ , shader(0)
+ , shaderType(type)
+ , compiled(false)
+ , isPartial(type == QGLShader::PartialVertexShader ||
+ type == QGLShader::PartialFragmentShader)
+ , hasPartialSource(false)
+ {
+ }
+
+ const QGLContext *context;
+ GLuint shader;
+ QGLShader::ShaderType shaderType;
+ bool compiled;
+ bool isPartial;
+ bool hasPartialSource;
+ QString log;
+ QByteArray partialSource;
+
+ bool create();
+ bool compile(QGLShader *q);
+};
+
+#define ctx context
+
+bool QGLShaderPrivate::create()
+{
+ if (isPartial)
+ return true;
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) {
+ if (shaderType == QGLShader::VertexShader)
+ shader = glCreateShader(GL_VERTEX_SHADER);
+ else
+ shader = glCreateShader(GL_FRAGMENT_SHADER);
+ if (!shader) {
+ qWarning() << "QGLShader: could not create shader";
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QGLShaderPrivate::compile(QGLShader *q)
+{
+ // Partial shaders are compiled during QGLShaderProgram::link().
+ if (isPartial && hasPartialSource) {
+ compiled = true;
+ return true;
+ }
+ if (!shader)
+ return false;
+ glCompileShader(shader);
+ GLint value = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
+ compiled = (value != 0);
+ value = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
+ if (!compiled && value > 1) {
+ char *logbuf = new char [value];
+ GLint len;
+ glGetShaderInfoLog(shader, value, &len, logbuf);
+ log = QString::fromLatin1(logbuf);
+ QString name = q->objectName();
+ if (name.isEmpty())
+ qWarning() << "QGLShader::compile:" << log;
+ else
+ qWarning() << "QGLShader::compile[" << name << "]:" << log;
+ delete [] logbuf;
+ }
+ return compiled;
+}
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ QGLShaderProgram::hasShaderPrograms() will return false.
+
+ This constructor is normally followed by a call to compile()
+ or compileFile().
+
+ The shader will be associated with the current QGLContext.
+
+ \sa compile(), compileFile()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isCompiled() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isCompiled()
+*/
+QGLShader::QGLShader(const QString& fileName, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, QGLContext::currentContext());
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, QGLContext::currentContext());
+ if (d->create() && !compileFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isCompiled() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isCompiled()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ if (d->create() && !compileFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then QGLShaderProgram::hasShaderPrograms() will return false.
+
+ This constructor is normally followed by a call to compile()
+ or compileFile().
+
+ The shader will be associated with \a context.
+
+ \sa compile(), compileFile()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isCompiled() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isCompiled()
+*/
+QGLShader::QGLShader(const QString& fileName, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, context);
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, context);
+ if (d->create() && !compileFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isCompiled() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isCompiled()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ if (d->create() && !compileFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Deletes this shader. If the shader has been attached to a
+ QGLShaderProgram object, then the actual shader will stay around
+ until the QGLShaderProgram is destroyed.
+*/
+QGLShader::~QGLShader()
+{
+ if (d->shader)
+ glDeleteShader(d->shader);
+ delete d;
+}
+
+/*!
+ Returns the type of this shader.
+*/
+QGLShader::ShaderType QGLShader::shaderType() const
+{
+ return d->shaderType;
+}
+
+// The precision qualifiers are useful on OpenGL/ES systems,
+// but usually not present on desktop systems. Define the
+// keywords to empty strings on desktop systems.
+#ifndef QT_OPENGL_ES
+#define QGL_DEFINE_QUALIFIERS 1
+static const char qualifierDefines[] =
+ "#define lowp\n"
+ "#define mediump\n"
+ "#define highp\n";
+#endif
+
+/*!
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+
+ \sa compileFile()
+*/
+bool QGLShader::compile(const char *source)
+{
+ if (d->isPartial) {
+ d->partialSource = QByteArray(source);
+ d->hasPartialSource = true;
+ return d->compile(this);
+ } else if (d->shader) {
+ QVarLengthArray<const char *> src;
+#ifdef QGL_DEFINE_QUALIFIERS
+ src.append(qualifierDefines);
+#endif
+ src.append(source);
+ glShaderSource(d->shader, src.size(), src.data(), 0);
+ return d->compile(this);
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+
+ \sa compileFile()
+*/
+bool QGLShader::compile(const QByteArray& source)
+{
+ return compile(source.constData());
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+
+ \sa compileFile()
+*/
+bool QGLShader::compile(const QString& source)
+{
+ return compile(source.toLatin1().constData());
+}
+
+/*!
+ Sets the source code for this shader to the contents of \a fileName
+ and compiles it. Returns true if the file could be opened and the
+ source compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+
+ \sa compile()
+*/
+bool QGLShader::compileFile(const QString& fileName)
+{
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "QGLShader: Unable to open file" << fileName;
+ return false;
+ }
+
+ QByteArray contents = file.readAll();
+ return compile(contents.constData());
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ If this function succeeds, then the shader will be considered compiled.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setShaderBinary(GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ glShaderBinary(1, &(d->shader), format, binary, length);
+ d->compiled = (glGetError() == GL_NO_ERROR);
+ return d->compiled;
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ The \a otherShader will also have binary code set on it. This is
+ for the case where \a binary contains both vertex and fragment
+ shader code.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ If this function succeeds, then the shader will be considered compiled.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setShaderBinary
+ (QGLShader& otherShader, GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ if (otherShader.d->isPartial || !otherShader.d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ GLuint shaders[2];
+ shaders[0] = d->shader;
+ shaders[1] = otherShader.d->shader;
+ glShaderBinary(2, shaders, format, binary, length);
+ d->compiled = (glGetError() == GL_NO_ERROR);
+ otherShader.d->compiled = d->compiled;
+ return d->compiled;
+}
+
+/*!
+ Returns a list of all binary formats that are supported by
+ setShaderBinary() on this system.
+
+ \sa setShaderBinary()
+*/
+QList<GLenum> QGLShader::shaderBinaryFormats()
+{
+ GLint num;
+ QList<GLenum> list;
+ glGetError(); // Clear error state.
+ glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &num);
+ if (glGetError() != GL_NO_ERROR || num <= 0)
+ return list;
+ QVarLengthArray<GLint> formats(num);
+ glGetIntegerv(GL_SHADER_BINARY_FORMATS, formats.data());
+ for (GLint i = 0; i < num; ++i)
+ list += (GLenum)(formats[i]);
+ return list;
+}
+
+/*!
+ Returns the source code for this shader.
+
+ \sa compile()
+*/
+QByteArray QGLShader::sourceCode() const
+{
+ if (d->isPartial)
+ return d->partialSource;
+ if (!d->shader)
+ return QByteArray();
+ GLint size = 0;
+ glGetShaderiv(d->shader, GL_SHADER_SOURCE_LENGTH, &size);
+ if (size <= 0)
+ return QByteArray();
+ GLint len = 0;
+ char *source = new char [size];
+ glGetShaderSource(d->shader, size, &len, source);
+ QByteArray src(source);
+ delete [] source;
+ return src;
+}
+
+/*!
+ Returns true if this shader has been compiled; false otherwise.
+
+ \sa compile()
+*/
+bool QGLShader::isCompiled() const
+{
+ return d->compiled;
+}
+
+/*!
+ Returns the errors and warnings that occurred during the last compile.
+
+ \sa compile()
+*/
+QString QGLShader::log() const
+{
+ return d->log;
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ this function will always return zero. Partial shaders are
+ created and compiled when QGLShaderProgram::link() is called.
+
+ \sa QGLShaderProgram::programId()
+*/
+GLuint QGLShader::shaderId() const
+{
+ return d->shader;
+}
+
+#undef ctx
+#define ctx context
+
+class QGLShaderProgramPrivate
+{
+public:
+ QGLShaderProgramPrivate(const QGLContext *ctx)
+ : context(ctx)
+ , program(0)
+ , linked(false)
+ , inited(false)
+ , hasPartialShaders(false)
+ , vertexShader(0)
+ , fragmentShader(0)
+ {
+ }
+ ~QGLShaderProgramPrivate()
+ {
+ if (program)
+ glDeleteProgram(program);
+ }
+
+ const QGLContext *context;
+ GLuint program;
+ bool linked;
+ bool inited;
+ bool hasPartialShaders;
+ QString log;
+ QList<QGLShader *> shaders;
+ QList<QGLShader *> anonShaders;
+ QGLShader *vertexShader;
+ QGLShader *fragmentShader;
+};
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with the current QGLContext.
+
+ \sa addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(QGLContext::currentContext());
+}
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with \a context.
+
+ \sa addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(context);
+}
+
+/*!
+ Deletes this shader program.
+*/
+QGLShaderProgram::~QGLShaderProgram()
+{
+ delete d;
+}
+
+bool QGLShaderProgram::init()
+{
+ if (d->program || d->inited)
+ return true;
+ d->inited = true;
+ if (!d->context)
+ d->context = QGLContext::currentContext();
+ if (!d->context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(d->context))) {
+ d->program = glCreateProgram();
+ if (!(d->program)) {
+ qWarning() << "QGLShaderProgram: could not create shader program";
+ return false;
+ }
+ return true;
+ } else {
+ qWarning() << "QGLShaderProgram: shader programs are not supported";
+ return false;
+ }
+}
+
+/*!
+ Adds a compiled \a shader to this shader program. Returns true
+ if the shader could be added, or false otherwise.
+
+ Ownership of the \a shader object remains with the caller.
+ It will not be deleted when this QGLShaderProgram instance
+ is deleted. This allows the caller to add the same shader
+ to multiple shader programs.
+
+ \sa removeShader(), link(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader *shader)
+{
+ if (!init())
+ return false;
+ if (d->shaders.contains(shader))
+ return true; // Already added to this shader program.
+ if (d->program && shader) {
+ if (!shader->d->compiled)
+ return false;
+ if (!shader->d->isPartial) {
+ if (!shader->d->shader)
+ return false;
+ glAttachShader(d->program, shader->d->shader);
+ } else {
+ d->hasPartialShaders = true;
+ }
+ d->linked = false; // Program needs to be relinked.
+ d->shaders.append(shader);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const char *source)
+{
+ if (!init())
+ return false;
+ QGLShader *shader = new QGLShader(type, this);
+ if (!shader->compile(source)) {
+ d->log = shader->log();
+ delete shader;
+ return false;
+ }
+ d->anonShaders.append(shader);
+ return addShader(shader);
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QByteArray& source)
+{
+ return addShader(type, source.constData());
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ and warnings will be made available via log().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), log(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QString& source)
+{
+ return addShader(type, source.toLatin1().constData());
+}
+
+/*!
+ Removes \a shader from this shader program. The object is not deleted.
+
+ \sa addShader(), link(), removeAllShaders()
+*/
+void QGLShaderProgram::removeShader(QGLShader *shader)
+{
+ if (d->program && shader && shader->d->shader) {
+ glDetachShader(d->program, shader->d->shader);
+ d->linked = false; // Program needs to be relinked.
+ }
+ d->shaders.removeAll(shader);
+ d->anonShaders.removeAll(shader);
+}
+
+/*!
+ Returns a list of all shaders that have been added to this shader
+ program using addShader().
+
+ \sa addShader(), removeShader()
+*/
+QList<QGLShader *> QGLShaderProgram::shaders() const
+{
+ return d->shaders;
+}
+
+/*!
+ Removes all of the shaders that were added to this program previously.
+ The QGLShader objects for the shaders will not be deleted if they
+ were constructed externally. QGLShader objects that are constructed
+ internally by QGLShaderProgram will be deleted.
+
+ \sa addShader(), removeShader()
+*/
+void QGLShaderProgram::removeAllShaders()
+{
+ foreach (QGLShader *shader, d->shaders) {
+ if (d->program && shader && shader->d->shader)
+ glDetachShader(d->program, shader->d->shader);
+ }
+ foreach (QGLShader *shader, d->anonShaders) {
+ // Delete shader objects that were created anonymously.
+ delete shader;
+ }
+ d->shaders.clear();
+ d->anonShaders.clear();
+ d->linked = false; // Program needs to be relinked.
+}
+
+#if defined(QT_OPENGL_ES_2)
+
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#endif
+#ifndef GL_NUM_PROGRAM_BINARY_FORMATS_OES
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#endif
+#ifndef GL_PROGRAM_BINARY_FORMATS_OES
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+#endif
+
+/*!
+ Returns the program binary associated with this shader program.
+ The numeric identifier of the program binary format is returned
+ in \a format. The \c OES_get_program_binary extension will need
+ to be supported by the system for binary retrieval to succeed.
+
+ Returns an empty QByteArray if the program binary cannot be
+ retrieved on this system, or the shader program has not yet
+ been linked.
+
+ The returned binary can be supplied to setProgramBinary() on the
+ same machine at some future point to reload the program. It contains
+ the compiled code of all of the shaders that were attached to the
+ program at the time programBinary() is called.
+
+ \sa setProgramBinary(), programBinaryFormats()
+*/
+QByteArray QGLShaderProgram::programBinary(int *format) const
+{
+#if defined(QT_OPENGL_ES_2)
+ if (!isLinked())
+ return QByteArray();
+
+ // Get the length of the binary data, bailing out if there is none.
+ GLint length = 0;
+ glGetProgramiv(d->program, GL_PROGRAM_BINARY_LENGTH_OES, &length);
+ if (length <= 0)
+ return QByteArray();
+
+ // Retrieve the binary data.
+ QByteArray binary(length, 0);
+ GLenum binaryFormat;
+ glGetProgramBinaryOES(d->program, length, 0, &binaryFormat, binary.data());
+ if (format)
+ *format = (int)binaryFormat;
+ return binary;
+#else
+ Q_UNUSED(format);
+ return QByteArray();
+#endif
+}
+
+/*!
+ Sets the \a binary for this shader program according to \a format.
+ Returns true if the binary was set, or false if the binary format
+ is not supported or this system does not support program binaries.
+ The program will be linked if the load succeeds.
+
+ \sa programBinary(), programBinaryFormats(), isLinked()
+*/
+bool QGLShaderProgram::setProgramBinary(int format, const QByteArray& binary)
+{
+#if defined(QT_OPENGL_ES_2)
+ // Load the binary and check that it was linked correctly.
+ glProgramBinaryOES(d->program, (GLenum)format,
+ binary.constData(), binary.size());
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->log = QString();
+ if (value > 1) {
+ char *logbuf = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, logbuf);
+ d->log = QString::fromLatin1(logbuf);
+ QString name = objectName();
+ if (name.isEmpty())
+ qWarning() << "QGLShader::setProgramBinary:" << d->log;
+ else
+ qWarning() << "QGLShader::setProgramBinary[" << name << "]:" << d->log;
+ delete [] logbuf;
+ }
+ return d->linked;
+#else
+ Q_UNUSED(format);
+ Q_UNUSED(binary);
+ return false;
+#endif
+}
+
+/*!
+ Returns the list of program binary formats that are accepted by
+ this system for use with setProgramBinary().
+
+ \sa programBinary(), setProgramBinary()
+*/
+QList<int> QGLShaderProgram::programBinaryFormats()
+{
+#if defined(QT_OPENGL_ES_2)
+ GLint count = 0;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &count);
+ if (count <= 0)
+ return QList<int>();
+ QVector<int> list;
+ list.resize(count);
+ glGetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, list.data());
+ return list.toList();
+#else
+ return QList<int>();
+#endif
+}
+
+/*!
+ Links together the shaders that were added to this program with
+ addShader(). Returns true if the link was successful or
+ false otherwise. If the link failed, the error messages can
+ be retrieved with log().
+
+ Subclasses can override this function to initialize attributes
+ and uniform variables for use in specific shader programs.
+
+ If the shader program was already linked, calling this
+ function again will force it to be re-linked.
+
+ \sa addShader(), log()
+*/
+bool QGLShaderProgram::link()
+{
+ if (!d->program)
+ return false;
+ if (d->hasPartialShaders) {
+ // Compile the partial vertex and fragment shaders.
+ QByteArray vertexSource;
+ QByteArray fragmentSource;
+ foreach (QGLShader *shader, d->shaders) {
+ if (shader->shaderType() == QGLShader::PartialVertexShader)
+ vertexSource += shader->sourceCode();
+ else if (shader->shaderType() == QGLShader::PartialFragmentShader)
+ fragmentSource += shader->sourceCode();
+ }
+ if (vertexSource.isEmpty()) {
+ if (d->vertexShader) {
+ glDetachShader(d->program, d->vertexShader->d->shader);
+ delete d->vertexShader;
+ d->vertexShader = 0;
+ }
+ } else {
+ if (!d->vertexShader) {
+ d->vertexShader =
+ new QGLShader(QGLShader::VertexShader, this);
+ }
+ if (!d->vertexShader->compile(vertexSource)) {
+ d->log = d->vertexShader->log();
+ return false;
+ }
+ glAttachShader(d->program, d->vertexShader->d->shader);
+ }
+ if (fragmentSource.isEmpty()) {
+ if (d->fragmentShader) {
+ glDetachShader(d->program, d->fragmentShader->d->shader);
+ delete d->fragmentShader;
+ d->fragmentShader = 0;
+ }
+ } else {
+ if (!d->fragmentShader) {
+ d->fragmentShader =
+ new QGLShader(QGLShader::FragmentShader, this);
+ }
+ if (!d->fragmentShader->compile(fragmentSource)) {
+ d->log = d->fragmentShader->log();
+ return false;
+ }
+ glAttachShader(d->program, d->fragmentShader->d->shader);
+ }
+ }
+ glLinkProgram(d->program);
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->log = QString();
+ if (value > 1) {
+ char *logbuf = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, logbuf);
+ d->log = QString::fromLatin1(logbuf);
+ QString name = objectName();
+ if (name.isEmpty())
+ qWarning() << "QGLShader::link:" << d->log;
+ else
+ qWarning() << "QGLShader::link[" << name << "]:" << d->log;
+ delete [] logbuf;
+ }
+ return d->linked;
+}
+
+/*!
+ Returns true if this shader program has been linked; false otherwise.
+
+ \sa link()
+*/
+bool QGLShaderProgram::isLinked() const
+{
+ return d->linked;
+}
+
+/*!
+ Returns the errors and warnings that occurred during the last link()
+ or addShader() with explicitly specified source code.
+
+ \sa link()
+*/
+QString QGLShaderProgram::log() const
+{
+ return d->log;
+}
+
+/*!
+ Enable use of this shader program in the currently active QGLContext.
+ Returns true if the program was successfully enabled; false
+ otherwise. If the shader program has not yet been linked,
+ or it needs to be re-linked, this function will call link().
+
+ \sa link(), disable()
+*/
+bool QGLShaderProgram::enable()
+{
+ if (!d->program)
+ return false;
+ if (!d->linked && !link())
+ return false;
+ glUseProgram(d->program);
+ return true;
+}
+
+#undef ctx
+#define ctx QGLContext::currentContext()
+
+/*!
+ Disables the active shader program in the current QGLContext.
+ This is equivalent to calling \c{glUseProgram(0)}.
+
+ \sa enable()
+*/
+void QGLShaderProgram::disable()
+{
+#if defined(QT_OPENGL_ES_2)
+ glUseProgram(0);
+#else
+ if (glUseProgram)
+ glUseProgram(0);
+#endif
+}
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Returns the OpenGL identifier associated with this shader program.
+
+ \sa QGLShader::shaderId()
+*/
+GLuint QGLShaderProgram::programId() const
+{
+ return d->program;
+}
+
+/*!
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const char *name, int location)
+{
+ glBindAttribLocation(d->program, location, name);
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.constData());
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QString& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.toLatin1().constData());
+}
+
+/*!
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetAttribLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::attributeLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QByteArray& name) const
+{
+ return attributeLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QString& name) const
+{
+ return attributeLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glVertexAttrib1fv(location, &value);
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glVertexAttrib2fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
+{
+ setAttributeValue(attributeLocation(name), x, y);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glVertexAttrib3fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setAttributeValue(attributeLocation(name), x, y, z);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setAttributeValue(attributeLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QColor& value)
+{
+ if (location != -1) {
+ GLfloat values[4] = {value.redF(), value.greenF(), value.blueF(), value.alphaF()};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, const GLfloat *values, int columns, int rows)
+{
+ if (rows < 1 || rows > 4) {
+ qWarning() << "QGLShaderProgram::setAttributeValue: rows" << rows << "not supported";
+ return;
+ }
+ if (location != -1) {
+ while (columns-- > 0) {
+ if (rows == 1)
+ glVertexAttrib1fv(location, values);
+ else if (rows == 2)
+ glVertexAttrib2fv(location, values);
+ else if (rows == 3)
+ glVertexAttrib3fv(location, values);
+ else
+ glVertexAttrib4fv(location, values);
+ values += rows;
+ ++location;
+ }
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, const GLfloat *values, int columns, int rows)
+{
+ setAttributeValue(attributeLocation(name), values, columns, rows);
+}
+
+/*!
+ Sets an array of vertex \a values on the attribute at \a location
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const GLfloat *values, int size, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 2D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector2D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 3D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector3D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 4D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector4D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ \overload
+
+ Sets an array of vertex \a values on the attribute called \a name
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, size, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 2D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector2D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 3D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector3D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 4D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector4D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ Disables the vertex array at \a location in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(int location)
+{
+ if (location != -1)
+ glDisableVertexAttribArray(location);
+}
+
+/*!
+ \overload
+
+ Disables the vertex array called \a name in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(const char *name)
+{
+ disableAttributeArray(attributeLocation(name));
+}
+
+/*!
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetUniformLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::uniformLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QByteArray& name) const
+{
+ return uniformLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QString& name) const
+{
+ return uniformLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glUniform1fv(location, 1, &value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLint value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+ This function should be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLuint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value. This function should be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLuint value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
+{
+ setUniformValue(uniformLocation(name), x, y);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glUniform3fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setUniformValue(uniformLocation(name), x, y, z);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setUniformValue(uniformLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QColor& color)
+{
+ if (location != -1) {
+ GLfloat values[4] = {color.redF(), color.greenF(), color.blueF(), color.alphaF()};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QColor& color)
+{
+ setUniformValue(uniformLocation(name), color);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QPoint& point)
+{
+ if (location != -1) {
+ GLfloat values[4] = {point.x(), point.y()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QPoint& point)
+{
+ setUniformValue(uniformLocation(name), point);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QPointF& point)
+{
+ if (location != -1) {
+ GLfloat values[4] = {point.x(), point.y()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the x and y coordinates of \a point.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QPointF& point)
+{
+ setUniformValue(uniformLocation(name), point);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QSize& size)
+{
+ if (location != -1) {
+ GLfloat values[4] = {size.width(), size.width()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QSize& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QSizeF& size)
+{
+ if (location != -1) {
+ GLfloat values[4] = {size.width(), size.height()};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable associated with \a name in the current
+ context to the width and height of the given \a size.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QSizeF& size)
+{
+ setUniformValue(uniformLocation(name), size);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
+{
+ if (location != -1)
+ glUniformMatrix2fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
+{
+ if (location != -1)
+ glUniformMatrix3fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(location, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue(int location, const QTransform& value)
+{
+ if (location != -1) {
+ GLfloat mat[3][3] = {
+ {value.m11(), value.m12(), value.m13()},
+ {value.m21(), value.m22(), value.m23()},
+ {value.m31(), value.m32(), value.m33()}
+ };
+ glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(name, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, const QTransform& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
+{
+ if (location != -1)
+ glUniform1iv(location, count, values);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLint *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. This overload
+ should be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLuint *values, int count)
+{
+ if (location != -1)
+ glUniform1iv(location, count, reinterpret_cast<const GLint *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. This overload
+ should be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLuint *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int size)
+{
+ if (location != -1) {
+ if (size == 1)
+ glUniform1fv(location, count, values);
+ else if (size == 2)
+ glUniform2fv(location, count, values);
+ else if (size == 3)
+ glUniform3fv(location, count, values);
+ else if (size == 4)
+ glUniform4fv(location, count, values);
+ else
+ qWarning() << "QGLShaderProgram::setUniformValue: size" << size << "not supported";
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLfloat *values, int count, int size)
+{
+ setUniformValueArray(uniformLocation(name), values, count, size);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
+{
+ if (location != -1)
+ glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
+{
+ if (location != -1)
+ glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
+{
+ if (location != -1)
+ glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+// We may have to repack matrix arrays if the matrix types
+// contain additional flag bits. Especially QMatrix4x4.
+#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ func(location, count, GL_FALSE, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ func(location, count, GL_FALSE, temp.constData()); \
+ }
+#if !defined(QT_OPENGL_ES_2)
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ if (func) \
+ func(location, count, GL_FALSE, values->constData()); \
+ else \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ if (func) \
+ func(location, count, GL_FALSE, temp.constData()); \
+ else \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#else
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#endif
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x3fv, glUniform3fv, location, values, count,
+ QMatrix2x3, 2, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x4fv, glUniform4fv, location, values, count,
+ QMatrix2x4, 2, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x2fv, glUniform2fv, location, values, count,
+ QMatrix3x2, 3, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x4fv, glUniform4fv, location, values, count,
+ QMatrix3x4, 3, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x2fv, glUniform2fv, location, values, count,
+ QMatrix4x2, 4, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x3fv, glUniform3fv, location, values, count,
+ QMatrix4x3, 4, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Returns true if shader programs written in the OpenGL Shading
+ Language (GLSL) are supported on this system; false otherwise.
+
+ The \a context is used to resolve the GLSL extensions.
+ If \a context is null, then QGLContext::currentContext() is used.
+*/
+bool QGLShaderProgram::hasShaderPrograms(const QGLContext *context)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ return qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
+#else
+ Q_UNUSED(context);
+ return true;
+#endif
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
new file mode 100644
index 0000000..06bff42
--- /dev/null
+++ b/src/opengl/qglshaderprogram.h
@@ -0,0 +1,293 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGLSHADERPROGRAM_H
+#define QGLSHADERPROGRAM_H
+
+#include <QtOpenGL/qgl.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qmatrix4x4.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+#if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
+
+class QGLShaderProgram;
+class QGLShaderPrivate;
+
+class Q_OPENGL_EXPORT QGLShader : public QObject
+{
+ Q_OBJECT
+public:
+ enum ShaderType
+ {
+ VertexShader,
+ FragmentShader,
+ PartialVertexShader,
+ PartialFragmentShader
+ };
+
+ explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0);
+ explicit QGLShader(const QString& fileName, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0);
+ QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShader();
+
+ QGLShader::ShaderType shaderType() const;
+
+ bool compile(const char *source);
+ bool compile(const QByteArray& source);
+ bool compile(const QString& source);
+ bool compileFile(const QString& fileName);
+
+ bool setShaderBinary(GLenum format, const void *binary, int length);
+ bool setShaderBinary(QGLShader& otherShader, GLenum format, const void *binary, int length);
+
+ static QList<GLenum> shaderBinaryFormats();
+
+ QByteArray sourceCode() const;
+
+ bool isCompiled() const;
+ QString log() const;
+
+ GLuint shaderId() const;
+
+private:
+ QGLShaderPrivate *d;
+
+ friend class QGLShaderProgram;
+
+ Q_DISABLE_COPY(QGLShader)
+};
+
+class QGLShaderProgramPrivate;
+
+class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QGLShaderProgram(QObject *parent = 0);
+ explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShaderProgram();
+
+ bool addShader(QGLShader *shader);
+ void removeShader(QGLShader *shader);
+ QList<QGLShader *> shaders() const;
+
+ bool addShader(QGLShader::ShaderType type, const char *source);
+ bool addShader(QGLShader::ShaderType type, const QByteArray& source);
+ bool addShader(QGLShader::ShaderType type, const QString& source);
+
+ void removeAllShaders();
+
+ QByteArray programBinary(int *format) const;
+ bool setProgramBinary(int format, const QByteArray& binary);
+ static QList<int> programBinaryFormats();
+
+ virtual bool link();
+ bool isLinked() const;
+ QString log() const;
+
+ bool enable();
+ static void disable();
+
+ GLuint programId() const;
+
+ void bindAttributeLocation(const char *name, int location);
+ void bindAttributeLocation(const QByteArray& name, int location);
+ void bindAttributeLocation(const QString& name, int location);
+
+ int attributeLocation(const char *name) const;
+ int attributeLocation(const QByteArray& name) const;
+ int attributeLocation(const QString& name) const;
+
+ void setAttributeValue(int location, GLfloat value);
+ void setAttributeValue(int location, GLfloat x, GLfloat y);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(int location, const QVector2D& value);
+ void setAttributeValue(int location, const QVector3D& value);
+ void setAttributeValue(int location, const QVector4D& value);
+ void setAttributeValue(int location, const QColor& value);
+ void setAttributeValue(int location, const GLfloat *values, int columns, int rows);
+
+ void setAttributeValue(const char *name, GLfloat value);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(const char *name, const QVector2D& value);
+ void setAttributeValue(const char *name, const QVector3D& value);
+ void setAttributeValue(const char *name, const QVector4D& value);
+ void setAttributeValue(const char *name, const QColor& value);
+ void setAttributeValue(const char *name, const GLfloat *values, int columns, int rows);
+
+ void setAttributeArray
+ (int location, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector4D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector4D *values, int stride = 0);
+ void disableAttributeArray(int location);
+ void disableAttributeArray(const char *name);
+
+ int uniformLocation(const char *name) const;
+ int uniformLocation(const QByteArray& name) const;
+ int uniformLocation(const QString& name) const;
+
+ void setUniformValue(int location, GLfloat value);
+ void setUniformValue(int location, GLint value);
+ void setUniformValue(int location, GLuint value);
+ void setUniformValue(int location, GLfloat x, GLfloat y);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(int location, const QVector2D& value);
+ void setUniformValue(int location, const QVector3D& value);
+ void setUniformValue(int location, const QVector4D& value);
+ void setUniformValue(int location, const QColor& color);
+ void setUniformValue(int location, const QPoint& point);
+ void setUniformValue(int location, const QPointF& point);
+ void setUniformValue(int location, const QSize& size);
+ void setUniformValue(int location, const QSizeF& size);
+ void setUniformValue(int location, const QMatrix2x2& value);
+ void setUniformValue(int location, const QMatrix2x3& value);
+ void setUniformValue(int location, const QMatrix2x4& value);
+ void setUniformValue(int location, const QMatrix3x2& value);
+ void setUniformValue(int location, const QMatrix3x3& value);
+ void setUniformValue(int location, const QMatrix3x4& value);
+ void setUniformValue(int location, const QMatrix4x2& value);
+ void setUniformValue(int location, const QMatrix4x3& value);
+ void setUniformValue(int location, const QMatrix4x4& value);
+ void setUniformValue(int location, const GLfloat value[4][4]);
+ void setUniformValue(int location, const QTransform& value);
+
+ void setUniformValue(const char *name, GLfloat value);
+ void setUniformValue(const char *name, GLint value);
+ void setUniformValue(const char *name, GLuint value);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(const char *name, const QVector2D& value);
+ void setUniformValue(const char *name, const QVector3D& value);
+ void setUniformValue(const char *name, const QVector4D& value);
+ void setUniformValue(const char *name, const QColor& color);
+ void setUniformValue(const char *name, const QPoint& point);
+ void setUniformValue(const char *name, const QPointF& point);
+ void setUniformValue(const char *name, const QSize& size);
+ void setUniformValue(const char *name, const QSizeF& size);
+ void setUniformValue(const char *name, const QMatrix2x2& value);
+ void setUniformValue(const char *name, const QMatrix2x3& value);
+ void setUniformValue(const char *name, const QMatrix2x4& value);
+ void setUniformValue(const char *name, const QMatrix3x2& value);
+ void setUniformValue(const char *name, const QMatrix3x3& value);
+ void setUniformValue(const char *name, const QMatrix3x4& value);
+ void setUniformValue(const char *name, const QMatrix4x2& value);
+ void setUniformValue(const char *name, const QMatrix4x3& value);
+ void setUniformValue(const char *name, const QMatrix4x4& value);
+ void setUniformValue(const char *name, const GLfloat value[4][4]);
+ void setUniformValue(const char *name, const QTransform& value);
+
+ void setUniformValueArray(int location, const GLfloat *values, int count, int size);
+ void setUniformValueArray(int location, const GLint *values, int count);
+ void setUniformValueArray(int location, const GLuint *values, int count);
+ void setUniformValueArray(int location, const QVector2D *values, int count);
+ void setUniformValueArray(int location, const QVector3D *values, int count);
+ void setUniformValueArray(int location, const QVector4D *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x4 *values, int count);
+
+ void setUniformValueArray(const char *name, const GLfloat *values, int count, int size);
+ void setUniformValueArray(const char *name, const GLint *values, int count);
+ void setUniformValueArray(const char *name, const GLuint *values, int count);
+ void setUniformValueArray(const char *name, const QVector2D *values, int count);
+ void setUniformValueArray(const char *name, const QVector3D *values, int count);
+ void setUniformValueArray(const char *name, const QVector4D *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x4 *values, int count);
+
+ static bool hasShaderPrograms(const QGLContext *context = 0);
+
+private:
+ QGLShaderProgramPrivate *d;
+
+ Q_DISABLE_COPY(QGLShaderProgram)
+
+ bool init();
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/opengl/qpaintengine_opengl.cpp b/src/opengl/qpaintengine_opengl.cpp
index c9fbc7e..5690c6b 100644
--- a/src/opengl/qpaintengine_opengl.cpp
+++ b/src/opengl/qpaintengine_opengl.cpp
@@ -39,7 +39,6 @@
**
****************************************************************************/
-#include <private/qtextengine_p.h>
#include <qdebug.h>
#include <private/qfontengine_p.h>
#include <qmath.h>
@@ -57,13 +56,11 @@
#include "qpen.h"
#include "qvarlengtharray.h"
#include <private/qpainter_p.h>
-#include <qglpixelbuffer.h>
#include <private/qglpixelbuffer_p.h>
#include <private/qbezier_p.h>
#include <qglframebufferobject.h>
#include "private/qtessellator_p.h"
-#include "private/qwindowsurface_gl_p.h"
#include "util/fragmentprograms_p.h"
@@ -125,35 +122,6 @@ struct QT_PointF {
qreal y;
};
-void qt_add_rect_to_array(const QRectF &r, q_vertexType *array)
-{
- qreal left = r.left();
- qreal right = r.right();
- qreal top = r.top();
- qreal bottom = r.bottom();
-
- array[0] = f2vt(left);
- array[1] = f2vt(top);
- array[2] = f2vt(right);
- array[3] = f2vt(top);
- array[4] = f2vt(right);
- array[5] = f2vt(bottom);
- array[6] = f2vt(left);
- array[7] = f2vt(bottom);
-}
-
-void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array)
-{
- array[0] = f2vt(x1);
- array[1] = f2vt(y1);
- array[2] = f2vt(x2);
- array[3] = f2vt(y1);
- array[4] = f2vt(x2);
- array[5] = f2vt(y2);
- array[6] = f2vt(x1);
- array[7] = f2vt(y2);
-}
-
struct QGLTrapezoid
{
QGLTrapezoid()
@@ -190,180 +158,6 @@ const QGLTrapezoid QGLTrapezoid::translated(const QPointF &delta) const
return trap;
}
-class QGLDrawable {
-public:
- QGLDrawable() : widget(0), buffer(0), fbo(0)
- , wsurf(0)
- {}
- inline void setDevice(QPaintDevice *pdev);
- inline void swapBuffers();
- inline void makeCurrent();
- inline void doneCurrent();
- inline QSize size() const;
- inline QGLFormat format() const;
- inline GLuint bindTexture(const QImage &image, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
- inline GLuint bindTexture(const QPixmap &pixmap, GLenum target = GL_TEXTURE_2D, GLint format = GL_RGBA);
- inline QColor backgroundColor() const;
- inline QGLContext *context() const;
- inline bool autoFillBackground() const;
-
-private:
- bool wasBound;
- QGLWidget *widget;
- QGLPixelBuffer *buffer;
- QGLFramebufferObject *fbo;
-#ifdef Q_WS_QWS
- QWSGLWindowSurface *wsurf;
-#else
- QGLWindowSurface *wsurf;
-#endif
-};
-
-void QGLDrawable::setDevice(QPaintDevice *pdev)
-{
- wasBound = false;
- widget = 0;
- buffer = 0;
- fbo = 0;
-#ifdef Q_WS_QWS
- wsurf = 0;
-#endif
- if (pdev->devType() == QInternal::Widget)
- widget = static_cast<QGLWidget *>(pdev);
- else if (pdev->devType() == QInternal::Pbuffer)
- buffer = static_cast<QGLPixelBuffer *>(pdev);
- else if (pdev->devType() == QInternal::FramebufferObject)
- fbo = static_cast<QGLFramebufferObject *>(pdev);
- else if (pdev->devType() == QInternal::UnknownDevice)
-#ifdef Q_WS_QWS
- wsurf = static_cast<QWSGLPaintDevice*>(pdev)->windowSurface();
-#else
- wsurf = static_cast<QGLWindowSurface *>(pdev);
-#endif
-}
-
-inline void QGLDrawable::swapBuffers()
-{
- if (widget) {
- if (widget->autoBufferSwap())
- widget->swapBuffers();
- } else {
- glFlush();
- }
-}
-
-inline void QGLDrawable::makeCurrent()
-{
- if (widget)
- widget->makeCurrent();
- else if (buffer)
- buffer->makeCurrent();
- else if (wsurf)
- wsurf->context()->makeCurrent();
- else if (fbo) {
- wasBound = fbo->isBound();
- if (!wasBound)
- fbo->bind();
- }
-}
-
-inline void QGLDrawable::doneCurrent()
-{
- if (fbo && !wasBound)
- fbo->release();
-}
-
-inline QSize QGLDrawable::size() const
-{
- if (widget) {
- return QSize(widget->d_func()->glcx->device()->width(),
- widget->d_func()->glcx->device()->height());
- } else if (buffer) {
- return buffer->size();
- } else if (fbo) {
- return fbo->size();
- } else if (wsurf) {
-#ifdef Q_WS_QWS
- return wsurf->window()->frameSize();
-#else
- return QSize(wsurf->width(), wsurf->height());
-#endif
- }
- return QSize();
-}
-
-inline QGLFormat QGLDrawable::format() const
-{
- if (widget)
- return widget->format();
- else if (buffer)
- return buffer->format();
- else if (wsurf)
- return wsurf->context()->format();
- else if (fbo && QGLContext::currentContext()) {
- QGLFormat fmt = QGLContext::currentContext()->format();
- fmt.setStencil(fbo->attachment() == QGLFramebufferObject::CombinedDepthStencil);
- fmt.setDepth(fbo->attachment() != QGLFramebufferObject::NoAttachment);
- return fmt;
- }
-
- return QGLFormat();
-}
-
-inline GLuint QGLDrawable::bindTexture(const QImage &image, GLenum target, GLint format)
-{
- if (widget)
- return widget->d_func()->glcx->d_func()->bindTexture(image, target, format, true);
- else if (buffer)
- return buffer->d_func()->qctx->d_func()->bindTexture(image, target, format, true);
- else if (fbo && QGLContext::currentContext())
- return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(image, target, format, true);
- else if (wsurf)
- return wsurf->context()->d_func()->bindTexture(image, target, format, true);
- return 0;
-}
-
-inline GLuint QGLDrawable::bindTexture(const QPixmap &pixmap, GLenum target, GLint format)
-{
- if (widget)
- return widget->d_func()->glcx->d_func()->bindTexture(pixmap, target, format, true);
- else if (buffer)
- return buffer->d_func()->qctx->d_func()->bindTexture(pixmap, target, format, true);
- else if (fbo && QGLContext::currentContext())
- return const_cast<QGLContext *>(QGLContext::currentContext())->d_func()->bindTexture(pixmap, target, format, true);
- else if (wsurf)
- return wsurf->context()->d_func()->bindTexture(pixmap, target, format, true);
- return 0;
-}
-
-inline QColor QGLDrawable::backgroundColor() const
-{
- if (widget)
- return widget->palette().brush(widget->backgroundRole()).color();
- return QApplication::palette().brush(QPalette::Background).color();
-}
-
-inline QGLContext *QGLDrawable::context() const
-{
- if (widget)
- return widget->d_func()->glcx;
- else if (buffer)
- return buffer->d_func()->qctx;
- else if (fbo)
- return const_cast<QGLContext *>(QGLContext::currentContext());
- else if (wsurf)
- return wsurf->context();
- return 0;
-}
-
-inline bool QGLDrawable::autoFillBackground() const
-{
- if (widget)
- return widget->autoFillBackground();
- else
- return false;
-}
-
class QOpenGLImmediateModeTessellator;
class QGLMaskGenerator;
@@ -1536,9 +1330,15 @@ bool QOpenGLPaintEngine::begin(QPaintDevice *pdev)
d->offscreen.begin();
- const QColor &c = d->drawable.backgroundColor();
- glClearColor(c.redF(), c.greenF(), c.blueF(), 1.0);
if (d->drawable.context()->d_func()->clear_on_painter_begin && d->drawable.autoFillBackground()) {
+
+ if (d->drawable.hasTransparentBackground())
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ else {
+ const QColor &c = d->drawable.backgroundColor();
+ glClearColor(c.redF(), c.greenF(), c.blueF(), 1.0);
+ }
+
GLbitfield clearBits = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT;
#ifndef QT_OPENGL_ES
clearBits |= GL_ACCUM_BUFFER_BIT;
@@ -1924,15 +1724,15 @@ static void drawTrapezoid(const QGLTrapezoid &trap, const qreal offscreenHeight,
qreal leftB = trap.bottomLeftX + (trap.topLeftX - trap.bottomLeftX) * reciprocal;
qreal rightB = trap.bottomRightX + (trap.topRightX - trap.bottomRightX) * reciprocal;
- const bool topZero = qFuzzyCompare(topDist + 1, 1);
+ const bool topZero = qFuzzyIsNull(topDist);
reciprocal = topZero ? 1.0 / bottomDist : 1.0 / topDist;
qreal leftA = topZero ? (trap.bottomLeftX - leftB) * reciprocal : (trap.topLeftX - leftB) * reciprocal;
qreal rightA = topZero ? (trap.bottomRightX - rightB) * reciprocal : (trap.topRightX - rightB) * reciprocal;
- qreal invLeftA = qFuzzyCompare(leftA + 1, 1) ? 0.0 : 1.0 / leftA;
- qreal invRightA = qFuzzyCompare(rightA + 1, 1) ? 0.0 : 1.0 / rightA;
+ qreal invLeftA = qFuzzyIsNull(leftA) ? 0.0 : 1.0 / leftA;
+ qreal invRightA = qFuzzyIsNull(rightA) ? 0.0 : 1.0 / rightA;
// fragment program needs the negative of invRightA as it mirrors the line
glTexCoord4f(topDist, bottomDist, invLeftA, -invRightA);
@@ -2233,7 +2033,7 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule)
// Enable color writes.
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
- glStencilMask(0);
+ glStencilMask(stencilMask);
setGradientOps(cbrush, QRectF(QPointF(min_x, min_y), QSizeF(max_x - min_x, max_y - min_y)));
@@ -2245,12 +2045,14 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule)
// Enable stencil func.
glStencilFunc(GL_NOTEQUAL, 0, stencilMask);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
composite(rect);
} else {
DEBUG_ONCE qDebug() << "QOpenGLPaintEnginePrivate: Drawing polygon using stencil method (no fragment programs)";
// Enable stencil func.
glStencilFunc(GL_NOTEQUAL, 0, stencilMask);
+ glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
#ifndef QT_OPENGL_ES
glBegin(GL_QUADS);
glVertex2f(min_x, min_y);
@@ -2261,24 +2063,6 @@ void QOpenGLPaintEnginePrivate::fillVertexArray(Qt::FillRule fillRule)
#endif
}
- glStencilMask(~0);
- glStencilFunc(GL_ALWAYS, 0, 0);
- glStencilOp(GL_ZERO, GL_ZERO, GL_ZERO);
-
- // clear all stencil values to 0
- glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
-
-#ifndef QT_OPENGL_ES
- glBegin(GL_QUADS);
- glVertex2f(min_x, min_y);
- glVertex2f(max_x, min_y);
- glVertex2f(max_x, max_y);
- glVertex2f(min_x, max_y);
- glEnd();
-#endif
-
- glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-
// Disable stencil writes.
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilMask(0);
@@ -2460,11 +2244,12 @@ void QOpenGLPaintEnginePrivate::updateDepthClip()
return;
}
-#ifndef QT_OPENGL_ES
- glClearDepth(0.0f);
-#else
+#if defined(QT_OPENGL_ES_1) || defined(QT_OPENGL_ES_2) || defined(QT_OPENGL_ES_1_CL)
glClearDepthf(0.0f);
+#else
+ glClearDepth(0.0f);
#endif
+
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
glClear(GL_DEPTH_BUFFER_BIT);
@@ -3300,6 +3085,9 @@ QGLTrapezoidMaskGenerator::QGLTrapezoidMaskGenerator(const QPainterPath &path, c
{
}
+extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array);
+extern void qt_add_texcoords_to_array(qreal x1, qreal y1, qreal x2, qreal y2, q_vertexType *array);
+
void QGLTrapezoidMaskGenerator::drawMask(const QRect &rect)
{
#ifdef QT_OPENGL_ES
@@ -3445,8 +3233,7 @@ QVector<QGLTrapezoid> QGLRectMaskGenerator::generateTrapezoids()
// manhattan distance (no rotation)
qreal width = qAbs(delta.x()) + qAbs(delta.y());
- Q_ASSERT(qFuzzyCompare(delta.x() + 1, static_cast<qreal>(1))
- || qFuzzyCompare(delta.y() + 1, static_cast<qreal>(1)));
+ Q_ASSERT(qFuzzyIsNull(delta.x()) || qFuzzyIsNull(delta.y()));
tessellator.tessellateRect(first, last, width);
} else {
@@ -5783,9 +5570,11 @@ void QOpenGLPaintEnginePrivate::ensureDrawableTexture()
QPixmapFilter *QOpenGLPaintEngine::createPixmapFilter(int type) const
{
+#if !defined(QT_OPENGL_ES_1) && !defined(QT_OPENGL_ES_1_CL)
if (QGLContext::currentContext())
return QGLContext::currentContext()->d_func()->createPixmapFilter(type);
else
+#endif
return 0;
}
diff --git a/src/opengl/qpixmapdata_gl.cpp b/src/opengl/qpixmapdata_gl.cpp
index 5d668cd..48feb82 100644
--- a/src/opengl/qpixmapdata_gl.cpp
+++ b/src/opengl/qpixmapdata_gl.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qpixmap.h"
+#include "qglframebufferobject.h"
#include <private/qpaintengine_raster_p.h>
@@ -48,6 +49,8 @@
#include <private/qgl_p.h>
#include <private/qdrawhelper_p.h>
+#include <private/qpaintengineex_opengl2_p.h>
+
QT_BEGIN_NAMESPACE
extern QGLWidget* qt_gl_share_widget();
@@ -57,12 +60,14 @@ class QGLShareContextScope
public:
QGLShareContextScope(const QGLContext *ctx)
: m_oldContext(0)
- , m_ctx(const_cast<QGLContext *>(ctx))
{
- const QGLContext *currentContext = QGLContext::currentContext();
+ QGLContext *currentContext = const_cast<QGLContext *>(QGLContext::currentContext());
if (currentContext != ctx && !qgl_share_reg()->checkSharing(ctx, currentContext)) {
- m_oldContext = const_cast<QGLContext *>(currentContext);
+ m_oldContext = currentContext;
+ m_ctx = const_cast<QGLContext *>(ctx);
m_ctx->makeCurrent();
+ } else {
+ m_ctx = currentContext;
}
}
@@ -87,58 +92,30 @@ private:
QGLContext *m_ctx;
};
-void qt_gl_convertFromGLImage(QImage *img)
-{
- const int w = img->width();
- const int h = img->height();
-
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- uint *p = (uint*)img->bits();
- uint *end = p + w*h;
-
- while (p < end) {
- uint a = *p << 24;
- *p = (*p >> 8) | a;
- p++;
- }
-
- *img = img->mirrored();
- } else {
- // mirror image
- uint *data = (uint *)img->bits();
-
- const int mid = h/2;
-
- for (int y = 0; y < mid; ++y) {
- uint *p = data + y * w;
- uint *end = p + w;
- uint *q = data + (h - y - 1) * w;
-
- while (p < end)
- qSwap(*p++, *q++);
- }
- }
-}
-
-
static int qt_gl_pixmap_serial = 0;
QGLPixmapData::QGLPixmapData(PixelType type)
: QPixmapData(type, OpenGLClass)
, m_width(0)
, m_height(0)
- , m_texture(0)
+ , m_renderFbo(0)
+ , m_textureId(0)
+ , m_engine(0)
+ , m_ctx(0)
, m_dirty(false)
+ , m_hasFillColor(false)
+ , m_hasAlpha(false)
{
setSerialNumber(++qt_gl_pixmap_serial);
}
QGLPixmapData::~QGLPixmapData()
{
- if (m_texture && qt_gl_share_widget()) {
- QGLShareContextScope ctx(qt_gl_share_widget()->context());
- glDeleteTextures(1, &m_texture);
- }
+ QGLWidget *shareWidget = qt_gl_share_widget();
+ if (!shareWidget)
+ return;
+ QGLShareContextScope ctx(shareWidget->context());
+ glDeleteTextures(1, &m_textureId);
}
bool QGLPixmapData::isValid() const
@@ -148,6 +125,9 @@ bool QGLPixmapData::isValid() const
bool QGLPixmapData::isValidContext(const QGLContext *ctx) const
{
+ if (ctx == m_ctx)
+ return true;
+
const QGLContext *share_ctx = qt_gl_share_widget()->context();
return ctx == share_ctx || qgl_share_reg()->checkSharing(ctx, share_ctx);
}
@@ -157,9 +137,20 @@ void QGLPixmapData::resize(int width, int height)
if (width == m_width && height == m_height)
return;
+ if (width <= 0 || height <= 0) {
+ width = 0;
+ height = 0;
+ }
+
m_width = width;
m_height = height;
+ if (m_textureId) {
+ QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ glDeleteTextures(1, &m_textureId);
+ m_textureId = 0;
+ }
+
m_source = QImage();
m_dirty = isValid();
setSerialNumber(++qt_gl_pixmap_serial);
@@ -173,36 +164,82 @@ void QGLPixmapData::ensureCreated() const
m_dirty = false;
QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ m_ctx = ctx;
const GLenum format = qt_gl_preferredTextureFormat();
- const GLenum target = qt_gl_preferredTextureTarget();
-
- if (!m_texture)
- glGenTextures(1, &m_texture);
-
- glBindTexture(target, m_texture);
+ const GLenum target = GL_TEXTURE_2D;
+
+ if (!m_textureId) {
+ glGenTextures(1, &m_textureId);
+ glBindTexture(target, m_textureId);
+ GLenum format = m_hasAlpha ? GL_RGBA : GL_RGB;
+ glTexImage2D(target, 0, format, m_width, m_height, 0,
+ GL_RGBA, GL_UNSIGNED_BYTE, 0);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ }
- if (m_source.isNull()) {
- glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format, GL_UNSIGNED_BYTE, 0);
- } else {
+ if (!m_source.isNull()) {
const QImage tx = ctx->d_func()->convertToGLFormat(m_source, true, format);
- glBindTexture(target, m_texture);
- glTexImage2D(target, 0, GL_RGBA, m_width, m_height, 0, format,
- GL_UNSIGNED_BYTE, tx.bits());
+ glBindTexture(target, m_textureId);
+ glTexSubImage2D(target, 0, 0, 0, m_width, m_height, format,
+ GL_UNSIGNED_BYTE, tx.bits());
- m_source = QImage();
+ if (useFramebufferObjects())
+ m_source = QImage();
}
}
+QGLFramebufferObject *QGLPixmapData::fbo() const
+{
+ return m_renderFbo;
+}
+
void QGLPixmapData::fromImage(const QImage &image,
Qt::ImageConversionFlags)
{
if (image.size() == QSize(m_width, m_height))
setSerialNumber(++qt_gl_pixmap_serial);
resize(image.width(), image.height());
- m_source = image;
+
+ if (pixelType() == BitmapType) {
+ m_source = image.convertToFormat(QImage::Format_MonoLSB);
+ } else {
+ m_source = image.hasAlphaChannel()
+ ? image.convertToFormat(QImage::Format_ARGB32_Premultiplied)
+ : image.convertToFormat(QImage::Format_RGB32);
+ }
+
m_dirty = true;
+ m_hasFillColor = false;
+
+ m_hasAlpha = image.hasAlphaChannel();
+
+ if (m_textureId) {
+ QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ glDeleteTextures(1, &m_textureId);
+ m_textureId = 0;
+ }
+}
+
+bool QGLPixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ Q_UNUSED(dx);
+ Q_UNUSED(dy);
+ Q_UNUSED(rect);
+ return false;
+}
+
+void QGLPixmapData::copy(const QPixmapData *data, const QRect &rect)
+{
+ if (data->classId() != QPixmapData::OpenGLClass) {
+ QPixmapData::copy(data, rect);
+ return;
+ }
+
+ // can be optimized to do a framebuffer blit or similar ...
+ QPixmapData::copy(data, rect);
}
void QGLPixmapData::fill(const QColor &color)
@@ -210,20 +247,46 @@ void QGLPixmapData::fill(const QColor &color)
if (!isValid())
return;
- if (!m_source.isNull()) {
- m_source.fill(PREMUL(color.rgba()));
- } else {
- // ## TODO: improve performance here
- QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
- img.fill(PREMUL(color.rgba()));
+ if (!m_textureId)
+ m_hasAlpha = color.alpha() != 255;
- fromImage(img, 0);
+ if (useFramebufferObjects()) {
+ m_source = QImage();
+ m_hasFillColor = true;
+ m_fillColor = color;
+ } else {
+ QImage image = fillImage(color);
+ fromImage(image, 0);
}
}
bool QGLPixmapData::hasAlphaChannel() const
{
- return true;
+ return m_hasAlpha;
+}
+
+QImage QGLPixmapData::fillImage(const QColor &color) const
+{
+ QImage img;
+ if (pixelType() == BitmapType) {
+ img = QImage(m_width, m_height, QImage::Format_MonoLSB);
+ img.setNumColors(2);
+ img.setColor(0, QColor(Qt::color0).rgba());
+ img.setColor(1, QColor(Qt::color1).rgba());
+
+ int gray = qGray(color.rgba());
+ if (qAbs(255 - gray) < gray)
+ img.fill(0);
+ else
+ img.fill(1);
+ } else {
+ img = QImage(m_width, m_height,
+ m_hasAlpha
+ ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_RGB32);
+ img.fill(PREMUL(color.rgba()));
+ }
+ return img;
}
QImage QGLPixmapData::toImage() const
@@ -231,29 +294,111 @@ QImage QGLPixmapData::toImage() const
if (!isValid())
return QImage();
- if (!m_source.isNull())
+ if (m_renderFbo) {
+ copyBackFromRenderFbo(true);
+ } else if (!m_source.isNull()) {
return m_source;
- else if (m_dirty)
- return QImage(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
+ } else if (m_dirty || m_hasFillColor) {
+ return fillImage(m_fillColor);
+ } else {
+ ensureCreated();
+ }
+
+ QGLShareContextScope ctx(qt_gl_share_widget()->context());
+ extern QImage qt_gl_read_texture(const QSize &size, bool alpha_format, bool include_alpha);
+ glBindTexture(GL_TEXTURE_2D, m_textureId);
+ return qt_gl_read_texture(QSize(m_width, m_height), true, true);
+}
+
+struct TextureBuffer
+{
+ QGLFramebufferObject *fbo;
+ QGL2PaintEngineEx *engine;
+};
+
+static QVector<TextureBuffer> textureBufferStack;
+static int currentTextureBuffer = 0;
+
+void QGLPixmapData::copyBackFromRenderFbo(bool keepCurrentFboBound) const
+{
+ if (!isValid())
+ return;
+
+ m_hasFillColor = false;
+
+ const QGLContext *share_ctx = qt_gl_share_widget()->context();
+ QGLShareContextScope ctx(share_ctx);
ensureCreated();
- QGLShareContextScope ctx(qt_gl_share_widget()->context());
- QImage img(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
+ if (!ctx->d_ptr->fbo)
+ glGenFramebuffers(1, &ctx->d_ptr->fbo);
- GLenum format = qt_gl_preferredTextureFormat();
- GLenum target = qt_gl_preferredTextureTarget();
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->fbo);
+ glFramebufferTexture2D(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
+ GL_TEXTURE_2D, m_textureId, 0);
- glBindTexture(target, m_texture);
-#ifndef QT_OPENGL_ES
- glGetTexImage(target, 0, format, GL_UNSIGNED_BYTE, img.bits());
-#else
- // XXX - cannot download textures this way on OpenGL/ES.
-#endif
+ const int x0 = 0;
+ const int x1 = m_width;
+ const int y0 = 0;
+ const int y1 = m_height;
- qt_gl_convertFromGLImage(&img);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER_EXT, m_renderFbo->handle());
- return img;
+ glDisable(GL_SCISSOR_TEST);
+
+ glBlitFramebufferEXT(x0, y0, x1, y1,
+ x0, y0, x1, y1,
+ GL_COLOR_BUFFER_BIT,
+ GL_NEAREST);
+
+ if (keepCurrentFboBound)
+ glBindFramebuffer(GL_FRAMEBUFFER_EXT, ctx->d_ptr->current_fbo);
+}
+
+void QGLPixmapData::swapBuffers()
+{
+ if (!isValid())
+ return;
+
+ copyBackFromRenderFbo(false);
+ m_renderFbo->release();
+
+ --currentTextureBuffer;
+
+ m_renderFbo = 0;
+ m_engine = 0;
+}
+
+void QGLPixmapData::makeCurrent()
+{
+ if (isValid() && m_renderFbo)
+ m_renderFbo->bind();
+}
+
+void QGLPixmapData::doneCurrent()
+{
+ if (isValid() && m_renderFbo)
+ m_renderFbo->release();
+}
+
+static TextureBuffer createTextureBuffer(const QSize &size, QGL2PaintEngineEx *engine = 0)
+{
+ TextureBuffer buffer;
+ QGLFramebufferObjectFormat fmt;
+ fmt.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ fmt.setSamples(4);
+
+ buffer.fbo = new QGLFramebufferObject(size, fmt);
+ buffer.engine = engine ? engine : new QGL2PaintEngineEx;
+
+ return buffer;
+}
+
+bool QGLPixmapData::useFramebufferObjects()
+{
+ return QGLFramebufferObject::hasOpenGLFramebufferObjects()
+ && QGLFramebufferObject::hasOpenGLFramebufferBlit();
}
QPaintEngine* QGLPixmapData::paintEngine() const
@@ -261,23 +406,82 @@ QPaintEngine* QGLPixmapData::paintEngine() const
if (!isValid())
return 0;
- m_source = toImage();
- m_dirty = true;
+ if (m_engine)
+ return m_engine;
+
+ if (useFramebufferObjects()) {
+ extern QGLWidget* qt_gl_share_widget();
+
+ if (!QGLContext::currentContext())
+ qt_gl_share_widget()->makeCurrent();
+ QGLShareContextScope ctx(qt_gl_share_widget()->context());
+
+ if (textureBufferStack.size() <= currentTextureBuffer) {
+ textureBufferStack << createTextureBuffer(size());
+ } else {
+ QSize sz = textureBufferStack.at(currentTextureBuffer).fbo->size();
+ if (sz.width() < m_width || sz.height() < m_height) {
+ if (sz.width() < m_width)
+ sz.setWidth(qMax(m_width, qRound(sz.width() * 1.5)));
+ if (sz.height() < m_height)
+ sz.setHeight(qMax(m_height, qRound(sz.height() * 1.5)));
+
+ // wasting too much space?
+ if (sz.width() * sz.height() > m_width * m_height * 2.5)
+ sz = QSize(m_width, m_height);
+
+ delete textureBufferStack.at(currentTextureBuffer).fbo;
+ textureBufferStack[currentTextureBuffer] =
+ createTextureBuffer(sz, textureBufferStack.at(currentTextureBuffer).engine);
+ qDebug() << "Creating new pixmap texture buffer:" << sz;
+ }
+ }
+ if (textureBufferStack.at(currentTextureBuffer).fbo->isValid()) {
+ m_renderFbo = textureBufferStack.at(currentTextureBuffer).fbo;
+ m_engine = textureBufferStack.at(currentTextureBuffer).engine;
+
+ ++currentTextureBuffer;
+
+ return m_engine;
+ }
+
+ qWarning() << "Failed to create pixmap texture buffer of size " << size() << ", falling back to raster paint engine";
+ }
+
+ m_dirty = true;
+ if (m_source.size() != size())
+ m_source = QImage(size(), QImage::Format_ARGB32_Premultiplied);
+ if (m_hasFillColor) {
+ m_source.fill(PREMUL(m_fillColor.rgba()));
+ m_hasFillColor = false;
+ }
return m_source.paintEngine();
}
-GLuint QGLPixmapData::bind() const
+GLuint QGLPixmapData::bind(bool copyBack) const
{
- ensureCreated();
- glBindTexture(qt_gl_preferredTextureTarget(), m_texture);
- return m_texture;
+ if (m_renderFbo && copyBack) {
+ copyBackFromRenderFbo(true);
+ } else {
+ if (m_hasFillColor) {
+ m_dirty = true;
+ m_source = QImage(m_width, m_height, QImage::Format_ARGB32_Premultiplied);
+ m_source.fill(PREMUL(m_fillColor.rgba()));
+ m_hasFillColor = false;
+ }
+ ensureCreated();
+ }
+
+ GLuint id = m_textureId;
+ glBindTexture(GL_TEXTURE_2D, id);
+ return id;
}
GLuint QGLPixmapData::textureId() const
{
ensureCreated();
- return m_texture;
+ return m_textureId;
}
extern int qt_defaultDpiX();
@@ -285,6 +489,9 @@ extern int qt_defaultDpiY();
int QGLPixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
{
+ if (m_width == 0)
+ return 0;
+
switch (metric) {
case QPaintDevice::PdmWidth:
return m_width;
diff --git a/src/opengl/qpixmapdata_gl_p.h b/src/opengl/qpixmapdata_gl_p.h
index 63703fd..af10f2c 100644
--- a/src/opengl/qpixmapdata_gl_p.h
+++ b/src/opengl/qpixmapdata_gl_p.h
@@ -60,6 +60,7 @@
QT_BEGIN_NAMESPACE
class QPaintEngine;
+class QGLFramebufferObject;
class QGLPixmapData : public QPixmapData
{
@@ -72,19 +73,37 @@ public:
void resize(int width, int height);
void fromImage(const QImage &image,
Qt::ImageConversionFlags flags);
+ void copy(const QPixmapData *data, const QRect &rect);
+
+ bool scroll(int dx, int dy, const QRect &rect);
void fill(const QColor &color);
bool hasAlphaChannel() const;
QImage toImage() const;
QPaintEngine* paintEngine() const;
- GLuint bind() const;
+ GLuint bind(bool copyBack = true) const;
GLuint textureId() const;
bool isValidContext(const QGLContext *ctx) const;
void ensureCreated() const;
+ bool isUninitialized() const { return m_dirty && m_source.isNull(); }
+
+ bool needsFill() const { return m_hasFillColor; }
+ QColor fillColor() const { return m_fillColor; }
+
+ QSize size() const { return QSize(m_width, m_height); }
+ int width() const { return m_width; }
+ int height() const { return m_height; }
+
+ QGLFramebufferObject *fbo() const;
+
+ void makeCurrent();
+ void doneCurrent();
+ void swapBuffers();
+
protected:
int metric(QPaintDevice::PaintDeviceMetric metric) const;
@@ -92,12 +111,30 @@ private:
QGLPixmapData(const QGLPixmapData &other);
QGLPixmapData &operator=(const QGLPixmapData &other);
+ void copyBackFromRenderFbo(bool keepCurrentFboBound) const;
+
+ static bool useFramebufferObjects();
+
+ QImage fillImage(const QColor &color) const;
+
int m_width;
int m_height;
- mutable GLuint m_texture;
- mutable bool m_dirty;
+ mutable QGLFramebufferObject *m_renderFbo;
+ mutable GLuint m_textureId;
+ mutable QPaintEngine *m_engine;
+ mutable QGLContext *m_ctx;
mutable QImage m_source;
+
+ // the texture is not in sync with the source image
+ mutable bool m_dirty;
+
+ // fill has been called and no painting has been done, so the pixmap is
+ // represented by a single fill color
+ mutable QColor m_fillColor;
+ mutable bool m_hasFillColor;
+
+ mutable bool m_hasAlpha;
};
QT_END_NAMESPACE
diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp
index b41adf9..01974a2 100644
--- a/src/opengl/qwindowsurface_gl.cpp
+++ b/src/opengl/qwindowsurface_gl.cpp
@@ -69,7 +69,8 @@
#include <private/qglpixelbuffer_p.h>
#include <private/qgraphicssystem_gl_p.h>
-#include <private/qpaintengine_opengl_p.h>
+
+#include <private/qpaintengineex_opengl2_p.h>
#ifndef GLX_ARB_multisample
#define GLX_SAMPLE_BUFFERS_ARB 100000
@@ -100,17 +101,19 @@ QGLGraphicsSystem::QGLGraphicsSystem()
int i = 0;
int spec[16];
spec[i++] = GLX_RGBA;
-#if 0
spec[i++] = GLX_DOUBLEBUFFER;
- spec[i++] = GLX_DEPTH_SIZE;
- spec[i++] = 8;
- spec[i++] = GLX_STENCIL_SIZE;
- spec[i++] = 8;
- spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
- spec[i++] = 1;
- spec[i++] = GLX_SAMPLES_ARB;
- spec[i++] = 4;
-#endif
+
+ if (!qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull()) {
+ spec[i++] = GLX_DEPTH_SIZE;
+ spec[i++] = 8;
+ spec[i++] = GLX_STENCIL_SIZE;
+ spec[i++] = 8;
+ spec[i++] = GLX_SAMPLE_BUFFERS_ARB;
+ spec[i++] = 1;
+ spec[i++] = GLX_SAMPLES_ARB;
+ spec[i++] = 4;
+ }
+
spec[i++] = XNone;
XVisualInfo *vi = glXChooseVisual(X11->display, X11->defaultScreen, spec);
@@ -187,9 +190,10 @@ public:
}
void cleanup() {
- delete widget;
- widget = 0;
+ QGLWidget *w = widget;
cleanedUp = true;
+ widget = 0;
+ delete w;
}
static bool cleanedUp;
@@ -227,6 +231,7 @@ struct QGLWindowSurfacePrivate
int tried_fbo : 1;
int tried_pb : 1;
+ int destructive_swap_buffers : 1;
QGLContext *ctx;
@@ -250,6 +255,7 @@ QGLWindowSurface::QGLWindowSurface(QWidget *window)
d_ptr->ctx = 0;
d_ptr->tried_fbo = false;
d_ptr->tried_pb = false;
+ d_ptr->destructive_swap_buffers = qgetenv("QT_GL_SWAPBUFFER_PRESERVE").isNull();
}
QGLWindowSurface::~QGLWindowSurface()
@@ -266,6 +272,24 @@ QGLWindowSurface::~QGLWindowSurface()
delete d_ptr;
}
+void QGLWindowSurface::deleted(QObject *object)
+{
+ QWidget *widget = qobject_cast<QWidget *>(object);
+ if (widget) {
+ QWidgetPrivate *widgetPrivate = widget->d_func();
+ if (widgetPrivate->extraData()) {
+ union { QGLContext **ctxPtr; void **voidPtr; };
+ voidPtr = &widgetPrivate->extraData()->glContext;
+ int index = d_ptr->contexts.indexOf(ctxPtr);
+ if (index != -1) {
+ delete *ctxPtr;
+ *ctxPtr = 0;
+ d_ptr->contexts.removeAt(index);
+ }
+ }
+ }
+}
+
void QGLWindowSurface::hijackWindow(QWidget *widget)
{
QWidgetPrivate *widgetPrivate = widget->d_func();
@@ -282,23 +306,19 @@ void QGLWindowSurface::hijackWindow(QWidget *widget)
union { QGLContext **ctxPtr; void **voidPtr; };
+ connect(widget, SIGNAL(destroyed(QObject *)), this, SLOT(deleted(QObject *)));
+
voidPtr = &widgetPrivate->extraData()->glContext;
d_ptr->contexts << ctxPtr;
qDebug() << "hijackWindow() context created for" << widget << d_ptr->contexts.size();
}
-#if !defined(QT_OPENGL_ES_2)
-Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_gl_window_surface_paintengine)
-#endif
+Q_GLOBAL_STATIC(QGL2PaintEngineEx, qt_gl_window_surface_2_engine)
/*! \reimp */
QPaintEngine *QGLWindowSurface::paintEngine() const
{
-#if !defined(QT_OPENGL_ES_2)
- return qt_gl_window_surface_paintengine();
-#else
- return 0;
-#endif
+ return qt_gl_window_surface_2_engine();
}
int QGLWindowSurface::metric(PaintDeviceMetric m) const
@@ -313,6 +333,8 @@ QGLContext *QGLWindowSurface::context() const
QPaintDevice *QGLWindowSurface::paintDevice()
{
+ updateGeometry();
+
if (d_ptr->pb)
return d_ptr->pb;
@@ -328,6 +350,7 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize,
void QGLWindowSurface::beginPaint(const QRegion &)
{
+ updateGeometry();
}
void QGLWindowSurface::endPaint(const QRegion &rgn)
@@ -343,6 +366,9 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget();
Q_ASSERT(parent);
+ if (!geometry().isValid())
+ return;
+
hijackWindow(parent);
QRect br = rgn.boundingRect().translated(offset);
@@ -350,53 +376,57 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
QPoint wOffset = qt_qwidget_data(parent)->wrect.topLeft();
QRect rect = br.translated(-offset - wOffset);
- const GLenum target = qt_gl_preferredTextureTarget();
+ const GLenum target = GL_TEXTURE_2D;
if (context()) {
context()->makeCurrent();
if (context()->format().doubleBuffer()) {
- glBindTexture(target, d_ptr->tex_id);
+#if !defined(QT_OPENGL_ES_2)
+ if (d_ptr->destructive_swap_buffers) {
+ glBindTexture(target, d_ptr->tex_id);
- QVector<QRect> rects = d_ptr->paintedRegion.rects();
- for (int i = 0; i < rects.size(); ++i) {
- QRect br = rects.at(i);
- if (br.isEmpty())
- continue;
+ QVector<QRect> rects = d_ptr->paintedRegion.rects();
+ for (int i = 0; i < rects.size(); ++i) {
+ QRect br = rects.at(i);
+ if (br.isEmpty())
+ continue;
- const uint bottom = window()->height() - (br.y() + br.height());
- glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
- }
+ const uint bottom = window()->height() - (br.y() + br.height());
+ glCopyTexSubImage2D(target, 0, br.x(), bottom, br.x(), bottom, br.width(), br.height());
+ }
- glBindTexture(target, 0);
+ glBindTexture(target, 0);
- QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion;
+ QRegion dirtyRegion = QRegion(window()->rect()) - d_ptr->paintedRegion;
- if (!dirtyRegion.isEmpty()) {
- context()->makeCurrent();
+ if (!dirtyRegion.isEmpty()) {
+ context()->makeCurrent();
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
#ifndef QT_OPENGL_ES
- glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999);
+ glOrtho(0, window()->width(), window()->height(), 0, -999999, 999999);
#else
- glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999);
+ glOrthof(0, window()->width(), window()->height(), 0, -999999, 999999);
#endif
- glViewport(0, 0, window()->width(), window()->height());
+ glViewport(0, 0, window()->width(), window()->height());
- QVector<QRect> rects = dirtyRegion.rects();
- glColor4f(1, 1, 1, 1);
- for (int i = 0; i < rects.size(); ++i) {
- QRect rect = rects.at(i);
- if (rect.isEmpty())
- continue;
+ QVector<QRect> rects = dirtyRegion.rects();
+ glColor4f(1, 1, 1, 1);
+ for (int i = 0; i < rects.size(); ++i) {
+ QRect rect = rects.at(i);
+ if (rect.isEmpty())
+ continue;
- drawTexture(rect, d_ptr->tex_id, window()->size(), rect);
+ drawTexture(rect, d_ptr->tex_id, window()->size(), rect);
+ }
}
}
+#endif
d_ptr->paintedRegion = QRegion();
context()->swapBuffers();
@@ -421,48 +451,75 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint &
}
QSize size = widget->rect().size();
- if (ctx->format().doubleBuffer()) {
+ if (d_ptr->destructive_swap_buffers && ctx->format().doubleBuffer()) {
rect = parent->rect();
br = rect.translated(wOffset);
size = parent->size();
}
- ctx->makeCurrent();
+ glDisable(GL_SCISSOR_TEST);
+
+ if (d_ptr->fbo && QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit) {
+ const int h = d_ptr->fbo->height();
+
+ const int x0 = rect.left();
+ const int x1 = rect.left() + rect.width();
+ const int y0 = h - (rect.top() + rect.height());
+ const int y1 = h - rect.top();
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, 0);
+
+ glBlitFramebufferEXT(x0, y0, x1, y1,
+ x0, y0, x1, y1,
+ GL_COLOR_BUFFER_BIT,
+ GL_NEAREST);
+
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER_EXT, d_ptr->fbo->handle());
+ }
+#if !defined(QT_OPENGL_ES_2)
+ else {
+ glDisable(GL_DEPTH_TEST);
+
+ if (d_ptr->fbo) {
+ d_ptr->fbo->release();
+ } else {
+ ctx->makeCurrent();
#ifdef Q_WS_MAC
- ctx->updatePaintDevice();
+ ctx->updatePaintDevice();
#endif
- if (d_ptr->fbo)
- d_ptr->fbo->release();
+ }
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
#ifndef QT_OPENGL_ES
- glOrtho(0, size.width(), size.height(), 0, -999999, 999999);
+ glOrtho(0, size.width(), size.height(), 0, -999999, 999999);
#else
- glOrthof(0, size.width(), size.height(), 0, -999999, 999999);
+ glOrthof(0, size.width(), size.height(), 0, -999999, 999999);
#endif
- glViewport(0, 0, size.width(), size.height());
+ glViewport(0, 0, size.width(), size.height());
- glColor4f(1, 1, 1, 1);
- drawTexture(rect, texture, window()->size(), br);
+ glColor4f(1, 1, 1, 1);
+ drawTexture(rect, texture, window()->size(), br);
+
+ if (d_ptr->fbo)
+ d_ptr->fbo->bind();
+ }
+#endif
if (ctx->format().doubleBuffer())
ctx->swapBuffers();
else
glFlush();
-
- if (d_ptr->fbo)
- d_ptr->fbo->bind();
}
-void QGLWindowSurface::setGeometry(const QRect &rect)
+void QGLWindowSurface::updateGeometry()
{
- QWindowSurface::setGeometry(rect);
+ QRect rect = QWindowSurface::geometry();
- const GLenum target = qt_gl_preferredTextureTarget();
+ const GLenum target = GL_TEXTURE_2D;
if (rect.width() <= 0 || rect.height() <= 0)
return;
@@ -473,13 +530,51 @@ void QGLWindowSurface::setGeometry(const QRect &rect)
d_ptr->size = rect.size();
if (d_ptr->ctx) {
- glBindTexture(target, d_ptr->tex_id);
- glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- glBindTexture(target, 0);
+ if (d_ptr->destructive_swap_buffers) {
+ glBindTexture(target, d_ptr->tex_id);
+ glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ glBindTexture(target, 0);
+ }
return;
}
- if (d_ptr->pb || !d_ptr->tried_pb) {
+ if (d_ptr->destructive_swap_buffers
+ && (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject)
+#ifdef QT_OPENGL_ES_2
+ && (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
+#endif
+ && (d_ptr->fbo || !d_ptr->tried_fbo))
+ {
+ d_ptr->tried_fbo = true;
+ hijackWindow(window());
+ QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
+ ctx->d_ptr->internal_context = true;
+ ctx->makeCurrent();
+ delete d_ptr->fbo;
+
+ QGLFramebufferObjectFormat format;
+ format.setAttachment(QGLFramebufferObject::CombinedDepthStencil);
+ format.setInternalFormat(GL_RGBA);
+ format.setTextureTarget(target);
+
+ if (QGLExtensions::glExtensions & QGLExtensions::FramebufferBlit)
+ format.setSamples(8);
+
+ d_ptr->fbo = new QGLFramebufferObject(rect.size(), format);
+ d_ptr->fbo->bind();
+ if (d_ptr->fbo->isValid()) {
+ qDebug() << "Created Window Surface FBO" << rect.size()
+ << "with samples" << d_ptr->fbo->format().samples();
+ return;
+ } else {
+ qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back";
+ delete d_ptr->fbo;
+ d_ptr->fbo = 0;
+ }
+ }
+
+#if !defined(QT_OPENGL_ES_2)
+ if (d_ptr->destructive_swap_buffers && (d_ptr->pb || !d_ptr->tried_pb)) {
d_ptr->tried_pb = true;
if (d_ptr->pb) {
@@ -494,7 +589,7 @@ void QGLWindowSurface::setGeometry(const QRect &rect)
qt_gl_share_widget());
if (d_ptr->pb->isValid()) {
- qDebug() << "PB Sample buffers:" << d_ptr->pb->format().sampleBuffers();
+ qDebug() << "Created Window Surface Pixelbuffer, Sample buffers:" << d_ptr->pb->format().sampleBuffers();
d_ptr->pb->makeCurrent();
glGenTextures(1, &d_ptr->pb_tex_id);
@@ -521,44 +616,32 @@ void QGLWindowSurface::setGeometry(const QRect &rect)
d_ptr->pb = 0;
}
}
-
- if ((QGLExtensions::glExtensions & QGLExtensions::FramebufferObject) && (d_ptr->fbo || !d_ptr->tried_fbo)) {
- d_ptr->tried_fbo = true;
- hijackWindow(window());
- QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
- ctx->d_ptr->internal_context = true;
- ctx->makeCurrent();
- delete d_ptr->fbo;
- d_ptr->fbo = new QGLFramebufferObject(rect.size(), QGLFramebufferObject::CombinedDepthStencil,
- GLenum(target), GLenum(GL_RGBA));
-
- d_ptr->fbo->bind();
- if (d_ptr->fbo->isValid()) {
- return;
- } else {
- qDebug() << "QGLWindowSurface: Failed to create valid FBO, falling back";
- delete d_ptr->fbo;
- d_ptr->fbo = 0;
- }
- }
+#endif // !defined(QT_OPENGL_ES_2)
hijackWindow(window());
QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext);
ctx->makeCurrent();
- glGenTextures(1, &d_ptr->tex_id);
- glBindTexture(target, d_ptr->tex_id);
- glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
+ if (d_ptr->destructive_swap_buffers) {
+ glGenTextures(1, &d_ptr->tex_id);
+ glBindTexture(target, d_ptr->tex_id);
+ glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
- glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
- glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
- glBindTexture(target, 0);
+ glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glBindTexture(target, 0);
+ }
qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;;
d_ptr->ctx = ctx;
d_ptr->ctx->d_ptr->internal_context = true;
}
+void QGLWindowSurface::setGeometry(const QRect &rect)
+{
+ QWindowSurface::setGeometry(rect);
+}
+
bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy)
{
// this code randomly fails currently for unknown reasons
@@ -582,7 +665,7 @@ bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy)
return true;
#endif
- const GLenum target = qt_gl_preferredTextureTarget();
+ const GLenum target = GL_TEXTURE_2D;
glBindTexture(target, d_ptr->tex_id);
glCopyTexImage2D(target, 0, GL_RGBA, br.x(), d_ptr->pb->height() - (br.y() + br.height()), br.width(), br.height(), 0);
@@ -595,7 +678,7 @@ bool QGLWindowSurface::scroll(const QRegion &area, int dx, int dy)
static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br)
{
- const GLenum target = qt_gl_preferredTextureTarget();
+ const GLenum target = GL_TEXTURE_2D;
QRectF src = br.isEmpty()
? QRectF(QPointF(), texSize)
: QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size());
@@ -623,6 +706,7 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize,
extern void qt_add_rect_to_array(const QRectF &r, q_vertexType *array); // qpaintengine_opengl.cpp
qt_add_rect_to_array(rect, vertexArray);
+#if !defined(QT_OPENGL_ES_2)
glVertexPointer(2, q_vertexTypeEnum, 0, vertexArray);
glTexCoordPointer(2, q_vertexTypeEnum, 0, texCoordArray);
@@ -634,6 +718,7 @@ static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize,
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+#endif
glDisable(target);
glBindTexture(target, 0);
diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h
index 0194378..9efd1ae 100644
--- a/src/opengl/qwindowsurface_gl_p.h
+++ b/src/opengl/qwindowsurface_gl_p.h
@@ -65,8 +65,9 @@ class QRegion;
class QWidget;
struct QGLWindowSurfacePrivate;
-class QGLWindowSurface : public QWindowSurface, public QPaintDevice
+class QGLWindowSurface : public QObject, public QWindowSurface, public QPaintDevice
{
+ Q_OBJECT
public:
QGLWindowSurface(QWidget *window);
~QGLWindowSurface();
@@ -74,6 +75,7 @@ public:
QPaintDevice *paintDevice();
void flush(QWidget *widget, const QRegion &region, const QPoint &offset);
void setGeometry(const QRect &rect);
+ void updateGeometry();
bool scroll(const QRegion &area, int dx, int dy);
void beginPaint(const QRegion &region);
@@ -90,6 +92,9 @@ public:
protected:
int metric(PaintDeviceMetric metric) const;
+private slots:
+ void deleted(QObject *object);
+
private:
void hijackWindow(QWidget *widget);
diff --git a/src/opengl/util/fragmentprograms_p.h b/src/opengl/util/fragmentprograms_p.h
index ecf0bf8..d4b54d4 100644
--- a/src/opengl/util/fragmentprograms_p.h
+++ b/src/opengl/util/fragmentprograms_p.h
@@ -71,7 +71,7 @@ enum FragmentVariable {
VAR_FMP2_M_RADIUS2,
VAR_FMP,
VAR_INV_MATRIX_M0,
- VAR_ANGLE,
+ VAR_ANGLE
};
enum FragmentBrushType {
@@ -80,7 +80,7 @@ enum FragmentBrushType {
FRAGMENT_PROGRAM_BRUSH_CONICAL,
FRAGMENT_PROGRAM_BRUSH_LINEAR,
FRAGMENT_PROGRAM_BRUSH_TEXTURE,
- FRAGMENT_PROGRAM_BRUSH_PATTERN,
+ FRAGMENT_PROGRAM_BRUSH_PATTERN
};
enum FragmentCompositionModeType {
@@ -109,12 +109,12 @@ enum FragmentCompositionModeType {
COMPOSITION_MODES_DIFFERENCE_NOMASK,
COMPOSITION_MODES_EXCLUSION_NOMASK,
COMPOSITION_MODE_BLEND_MODE_MASK,
- COMPOSITION_MODE_BLEND_MODE_NOMASK,
+ COMPOSITION_MODE_BLEND_MODE_NOMASK
};
enum FragmentMaskType {
FRAGMENT_PROGRAM_MASK_TRAPEZOID_AA,
- FRAGMENT_PROGRAM_MASK_ELLIPSE_AA,
+ FRAGMENT_PROGRAM_MASK_ELLIPSE_AA
};
static const unsigned int num_fragment_variables = 19;
diff --git a/src/opengl/util/generator.cpp b/src/opengl/util/generator.cpp
index de2450d..430ced1 100644
--- a/src/opengl/util/generator.cpp
+++ b/src/opengl/util/generator.cpp
@@ -48,6 +48,7 @@
#include <QTextStream>
#include <QtDebug>
+#include <cstdlib>
QT_BEGIN_NAMESPACE
@@ -116,7 +117,7 @@ QList<QStringPair> readConf(const QString &confFile)
lineStream >> enumerator;
if (lineStream.atEnd()) {
- qDebug() << "Error in file" << confFile << "(" << enumerator << ")";
+ qDebug() << "Error in file" << confFile << '(' << enumerator << ')';
exit(0);
}
diff --git a/src/phonon/phonon.pro b/src/phonon/phonon.pro
index 221304d..0469839 100644
--- a/src/phonon/phonon.pro
+++ b/src/phonon/phonon.pro
@@ -1,5 +1,5 @@
TARGET = phonon
-include($$QT_SOURCE_TREE/src/qbase.pri)
+include(../qbase.pri)
PHONON_MAJOR_VERSION = $${QT_MAJOR_VERSION}
PHONON_MINOR_VERSION = 3
diff --git a/src/plugins/accessible/widgets/rangecontrols.cpp b/src/plugins/accessible/widgets/rangecontrols.cpp
index 9297d6e..6d8c184 100644
--- a/src/plugins/accessible/widgets/rangecontrols.cpp
+++ b/src/plugins/accessible/widgets/rangecontrols.cpp
@@ -799,7 +799,7 @@ int QAccessibleSlider::defaultAction(int /*child*/) const
/*! \internal */
QString QAccessibleSlider::actionText(int /*action*/, Text /*t*/, int /*child*/) const
{
- return QString(QLatin1String(""));
+ return QLatin1String("");
}
QAccessibleAbstractSlider::QAccessibleAbstractSlider(QWidget *w, Role r)
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
index 2fb533a..5be4d47 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
@@ -532,7 +532,9 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image,
d->prepareForBlit(QDirectFBScreen::hasAlpha(imgSurface));
d->blit(r, imgSurface, sr);
if (release) {
+#if (Q_DIRECTFB_VERSION >= 0x010000)
imgSurface->ReleaseSource(imgSurface);
+#endif
imgSurface->Release(imgSurface);
}
#endif
@@ -897,7 +899,9 @@ void QDirectFBPaintEnginePrivate::end()
{
lockedMemory = 0;
dfbDevice = 0;
+#if (Q_DIRECTFB_VERSION >= 0x010000)
surface->ReleaseSource(surface);
+#endif
surface->SetClip(surface, NULL);
surface = 0;
}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index 18754f5..8184073 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -225,7 +225,9 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
const DFBRectangle blitRect = { rect.x(), rect.y(),
rect.width(), rect.height() };
DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
+#if (Q_DIRECTFB_VERSION >= 0x010000)
dfbSurface->ReleaseSource(dfbSurface);
+#endif
if (result != DFB_OK) {
DirectFBError("QDirectFBPixmapData::copy()", result);
invalidate();
@@ -316,8 +318,9 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
const DFBRectangle destRect = { 0, 0, size.width(), size.height() };
data->dfbSurface->StretchBlit(data->dfbSurface, dfbSurface, 0, &destRect);
+#if (Q_DIRECTFB_VERSION >= 0x010000)
data->dfbSurface->ReleaseSource(data->dfbSurface);
-
+#endif
return QPixmap(data);
}
@@ -336,7 +339,9 @@ QImage QDirectFBPixmapData::toImage() const
imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX);
}
imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0);
+#if (Q_DIRECTFB_VERSION >= 0x010000)
imgSurface->ReleaseSource(imgSurface);
+#endif
imgSurface->Release(imgSurface);
return ret;
}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 9e35a66..f694ed9 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -196,7 +196,9 @@ IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src,
surface->SetBlittingFlags(surface, flags);
surface->Blit(surface, src, 0, 0, 0);
+#if (Q_DIRECTFB_VERSION >= 0x010000)
surface->ReleaseSource(surface);
+#endif
return surface;
}
@@ -317,7 +319,9 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img,
DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0);
if (result != DFB_OK)
DirectFBError("QDirectFBScreen::copyToDFBSurface()", result);
+#if (Q_DIRECTFB_VERSION >= 0x010000)
dfbSurface->ReleaseSource(dfbSurface);
+#endif
imgSurface->Release(imgSurface);
#else // QT_NO_DIRECTFB_PREALLOCATED
Q_ASSERT(image.format() == pixmapFormat);
@@ -388,10 +392,12 @@ DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format form
#endif
case QImage::Format_RGB16:
return DSPF_RGB16;
+#if (Q_DIRECTFB_VERSION >= 0x010000)
case QImage::Format_ARGB6666_Premultiplied:
return DSPF_ARGB6666;
case QImage::Format_RGB666:
return DSPF_RGB18;
+#endif
case QImage::Format_RGB32:
return DSPF_RGB32;
case QImage::Format_ARGB32_Premultiplied:
@@ -423,10 +429,12 @@ QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface)
return QImage::Format_RGB555;
case DSPF_RGB16:
return QImage::Format_RGB16;
+#if (Q_DIRECTFB_VERSION >= 0x010000)
case DSPF_ARGB6666:
return QImage::Format_ARGB6666_Premultiplied;
case DSPF_RGB18:
return QImage::Format_RGB666;
+#endif
case DSPF_RGB32:
return QImage::Format_RGB32;
case DSPF_ARGB: {
@@ -778,9 +786,13 @@ static const FlagDescription blitDescriptions[] = {
{ " DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY },
{ " DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY },
{ " DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE },
+#if (Q_DIRECTFB_VERSION >= 0x000923)
{ " DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR },
{ " DSBLIT_XOR", DSBLIT_XOR },
+#endif
+#if (Q_DIRECTFB_VERSION >= 0x010000)
{ " DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION },
+#endif
{ 0, 0 }
};
@@ -798,6 +810,7 @@ static const FlagDescription drawDescriptions[] = {
+#if (Q_DIRECTFB_VERSION >= 0x000923)
static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags)
{
#ifdef QT_NO_DEBUG
@@ -818,9 +831,6 @@ static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags
return (QLatin1Char(' ') + list.join(QLatin1String("|"))).toLatin1();
#endif
}
-
-
-
static void printDirectFBInfo(IDirectFB *fb, IDirectFBSurface *primarySurface)
{
DFBResult result;
@@ -845,6 +855,7 @@ static void printDirectFBInfo(IDirectFB *fb, IDirectFBSurface *primarySurface)
dev.drawing_flags, ::flagDescriptions(dev.drawing_flags, drawDescriptions).constData(),
(dev.video_memory >> 10));
}
+#endif
static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value)
{
@@ -1039,8 +1050,10 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
setGraphicsSystem(d_ptr);
+#if (Q_DIRECTFB_VERSION >= 0x000923)
if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive))
printDirectFBInfo(d_ptr->dfb, d_ptr->dfbSurface);
+#endif
return true;
}
@@ -1223,7 +1236,9 @@ void QDirectFBScreen::compose(const QRegion &region)
blit(surface->image(), offset, r);
}
}
+#if (Q_DIRECTFB_VERSION >= 0x010000)
d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface);
+#endif
}
// Normally, when using DirectFB to compose the windows (I.e. when
@@ -1271,7 +1286,9 @@ void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft,
return;
}
blit(src, topLeft, reg);
+#if (Q_DIRECTFB_VERSION >= 0x010000)
d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface);
+#endif
src->Release(src);
}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
index 84199a2..c105590 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
@@ -177,11 +177,15 @@ inline bool QDirectFBScreen::hasAlpha(DFBSurfacePixelFormat format)
case DSPF_A1:
case DSPF_ARGB2554:
case DSPF_ARGB4444:
+#if (Q_DIRECTFB_VERSION >= 0x000923)
case DSPF_AYUV:
+#endif
+#if (Q_DIRECTFB_VERSION >= 0x010000)
case DSPF_A4:
case DSPF_ARGB1666:
case DSPF_ARGB6666:
case DSPF_LUT2:
+#endif
return true;
default:
return false;
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
index 330eb88..442f8dd 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
@@ -188,14 +188,25 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask)
if (!dfbWindow)
createWindow();
- if (isResize && isMove)
+#if (Q_DIRECTFB_VERSION >= 0x010000)
+ if (isResize && isMove) {
result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(),
rect.width(), rect.height());
- else if (isResize)
+ } else if (isResize) {
result = dfbWindow->Resize(dfbWindow,
rect.width(), rect.height());
- else if (isMove)
+ } else if (isMove) {
result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
+ }
+#else
+ if (isResize) {
+ result = dfbWindow->Resize(dfbWindow,
+ rect.width(), rect.height());
+ }
+ if (isMove) {
+ result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y());
+ }
+#endif
#endif
}
diff --git a/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp b/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp
index 3a40b4c..da61a22 100644
--- a/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp
+++ b/src/plugins/gfxdrivers/hybrid/hybridscreen.cpp
@@ -103,11 +103,11 @@ bool HybridScreen::connect(const QString &displaySpec)
{
QString dspec = displaySpec;
if (dspec.startsWith(QLatin1String("hybrid:"), Qt::CaseInsensitive))
- dspec = dspec.mid(QString(QLatin1String("hybrid:")).size());
+ dspec = dspec.mid(QString::fromLatin1("hybrid:").size());
else if (dspec.compare(QLatin1String("hybrid"), Qt::CaseInsensitive) == 0)
dspec = QString();
- const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
if (dspec.endsWith(displayIdSpec))
dspec = dspec.left(dspec.size() - displayIdSpec.size());
diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
index b0ffbf1..65efdbc 100644
--- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
+++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.cpp
@@ -104,7 +104,7 @@ bool PvrEglScreen::connect(const QString &displaySpec)
break;
case PVR2D_ARGB8888:
d = 32;
- setPixelFormat(QImage::Format_ARGB32);
+ setPixelFormat(QImage::Format_ARGB32_Premultiplied);
break;
default:
pvrQwsDisplayClose();
diff --git a/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp b/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp
index b7f03ba..8be3672 100644
--- a/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp
+++ b/src/plugins/gfxdrivers/vnc/qscreenvnc_qws.cpp
@@ -2100,11 +2100,11 @@ bool QVNCScreen::connect(const QString &displaySpec)
{
QString dspec = displaySpec;
if (dspec.startsWith(QLatin1String("vnc:"), Qt::CaseInsensitive))
- dspec = dspec.mid(QString(QLatin1String("vnc:")).size());
+ dspec = dspec.mid(QString::fromLatin1("vnc:").size());
else if (dspec.compare(QLatin1String("vnc"), Qt::CaseInsensitive) == 0)
dspec = QString();
- const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
if (dspec.endsWith(displayIdSpec))
dspec = dspec.left(dspec.size() - displayIdSpec.size());
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index 299190b..da5ae15 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -57,38 +57,38 @@
// in an ICO file.
typedef struct
{
- quint8 bWidth; // Width of the image
- quint8 bHeight; // Height of the image (times 2)
- quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ]
- quint8 bReserved; // Reserved
- quint16 wPlanes; // Color Planes
- quint16 wBitCount; // Bits per pixel
- quint32 dwBytesInRes; // how many bytes in this resource?
- quint32 dwImageOffset; // where in the file is this image
+ quint8 bWidth; // Width of the image
+ quint8 bHeight; // Height of the image (times 2)
+ quint8 bColorCount; // Number of colors in image (0 if >=8bpp) [ not ture ]
+ quint8 bReserved; // Reserved
+ quint16 wPlanes; // Color Planes
+ quint16 wBitCount; // Bits per pixel
+ quint32 dwBytesInRes; // how many bytes in this resource?
+ quint32 dwImageOffset; // where in the file is this image
} ICONDIRENTRY, *LPICONDIRENTRY;
#define ICONDIRENTRY_SIZE 16
typedef struct
{
- quint16 idReserved; // Reserved
- quint16 idType; // resource type (1 for icons)
- quint16 idCount; // how many images?
- ICONDIRENTRY idEntries[1]; // the entries for each image
+ quint16 idReserved; // Reserved
+ quint16 idType; // resource type (1 for icons)
+ quint16 idCount; // how many images?
+ ICONDIRENTRY idEntries[1]; // the entries for each image
} ICONDIR, *LPICONDIR;
#define ICONDIR_SIZE 6 // Exclude the idEntries field
-typedef struct { // BMP information header
- quint32 biSize; // size of this struct
- quint32 biWidth; // pixmap width
- quint32 biHeight; // pixmap height
- quint16 biPlanes; // should be 1
- quint16 biBitCount; // number of bits per pixel
- quint32 biCompression; // compression method
- quint32 biSizeImage; // size of image
- quint32 biXPelsPerMeter; // horizontal resolution
- quint32 biYPelsPerMeter; // vertical resolution
- quint32 biClrUsed; // number of colors used
- quint32 biClrImportant; // number of important colors
+typedef struct { // BMP information header
+ quint32 biSize; // size of this struct
+ quint32 biWidth; // pixmap width
+ quint32 biHeight; // pixmap height (specifies the combined height of the XOR and AND masks)
+ quint16 biPlanes; // should be 1
+ quint16 biBitCount; // number of bits per pixel
+ quint32 biCompression; // compression method
+ quint32 biSizeImage; // size of image
+ quint32 biXPelsPerMeter; // horizontal resolution
+ quint32 biYPelsPerMeter; // vertical resolution
+ quint32 biClrUsed; // number of colors used
+ quint32 biClrImportant; // number of important colors
} BMP_INFOHDR ,*LPBMP_INFOHDR;
#define BMP_INFOHDR_SIZE 40
@@ -108,7 +108,7 @@ private:
bool readHeader();
bool readIconEntry(int index, ICONDIRENTRY * iconEntry);
- bool readBMPHeader(ICONDIRENTRY & iconEntry, BMP_INFOHDR * header);
+ bool readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header);
void findColorInfo(QImage & image);
void readColorTable(QImage & image);
@@ -254,7 +254,7 @@ ICOReader::ICOReader(QIODevice * iodevice)
int ICOReader::count()
{
if (readHeader())
- return iconDir.idCount;
+ return iconDir.idCount;
return 0;
}
@@ -268,17 +268,17 @@ bool ICOReader::canRead(QIODevice *iodev)
if (readIconDir(iodev, &ikonDir)) {
qint64 readBytes = ICONDIR_SIZE;
if (readIconDirEntry(iodev, &ikonDir.idEntries[0])) {
- readBytes += ICONDIRENTRY_SIZE;
- // ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file.
- if ( ikonDir.idReserved == 0
- && ikonDir.idType == 1
- && ikonDir.idEntries[0].bReserved == 0
- && ikonDir.idEntries[0].wPlanes <= 1
- && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel
- && ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40
- ) {
- isProbablyICO = true;
- }
+ readBytes += ICONDIRENTRY_SIZE;
+ // ICO format does not have a magic identifier, so we read 6 different values, which will hopefully be enough to identify the file.
+ if ( ikonDir.idReserved == 0
+ && ikonDir.idType == 1
+ && ikonDir.idEntries[0].bReserved == 0
+ && ikonDir.idEntries[0].wPlanes <= 1
+ && ikonDir.idEntries[0].wBitCount <= 32 // Bits per pixel
+ && ikonDir.idEntries[0].dwBytesInRes >= 40 // Must be over 40, since sizeof (infoheader) == 40
+ ) {
+ isProbablyICO = true;
+ }
if (iodev->isSequential()) {
// Our structs might be padded due to alignment, so we need to fetch each member before we ungetChar() !
@@ -323,8 +323,7 @@ bool ICOReader::canRead(QIODevice *iodev)
iodev->ungetChar((tmp >> 8) & 0xff);
iodev->ungetChar(tmp & 0xff);
}
-
- }
+ }
if (!iodev->isSequential()) iodev->seek(oldPos);
}
@@ -334,21 +333,21 @@ bool ICOReader::canRead(QIODevice *iodev)
bool ICOReader::readHeader()
{
if (iod && !headerRead) {
- startpos = iod->pos();
- if (readIconDir(iod, &iconDir)) {
- if (iconDir.idReserved == 0 || iconDir.idType == 1)
- headerRead = true;
- }
+ startpos = iod->pos();
+ if (readIconDir(iod, &iconDir)) {
+ if (iconDir.idReserved == 0 || iconDir.idType == 1)
+ headerRead = true;
+ }
}
return headerRead;
}
-bool ICOReader::readIconEntry(int index, ICONDIRENTRY * iconEntry)
+bool ICOReader::readIconEntry(int index, ICONDIRENTRY *iconEntry)
{
if (iod) {
- if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) {
- return readIconDirEntry(iod, iconEntry);
+ if (iod->seek(startpos + ICONDIR_SIZE + (index * ICONDIRENTRY_SIZE))) {
+ return readIconDirEntry(iod, iconEntry);
}
}
return false;
@@ -356,49 +355,24 @@ bool ICOReader::readIconEntry(int index, ICONDIRENTRY * iconEntry)
-bool ICOReader::readBMPHeader(ICONDIRENTRY & iconEntry, BMP_INFOHDR * header)
+bool ICOReader::readBMPHeader(quint32 imageOffset, BMP_INFOHDR * header)
{
- memset(&icoAttrib, 0, sizeof(IcoAttrib));
if (iod) {
- if (iod->seek(startpos + iconEntry.dwImageOffset)) {
- if (readBMPInfoHeader(iod, header)) {
-
- icoAttrib.nbits = header->biBitCount ? header->biBitCount : iconEntry.wBitCount;
- icoAttrib.h = header->biHeight / 2; // this height is always double the iconEntry height (for the mask)
- icoAttrib.w = header->biWidth;
-
- switch (icoAttrib.nbits) {
- case 32:
- case 24:
- case 16:
- icoAttrib.depth = 32;
- break;
- case 8:
- case 4:
- icoAttrib.depth = 8;
- break;
- default:
- icoAttrib.depth = 1;
- }
-
- if ( icoAttrib.depth == 32 ) // there's no colormap
- icoAttrib.ncolors = 0;
- else // # colors used
- icoAttrib.ncolors = header->biClrUsed ? header->biClrUsed : 1 << icoAttrib.nbits;
- //qDebug() << "Bits:" << icoAttrib.nbits << "Depth:" << icoAttrib.depth << "Ncols:" << icoAttrib.ncolors;
- return TRUE;
- }
- }
+ if (iod->seek(startpos + imageOffset)) {
+ if (readBMPInfoHeader(iod, header)) {
+ return TRUE;
+ }
+ }
}
return FALSE;
}
void ICOReader::findColorInfo(QImage & image)
{
- if (icoAttrib.ncolors > 0) { // set color table
- readColorTable(image);
+ if (icoAttrib.ncolors > 0) { // set color table
+ readColorTable(image);
} else if (icoAttrib.nbits == 16) { // don't support RGB values for 15/16 bpp
- image = QImage();
+ image = QImage();
}
}
@@ -406,29 +380,29 @@ void ICOReader::readColorTable(QImage & image)
{
if (iod) {
image.setNumColors(icoAttrib.ncolors);
- uchar rgb[4];
- for (int i=0; i<icoAttrib.ncolors; i++) {
- if (iod->read((char*)rgb, 4) != 4) {
- image = QImage();
- break;
- }
- image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0]));
- }
+ uchar rgb[4];
+ for (int i=0; i<icoAttrib.ncolors; i++) {
+ if (iod->read((char*)rgb, 4) != 4) {
+ image = QImage();
+ break;
+ }
+ image.setColor(i, qRgb(rgb[2],rgb[1],rgb[0]));
+ }
} else {
- image = QImage();
+ image = QImage();
}
}
void ICOReader::readBMP(QImage & image)
{
- if (icoAttrib.nbits == 1) { // 1 bit BMP image
- read1BitBMP(image);
- } else if (icoAttrib.nbits == 4) { // 4 bit BMP image
- read4BitBMP(image);
+ if (icoAttrib.nbits == 1) { // 1 bit BMP image
+ read1BitBMP(image);
+ } else if (icoAttrib.nbits == 4) { // 4 bit BMP image
+ read4BitBMP(image);
} else if (icoAttrib.nbits == 8) {
- read8BitBMP(image);
+ read8BitBMP(image);
} else if (icoAttrib.nbits == 16 || icoAttrib.nbits == 24 || icoAttrib.nbits == 32 ) { // 16,24,32 bit BMP image
- read16_24_32BMP(image);
+ read16_24_32BMP(image);
}
}
@@ -442,17 +416,17 @@ void ICOReader::read1BitBMP(QImage & image)
{
if (iod) {
- int h = image.height();
- int bpl = image.bytesPerLine();
+ int h = image.height();
+ int bpl = image.bytesPerLine();
- while (--h >= 0) {
- if (iod->read((char*)image.scanLine(h),bpl) != bpl) {
- image = QImage();
- break;
- }
- }
+ while (--h >= 0) {
+ if (iod->read((char*)image.scanLine(h),bpl) != bpl) {
+ image = QImage();
+ break;
+ }
+ }
} else {
- image = QImage();
+ image = QImage();
}
}
@@ -460,30 +434,30 @@ void ICOReader::read4BitBMP(QImage & image)
{
if (iod) {
- int h = icoAttrib.h;
- int buflen = ((icoAttrib.w+7)/8)*4;
- uchar *buf = new uchar[buflen];
- Q_CHECK_PTR(buf);
-
- while (--h >= 0) {
- if (iod->read((char*)buf,buflen) != buflen) {
- image = QImage();
- break;
- }
- register uchar *p = image.scanLine(h);
- uchar *b = buf;
- for (int i=0; i<icoAttrib.w/2; i++) { // convert nibbles to bytes
- *p++ = *b >> 4;
- *p++ = *b++ & 0x0f;
- }
- if (icoAttrib.w & 1) // the last nibble
- *p = *b >> 4;
- }
-
- delete [] buf;
+ int h = icoAttrib.h;
+ int buflen = ((icoAttrib.w+7)/8)*4;
+ uchar *buf = new uchar[buflen];
+ Q_CHECK_PTR(buf);
+
+ while (--h >= 0) {
+ if (iod->read((char*)buf,buflen) != buflen) {
+ image = QImage();
+ break;
+ }
+ register uchar *p = image.scanLine(h);
+ uchar *b = buf;
+ for (int i=0; i<icoAttrib.w/2; i++) { // convert nibbles to bytes
+ *p++ = *b >> 4;
+ *p++ = *b++ & 0x0f;
+ }
+ if (icoAttrib.w & 1) // the last nibble
+ *p = *b >> 4;
+ }
+
+ delete [] buf;
} else {
- image = QImage();
+ image = QImage();
}
}
@@ -491,52 +465,51 @@ void ICOReader::read8BitBMP(QImage & image)
{
if (iod) {
- int h = icoAttrib.h;
- int bpl = image.bytesPerLine();
+ int h = icoAttrib.h;
+ int bpl = image.bytesPerLine();
- while (--h >= 0) {
- if (iod->read((char *)image.scanLine(h), bpl) != bpl) {
- image = QImage();
- break;
- }
- }
+ while (--h >= 0) {
+ if (iod->read((char *)image.scanLine(h), bpl) != bpl) {
+ image = QImage();
+ break;
+ }
+ }
} else {
- image = QImage();
+ image = QImage();
}
}
void ICOReader::read16_24_32BMP(QImage & image)
{
if (iod) {
-
- int h = icoAttrib.h;
- register QRgb *p;
- QRgb *end;
- uchar *buf = new uchar[image.bytesPerLine()];
- int bpl = ((icoAttrib.w*icoAttrib.nbits+31)/32)*4;
- uchar *b;
-
- while (--h >= 0) {
- p = (QRgb *)image.scanLine(h);
- end = p + icoAttrib.w;
- if (iod->read((char *)buf, bpl) != bpl) {
- image = QImage();
- break;
- }
- b = buf;
- while (p < end) {
+ int h = icoAttrib.h;
+ register QRgb *p;
+ QRgb *end;
+ uchar *buf = new uchar[image.bytesPerLine()];
+ int bpl = ((icoAttrib.w*icoAttrib.nbits+31)/32)*4;
+ uchar *b;
+
+ while (--h >= 0) {
+ p = (QRgb *)image.scanLine(h);
+ end = p + icoAttrib.w;
+ if (iod->read((char *)buf, bpl) != bpl) {
+ image = QImage();
+ break;
+ }
+ b = buf;
+ while (p < end) {
if (icoAttrib.nbits == 24)
*p++ = qRgb(*(b+2), *(b+1), *b);
else if (icoAttrib.nbits == 32)
*p++ = qRgba(*(b+2), *(b+1), *b, *(b+3));
- b += icoAttrib.nbits/8;
- }
- }
+ b += icoAttrib.nbits/8;
+ }
+ }
- delete[] buf;
+ delete[] buf;
} else {
- image = QImage();
+ image = QImage();
}
}
@@ -550,7 +523,28 @@ QImage ICOReader::iconAt(int index)
if (readIconEntry(index, &iconEntry)) {
BMP_INFOHDR header;
- if (readBMPHeader(iconEntry, &header)) {
+ if (readBMPHeader(iconEntry.dwImageOffset, &header)) {
+ icoAttrib.nbits = header.biBitCount ? header.biBitCount : iconEntry.wBitCount;
+
+ switch (icoAttrib.nbits) {
+ case 32:
+ case 24:
+ case 16:
+ icoAttrib.depth = 32;
+ break;
+ case 8:
+ case 4:
+ icoAttrib.depth = 8;
+ break;
+ default:
+ icoAttrib.depth = 1;
+ }
+ if (icoAttrib.depth == 32) // there's no colormap
+ icoAttrib.ncolors = 0;
+ else // # colors used
+ icoAttrib.ncolors = header.biClrUsed ? header.biClrUsed : 1 << icoAttrib.nbits;
+ icoAttrib.w = iconEntry.bWidth;
+ icoAttrib.h = iconEntry.bHeight;
QImage::Format format = QImage::Format_ARGB32;
if (icoAttrib.nbits == 24)
@@ -605,8 +599,8 @@ QList<QImage> ICOReader::read(QIODevice * device)
QList<QImage> images;
ICOReader reader(device);
- for (int i=0; i<reader.count(); i++)
- images += reader.iconAt(i);
+ for (int i = 0; i < reader.count(); i++)
+ images += reader.iconAt(i);
return images;
}
@@ -659,8 +653,8 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
}
maskImage = maskImage.convertToFormat(QImage::Format_Mono);
- int nbits = 32;
- int bpl_bmp = ((image.width()*nbits+31)/32)*4;
+ int nbits = 32;
+ int bpl_bmp = ((image.width()*nbits+31)/32)*4;
entries[i].bColorCount = 0;
entries[i].bReserved = 0;
@@ -670,7 +664,7 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
entries[i].dwBytesInRes = BMP_INFOHDR_SIZE + (bpl_bmp * image.height())
+ (maskImage.bytesPerLine() * maskImage.height());
entries[i].wPlanes = 1;
- if (i==0)
+ if (i == 0)
entries[i].dwImageOffset = origOffset + ICONDIR_SIZE
+ (id.idCount * ICONDIRENTRY_SIZE);
else
@@ -695,7 +689,7 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
uchar *b;
memset( buf, 0, bpl_bmp );
int y;
- for (y=image.height()-1; y>=0; y--) { // write the image bits
+ for (y = image.height() - 1; y >= 0; y--) { // write the image bits
// 32 bits
QRgb *p = (QRgb *)image.scanLine(y);
QRgb *end = p + image.width();
@@ -717,13 +711,10 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
maskImage.invertPixels(); // seems as though it needs this
// NOTE! !! The mask is only flipped vertically - not horizontally !!
- for (y=maskImage.height()-1; y>=0; y--)
+ for (y = maskImage.height() - 1; y >= 0; y--)
buffer.write((char*)maskImage.scanLine(y), maskImage.bytesPerLine());
-
}
-
-
if (writeIconDir(device, id)) {
int i;
bool bOK = true;
@@ -731,7 +722,7 @@ bool ICOReader::write(QIODevice * device, const QList<QImage> & images)
bOK = writeIconDirEntry(device, entries[i]);
}
if (bOK) {
- for (i=0; i<id.idCount && bOK; i++) {
+ for (i = 0; i < id.idCount && bOK; i++) {
bOK = writeBMPInfoHeader(device, bmpHeaders[i]);
bOK &= (device->write(imageData[i]) == (int) imageData[i].size());
}
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 6d0bc1f..088ef97 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -781,7 +781,8 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage,
#ifndef QT_NO_IMAGE_SMOOTHSCALE
// If high quality not required, shrink image during decompression
- if (scaledSize.isValid() && quality < HIGH_QUALITY_THRESHOLD && !params.contains(QLatin1String("GetHeaderInformation")) ) {
+ if (scaledSize.isValid() && !scaledSize.isEmpty() && quality < HIGH_QUALITY_THRESHOLD
+ && !params.contains(QLatin1String("GetHeaderInformation")) ) {
cinfo.scale_denom = qMin(cinfo.image_width / scaledSize.width(),
cinfo.image_width / scaledSize.height());
if (cinfo.scale_denom < 2) {
diff --git a/src/plugins/imageformats/svg/qsvgiohandler.cpp b/src/plugins/imageformats/svg/qsvgiohandler.cpp
index 41b247b..405a760 100644
--- a/src/plugins/imageformats/svg/qsvgiohandler.cpp
+++ b/src/plugins/imageformats/svg/qsvgiohandler.cpp
@@ -64,6 +64,7 @@ public:
}
bool load(QIODevice *device);
+ static bool findSvgTag(QIODevice *device);
QSvgRenderer *r;
QSize defaultSize;
@@ -86,6 +87,33 @@ bool QSvgIOHandlerPrivate::load(QIODevice *device)
return loaded;
}
+bool QSvgIOHandlerPrivate::findSvgTag(QIODevice *device)
+{
+ qint64 pos = device->pos();
+ device->seek(0);
+ char buffer[256];
+ const char svg_tag[] = "<svg";
+
+ while (1) {
+ int size = device->read(buffer, 256);
+ for (int i=0; i<size - 5; ++i) {
+ if (!memcmp(buffer + i, svg_tag, 4)) {
+ if (buffer[i+4] == ' ' || buffer[i+4] == '\t'
+ || buffer[i+4] == '\n' || buffer[i+4] == '\r')
+ {
+ device->seek(pos);
+ return true;
+ }
+ }
+ }
+ if (device->atEnd())
+ break;
+ device->seek(device->pos()-4);
+ }
+ device->seek(pos);
+ return false;
+}
+
QSvgIOHandler::QSvgIOHandler()
: d(new QSvgIOHandlerPrivate())
{
@@ -101,9 +129,7 @@ QSvgIOHandler::~QSvgIOHandler()
bool QSvgIOHandler::canRead() const
{
- QByteArray contents = device()->peek(80);
-
- return contents.contains("<svg");
+ return QSvgIOHandlerPrivate::findSvgTag(device());
}
@@ -182,8 +208,7 @@ bool QSvgIOHandler::supportsOption(ImageOption option) const
bool QSvgIOHandler::canRead(QIODevice *device)
{
- QByteArray contents = device->peek(80);
- return contents.contains("<svg");
+ return QSvgIOHandlerPrivate::findSvgTag(device);
}
QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp
index 518e6d1..791aeaa 100644
--- a/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -131,58 +131,138 @@ bool QTiffHandler::read(QImage *image)
if (!canRead())
return false;
- TIFF *tiff = TIFFClientOpen("foo",
- "r",
- this,
- qtiffReadProc,
- qtiffWriteProc,
- qtiffSeekProc,
- qtiffCloseProc,
- qtiffSizeProc,
- qtiffMapProc,
- qtiffUnmapProc);
-
- if (tiff) {
- uint32 width = 0;
- uint32 height = 0;
- TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width);
- TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height);
- if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32)
- *image = QImage(width, height, QImage::Format_ARGB32);
+ TIFF *const tiff = TIFFClientOpen("foo",
+ "r",
+ this,
+ qtiffReadProc,
+ qtiffWriteProc,
+ qtiffSeekProc,
+ qtiffCloseProc,
+ qtiffSizeProc,
+ qtiffMapProc,
+ qtiffUnmapProc);
+
+ if (!tiff) {
+ return false;
+ }
+ uint32 width;
+ uint32 height;
+ uint16 photometric;
+ if (!TIFFGetField(tiff, TIFFTAG_IMAGEWIDTH, &width)
+ || !TIFFGetField(tiff, TIFFTAG_IMAGELENGTH, &height)
+ || !TIFFGetField(tiff, TIFFTAG_PHOTOMETRIC, &photometric)) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) {
+ if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono)
+ *image = QImage(width, height, QImage::Format_Mono);
+ QVector<QRgb> colortable(2);
+ if (photometric == PHOTOMETRIC_MINISBLACK) {
+ colortable[0] = 0xff000000;
+ colortable[1] = 0xffffffff;
+ } else {
+ colortable[0] = 0xffffffff;
+ colortable[1] = 0xff000000;
+ }
+ image->setColorTable(colortable);
+
if (!image->isNull()) {
- if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, 0)) {
- uint16 resUnit = RESUNIT_NONE;
- float resX = 0;
- float resY = 0;
- TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit);
- TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX);
- TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY);
- switch(resUnit) {
- case RESUNIT_CENTIMETER:
- image->setDotsPerMeterX(qRound(resX * 100));
- image->setDotsPerMeterY(qRound(resY * 100));
- break;
- case RESUNIT_INCH:
- image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
- image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
- break;
- default:
- // do nothing as defaults have already
- // been set within the QImage class
- break;
+ for (uint32 y=0; y<height; ++y) {
+ if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
+ TIFFClose(tiff);
+ return false;
+ }
+ }
+ }
+ } else {
+ uint16 bitPerSample;
+ if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) {
+ TIFFClose(tiff);
+ return false;
+ }
+ if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) {
+ if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8)
+ *image = QImage(width, height, QImage::Format_Indexed8);
+ if (!image->isNull()) {
+ // create the color table
+ const uint16 tableSize = 256;
+ uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
+ uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
+ uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16)));
+ if (!redTable || !greenTable || !blueTable) {
+ TIFFClose(tiff);
+ return false;
+ }
+ if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ QVector<QRgb> qtColorTable(tableSize);
+ for (int i = 0; i<tableSize ;++i) {
+ const int red = redTable[i] / 257;
+ const int green = greenTable[i] / 257;
+ const int blue = blueTable[i] / 257;
+ qtColorTable[i] = qRgb(red, green, blue);
+
+ }
+
+ image->setColorTable(qtColorTable);
+ for (uint32 y=0; y<height; ++y) {
+ if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) {
+ TIFFClose(tiff);
+ return false;
+ }
+ }
+
+ // free redTable, greenTable and greenTable done by libtiff
+ }
+ } else {
+ if (image->size() != QSize(width, height) || image->format() != QImage::Format_ARGB32)
+ *image = QImage(width, height, QImage::Format_ARGB32);
+ if (!image->isNull()) {
+ if (TIFFReadRGBAImageOriented(tiff, width, height, reinterpret_cast<uint32 *>(image->bits()), ORIENTATION_TOPLEFT, 0)) {
+ for (uint32 y=0; y<height; ++y)
+ convert32BitOrder(image->scanLine(y), width);
+ } else {
+ TIFFClose(tiff);
+ return false;
}
- for (uint32 y=0; y<height; ++y)
- convert32BitOrder(image->scanLine(y), width);
- } else {
- *image = QImage();
}
}
- TIFFClose(tiff);
}
- if (image->isNull())
+ if (image->isNull()) {
+ TIFFClose(tiff);
return false;
+ }
+ float resX = 0;
+ float resY = 0;
+ uint16 resUnit = RESUNIT_NONE;
+ if (TIFFGetField(tiff, TIFFTAG_RESOLUTIONUNIT, &resUnit)
+ && TIFFGetField(tiff, TIFFTAG_XRESOLUTION, &resX)
+ && TIFFGetField(tiff, TIFFTAG_YRESOLUTION, &resY)) {
+
+ switch(resUnit) {
+ case RESUNIT_CENTIMETER:
+ image->setDotsPerMeterX(qRound(resX * 100));
+ image->setDotsPerMeterY(qRound(resY * 100));
+ break;
+ case RESUNIT_INCH:
+ image->setDotsPerMeterX(qRound(resX * (100 / 2.54)));
+ image->setDotsPerMeterY(qRound(resY * (100 / 2.54)));
+ break;
+ default:
+ // do nothing as defaults have already
+ // been set within the QImage class
+ break;
+ }
+ }
+
+ TIFFClose(tiff);
return true;
}
@@ -191,33 +271,148 @@ bool QTiffHandler::write(const QImage &image)
if (!device()->isWritable())
return false;
- TIFF *tiff = TIFFClientOpen("foo",
- "w",
- this,
- qtiffReadProc,
- qtiffWriteProc,
- qtiffSeekProc,
- qtiffCloseProc,
- qtiffSizeProc,
- qtiffMapProc,
- qtiffUnmapProc);
-
- if (tiff) {
- int width = image.width();
- int height = image.height();
- int depth = 32;
-
- if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
- || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
- || !TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
- || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
- || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, depth/8)
- || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)
- || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
+ TIFF *const tiff = TIFFClientOpen("foo",
+ "w",
+ this,
+ qtiffReadProc,
+ qtiffWriteProc,
+ qtiffSeekProc,
+ qtiffCloseProc,
+ qtiffSizeProc,
+ qtiffMapProc,
+ qtiffUnmapProc);
+ if (!tiff)
+ return false;
+
+ const int width = image.width();
+ const int height = image.height();
+
+ if (!TIFFSetField(tiff, TIFFTAG_IMAGEWIDTH, width)
+ || !TIFFSetField(tiff, TIFFTAG_IMAGELENGTH, height)
+ || !TIFFSetField(tiff, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG)) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ // set the resolution
+ bool resolutionSet = false;
+ const int dotPerMeterX = image.dotsPerMeterX();
+ const int dotPerMeterY = image.dotsPerMeterY();
+ if ((dotPerMeterX % 100) == 0
+ && (dotPerMeterY % 100) == 0) {
+ resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_CENTIMETER)
+ && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, dotPerMeterX/100.0)
+ && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, dotPerMeterY/100.0);
+ } else {
+ resolutionSet = TIFFSetField(tiff, TIFFTAG_RESOLUTIONUNIT, RESUNIT_INCH)
+ && TIFFSetField(tiff, TIFFTAG_XRESOLUTION, static_cast<float>(image.logicalDpiX()))
+ && TIFFSetField(tiff, TIFFTAG_YRESOLUTION, static_cast<float>(image.logicalDpiY()));
+ }
+ if (!resolutionSet) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ // configure image depth
+ const QImage::Format format = image.format();
+ if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) {
+ uint16 photometric = PHOTOMETRIC_MINISBLACK;
+ if (image.colorTable().at(0) == 0xffffffff)
+ photometric = PHOTOMETRIC_MINISWHITE;
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) {
TIFFClose(tiff);
return false;
}
+ // try to do the conversion in chunks no greater than 16 MB
+ int chunks = (width * height / (1024 * 1024 * 16)) + 1;
+ int chunkHeight = qMax(height / chunks, 1);
+
+ int y = 0;
+ while (y < height) {
+ QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y)).convertToFormat(QImage::Format_Mono);
+
+ int chunkStart = y;
+ int chunkEnd = y + chunk.height();
+ while (y < chunkEnd) {
+ if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
+ TIFFClose(tiff);
+ return false;
+ }
+ ++y;
+ }
+ }
+ TIFFClose(tiff);
+ } else if (format == QImage::Format_Indexed8) {
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS)
+ || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
+ TIFFClose(tiff);
+ return false;
+ }
+ //// write the color table
+ // allocate the color tables
+ uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
+ uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
+ uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16)));
+ if (!redTable || !greenTable || !blueTable) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ // set the color table
+ const QVector<QRgb> colorTable = image.colorTable();
+
+ const int tableSize = colorTable.size();
+ Q_ASSERT(tableSize <= 256);
+ for (int i = 0; i<tableSize; ++i) {
+ const QRgb color = colorTable.at(i);
+ redTable[i] = qRed(color) * 257;
+ greenTable[i] = qGreen(color) * 257;
+ blueTable[i] = qBlue(color) * 257;
+ }
+
+ const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable);
+
+ qFree(redTable);
+ qFree(greenTable);
+ qFree(blueTable);
+
+ if (!setColorTableSuccess) {
+ TIFFClose(tiff);
+ return false;
+ }
+
+ //// write the data
+ // try to do the conversion in chunks no greater than 16 MB
+ int chunks = (width * height/ (1024 * 1024 * 16)) + 1;
+ int chunkHeight = qMax(height / chunks, 1);
+
+ int y = 0;
+ while (y < height) {
+ QImage chunk = image.copy(0, y, width, qMin(chunkHeight, height - y));
+
+ int chunkStart = y;
+ int chunkEnd = y + chunk.height();
+ while (y < chunkEnd) {
+ if (TIFFWriteScanline(tiff, reinterpret_cast<uint32 *>(chunk.scanLine(y - chunkStart)), y) != 1) {
+ TIFFClose(tiff);
+ return false;
+ }
+ ++y;
+ }
+ }
+ TIFFClose(tiff);
+
+ } else {
+ if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB)
+ || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_LZW)
+ || !TIFFSetField(tiff, TIFFTAG_SAMPLESPERPIXEL, 4)
+ || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) {
+ TIFFClose(tiff);
+ return false;
+ }
// try to do the ARGB32 conversion in chunks no greater than 16 MB
int chunks = (width * height * 4 / (1024 * 1024 * 16)) + 1;
int chunkHeight = qMax(height / chunks, 1);
@@ -242,9 +437,8 @@ bool QTiffHandler::write(const QImage &image)
}
}
TIFFClose(tiff);
- } else {
- return false;
}
+
return true;
}
diff --git a/src/plugins/kbddrivers/kbddrivers.pro b/src/plugins/kbddrivers/kbddrivers.pro
index 6605972..a34b780 100644
--- a/src/plugins/kbddrivers/kbddrivers.pro
+++ b/src/plugins/kbddrivers/kbddrivers.pro
@@ -1,6 +1,5 @@
TEMPLATE = subdirs
-contains(kbd-plugins, usb): SUBDIRS += usb
+contains(kbd-plugins, linuxinput): SUBDIRS += linuxinput
contains(kbd-plugins, sl5000): SUBDIRS += sl5000
contains(kbd-plugins, vr41xx): SUBDIRS += vr41xx
contains(kbd-plugins, yopy): SUBDIRS += yopy
-contains(kbd-plugins, linuxis): SUBDIRS += linuxis
diff --git a/src/plugins/kbddrivers/linuxinput/linuxinput.pro b/src/plugins/kbddrivers/linuxinput/linuxinput.pro
new file mode 100644
index 0000000..862a220
--- /dev/null
+++ b/src/plugins/kbddrivers/linuxinput/linuxinput.pro
@@ -0,0 +1,14 @@
+TARGET = qlinuxinputkbddriver
+include(../../qpluginbase.pri)
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/kbddrivers
+target.path = $$[QT_INSTALL_PLUGINS]/kbddrivers
+INSTALLS += target
+
+DEFINES += QT_QWS_KBD_LINUXINPUT
+
+HEADERS = $$QT_SOURCE_TREE/src/gui/embedded/qkbdlinuxinput_qws.h
+
+SOURCES = main.cpp \
+ $$QT_SOURCE_TREE/src/gui/embedded/qkbdlinuxinput_qws.cpp
+
diff --git a/src/plugins/kbddrivers/usb/main.cpp b/src/plugins/kbddrivers/linuxinput/main.cpp
index 1d6ab89..45d06c4 100644
--- a/src/plugins/kbddrivers/usb/main.cpp
+++ b/src/plugins/kbddrivers/linuxinput/main.cpp
@@ -40,38 +40,38 @@
****************************************************************************/
#include <qkbddriverplugin_qws.h>
-#include <qkbdusb_qws.h>
+#include <qkbdlinuxinput_qws.h>
QT_BEGIN_NAMESPACE
-class QUsbKbdDriver : public QKbdDriverPlugin
+class QLinuxInputKbdDriver : public QKbdDriverPlugin
{
public:
- QUsbKbdDriver();
+ QLinuxInputKbdDriver();
QStringList keys() const;
QWSKeyboardHandler* create(const QString &driver, const QString &device);
};
-QUsbKbdDriver::QUsbKbdDriver()
+QLinuxInputKbdDriver::QLinuxInputKbdDriver()
: QKbdDriverPlugin()
{
}
-QStringList QUsbKbdDriver::keys() const
+QStringList QLinuxInputKbdDriver::keys() const
{
- return (QStringList() << QLatin1String("Usb"));
+ return (QStringList() << QLatin1String("LinuxInput"));
}
-QWSKeyboardHandler* QUsbKbdDriver::create(const QString &driver,
- const QString &device)
+QWSKeyboardHandler* QLinuxInputKbdDriver::create(const QString &driver,
+ const QString &device)
{
Q_UNUSED(device);
- if (driver.compare(QLatin1String("Usb"), Qt::CaseInsensitive))
+ if (driver.compare(QLatin1String("LinuxInput"), Qt::CaseInsensitive))
return 0;
- return new QWSUsbKeyboardHandler(driver);
+ return new QWSLinuxInputKeyboardHandler(driver, device);
}
-Q_EXPORT_PLUGIN2(qwsusbkbddriver, QUsbKbdDriver)
+Q_EXPORT_PLUGIN2(qwslinuxinputkbddriver, QLinuxInputKbdDriver)
QT_END_NAMESPACE
diff --git a/src/plugins/kbddrivers/linuxis/README b/src/plugins/kbddrivers/linuxis/README
deleted file mode 100644
index 37a9a89..0000000
--- a/src/plugins/kbddrivers/linuxis/README
+++ /dev/null
@@ -1 +0,0 @@
-This is a keypad/only keyboard driver based on the Linux input subsystem.
diff --git a/src/plugins/kbddrivers/linuxis/linuxis.pro b/src/plugins/kbddrivers/linuxis/linuxis.pro
deleted file mode 100644
index 5e652b5..0000000
--- a/src/plugins/kbddrivers/linuxis/linuxis.pro
+++ /dev/null
@@ -1,11 +0,0 @@
-TARGET = linuxiskbdhandler
-include(../../qpluginbase.pri)
-
-QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/kbddrivers
-target.path = $$[QT_INSTALL_PLUGINS]/kbddrivers
-INSTALLS += target
-
-CONFIG+=no_tr
-
-HEADERS = linuxiskbddriverplugin.h linuxiskbdhandler.h
-SOURCES = linuxiskbddriverplugin.cpp linuxiskbdhandler.cpp
diff --git a/src/plugins/kbddrivers/linuxis/linuxiskbdhandler.cpp b/src/plugins/kbddrivers/linuxis/linuxiskbdhandler.cpp
deleted file mode 100644
index 99b98b7..0000000
--- a/src/plugins/kbddrivers/linuxis/linuxiskbdhandler.cpp
+++ /dev/null
@@ -1,171 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** Contact: Qt Software Information (qt-info@nokia.com)
-**
-** This file is part of the plugins of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
-**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at qt-sales@nokia.com.
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "linuxiskbdhandler.h"
-
-#include <QSocketNotifier>
-
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-
-#include <linux/input.h>
-#include <linux/kd.h>
-
-#include <qdebug.h>
-#if 1
-#define qLog(x) qDebug()
-#else
-#define qLog(x) while (0) qDebug()
-#endif
-
-struct LinuxInputSubsystemKbdHandler::keytable_s LinuxInputSubsystemKbdHandler::keytable[] = {
- { KEY_PAGEDOWN, 0xffff, Qt::Key_Context1 },
- { KEY_END, 0xffff, Qt::Key_Back },
- { KEY_RIGHTCTRL, 0xffff, Qt::Key_Home },
- { KEY_SPACE, 0xffff, Qt::Key_Menu },
- { KEY_ENTER, 0xffff, Qt::Key_Select },
- { KEY_UP, 0xffff, Qt::Key_Up },
- { KEY_LEFT, 0xffff, Qt::Key_Left },
- { KEY_RIGHT, 0xffff, Qt::Key_Right },
- { KEY_DOWN, 0xffff, Qt::Key_Down },
- { KEY_POWER, 0xffff, Qt::Key_Call },
- { KEY_BACKSPACE, 0xffff, Qt::Key_Backspace },
- { KEY_F1, 0xffff, Qt::Key_Hangup },
- { KEY_KP1, '1', Qt::Key_1 },
- { KEY_KP2, '2', Qt::Key_2 },
- { KEY_KP3, '3', Qt::Key_3 },
- { KEY_KP4, '4', Qt::Key_4 },
- { KEY_KP5, '5', Qt::Key_5 },
- { KEY_KP6, '6', Qt::Key_6 },
- { KEY_KP7, '7', Qt::Key_7 },
- { KEY_KP8, '8', Qt::Key_8 },
- { KEY_KP9, '9', Qt::Key_9 },
- { KEY_KP0, '0', Qt::Key_0 },
- { KEY_APOSTROPHE, '*', Qt::Key_Asterisk },
- { KEY_3, '#', Qt::Key_NumberSign },
- { KEY_F2, 0xffff, Qt::Key_F2 },
- { KEY_F3, 0xffff, Qt::Key_F3 },
- { KEY_F4, 0xffff, Qt::Key_F4 },
- { KEY_F5, 0xffff, Qt::Key_F5 },
- { KEY_F6, 0xffff, Qt::Key_F6 },
- { KEY_F7, 0xffff, Qt::Key_VolumeUp },
- { KEY_F8, 0xffff, Qt::Key_VolumeDown },
- { KEY_F9, 0xffff, Qt::Key_F9 },
- { 0, 0, Qt::Key_unknown },
-};
-
-struct LinuxInputSubsystemKbdHandler::keymap_s LinuxInputSubsystemKbdHandler::keymap[KEY_MAX];
-
-LinuxInputSubsystemKbdHandler::LinuxInputSubsystemKbdHandler(const QString &device)
-{
- qLog(Input) << "Loaded LinuxInputSubsystem keypad plugin!";
- setObjectName( "LinuxInputSubsystem Keypad Handler" );
- kbdFD = ::open(device.toLocal8Bit().constData(), O_RDONLY, 0);
- if (kbdFD >= 0) {
- qLog(Input) << "Opened" << device << "as keypad input";
-#if 0
- struct kbd_repeat kbdrep;
- kbdrep.delay = 500; /* ms */
- kbdrep.period = 250; /* ms */
- ioctl(kbdFD, KDKBDREP, &kbdrep);
-#endif
- m_notify = new QSocketNotifier( kbdFD, QSocketNotifier::Read, this );
- connect( m_notify, SIGNAL(activated(int)), this, SLOT(readKbdData()));
- } else {
- qWarning("Cannot open '%s' for keypad (%s)",
- device.toLocal8Bit().constData(), strerror(errno));
- return;
- }
- shift = false;
-
- initmap();
-}
-
-LinuxInputSubsystemKbdHandler::~LinuxInputSubsystemKbdHandler()
-{
-}
-
-void LinuxInputSubsystemKbdHandler::initmap()
-{
- for (int i = 0; i < KEY_MAX; i++) {
- keymap[i].unicode = 0xffff;
- keymap[i].keycode = Qt::Key_unknown;
- }
- for (int i = 0; keytable[i].unicode; i++) {
- int idx = keytable[i].code;
- keymap[idx].unicode = keytable[i].unicode;
- keymap[idx].keycode = keytable[i].keycode;
- }
-}
-
-void LinuxInputSubsystemKbdHandler::readKbdData()
-{
- struct input_event *ie;
- struct input_event iebuf[32];
-
- uint n = ::read(kbdFD, iebuf, sizeof(iebuf));
-
- bool pressed;
- bool autorepeat;
- int modifiers = 0;
- int unicode, keycode;
-
- n /= sizeof(struct input_event);
- ie = iebuf;
- for (uint i = 0; i < n; i++) {
-
- pressed = ie->value != 0;
- autorepeat = ie->value == 2;
- qLog() << "keyEvent" << hex << ie->type << ie->code << ie->value;
- unicode = keymap[ie->code].unicode;
- keycode = keymap[ie->code].keycode;
-
- processKeyEvent(unicode, keycode, (Qt::KeyboardModifiers)modifiers,
- pressed, autorepeat);
-
- ie++;
- }
-
-}
-
diff --git a/src/plugins/kbddrivers/usb/usb.pro b/src/plugins/kbddrivers/usb/usb.pro
deleted file mode 100644
index 4187255..0000000
--- a/src/plugins/kbddrivers/usb/usb.pro
+++ /dev/null
@@ -1,14 +0,0 @@
-TARGET = qusbkbddriver
-include(../../qpluginbase.pri)
-
-QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/kbddrivers
-target.path = $$[QT_INSTALL_PLUGINS]/kbddrivers
-INSTALLS += target
-
-DEFINES += QT_QWS_KBD_USB
-
-HEADERS = $$QT_SOURCE_TREE/src/gui/embedded/qkbdusb_qws.h
-
-SOURCES = main.cpp \
- $$QT_SOURCE_TREE/src/gui/embedded/qkbdusb_qws.cpp
-
diff --git a/src/plugins/sqldrivers/odbc/odbc.pro b/src/plugins/sqldrivers/odbc/odbc.pro
index 0835ce1..3de8ab2 100644
--- a/src/plugins/sqldrivers/odbc/odbc.pro
+++ b/src/plugins/sqldrivers/odbc/odbc.pro
@@ -4,15 +4,9 @@ HEADERS = ../../../sql/drivers/odbc/qsql_odbc.h
SOURCES = main.cpp \
../../../sql/drivers/odbc/qsql_odbc.cpp
-mac {
- !contains( LIBS, .*odbc.* ) {
- LIBS *= -liodbc
- }
-}
-
unix {
!contains( LIBS, .*odbc.* ) {
- LIBS *= -lodbc
+ LIBS *= $$QT_LFLAGS_ODBC
}
}
diff --git a/src/qbase.pri b/src/qbase.pri
index d52120a..2b0abc2 100644
--- a/src/qbase.pri
+++ b/src/qbase.pri
@@ -4,7 +4,7 @@ INCLUDEPATH *= $$QMAKE_INCDIR_QT/$$TARGET #just for today to have some compat
isEmpty(QT_ARCH):!isEmpty(ARCH):QT_ARCH=$$ARCH #another compat that will rot for change #215700
TEMPLATE = lib
isEmpty(QT_MAJOR_VERSION) {
- VERSION=4.5.2
+ VERSION=4.6.0
} else {
VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION}
}
@@ -67,11 +67,6 @@ mac:!static:contains(QT_CONFIG, qt_framework) {
mac {
CONFIG += explicitlib
- true { #we want to use O2 on Qt itself (Os was used to fix other failures in older GCC)
- QMAKE_CFLAGS_RELEASE ~= s,-Os,-O2,
- QMAKE_CXXFLAGS_RELEASE ~= s,-Os,-O2,
- QMAKE_OBJECTIVE_CFLAGS_RELEASE ~= s,-Os,-O2,
- }
macx-g++ {
QMAKE_CFLAGS += -fconstant-cfstrings
QMAKE_CXXFLAGS += -fconstant-cfstrings
diff --git a/src/qt3support/dialogs/q3filedialog.cpp b/src/qt3support/dialogs/q3filedialog.cpp
index 1ec0cfc..e41941b 100644
--- a/src/qt3support/dialogs/q3filedialog.cpp
+++ b/src/qt3support/dialogs/q3filedialog.cpp
@@ -3879,7 +3879,7 @@ void Q3FileDialog::detailViewSelectionChanged()
d->moreFiles->setSelected(f->i, i->isSelected());
}
if (i->isSelected() && !((Q3FileDialogPrivate::File *)i)->info.isDir())
- str += QString(QLatin1String("\"%1\" ")).arg(i->text(0));
+ str += QString::fromLatin1("\"%1\" ").arg(i->text(0));
i = i->nextSibling();
}
d->moreFiles->blockSignals(false);
@@ -3931,7 +3931,7 @@ void Q3FileDialog::listBoxSelectionChanged()
}
if (d->moreFiles->isSelected(i)
&& !((Q3FileDialogPrivate::File*)(mcitem)->i)->info.isDir()) {
- str += QString(QLatin1String("\"%1\" ")).arg(i->text());
+ str += QString::fromLatin1("\"%1\" ").arg(i->text());
if (j == 0)
j = i;
}
@@ -4611,11 +4611,11 @@ void Q3FileDialog::setPreviewMode(PreviewMode m)
}
Q3FileDialog::PreviewMode Q3FileDialog::previewMode() const
{
- if (d->infoPreview && d->infoPreviewWidget->isVisible())
+ if (d->infoPreview && d->infoPreviewWidget->isVisibleTo(const_cast<Q3FileDialog *>(this)))
return Info;
- else if (d->contentsPreview && d->contentsPreviewWidget->isVisible())
+ else if (d->contentsPreview
+ && d->contentsPreviewWidget->isVisibleTo(const_cast<Q3FileDialog *>(this)))
return Contents;
-
return NoPreview;
}
@@ -5757,8 +5757,8 @@ void Q3FileDialog::insertEntry(const Q3ValueList<QUrlInfo> &lst, Q3NetworkOperat
if (!bShowHiddenFiles && inf.name() != QLatin1String("..")) {
if (d->url.isLocalFile()) {
QString file = d->url.path();
- if (!file.endsWith(QLatin1String("/")))
- file.append(QLatin1String("/"));
+ if (!file.endsWith(QLatin1Char('/')))
+ file.append(QLatin1Char('/'));
file += inf.name();
QT_WA({
if (GetFileAttributesW((TCHAR*)file.ucs2()) & FILE_ATTRIBUTE_HIDDEN)
diff --git a/src/qt3support/dialogs/q3filedialog_mac.cpp b/src/qt3support/dialogs/q3filedialog_mac.cpp
index f1c749ec..18bebf1 100644
--- a/src/qt3support/dialogs/q3filedialog_mac.cpp
+++ b/src/qt3support/dialogs/q3filedialog_mac.cpp
@@ -554,7 +554,7 @@ QString Q3FileDialog::macGetSaveFileName(const QString &start, const QString &fi
retstr = QString::fromUtf8((const char *)str_buffer);
//now filename
CFStringGetCString(ret.saveFileName, (char *)str_buffer, 1024, kCFStringEncodingUTF8);
- retstr += QLatin1String("/") + QString::fromUtf8((const char *)str_buffer);
+ retstr += QLatin1Char('/') + QString::fromUtf8((const char *)str_buffer);
}
NavDisposeReply(&ret);
if(selectedFilter)
diff --git a/src/qt3support/dialogs/q3filedialog_win.cpp b/src/qt3support/dialogs/q3filedialog_win.cpp
index 1be797a..a1c98f3 100644
--- a/src/qt3support/dialogs/q3filedialog_win.cpp
+++ b/src/qt3support/dialogs/q3filedialog_win.cpp
@@ -737,7 +737,7 @@ QString Q3FileDialog::winGetExistingDirectory(const QString& initialDirectory,
QDir::setCurrent(currentDir);
if (!result.isEmpty())
- result.replace(QLatin1String("\\"), QLatin1String("/"));
+ result.replace(QLatin1Char('\\'), QLatin1Char('/'));
return result;
#else
return QString();
diff --git a/src/qt3support/dialogs/q3tabdialog.cpp b/src/qt3support/dialogs/q3tabdialog.cpp
index 6242dce..52086a2 100644
--- a/src/qt3support/dialogs/q3tabdialog.cpp
+++ b/src/qt3support/dialogs/q3tabdialog.cpp
@@ -49,6 +49,7 @@
#include "qapplication.h"
#include "q3widgetstack.h"
#include "qlayout.h"
+#include "qevent.h"
QT_BEGIN_NAMESPACE
@@ -961,6 +962,16 @@ void Q3TabDialog::paintEvent(QPaintEvent *)
}
+/*!\reimp
+*/
+void Q3TabDialog::showEvent(QShowEvent *e)
+{
+ if (!e->spontaneous())
+ show();
+ QDialog::showEvent(e);
+}
+
+
/*!
Adds an OK button to the dialog and sets the button's text to \a text.
diff --git a/src/qt3support/dialogs/q3tabdialog.h b/src/qt3support/dialogs/q3tabdialog.h
index 3645df1..30acc7d 100644
--- a/src/qt3support/dialogs/q3tabdialog.h
+++ b/src/qt3support/dialogs/q3tabdialog.h
@@ -111,6 +111,7 @@ public:
protected:
void paintEvent(QPaintEvent *);
void resizeEvent(QResizeEvent *);
+ void showEvent(QShowEvent *);
void styleChange(QStyle&);
void setTabBar(QTabBar*);
QTabBar* tabBar() const;
diff --git a/src/qt3support/itemviews/q3iconview.cpp b/src/qt3support/itemviews/q3iconview.cpp
index d1a9c1e..a5664de 100644
--- a/src/qt3support/itemviews/q3iconview.cpp
+++ b/src/qt3support/itemviews/q3iconview.cpp
@@ -614,7 +614,7 @@ QByteArray Q3IconDrag::encodedData(const char* mime) const
(*it).item.textRect().x()).arg((*it).item.textRect().y()).
arg((*it).item.textRect().width()).arg(
(*it).item.textRect().height());
- k += QString(QLatin1String((*it).data.data())) + QLatin1String("$@@$");
+ k += QString::fromLatin1((*it).data.data()) + QLatin1String("$@@$");
s += k;
}
@@ -1820,8 +1820,8 @@ void Q3IconViewItem::calcRect(const QString &text_)
tw = r.width();
th = r.height();
- if (tw < view->d->fm->width(QLatin1String("X")))
- tw = view->d->fm->width(QLatin1String("X"));
+ if (tw < view->d->fm->width(QLatin1Char('X')))
+ tw = view->d->fm->width(QLatin1Char('X'));
itemTextRect.setWidth(tw);
itemTextRect.setHeight(th);
diff --git a/src/qt3support/network/q3dns.cpp b/src/qt3support/network/q3dns.cpp
index c53f2ff..3ca3977 100644
--- a/src/qt3support/network/q3dns.cpp
+++ b/src/qt3support/network/q3dns.cpp
@@ -1738,7 +1738,7 @@ void Q3Dns::setLabel( const QString & label )
const char * dom;
while( (dom=it.current()) != 0 ) {
++it;
- n.append( l.lower() + QLatin1String(".") + QLatin1String(dom) );
+ n.append( l.lower() + QLatin1Char('.') + QLatin1String(dom) );
}
}
n.append( l.lower() );
@@ -1902,8 +1902,8 @@ QString Q3Dns::toInAddrArpaDomain( const QHostAddress &address )
s = QLatin1String("ip6.arpa");
uint b = 0;
while( b < 16 ) {
- s = QString::number( i.c[b]%16, 16 ) + QLatin1String(".") +
- QString::number( i.c[b]/16, 16 ) + QLatin1String(".") + s;
+ s = QString::number( i.c[b]%16, 16 ) + QLatin1Char('.') +
+ QString::number( i.c[b]/16, 16 ) + QLatin1Char('.') + s;
b++;
}
}
@@ -2347,7 +2347,7 @@ void Q3Dns::doResInit()
nameServer += QLatin1String(dnsServer->IpAddress.String);
dnsServer = dnsServer->Next;
if ( dnsServer != 0 )
- nameServer += QLatin1String(" ");
+ nameServer += QLatin1Char(' ');
}
searchList = QLatin1String("");
separator = ' ';
@@ -2360,12 +2360,12 @@ void Q3Dns::doResInit()
}
if ( !gotNetworkParams ) {
if ( getDnsParamsFromRegistry(
- QString( QLatin1String("System\\CurrentControlSet\\Services\\Tcpip\\Parameters") ),
+ QLatin1String("System\\CurrentControlSet\\Services\\Tcpip\\Parameters"),
&domainName, &nameServer, &searchList )) {
// for NT
separator = ' ';
} else if ( getDnsParamsFromRegistry(
- QString( QLatin1String("System\\CurrentControlSet\\Services\\VxD\\MSTCP") ),
+ QLatin1String("System\\CurrentControlSet\\Services\\VxD\\MSTCP"),
&domainName, &nameServer, &searchList )) {
// for Windows 98
separator = ',';
@@ -2395,7 +2395,7 @@ void Q3Dns::doResInit()
} while( first < (int)nameServer.length() );
}
- searchList = searchList + QLatin1String(" ") + domainName;
+ searchList += QLatin1Char(' ') + domainName;
searchList = searchList.simplifyWhiteSpace().lower();
first = 0;
do {
@@ -2488,7 +2488,7 @@ void Q3Dns::doResInit()
while ( !stream.atEnd() ) {
line = stream.readLine();
QStringList list = QStringList::split( QLatin1String(" "), line );
- if( line.startsWith( QLatin1String("#") ) || list.size() < 2 )
+ if( line.startsWith( QLatin1Char('#') ) || list.size() < 2 )
continue;
const QString type = list[0].lower();
diff --git a/src/qt3support/network/q3ftp.cpp b/src/qt3support/network/q3ftp.cpp
index 5ab84cc..44c1f5c 100644
--- a/src/qt3support/network/q3ftp.cpp
+++ b/src/qt3support/network/q3ftp.cpp
@@ -485,7 +485,7 @@ bool Q3FtpDTP::parseDir( const QString &buffer, const QString &userName, QUrlInf
dateStr += lst[ 6 ];
dateStr += QLatin1Char(' ');
- if ( lst[ 7 ].contains( QLatin1String(":") ) ) {
+ if ( lst[ 7 ].contains( QLatin1Char(':') ) ) {
time = QTime( lst[ 7 ].left( 2 ).toInt(), lst[ 7 ].right( 2 ).toInt() );
dateStr += QString::number( QDate::currentDate().year() );
} else {
@@ -495,7 +495,7 @@ bool Q3FtpDTP::parseDir( const QString &buffer, const QString &userName, QUrlInf
QDate date = QDate::fromString( dateStr );
info->setLastModified( QDateTime( date, time ) );
- if ( lst[ 7 ].contains( QLatin1String(":") ) ) {
+ if ( lst[ 7 ].contains( QLatin1Char(':') ) ) {
const int futureTolerance = 600;
if( info->lastModified().secsTo( QDateTime::currentDateTime() ) < -futureTolerance ) {
QDateTime dt = info->lastModified();
@@ -512,7 +512,7 @@ bool Q3FtpDTP::parseDir( const QString &buffer, const QString &userName, QUrlInf
else {
QString n;
for ( uint i = 8; i < (uint) lst.count(); ++i )
- n += lst[ i ] + QLatin1String(" ");
+ n += lst[ i ] + QLatin1Char(' ');
n = n.stripWhiteSpace();
info->setName( n );
}
@@ -897,7 +897,7 @@ bool Q3FtpPI::processReply()
// ### error handling
} else {
QStringList lst = addrPortPattern.capturedTexts();
- QString host = lst[1] + QLatin1String(".") + lst[2] + QLatin1String(".") + lst[3] + QLatin1String(".") + lst[4];
+ QString host = lst[1] + QLatin1Char('.') + lst[2] + QLatin1Char('.') + lst[3] + QLatin1Char('.') + lst[4];
Q_UINT16 port = ( lst[5].toUInt() << 8 ) + lst[6].toUInt();
waitForDtpToConnect = true;
dtp.connectToHost( host, port );
@@ -1435,8 +1435,8 @@ int Q3Ftp::connectToHost( const QString &host, Q_UINT16 port )
int Q3Ftp::login( const QString &user, const QString &password )
{
QStringList cmds;
- cmds << ( QString(QLatin1String("USER ")) + ( user.isNull() ? QString(QLatin1String("anonymous")) : user ) + QLatin1String("\r\n") );
- cmds << ( QString(QLatin1String("PASS ")) + ( password.isNull() ? QString(QLatin1String("anonymous@")) : password ) + QLatin1String("\r\n") );
+ cmds << ( QString::fromLatin1("USER ") + ( user.isNull() ? QString::fromLatin1("anonymous") : user ) + QLatin1String("\r\n") );
+ cmds << ( QString::fromLatin1("PASS ") + ( password.isNull() ? QString::fromLatin1("anonymous@") : password ) + QLatin1String("\r\n") );
return addCommand( new Q3FtpCommand( Login, cmds ) );
}
@@ -2095,7 +2095,7 @@ void Q3Ftp::operationListChildren( Q3NetworkOperation *op )
{
op->setState( StInProgress );
- cd( ( url()->path().isEmpty() ? QString( QLatin1String("/") ) : url()->path() ) );
+ cd( ( url()->path().isEmpty() ? QString::fromLatin1("/") : url()->path() ) );
list();
emit start( op );
}
@@ -2115,7 +2115,7 @@ void Q3Ftp::operationRemove( Q3NetworkOperation *op )
{
op->setState( StInProgress );
- cd( ( url()->path().isEmpty() ? QString( QLatin1String("/") ) : url()->path() ) );
+ cd( ( url()->path().isEmpty() ? QString::fromLatin1("/") : url()->path() ) );
remove( Q3Url( op->arg( 0 ) ).path() );
}
@@ -2125,7 +2125,7 @@ void Q3Ftp::operationRename( Q3NetworkOperation *op )
{
op->setState( StInProgress );
- cd( ( url()->path().isEmpty() ? QString( QLatin1String("/") ) : url()->path() ) );
+ cd( ( url()->path().isEmpty() ? QString::fromLatin1("/") : url()->path() ) );
rename( op->arg( 0 ), op->arg( 1 ));
}
@@ -2179,8 +2179,8 @@ bool Q3Ftp::checkConnection( Q3NetworkOperation *op )
connectToHost( url()->host(), url()->port() != -1 ? url()->port() : 21 );
break;
}
- QString user = url()->user().isEmpty() ? QString( QLatin1String("anonymous") ) : url()->user();
- QString pass = url()->password().isEmpty() ? QString( QLatin1String("anonymous@") ) : url()->password();
+ QString user = url()->user().isEmpty() ? QString::fromLatin1("anonymous") : url()->user();
+ QString pass = url()->password().isEmpty() ? QString::fromLatin1("anonymous@") : url()->password();
login( user, pass );
}
diff --git a/src/qt3support/network/q3http.cpp b/src/qt3support/network/q3http.cpp
index 591b381..aabf4a3 100644
--- a/src/qt3support/network/q3http.cpp
+++ b/src/qt3support/network/q3http.cpp
@@ -468,7 +468,7 @@ bool Q3HttpHeader::parse( const QString& str )
if ( !(*it).isEmpty() ) {
if ( (*it)[0].isSpace() ) {
if ( !lines.isEmpty() ) {
- lines.last() += QLatin1String(" ");
+ lines.last() += QLatin1Char(' ');
lines.last() += (*it).stripWhiteSpace();
}
} else {
@@ -562,7 +562,7 @@ void Q3HttpHeader::removeValue( const QString& key )
*/
bool Q3HttpHeader::parseLine( const QString& line, int )
{
- int i = line.find( QLatin1String(":") );
+ int i = line.find( QLatin1Char(':') );
if ( i == -1 )
return false;
@@ -647,7 +647,7 @@ QString Q3HttpHeader::contentType() const
if ( type.isEmpty() )
return QString();
- int pos = type.find( QLatin1String(";") );
+ int pos = type.find( QLatin1Char(';') );
if ( pos == -1 )
return type;
@@ -2210,7 +2210,7 @@ void Q3Http::clientReply( const Q3HttpResponseHeader &rep )
if ( rep.statusCode() >= 400 && rep.statusCode() < 600 ) {
op->setState( StFailed );
op->setProtocolDetail(
- QString(QLatin1String("%1 %2")).arg(rep.statusCode()).arg(rep.reasonPhrase())
+ QString::fromLatin1("%1 %2").arg(rep.statusCode()).arg(rep.reasonPhrase())
);
switch ( rep.statusCode() ) {
case 401:
diff --git a/src/qt3support/network/q3url.cpp b/src/qt3support/network/q3url.cpp
index fc2fdb2..68753b6 100644
--- a/src/qt3support/network/q3url.cpp
+++ b/src/qt3support/network/q3url.cpp
@@ -211,8 +211,8 @@ Q3Url::Q3Url( const Q3Url& url )
bool Q3Url::isRelativeUrl( const QString &url )
{
- int colon = url.find( QLatin1String(":") );
- int slash = url.find( QLatin1String("/") );
+ int colon = url.find( QLatin1Char(':') );
+ int slash = url.find( QLatin1Char('/') );
return ( slash != 0 && ( colon == -1 || ( slash != -1 && colon > slash ) ) );
}
@@ -280,8 +280,8 @@ Q3Url::Q3Url( const Q3Url& url, const QString& relUrl, bool checkSlash )
if ( !d->host.isEmpty() && !d->user.isEmpty() && !d->pass.isEmpty() )
p = QLatin1String("/");
}
- if ( !p.isEmpty() && p.right(1)!=QLatin1String("/") )
- p += QLatin1String("/");
+ if ( !p.isEmpty() && !p.endsWith(QLatin1Char('/')) )
+ p += QLatin1Char('/');
p += rel;
d->path = p;
d->cleanPathDirty = true;
@@ -678,7 +678,7 @@ bool Q3Url::parse( const QString& url )
++cs;
while ( url_[ cs ] == QLatin1Char('/') )
++cs;
- int slash = url_.find( QLatin1String("/"), cs );
+ int slash = url_.find( QLatin1Char('/'), cs );
if ( slash == -1 )
slash = url_.length() - 1;
QString tmp = url_.mid( cs, slash - cs + 1 );
@@ -686,7 +686,7 @@ bool Q3Url::parse( const QString& url )
if ( !tmp.isEmpty() ) { // if this part exists
// look for the @ in this part
- int at = tmp.find( QLatin1String("@") );
+ int at = tmp.find( QLatin1Char('@') );
if ( at != -1 )
at += cs;
// we have no @, which means host[:port], so directly
@@ -793,7 +793,7 @@ bool Q3Url::parse( const QString& url )
// hack for windows
if ( d->path.length() == 2 && d->path[ 1 ] == QLatin1Char(':') )
- d->path += QLatin1String("/");
+ d->path += QLatin1Char('/');
// #### do some corrections, should be done nicer too
if ( !d->pass.isEmpty() ) {
@@ -808,7 +808,7 @@ bool Q3Url::parse( const QString& url )
if ( d->path[ 0 ] == QLatin1Char('@') || d->path[ 0 ] == QLatin1Char(':') )
d->path.remove( (uint)0, 1 );
if ( d->path[ 0 ] != QLatin1Char('/') && !relPath && d->path[ 1 ] != QLatin1Char(':') )
- d->path.prepend( QLatin1String("/") );
+ d->path.prepend( QLatin1Char('/') );
}
if ( !d->refEncoded.isEmpty() && d->refEncoded[ 0 ] == QLatin1Char('#') )
d->refEncoded.remove( (uint)0, 1 );
@@ -820,9 +820,9 @@ bool Q3Url::parse( const QString& url )
#if defined(Q_OS_WIN32)
// hack for windows file://machine/path syntax
if ( d->protocol == QLatin1String("file") ) {
- if ( url.left( 7 ) == QLatin1String("file://") &&
+ if ( url.startsWith(QLatin1String("file://")) &&
d->path.length() > 1 && d->path[ 1 ] != QLatin1Char(':') )
- d->path.prepend( QLatin1String("/") );
+ d->path.prepend( QLatin1Char('/') );
}
#endif
@@ -942,7 +942,7 @@ void Q3Url::setFileName( const QString& name )
p += fn;
if ( !d->queryEncoded.isEmpty() )
- p += QLatin1String("?") + d->queryEncoded;
+ p += QLatin1Char('?') + d->queryEncoded;
setEncodedPathAndQuery( p );
}
@@ -961,7 +961,7 @@ QString Q3Url::encodedPathAndQuery()
encode( p );
if ( !d->queryEncoded.isEmpty() ) {
- p += QLatin1String("?");
+ p += QLatin1Char('?');
p += d->queryEncoded;
}
@@ -1011,7 +1011,7 @@ QString Q3Url::path( bool correct ) const
} else if ( isLocalFile() ) {
#if defined(Q_OS_WIN32)
// hack for stuff like \\machine\path and //machine/path on windows
- if ( ( d->path.left( 1 ) == QLatin1String("/") || d->path.left( 1 ) == QLatin1String("\\") ) &&
+ if ( ( d->path.startsWith(QLatin1Char('/')) || d->path.startsWith(QLatin1Char('\\')) ) &&
d->path.length() > 1 ) {
d->cleanPath = d->path;
bool share = (d->cleanPath[0] == QLatin1Char('\\') && d->cleanPath[1] == QLatin1Char('\\')) ||
@@ -1021,7 +1021,7 @@ QString Q3Url::path( bool correct ) const
if ( share ) {
check = false;
while (d->cleanPath.at(0) != QLatin1Char('/') || d->cleanPath.at(1) != QLatin1Char('/'))
- d->cleanPath.prepend(QLatin1String("/"));
+ d->cleanPath.prepend(QLatin1Char('/'));
}
}
#endif
@@ -1036,7 +1036,7 @@ QString Q3Url::path( bool correct ) const
dir = QDir::cleanDirPath( canPath );
else
dir = QDir::cleanDirPath( QDir( d->path ).absPath() );
- dir += QLatin1String("/");
+ dir += QLatin1Char('/');
if ( dir == QLatin1String("//") )
d->cleanPath = QLatin1String("/");
else
@@ -1046,14 +1046,13 @@ QString Q3Url::path( bool correct ) const
QDir::cleanDirPath( (qt_resolve_symlinks ?
fi.dir().canonicalPath() :
fi.dir().absPath()) );
- d->cleanPath = p + QLatin1String("/") + fi.fileName();
+ d->cleanPath = p + QLatin1Char('/') + fi.fileName();
}
}
} else {
- if ( d->path != QLatin1String("/") && d->path[ (int)d->path.length() - 1 ] == QLatin1Char('/') )
- d->cleanPath = QDir::cleanDirPath( d->path ) + QLatin1String("/");
- else
d->cleanPath = QDir::cleanDirPath( d->path );
+ if ( d->path.length() > 1 && d->path.endsWith(QLatin1Char('/')) )
+ d->cleanPath += QLatin1Char('/');
}
if ( check )
@@ -1084,9 +1083,9 @@ bool Q3Url::isLocalFile() const
QString Q3Url::fileName() const
{
- if ( d->path.isEmpty() || d->path.endsWith( QLatin1String("/") )
+ if ( d->path.isEmpty() || d->path.endsWith( QLatin1Char('/') )
#ifdef Q_WS_WIN
- || d->path.endsWith( QLatin1String("\\") )
+ || d->path.endsWith( QLatin1Char('\\') )
#endif
)
return QString();
@@ -1110,12 +1109,12 @@ void Q3Url::addPath( const QString& pa )
if ( path().isEmpty() ) {
if ( p[ 0 ] != QLatin1Char( '/' ) )
- d->path = QLatin1String("/") + p;
+ d->path = QLatin1Char('/') + p;
else
d->path = p;
} else {
if ( p[ 0 ] != QLatin1Char( '/' ) && d->path[ (int)d->path.length() - 1 ] != QLatin1Char('/') )
- d->path += QLatin1String("/") + p;
+ d->path += QLatin1Char('/') + p;
else
d->path += p;
}
@@ -1250,11 +1249,11 @@ QString Q3Url::toString( bool encodedPath, bool forcePrependProtocol ) const
if ( isLocalFile() ) {
if ( forcePrependProtocol )
- res = d->protocol + QLatin1String(":") + p;
+ res = d->protocol + QLatin1Char(':') + p;
else
res = p;
} else if ( d->protocol == QLatin1String("mailto") ) {
- res = d->protocol + QLatin1String(":") + p;
+ res = d->protocol + QLatin1Char(':') + p;
} else {
res = d->protocol + QLatin1String("://");
if ( !d->user.isEmpty() || !d->pass.isEmpty() ) {
@@ -1267,24 +1266,24 @@ QString Q3Url::toString( bool encodedPath, bool forcePrependProtocol ) const
if ( !d->pass.isEmpty() ) {
tmp = d->pass;
encode( tmp );
- res += QLatin1String(":") + tmp;
+ res += QLatin1Char(':') + tmp;
}
- res += QLatin1String("@");
+ res += QLatin1Char('@');
}
res += d->host;
if ( d->port != -1 )
- res += QLatin1String(":") + QString( QLatin1String("%1") ).arg( d->port );
+ res += QLatin1Char(':') + QString::number( d->port );
if ( !p.isEmpty() ) {
if ( !d->host.isEmpty() && p[0]!= QLatin1Char( '/' ) )
- res += QLatin1String("/");
+ res += QLatin1Char('/');
res += p;
}
}
if ( !d->refEncoded.isEmpty() )
- res += QLatin1String("#") + d->refEncoded;
+ res += QLatin1Char('#') + d->refEncoded;
if ( !d->queryEncoded.isEmpty() )
- res += QLatin1String("?") + d->queryEncoded;
+ res += QLatin1Char('?') + d->queryEncoded;
return res;
}
diff --git a/src/qt3support/network/q3urloperator.cpp b/src/qt3support/network/q3urloperator.cpp
index b415e12..6afd8ab 100644
--- a/src/qt3support/network/q3urloperator.cpp
+++ b/src/qt3support/network/q3urloperator.cpp
@@ -579,7 +579,7 @@ Q3PtrList<Q3NetworkOperation> Q3UrlOperator::copy( const QString &from, const QS
if (frm == to + file)
return ops;
- file.prepend( QLatin1String("/") );
+ file.prepend( QLatin1Char('/') );
// uFrom and uTo are deleted when the Q3NetworkProtocol deletes itself via
// autodelete
diff --git a/src/qt3support/other/q3dragobject.cpp b/src/qt3support/other/q3dragobject.cpp
index fb57220..89ffe24 100644
--- a/src/qt3support/other/q3dragobject.cpp
+++ b/src/qt3support/other/q3dragobject.cpp
@@ -93,7 +93,7 @@ public:
Q3TextDragPrivate() { setSubType(QLatin1String("plain")); }
void setSubType(const QString & st) {
subtype = st;
- fmt = QString(QLatin1String("text/")).toLatin1() + subtype.toLatin1();
+ fmt = "text/" + subtype.toLatin1();
}
QString txt;
@@ -208,11 +208,6 @@ void Q3DragObject::setPixmap(QPixmap pm, const QPoint& hotspot)
Q_D(Q3DragObject);
d->pixmap = pm;
d->hot = hotspot;
-#if 0
- QDragManager *manager = QDragManager::self();
- if (manager && manager->object == d->data)
- manager->updatePixmap();
-#endif
}
/*!
@@ -1302,7 +1297,7 @@ QByteArray Q3UriDrag::localFileToUri(const QString& filename)
r.prepend(QString::fromLatin1(hostname));
}
#endif
- return unicodeUriToUri(QString(QLatin1String("file://") + r));
+ return unicodeUriToUri(QLatin1String("file://") + r);
}
/*!
@@ -1357,7 +1352,7 @@ QString Q3UriDrag::uriToLocalFile(const char* uri)
return file;
if (0==qstrnicmp(uri,"file:/",6)) // It is a local file uri
uri += 6;
- else if (QString(QLatin1String(uri)).indexOf(QLatin1String(":/")) != -1) // It is a different scheme uri
+ else if (QString::fromLatin1(uri).indexOf(QLatin1String(":/")) != -1) // It is a different scheme uri
return file;
bool local = uri[0] != '/' || (uri[0] != '\0' && uri[1] == '/');
diff --git a/src/qt3support/other/q3process.cpp b/src/qt3support/other/q3process.cpp
index 6eac812..9689de9 100644
--- a/src/qt3support/other/q3process.cpp
+++ b/src/qt3support/other/q3process.cpp
@@ -483,7 +483,7 @@ QString Q3Process::readLineStdout()
return QString();
if ( !buf->scanNewline( &a ) )
- return QString( QLatin1String(buf->readAll()) );
+ return QLatin1String(buf->readAll());
}
uint size = a.size();
diff --git a/src/qt3support/other/q3process_unix.cpp b/src/qt3support/other/q3process_unix.cpp
index 098c581..2492bf2 100644
--- a/src/qt3support/other/q3process_unix.cpp
+++ b/src/qt3support/other/q3process_unix.cpp
@@ -828,7 +828,7 @@ bool Q3Process::start( QStringList *env )
#ifndef QT_NO_DIR
QFileInfo fileInfo( dir, command );
#else
- QFileInfo fileInfo( dir + "/" + command );
+ QFileInfo fileInfo( dir + QLatin1Char('/') + command );
#endif
if ( fileInfo.isExecutable() ) {
#if defined(Q_OS_MACX)
diff --git a/src/qt3support/other/q3process_win.cpp b/src/qt3support/other/q3process_win.cpp
index 3c862ee..7dc28cb 100644
--- a/src/qt3support/other/q3process_win.cpp
+++ b/src/qt3support/other/q3process_win.cpp
@@ -285,7 +285,7 @@ bool Q3Process::start( QStringList *env )
for ( ; it != _arguments.end(); ++it ) {
QString tmp = *it;
// escape a single " because the arguments will be parsed
- tmp.replace( QLatin1String("\""), QLatin1String("\\\"") );
+ tmp.replace( QLatin1Char('\"'), QLatin1String("\\\"") );
if ( tmp.isEmpty() || tmp.contains( QLatin1Char(' ') ) || tmp.contains( QLatin1Char('\t') ) ) {
// The argument must not end with a \ since this would be interpreted
// as escaping the quote -- rather put the \ behind the quote: e.g.
@@ -294,9 +294,9 @@ bool Q3Process::start( QStringList *env )
int i = tmp.length();
while ( i>0 && tmp.at( i-1 ) == QLatin1Char('\\') ) {
--i;
- endQuote += QLatin1String("\\");
+ endQuote += QLatin1Char('\\');
}
- args += QString( QLatin1String(" \"") ) + tmp.left( i ) + endQuote;
+ args += QLatin1String(" \"") + tmp.left( i ) + endQuote;
} else {
args += QLatin1Char(' ') + tmp;
}
@@ -330,7 +330,7 @@ bool Q3Process::start( QStringList *env )
// add PATH if necessary (for DLL loading)
QByteArray path = qgetenv( "PATH" );
if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) {
- QString tmp = QString( QLatin1String("PATH=%1") ).arg(QString::fromLatin1(path.constData()));
+ QString tmp = QString::fromLatin1("PATH=%1").arg(QLatin1String(path.constData()));
uint tmpSize = sizeof(TCHAR) * (tmp.length()+1);
envlist.resize( envlist.size() + tmpSize );
memcpy( envlist.data()+pos, tmp.ucs2(), tmpSize );
@@ -378,7 +378,7 @@ bool Q3Process::start( QStringList *env )
// add PATH if necessary (for DLL loading)
QByteArray path = qgetenv( "PATH" );
if ( env->grep( QRegExp(QLatin1String("^PATH="),FALSE) ).empty() && !path.isNull() ) {
- Q3CString tmp = QString( QLatin1String("PATH=%1") ).arg(QString::fromLatin1(path.constData())).local8Bit();
+ Q3CString tmp = QString::fromLatin1("PATH=%1").arg(QString::fromLatin1(path.constData())).local8Bit();
uint tmpSize = tmp.length() + 1;
envlist.resize( envlist.size() + tmpSize );
memcpy( envlist.data()+pos, tmp.data(), tmpSize );
diff --git a/src/qt3support/painting/q3paintengine_svg.cpp b/src/qt3support/painting/q3paintengine_svg.cpp
index 95528e8..22e0d49 100644
--- a/src/qt3support/painting/q3paintengine_svg.cpp
+++ b/src/qt3support/painting/q3paintengine_svg.cpp
@@ -263,7 +263,7 @@ void Q3SVGPaintEngine::updateClipPath(const QPainterPath &path, Qt::ClipOperatio
QDomElement e;
d->currentClip++;
e = d->doc.createElement(QLatin1String("clipPath"));
- e.setAttribute(QLatin1String("id"), QString(QLatin1String("clip%1")).arg(d->currentClip));
+ e.setAttribute(QLatin1String("id"), QString::fromLatin1("clip%1").arg(d->currentClip));
QDomElement path_element = d->doc.createElement(QLatin1String("path"));
path_element.setAttribute(QLatin1String("d"), qt_svg_compose_path(path));
@@ -509,14 +509,14 @@ bool Q3SVGPaintEngine::save(const QString &fileName)
int icount = 0;
ImageList::Iterator iit = d->images.begin();
for (; iit != d->images.end(); ++iit) {
- QString href = QString(QLatin1String("%1_%2.png")).arg(svgName).arg(icount);
+ QString href = QString::fromLatin1("%1_%2.png").arg(svgName).arg(icount);
(*iit).image.save(href, "PNG");
(*iit).element.setAttribute(QLatin1String("xlink:href"), href);
icount++;
}
PixmapList::Iterator pit = d->pixmaps.begin();
for (; pit != d->pixmaps.end(); ++pit) {
- QString href = QString(QLatin1String("%1_%2.png")).arg(svgName).arg(icount);
+ QString href = QString::fromLatin1("%1_%2.png").arg(svgName).arg(icount);
(*pit).pixmap.save(href, "PNG");
(*pit).element.setAttribute(QLatin1String("xlink:href"), href);
icount++;
@@ -592,7 +592,7 @@ void Q3SVGPaintEnginePrivate::appendChild(QDomElement &e, QPicturePrivate::Paint
if (c == QPicturePrivate::PdcSetClipRegion || c == QPicturePrivate::PdcSetClipPath) {
QDomElement ne;
ne = doc.createElement(QLatin1String("g"));
- ne.setAttribute(QLatin1String("style"), QString(QLatin1String("clip-path:url(#clip%1)")).arg(currentClip));
+ ne.setAttribute(QLatin1String("style"), QString::fromLatin1("clip-path:url(#clip%1)").arg(currentClip));
if (dirtyTransform) {
applyTransform(&ne);
dirtyTransform = false;
@@ -621,12 +621,12 @@ void Q3SVGPaintEnginePrivate::applyStyle(QDomElement *e, QPicturePrivate::PaintC
if (c == QPicturePrivate::PdcDrawText2 || c == QPicturePrivate::PdcDrawText2Formatted) {
// QPainter has a reversed understanding of pen/stroke vs.
// brush/fill for text
- s += QString(QLatin1String("fill:rgb(%1,%2,%3);")).arg(pcol.red()).arg(pcol.green()).arg(pcol.blue());
- s += QString(QLatin1String("stroke-width:0;"));
+ s += QString::fromLatin1("fill:rgb(%1,%2,%3);").arg(pcol.red()).arg(pcol.green()).arg(pcol.blue());
+ s += QLatin1String("stroke-width:0;");
QFont f = cfont;
QFontInfo fi(f);
- s += QString(QLatin1String("font-size:%1;")).arg(fi.pointSize());
- s += QString(QLatin1String("font-style:%1;")).arg(f.italic() ? QLatin1String("italic") : QLatin1String("normal"));
+ s += QString::fromLatin1("font-size:%1;").arg(fi.pointSize());
+ s += QString::fromLatin1("font-style:%1;").arg(f.italic() ? QLatin1String("italic") : QLatin1String("normal"));
// not a very scientific distribution
QString fw;
if (f.weight() <= QFont::Light)
@@ -641,32 +641,32 @@ void Q3SVGPaintEnginePrivate::applyStyle(QDomElement *e, QPicturePrivate::PaintC
fw = QLatin1String("800");
else
fw = QLatin1String("900");
- s += QString(QLatin1String("font-weight:%1;")).arg(fw);
- s += QString(QLatin1String("font-family:%1;")).arg(f.family());
+ s += QString::fromLatin1("font-weight:%1;").arg(fw);
+ s += QString::fromLatin1("font-family:%1;").arg(f.family());
} else {
- s += QString(QLatin1String("stroke:rgb(%1,%2,%3);")).arg(pcol.red()).arg(pcol.green()).arg(pcol.blue());
+ s += QString::fromLatin1("stroke:rgb(%1,%2,%3);").arg(pcol.red()).arg(pcol.green()).arg(pcol.blue());
if (pcol.alpha() != 255)
- s += QString(QLatin1String("stroke-opacity:%1;")).arg(pcol.alpha()/255.0);
+ s += QString::fromLatin1("stroke-opacity:%1;").arg(pcol.alpha()/255.0);
if (bcol.alpha() != 255)
- s += QString(QLatin1String("fill-opacity:%1;")).arg(bcol.alpha()/255.0);
+ s += QString::fromLatin1("fill-opacity:%1;").arg(bcol.alpha()/255.0);
double pw = cpen.width();
if (pw == 0 && cpen.style() != Qt::NoPen)
pw = 0.9;
if (c == QPicturePrivate::PdcDrawLine)
pw /= (qAbs(worldMatrix.m11()) + qAbs(worldMatrix.m22())) / 2.0;
- s += QString(QLatin1String("stroke-width:%1;")).arg(pw);
+ s += QString::fromLatin1("stroke-width:%1;").arg(pw);
if (cpen.style() == Qt::DashLine)
- s+= QString(QLatin1String("stroke-dasharray:18,6;"));
+ s+= QLatin1String("stroke-dasharray:18,6;");
else if (cpen.style() == Qt::DotLine)
- s+= QString(QLatin1String("stroke-dasharray:3;"));
+ s+= QLatin1String("stroke-dasharray:3;");
else if (cpen.style() == Qt::DashDotLine)
- s+= QString(QLatin1String("stroke-dasharray:9,6,3,6;"));
+ s+= QLatin1String("stroke-dasharray:9,6,3,6;");
else if (cpen.style() == Qt::DashDotDotLine)
- s+= QString(QLatin1String("stroke-dasharray:9,3,3;"));
+ s+= QLatin1String("stroke-dasharray:9,3,3;");
if (cbrush.style() == Qt::NoBrush || c == QPicturePrivate::PdcDrawPolyline || c == QPicturePrivate::PdcDrawCubicBezier)
s += QLatin1String("fill:none;"); // Qt polylines use no brush, neither do Beziers
else
- s += QString(QLatin1String("fill:rgb(%1,%2,%3);")).arg(bcol.red()).arg(bcol.green()).arg(bcol.blue());
+ s += QString::fromLatin1("fill:rgb(%1,%2,%3);").arg(bcol.red()).arg(bcol.green()).arg(bcol.blue());
}
e->setAttribute(QLatin1String("style"), s);
}
@@ -679,13 +679,13 @@ void Q3SVGPaintEnginePrivate::applyTransform(QDomElement *e) const
bool rot = (m.m11() != 1.0 || m.m12() != 0.0 ||
m.m21() != 0.0 || m.m22() != 1.0);
if (!rot && (m.dx() != 0.0 || m.dy() != 0.0)) {
- s = QString(QLatin1String("translate(%1,%2)")).arg(m.dx()).arg(m.dy());
+ s = QString::fromLatin1("translate(%1,%2)").arg(m.dx()).arg(m.dy());
} else if (rot) {
if (m.m12() == 0.0 && m.m21() == 0.0 &&
m.dx() == 0.0 && m.dy() == 0.0)
- s = QString(QLatin1String("scale(%1,%2)")).arg(m.m11()).arg(m.m22());
+ s = QString::fromLatin1("scale(%1,%2)").arg(m.m11()).arg(m.m22());
else
- s = QString(QLatin1String("matrix(%1,%2,%3,%4,%5,%6)"))
+ s = QString::fromLatin1("matrix(%1,%2,%3,%4,%5,%6)")
.arg(m.m11()).arg(m.m12())
.arg(m.m21()).arg(m.m22())
.arg(m.dx()).arg(m.dy());
@@ -730,9 +730,9 @@ bool Q3SVGPaintEngine::play(QPainter *pt)
d->brect.setX(x);
d->brect.setY(y);
QString wstr = attr.contains(QLatin1String("width"))
- ? attr.namedItem(QLatin1String("width")).nodeValue() : QString(QLatin1String("100%"));
+ ? attr.namedItem(QLatin1String("width")).nodeValue() : QString::fromLatin1("100%");
QString hstr = attr.contains(QLatin1String("height"))
- ? attr.namedItem(QLatin1String("height")).nodeValue() : QString(QLatin1String("100%"));
+ ? attr.namedItem(QLatin1String("height")).nodeValue() : QString::fromLatin1("100%");
double width = d->parseLen(wstr, 0, true);
double height = d->parseLen(hstr, 0, false);
// SVG doesn't respect x and y. But we want a proper bounding rect.
diff --git a/src/qt3support/text/q3richtext.cpp b/src/qt3support/text/q3richtext.cpp
index e508001..d02f961 100644
--- a/src/qt3support/text/q3richtext.cpp
+++ b/src/qt3support/text/q3richtext.cpp
@@ -1678,7 +1678,7 @@ void Q3TextDocument::setRichTextInternal(const QString &text, Q3TextCursor* curs
if (curtag.style->displayMode() == Q3StyleSheetItem::DisplayListItem) {
// we are in a li and a new block comes along
- if (nstyle->name() == QString(QLatin1String("ul")) || nstyle->name() == QLatin1String("ol"))
+ if (nstyle->name() == QLatin1String("ul") || nstyle->name() == QLatin1String("ol"))
hasNewPar = false; // we want an empty li (like most browsers)
if (!hasNewPar) {
/* do not add new blocks inside
@@ -1857,7 +1857,7 @@ void Q3TextDocument::setRichTextInternal(const QString &text, Q3TextCursor* curs
curtag.format = curtag.format.makeTextFormat(nstyle, attr, scaleFontsFactor);
if (nstyle->isAnchor()) {
if (!anchorName.isEmpty())
- anchorName += QLatin1String("#") + attr[QLatin1String("name")];
+ anchorName += QLatin1Char('#') + attr[QLatin1String("name")];
else
anchorName = attr[QLatin1String("name")];
curtag.anchorHref = attr[QLatin1String("href")];
@@ -2436,7 +2436,7 @@ QString Q3TextDocument::richText() const
list_type = QLatin1String(" type=") + list_style_to_string(p->listStyle());
for (int i = pastListDepth; i < listDepth; i++) {
s += list_is_ordered(p->listStyle()) ? QLatin1String("<ol") : QLatin1String("<ul");
- s += list_type + QLatin1String(">");
+ s += list_type + QLatin1Char('>');
}
} else {
s += QLatin1Char('\n');
@@ -2463,7 +2463,7 @@ QString Q3TextDocument::richText() const
s += margin_to_string(item_li, p->utm, p->ubm, p->ulm, p->urm, p->uflm);
s += list_value_to_string(p->listValue());
s += direction_to_string(p->direction());
- s += QLatin1String(">");
+ s += QLatin1Char('>');
s += ps;
s += QLatin1String("</li>");
} else if (p->listDepth()) {
@@ -2471,7 +2471,7 @@ QString Q3TextDocument::richText() const
s += align_to_string(p->alignment());
s += margin_to_string(item_div, p->utm, p->ubm, p->ulm, p->urm, p->uflm);
s += direction_to_string(p->direction());
- s += QLatin1String(">");
+ s += QLatin1Char('>');
s += ps;
s += QLatin1String("</div>");
} else {
@@ -2480,7 +2480,7 @@ QString Q3TextDocument::richText() const
s += align_to_string(p->alignment());
s += margin_to_string(item_p, p->utm, p->ubm, p->ulm, p->urm, p->uflm);
s += direction_to_string(p->direction());
- s += QLatin1String(">");
+ s += QLatin1Char('>');
s += ps;
s += QLatin1String("</p>");
}
@@ -6667,7 +6667,7 @@ Q3TextImage::Q3TextImage(Q3TextDocument *p, const QMap<QString, QString> &attr,
imageName = attr[QLatin1String("source")];
if (!imageName.isEmpty()) {
- imgId = QString(QLatin1String("%1,%2,%3,%4")).arg(imageName).arg(width).arg(height).arg((ulong)&factory);
+ imgId = QString::fromLatin1("%1,%2,%3,%4").arg(imageName).arg(width).arg(height).arg((ulong)&factory);
if (!pixmap_map)
pixmap_map = new QMap<QString, QPixmapInt>;
if (pixmap_map->contains(imgId)) {
@@ -6761,13 +6761,13 @@ QString Q3TextImage::richText() const
s += QLatin1String("<img ");
QMap<QString, QString>::ConstIterator it = attributes.begin();
for (; it != attributes.end(); ++it) {
- s += it.key() + QLatin1String("=");
+ s += it.key() + QLatin1Char('=');
if ((*it).contains(QLatin1Char(' ')))
- s += QLatin1String("\"") + *it + QLatin1String("\" ");
+ s += QLatin1Char('\"') + *it + QLatin1String("\" ");
else
- s += *it + QLatin1String(" ");
+ s += *it + QLatin1Char(' ');
}
- s += QLatin1String(">");
+ s += QLatin1Char('>');
return s;
}
@@ -7722,7 +7722,7 @@ QString Q3TextTable::richText() const
s = QLatin1String("<table ");
QMap<QString, QString>::ConstIterator it = attributes.begin();
for (; it != attributes.end(); ++it)
- s += it.key() + QLatin1String("=") + *it + QLatin1String(" ");
+ s += it.key() + QLatin1Char('=') + *it + QLatin1Char(' ');
s += QLatin1String(">\n");
int lastRow = -1;
@@ -7739,8 +7739,8 @@ QString Q3TextTable::richText() const
s += QLatin1String("<td");
it = cell->attributes.constBegin();
for (; it != cell->attributes.constEnd(); ++it)
- s += QLatin1String(" ") + it.key() + QLatin1String("=") + *it;
- s += QLatin1String(">");
+ s += QLatin1Char(' ') + it.key() + QLatin1Char('=') + *it;
+ s += QLatin1Char('>');
s += cell->richText()->richText();
s += QLatin1String("</td>");
}
diff --git a/src/qt3support/text/q3textedit.cpp b/src/qt3support/text/q3textedit.cpp
index 7577dce..d1db1e4 100644
--- a/src/qt3support/text/q3textedit.cpp
+++ b/src/qt3support/text/q3textedit.cpp
@@ -77,7 +77,7 @@
#include <qkeysequence.h>
#define ACCEL_KEY(k) QLatin1Char('\t') + QString(QKeySequence(Qt::CTRL | Qt::Key_ ## k))
#else
-#define ACCEL_KEY(k) QLatin1Char('\t' )+ QString(QLatin1String("Ctrl+" #k))
+#define ACCEL_KEY(k) QLatin1Char('\t' )+ QString::fromLatin1("Ctrl+" #k)
#endif
#ifdef QT_TEXTEDIT_OPTIMIZATION
@@ -6625,7 +6625,7 @@ void Q3TextEdit::optimSetTextFormat(Q3TextDocument * td, Q3TextCursor * cur,
}
if (tag) {
QString col = tag->tag.simplified();
- if (col.left(10) == QLatin1String("font color")) {
+ if (col.startsWith(QLatin1String("font color"))) {
int i = col.indexOf(QLatin1Char('='), 10);
col = col.mid(i + 1).simplified();
if (col[0] == QLatin1Char('\"'))
diff --git a/src/qt3support/widgets/q3action.cpp b/src/qt3support/widgets/q3action.cpp
index 311212a..caca47b 100644
--- a/src/qt3support/widgets/q3action.cpp
+++ b/src/qt3support/widgets/q3action.cpp
@@ -415,7 +415,7 @@ static QString qt_stripMenuText(QString s)
s.remove(QLatin1String("..."));
s.remove(QLatin1Char('&'));
return s.trimmed();
-};
+}
/*!
Constructs an action called \a name with parent \a parent.
diff --git a/src/qt3support/widgets/q3mainwindow.cpp b/src/qt3support/widgets/q3mainwindow.cpp
index 2ee3bdc..ae80321 100644
--- a/src/qt3support/widgets/q3mainwindow.cpp
+++ b/src/qt3support/widgets/q3mainwindow.cpp
@@ -2261,7 +2261,7 @@ static void saveDockArea(QTextStream &ts, Q3DockArea *a)
for (int i = 0; i < l.size(); ++i) {
Q3DockWindow *dw = l.at(i);
ts << QString(dw->windowTitle());
- ts << ",";
+ ts << ',';
}
ts << endl;
ts << *a;
@@ -2287,7 +2287,7 @@ QTextStream &operator<<(QTextStream &ts, const Q3MainWindow &mainWindow)
for (int i = 0; i < l.size(); ++i) {
Q3DockWindow *dw = l.at(i);
ts << dw->windowTitle();
- ts << ",";
+ ts << ',';
}
ts << endl;
@@ -2295,17 +2295,17 @@ QTextStream &operator<<(QTextStream &ts, const Q3MainWindow &mainWindow)
for (int i = 0; i < l.size(); ++i) {
Q3DockWindow *dw = l.at(i);
ts << dw->windowTitle();
- ts << ",";
+ ts << ',';
}
ts << endl;
for (int i = 0; i < l.size(); ++i) {
Q3DockWindow *dw = l.at(i);
- ts << "[" << dw->windowTitle() << ","
- << (int)dw->geometry().x() << ","
- << (int)dw->geometry().y() << ","
- << (int)dw->geometry().width() << ","
- << (int)dw->geometry().height() << ","
- << (int)dw->isVisible() << "]";
+ ts << '[' << dw->windowTitle() << ','
+ << (int)dw->geometry().x() << ','
+ << (int)dw->geometry().y() << ','
+ << (int)dw->geometry().width() << ','
+ << (int)dw->geometry().height() << ','
+ << (int)dw->isVisible() << ']';
}
ts << endl;
diff --git a/src/script/qscriptcontext.cpp b/src/script/qscriptcontext.cpp
index 0b72342..4db32d0 100644
--- a/src/script/qscriptcontext.cpp
+++ b/src/script/qscriptcontext.cpp
@@ -467,7 +467,7 @@ QString QScriptContext::toString() const
QScriptValue arg = argument(i);
result.append(safeValueToString(arg));
}
- result.append(QLatin1String(")"));
+ result.append(QLatin1Char(')'));
QString fileName = info.fileName();
int lineNumber = info.lineNumber();
diff --git a/src/script/qscriptcontext_p.cpp b/src/script/qscriptcontext_p.cpp
index 199c9d4..f19ba9c 100644
--- a/src/script/qscriptcontext_p.cpp
+++ b/src/script/qscriptcontext_p.cpp
@@ -841,7 +841,7 @@ Ltop:
flags = iPtr->operand[1].m_int_value;
#ifndef QT_NO_REGEXP
if (flags != 0) {
- literal += QLatin1String("/");
+ literal += QLatin1Char('/');
literal += QString::number(flags);
}
#endif
@@ -2396,10 +2396,10 @@ QStringList QScriptContextPrivate::backtrace() const
s += QLatin1String("<global>");
}
}
- s += QLatin1String("(");
+ s += QLatin1Char('(');
for (int i = 0; i < ctx->argc; ++i) {
if (i > 0)
- s += QLatin1String(",");
+ s += QLatin1Char(',');
QScriptValueImpl arg = ctx->args[i];
if (arg.isObject())
s += QLatin1String("[object Object]"); // don't do a function call
diff --git a/src/script/qscriptecmaerror.cpp b/src/script/qscriptecmaerror.cpp
index fc39bf9..0dde68c 100644
--- a/src/script/qscriptecmaerror.cpp
+++ b/src/script/qscriptecmaerror.cpp
@@ -318,18 +318,18 @@ QStringList Error::backtrace(const QScriptValueImpl &error)
} else {
s += functionName;
}
- s += QLatin1String("(");
+ s += QLatin1Char('(');
QScriptValueImpl arguments = frame.property(QLatin1String("arguments"));
if (arguments.isObject()) {
int argCount = arguments.property(QLatin1String("length")).toInt32();
for (int j = 0; j < argCount; ++j) {
if (j > 0)
- s += QLatin1String(",");
+ s += QLatin1Char(',');
s += arguments.property(j).toString();
}
}
s += QLatin1String(")@") + o.property(QLatin1String("fileName")).toString()
- + QLatin1String(":") + o.property(QLatin1String("lineNumber")).toString();
+ + QLatin1Char(':') + o.property(QLatin1String("lineNumber")).toString();
result.append(s);
}
return result;
diff --git a/src/script/qscriptecmafunction.cpp b/src/script/qscriptecmafunction.cpp
index ec45ae4..a1e5b58 100644
--- a/src/script/qscriptecmafunction.cpp
+++ b/src/script/qscriptecmafunction.cpp
@@ -197,7 +197,7 @@ QString Function::buildFunction(QScriptContextPrivate *context)
// the formals
for (int i = 0; i < argc - 1; ++i) {
if (i != 0)
- code += QLatin1String(",");
+ code += QLatin1Char(',');
code += context->argument(i).toString();
}
diff --git a/src/script/qscriptecmaglobal.cpp b/src/script/qscriptecmaglobal.cpp
index da7ab9e..b5cf675 100644
--- a/src/script/qscriptecmaglobal.cpp
+++ b/src/script/qscriptecmaglobal.cpp
@@ -296,7 +296,7 @@ public:
QString result;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i != 0)
- result.append(QLatin1String(" "));
+ result.append(QLatin1Char(' '));
QString s = context->argument(i).toString();
if (context->state() == QScriptContext::ExceptionState)
diff --git a/src/script/qscriptecmaobject.cpp b/src/script/qscriptecmaobject.cpp
index 694f479..c4a1b08 100644
--- a/src/script/qscriptecmaobject.cpp
+++ b/src/script/qscriptecmaobject.cpp
@@ -113,7 +113,7 @@ QScriptValueImpl Object::method_toString(QScriptContextPrivate *context, QScript
QString s = QLatin1String("[object ");
QScriptValueImpl self = context->thisObject();
s += self.classInfo()->name();
- s += QLatin1String("]");
+ s += QLatin1Char(']');
return (QScriptValueImpl(eng, s));
}
diff --git a/src/script/qscriptengine.cpp b/src/script/qscriptengine.cpp
index 2a36104..8441842 100644
--- a/src/script/qscriptengine.cpp
+++ b/src/script/qscriptengine.cpp
@@ -583,7 +583,7 @@ QScriptValue QScriptEngine::newQObject(const QScriptValue &scriptObject,
QScriptValuePrivate *p = QScriptValuePrivate::get(scriptObject);
if (!p || !p->value.isObject())
return newQObject(qtObject, ownership, options);
- if (p->value.isVariant()) {
+ if (p->value.isQObject()) {
QScript::ExtQObject::Instance *data;
data = d->qobjectConstructor->get(p->value);
Q_ASSERT(data != 0);
diff --git a/src/script/qscriptengine_p.cpp b/src/script/qscriptengine_p.cpp
index 27b8101..ad26550 100644
--- a/src/script/qscriptengine_p.cpp
+++ b/src/script/qscriptengine_p.cpp
@@ -1662,6 +1662,11 @@ bool QScriptEnginePrivate::convert(const QScriptValueImpl &value,
return false;
}
+QScriptEngine::DemarshalFunction QScriptEnginePrivate::demarshalFunction(int type) const
+{
+ return m_customTypes.value(type).demarshal;
+}
+
QScriptValuePrivate *QScriptEnginePrivate::registerValue(const QScriptValueImpl &value)
{
if (value.isString()) {
diff --git a/src/script/qscriptenginefwd_p.h b/src/script/qscriptenginefwd_p.h
index 2ea66c5..855317c 100644
--- a/src/script/qscriptenginefwd_p.h
+++ b/src/script/qscriptenginefwd_p.h
@@ -350,6 +350,7 @@ public:
QScriptValueImpl create(int type, const void *ptr);
static bool convert(const QScriptValueImpl &value, int type, void *ptr,
QScriptEnginePrivate *eng);
+ QScriptEngine::DemarshalFunction demarshalFunction(int type) const;
QScriptValueImpl arrayFromStringList(const QStringList &lst);
static QStringList stringListFromArray(const QScriptValueImpl &arr);
diff --git a/src/script/qscriptextqobject.cpp b/src/script/qscriptextqobject.cpp
index d18c3da..47c04d4 100644
--- a/src/script/qscriptextqobject.cpp
+++ b/src/script/qscriptextqobject.cpp
@@ -425,7 +425,7 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType
matchDistance += 10;
}
}
- } else if (actual.isNumber()) {
+ } else if (actual.isNumber() || actual.isString()) {
// see if it's an enum value
QMetaEnum m;
if (argType.isMetaEnum()) {
@@ -436,11 +436,21 @@ static void callQtMethod(QScriptContextPrivate *context, QMetaMethod::MethodType
m = meta->enumerator(mi);
}
if (m.isValid()) {
- int ival = actual.toInt32();
- if (m.valueToKey(ival) != 0) {
- qVariantSetValue(v, ival);
- converted = true;
- matchDistance += 10;
+ if (actual.isNumber()) {
+ int ival = actual.toInt32();
+ if (m.valueToKey(ival) != 0) {
+ qVariantSetValue(v, ival);
+ converted = true;
+ matchDistance += 10;
+ }
+ } else {
+ QString sval = actual.toString();
+ int ival = m.keyToValue(sval.toLatin1());
+ if (ival != -1) {
+ qVariantSetValue(v, ival);
+ converted = true;
+ matchDistance += 10;
+ }
}
}
}
@@ -1657,12 +1667,27 @@ void QScript::QObjectConnectionManager::execute(int slotIndex, void **argv)
activation_data->m_members[i].object(nameId, i,
QScriptValue::Undeletable
| QScriptValue::SkipInEnumeration);
+ QScriptValueImpl actual;
if (i < argc) {
- int argType = QMetaType::type(parameterTypes.at(i));
- activation_data->m_values[i] = eng->create(argType, argv[i + 1]);
+ void *arg = argv[i + 1];
+ QByteArray typeName = parameterTypes.at(i);
+ int argType = QMetaType::type(typeName);
+ if (!argType) {
+ if (typeName == "QVariant") {
+ actual = eng->valueFromVariant(*reinterpret_cast<QVariant*>(arg));
+ } else {
+ qWarning("QScriptEngine: Unable to handle unregistered datatype '%s' "
+ "when invoking handler of signal %s::%s",
+ typeName.constData(), meta->className(), method.signature());
+ actual = eng->undefinedValue();
+ }
+ } else {
+ actual = eng->create(argType, arg);
+ }
} else {
- activation_data->m_values[i] = eng->undefinedValue();
+ actual = eng->undefinedValue();
}
+ activation_data->m_values[i] = actual;
}
QScriptValueImpl senderObject;
@@ -1809,7 +1834,16 @@ void QScript::QtPropertyFunction::execute(QScriptContextPrivate *context)
}
} else {
// set
- QVariant v = variantFromValue(eng_p, prop.userType(), context->argument(0));
+ QScriptValueImpl arg = context->argument(0);
+ QVariant v;
+ if (prop.isEnumType() && arg.isString()
+ && !eng_p->demarshalFunction(prop.userType())) {
+ // give QMetaProperty::write() a chance to convert from
+ // string to enum value
+ v = arg.toString();
+ } else {
+ v = variantFromValue(eng_p, prop.userType(), arg);
+ }
QScriptable *scriptable = scriptableFromQObject(qobject);
QScriptEngine *oldEngine = 0;
@@ -1864,8 +1898,6 @@ void QScript::QtFunction::execute(QScriptContextPrivate *context)
return;
}
- QScriptValueImpl result = eng_p->undefinedValue();
-
const QMetaObject *meta = qobj->metaObject();
QObject *thisQObject = context->thisObject().toQObject();
diff --git a/src/script/qscriptparser.cpp b/src/script/qscriptparser.cpp
index 0b04df1..7408ec5 100644
--- a/src/script/qscriptparser.cpp
+++ b/src/script/qscriptparser.cpp
@@ -1148,9 +1148,9 @@ case 266: {
error_message += QLatin1String (", ");
first = false;
- error_message += QLatin1String("`");
+ error_message += QLatin1Char('`');
error_message += QLatin1String (spell [expected_tokens [s]]);
- error_message += QLatin1String("'");
+ error_message += QLatin1Char('\'');
}
}
diff --git a/src/script/qscriptprettypretty.cpp b/src/script/qscriptprettypretty.cpp
index 6ee1e55..b221b0a 100644
--- a/src/script/qscriptprettypretty.cpp
+++ b/src/script/qscriptprettypretty.cpp
@@ -73,13 +73,13 @@ PrettyPretty::~PrettyPretty()
void PrettyPretty::acceptAsBlock(AST::Node *node)
{
- out << "{";
+ out << '{';
pushIndentLevel();
newlineAndIndent();
accept(node);
popIndentLevel();
newlineAndIndent();
- out << "}";
+ out << '}';
}
int PrettyPretty::operatorPrecedenceLevel(int op)
@@ -230,8 +230,8 @@ void PrettyPretty::endVisit(AST::FalseLiteral *node)
bool PrettyPretty::visit(AST::StringLiteral *node)
{
QString lit = QScriptEnginePrivate::toString(node->value);
- lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
- out << "\"" << lit << "\"";
+ lit.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
+ out << '\"' << lit << '\"';
return false;
}
@@ -253,7 +253,7 @@ void PrettyPretty::endVisit(AST::NumericLiteral *node)
bool PrettyPretty::visit(AST::RegExpLiteral *node)
{
- out << "/" << QScriptEnginePrivate::toString(node->pattern) << "/";
+ out << '/' << QScriptEnginePrivate::toString(node->pattern) << '/';
if (node->flags)
out << QScript::Ecma::RegExp::flagsToString(node->flags);
@@ -267,10 +267,10 @@ void PrettyPretty::endVisit(AST::RegExpLiteral *node)
bool PrettyPretty::visit(AST::ArrayLiteral *node)
{
- out << "[";
+ out << '[';
accept(node->elements);
accept(node->elision);
- out << "]";
+ out << ']';
return false;
}
@@ -281,7 +281,7 @@ void PrettyPretty::endVisit(AST::ArrayLiteral *node)
bool PrettyPretty::visit(AST::ObjectLiteral *node)
{
- out << "{";
+ out << '{';
if (node->properties) {
pushIndentLevel();
AST::PropertyNameAndValueList *prop;
@@ -289,12 +289,12 @@ bool PrettyPretty::visit(AST::ObjectLiteral *node)
newlineAndIndent();
accept(prop);
if (prop->next)
- out << ",";
+ out << ',';
}
popIndentLevel();
newlineAndIndent();
}
- out << "}";
+ out << '}';
return false;
}
@@ -384,9 +384,9 @@ void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node)
bool PrettyPretty::visit(AST::ArrayMemberExpression *node)
{
accept(node->base);
- out << "[";
+ out << '[';
accept(node->expression);
- out << "]";
+ out << ']';
return false;
}
@@ -398,7 +398,7 @@ void PrettyPretty::endVisit(AST::ArrayMemberExpression *node)
bool PrettyPretty::visit(AST::FieldMemberExpression *node)
{
accept(node->base);
- out << "." << QScriptEnginePrivate::toString(node->name);
+ out << '.' << QScriptEnginePrivate::toString(node->name);
return false;
}
@@ -411,9 +411,9 @@ bool PrettyPretty::visit(AST::NewMemberExpression *node)
{
out << "new ";
accept(node->base);
- out << "(";
+ out << '(';
accept(node->arguments);
- out << ")";
+ out << ')';
return false;
}
@@ -437,9 +437,9 @@ void PrettyPretty::endVisit(AST::NewExpression *node)
bool PrettyPretty::visit(AST::CallExpression *node)
{
accept(node->base);
- out << "(";
+ out << '(';
accept(node->arguments);
- out << ")";
+ out << ')';
return false;
}
@@ -549,13 +549,13 @@ void PrettyPretty::endVisit(AST::PreDecrementExpression *node)
bool PrettyPretty::visit(AST::UnaryPlusExpression *node)
{
- out << "+";
+ out << '+';
bool needParens = (node->expression->binaryExpressionCast() != 0);
if (needParens)
- out << "(";
+ out << '(';
accept(node->expression);
if (needParens)
- out << ")";
+ out << ')';
return false;
}
@@ -566,13 +566,13 @@ void PrettyPretty::endVisit(AST::UnaryPlusExpression *node)
bool PrettyPretty::visit(AST::UnaryMinusExpression *node)
{
- out << "-";
+ out << '-';
bool needParens = (node->expression->binaryExpressionCast() != 0);
if (needParens)
- out << "(";
+ out << '(';
accept(node->expression);
if (needParens)
- out << ")";
+ out << ')';
return false;
}
@@ -583,13 +583,13 @@ void PrettyPretty::endVisit(AST::UnaryMinusExpression *node)
bool PrettyPretty::visit(AST::TildeExpression *node)
{
- out << "~";
+ out << '~';
bool needParens = (node->expression->binaryExpressionCast() != 0);
if (needParens)
- out << "(";
+ out << '(';
accept(node->expression);
if (needParens)
- out << ")";
+ out << ')';
return false;
}
@@ -600,13 +600,13 @@ void PrettyPretty::endVisit(AST::TildeExpression *node)
bool PrettyPretty::visit(AST::NotExpression *node)
{
- out << "!";
+ out << '!';
bool needParens = (node->expression->binaryExpressionCast() != 0);
if (needParens)
- out << "(";
+ out << '(';
accept(node->expression);
if (needParens)
- out << ")";
+ out << ')';
return false;
}
@@ -620,10 +620,10 @@ bool PrettyPretty::visit(AST::BinaryExpression *node)
bool needParens = node->left->binaryExpressionCast()
&& (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0);
if (needParens)
- out << "(";
+ out << '(';
accept(node->left);
if (needParens)
- out << ")";
+ out << ')';
QString s;
switch (node->op) {
case QSOperator::Add:
@@ -699,14 +699,14 @@ bool PrettyPretty::visit(AST::BinaryExpression *node)
default:
Q_ASSERT (0);
}
- out << " " << s << " ";
+ out << ' ' << s << ' ';
needParens = node->right->binaryExpressionCast()
&& (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0);
if (needParens)
- out << "(";
+ out << '(';
accept(node->right);
if (needParens)
- out << ")";
+ out << ')';
return false;
}
@@ -798,7 +798,7 @@ bool PrettyPretty::visit(AST::VariableStatement *node)
void PrettyPretty::endVisit(AST::VariableStatement *node)
{
Q_UNUSED(node);
- out << ";";
+ out << ';';
}
bool PrettyPretty::visit(AST::VariableDeclaration *node)
@@ -819,7 +819,7 @@ void PrettyPretty::endVisit(AST::VariableDeclaration *node)
bool PrettyPretty::visit(AST::EmptyStatement *node)
{
Q_UNUSED(node);
- out << ";";
+ out << ';';
return true;
}
@@ -831,7 +831,7 @@ void PrettyPretty::endVisit(AST::EmptyStatement *node)
bool PrettyPretty::visit(AST::ExpressionStatement *node)
{
accept(node->expression);
- out << ";";
+ out << ';';
return false;
}
@@ -959,9 +959,9 @@ bool PrettyPretty::visit(AST::ContinueStatement *node)
{
out << "continue";
if (node->label) {
- out << " " << QScriptEnginePrivate::toString(node->label);
+ out << ' ' << QScriptEnginePrivate::toString(node->label);
}
- out << ";";
+ out << ';';
return false;
}
@@ -974,9 +974,9 @@ bool PrettyPretty::visit(AST::BreakStatement *node)
{
out << "break";
if (node->label) {
- out << " " << QScriptEnginePrivate::toString(node->label);
+ out << ' ' << QScriptEnginePrivate::toString(node->label);
}
- out << ";";
+ out << ';';
return false;
}
@@ -989,10 +989,10 @@ bool PrettyPretty::visit(AST::ReturnStatement *node)
{
out << "return";
if (node->expression) {
- out << " ";
+ out << ' ';
accept(node->expression);
}
- out << ";";
+ out << ';';
return false;
}
@@ -1067,7 +1067,7 @@ bool PrettyPretty::visit(AST::CaseClause *node)
{
out << "case ";
accept(node->expression);
- out << ":";
+ out << ':';
if (node->statements) {
newlineAndIndent();
accept(node->statements);
@@ -1109,7 +1109,7 @@ bool PrettyPretty::visit(AST::ThrowStatement *node)
Q_UNUSED(node);
out << "throw ";
accept(node->expression);
- out << ";";
+ out << ';';
return false;
}
@@ -1166,10 +1166,10 @@ bool PrettyPretty::visit(AST::FunctionDeclaration *node)
out << "function";
if (node->name)
- out << " " << QScriptEnginePrivate::toString(node->name);
+ out << ' ' << QScriptEnginePrivate::toString(node->name);
// the arguments
- out << "(";
+ out << '(';
for (AST::FormalParameterList *it = node->formals; it; it = it->next) {
if (it->name)
out << QScriptEnginePrivate::toString(it->name);
@@ -1177,7 +1177,7 @@ bool PrettyPretty::visit(AST::FunctionDeclaration *node)
if (it->next)
out << ", ";
}
- out << ")";
+ out << ')';
// the function body
out << " {";
@@ -1190,7 +1190,7 @@ bool PrettyPretty::visit(AST::FunctionDeclaration *node)
newlineAndIndent();
}
- out << "}";
+ out << '}';
return false;
}
@@ -1205,10 +1205,10 @@ bool PrettyPretty::visit(AST::FunctionExpression *node)
out << "function";
if (node->name)
- out << " " << QScriptEnginePrivate::toString(node->name);
+ out << ' ' << QScriptEnginePrivate::toString(node->name);
// the arguments
- out << "(";
+ out << '(';
for (AST::FormalParameterList *it = node->formals; it; it = it->next) {
if (it->name)
out << QScriptEnginePrivate::toString(it->name);
@@ -1216,7 +1216,7 @@ bool PrettyPretty::visit(AST::FunctionExpression *node)
if (it->next)
out << ", ";
}
- out << ")";
+ out << ')';
// the function body
out << " {";
@@ -1229,7 +1229,7 @@ bool PrettyPretty::visit(AST::FunctionExpression *node)
newlineAndIndent();
}
- out << "}";
+ out << '}';
return false;
}
@@ -1320,7 +1320,7 @@ bool PrettyPretty::visit(AST::DebuggerStatement *node)
void PrettyPretty::endVisit(AST::DebuggerStatement *node)
{
Q_UNUSED(node);
- out << ";";
+ out << ';';
}
bool PrettyPretty::preVisit(AST::Node *node)
diff --git a/src/script/qscriptsyntaxchecker.cpp b/src/script/qscriptsyntaxchecker.cpp
index 9653bc1..74ca00f 100644
--- a/src/script/qscriptsyntaxchecker.cpp
+++ b/src/script/qscriptsyntaxchecker.cpp
@@ -186,9 +186,9 @@ SyntaxChecker::Result SyntaxChecker::checkSyntax(const QString &code)
error_message += QLatin1String (", ");
first = false;
- error_message += QLatin1String("`");
+ error_message += QLatin1Char('`');
error_message += QLatin1String (spell [expected_tokens [s]]);
- error_message += QLatin1String("'");
+ error_message += QLatin1Char('\'');
}
}
diff --git a/src/script/qscriptsyntaxchecker_p.h b/src/script/qscriptsyntaxchecker_p.h
index 0c02d24..18f0611 100644
--- a/src/script/qscriptsyntaxchecker_p.h
+++ b/src/script/qscriptsyntaxchecker_p.h
@@ -71,7 +71,7 @@ public:
enum State {
Error,
Intermediate,
- Valid,
+ Valid
};
struct Result {
diff --git a/src/script/qscriptvalue.cpp b/src/script/qscriptvalue.cpp
index 4282248..0f0b6f7 100644
--- a/src/script/qscriptvalue.cpp
+++ b/src/script/qscriptvalue.cpp
@@ -904,6 +904,7 @@ qsreal QScriptValue::toInteger() const
\row \o QObject Object \o A QVariant containing a pointer to the QObject.
\row \o Date Object \o A QVariant containing the date value (toDateTime()).
\row \o RegExp Object \o A QVariant containing the regular expression value (toRegExp()).
+ \row \o Array Object \o The array is converted to a QVariantList.
\row \o Object \o If the value is primitive, then the result is converted to a QVariant according to the above rules; otherwise, an invalid QVariant is returned.
\endtable
diff --git a/src/script/qscriptvalueimpl.cpp b/src/script/qscriptvalueimpl.cpp
index 15d1b8a..7c7b711 100644
--- a/src/script/qscriptvalueimpl.cpp
+++ b/src/script/qscriptvalueimpl.cpp
@@ -339,6 +339,8 @@ QVariant QScriptValueImpl::toVariant() const
if (isQObject())
return qVariantFromValue(toQObject());
#endif
+ if (isArray())
+ return QScriptEnginePrivate::variantListFromArray(*this);
QScriptValueImpl v = engine()->toPrimitive(*this);
if (!v.isObject())
@@ -395,7 +397,7 @@ QDebug &operator<<(QDebug &d, const QScriptValueImpl &object)
QScriptObject *od = object.objectValue();
for (int i=0; i<od->memberCount(); ++i) {
if (i != 0)
- d << ",";
+ d << ',';
QScript::Member m;
od->member(i, &m);
@@ -404,7 +406,7 @@ QDebug &operator<<(QDebug &d, const QScriptValueImpl &object)
d << object.engine()->toString(m.nameId());
QScriptValueImpl o;
od->get(m, &o);
- d.nospace() << QLatin1String(":")
+ d.nospace() << QLatin1Char(':')
<< (o.classInfo()
? o.classInfo()->name()
: QLatin1String("?"));
@@ -415,14 +417,14 @@ QDebug &operator<<(QDebug &d, const QScriptValueImpl &object)
QScriptValueImpl scope = object.scope();
while (scope.isValid()) {
Q_ASSERT(scope.isObject());
- d.nospace() << " " << scope.objectValue();
+ d.nospace() << ' ' << scope.objectValue();
scope = scope.scope();
}
- d.nospace() << "}";
+ d.nospace() << '}';
break;
}
- d << ")";
+ d << ')';
return d;
}
diff --git a/src/script/qscriptxmlgenerator.cpp b/src/script/qscriptxmlgenerator.cpp
index 131882b..163b60c 100644
--- a/src/script/qscriptxmlgenerator.cpp
+++ b/src/script/qscriptxmlgenerator.cpp
@@ -121,10 +121,10 @@ QTextStream &XmlGenerator::startTag(const QString &name, AST::Node *locationNode
{
pushIndentLevel();
newlineAndIndent();
- out << QLatin1String("<") << name;
+ out << QLatin1Char('<') << name;
if (locationNode)
- out << QLatin1String(" line=\"") << locationNode->startLine << QLatin1String("\"");
- out << QLatin1String(">");
+ out << QLatin1String(" line=\"") << locationNode->startLine << QLatin1Char('\"');
+ out << QLatin1Char('>');
return out;
}
@@ -132,7 +132,7 @@ QTextStream &XmlGenerator::endTag(const QString &name)
{
newlineAndIndent();
popIndentLevel();
- out << QLatin1String("</") << escape(name) << QLatin1String(">");
+ out << QLatin1String("</") << escape(name) << QLatin1Char('>');
return out;
}
@@ -233,7 +233,7 @@ void XmlGenerator::endVisit(AST::NumericLiteral *)
bool XmlGenerator::visit(AST::RegExpLiteral *node)
{
startTag(QLatin1String("regexp"));
- out << QLatin1String("/") << escape(QScriptEnginePrivate::toString(node->pattern)) << QLatin1String("/");
+ out << QLatin1Char('/') << escape(QScriptEnginePrivate::toString(node->pattern)) << QLatin1Char('/');
if (node->flags)
out << QScript::Ecma::RegExp::flagsToString(node->flags);
out << QLatin1String("</regexp>");
diff --git a/src/scripttools/debugging/debugging.pri b/src/scripttools/debugging/debugging.pri
index fa39e83..2082fd0 100644
--- a/src/scripttools/debugging/debugging.pri
+++ b/src/scripttools/debugging/debugging.pri
@@ -111,7 +111,8 @@ SOURCES += \
$$PWD/qscriptbreakpointswidget.cpp \
$$PWD/qscriptbreakpointsmodel.cpp \
$$PWD/qscripterrorlogwidgetinterface.cpp \
- $$PWD/qscripterrorlogwidget.cpp
+ $$PWD/qscripterrorlogwidget.cpp \
+ $$PWD/qscriptdebuggerstandardwidgetfactory.cpp
HEADERS += \
$$PWD/qscriptdebuggerconsolewidgetinterface_p_p.h \
@@ -148,7 +149,8 @@ HEADERS += \
$$PWD/qscripterrorlogwidgetinterface_p_p.h \
$$PWD/qscripterrorlogwidgetinterface_p.h \
$$PWD/qscripterrorlogwidget_p.h \
- $$PWD/qscriptdebuggerwidgetfactoryinterface_p.h
+ $$PWD/qscriptdebuggerwidgetfactoryinterface_p.h \
+ $$PWD/qscriptdebuggerstandardwidgetfactory_p.h
SOURCES += \
$$PWD/qscriptenginedebugger.cpp
diff --git a/src/scripttools/debugging/qscriptcompletiontask.cpp b/src/scripttools/debugging/qscriptcompletiontask.cpp
index 119b96a..e2034f3 100644
--- a/src/scripttools/debugging/qscriptcompletiontask.cpp
+++ b/src/scripttools/debugging/qscriptcompletiontask.cpp
@@ -44,12 +44,10 @@
#include "qscriptdebuggerconsole_p.h"
#include "qscriptdebuggerconsolecommand_p.h"
#include "qscriptdebuggerconsolecommandmanager_p.h"
-
-#include "qscriptenginedebuggerfrontend_p.h" // ### kill
-#include "qscriptdebuggerbackend_p.h" // ### kill
-#include <QtScript/qscriptcontext.h>
-#include <QtScript/qscriptvalue.h>
-#include <QtScript/qscriptvalueiterator.h>
+#include "qscriptdebuggercommandschedulerjob_p.h"
+#include "qscriptdebuggercommandschedulerfrontend_p.h"
+#include "qscriptdebuggerjobschedulerinterface_p.h"
+#include "qscriptdebuggerresponse_p.h"
#include "private/qobject_p.h"
@@ -67,11 +65,13 @@ public:
~QScriptCompletionTaskPrivate();
void completeScriptExpression();
+ void emitFinished();
QString contents;
int cursorPosition;
int frameIndex;
- QScriptDebuggerFrontend *frontend;
+ QScriptDebuggerCommandSchedulerInterface *commandScheduler;
+ QScriptDebuggerJobSchedulerInterface *jobScheduler;
QScriptDebuggerConsole *console;
};
@@ -83,28 +83,33 @@ QScriptCompletionTaskPrivate::~QScriptCompletionTaskPrivate()
{
}
-QScriptCompletionTask::QScriptCompletionTask(
- const QString &contents, int cursorPosition,
- int frameIndex, QScriptDebuggerFrontend *frontend,
- QScriptDebuggerConsole *console,
- QObject *parent)
- : QScriptCompletionTaskInterface(
- *new QScriptCompletionTaskPrivate, parent)
+class QScriptCompleteExpressionJob : public QScriptDebuggerCommandSchedulerJob
{
- Q_D(QScriptCompletionTask);
- d->contents = contents;
- d->cursorPosition = cursorPosition;
- if ((frameIndex == -1) && console)
- d->frameIndex = console->currentFrameIndex();
- else
- d->frameIndex = frameIndex;
- d->frontend = frontend;
- d->console = console;
-}
+public:
+ QScriptCompleteExpressionJob(int frameIndex, const QStringList &path,
+ QScriptCompletionTaskPrivate *task,
+ QScriptDebuggerCommandSchedulerInterface *scheduler)
+ : QScriptDebuggerCommandSchedulerJob(scheduler),
+ m_frameIndex(frameIndex), m_path(path), m_task(task)
+ {}
-QScriptCompletionTask::~QScriptCompletionTask()
-{
-}
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetCompletions(m_frameIndex, m_path);
+ }
+ void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
+ {
+ m_task->results = response.result().toStringList();
+ m_task->emitFinished();
+ finish();
+ }
+
+private:
+ int m_frameIndex;
+ QStringList m_path;
+ QScriptCompletionTaskPrivate *m_task;
+};
namespace {
@@ -122,17 +127,49 @@ static bool isPrefixOf(const QString &prefix, const QString &what)
} // namespace
+class QScriptCompleteScriptsJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ QScriptCompleteScriptsJob(const QString &prefix, QScriptCompletionTaskPrivate *task,
+ QScriptDebuggerCommandSchedulerInterface *scheduler)
+ : QScriptDebuggerCommandSchedulerJob(scheduler),
+ m_prefix(prefix), m_task(task)
+ {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetScripts();
+ }
+ void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
+ {
+ QScriptScriptMap scripts = response.resultAsScripts();
+ QScriptScriptMap::const_iterator it;
+ for (it = scripts.constBegin(); it != scripts.constEnd(); ++it) {
+ QString fileName = it.value().fileName();
+ if (isPrefixOf(m_prefix, fileName))
+ m_task->results.append(fileName);
+ }
+ m_task->emitFinished();
+ finish();
+ }
+private:
+ QString m_prefix;
+ QScriptCompletionTaskPrivate *m_task;
+};
+
void QScriptCompletionTaskPrivate::completeScriptExpression()
{
int pos = cursorPosition;
if ((pos > 0) && contents.at(pos-1).isNumber()) {
// completion of numbers is pointless
+ emitFinished();
return;
}
while ((pos > 0) && isIdentChar(contents.at(pos-1)))
--pos;
- int pos2 = cursorPosition;
+ int pos2 = cursorPosition - 1;
while ((pos2 < contents.size()-1) && isIdentChar(contents.at(pos2+1)))
++pos2;
QString ident = contents.mid(pos, pos2 - pos + 1);
@@ -148,65 +185,41 @@ void QScriptCompletionTaskPrivate::completeScriptExpression()
path.prepend(contents.mid(pos, pos2 - pos));
}
- // ### super-cheating for now; have to use the async API
- QScriptEngineDebuggerFrontend *edf = static_cast<QScriptEngineDebuggerFrontend*>(frontend);
- QScriptDebuggerBackend *backend = edf->backend();
- QScriptContext *ctx = backend->context(frameIndex);
- QScriptValueList objects;
- QString prefix = path.last();
- QSet<QString> matches;
- if (path.size() > 1) {
- const QString &topLevelIdent = path.at(0);
- QScriptValue obj;
- if (topLevelIdent == QString::fromLatin1("this")) {
- obj = ctx->thisObject();
- } else {
- QScriptValueList scopeChain;
- scopeChain = ctx->scopeChain();
- for (int i = 0; i < scopeChain.size(); ++i) {
- QScriptValue oo = scopeChain.at(i).property(topLevelIdent);
- if (oo.isObject()) {
- obj = oo;
- break;
- }
- }
- }
- for (int i = 1; obj.isObject() && (i < path.size()-1); ++i)
- obj = obj.property(path.at(i));
- if (obj.isValid())
- objects.append(obj);
- } else {
- objects << ctx->scopeChain();
- QStringList keywords;
- keywords.append(QString::fromLatin1("this"));
- keywords.append(QString::fromLatin1("true"));
- keywords.append(QString::fromLatin1("false"));
- keywords.append(QString::fromLatin1("null"));
- for (int i = 0; i < keywords.size(); ++i) {
- const QString &kwd = keywords.at(i);
- if (isPrefixOf(prefix, kwd))
- matches.insert(kwd);
- }
- }
+ length = path.last().length();
+ type = QScriptCompletionTask::ScriptIdentifierCompletion;
- for (int i = 0; i < objects.size(); ++i) {
- QScriptValue obj = objects.at(i);
- while (obj.isObject()) {
- QScriptValueIterator it(obj);
- while (it.hasNext()) {
- it.next();
- QString propertyName = it.name();
- if (isPrefixOf(prefix, propertyName))
- matches.insert(propertyName);
- }
- obj = obj.prototype();
- }
- }
- results = matches.toList();
- qStableSort(results);
+ QScriptDebuggerJob *job = new QScriptCompleteExpressionJob(frameIndex, path, this, commandScheduler);
+ jobScheduler->scheduleJob(job);
+}
- length = prefix.length();
- type = QScriptCompletionTask::ScriptIdentifierCompletion;
+void QScriptCompletionTaskPrivate::emitFinished()
+{
+ emit q_func()->finished();
+}
+
+QScriptCompletionTask::QScriptCompletionTask(
+ const QString &contents, int cursorPosition, int frameIndex,
+ QScriptDebuggerCommandSchedulerInterface *commandScheduler,
+ QScriptDebuggerJobSchedulerInterface *jobScheduler,
+ QScriptDebuggerConsole *console,
+ QObject *parent)
+ : QScriptCompletionTaskInterface(
+ *new QScriptCompletionTaskPrivate, parent)
+{
+ Q_D(QScriptCompletionTask);
+ d->contents = contents;
+ d->cursorPosition = cursorPosition;
+ if ((frameIndex == -1) && console)
+ d->frameIndex = console->currentFrameIndex();
+ else
+ d->frameIndex = frameIndex;
+ d->commandScheduler = commandScheduler;
+ d->jobScheduler = jobScheduler;
+ d->console = console;
+}
+
+QScriptCompletionTask::~QScriptCompletionTask()
+{
}
void QScriptCompletionTask::start()
@@ -223,7 +236,6 @@ void QScriptCompletionTask::start()
if ((d->cursorPosition >= cmdIndex) && (d->cursorPosition <= (cmdIndex+len))) {
// editing command --> get command completions
d->results = d->console->commandManager()->completions(prefix);
- qStableSort(d->results);
d->position = cmdRx.pos(1);
d->length = prefix.length();
d->type = CommandNameCompletion;
@@ -256,41 +268,37 @@ void QScriptCompletionTask::start()
}
QString argType = cmd->argumentTypes().value(argNum);
if (!argType.isEmpty()) {
- if (argType == QString::fromLatin1("command-or-group-name")) {
+ if (argType == QLatin1String("command-or-group-name")) {
d->results = d->console->commandManager()->completions(arg);
- } else if (argType == QString::fromLatin1("script-filename")) {
- // ### super-cheating for now; have to use the async API
- QScriptEngineDebuggerFrontend *edf = static_cast<QScriptEngineDebuggerFrontend*>(d->frontend);
- QScriptDebuggerBackend *backend = edf->backend();
- QScriptScriptMap scripts = backend->scripts();
- QScriptScriptMap::const_iterator it;
- for (it = scripts.constBegin(); it != scripts.constEnd(); ++it) {
- QString fileName = it.value().fileName();
- if (isPrefixOf(arg, fileName))
- d->results.append(fileName);
- }
- } else if (argType == QString::fromLatin1("subcommand-name")) {
+ } else if (argType == QLatin1String("script-filename")) {
+ d->position = pos;
+ d->length = arg.length();
+ d->type = CommandArgumentCompletion;
+ QScriptDebuggerJob *job = new QScriptCompleteScriptsJob(arg, d, d->commandScheduler);
+ d->jobScheduler->scheduleJob(job);
+ } else if (argType == QLatin1String("subcommand-name")) {
for (int i = 0; i < cmd->subCommands().size(); ++i) {
QString name = cmd->subCommands().at(i);
if (isPrefixOf(arg, name))
d->results.append(name);
}
- } else if (argType == QString::fromLatin1("script")) {
+ qStableSort(d->results);
+ } else if (argType == QLatin1String("script")) {
d->completeScriptExpression();
+ } else {
+ emit finished();
}
if ((d->type == NoCompletion) && !d->results.isEmpty()) {
- qStableSort(d->results);
d->position = pos;
d->length = arg.length();
d->type = CommandArgumentCompletion;
+ emit finished();
}
}
- emit finished();
}
} else {
// assume it's an eval expression
d->completeScriptExpression();
- emit finished();
}
}
diff --git a/src/scripttools/debugging/qscriptcompletiontask_p.h b/src/scripttools/debugging/qscriptcompletiontask_p.h
index dd82250..0055959 100644
--- a/src/scripttools/debugging/qscriptcompletiontask_p.h
+++ b/src/scripttools/debugging/qscriptcompletiontask_p.h
@@ -60,7 +60,8 @@
QT_BEGIN_NAMESPACE
-class QScriptDebuggerFrontend;
+class QScriptDebuggerCommandSchedulerInterface;
+class QScriptDebuggerJobSchedulerInterface;
class QScriptDebuggerConsole;
class QScriptCompletionTaskPrivate;
@@ -70,9 +71,9 @@ class Q_AUTOTEST_EXPORT QScriptCompletionTask
Q_OBJECT
public:
QScriptCompletionTask(
- const QString &contents, int cursorPosition,
- int frameIndex,
- QScriptDebuggerFrontend *frontend,
+ const QString &contents, int cursorPosition, int frameIndex,
+ QScriptDebuggerCommandSchedulerInterface *commandScheduler,
+ QScriptDebuggerJobSchedulerInterface *jobScheduler,
QScriptDebuggerConsole *console,
QObject *parent = 0);
~QScriptCompletionTask();
diff --git a/src/scripttools/debugging/qscriptdebugger.cpp b/src/scripttools/debugging/qscriptdebugger.cpp
index ce43572..454d051 100644
--- a/src/scripttools/debugging/qscriptdebugger.cpp
+++ b/src/scripttools/debugging/qscriptdebugger.cpp
@@ -94,6 +94,7 @@
#include <QtGui/qevent.h>
#include <QtGui/qicon.h>
#include <QtGui/qinputdialog.h>
+#include <QtGui/qtooltip.h>
QT_BEGIN_NAMESPACE
typedef QPair<QList<qint64>, QList<qint64> > QScriptScriptsDelta;
@@ -171,8 +172,8 @@ public:
QScriptCompletionTaskInterface *createCompletionTask(
const QString &contents, int cursorPosition, int frameIndex, int options);
- QString toolTip(int frameIndex, int lineNumber,
- const QStringList &path);
+ void showToolTip(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path);
static QPixmap pixmap(const QString &path);
@@ -633,11 +634,49 @@ bool QScriptDebuggerPrivate::debuggerEvent(const QScriptDebuggerEvent &event)
return !interactive;
}
+class QScriptToolTipJob : public QScriptDebuggerCommandSchedulerJob
+{
+public:
+ QScriptToolTipJob(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path,
+ QScriptDebuggerCommandSchedulerInterface *scheduler)
+ : QScriptDebuggerCommandSchedulerJob(scheduler), m_pos(pos),
+ m_frameIndex(frameIndex), m_lineNumber(lineNumber), m_path(path)
+ {}
+
+ void start()
+ {
+ QScriptDebuggerCommandSchedulerFrontend frontend(commandScheduler(), this);
+ frontend.scheduleGetPropertyExpressionValue(m_frameIndex, m_lineNumber, m_path);
+ }
+ void handleResponse(const QScriptDebuggerResponse &response, int /*commandId*/)
+ {
+ QString tip = response.result().toString();
+ if (tip.indexOf(QLatin1Char('\n')) != -1) {
+ QStringList lines = tip.split(QLatin1Char('\n'));
+ int lineCount = lines.size();
+ if (lineCount > 5) {
+ lines = lines.mid(0, 5);
+ lines.append(QString::fromLatin1("(... %0 more lines ...)").arg(lineCount - 5));
+ }
+ tip = lines.join(QLatin1String("\n"));
+ }
+ QToolTip::showText(m_pos, tip);
+ finish();
+ }
+
+private:
+ QPoint m_pos;
+ int m_frameIndex;
+ int m_lineNumber;
+ QStringList m_path;
+};
+
/*!
\reimp
*/
-QString QScriptDebuggerPrivate::toolTip(int frameIndex, int lineNumber,
- const QStringList &path)
+void QScriptDebuggerPrivate::showToolTip(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path)
{
if (frameIndex == -1) {
if (stackWidget)
@@ -645,40 +684,8 @@ QString QScriptDebuggerPrivate::toolTip(int frameIndex, int lineNumber,
else
frameIndex = console->currentFrameIndex();
}
- // ### cheating for now, need to use async API
- QScriptEngineDebuggerFrontend *edf = static_cast<QScriptEngineDebuggerFrontend*>(frontend);
- QScriptDebuggerBackend *backend = edf->backend();
- QScriptContext *ctx = backend->context(frameIndex);
- if (!ctx || path.isEmpty())
- return QString();
- QScriptContextInfo ctxInfo(ctx);
- if (ctx->callee().isValid()
- && ((lineNumber < ctxInfo.functionStartLineNumber())
- || (lineNumber > ctxInfo.functionEndLineNumber()))) {
- return QString();
- }
- QScriptValueList objects;
- int pathIndex = 0;
- if (path.at(0) == QLatin1String("this")) {
- objects.append(ctx->thisObject());
- ++pathIndex;
- } else {
- objects << ctx->scopeChain();
- }
- for (int i = 0; i < objects.size(); ++i) {
- QScriptValue val = objects.at(i);
- for (int j = pathIndex; val.isValid() && (j < path.size()); ++j) {
- val = val.property(path.at(j));
- }
- if (val.isValid()) {
- bool hadException = (ctx->state() == QScriptContext::ExceptionState);
- QString str = val.toString();
- if (!hadException && backend->engine()->hasUncaughtException())
- backend->engine()->clearExceptions();
- return str;
- }
- }
- return QString();
+ QScriptDebuggerJob *job = new QScriptToolTipJob(pos, frameIndex, lineNumber, path, this);
+ scheduleJob(job);
}
/*!
@@ -688,7 +695,7 @@ QScriptCompletionTaskInterface *QScriptDebuggerPrivate::createCompletionTask(
const QString &contents, int cursorPosition, int frameIndex, int options)
{
return new QScriptCompletionTask(
- contents, cursorPosition, frameIndex, frontend,
+ contents, cursorPosition, frameIndex, this, this,
(options & QScriptCompletionProviderInterface::ConsoleCommandCompletion) ? console : 0);
}
@@ -1072,7 +1079,7 @@ class LoadLocalsJob : public QScriptDebuggerCommandSchedulerJob
public:
LoadLocalsJob(QScriptDebuggerPrivate *debugger, int frameIndex)
: QScriptDebuggerCommandSchedulerJob(debugger),
- m_debugger(debugger), m_frameIndex(frameIndex), m_state(0) {}
+ m_debugger(debugger), m_frameIndex(frameIndex) {}
void start()
{
@@ -1104,7 +1111,6 @@ public:
private:
QScriptDebuggerPrivate *m_debugger;
int m_frameIndex;
- int m_state;
};
class EmitStoppedSignalJob : public QScriptDebuggerJob
@@ -1331,6 +1337,122 @@ void QScriptDebugger::setFrontend(QScriptDebuggerFrontend *frontend)
}
}
+QAction *QScriptDebugger::action(DebuggerAction action, QObject *parent)
+{
+ switch (action) {
+ case InterruptAction:
+ return interruptAction(parent);
+ case ContinueAction:
+ return continueAction(parent);
+ case StepIntoAction:
+ return stepIntoAction(parent);
+ case StepOverAction:
+ return stepOverAction(parent);
+ case StepOutAction:
+ return stepOutAction(parent);
+ case RunToCursorAction:
+ return runToCursorAction(parent);
+ case RunToNewScriptAction:
+ return runToNewScriptAction(parent);
+ case ToggleBreakpointAction:
+ return toggleBreakpointAction(parent);
+ case ClearDebugOutputAction:
+ return clearDebugOutputAction(parent);
+ case ClearErrorLogAction:
+ return clearErrorLogAction(parent);
+ case ClearConsoleAction:
+ return clearConsoleAction(parent);
+ case FindInScriptAction:
+ return findInScriptAction(parent);
+ case FindNextInScriptAction:
+ return findNextInScriptAction(parent);
+ case FindPreviousInScriptAction:
+ return findPreviousInScriptAction(parent);
+ case GoToLineAction:
+ return goToLineAction(parent);
+ }
+ return 0;
+}
+
+QWidget *QScriptDebugger::widget(DebuggerWidget widget)
+{
+ switch (widget) {
+ case ConsoleWidget: {
+ QScriptDebuggerConsoleWidgetInterface *w = consoleWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createConsoleWidget();
+ setConsoleWidget(w);
+ }
+ return w;
+ }
+ case StackWidget: {
+ QScriptDebuggerStackWidgetInterface *w = stackWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createStackWidget();
+ setStackWidget(w);
+ }
+ return w;
+ }
+ case ScriptsWidget: {
+ QScriptDebuggerScriptsWidgetInterface *w = scriptsWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createScriptsWidget();
+ setScriptsWidget(w);
+ }
+ return w;
+ }
+ case LocalsWidget: {
+ QScriptDebuggerLocalsWidgetInterface *w = localsWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createLocalsWidget();
+ setLocalsWidget(w);
+ }
+ return w;
+ }
+ case CodeWidget: {
+ QScriptDebuggerCodeWidgetInterface *w = codeWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createCodeWidget();
+ setCodeWidget(w);
+ }
+ return w;
+ }
+ case CodeFinderWidget: {
+ QScriptDebuggerCodeFinderWidgetInterface *w = codeFinderWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createCodeFinderWidget();
+ setCodeFinderWidget(w);
+ }
+ return w;
+ }
+ case BreakpointsWidget: {
+ QScriptBreakpointsWidgetInterface *w = breakpointsWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createBreakpointsWidget();
+ setBreakpointsWidget(w);
+ }
+ return w;
+ }
+ case DebugOutputWidget: {
+ QScriptDebugOutputWidgetInterface *w = debugOutputWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createDebugOutputWidget();
+ setDebugOutputWidget(w);
+ }
+ return w;
+ }
+ case ErrorLogWidget: {
+ QScriptErrorLogWidgetInterface *w = errorLogWidget();
+ if (!w && widgetFactory()) {
+ w = widgetFactory()->createErrorLogWidget();
+ setErrorLogWidget(w);
+ }
+ return w;
+ }
+ }
+ return 0;
+}
+
QScriptDebuggerConsoleWidgetInterface *QScriptDebugger::consoleWidget() const
{
Q_D(const QScriptDebugger);
diff --git a/src/scripttools/debugging/qscriptdebugger_p.h b/src/scripttools/debugging/qscriptdebugger_p.h
index 8f14f4d..6d8fcab 100644
--- a/src/scripttools/debugging/qscriptdebugger_p.h
+++ b/src/scripttools/debugging/qscriptdebugger_p.h
@@ -76,12 +76,46 @@ class Q_AUTOTEST_EXPORT QScriptDebugger : public QObject
{
Q_OBJECT
public:
+ // mirrors QScriptEngineDebugger::DebuggerWidget
+ enum DebuggerWidget {
+ ConsoleWidget,
+ StackWidget,
+ ScriptsWidget,
+ LocalsWidget,
+ CodeWidget,
+ CodeFinderWidget,
+ BreakpointsWidget,
+ DebugOutputWidget,
+ ErrorLogWidget
+ };
+ // mirrors QScriptEngineDebugger::DebuggerAction
+ enum DebuggerAction {
+ InterruptAction,
+ ContinueAction,
+ StepIntoAction,
+ StepOverAction,
+ StepOutAction,
+ RunToCursorAction,
+ RunToNewScriptAction,
+ ToggleBreakpointAction,
+ ClearDebugOutputAction,
+ ClearErrorLogAction,
+ ClearConsoleAction,
+ FindInScriptAction,
+ FindNextInScriptAction,
+ FindPreviousInScriptAction,
+ GoToLineAction
+ };
+
QScriptDebugger(QObject *parent = 0);
~QScriptDebugger();
QScriptDebuggerFrontend *frontend() const;
void setFrontend(QScriptDebuggerFrontend *frontend);
+ QWidget *widget(DebuggerWidget widget);
+ QAction *action(DebuggerAction action, QObject *parent);
+
QScriptDebuggerConsoleWidgetInterface *consoleWidget() const;
void setConsoleWidget(QScriptDebuggerConsoleWidgetInterface *consoleWidget);
diff --git a/src/scripttools/debugging/qscriptdebuggerbackend.cpp b/src/scripttools/debugging/qscriptdebuggerbackend.cpp
index 46d8497..07ae1d3 100644
--- a/src/scripttools/debugging/qscriptdebuggerbackend.cpp
+++ b/src/scripttools/debugging/qscriptdebuggerbackend.cpp
@@ -292,7 +292,7 @@ QScriptValue QScriptDebuggerBackendPrivate::trace(QScriptContext *context,
QString str;
for (int i = 0; i < context->argumentCount(); ++i) {
if (i > 0)
- str.append(QLatin1String(" "));
+ str.append(QLatin1Char(' '));
str.append(context->argument(i).toString());
}
QScriptDebuggerEvent e(QScriptDebuggerEvent::Trace);
diff --git a/src/scripttools/debugging/qscriptdebuggercodeview.cpp b/src/scripttools/debugging/qscriptdebuggercodeview.cpp
index bc493e0..c03ec83 100644
--- a/src/scripttools/debugging/qscriptdebuggercodeview.cpp
+++ b/src/scripttools/debugging/qscriptdebuggercodeview.cpp
@@ -214,7 +214,6 @@ bool QScriptDebuggerCodeView::event(QEvent *e)
if (contents.isEmpty())
return false;
int linePosition = cursor.position() - block.position();
- linePosition -= 3;
if (linePosition < 0)
linePosition = 0;
@@ -233,7 +232,7 @@ bool QScriptDebuggerCodeView::event(QEvent *e)
// ignore string literals
return false;
}
- int pos2 = linePosition;
+ int pos2 = linePosition - 1;
while ((pos2 < contents.size()-1) && isIdentChar(contents.at(pos2+1)))
++pos2;
QString ident = contents.mid(pos, pos2 - pos + 1);
diff --git a/src/scripttools/debugging/qscriptdebuggercodewidget.cpp b/src/scripttools/debugging/qscriptdebuggercodewidget.cpp
index 14ce0fe..b2f1dec 100644
--- a/src/scripttools/debugging/qscriptdebuggercodewidget.cpp
+++ b/src/scripttools/debugging/qscriptdebuggercodewidget.cpp
@@ -49,7 +49,6 @@
#include <QtCore/qdebug.h>
#include <QtGui/qboxlayout.h>
#include <QtGui/qstackedwidget.h>
-#include <QtGui/qtooltip.h>
QT_BEGIN_NAMESPACE
@@ -197,17 +196,7 @@ void QScriptDebuggerCodeWidgetPrivate::_q_onScriptsChanged()
void QScriptDebuggerCodeWidgetPrivate::_q_onToolTipRequest(
const QPoint &pos, int lineNumber, const QStringList &path)
{
- QString tip = toolTipProvider->toolTip(/*frameIndex=*/-1, lineNumber, path);
- if (tip.indexOf(QLatin1Char('\n')) != -1) {
- QStringList lines = tip.split(QLatin1Char('\n'));
- int lineCount = lines.size();
- if (lineCount > 5) {
- lines = lines.mid(0, 5);
- lines.append(QString::fromLatin1("(... %0 more lines ...)").arg(lineCount - 5));
- }
- tip = lines.join(QLatin1String("\n"));
- }
- QToolTip::showText(pos, tip);
+ toolTipProvider->showToolTip(pos, /*frameIndex=*/-1, lineNumber, path);
}
QScriptDebuggerCodeWidget::QScriptDebuggerCodeWidget(QWidget *parent)
diff --git a/src/scripttools/debugging/qscriptdebuggercommand.cpp b/src/scripttools/debugging/qscriptdebuggercommand.cpp
index 98bb3b3..e5bfa9d 100644
--- a/src/scripttools/debugging/qscriptdebuggercommand.cpp
+++ b/src/scripttools/debugging/qscriptdebuggercommand.cpp
@@ -45,6 +45,7 @@
#include <QtCore/qhash.h>
#include <QtCore/qdatastream.h>
+#include <QtCore/qstringlist.h>
Q_DECLARE_METATYPE(QScriptBreakpointData)
Q_DECLARE_METATYPE(QScriptDebuggerValue)
@@ -557,6 +558,25 @@ QScriptDebuggerCommand QScriptDebuggerCommand::contextsCheckpoint()
return cmd;
}
+QScriptDebuggerCommand QScriptDebuggerCommand::getPropertyExpressionValue(
+ int contextIndex, int lineNumber, const QStringList &path)
+{
+ QScriptDebuggerCommand cmd(GetPropertyExpressionValue);
+ cmd.setContextIndex(contextIndex);
+ cmd.setLineNumber(lineNumber);
+ cmd.setAttribute(UserAttribute, path);
+ return cmd;
+}
+
+QScriptDebuggerCommand QScriptDebuggerCommand::getCompletions(
+ int contextIndex, const QStringList &path)
+{
+ QScriptDebuggerCommand cmd(GetCompletions);
+ cmd.setContextIndex(contextIndex);
+ cmd.setAttribute(UserAttribute, path);
+ return cmd;
+}
+
QScriptDebuggerCommand QScriptDebuggerCommand::newScriptObjectSnapshotCommand()
{
QScriptDebuggerCommand cmd(NewScriptObjectSnapshot);
diff --git a/src/scripttools/debugging/qscriptdebuggercommand_p.h b/src/scripttools/debugging/qscriptdebuggercommand_p.h
index 363738f..7a2507d 100644
--- a/src/scripttools/debugging/qscriptdebuggercommand_p.h
+++ b/src/scripttools/debugging/qscriptdebuggercommand_p.h
@@ -106,6 +106,8 @@ public:
GetActivationObject,
GetScopeChain,
ContextsCheckpoint,
+ GetPropertyExpressionValue,
+ GetCompletions,
NewScriptObjectSnapshot,
ScriptObjectSnapshotCapture,
@@ -229,6 +231,9 @@ public:
static QScriptDebuggerCommand getActivationObjectCommand(int contextIndex);
static QScriptDebuggerCommand getScopeChainCommand(int contextIndex);
static QScriptDebuggerCommand contextsCheckpoint();
+ static QScriptDebuggerCommand getPropertyExpressionValue(int contextIndex, int lineNumber,
+ const QStringList &path);
+ static QScriptDebuggerCommand getCompletions(int contextIndex, const QStringList &path);
static QScriptDebuggerCommand newScriptObjectSnapshotCommand();
static QScriptDebuggerCommand scriptObjectSnapshotCaptureCommand(int id, const QScriptDebuggerValue &object);
diff --git a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp
index e75ff99..010aae7 100644
--- a/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp
+++ b/src/scripttools/debugging/qscriptdebuggercommandexecutor.cpp
@@ -100,12 +100,18 @@ QScriptDebuggerCommandExecutor::~QScriptDebuggerCommandExecutor()
{
}
+static bool isPrefixOf(const QString &prefix, const QString &what)
+{
+ return ((what.length() > prefix.length())
+ && what.startsWith(prefix));
+}
+
/*!
Applies the given \a command to the given \a backend.
*/
QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute(
- QScriptDebuggerBackend *backend,
- const QScriptDebuggerCommand &command)
+ QScriptDebuggerBackend *backend,
+ const QScriptDebuggerCommand &command)
{
QScriptDebuggerResponse response;
switch (command.type()) {
@@ -299,6 +305,104 @@ QScriptDebuggerResponse QScriptDebuggerCommandExecutor::execute(
response.setResult(qVariantFromValue(backend->contextsCheckpoint()));
} break;
+ case QScriptDebuggerCommand::GetPropertyExpressionValue: {
+ QScriptContext *ctx = backend->context(command.contextIndex());
+ int lineNumber = command.lineNumber();
+ QVariant attr = command.attribute(QScriptDebuggerCommand::UserAttribute);
+ QStringList path = attr.toStringList();
+ if (!ctx || path.isEmpty())
+ break;
+ QScriptContextInfo ctxInfo(ctx);
+ if (ctx->callee().isValid()
+ && ((lineNumber < ctxInfo.functionStartLineNumber())
+ || (lineNumber > ctxInfo.functionEndLineNumber()))) {
+ break;
+ }
+ QScriptValueList objects;
+ int pathIndex = 0;
+ if (path.at(0) == QLatin1String("this")) {
+ objects.append(ctx->thisObject());
+ ++pathIndex;
+ } else {
+ objects << ctx->scopeChain();
+ }
+ for (int i = 0; i < objects.size(); ++i) {
+ QScriptValue val = objects.at(i);
+ for (int j = pathIndex; val.isValid() && (j < path.size()); ++j) {
+ val = val.property(path.at(j));
+ }
+ if (val.isValid()) {
+ bool hadException = (ctx->state() == QScriptContext::ExceptionState);
+ QString str = val.toString();
+ if (!hadException && backend->engine()->hasUncaughtException())
+ backend->engine()->clearExceptions();
+ response.setResult(str);
+ break;
+ }
+ }
+ } break;
+
+ case QScriptDebuggerCommand::GetCompletions: {
+ QScriptContext *ctx = backend->context(command.contextIndex());
+ QVariant attr = command.attribute(QScriptDebuggerCommand::UserAttribute);
+ QStringList path = attr.toStringList();
+ if (!ctx || path.isEmpty())
+ break;
+ QScriptValueList objects;
+ QString prefix = path.last();
+ QSet<QString> matches;
+ if (path.size() > 1) {
+ const QString &topLevelIdent = path.at(0);
+ QScriptValue obj;
+ if (topLevelIdent == QLatin1String("this")) {
+ obj = ctx->thisObject();
+ } else {
+ QScriptValueList scopeChain;
+ scopeChain = ctx->scopeChain();
+ for (int i = 0; i < scopeChain.size(); ++i) {
+ QScriptValue oo = scopeChain.at(i).property(topLevelIdent);
+ if (oo.isObject()) {
+ obj = oo;
+ break;
+ }
+ }
+ }
+ for (int i = 1; obj.isObject() && (i < path.size()-1); ++i)
+ obj = obj.property(path.at(i));
+ if (obj.isValid())
+ objects.append(obj);
+ } else {
+ objects << ctx->scopeChain();
+ QStringList keywords;
+ keywords.append(QString::fromLatin1("this"));
+ keywords.append(QString::fromLatin1("true"));
+ keywords.append(QString::fromLatin1("false"));
+ keywords.append(QString::fromLatin1("null"));
+ for (int i = 0; i < keywords.size(); ++i) {
+ const QString &kwd = keywords.at(i);
+ if (isPrefixOf(prefix, kwd))
+ matches.insert(kwd);
+ }
+ }
+
+ for (int i = 0; i < objects.size(); ++i) {
+ QScriptValue obj = objects.at(i);
+ while (obj.isObject()) {
+ QScriptValueIterator it(obj);
+ while (it.hasNext()) {
+ it.next();
+ QString propertyName = it.name();
+ if (isPrefixOf(prefix, propertyName))
+ matches.insert(propertyName);
+ }
+ obj = obj.prototype();
+ }
+ }
+ QStringList matchesList = matches.toList();
+ qStableSort(matchesList);
+ response.setResult(matchesList);
+ } break;
+
case QScriptDebuggerCommand::NewScriptObjectSnapshot: {
int id = backend->newScriptObjectSnapshot();
response.setResult(id);
diff --git a/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend.cpp b/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend.cpp
index 1e20ab4..83e634e 100644
--- a/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend.cpp
+++ b/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend.cpp
@@ -251,6 +251,17 @@ int QScriptDebuggerCommandSchedulerFrontend::scheduleContextsCheckpoint()
return scheduleCommand(QScriptDebuggerCommand::contextsCheckpoint());
}
+int QScriptDebuggerCommandSchedulerFrontend::scheduleGetPropertyExpressionValue(
+ int contextIndex, int lineNumber, const QStringList &path)
+{
+ return scheduleCommand(QScriptDebuggerCommand::getPropertyExpressionValue(contextIndex, lineNumber, path));
+}
+
+int QScriptDebuggerCommandSchedulerFrontend::scheduleGetCompletions(int contextIndex, const QStringList &path)
+{
+ return scheduleCommand(QScriptDebuggerCommand::getCompletions(contextIndex, path));
+}
+
int QScriptDebuggerCommandSchedulerFrontend::scheduleEvaluate(int contextIndex,
const QString &program,
const QString &fileName,
diff --git a/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend_p.h b/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend_p.h
index ed9cbf9..9a1a36d 100644
--- a/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend_p.h
+++ b/src/scripttools/debugging/qscriptdebuggercommandschedulerfrontend_p.h
@@ -109,6 +109,9 @@ public:
int scheduleGetActivationObject(int contextIndex);
int scheduleGetScopeChain(int contextIndex);
int scheduleContextsCheckpoint();
+ int scheduleGetPropertyExpressionValue(int contextIndex, int lineNumber,
+ const QStringList &path);
+ int scheduleGetCompletions(int contextIndex, const QStringList &path);
// iteration
int scheduleNewScriptValueIterator(const QScriptDebuggerValue &object);
diff --git a/src/scripttools/debugging/qscriptdebuggerconsole.cpp b/src/scripttools/debugging/qscriptdebuggerconsole.cpp
index 09a32db..3783050 100644
--- a/src/scripttools/debugging/qscriptdebuggerconsole.cpp
+++ b/src/scripttools/debugging/qscriptdebuggerconsole.cpp
@@ -163,10 +163,10 @@ QScriptDebuggerConsoleCommandJob *QScriptDebuggerConsolePrivate::createJob(
.arg(name));
for (int j = 0; j < completions.size(); ++j) {
if (j > 0)
- msg.append(QString::fromLatin1(", "));
+ msg.append(QLatin1String(", "));
msg.append(completions.at(j));
}
- msg.append(QString::fromLatin1("."));
+ msg.append(QLatin1Char('.'));
messageHandler->message(QtWarningMsg, msg);
return 0;
}
diff --git a/src/scripttools/debugging/qscriptdebuggerlocalsmodel.cpp b/src/scripttools/debugging/qscriptdebuggerlocalsmodel.cpp
index caeb971..e096ba8 100644
--- a/src/scripttools/debugging/qscriptdebuggerlocalsmodel.cpp
+++ b/src/scripttools/debugging/qscriptdebuggerlocalsmodel.cpp
@@ -807,7 +807,7 @@ QVariant QScriptDebuggerLocalsModel::data(const QModelIndex &index, int role) co
QString str = node->property.valueAsString();
if (node->property.value().type() == QScriptDebuggerValue::StringValue) {
// escape
- str.replace(QLatin1String("\""), QLatin1String("\\\""));
+ str.replace(QLatin1Char('\"'), QLatin1String("\\\""));
str.prepend(QLatin1Char('\"'));
str.append(QLatin1Char('\"'));
}
diff --git a/src/scripttools/debugging/qscriptdebuggerobjectsnapshotdelta_p.h b/src/scripttools/debugging/qscriptdebuggerobjectsnapshotdelta_p.h
index e3ec541..546ed7f 100644
--- a/src/scripttools/debugging/qscriptdebuggerobjectsnapshotdelta_p.h
+++ b/src/scripttools/debugging/qscriptdebuggerobjectsnapshotdelta_p.h
@@ -60,6 +60,8 @@
QT_BEGIN_NAMESPACE
+class QDataStream;
+
class Q_AUTOTEST_EXPORT QScriptDebuggerObjectSnapshotDelta
{
public:
@@ -68,6 +70,9 @@ public:
QScriptDebuggerValuePropertyList addedProperties;
};
+Q_AUTOTEST_EXPORT QDataStream &operator<<(QDataStream &, const QScriptDebuggerObjectSnapshotDelta &);
+Q_AUTOTEST_EXPORT QDataStream &operator>>(QDataStream &, QScriptDebuggerObjectSnapshotDelta &);
+
QT_END_NAMESPACE
#endif
diff --git a/src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory.cpp b/src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory.cpp
new file mode 100644
index 0000000..09d6f2f
--- /dev/null
+++ b/src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory.cpp
@@ -0,0 +1,109 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtSCriptTools module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscriptdebuggerstandardwidgetfactory_p.h"
+#include "qscriptdebuggerconsolewidget_p.h"
+#include "qscriptdebuggerstackwidget_p.h"
+#include "qscriptdebuggerscriptswidget_p.h"
+#include "qscriptdebuggerlocalswidget_p.h"
+#include "qscriptdebuggercodewidget_p.h"
+#include "qscriptdebuggercodefinderwidget_p.h"
+#include "qscriptbreakpointswidget_p.h"
+#include "qscriptdebugoutputwidget_p.h"
+#include "qscripterrorlogwidget_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QScriptDebuggerStandardWidgetFactory::QScriptDebuggerStandardWidgetFactory(QObject *parent)
+ : QObject(parent)
+{
+}
+
+QScriptDebuggerStandardWidgetFactory::~QScriptDebuggerStandardWidgetFactory()
+{
+}
+
+QScriptDebugOutputWidgetInterface *QScriptDebuggerStandardWidgetFactory::createDebugOutputWidget()
+{
+ return new QScriptDebugOutputWidget();
+}
+
+QScriptDebuggerConsoleWidgetInterface *QScriptDebuggerStandardWidgetFactory::createConsoleWidget()
+{
+ return new QScriptDebuggerConsoleWidget();
+}
+
+QScriptErrorLogWidgetInterface *QScriptDebuggerStandardWidgetFactory::createErrorLogWidget()
+{
+ return new QScriptErrorLogWidget();
+}
+
+QScriptDebuggerCodeFinderWidgetInterface *QScriptDebuggerStandardWidgetFactory::createCodeFinderWidget()
+{
+ return new QScriptDebuggerCodeFinderWidget();
+}
+
+QScriptDebuggerStackWidgetInterface *QScriptDebuggerStandardWidgetFactory::createStackWidget()
+{
+ return new QScriptDebuggerStackWidget();
+}
+
+QScriptDebuggerScriptsWidgetInterface *QScriptDebuggerStandardWidgetFactory::createScriptsWidget()
+{
+ return new QScriptDebuggerScriptsWidget();
+}
+
+QScriptDebuggerLocalsWidgetInterface *QScriptDebuggerStandardWidgetFactory::createLocalsWidget()
+{
+ return new QScriptDebuggerLocalsWidget();
+}
+
+QScriptDebuggerCodeWidgetInterface *QScriptDebuggerStandardWidgetFactory::createCodeWidget()
+{
+ return new QScriptDebuggerCodeWidget();
+}
+
+QScriptBreakpointsWidgetInterface *QScriptDebuggerStandardWidgetFactory::createBreakpointsWidget()
+{
+ return new QScriptBreakpointsWidget();
+}
+
+QT_END_NAMESPACE
diff --git a/src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory_p.h b/src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory_p.h
new file mode 100644
index 0000000..bfce66e
--- /dev/null
+++ b/src/scripttools/debugging/qscriptdebuggerstandardwidgetfactory_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtSCriptTools module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCRIPTDEBUGGERSTANDARDWIDGETFACTORY_P_H
+#define QSCRIPTDEBUGGERSTANDARDWIDGETFACTORY_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qobject.h>
+
+#include "qscriptdebuggerwidgetfactoryinterface_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_AUTOTEST_EXPORT QScriptDebuggerStandardWidgetFactory
+ : public QObject, public QScriptDebuggerWidgetFactoryInterface
+{
+public:
+ QScriptDebuggerStandardWidgetFactory(QObject *parent = 0);
+ virtual ~QScriptDebuggerStandardWidgetFactory();
+
+ QScriptDebugOutputWidgetInterface *createDebugOutputWidget();
+ QScriptDebuggerConsoleWidgetInterface *createConsoleWidget();
+ QScriptErrorLogWidgetInterface *createErrorLogWidget();
+ QScriptDebuggerCodeFinderWidgetInterface *createCodeFinderWidget();
+ QScriptDebuggerStackWidgetInterface *createStackWidget();
+ QScriptDebuggerScriptsWidgetInterface *createScriptsWidget();
+ QScriptDebuggerLocalsWidgetInterface *createLocalsWidget();
+ QScriptDebuggerCodeWidgetInterface *createCodeWidget();
+ QScriptBreakpointsWidgetInterface *createBreakpointsWidget();
+
+private:
+ Q_DISABLE_COPY(QScriptDebuggerStandardWidgetFactory)
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/scripttools/debugging/qscriptdebuggervalueproperty.cpp b/src/scripttools/debugging/qscriptdebuggervalueproperty.cpp
index 63f820b..8a144c5 100644
--- a/src/scripttools/debugging/qscriptdebuggervalueproperty.cpp
+++ b/src/scripttools/debugging/qscriptdebuggervalueproperty.cpp
@@ -41,6 +41,7 @@
#include "qscriptdebuggervalueproperty_p.h"
#include "qscriptdebuggervalue_p.h"
+#include "qscriptdebuggerobjectsnapshotdelta_p.h"
#include <QtCore/qatomic.h>
#include <QtCore/qdatastream.h>
@@ -215,4 +216,20 @@ QDataStream &operator>>(QDataStream &in, QScriptDebuggerValueProperty &property)
return in;
}
+QDataStream &operator<<(QDataStream &out, const QScriptDebuggerObjectSnapshotDelta &delta)
+{
+ out << delta.removedProperties;
+ out << delta.changedProperties;
+ out << delta.addedProperties;
+ return out;
+}
+
+QDataStream &operator>>(QDataStream &in, QScriptDebuggerObjectSnapshotDelta &delta)
+{
+ in >> delta.removedProperties;
+ in >> delta.changedProperties;
+ in >> delta.addedProperties;
+ return in;
+}
+
QT_END_NAMESPACE
diff --git a/src/scripttools/debugging/qscriptdebuggerwidgetfactoryinterface_p.h b/src/scripttools/debugging/qscriptdebuggerwidgetfactoryinterface_p.h
index 9ad1eeb..ea22793 100644
--- a/src/scripttools/debugging/qscriptdebuggerwidgetfactoryinterface_p.h
+++ b/src/scripttools/debugging/qscriptdebuggerwidgetfactoryinterface_p.h
@@ -61,6 +61,11 @@ class QScriptDebugOutputWidgetInterface;
class QScriptDebuggerConsoleWidgetInterface;
class QScriptErrorLogWidgetInterface;
class QScriptDebuggerCodeFinderWidgetInterface;
+class QScriptDebuggerStackWidgetInterface;
+class QScriptDebuggerScriptsWidgetInterface;
+class QScriptDebuggerLocalsWidgetInterface;
+class QScriptDebuggerCodeWidgetInterface;
+class QScriptBreakpointsWidgetInterface;
class Q_AUTOTEST_EXPORT QScriptDebuggerWidgetFactoryInterface
{
@@ -71,6 +76,11 @@ public:
virtual QScriptDebuggerConsoleWidgetInterface *createConsoleWidget() = 0;
virtual QScriptErrorLogWidgetInterface *createErrorLogWidget() = 0;
virtual QScriptDebuggerCodeFinderWidgetInterface *createCodeFinderWidget() = 0;
+ virtual QScriptDebuggerStackWidgetInterface *createStackWidget() = 0;
+ virtual QScriptDebuggerScriptsWidgetInterface *createScriptsWidget() = 0;
+ virtual QScriptDebuggerLocalsWidgetInterface *createLocalsWidget() = 0;
+ virtual QScriptDebuggerCodeWidgetInterface *createCodeWidget() = 0;
+ virtual QScriptBreakpointsWidgetInterface *createBreakpointsWidget() = 0;
};
QT_END_NAMESPACE
diff --git a/src/scripttools/debugging/qscriptenginedebugger.cpp b/src/scripttools/debugging/qscriptenginedebugger.cpp
index 0f8b600..a278e14 100644
--- a/src/scripttools/debugging/qscriptenginedebugger.cpp
+++ b/src/scripttools/debugging/qscriptenginedebugger.cpp
@@ -42,16 +42,7 @@
#include "qscriptenginedebugger.h"
#include "qscriptdebugger_p.h"
#include "qscriptenginedebuggerfrontend_p.h"
-#include "qscriptdebuggerconsolewidget_p.h"
-#include "qscriptdebuggerstackwidget_p.h"
-#include "qscriptdebuggerscriptswidget_p.h"
-#include "qscriptdebuggerlocalswidget_p.h"
-#include "qscriptdebuggercodewidget_p.h"
-#include "qscriptdebuggercodefinderwidget_p.h"
-#include "qscriptbreakpointswidget_p.h"
-#include "qscriptdebugoutputwidget_p.h"
-#include "qscripterrorlogwidget_p.h"
-#include "qscriptdebuggerwidgetfactoryinterface_p.h"
+#include "qscriptdebuggerstandardwidgetfactory_p.h"
#include <private/qobject_p.h>
#include <QtCore/qsettings.h>
@@ -238,19 +229,13 @@ public:
*/
class QScriptEngineDebuggerPrivate
- : public QObjectPrivate,
- public QScriptDebuggerWidgetFactoryInterface
+ : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QScriptEngineDebugger)
public:
QScriptEngineDebuggerPrivate();
~QScriptEngineDebuggerPrivate();
- QScriptDebugOutputWidgetInterface *createDebugOutputWidget();
- QScriptDebuggerConsoleWidgetInterface *createConsoleWidget();
- QScriptErrorLogWidgetInterface *createErrorLogWidget();
- QScriptDebuggerCodeFinderWidgetInterface *createCodeFinderWidget();
-
// private slots
void _q_showStandardWindow();
@@ -320,26 +305,6 @@ QScriptEngineDebuggerPrivate::~QScriptEngineDebuggerPrivate()
}
}
-QScriptDebugOutputWidgetInterface *QScriptEngineDebuggerPrivate::createDebugOutputWidget()
-{
- return new QScriptDebugOutputWidget();
-}
-
-QScriptDebuggerConsoleWidgetInterface *QScriptEngineDebuggerPrivate::createConsoleWidget()
-{
- return new QScriptDebuggerConsoleWidget();
-}
-
-QScriptErrorLogWidgetInterface *QScriptEngineDebuggerPrivate::createErrorLogWidget()
-{
- return new QScriptErrorLogWidget();
-}
-
-QScriptDebuggerCodeFinderWidgetInterface *QScriptEngineDebuggerPrivate::createCodeFinderWidget()
-{
- return new QScriptDebuggerCodeFinderWidget();
-}
-
void QScriptEngineDebuggerPrivate::_q_showStandardWindow()
{
Q_Q(QScriptEngineDebugger);
@@ -352,7 +317,7 @@ void QScriptEngineDebuggerPrivate::createDebugger()
Q_Q(QScriptEngineDebugger);
if (!debugger) {
debugger = new QScriptDebugger();
- debugger->setWidgetFactory(this);
+ debugger->setWidgetFactory(new QScriptDebuggerStandardWidgetFactory(q));
QObject::connect(debugger, SIGNAL(started()),
q, SIGNAL(evaluationResumed()));
QObject::connect(debugger, SIGNAL(stopped()),
@@ -447,81 +412,7 @@ QWidget *QScriptEngineDebugger::widget(DebuggerWidget widget) const
{
Q_D(const QScriptEngineDebugger);
const_cast<QScriptEngineDebuggerPrivate*>(d)->createDebugger();
- switch (widget) {
- case ConsoleWidget: {
- QScriptDebuggerConsoleWidgetInterface *w = d->debugger->consoleWidget();
- if (!w) {
- w = new QScriptDebuggerConsoleWidget();
- d->debugger->setConsoleWidget(w);
- }
- return w;
- }
- case StackWidget: {
- QScriptDebuggerStackWidgetInterface *w = d->debugger->stackWidget();
- if (!w) {
- w = new QScriptDebuggerStackWidget();
- d->debugger->setStackWidget(w);
- }
- return w;
- }
- case ScriptsWidget: {
- QScriptDebuggerScriptsWidgetInterface *w = d->debugger->scriptsWidget();
- if (!w) {
- w = new QScriptDebuggerScriptsWidget();
- d->debugger->setScriptsWidget(w);
- }
- return w;
- }
- case LocalsWidget: {
- QScriptDebuggerLocalsWidgetInterface *w = d->debugger->localsWidget();
- if (!w) {
- w = new QScriptDebuggerLocalsWidget();
- d->debugger->setLocalsWidget(w);
- }
- return w;
- }
- case CodeWidget: {
- QScriptDebuggerCodeWidgetInterface *w = d->debugger->codeWidget();
- if (!w) {
- w = new QScriptDebuggerCodeWidget();
- d->debugger->setCodeWidget(w);
- }
- return w;
- }
- case CodeFinderWidget: {
- QScriptDebuggerCodeFinderWidgetInterface *w = d->debugger->codeFinderWidget();
- if (!w) {
- w = new QScriptDebuggerCodeFinderWidget();
- d->debugger->setCodeFinderWidget(w);
- }
- return w;
- }
- case BreakpointsWidget: {
- QScriptBreakpointsWidgetInterface *w = d->debugger->breakpointsWidget();
- if (!w) {
- w = new QScriptBreakpointsWidget();
- d->debugger->setBreakpointsWidget(w);
- }
- return w;
- }
- case DebugOutputWidget: {
- QScriptDebugOutputWidgetInterface *w = d->debugger->debugOutputWidget();
- if (!w) {
- w = new QScriptDebugOutputWidget();
- d->debugger->setDebugOutputWidget(w);
- }
- return w;
- }
- case ErrorLogWidget: {
- QScriptErrorLogWidgetInterface *w = d->debugger->errorLogWidget();
- if (!w) {
- w = new QScriptErrorLogWidget();
- d->debugger->setErrorLogWidget(w);
- }
- return w;
- }
- }
- return 0;
+ return d->debugger->widget(static_cast<QScriptDebugger::DebuggerWidget>(widget));
}
/*!
@@ -545,39 +436,7 @@ QAction *QScriptEngineDebugger::action(DebuggerAction action) const
Q_D(const QScriptEngineDebugger);
QScriptEngineDebugger *that = const_cast<QScriptEngineDebugger*>(this);
that->d_func()->createDebugger();
- switch (action) {
- case InterruptAction:
- return d->debugger->interruptAction(that);
- case ContinueAction:
- return d->debugger->continueAction(that);
- case StepIntoAction:
- return d->debugger->stepIntoAction(that);
- case StepOverAction:
- return d->debugger->stepOverAction(that);
- case StepOutAction:
- return d->debugger->stepOutAction(that);
- case RunToCursorAction:
- return d->debugger->runToCursorAction(that);
- case RunToNewScriptAction:
- return d->debugger->runToNewScriptAction(that);
- case ToggleBreakpointAction:
- return d->debugger->toggleBreakpointAction(that);
- case ClearDebugOutputAction:
- return d->debugger->clearDebugOutputAction(that);
- case ClearErrorLogAction:
- return d->debugger->clearErrorLogAction(that);
- case ClearConsoleAction:
- return d->debugger->clearConsoleAction(that);
- case FindInScriptAction:
- return d->debugger->findInScriptAction(that);
- case FindNextInScriptAction:
- return d->debugger->findNextInScriptAction(that);
- case FindPreviousInScriptAction:
- return d->debugger->findPreviousInScriptAction(that);
- case GoToLineAction:
- return d->debugger->goToLineAction(that);
- }
- return 0;
+ return d->debugger->action(static_cast<QScriptDebugger::DebuggerAction>(action), that);
}
/*!
diff --git a/src/scripttools/debugging/qscripttooltipproviderinterface_p.h b/src/scripttools/debugging/qscripttooltipproviderinterface_p.h
index 0a273d9..463f087 100644
--- a/src/scripttools/debugging/qscripttooltipproviderinterface_p.h
+++ b/src/scripttools/debugging/qscripttooltipproviderinterface_p.h
@@ -57,6 +57,7 @@
QT_BEGIN_NAMESPACE
+class QPoint;
class QStringList;
class Q_AUTOTEST_EXPORT QScriptToolTipProviderInterface
@@ -64,8 +65,8 @@ class Q_AUTOTEST_EXPORT QScriptToolTipProviderInterface
public:
virtual ~QScriptToolTipProviderInterface() {}
- virtual QString toolTip(int frameIndex, int lineNumber,
- const QStringList &path) = 0;
+ virtual void showToolTip(const QPoint &pos, int frameIndex,
+ int lineNumber, const QStringList &path) = 0;
};
QT_END_NAMESPACE
diff --git a/src/sql/drivers/db2/qsql_db2.cpp b/src/sql/drivers/db2/qsql_db2.cpp
index 11d0041..c7cbc9b 100644
--- a/src/sql/drivers/db2/qsql_db2.cpp
+++ b/src/sql/drivers/db2/qsql_db2.cpp
@@ -1666,7 +1666,7 @@ QVariant QDB2Driver::handle() const
QString QDB2Driver::escapeIdentifier(const QString &identifier, IdentifierType) const
{
QString res = identifier;
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp
index 1645555..199ad8e 100644
--- a/src/sql/drivers/ibase/qsql_ibase.cpp
+++ b/src/sql/drivers/ibase/qsql_ibase.cpp
@@ -1732,7 +1732,7 @@ bool QIBaseDriver::subscribeToNotificationImplementation(const QString &name)
eBuffer->resultBuffer);
if (status[0] == 1 && status[1]) {
- setLastError(QSqlError(QString(QLatin1String("Could not subscribe to event notifications for %1.")).arg(name)));
+ setLastError(QSqlError(QString::fromLatin1("Could not subscribe to event notifications for %1.").arg(name)));
d->eventBuffers.remove(name);
qFreeEventBuffer(eBuffer);
return false;
@@ -1760,7 +1760,7 @@ bool QIBaseDriver::unsubscribeFromNotificationImplementation(const QString &name
isc_cancel_events(status, &d->ibase, &eBuffer->eventId);
if (status[0] == 1 && status[1]) {
- setLastError(QSqlError(QString(QLatin1String("Could not unsubscribe from event notifications for %1.")).arg(name)));
+ setLastError(QSqlError(QString::fromLatin1("Could not unsubscribe from event notifications for %1.").arg(name)));
return false;
}
@@ -1818,7 +1818,7 @@ void QIBaseDriver::qHandleEventNotification(void *updatedResultBuffer)
QString QIBaseDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
{
QString res = identifier;
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
index 53645c9..82ed124 100644
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
@@ -1468,7 +1468,7 @@ QString QMYSQLDriver::formatValue(const QSqlField &field, bool trimStrings) cons
QString QMYSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
{
QString res = identifier;
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('`')) && identifier.right(1) != QString(QLatin1Char('`')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('`')) && !identifier.endsWith(QLatin1Char('`')) ) {
res.prepend(QLatin1Char('`')).append(QLatin1Char('`'));
res.replace(QLatin1Char('.'), QLatin1String("`.`"));
}
@@ -1478,12 +1478,9 @@ QString QMYSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType
bool QMYSQLDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const
{
Q_UNUSED(type);
- bool isLeftDelimited = (identifier.left(1) == QString(QLatin1Char('`')));
- bool isRightDelimited = (identifier.right(1) == QString(QLatin1Char('`')));
- if( identifier.size() > 2 && isLeftDelimited && isRightDelimited )
- return true;
- else
- return false;
+ return identifier.size() > 2
+ && identifier.startsWith(QLatin1Char('`')) //left delimited
+ && identifier.endsWith(QLatin1Char('`')); //right delimited
}
QT_END_NAMESPACE
diff --git a/src/sql/drivers/oci/qsql_oci.cpp b/src/sql/drivers/oci/qsql_oci.cpp
index a7031b1..e6ee63d 100644
--- a/src/sql/drivers/oci/qsql_oci.cpp
+++ b/src/sql/drivers/oci/qsql_oci.cpp
@@ -2040,8 +2040,8 @@ bool QOCIDriver::open(const QString & db,
QString connectionString = db;
if (!hostname.isEmpty())
connectionString =
- QString(QLatin1String("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=%1)(Port=%2))"
- "(CONNECT_DATA=(SID=%3)))")).arg(hostname).arg((port > -1 ? port : 1521)).arg(db);
+ QString::fromLatin1("(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(Host=%1)(Port=%2))"
+ "(CONNECT_DATA=(SID=%3)))").arg(hostname).arg((port > -1 ? port : 1521)).arg(db);
r = OCIHandleAlloc(d->env, reinterpret_cast<void **>(&d->srvhp), OCI_HTYPE_SERVER, 0, 0);
if (r == OCI_SUCCESS)
@@ -2219,7 +2219,7 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
while (t.next()) {
if (t.value(0).toString().toUpper() != user.toUpper())
- tl.append(t.value(0).toString() + QLatin1String(".") + t.value(1).toString());
+ tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
else
tl.append(t.value(1).toString());
}
@@ -2235,7 +2235,7 @@ QStringList QOCIDriver::tables(QSql::TableType type) const
"and owner != 'WMSYS'"));
while (t.next()) {
if (t.value(0).toString().toUpper() != d->user.toUpper())
- tl.append(t.value(0).toString() + QLatin1String(".") + t.value(1).toString());
+ tl.append(t.value(0).toString() + QLatin1Char('.') + t.value(1).toString());
else
tl.append(t.value(1).toString());
}
@@ -2297,7 +2297,7 @@ QSqlRecord QOCIDriver::record(const QString& tablename) const
else
owner = owner.toUpper();
- tmpStmt += QLatin1String(" and owner='") + owner + QLatin1String("'");
+ tmpStmt += QLatin1String(" and owner='") + owner + QLatin1Char('\'');
t.setForwardOnly(true);
t.exec(tmpStmt);
if (!t.next()) { // try and see if the tablename is a synonym
@@ -2352,7 +2352,7 @@ QSqlIndex QOCIDriver::primaryIndex(const QString& tablename) const
else
table = table.toUpper();
- tmpStmt = stmt + QLatin1String(" and a.table_name='") + table + QLatin1String("'");
+ tmpStmt = stmt + QLatin1String(" and a.table_name='") + table + QLatin1Char('\'');
if (owner.isEmpty()) {
owner = d->user;
}
@@ -2362,7 +2362,7 @@ QSqlIndex QOCIDriver::primaryIndex(const QString& tablename) const
else
owner = owner.toUpper();
- tmpStmt += QLatin1String(" and a.owner='") + owner + QLatin1String("'");
+ tmpStmt += QLatin1String(" and a.owner='") + owner + QLatin1Char('\'');
t.setForwardOnly(true);
t.exec(tmpStmt);
@@ -2386,7 +2386,7 @@ QSqlIndex QOCIDriver::primaryIndex(const QString& tablename) const
tt.exec(QLatin1String("select data_type from all_tab_columns where table_name='") +
t.value(2).toString() + QLatin1String("' and column_name='") +
t.value(0).toString() + QLatin1String("' and owner='") +
- owner +QLatin1String("'"));
+ owner + QLatin1Char('\''));
if (!tt.next()) {
return QSqlIndex();
}
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index ee500a0..8eaa8bf 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -213,14 +213,14 @@ static QString qWarnODBCHandle(int handleType, SQLHANDLE handle, int *nativeCode
static QString qODBCWarn(const QODBCPrivate* odbc, int *nativeCode = 0)
{
- return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1String(" ")
- + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc) + QLatin1String(" ")
+ return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1Char(' ')
+ + qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc) + QLatin1Char(' ')
+ qWarnODBCHandle(SQL_HANDLE_STMT, odbc->hStmt, nativeCode));
}
static QString qODBCWarn(const QODBCDriverPrivate* odbc, int *nativeCode = 0)
{
- return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1String(" ")
+ return (qWarnODBCHandle(SQL_HANDLE_ENV, odbc->hEnv) + QLatin1Char(' ')
+ qWarnODBCHandle(SQL_HANDLE_DBC, odbc->hDbc, nativeCode));
}
@@ -2414,12 +2414,12 @@ QString QODBCDriver::escapeIdentifier(const QString &identifier, IdentifierType)
{
QString res = identifier;
if (d->isMySqlServer) {
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('`')) && identifier.right(1) != QString(QLatin1Char('`')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('`')) && !identifier.endsWith(QLatin1Char('`')) ) {
res.prepend(QLatin1Char('`')).append(QLatin1Char('`'));
res.replace(QLatin1Char('.'), QLatin1String("`.`"));
}
} else {
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
@@ -2430,13 +2430,10 @@ QString QODBCDriver::escapeIdentifier(const QString &identifier, IdentifierType)
bool QODBCDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType) const
{
- QString quote = d->quoteChar();
- bool isLeftDelimited = identifier.left(1) == quote;
- bool isRightDelimited = identifier.right(1) == quote;
- if( identifier.size() > 2 && isLeftDelimited && isRightDelimited )
- return true;
- else
- return false;
+ QChar quote = d->quoteChar();
+ return identifier.size() > 2
+ && identifier.startsWith(quote) //left delimited
+ && identifier.endsWith(quote); //right delimited
}
QT_END_NAMESPACE
diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp
index 16d19f1..ce0b8c5 100644
--- a/src/sql/drivers/psql/qsql_psql.cpp
+++ b/src/sql/drivers/psql/qsql_psql.cpp
@@ -541,7 +541,7 @@ bool QPSQLResult::prepare(const QString &query)
qDeallocatePreparedStmt(d);
const QString stmtId = qMakePreparedStmtId();
- const QString stmt = QString(QLatin1String("PREPARE %1 AS ")).arg(stmtId).append(qReplacePlaceholderMarkers(query));
+ const QString stmt = QString::fromLatin1("PREPARE %1 AS ").arg(stmtId).append(qReplacePlaceholderMarkers(query));
PGresult *result = PQexec(d->driver->connection,
d->driver->isUtf8 ? stmt.toUtf8().constData()
@@ -570,9 +570,9 @@ bool QPSQLResult::exec()
QString stmt;
const QString params = qCreateParamString(boundValues(), d->q->driver());
if (params.isEmpty())
- stmt = QString(QLatin1String("EXECUTE %1")).arg(d->preparedStmtId);
+ stmt = QString::fromLatin1("EXECUTE %1").arg(d->preparedStmtId);
else
- stmt = QString(QLatin1String("EXECUTE %1 (%2)")).arg(d->preparedStmtId).arg(params);
+ stmt = QString::fromLatin1("EXECUTE %1 (%2)").arg(d->preparedStmtId).arg(params);
d->result = PQexec(d->driver->connection,
d->driver->isUtf8 ? stmt.toUtf8().constData()
@@ -1102,12 +1102,12 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
QTime tm = field.value().toDateTime().time();
// msecs need to be right aligned otherwise psql
// interpretes them wrong
- r = QLatin1String("'") + QString::number(dt.year()) + QLatin1String("-")
- + QString::number(dt.month()) + QLatin1String("-")
- + QString::number(dt.day()) + QLatin1String(" ")
- + tm.toString() + QLatin1String(".")
+ r = QLatin1Char('\'') + QString::number(dt.year()) + QLatin1Char('-')
+ + QString::number(dt.month()) + QLatin1Char('-')
+ + QString::number(dt.day()) + QLatin1Char(' ')
+ + tm.toString() + QLatin1Char('.')
+ QString::number(tm.msec()).rightJustified(3, QLatin1Char('0'))
- + QLatin1String("'");
+ + QLatin1Char('\'');
} else {
r = QLatin1String("NULL");
}
@@ -1162,7 +1162,7 @@ QString QPSQLDriver::formatValue(const QSqlField &field, bool trimStrings) const
QString QPSQLDriver::escapeIdentifier(const QString &identifier, IdentifierType) const
{
QString res = identifier;
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
@@ -1195,7 +1195,7 @@ bool QPSQLDriver::subscribeToNotificationImplementation(const QString &name)
int socket = PQsocket(d->connection);
if (socket) {
- QString query = QString(QLatin1String("LISTEN %1")).arg(escapeIdentifier(name, QSqlDriver::TableName));
+ QString query = QLatin1String("LISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
if (PQresultStatus(PQexec(d->connection,
d->isUtf8 ? query.toUtf8().constData()
: query.toLocal8Bit().constData())
@@ -1227,7 +1227,7 @@ bool QPSQLDriver::unsubscribeFromNotificationImplementation(const QString &name)
return false;
}
- QString query = QString(QLatin1String("UNLISTEN %1")).arg(escapeIdentifier(name, QSqlDriver::TableName));
+ QString query = QLatin1String("UNLISTEN ") + escapeIdentifier(name, QSqlDriver::TableName);
if (PQresultStatus(PQexec(d->connection,
d->isUtf8 ? query.toUtf8().constData()
: query.toLocal8Bit().constData())
diff --git a/src/sql/drivers/sqlite/qsql_sqlite.cpp b/src/sql/drivers/sqlite/qsql_sqlite.cpp
index f732077..05d63ca 100644
--- a/src/sql/drivers/sqlite/qsql_sqlite.cpp
+++ b/src/sql/drivers/sqlite/qsql_sqlite.cpp
@@ -631,9 +631,9 @@ static QSqlIndex qGetTableInfo(QSqlQuery &q, const QString &tableName, bool only
{
QString schema;
QString table(tableName);
- int indexOfSeparator = tableName.indexOf(QLatin1String("."));
+ int indexOfSeparator = tableName.indexOf(QLatin1Char('.'));
if (indexOfSeparator > -1) {
- schema = tableName.left(indexOfSeparator).append(QLatin1String("."));
+ schema = tableName.left(indexOfSeparator).append(QLatin1Char('.'));
table = tableName.mid(indexOfSeparator + 1);
}
q.exec(QLatin1String("PRAGMA ") + schema + QLatin1String("table_info ('") + table + QLatin1String("')"));
diff --git a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
index d0c6e18..cb72ff0 100644
--- a/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
+++ b/src/sql/drivers/sqlite2/qsql_sqlite2.cpp
@@ -170,8 +170,8 @@ void QSQLite2ResultPrivate::init(const char **cnames, int numCols)
//remove quotations around the field name if any
QString fieldStr = QString::fromAscii(fieldName);
- QString quote = QString::fromLatin1("\"");
- if ( fieldStr.length() > 2 && fieldStr.left(1) == quote && fieldStr.right(1) == quote) {
+ QLatin1Char quote('\"');
+ if ( fieldStr.length() > 2 && fieldStr.startsWith(quote) && fieldStr.endsWith(quote)) {
fieldStr = fieldStr.mid(1);
fieldStr.chop(1);
}
@@ -561,7 +561,7 @@ QVariant QSQLite2Driver::handle() const
QString QSQLite2Driver::escapeIdentifier(const QString &identifier, IdentifierType /*type*/) const
{
QString res = identifier;
- if(!identifier.isEmpty() && identifier.left(1) != QString(QLatin1Char('"')) && identifier.right(1) != QString(QLatin1Char('"')) ) {
+ if(!identifier.isEmpty() && !identifier.startsWith(QLatin1Char('"')) && !identifier.endsWith(QLatin1Char('"')) ) {
res.replace(QLatin1Char('"'), QLatin1String("\"\""));
res.prepend(QLatin1Char('"')).append(QLatin1Char('"'));
res.replace(QLatin1Char('.'), QLatin1String("\".\""));
diff --git a/src/sql/drivers/tds/qsql_tds.cpp b/src/sql/drivers/tds/qsql_tds.cpp
index 515f0de..298b008 100644
--- a/src/sql/drivers/tds/qsql_tds.cpp
+++ b/src/sql/drivers/tds/qsql_tds.cpp
@@ -181,7 +181,7 @@ static int CS_PUBLIC qTdsMsgHandler (DBPROCESS* dbproc,
}
if (severity > 0) {
- QString errMsg = QString(QLatin1String("%1 (%2)")).arg(QString::fromAscii(msgtext)).arg(
+ QString errMsg = QString::fromLatin1("%1 (%2)").arg(QString::fromAscii(msgtext)).arg(
msgstate);
p->addErrorMsg(errMsg);
}
@@ -211,8 +211,8 @@ static int CS_PUBLIC qTdsErrHandler(DBPROCESS* dbproc,
}
- QString errMsg = QString(QLatin1String("%1 %2\n")).arg(QString::fromAscii(dberrstr)).arg(
- QString::fromAscii(oserrstr));
+ QString errMsg = QString::fromLatin1("%1 %2\n").arg(QLatin1String(dberrstr)).arg(
+ QLatin1String(oserrstr));
errMsg += p->getErrorMsgs();
p->lastError = qMakeError(errMsg, QSqlError::UnknownError, dberr);
p->clearErrorMsgs();
diff --git a/src/sql/kernel/qsqldriver.cpp b/src/sql/kernel/qsqldriver.cpp
index 40bc0df..477d531 100644
--- a/src/sql/kernel/qsqldriver.cpp
+++ b/src/sql/kernel/qsqldriver.cpp
@@ -520,7 +520,7 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
continue;
s.append(prepareIdentifier(rec.fieldName(i), QSqlDriver::FieldName, this)).append(QLatin1String(", "));
if (preparedStatement)
- vals.append(QLatin1String("?"));
+ vals.append(QLatin1Char('?'));
else
vals.append(formatValue(rec.field(i)));
vals.append(QLatin1String(", "));
@@ -530,7 +530,7 @@ QString QSqlDriver::sqlStatement(StatementType type, const QString &tableName,
} else {
vals.chop(2); // remove trailing comma
s[s.length() - 2] = QLatin1Char(')');
- s.append(QLatin1String("VALUES (")).append(vals).append(QLatin1String(")"));
+ s.append(QLatin1String("VALUES (")).append(vals).append(QLatin1Char(')'));
}
break; }
}
@@ -625,10 +625,7 @@ QString QSqlDriver::formatValue(const QSqlField &field, bool trimStrings) const
break;
}
case QVariant::Bool:
- if (field.value().toBool())
- r = QLatin1String("1");
- else
- r = QLatin1String("0");
+ r = QString::number(field.value().toBool());
break;
case QVariant::ByteArray : {
if (hasFeature(BLOB)) {
@@ -884,12 +881,9 @@ QStringList QSqlDriver::subscribedToNotificationsImplementation() const
bool QSqlDriver::isIdentifierEscapedImplementation(const QString &identifier, IdentifierType type) const
{
Q_UNUSED(type);
- bool isLeftDelimited = identifier.left(1) == QString(QLatin1Char('"'));
- bool isRightDelimited = identifier.right(1) == QString(QLatin1Char('"'));
- if( identifier.size() > 2 && isLeftDelimited && isRightDelimited )
- return true;
- else
- return false;
+ return identifier.size() > 2
+ && identifier.startsWith(QLatin1Char('"')) //left delimited
+ && identifier.endsWith(QLatin1Char('"')); //right delimited
}
/*!
diff --git a/src/sql/kernel/qsqlerror.cpp b/src/sql/kernel/qsqlerror.cpp
index 14fc050..b1fa6e2 100644
--- a/src/sql/kernel/qsqlerror.cpp
+++ b/src/sql/kernel/qsqlerror.cpp
@@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
QDebug operator<<(QDebug dbg, const QSqlError &s)
{
dbg.nospace() << "QSqlError(" << s.number() << ", " << s.driverText() <<
- ", " << s.databaseText() << ")";
+ ", " << s.databaseText() << ')';
return dbg.space();
}
#endif
diff --git a/src/sql/kernel/qsqlfield.cpp b/src/sql/kernel/qsqlfield.cpp
index 4c1f1f4..80f193f 100644
--- a/src/sql/kernel/qsqlfield.cpp
+++ b/src/sql/kernel/qsqlfield.cpp
@@ -523,8 +523,8 @@ QDebug operator<<(QDebug dbg, const QSqlField &f)
if (f.typeID() >= 0)
dbg.nospace() << ", typeID: " << f.typeID();
if (!f.defaultValue().isNull())
- dbg.nospace() << ", auto-value: \"" << f.defaultValue() << "\"";
- dbg.nospace() << ")";
+ dbg.nospace() << ", auto-value: \"" << f.defaultValue() << '\"';
+ dbg.nospace() << ')';
return dbg.space();
#else
qWarning("This compiler doesn't support streaming QSqlField to QDebug");
diff --git a/src/sql/kernel/qsqlrecord.cpp b/src/sql/kernel/qsqlrecord.cpp
index 0162664..95f6020 100644
--- a/src/sql/kernel/qsqlrecord.cpp
+++ b/src/sql/kernel/qsqlrecord.cpp
@@ -589,7 +589,7 @@ void QSqlRecord::detach()
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug dbg, const QSqlRecord &r)
{
- dbg << "QSqlRecord(" << r.count() << ")";
+ dbg << "QSqlRecord(" << r.count() << ')';
for (int i = 0; i < r.count(); ++i)
dbg << '\n' << QString::fromLatin1("%1:").arg(i, 2) << r.field(i) << r.value(i).toString();
return dbg;
diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp
index 12eae84..1b8fb4c 100644
--- a/src/sql/models/qsqlrelationaltablemodel.cpp
+++ b/src/sql/models/qsqlrelationaltablemodel.cpp
@@ -573,7 +573,7 @@ QString QSqlRelationalTableModel::selectStatement() const
}
// this needs fixing!! the below if is borken.
- tables.append(relation.tableName().append(QLatin1String(" ")).append(relTableAlias));
+ tables.append(relation.tableName().append(QLatin1Char(' ')).append(relTableAlias));
if(!where.isEmpty())
where.append(QLatin1String(" AND "));
where.append(d->relationField(tableName(), d->db.driver()->escapeIdentifier(rec.fieldName(i), QSqlDriver::FieldName)));
diff --git a/src/svg/qgraphicssvgitem.cpp b/src/svg/qgraphicssvgitem.cpp
index e17df03..a14636e 100644
--- a/src/svg/qgraphicssvgitem.cpp
+++ b/src/svg/qgraphicssvgitem.cpp
@@ -186,7 +186,7 @@ static void qt_graphicsItem_highlightSelected(
QGraphicsItem *item, QPainter *painter, const QStyleOptionGraphicsItem *option)
{
const QRectF murect = painter->transform().mapRect(QRectF(0, 0, 1, 1));
- if (qFuzzyCompare(qMax(murect.width(), murect.height()) + 1, 1))
+ if (qFuzzyIsNull(qMax(murect.width(), murect.height())))
return;
const QRectF mbrect = painter->transform().mapRect(item->boundingRect());
diff --git a/src/svg/qsvggenerator.cpp b/src/svg/qsvggenerator.cpp
index 5052ec7..70a6e63 100644
--- a/src/svg/qsvggenerator.cpp
+++ b/src/svg/qsvggenerator.cpp
@@ -362,7 +362,7 @@ public:
translate_dashPattern(spen.dashPattern(), penWidth, &dashPattern);
// SVG uses absolute offset
- dashOffset = QString::fromLatin1("%1").arg(spen.dashOffset() * penWidth);
+ dashOffset = QString::number(spen.dashOffset() * penWidth);
d_func()->attributes.stroke = color;
d_func()->attributes.strokeOpacity = colorOpacity;
@@ -403,8 +403,8 @@ public:
}
switch (spen.joinStyle()) {
case Qt::MiterJoin:
- stream() << "stroke-linejoin=\"miter\" ";
- stream() << "stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";
+ stream() << "stroke-linejoin=\"miter\" "
+ "stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";
break;
case Qt::BevelJoin:
stream() << "stroke-linejoin=\"bevel\" ";
@@ -413,8 +413,8 @@ public:
stream() << "stroke-linejoin=\"round\" ";
break;
case Qt::SvgMiterJoin:
- stream() << "stroke-linejoin=\"miter\" ";
- stream() << "stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";
+ stream() << "stroke-linejoin=\"miter\" "
+ "stroke-miterlimit=\""<<spen.miterLimit()<<"\" ";
break;
default:
qWarning("Unhandled join style");
@@ -427,8 +427,8 @@ public:
case Qt::SolidPattern: {
QString color, colorOpacity;
translate_color(sbrush.color(), &color, &colorOpacity);
- stream() << "fill=\"" << color << "\" ";
- stream() << "fill-opacity=\""
+ stream() << "fill=\"" << color << "\" "
+ "fill-opacity=\""
<< colorOpacity << "\" ";
d_func()->attributes.fill = color;
d_func()->attributes.fillOpacity = colorOpacity;
@@ -493,9 +493,9 @@ public:
d->attributes.font_style = d->font.italic() ? QLatin1String("italic") : QLatin1String("normal");
*d->stream << "font-family=\"" << d->attributes.font_family << "\" "
- << "font-size=\"" << d->attributes.font_size << "\" "
- << "font-weight=\"" << d->attributes.font_weight << "\" "
- << "font-style=\"" << d->attributes.font_style << "\" "
+ "font-size=\"" << d->attributes.font_size << "\" "
+ "font-weight=\"" << d->attributes.font_weight << "\" "
+ "font-style=\"" << d->attributes.font_style << "\" "
<< endl;
}
};
@@ -848,13 +848,13 @@ bool QSvgPaintEngine::begin(QPaintDevice *)
}
if (d->viewBox.isValid()) {
- *d->stream << " viewBox=\"" << d->viewBox.left() << " " << d->viewBox.top();
- *d->stream << " " << d->viewBox.width() << " " << d->viewBox.height() << "\"" << endl;
+ *d->stream << " viewBox=\"" << d->viewBox.left() << ' ' << d->viewBox.top();
+ *d->stream << ' ' << d->viewBox.width() << ' ' << d->viewBox.height() << '\"' << endl;
}
*d->stream << " xmlns=\"http://www.w3.org/2000/svg\""
- << " xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
- << " version=\"1.2\" baseProfile=\"tiny\">" << endl;
+ " xmlns:xlink=\"http://www.w3.org/1999/xlink\" "
+ " version=\"1.2\" baseProfile=\"tiny\">" << endl;
if (!d->attributes.document_title.isEmpty()) {
*d->stream << "<title>" << d->attributes.document_title << "</title>" << endl;
@@ -917,10 +917,10 @@ void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,
Q_UNUSED(sr);
Q_UNUSED(flags);
stream() << "<image ";
- stream() << "x=\""<<r.x()<<"\" ";
- stream() << "y=\""<<r.y()<<"\" ";
- stream() << "width=\""<<r.width()<<"\" ";
- stream() << "height=\""<<r.height()<<"\" ";
+ stream() << "x=\""<<r.x()<<"\" "
+ "y=\""<<r.y()<<"\" "
+ "width=\""<<r.width()<<"\" "
+ "height=\""<<r.height()<<"\" ";
QByteArray data;
QBuffer buffer(&data);
@@ -929,8 +929,7 @@ void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,
buffer.close();
stream() << "xlink:href=\"data:image/png;base64,"
<< data.toBase64()
- <<"\" ";
- stream() << "/>\n";
+ <<"\" />\n";
}
void QSvgPaintEngine::updateState(const QPaintEngineState &state)
@@ -957,10 +956,10 @@ void QSvgPaintEngine::updateState(const QPaintEngineState &state)
if (flags & QPaintEngine::DirtyTransform) {
d->matrix = state.matrix();
- *d->stream << "transform=\"matrix(" << d->matrix.m11() << ","
- << d->matrix.m12() << ","
- << d->matrix.m21() << "," << d->matrix.m22() << ","
- << d->matrix.dx() << "," << d->matrix.dy()
+ *d->stream << "transform=\"matrix(" << d->matrix.m11() << ','
+ << d->matrix.m12() << ','
+ << d->matrix.m21() << ',' << d->matrix.m22() << ','
+ << d->matrix.dx() << ',' << d->matrix.dy()
<< ")\""
<< endl;
}
@@ -970,11 +969,11 @@ void QSvgPaintEngine::updateState(const QPaintEngineState &state)
}
if (flags & QPaintEngine::DirtyOpacity) {
- if (!qFuzzyCompare(state.opacity(), 1))
+ if (!qFuzzyIsNull(state.opacity() - 1))
stream() << "opacity=\""<<state.opacity()<<"\" ";
}
- *d->stream << ">" << endl;
+ *d->stream << '>' << endl;
d->afterFirstUpdate = true;
}
@@ -983,10 +982,8 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p)
{
Q_D(QSvgPaintEngine);
- *d->stream << "<path ";
-
-
- *d->stream << "fill-rule=";
+ *d->stream << "<path "
+ "fill-rule=";
if (p.fillRule() == Qt::OddEvenFill)
*d->stream << "\"evenodd\" ";
else
@@ -998,13 +995,13 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p)
const QPainterPath::Element &e = p.elementAt(i);
switch (e.type) {
case QPainterPath::MoveToElement:
- *d->stream << "M" << e.x << "," << e.y;
+ *d->stream << 'M' << e.x << ',' << e.y;
break;
case QPainterPath::LineToElement:
- *d->stream << "L" << e.x << "," << e.y;
+ *d->stream << 'L' << e.x << ',' << e.y;
break;
case QPainterPath::CurveToElement:
- *d->stream << "C" << e.x << "," << e.y;
+ *d->stream << 'C' << e.x << ',' << e.y;
++i;
while (i < p.elementCount()) {
const QPainterPath::Element &e = p.elementAt(i);
@@ -1012,8 +1009,8 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p)
--i;
break;
} else
- *d->stream << " ";
- *d->stream << e.x << "," << e.y;
+ *d->stream << ' ';
+ *d->stream << e.x << ',' << e.y;
++i;
}
break;
@@ -1021,7 +1018,7 @@ void QSvgPaintEngine::drawPath(const QPainterPath &p)
break;
}
if (i != p.elementCount() - 1) {
- *d->stream << " ";
+ *d->stream << ' ';
}
}
@@ -1043,7 +1040,7 @@ void QSvgPaintEngine::drawPolygon(const QPointF *points, int pointCount,
stream() << "<polyline fill=\"none\" points=\"";
for (int i = 0; i < pointCount; ++i) {
const QPointF &pt = points[i];
- stream() << pt.x() << "," << pt.y() << " ";
+ stream() << pt.x() << ',' << pt.y() << ' ';
}
stream() << "\" />" <<endl;
} else {
@@ -1062,10 +1059,10 @@ void QSvgPaintEngine::drawTextItem(const QPointF &pt, const QTextItem &textItem)
QString s = QString::fromRawData(ti.chars, ti.num_chars);
*d->stream << "<text "
- << "fill=\"" << d->attributes.stroke << "\" "
- << "fill-opacity=\"" << d->attributes.strokeOpacity << "\" "
- << "stroke=\"none\" "
- << "x=\"" << pt.x() << "\" y=\"" << pt.y() << "\" ";
+ "fill=\"" << d->attributes.stroke << "\" "
+ "fill-opacity=\"" << d->attributes.strokeOpacity << "\" "
+ "stroke=\"none\" "
+ "x=\"" << pt.x() << "\" y=\"" << pt.y() << "\" ";
qfontToSvg(textItem.font());
*d->stream << " >"
<< Qt::escape(s)
diff --git a/src/svg/qsvggraphics.cpp b/src/svg/qsvggraphics.cpp
index 9ff9c26..1cd1f8b 100644
--- a/src/svg/qsvggraphics.cpp
+++ b/src/svg/qsvggraphics.cpp
@@ -94,7 +94,7 @@ QSvgCircle::QSvgCircle(QSvgNode *parent, const QRectF &rect)
QRectF QSvgCircle::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_bounds;
else {
QPainterPath path;
@@ -129,7 +129,7 @@ QSvgEllipse::QSvgEllipse(QSvgNode *parent, const QRectF &rect)
QRectF QSvgEllipse::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_bounds;
else {
QPainterPath path;
@@ -190,7 +190,7 @@ void QSvgPath::draw(QPainter *p, QSvgExtraStates &states)
QRectF QSvgPath::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_cachedBounds;
else {
return boundsOnStroke(m_path, sw);
@@ -206,7 +206,7 @@ QSvgPolygon::QSvgPolygon(QSvgNode *parent, const QPolygonF &poly)
QRectF QSvgPolygon::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_poly.boundingRect();
else {
QPainterPath path;
@@ -249,7 +249,7 @@ QSvgRect::QSvgRect(QSvgNode *node, const QRectF &rect, int rx, int ry)
QRectF QSvgRect::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_rect;
else {
QPainterPath path;
@@ -596,7 +596,7 @@ QRectF QSvgUse::transformedBounds(const QTransform &transform) const
QRectF QSvgPolyline::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_poly.boundingRect();
else {
QPainterPath path;
@@ -608,7 +608,7 @@ QRectF QSvgPolyline::bounds() const
QRectF QSvgArc::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1))
+ if (qFuzzyIsNull(sw))
return m_cachedBounds;
else {
return boundsOnStroke(cubic, sw);
@@ -623,7 +623,7 @@ QRectF QSvgImage::bounds() const
QRectF QSvgLine::bounds() const
{
qreal sw = strokeWidth();
- if (qFuzzyCompare(sw + 1, 1)) {
+ if (qFuzzyIsNull(sw)) {
qreal minX = qMin(m_bounds.x1(), m_bounds.x2());
qreal minY = qMin(m_bounds.y1(), m_bounds.y2());
qreal maxX = qMax(m_bounds.x1(), m_bounds.x2());
diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp
index 6a897e8..c5026b8 100644
--- a/src/svg/qsvghandler.cpp
+++ b/src/svg/qsvghandler.cpp
@@ -2550,6 +2550,9 @@ static QSvgNode *createImageNode(QSvgNode *parent,
return 0;
}
+ if (image.format() == QImage::Format_ARGB32)
+ image = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
+
QSvgNode *img = new QSvgImage(parent,
image,
QRect(int(nx),
diff --git a/src/testlib/qabstracttestlogger.cpp b/src/testlib/qabstracttestlogger.cpp
index e5d5d59..a884641 100644
--- a/src/testlib/qabstracttestlogger.cpp
+++ b/src/testlib/qabstracttestlogger.cpp
@@ -77,6 +77,7 @@ bool QAbstractTestLogger::isTtyOutput()
#endif
}
+
void QAbstractTestLogger::startLogging()
{
QTEST_ASSERT(!QTest::stream);
diff --git a/src/testlib/qbenchmark.cpp b/src/testlib/qbenchmark.cpp
index 64594c1..d048672 100644
--- a/src/testlib/qbenchmark.cpp
+++ b/src/testlib/qbenchmark.cpp
@@ -1,4 +1,3 @@
-
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
diff --git a/src/testlib/qbenchmark_p.h b/src/testlib/qbenchmark_p.h
index 8bb6e84..f3cd094 100644
--- a/src/testlib/qbenchmark_p.h
+++ b/src/testlib/qbenchmark_p.h
@@ -55,7 +55,7 @@
#include <QtCore/qglobal.h>
-#if defined(Q_OS_LINUX) && !defined(QT_NO_PROCESS)
+#if (defined(Q_OS_LINUX) || defined Q_OS_MAC) && !defined(QT_NO_PROCESS)
#define QTESTLIB_USE_VALGRIND
#else
#undef QTESTLIB_USE_VALGRIND
@@ -81,7 +81,7 @@ struct QBenchmarkContext
QString toString() const
{
- QString s = QString(QLatin1String("%1,%2,%3")).arg(slotName).arg(tag).arg(checkpointIndex);
+ QString s = QString::fromLatin1("%1,%2,%3").arg(slotName).arg(tag).arg(checkpointIndex);
return s;
}
diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp
index 4b4ccd7..c61460d 100644
--- a/src/testlib/qbenchmarkvalgrind.cpp
+++ b/src/testlib/qbenchmarkvalgrind.cpp
@@ -1,4 +1,3 @@
-
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
@@ -52,6 +51,8 @@
#include <QtCore/qset.h>
#include "3rdparty/callgrind_p.h"
+QT_BEGIN_NAMESPACE
+
// Returns true iff a sufficiently recent valgrind is available.
bool QBenchmarkValgrindUtils::haveValgrind()
{
@@ -132,12 +133,12 @@ QString QBenchmarkValgrindUtils::getNewestFileName()
QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
Q_ASSERT(!base.isEmpty());
- nameFilters << QString(QLatin1String("%1.*")).arg(base);
+ nameFilters << QString::fromLatin1("%1.*").arg(base);
QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
Q_ASSERT(!fiList.empty());
int hiSuffix = -1;
QFileInfo lastFileInfo;
- const QString pattern = QString(QLatin1String("%1.(\\d+)")).arg(base);
+ const QString pattern = QString::fromLatin1("%1.(\\d+)").arg(base);
const QRegExp rx(pattern);
foreach (QFileInfo fileInfo, fiList) {
const int index = rx.indexIn(fileInfo.fileName());
@@ -167,8 +168,8 @@ void QBenchmarkValgrindUtils::cleanup()
QString base = QBenchmarkGlobalData::current->callgrindOutFileBase;
Q_ASSERT(!base.isEmpty());
nameFilters
- << QString(QLatin1String("%1")).arg(base) // overall summary
- << QString(QLatin1String("%1.*")).arg(base); // individual dumps
+ << base // overall summary
+ << QString::fromLatin1("%1.*").arg(base); // individual dumps
QFileInfoList fiList = QDir().entryInfoList(nameFilters, QDir::Files | QDir::Readable);
foreach (QFileInfo fileInfo, fiList) {
const bool removeOk = QFile::remove(fileInfo.fileName());
@@ -179,7 +180,7 @@ void QBenchmarkValgrindUtils::cleanup()
QString QBenchmarkValgrindUtils::outFileBase(qint64 pid)
{
- return QString(QLatin1String("callgrind.out.%1")).arg(
+ return QString::fromLatin1("callgrind.out.%1").arg(
pid != -1 ? pid : QCoreApplication::applicationPid());
}
@@ -272,4 +273,6 @@ QString QBenchmarkCallgrindMeasurer::metricText()
return QLatin1String("callgrind");
}
+QT_END_NAMESPACE
+
#endif // QTESTLIB_USE_VALGRIND
diff --git a/src/testlib/qplaintestlogger.cpp b/src/testlib/qplaintestlogger.cpp
index c408c1c..78c9a85 100644
--- a/src/testlib/qplaintestlogger.cpp
+++ b/src/testlib/qplaintestlogger.cpp
@@ -226,9 +226,9 @@ namespace QTest {
template <typename T> QString formatResult(T number, int significantDigits)
{
if (number < T(0))
- return QString(QLatin1String("NAN"));
+ return QLatin1String("NAN");
if (number == T(0))
- return QString(QLatin1String("0"));
+ return QLatin1String("0");
QString beforeDecimalPoint = QString::number(qint64(number), 'f', 0);
QString afterDecimalPoint = QString::number(number, 'f', 20);
diff --git a/src/testlib/qsignaldumper.cpp b/src/testlib/qsignaldumper.cpp
index 0a32a6d..3a9d75e 100644
--- a/src/testlib/qsignaldumper.cpp
+++ b/src/testlib/qsignaldumper.cpp
@@ -87,7 +87,7 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv
str.fill(' ', QTest::iLevel++ * QTest::IndentSpacesCount);
str += "Signal: ";
str += mo->className();
- str += "(";
+ str += '(';
QString objname = caller->objectName();
str += objname.toLocal8Bit();
@@ -114,15 +114,15 @@ static void qSignalDumperCallback(QObject *caller, int method_index, void **argv
str.append(QByteArray::number(addr, 16));
} else if (typeId != QMetaType::Void) {
str.append(arg)
- .append("(")
+ .append('(')
.append(QVariant(typeId, argv[i + 1]).toString().toLocal8Bit())
- .append(")");
+ .append(')');
}
str.append(", ");
}
if (str.endsWith(", "))
str.chop(2);
- str.append(")");
+ str.append(')');
qPrintMessage(str);
}
@@ -143,7 +143,7 @@ static void qSignalDumperCallbackSlot(QObject *caller, int method_index, void **
str.fill(' ', QTest::iLevel * QTest::IndentSpacesCount);
str += "Slot: ";
str += mo->className();
- str += "(";
+ str += '(';
QString objname = caller->objectName();
str += objname.toLocal8Bit();
diff --git a/src/testlib/qtestbasicstreamer.cpp b/src/testlib/qtestbasicstreamer.cpp
new file mode 100644
index 0000000..f22b3d2
--- /dev/null
+++ b/src/testlib/qtestbasicstreamer.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestbasicstreamer.h"
+#include "qtestlogger_p.h"
+#include "qtestelement.h"
+#include "qtestelementattribute.h"
+#include "QtTest/private/qtestlog_p.h"
+#include "qtestassert.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#ifndef Q_OS_WIN
+#include <unistd.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+namespace QTest
+{
+ static FILE *stream = 0;
+}
+
+QTestBasicStreamer::QTestBasicStreamer()
+ :testLogger(0)
+{
+}
+
+QTestBasicStreamer::~QTestBasicStreamer()
+{}
+
+void QTestBasicStreamer::formatStart(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestBasicStreamer::formatEnd(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestBasicStreamer::formatBeforeAttributes(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestBasicStreamer::formatAfterAttributes(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestBasicStreamer::formatAttributes(const QTestElement *, const QTestElementAttribute *attribute, char *formatted) const
+{
+ if(!attribute || !formatted )
+ return;
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestBasicStreamer::output(QTestElement *element) const
+{
+ if(!element)
+ return;
+
+ outputElements(element);
+}
+
+void QTestBasicStreamer::outputElements(QTestElement *element, bool) const
+{
+ char buf[1024];
+ bool hasChildren;
+ /*
+ Elements are in reverse order of occurrence, so start from the end and work
+ our way backwards.
+ */
+ while (element && element->nextElement()) {
+ element = element->nextElement();
+ }
+ while (element) {
+ hasChildren = element->childElements();
+
+ formatStart(element, buf);
+ outputString(buf);
+
+ formatBeforeAttributes(element, buf);
+ outputString(buf);
+
+ outputElementAttributes(element, element->attributes());
+
+ formatAfterAttributes(element, buf);
+ outputString(buf);
+
+ if(hasChildren)
+ outputElements(element->childElements(), true);
+
+ formatEnd(element, buf);
+ outputString(buf);
+
+ element = element->previousElement();
+ }
+}
+
+void QTestBasicStreamer::outputElementAttributes(const QTestElement* element, QTestElementAttribute *attribute) const
+{
+ char buf[1024];
+ while(attribute){
+ formatAttributes(element, attribute, buf);
+ outputString(buf);
+ attribute = attribute->nextElement();
+ }
+}
+
+void QTestBasicStreamer::outputString(const char *msg) const
+{
+ QTEST_ASSERT(QTest::stream);
+
+ ::fputs(msg, QTest::stream);
+ ::fflush(QTest::stream);
+}
+
+void QTestBasicStreamer::startStreaming()
+{
+ QTEST_ASSERT(!QTest::stream);
+
+ const char *out = QTestLog::outputFileName();
+ if (!out) {
+ QTest::stream = stdout;
+ return;
+ }
+ #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE)
+ if (::fopen_s(&QTest::stream, out, "wt")) {
+ #else
+ QTest::stream = ::fopen(out, "wt");
+ if (!QTest::stream) {
+ #endif
+ printf("Unable to open file for logging: %s", out);
+ ::exit(1);
+ }
+}
+
+bool QTestBasicStreamer::isTtyOutput()
+{
+ QTEST_ASSERT(QTest::stream);
+
+#if defined(Q_OS_WIN) || defined(Q_OS_INTEGRITY)
+ return true;
+#else
+ static bool ttyoutput = isatty(fileno(QTest::stream));
+ return ttyoutput;
+#endif
+}
+
+void QTestBasicStreamer::stopStreaming()
+{
+ QTEST_ASSERT(QTest::stream);
+ if (QTest::stream != stdout)
+ fclose(QTest::stream);
+
+ QTest::stream = 0;
+}
+
+void QTestBasicStreamer::setLogger(const QTestLogger *tstLogger)
+{
+ testLogger = tstLogger;
+}
+
+const QTestLogger *QTestBasicStreamer::logger() const
+{
+ return testLogger;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestbasicstreamer.h b/src/testlib/qtestbasicstreamer.h
new file mode 100644
index 0000000..61cdfd5
--- /dev/null
+++ b/src/testlib/qtestbasicstreamer.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTBASICSTREAMER_H
+#define QTESTBASICSTREAMER_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+class QTestElement;
+class QTestElementAttribute;
+class QTestLogger;
+
+class QTestBasicStreamer
+{
+ public:
+ QTestBasicStreamer();
+ virtual ~QTestBasicStreamer();
+
+ virtual void output(QTestElement *element) const;
+
+ void outputString(const char *msg) const;
+ bool isTtyOutput();
+ void startStreaming();
+ void stopStreaming();
+
+ void setLogger(const QTestLogger *tstLogger);
+ const QTestLogger *logger() const;
+
+ protected:
+ virtual void formatStart(const QTestElement *element = 0, char *formatted = 0) const;
+ virtual void formatEnd(const QTestElement *element = 0, char *formatted = 0) const;
+ virtual void formatBeforeAttributes(const QTestElement *element = 0, char *formatted = 0) const;
+ virtual void formatAfterAttributes(const QTestElement *element = 0, char *formatted = 0) const;
+ virtual void formatAttributes(const QTestElement *element = 0, const QTestElementAttribute *attribute = 0, char *formatted = 0) const;
+ virtual void outputElements(QTestElement *element, bool isChildElement = false) const;
+ virtual void outputElementAttributes(const QTestElement *element, QTestElementAttribute *attribute) const;
+
+ private:
+ const QTestLogger *testLogger;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 38e63cf..a3e3201 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -54,6 +54,7 @@
#include <QtCore/qdir.h>
#include <QtCore/qprocess.h>
#include <QtCore/qdebug.h>
+#include <QtCore/qlibraryinfo.h>
#include "QtTest/private/qtestlog_p.h"
#include "QtTest/private/qtesttable_p.h"
@@ -823,8 +824,10 @@ static void qParseArgs(int argc, char *argv[])
const char *testOptions =
" options:\n"
" -functions : Returns a list of current testfunctions\n"
+ " -xunitxml : Outputs results as XML XUnit document\n"
" -xml : Outputs results as XML document\n"
" -lightxml : Outputs results as stream of XML tags\n"
+ " -flush : Flushes the resutls\n"
" -o filename: Writes all output into a file\n"
" -silent : Only outputs warnings and failures\n"
" -v1 : Print enter messages for each testfunction\n"
@@ -849,9 +852,8 @@ static void qParseArgs(int argc, char *argv[])
" -iterations n : Sets the number of accumulation iterations.\n"
" -median n : Sets the number of median iterations.\n"
" -vb : Print out verbose benchmarking information.\n"
-#ifndef QT_NO_PROCESS
-// Will be enabled when tools are integrated.
-// " -chart : Runs the chart generator after the test. No output is printed to the console\n"
+#if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS)
+ " -chart : Create chart based on the benchmark result.\n"
#endif
"\n"
" -help : This help\n";
@@ -866,10 +868,14 @@ static void qParseArgs(int argc, char *argv[])
} else if (strcmp(argv[i], "-functions") == 0) {
qPrintTestSlots();
exit(0);
+ } else if(strcmp(argv[i], "-xunitxml") == 0){
+ QTestLog::setLogMode(QTestLog::XunitXML);
} else if (strcmp(argv[i], "-xml") == 0) {
QTestLog::setLogMode(QTestLog::XML);
} else if (strcmp(argv[i], "-lightxml") == 0) {
QTestLog::setLogMode(QTestLog::LightXML);
+ }else if(strcmp(argv[i], "-flush") == 0){
+ QTestLog::setFlushMode(QTestLog::FLushOn);
} else if (strcmp(argv[i], "-silent") == 0) {
QTestLog::setVerboseLevel(-1);
} else if (strcmp(argv[i], "-v1") == 0) {
@@ -962,7 +968,7 @@ static void qParseArgs(int argc, char *argv[])
} else if (strcmp(argv[i], "-vb") == 0) {
QBenchmarkGlobalData::current->verboseOutput = true;
-#ifndef QT_NO_PROCESS
+#if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS)
} else if (strcmp(argv[i], "-chart") == 0) {
QBenchmarkGlobalData::current->createChart = true;
QTestLog::setLogMode(QTestLog::XML);
@@ -1011,7 +1017,7 @@ QBenchmarkResult qMedian(const QList<QBenchmarkResult> &container)
if (count == 1)
return container.at(0);
-
+
QList<QBenchmarkResult> containerCopy = container;
qSort(containerCopy);
@@ -1061,7 +1067,7 @@ static void qInvokeTestMethodDataEntry(char *slot)
QTestResult::currentDataTag()
? QTestResult::currentDataTag() : "");
- invokeOk = QMetaObject::invokeMethod(QTest::currentTestObject, slot,
+ invokeOk = QMetaObject::invokeMethod(QTest::currentTestObject, slot,
Qt::DirectConnection);
if (!invokeOk)
QTestResult::addFailure("Unable to execute slot", __FILE__, __LINE__);
@@ -1082,7 +1088,7 @@ static void qInvokeTestMethodDataEntry(char *slot)
if (i > -1) // iteration -1 is the warmup iteration.
results.append(QBenchmarkTestMethodData::current->result);
- if (QBenchmarkTestMethodData::current->isBenchmark() &&
+ if (QBenchmarkTestMethodData::current->isBenchmark() &&
QBenchmarkGlobalData::current->verboseOutput) {
if (i == -1) {
qDebug() << "warmup stage result :" << QBenchmarkTestMethodData::current->result.value;
@@ -1213,13 +1219,13 @@ void *fetchData(QTestData *data, const char *tagName, int typeId)
/*!
\fn char* QTest::toHexRepresentation(const char *ba, int length)
-
+
Returns a pointer to a string that is the string \a ba represented
as a space-separated sequence of hex characters. If the input is
considered too long, it is truncated. A trucation is indicated in
the returned string as an ellipsis at the end.
- \a length is the length of the string \a ba.
+ \a length is the length of the string \a ba.
*/
char *toHexRepresentation(const char *ba, int length)
{
@@ -1278,56 +1284,56 @@ char *toHexRepresentation(const char *ba, int length)
return result;
}
-static void qInvokeTestMethods(QObject *testObject)
-{
- const QMetaObject *metaObject = testObject->metaObject();
- QTEST_ASSERT(metaObject);
-
- QTestLog::startLogging();
-
- QTestResult::setCurrentTestFunction("initTestCase");
- QTestResult::setCurrentTestLocation(QTestResult::DataFunc);
- QTestTable::globalTestTable();
- QMetaObject::invokeMethod(testObject, "initTestCase_data", Qt::DirectConnection);
-
- if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) {
- QTestResult::setCurrentTestLocation(QTestResult::InitFunc);
- QMetaObject::invokeMethod(testObject, "initTestCase");
-
- // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy.
- const bool previousFailed = QTestResult::testFailed();
- QTestResult::finishedCurrentTestFunction();
-
- if(!QTestResult::skipCurrentTest() && !previousFailed) {
-
- if (lastTestFuncIdx >= 0) {
- for (int i = 0; i <= lastTestFuncIdx; ++i) {
- if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(),
- testFuncs[i].data))
- break;
- }
- } else {
- int methodCount = metaObject->methodCount();
- for (int i = 0; i < methodCount; ++i) {
- QMetaMethod slotMethod = metaObject->method(i);
- if (!isValidSlot(slotMethod))
- continue;
- if (!qInvokeTestMethod(slotMethod.signature()))
- break;
- }
- }
- }
-
- QTestResult::setSkipCurrentTest(false);
- QTestResult::setCurrentTestFunction("cleanupTestCase");
- QMetaObject::invokeMethod(testObject, "cleanupTestCase");
- }
- QTestResult::finishedCurrentTestFunction();
- QTestResult::setCurrentTestFunction(0);
- QTestTable::clearGlobalTestTable();
-
- QTestLog::stopLogging();
-}
+static void qInvokeTestMethods(QObject *testObject)
+{
+ const QMetaObject *metaObject = testObject->metaObject();
+ QTEST_ASSERT(metaObject);
+
+ QTestLog::startLogging();
+
+ QTestResult::setCurrentTestFunction("initTestCase");
+ QTestResult::setCurrentTestLocation(QTestResult::DataFunc);
+ QTestTable::globalTestTable();
+ QMetaObject::invokeMethod(testObject, "initTestCase_data", Qt::DirectConnection);
+
+ if (!QTestResult::skipCurrentTest() && !QTest::currentTestFailed()) {
+ QTestResult::setCurrentTestLocation(QTestResult::InitFunc);
+ QMetaObject::invokeMethod(testObject, "initTestCase");
+
+ // finishedCurrentTestFunction() resets QTestResult::testFailed(), so use a local copy.
+ const bool previousFailed = QTestResult::testFailed();
+ QTestResult::finishedCurrentTestFunction();
+
+ if(!QTestResult::skipCurrentTest() && !previousFailed) {
+
+ if (lastTestFuncIdx >= 0) {
+ for (int i = 0; i <= lastTestFuncIdx; ++i) {
+ if (!qInvokeTestMethod(metaObject->method(testFuncs[i].function).signature(),
+ testFuncs[i].data))
+ break;
+ }
+ } else {
+ int methodCount = metaObject->methodCount();
+ for (int i = 0; i < methodCount; ++i) {
+ QMetaMethod slotMethod = metaObject->method(i);
+ if (!isValidSlot(slotMethod))
+ continue;
+ if (!qInvokeTestMethod(slotMethod.signature()))
+ break;
+ }
+ }
+ }
+
+ QTestResult::setSkipCurrentTest(false);
+ QTestResult::setCurrentTestFunction("cleanupTestCase");
+ QMetaObject::invokeMethod(testObject, "cleanupTestCase");
+ }
+ QTestResult::finishedCurrentTestFunction();
+ QTestResult::setCurrentTestFunction(0);
+ QTestTable::clearGlobalTestTable();
+
+ QTestLog::stopLogging();
+}
} // namespace
@@ -1467,26 +1473,21 @@ int QTest::qExec(QObject *testObject, int argc, char **argv)
#endif
-#ifndef QT_NO_PROCESS
+#if !defined(QT_NO_PROCESS) || !defined(QT_NO_SETTINGS)
if (QBenchmarkGlobalData::current->createChart) {
-
-#define XSTR(s) STR(s)
-#define STR(s) #s
+ QString chartLocation = QLibraryInfo::location(QLibraryInfo::BinariesPath);
#ifdef Q_OS_WIN
- const char * path = XSTR(QBENCHLIB_BASE) "/tools/generatereport/generatereport.exe";
+ chartLocation += QLatin1String("/../tools/qtestlib/chart/release/chart.exe");
#else
- const char * path = XSTR(QBENCHLIB_BASE) "/tools/generatereport/generatereport";
+ chartLocation += QLatin1String("/../tools/qtestlib/chart/chart");
#endif
-#undef XSTR
-#undef STR
-
- if (QFile::exists(QLatin1String(path))) {
+ if (QFile::exists(chartLocation)) {
QProcess p;
p.setProcessChannelMode(QProcess::ForwardedChannels);
- p.start(QLatin1String(path), QStringList() << QLatin1String("results.xml"));
+ p.start(chartLocation, QStringList() << QLatin1String("results.xml"));
p.waitForFinished(-1);
} else {
- qWarning("Could not find %s, please make sure it is compiled.", path);
+ qDebug() << QLatin1String("Could not find the chart tool in ") + chartLocation + QLatin1String(", please make sure it is compiled.");
}
}
#endif
@@ -1810,8 +1811,8 @@ COMPARE_IMPL2(quint64, %llu)
#endif
COMPARE_IMPL2(bool, %d)
COMPARE_IMPL2(char, %c)
-COMPARE_IMPL2(float, %g);
-COMPARE_IMPL2(double, %lg);
+COMPARE_IMPL2(float, %g)
+COMPARE_IMPL2(double, %lg)
/*! \internal
*/
diff --git a/src/testlib/qtestcoreelement.h b/src/testlib/qtestcoreelement.h
new file mode 100644
index 0000000..907041f
--- /dev/null
+++ b/src/testlib/qtestcoreelement.h
@@ -0,0 +1,172 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTCOREELEMENT_H
+#define QTESTCOREELEMENT_H
+
+#include <QtTest/qtestcorelist.h>
+#include <QtTest/qtestelementattribute.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+template <class ElementType>
+class QTestCoreElement: public QTestCoreList<ElementType>
+{
+ public:
+ QTestCoreElement( int type = -1 );
+ virtual ~QTestCoreElement();
+
+ void addAttribute(const QTest::AttributeIndex index, const char *value);
+ QTestElementAttribute *attributes() const;
+ const char *attributeValue(QTest::AttributeIndex index) const;
+ const char *attributeName(QTest::AttributeIndex index) const;
+ const QTestElementAttribute *attribute(QTest::AttributeIndex index) const;
+
+ const char *elementName() const;
+ QTest::LogElementType elementType() const;
+
+ private:
+ QTestElementAttribute *listOfAttributes;
+ QTest::LogElementType type;
+};
+
+template<class ElementType>
+QTestCoreElement<ElementType>::QTestCoreElement(int t)
+:listOfAttributes(0), type((QTest::LogElementType)t)
+{
+}
+
+template<class ElementType>
+QTestCoreElement<ElementType>::~QTestCoreElement()
+{
+ delete listOfAttributes;
+}
+
+template <class ElementType>
+void QTestCoreElement<ElementType>::addAttribute(const QTest::AttributeIndex attributeIndex, const char *value)
+{
+ if(attributeIndex == -1)
+ return;
+
+ if (attribute(attributeIndex))
+ return;
+
+ QTestElementAttribute *attribute = new QTestElementAttribute;
+ attribute->setPair(attributeIndex, value);
+ attribute->addToList(&listOfAttributes);
+}
+
+template <class ElementType>
+QTestElementAttribute *QTestCoreElement<ElementType>::attributes() const
+{
+ return listOfAttributes;
+}
+
+template <class ElementType>
+const char *QTestCoreElement<ElementType>::attributeValue(QTest::AttributeIndex index) const
+{
+ const QTestElementAttribute *attrb = attribute(index);
+ if(attrb)
+ return attrb->value();
+
+ return 0;
+}
+
+template <class ElementType>
+const char *QTestCoreElement<ElementType>::attributeName(QTest::AttributeIndex index) const
+{
+ const QTestElementAttribute *attrb = attribute(index);
+ if(attrb)
+ return attrb->name();
+
+ return 0;
+}
+
+template <class ElementType>
+const char *QTestCoreElement<ElementType>::elementName() const
+{
+ const char *xmlElementNames[] =
+ {
+ "property",
+ "properties",
+ "failure",
+ "error",
+ "testcase",
+ "testsuite",
+ "benchmark",
+ "system-err"
+ };
+
+ if(type != QTest::LET_Undefined)
+ return xmlElementNames[type];
+
+ return 0;
+}
+
+template <class ElementType>
+QTest::LogElementType QTestCoreElement<ElementType>::elementType() const
+{
+ return type;
+}
+
+template <class ElementType>
+const QTestElementAttribute *QTestCoreElement<ElementType>::attribute(QTest::AttributeIndex index) const
+{
+ QTestElementAttribute *iterator = listOfAttributes;
+ while(iterator){
+ if(iterator->index() == index)
+ return iterator;
+
+ iterator = iterator->nextElement();
+ }
+
+ return 0;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/plugins/kbddrivers/linuxis/linuxiskbddriverplugin.cpp b/src/testlib/qtestcorelist.h
index 79cd298..9983b27 100644
--- a/src/plugins/kbddrivers/linuxis/linuxiskbddriverplugin.cpp
+++ b/src/testlib/qtestcorelist.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtTest module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,49 +39,98 @@
**
****************************************************************************/
-#include "linuxiskbddriverplugin.h"
-#include "linuxiskbdhandler.h"
+#ifndef QTESTCORELIST_H
+#define QTESTCORELIST_H
-#include <qdebug.h>
-#if 1
-#define qLog(x) qDebug()
-#else
-#define qLog(x) while (0) qDebug()
-#endif
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
-LinuxInputSubsystemKbdDriverPlugin::LinuxInputSubsystemKbdDriverPlugin( QObject *parent )
- : QKbdDriverPlugin( parent )
+QT_MODULE(Test)
+
+template <class T>
+class QTestCoreList
{
-}
+ public:
+ QTestCoreList();
+ virtual ~QTestCoreList();
+
+ void addToList(T **list);
+ T *nextElement();
+ T *previousElement();
+ int count(T *list);
+ int count();
-LinuxInputSubsystemKbdDriverPlugin::~LinuxInputSubsystemKbdDriverPlugin()
+ private:
+ T *next;
+ T *prev;
+};
+
+template <class T>
+QTestCoreList<T>::QTestCoreList()
+:next(0)
+,prev(0)
{
}
-QWSKeyboardHandler* LinuxInputSubsystemKbdDriverPlugin::create(const QString &driver, const QString &device)
+template <class T>
+QTestCoreList<T>::~QTestCoreList()
{
- if (device.isEmpty()) {
- return create( driver );
+ if (prev) {
+ prev->next = 0;
}
- if( driver.toLower() == "linuxis" || driver.toLower() == "linuxiskbdhandler" ) {
- qLog(Input) << "Before call LinuxInputSubsystemKbdHandler(" << device << ")";
- return new LinuxInputSubsystemKbdHandler(device);
+ delete prev;
+
+ if (next) {
+ next->prev = 0;
}
- return 0;
+ delete next;
}
-QWSKeyboardHandler* LinuxInputSubsystemKbdDriverPlugin::create( const QString &driver)
+template <class T>
+void QTestCoreList<T>::addToList(T **list)
{
- if( driver.toLower() == "linuxis" || driver.toLower() == "linuxiskbdhandler" ) {
- qLog(Input) << "Before call LinuxInputSubsystemKbdHandler()";
- return new LinuxInputSubsystemKbdHandler();
+ if (next)
+ next->addToList(list);
+ else {
+ next = *list;
+ if (next)
+ next->prev = static_cast<T*>(this);
}
- return 0;
+
+ *list = static_cast<T*>(this);
}
-QStringList LinuxInputSubsystemKbdDriverPlugin::keys() const
+template <class T>
+T *QTestCoreList<T>::nextElement()
{
- return QStringList() << "linuxis" << "linuxiskbdhandler";
+ return next;
}
-Q_EXPORT_PLUGIN2(qwslinuxiskbdhandler, LinuxInputSubsystemKbdDriverPlugin)
+template <class T>
+T *QTestCoreList<T>::previousElement()
+{
+ return prev;
+}
+
+template <class T>
+int QTestCoreList<T>::count()
+{
+ int numOfElements = 0;
+ T *it = next;
+
+ while(it){
+ ++numOfElements;
+ it = it->nextElement();
+ }
+
+ return numOfElements;
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qtestelement.cpp b/src/testlib/qtestelement.cpp
new file mode 100644
index 0000000..a417360
--- /dev/null
+++ b/src/testlib/qtestelement.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestelement.h"
+
+QT_BEGIN_NAMESPACE
+
+QTestElement::QTestElement(int type)
+ :QTestCoreElement<QTestElement>(type),
+ listOfChildren(0),
+ parent(0)
+{
+}
+
+QTestElement::~QTestElement()
+{
+ delete listOfChildren;
+}
+
+bool QTestElement::addLogElement(QTestElement *element)
+{
+ if(!element)
+ return false;
+
+ if(element->elementType() != QTest::LET_Undefined){
+ element->addToList(&listOfChildren);
+ element->setParent(this);
+ return true;
+ }
+
+ return false;
+}
+
+QTestElement *QTestElement::childElements() const
+{
+ return listOfChildren;
+}
+
+const QTestElement *QTestElement::parentElement() const
+{
+ return parent;
+}
+
+void QTestElement::setParent(const QTestElement *p)
+{
+ parent = p;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestelement.h b/src/testlib/qtestelement.h
new file mode 100644
index 0000000..e75689a
--- /dev/null
+++ b/src/testlib/qtestelement.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTELEMENT_H
+#define QTESTELEMENT_H
+
+#include <QtTest/qtestcoreelement.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+class QTestElement: public QTestCoreElement<QTestElement>
+{
+ public:
+ QTestElement(int type = -1);
+ ~QTestElement();
+
+ bool addLogElement(QTestElement *element);
+ QTestElement *childElements() const;
+
+ const QTestElement *parentElement() const;
+ void setParent(const QTestElement *p);
+
+ private:
+ QTestElement *listOfChildren;
+ const QTestElement * parent;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qtestelementattribute.cpp b/src/testlib/qtestelementattribute.cpp
new file mode 100644
index 0000000..783b83d
--- /dev/null
+++ b/src/testlib/qtestelementattribute.cpp
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestelementattribute.h"
+#include <QtCore/qbytearray.h>
+#include <string.h>
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+/*! \enum QTest::AttributeIndex
+ This enum numbers the different tests.
+
+ \value AI_Undefined
+
+ \value AI_Name
+
+ \value AI_Result
+
+ \value AI_Tests
+
+ \value AI_Failures
+
+ \value AI_Errors
+
+ \value AI_Type
+
+ \value AI_Description
+
+ \value AI_PropertyValue
+
+ \value AI_QTestVersion
+
+ \value AI_QtVersion
+
+ \value AI_File
+
+ \value AI_Line
+
+ \value AI_Metric
+
+ \value AI_Tag
+
+ \value AI_Value
+
+ \value AI_Iterations
+*/
+
+/*! \enum QTest::LogElementType
+ The enum specifies the kinds of test log messages.
+
+ \value LET_Undefined
+
+ \value LET_Property
+
+ \value LET_Properties
+
+ \value LET_Failure
+
+ \value LET_Error
+
+ \value LET_TestCase
+
+ \value LET_TestSuite
+
+ \value LET_Benchmark
+
+ \value LET_SystemError
+*/
+
+QTestElementAttribute::QTestElementAttribute()
+ :attributeValue(0),
+ attributeIndex(QTest::AI_Undefined)
+{
+}
+
+QTestElementAttribute::~QTestElementAttribute()
+{
+ delete[] attributeValue;
+}
+
+const char *QTestElementAttribute::value() const
+{
+ return attributeValue;
+}
+
+const char *QTestElementAttribute::name() const
+{
+ const char *AttributeNames[] =
+ {
+ "name",
+ "result",
+ "tests",
+ "failures",
+ "errors",
+ "type",
+ "description",
+ "value",
+ "qtestversion",
+ "qtversion",
+ "file",
+ "line",
+ "metric",
+ "tag",
+ "value",
+ "iterations"
+ };
+
+ if(attributeIndex != QTest::AI_Undefined)
+ return AttributeNames[attributeIndex];
+
+ return 0;
+}
+
+QTest::AttributeIndex QTestElementAttribute::index() const
+{
+ return attributeIndex;
+}
+
+bool QTestElementAttribute::isNull() const
+{
+ return attributeIndex == QTest::AI_Undefined;
+}
+
+bool QTestElementAttribute::setPair(QTest::AttributeIndex index, const char *value)
+{
+ if(!value)
+ return false;
+
+ delete[] attributeValue;
+
+ attributeIndex = index;
+ attributeValue = qstrdup(value);
+
+ return (attributeValue!=0) ? true:false;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestelementattribute.h b/src/testlib/qtestelementattribute.h
new file mode 100644
index 0000000..944d9c0
--- /dev/null
+++ b/src/testlib/qtestelementattribute.h
@@ -0,0 +1,111 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTELEMENTATTRIBUTE_H
+#define QTESTELEMENTATTRIBUTE_H
+
+#include <QtTest/qtestcorelist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+namespace QTest {
+
+ enum AttributeIndex
+ {
+ AI_Undefined = -1,
+ AI_Name = 0,
+ AI_Result = 1,
+ AI_Tests = 2,
+ AI_Failures = 3,
+ AI_Errors = 4,
+ AI_Type = 5,
+ AI_Description = 6,
+ AI_PropertyValue = 7,
+ AI_QTestVersion = 8,
+ AI_QtVersion = 9,
+ AI_File = 10,
+ AI_Line = 11,
+ AI_Metric = 12,
+ AI_Tag = 13,
+ AI_Value = 14,
+ AI_Iterations = 15
+ };
+
+ enum LogElementType
+ {
+ LET_Undefined = -1,
+ LET_Property = 0,
+ LET_Properties = 1,
+ LET_Failure = 2,
+ LET_Error = 3,
+ LET_TestCase = 4,
+ LET_TestSuite = 5,
+ LET_Benchmark = 6,
+ LET_SystemError = 7
+ };
+}
+
+class QTestElementAttribute: public QTestCoreList<QTestElementAttribute>
+{
+ public:
+ QTestElementAttribute();
+ ~QTestElementAttribute();
+
+ const char *value() const;
+ const char *name() const;
+ QTest::AttributeIndex index() const;
+ bool isNull() const;
+ bool setPair(QTest::AttributeIndex attributeIndex, const char *value);
+
+ private:
+ char *attributeValue;
+ QTest::AttributeIndex attributeIndex;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qtestfilelogger.cpp b/src/testlib/qtestfilelogger.cpp
new file mode 100644
index 0000000..50741de
--- /dev/null
+++ b/src/testlib/qtestfilelogger.cpp
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestfilelogger.h"
+#include "qtestassert.h"
+#include "QtTest/private/qtestlog_p.h"
+#include "QtTest/private/qtestresult_p.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QTest
+{
+ static FILE *stream = 0;
+}
+
+QTestFileLogger::QTestFileLogger()
+{
+}
+
+QTestFileLogger::~QTestFileLogger()
+{
+ if(QTest::stream)
+ fclose(QTest::stream);
+
+ QTest::stream = 0;
+}
+
+void QTestFileLogger::init()
+{
+ char filename[100];
+ QTest::qt_snprintf(filename, sizeof(filename), "%s.log",
+ QTestResult::currentTestObjectName());
+
+ #if defined(_MSC_VER) && _MSC_VER >= 1400 && !defined(Q_OS_WINCE)
+ if (::fopen_s(&QTest::stream, filename, "wt")) {
+ #else
+ QTest::stream = ::fopen(filename, "wt");
+ if (!QTest::stream) {
+ #endif
+ printf("Unable to open file for simple logging: %s", filename);
+ ::exit(1);
+ }
+}
+
+void QTestFileLogger::flush(const char *msg)
+{
+ QTEST_ASSERT(QTest::stream);
+
+ ::fputs(msg, QTest::stream);
+ ::fflush(QTest::stream);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/kbddrivers/linuxis/linuxiskbddriverplugin.h b/src/testlib/qtestfilelogger.h
index b5f599f..f6a993d 100644
--- a/src/plugins/kbddrivers/linuxis/linuxiskbddriverplugin.h
+++ b/src/testlib/qtestfilelogger.h
@@ -3,7 +3,7 @@
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** Contact: Qt Software Information (qt-info@nokia.com)
**
-** This file is part of the plugins of the Qt Toolkit.
+** This file is part of the QtTest module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
@@ -39,20 +39,29 @@
**
****************************************************************************/
-#ifndef LINUXISKBDDRIVERPLUGIN_H
-#define LINUXISKBDDRIVERPLUGIN_H
+#ifndef QTESTFILELOGGER_H
+#define QTESTFILELOGGER_H
-#include <QtGui/QWSKeyboardHandlerFactoryInterface>
+#include <QtCore/qglobal.h>
-class LinuxInputSubsystemKbdDriverPlugin : public QKbdDriverPlugin {
- Q_OBJECT
-public:
- LinuxInputSubsystemKbdDriverPlugin( QObject *parent = 0 );
- ~LinuxInputSubsystemKbdDriverPlugin();
+QT_BEGIN_HEADER
- QWSKeyboardHandler* create(const QString& driver, const QString& device);
- QWSKeyboardHandler* create(const QString& driver);
- QStringList keys()const;
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+class QTestFileLogger
+{
+ public:
+ QTestFileLogger();
+ ~QTestFileLogger();
+
+ void init();
+ void flush(const char *msg);
};
-#endif // LINUXISKBDDRIVERPLUGIN_H
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTESTFILELOGGER_H
diff --git a/src/testlib/qtestlightxmlstreamer.cpp b/src/testlib/qtestlightxmlstreamer.cpp
new file mode 100644
index 0000000..75fec40
--- /dev/null
+++ b/src/testlib/qtestlightxmlstreamer.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestlightxmlstreamer.h"
+#include "qtestelement.h"
+#include "qtestelementattribute.h"
+
+#include "QtTest/private/qtestlog_p.h"
+#include "QtTest/private/qtestresult_p.h"
+#include "QtTest/private/qxmltestlogger_p.h"
+
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+QTestLightXmlStreamer::QTestLightXmlStreamer()
+ :QTestBasicStreamer()
+{
+}
+
+QTestLightXmlStreamer::~QTestLightXmlStreamer()
+{}
+
+void QTestLightXmlStreamer::formatStart(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted)
+ return;
+
+ switch(element->elementType()){
+ case QTest::LET_TestCase: {
+ char quotedTf[950];
+ QXmlTestLogger::xmlQuote(quotedTf, element->attributeValue(QTest::AI_Name),
+ sizeof(quotedTf));
+
+ QTest::qt_snprintf(formatted, 1024, "<TestFunction name=\"%s\">\n", quotedTf);
+ break;
+ }
+ case QTest::LET_Failure: {
+ char cdataDesc[900];
+ QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description),
+ sizeof(cdataDesc));
+
+ QTest::qt_snprintf(formatted, 1024, " <Description><![CDATA[%s]]></Description>\n",
+ cdataDesc);
+ break;
+ }
+ case QTest::LET_Error: {
+ // assuming type and attribute names don't need quoting
+ char quotedFile[128];
+ char cdataDesc[700];
+ QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File),
+ sizeof(quotedFile));
+ QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description),
+ sizeof(cdataDesc));
+
+ QTest::qt_snprintf(formatted, 1024, "<Message type=\"%s\" %s=\"%s\" %s=\"%s\">\n <Description><![CDATA[%s]]></Description>\n</Message>\n",
+ element->attributeValue(QTest::AI_Type),
+ element->attributeName(QTest::AI_File),
+ quotedFile,
+ element->attributeName(QTest::AI_Line),
+ element->attributeValue(QTest::AI_Line),
+ cdataDesc);
+ break;
+ }
+ case QTest::LET_Benchmark: {
+ // assuming value and iterations don't need quoting
+ char quotedMetric[256];
+ char quotedTag[256];
+ QXmlTestLogger::xmlQuote(quotedMetric, element->attributeValue(QTest::AI_Metric),
+ sizeof(quotedMetric));
+ QXmlTestLogger::xmlQuote(quotedTag, element->attributeValue(QTest::AI_Tag),
+ sizeof(quotedTag));
+
+ QTest::qt_snprintf(formatted, 1024, "<BenchmarkResult %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" />\n",
+ element->attributeName(QTest::AI_Metric),
+ quotedMetric,
+ element->attributeName(QTest::AI_Tag),
+ quotedTag,
+ element->attributeName(QTest::AI_Value),
+ element->attributeValue(QTest::AI_Value),
+ element->attributeName(QTest::AI_Iterations),
+ element->attributeValue(QTest::AI_Iterations) );
+ break;
+ }
+ default:
+ QTest::qt_snprintf(formatted, 10, "");
+ }
+}
+
+void QTestLightXmlStreamer::formatEnd(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted)
+ return;
+
+ if (element->elementType() == QTest::LET_TestCase) {
+ if( element->attribute(QTest::AI_Result) && element->childElements())
+ QTest::qt_snprintf(formatted, 1024, "</Incident>\n</TestFunction>\n");
+ else
+ QTest::qt_snprintf(formatted, 1024, "</TestFunction>\n");
+ }
+ else
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestLightXmlStreamer::formatBeforeAttributes(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted)
+ return;
+
+ if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)){
+ char buf[900];
+ char quotedFile[700];
+ QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File),
+ sizeof(quotedFile));
+
+ QTest::qt_snprintf(buf, sizeof(buf), "%s=\"%s\" %s=\"%s\"",
+ element->attributeName(QTest::AI_File),
+ quotedFile,
+ element->attributeName(QTest::AI_Line),
+ element->attributeValue(QTest::AI_Line));
+
+ if( !element->childElements() )
+ QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s/>\n",
+ element->attributeValue(QTest::AI_Result), buf);
+ else
+ QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s>\n",
+ element->attributeValue(QTest::AI_Result), buf);
+ }else{
+ QTest::qt_snprintf(formatted, 10, "");
+ }
+}
+
+void QTestLightXmlStreamer::output(QTestElement *element) const
+{
+ char buf[1024];
+ QTest::qt_snprintf(buf, sizeof(buf), "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n",
+ qVersion(), QTEST_VERSION_STR );
+ outputString(buf);
+
+ QTest::qt_snprintf(buf, sizeof(buf), "</Environment>\n");
+ outputString(buf);
+
+ QTestBasicStreamer::output(element);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestlightxmlstreamer.h b/src/testlib/qtestlightxmlstreamer.h
new file mode 100644
index 0000000..3f564a8
--- /dev/null
+++ b/src/testlib/qtestlightxmlstreamer.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTLIGHTXMLSTREAMER_H
+#define QTESTLIGHTXMLSTREAMER_H
+
+#include <QtTest/qtestbasicstreamer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+class QTestElement;
+class QTestElementAttribute;
+
+class QTestLightXmlStreamer: public QTestBasicStreamer
+{
+ public:
+ QTestLightXmlStreamer();
+ ~QTestLightXmlStreamer();
+
+ void formatStart(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatEnd(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatBeforeAttributes(const QTestElement *element = 0, char *formatted = 0) const;
+ void output(QTestElement *element) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qtestlog.cpp b/src/testlib/qtestlog.cpp
index aa56e6c..bcb1c1b 100644
--- a/src/testlib/qtestlog.cpp
+++ b/src/testlib/qtestlog.cpp
@@ -46,7 +46,6 @@
#include "QtTest/private/qabstracttestlogger_p.h"
#include "QtTest/private/qplaintestlogger_p.h"
#include "QtTest/private/qxmltestlogger_p.h"
-
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
@@ -54,6 +53,9 @@
#include <string.h>
#include <limits.h>
+
+#include "qtestlogger_p.h"
+
QT_BEGIN_NAMESPACE
namespace QTest {
@@ -83,6 +85,7 @@ namespace QTest {
static IgnoreResultList *ignoreResultList = 0;
static QTestLog::LogMode logMode = QTestLog::Plain;
+ static QTestLog::FlushMode flushMode = QTestLog::NoFlush;
static int verbosity = 0;
static int maxWarnings = 2002;
@@ -270,15 +273,24 @@ void QTestLog::startLogging()
QTEST_ASSERT(!QTest::testLogger);
switch (QTest::logMode) {
- case QTestLog::Plain:
- QTest::testLogger = new QPlainTestLogger();
- break;
- case QTestLog::XML:
- QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete);
- break;
- case QTestLog::LightXML:
- QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light);
- }
+ case QTestLog::Plain:
+ QTest::testLogger = new QPlainTestLogger;
+ break;
+ case QTestLog::XML:{
+ if(QTest::flushMode == QTestLog::FLushOn)
+ QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Complete);
+ else
+ QTest::testLogger = new QTestLogger(QTestLogger::TLF_XML);
+ break;
+ }case QTestLog::LightXML:{
+ if(QTest::flushMode == QTestLog::FLushOn)
+ QTest::testLogger = new QXmlTestLogger(QXmlTestLogger::Light);
+ else
+ QTest::testLogger = new QTestLogger(QTestLogger::TLF_LightXml);
+ break;
+ }case QTestLog::XunitXML:
+ QTest::testLogger = new QTestLogger(QTestLogger::TLF_XunitXml);
+ }
QTest::testLogger->startLogging();
@@ -361,4 +373,9 @@ void QTestLog::setMaxWarnings(int m)
QTest::maxWarnings = m <= 0 ? INT_MAX : m + 2;
}
+void QTestLog::setFlushMode(FlushMode mode)
+{
+ QTest::flushMode = mode;
+}
+
QT_END_NAMESPACE
diff --git a/src/testlib/qtestlog_p.h b/src/testlib/qtestlog_p.h
index fa49a38..0d761e3 100644
--- a/src/testlib/qtestlog_p.h
+++ b/src/testlib/qtestlog_p.h
@@ -62,7 +62,8 @@ class QBenchmarkResult;
class QTestLog
{
public:
- enum LogMode { Plain = 0, XML, LightXML };
+ enum LogMode { Plain = 0, XML, LightXML, XunitXML };
+ enum FlushMode { NoFlush = 0, FLushOn };
static void enterTestFunction(const char* function);
static void leaveTestFunction();
@@ -95,6 +96,8 @@ public:
static void setMaxWarnings(int max);
+ static void setFlushMode(FlushMode mode);
+
private:
QTestLog();
~QTestLog();
diff --git a/src/testlib/qtestlogger.cpp b/src/testlib/qtestlogger.cpp
new file mode 100644
index 0000000..46af232
--- /dev/null
+++ b/src/testlib/qtestlogger.cpp
@@ -0,0 +1,403 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestlogger_p.h"
+#include "qtestelement.h"
+#include "qtestxunitstreamer.h"
+#include "qtestxmlstreamer.h"
+#include "qtestlightxmlstreamer.h"
+#include "qtestfilelogger.h"
+
+#include "QtTest/qtestcase.h"
+#include "QtTest/private/qtestresult_p.h"
+#include "QtTest/private/qbenchmark_p.h"
+
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+QTestLogger::QTestLogger(int fm)
+ :listOfTestcases(0), currentLogElement(0), errorLogElement(0),
+ logFormatter(0), format( (TestLoggerFormat)fm ), filelogger(new QTestFileLogger),
+ testCounter(0), passCounter(0),
+ failureCounter(0), errorCounter(0),
+ warningCounter(0), skipCounter(0),
+ systemCounter(0), qdebugCounter(0),
+ qwarnCounter(0), qfatalCounter(0),
+ infoCounter(0)
+{
+}
+
+QTestLogger::~QTestLogger()
+{
+ if(format == TLF_XunitXml)
+ delete currentLogElement;
+ else
+ delete listOfTestcases;
+
+ delete logFormatter;
+ delete filelogger;
+}
+
+void QTestLogger::startLogging()
+{
+ switch(format){
+ case TLF_LightXml:{
+ logFormatter = new QTestLightXmlStreamer;
+ filelogger->init();
+ break;
+ }case TLF_XML:{
+ logFormatter = new QTestXmlStreamer;
+ filelogger->init();
+ break;
+ }case TLF_XunitXml:{
+ logFormatter = new QTestXunitStreamer;
+ delete errorLogElement;
+ errorLogElement = new QTestElement(QTest::LET_SystemError);
+ filelogger->init();
+ break;
+ }
+ }
+
+ logFormatter->setLogger(this);
+ logFormatter->startStreaming();
+}
+
+void QTestLogger::stopLogging()
+{
+ QTestElement *iterator = listOfTestcases;
+
+ if(format == TLF_XunitXml ){
+ char buf[10];
+
+ currentLogElement = new QTestElement(QTest::LET_TestSuite);
+ currentLogElement->addAttribute(QTest::AI_Name, QTestResult::currentTestObjectName());
+
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", testCounter);
+ currentLogElement->addAttribute(QTest::AI_Tests, buf);
+
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", failureCounter);
+ currentLogElement->addAttribute(QTest::AI_Failures, buf);
+
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", errorCounter);
+ currentLogElement->addAttribute(QTest::AI_Errors, buf);
+
+ QTestElement *property;
+ QTestElement *properties = new QTestElement(QTest::LET_Properties);
+
+ property = new QTestElement(QTest::LET_Property);
+ property->addAttribute(QTest::AI_Name, "QTestVersion");
+ property->addAttribute(QTest::AI_PropertyValue, QTEST_VERSION_STR);
+ properties->addLogElement(property);
+
+ property = new QTestElement(QTest::LET_Property);
+ property->addAttribute(QTest::AI_Name, "QtVersion");
+ property->addAttribute(QTest::AI_PropertyValue, qVersion());
+ properties->addLogElement(property);
+
+ currentLogElement->addLogElement(properties);
+
+ currentLogElement->addLogElement(iterator);
+
+ /* For correct indenting, make sure every testcase knows its parent */
+ QTestElement* testcase = iterator;
+ while (testcase) {
+ testcase->setParent(currentLogElement);
+ testcase = testcase->nextElement();
+ }
+
+ currentLogElement->addLogElement(errorLogElement);
+
+ QTestElement *it = currentLogElement;
+ logFormatter->output(it);
+ }else{
+ logFormatter->output(iterator);
+ }
+
+ logFormatter->stopStreaming();
+}
+
+void QTestLogger::enterTestFunction(const char *function)
+{
+ char buf[1024];
+ QTest::qt_snprintf(buf, sizeof(buf), "Entered test-function: %s\n", function);
+ filelogger->flush(buf);
+
+ currentLogElement = new QTestElement(QTest::LET_TestCase);
+ currentLogElement->addAttribute(QTest::AI_Name, function);
+ currentLogElement->addToList(&listOfTestcases);
+
+ ++testCounter;
+}
+
+void QTestLogger::leaveTestFunction()
+{
+}
+
+void QTestLogger::addIncident(IncidentTypes type, const char *description,
+ const char *file, int line)
+{
+ const char *typeBuf = 0;
+ char buf[100];
+
+ switch (type) {
+ case QAbstractTestLogger::XPass:
+ ++failureCounter;
+ typeBuf = "xpass";
+ break;
+ case QAbstractTestLogger::Pass:
+ ++passCounter;
+ typeBuf = "pass";
+ break;
+ case QAbstractTestLogger::XFail:
+ ++passCounter;
+ typeBuf = "xfail";
+ break;
+ case QAbstractTestLogger::Fail:
+ ++failureCounter;
+ typeBuf = "fail";
+ break;
+ default:
+ typeBuf = "??????";
+ break;
+ }
+
+ if (type == QAbstractTestLogger::Fail || type == QAbstractTestLogger::XPass
+ || ((format != TLF_XunitXml) && (type == QAbstractTestLogger::XFail))) {
+ QTestElement *failureElement = new QTestElement(QTest::LET_Failure);
+ failureElement->addAttribute(QTest::AI_Result, typeBuf);
+ if(file)
+ failureElement->addAttribute(QTest::AI_File, file);
+ else
+ failureElement->addAttribute(QTest::AI_File, "");
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", line);
+ failureElement->addAttribute(QTest::AI_Line, buf);
+ failureElement->addAttribute(QTest::AI_Description, description);
+ const char* tag = QTestResult::currentDataTag();
+ if (tag) {
+ failureElement->addAttribute(QTest::AI_Tag, tag);
+ }
+ currentLogElement->addLogElement(failureElement);
+ }
+
+ /*
+ Only one result can be shown for the whole testfunction.
+ Check if we currently have a result, and if so, overwrite it
+ iff the new result is worse.
+ */
+ QTestElementAttribute* resultAttr =
+ const_cast<QTestElementAttribute*>(currentLogElement->attribute(QTest::AI_Result));
+ if (resultAttr) {
+ const char* oldResult = resultAttr->value();
+ bool overwrite = false;
+ if (!strcmp(oldResult, "pass")) {
+ overwrite = true;
+ }
+ else if (!strcmp(oldResult, "xfail")) {
+ overwrite = (type == QAbstractTestLogger::XPass || type == QAbstractTestLogger::Fail);
+ }
+ else if (!strcmp(oldResult, "xpass")) {
+ overwrite = (type == QAbstractTestLogger::Fail);
+ }
+ if (overwrite) {
+ resultAttr->setPair(QTest::AI_Result, typeBuf);
+ }
+ }
+ else {
+ currentLogElement->addAttribute(QTest::AI_Result, typeBuf);
+ }
+
+ if(file)
+ currentLogElement->addAttribute(QTest::AI_File, file);
+ else
+ currentLogElement->addAttribute(QTest::AI_File, "");
+
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", line);
+ currentLogElement->addAttribute(QTest::AI_Line, buf);
+
+ /*
+ Since XFAIL does not add a failure to the testlog in xunitxml, add a message, so we still
+ have some information about the expected failure.
+ */
+ if (format == TLF_XunitXml && type == QAbstractTestLogger::XFail) {
+ QTestLogger::addMessage(QAbstractTestLogger::Info, description, file, line);
+ }
+}
+
+void QTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
+{
+ QTestElement *benchmarkElement = new QTestElement(QTest::LET_Benchmark);
+// printf("element %i", benchmarkElement->elementType());
+
+ benchmarkElement->addAttribute(QTest::AI_Metric, QBenchmarkGlobalData::current->measurer->metricText().toAscii().data());
+ benchmarkElement->addAttribute(QTest::AI_Tag, result.context.tag.toAscii().data());
+ benchmarkElement->addAttribute(QTest::AI_Value, QByteArray::number(result.value).constData());
+
+ char buf[100];
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", result.iterations);
+ benchmarkElement->addAttribute(QTest::AI_Iterations, buf);
+ currentLogElement->addLogElement(benchmarkElement);
+}
+
+void QTestLogger::addMessage(MessageTypes type, const char *message, const char *file, int line)
+{
+ QTestElement *errorElement = new QTestElement(QTest::LET_Error);
+ const char *typeBuf = 0;
+
+ switch (type) {
+ case QAbstractTestLogger::Warn:
+ ++warningCounter;
+ typeBuf = "warn";
+ break;
+ case QAbstractTestLogger::QSystem:
+ ++systemCounter;
+ typeBuf = "system";
+ break;
+ case QAbstractTestLogger::QDebug:
+ ++qdebugCounter;
+ typeBuf = "qdebug";
+ break;
+ case QAbstractTestLogger::QWarning:
+ ++qwarnCounter;
+ typeBuf = "qwarning";
+ break;
+ case QAbstractTestLogger::QFatal:
+ ++qfatalCounter;
+ typeBuf = "qfatal";
+ break;
+ case QAbstractTestLogger::Skip:
+ ++skipCounter;
+ typeBuf = "skip";
+ break;
+ case QAbstractTestLogger::Info:
+ ++infoCounter;
+ typeBuf = "info";
+ break;
+ default:
+ typeBuf = "??????";
+ break;
+ }
+
+ errorElement->addAttribute(QTest::AI_Type, typeBuf);
+ errorElement->addAttribute(QTest::AI_Description, message);
+
+ if(file)
+ errorElement->addAttribute(QTest::AI_File, file);
+ else
+ errorElement->addAttribute(QTest::AI_File, "");
+
+ char buf[100];
+ QTest::qt_snprintf(buf, sizeof(buf), "%i", line);
+ errorElement->addAttribute(QTest::AI_Line, buf);
+
+ currentLogElement->addLogElement(errorElement);
+ ++errorCounter;
+
+ // Also add the message to the system error log (i.e. stderr), if one exists
+ if (errorLogElement) {
+ QTestElement *systemErrorElement = new QTestElement(QTest::LET_Error);
+ systemErrorElement->addAttribute(QTest::AI_Description, message);
+ errorLogElement->addLogElement(systemErrorElement);
+ }
+}
+
+void QTestLogger::setLogFormat(TestLoggerFormat fm)
+{
+ format = fm;
+}
+
+QTestLogger::TestLoggerFormat QTestLogger::logFormat()
+{
+ return format;
+}
+
+int QTestLogger::passCount() const
+{
+ return passCounter;
+}
+
+int QTestLogger::failureCount() const
+{
+ return failureCounter;
+}
+
+int QTestLogger::errorCount() const
+{
+ return errorCounter;
+}
+
+int QTestLogger::warningCount() const
+{
+ return warningCounter;
+}
+
+int QTestLogger::skipCount() const
+{
+ return skipCounter;
+}
+
+int QTestLogger::systemCount() const
+{
+ return systemCounter;
+}
+
+int QTestLogger::qdebugCount() const
+{
+ return qdebugCounter;
+}
+
+int QTestLogger::qwarnCount() const
+{
+ return qwarnCounter;
+}
+
+int QTestLogger::qfatalCount() const
+{
+ return qfatalCounter;
+}
+
+int QTestLogger::infoCount() const
+{
+ return infoCounter;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestlogger_p.h b/src/testlib/qtestlogger_p.h
new file mode 100644
index 0000000..9807fd2
--- /dev/null
+++ b/src/testlib/qtestlogger_p.h
@@ -0,0 +1,127 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTLOGGER_P_H
+#define QTESTLOGGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtTest/private/qabstracttestlogger_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QTestBasicStreamer;
+class QTestElement;
+class QTestFileLogger;
+
+class QTestLogger : public QAbstractTestLogger
+{
+ public:
+ QTestLogger(int fm = 0);
+ ~QTestLogger();
+
+ enum TestLoggerFormat
+ {
+ TLF_XML = 0,
+ TLF_LightXml = 1,
+ TLF_XunitXml = 2
+ };
+
+ void startLogging();
+ void stopLogging();
+
+ void enterTestFunction(const char *function);
+ void leaveTestFunction();
+
+ void addIncident(IncidentTypes type, const char *description,
+ const char *file = 0, int line = 0);
+ void addBenchmarkResult(const QBenchmarkResult &result);
+
+ void addMessage(MessageTypes type, const char *message,
+ const char *file = 0, int line = 0);
+
+ void setLogFormat(TestLoggerFormat fm);
+ TestLoggerFormat logFormat();
+
+ int passCount() const;
+ int failureCount() const;
+ int errorCount() const;
+ int warningCount() const;
+ int skipCount() const;
+ int systemCount() const;
+ int qdebugCount() const;
+ int qwarnCount() const;
+ int qfatalCount() const;
+ int infoCount() const;
+
+ private:
+ QTestElement *listOfTestcases;
+ QTestElement *currentLogElement;
+ QTestElement *errorLogElement;
+ QTestBasicStreamer *logFormatter;
+ TestLoggerFormat format;
+ QTestFileLogger *filelogger;
+
+ int testCounter;
+ int passCounter;
+ int failureCounter;
+ int errorCounter;
+ int warningCounter;
+ int skipCounter;
+ int systemCounter;
+ int qdebugCounter;
+ int qwarnCounter;
+ int qfatalCounter;
+ int infoCounter;
+};
+
+QT_END_NAMESPACE
+
+#endif // QTESTLOGGER_P_H
diff --git a/src/testlib/qtestresult.cpp b/src/testlib/qtestresult.cpp
index 39759b5..0f21378 100644
--- a/src/testlib/qtestresult.cpp
+++ b/src/testlib/qtestresult.cpp
@@ -68,7 +68,7 @@ namespace QTest
static const char *expectFailComment = 0;
static int expectFailMode = 0;
-};
+}
void QTestResult::reset()
{
diff --git a/src/testlib/qtestxmlstreamer.cpp b/src/testlib/qtestxmlstreamer.cpp
new file mode 100644
index 0000000..5d57bab
--- /dev/null
+++ b/src/testlib/qtestxmlstreamer.cpp
@@ -0,0 +1,219 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestxmlstreamer.h"
+#include "qtestelement.h"
+#include "qtestelementattribute.h"
+
+#include "QtTest/private/qtestlog_p.h"
+#include "QtTest/private/qtestresult_p.h"
+#include "QtTest/private/qxmltestlogger_p.h"
+
+#include <string.h>
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+QTestXmlStreamer::QTestXmlStreamer()
+ :QTestBasicStreamer()
+{
+}
+
+QTestXmlStreamer::~QTestXmlStreamer()
+{}
+
+void QTestXmlStreamer::formatStart(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted)
+ return;
+
+ switch(element->elementType()){
+ case QTest::LET_TestCase: {
+ char quotedTf[950];
+ QXmlTestLogger::xmlQuote(quotedTf, element->attributeValue(QTest::AI_Name),
+ sizeof(quotedTf));
+
+ QTest::qt_snprintf(formatted, 1024, "<TestFunction name=\"%s\">\n", quotedTf);
+ break;
+ }
+ case QTest::LET_Failure: {
+ char cdataDesc[800];
+ QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description),
+ sizeof(cdataDesc));
+
+ char location[100];
+ char quotedFile[70];
+ QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File),
+ sizeof(quotedFile));
+
+ QTest::qt_snprintf(location, sizeof(location), "%s=\"%s\" %s=\"%s\"",
+ element->attributeName(QTest::AI_File),
+ quotedFile,
+ element->attributeName(QTest::AI_Line),
+ element->attributeValue(QTest::AI_Line));
+
+ if (element->attribute(QTest::AI_Tag)) {
+ char cdataTag[100];
+ QXmlTestLogger::xmlCdata(cdataTag, element->attributeValue(QTest::AI_Tag),
+ sizeof(cdataTag));
+ QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s>\n"
+ " <DataTag><![CDATA[%s]]></DataTag>\n"
+ " <Description><![CDATA[%s]]></Description>\n"
+ "</Incident>\n", element->attributeValue(QTest::AI_Result),
+ location, cdataTag, cdataDesc);
+ }
+ else {
+ QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s>\n"
+ " <Description><![CDATA[%s]]></Description>\n"
+ "</Incident>\n", element->attributeValue(QTest::AI_Result),
+ location, cdataDesc);
+ }
+ break;
+ }
+ case QTest::LET_Error: {
+ // assuming type and attribute names don't need quoting
+ char quotedFile[128];
+ char cdataDesc[700];
+ QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File),
+ sizeof(quotedFile));
+ QXmlTestLogger::xmlCdata(cdataDesc, element->attributeValue(QTest::AI_Description),
+ sizeof(cdataDesc));
+
+ QTest::qt_snprintf(formatted, 1024, "<Message type=\"%s\" %s=\"%s\" %s=\"%s\">\n <Description><![CDATA[%s]]></Description>\n</Message>\n",
+ element->attributeValue(QTest::AI_Type),
+ element->attributeName(QTest::AI_File),
+ quotedFile,
+ element->attributeName(QTest::AI_Line),
+ element->attributeValue(QTest::AI_Line),
+ cdataDesc);
+ break;
+ }
+ case QTest::LET_Benchmark: {
+ // assuming value and iterations don't need quoting
+ char quotedMetric[256];
+ char quotedTag[256];
+ QXmlTestLogger::xmlQuote(quotedMetric, element->attributeValue(QTest::AI_Metric),
+ sizeof(quotedMetric));
+ QXmlTestLogger::xmlQuote(quotedTag, element->attributeValue(QTest::AI_Tag),
+ sizeof(quotedTag));
+
+ QTest::qt_snprintf(formatted, 1024, "<BenchmarkResult %s=\"%s\" %s=\"%s\" %s=\"%s\" %s=\"%s\" />\n",
+ element->attributeName(QTest::AI_Metric),
+ quotedMetric,
+ element->attributeName(QTest::AI_Tag),
+ quotedTag,
+ element->attributeName(QTest::AI_Value),
+ element->attributeValue(QTest::AI_Value),
+ element->attributeName(QTest::AI_Iterations),
+ element->attributeValue(QTest::AI_Iterations) );
+ break;
+ }
+ default:
+ QTest::qt_snprintf(formatted, 10, "");
+ }
+}
+
+void QTestXmlStreamer::formatEnd(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted)
+ return;
+
+ if (element->elementType() == QTest::LET_TestCase) {
+ QTest::qt_snprintf(formatted, 1024, "</TestFunction>\n");
+ }
+ else
+ QTest::qt_snprintf(formatted, 10, "");
+}
+
+void QTestXmlStreamer::formatBeforeAttributes(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted)
+ return;
+
+ if (element->elementType() == QTest::LET_TestCase && element->attribute(QTest::AI_Result)){
+ char buf[900];
+ char quotedFile[700];
+ QXmlTestLogger::xmlQuote(quotedFile, element->attributeValue(QTest::AI_File),
+ sizeof(quotedFile));
+
+ QTest::qt_snprintf(buf, sizeof(buf), "%s=\"%s\" %s=\"%s\"",
+ element->attributeName(QTest::AI_File),
+ quotedFile,
+ element->attributeName(QTest::AI_Line),
+ element->attributeValue(QTest::AI_Line));
+
+ if( !element->childElements() ) {
+ QTest::qt_snprintf(formatted, 1024, "<Incident type=\"%s\" %s/>\n",
+ element->attributeValue(QTest::AI_Result), buf);
+ }
+ else {
+ QTest::qt_snprintf(formatted, 10, "");
+ }
+ }else{
+ QTest::qt_snprintf(formatted, 10, "");
+ }
+}
+
+void QTestXmlStreamer::output(QTestElement *element) const
+{
+ char buf[1024];
+ char quotedTc[800];
+ QXmlTestLogger::xmlQuote(quotedTc, QTestResult::currentTestObjectName(), sizeof(quotedTc));
+
+ QTest::qt_snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n<TestCase name=\"%s\">\n",
+ quotedTc);
+ outputString(buf);
+
+ QTest::qt_snprintf(buf, sizeof(buf), "<Environment>\n <QtVersion>%s</QtVersion>\n <QTestVersion>%s</QTestVersion>\n",
+ qVersion(), QTEST_VERSION_STR );
+ outputString(buf);
+
+ QTest::qt_snprintf(buf, sizeof(buf), "</Environment>\n");
+ outputString(buf);
+
+ QTestBasicStreamer::output(element);
+
+ QTest::qt_snprintf(buf, sizeof(buf), "</TestCase>\n");
+ outputString(buf);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestxmlstreamer.h b/src/testlib/qtestxmlstreamer.h
new file mode 100644
index 0000000..814bffc
--- /dev/null
+++ b/src/testlib/qtestxmlstreamer.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTXMLSTREAMER_H
+#define QTESXMLSTREAMER_H
+
+#include <QtTest/qtestbasicstreamer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+class QTestElement;
+class QTestElementAttribute;
+
+class QTestXmlStreamer: public QTestBasicStreamer
+{
+ public:
+ QTestXmlStreamer();
+ ~QTestXmlStreamer();
+
+ void formatStart(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatEnd(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatBeforeAttributes(const QTestElement *element = 0, char *formatted = 0) const;
+ void output(QTestElement *element) const;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qtestxunitstreamer.cpp b/src/testlib/qtestxunitstreamer.cpp
new file mode 100644
index 0000000..a34791c
--- /dev/null
+++ b/src/testlib/qtestxunitstreamer.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtestxunitstreamer.h"
+#include "qtestelement.h"
+
+#include "QtTest/private/qtestlog_p.h"
+#include "QtTest/private/qtestresult_p.h"
+#include "QtTest/private/qxmltestlogger_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QTestXunitStreamer::QTestXunitStreamer()
+ :QTestBasicStreamer()
+{}
+
+QTestXunitStreamer::~QTestXunitStreamer()
+{}
+
+void QTestXunitStreamer::indentForElement(const QTestElement* element, char* buf, int size)
+{
+ if (size == 0) return;
+
+ buf[0] = 0;
+
+ if (!element) return;
+
+ char* endbuf = buf + size;
+ element = element->parentElement();
+ while (element && buf+2 < endbuf) {
+ *(buf++) = ' ';
+ *(buf++) = ' ';
+ *buf = 0;
+ element = element->parentElement();
+ }
+}
+
+void QTestXunitStreamer::formatStart(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+
+ char indent[20];
+ indentForElement(element, indent, sizeof(indent));
+
+ // Errors are written as CDATA within system-err, comments elsewhere
+ if (element->elementType() == QTest::LET_Error) {
+ if (element->parentElement()->elementType() == QTest::LET_SystemError) {
+ QTest::qt_snprintf(formatted, 1024, "<![CDATA[");
+ }
+ else {
+ QTest::qt_snprintf(formatted, 1024, "%s<!--", indent);
+ }
+ return;
+ }
+
+ QTest::qt_snprintf(formatted, 1024, "%s<%s", indent, element->elementName());
+}
+
+void QTestXunitStreamer::formatEnd(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+
+ if(!element->childElements()){
+ QTest::qt_snprintf(formatted, 10, "");
+ return;
+ }
+
+ char indent[20];
+ indentForElement(element, indent, sizeof(indent));
+
+ QTest::qt_snprintf(formatted, 1024, "%s</%s>\n", indent, element->elementName());
+}
+
+void QTestXunitStreamer::formatAttributes(const QTestElement* element, const QTestElementAttribute *attribute, char *formatted) const
+{
+ if(!attribute || !formatted )
+ return;
+
+ QTest::AttributeIndex attrindex = attribute->index();
+
+ // For errors within system-err, we only want to output `message'
+ if (element && element->elementType() == QTest::LET_Error
+ && element->parentElement()->elementType() == QTest::LET_SystemError) {
+
+ if (attrindex != QTest::AI_Description) return;
+
+ QXmlTestLogger::xmlCdata(formatted, attribute->value(), 1024);
+ return;
+ }
+
+ char const* key = 0;
+ if (attrindex == QTest::AI_Description)
+ key = "message";
+ else if (attrindex != QTest::AI_File && attrindex != QTest::AI_Line)
+ key = attribute->name();
+
+ if (key) {
+ char quotedValue[900];
+ QXmlTestLogger::xmlQuote(quotedValue, attribute->value(), sizeof(quotedValue));
+ QTest::qt_snprintf(formatted, 1024, " %s=\"%s\"", key, quotedValue);
+ }
+ else {
+ QTest::qt_snprintf(formatted, 10, "");
+ }
+}
+
+void QTestXunitStreamer::formatAfterAttributes(const QTestElement *element, char *formatted) const
+{
+ if(!element || !formatted )
+ return;
+
+ // Errors are written as CDATA within system-err, comments elsewhere
+ if (element->elementType() == QTest::LET_Error) {
+ if (element->parentElement()->elementType() == QTest::LET_SystemError) {
+ QTest::qt_snprintf(formatted, 1024, "]]>\n");
+ }
+ else {
+ QTest::qt_snprintf(formatted, 1024, " -->\n");
+ }
+ return;
+ }
+
+ if(!element->childElements())
+ QTest::qt_snprintf(formatted, 10, "/>\n");
+ else
+ QTest::qt_snprintf(formatted, 10, ">\n");
+}
+
+void QTestXunitStreamer::output(QTestElement *element) const
+{
+ char buf[1024];
+ QTest::qt_snprintf(buf, sizeof(buf), "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n");
+ outputString(buf);
+ QTestBasicStreamer::output(element);
+}
+
+void QTestXunitStreamer::outputElements(QTestElement *element, bool) const
+{
+ char buf[1024];
+ bool hasChildren;
+ /*
+ Elements are in reverse order of occurrence, so start from the end and work
+ our way backwards.
+ */
+ while (element && element->nextElement()) {
+ element = element->nextElement();
+ }
+ while (element) {
+ hasChildren = element->childElements();
+
+ if(element->elementType() != QTest::LET_Benchmark){
+ formatStart(element, buf);
+ outputString(buf);
+
+ formatBeforeAttributes(element, buf);
+ outputString(buf);
+
+ outputElementAttributes(element, element->attributes());
+
+ formatAfterAttributes(element, buf);
+ outputString(buf);
+
+ if(hasChildren)
+ outputElements(element->childElements(), true);
+
+ formatEnd(element, buf);
+ outputString(buf);
+ }
+ element = element->previousElement();
+ }
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/testlib/qtestxunitstreamer.h b/src/testlib/qtestxunitstreamer.h
new file mode 100644
index 0000000..0e48b2c
--- /dev/null
+++ b/src/testlib/qtestxunitstreamer.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtTest module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain
+** additional rights. These rights are described in the Nokia Qt LGPL
+** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTESTXUNITSTREAMER_H
+#define QTESTXUNITSTREAMER_H
+
+#include <QtTest/qtestbasicstreamer.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Test)
+
+class QTestLogger;
+
+class QTestXunitStreamer: public QTestBasicStreamer
+{
+ public:
+ QTestXunitStreamer();
+ ~QTestXunitStreamer();
+
+ void formatStart(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatEnd(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatAfterAttributes(const QTestElement *element = 0, char *formatted = 0) const;
+ void formatAttributes(const QTestElement *element = 0, const QTestElementAttribute *attribute = 0, char *formatted = 0) const;
+ void output(QTestElement *element) const;
+ void outputElements(QTestElement *element, bool isChildElement = false) const;
+
+ private:
+ void displayXunitXmlHeader() const;
+ static void indentForElement(const QTestElement* element, char* buf, int size);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/testlib/qxmltestlogger.cpp b/src/testlib/qxmltestlogger.cpp
index bba98da..0606ced 100644
--- a/src/testlib/qxmltestlogger.cpp
+++ b/src/testlib/qxmltestlogger.cpp
@@ -46,6 +46,7 @@
#include "QtTest/private/qxmltestlogger_p.h"
#include "QtTest/private/qtestresult_p.h"
#include "QtTest/private/qbenchmark_p.h"
+#include "QtTest/qtestcase.h"
QT_BEGIN_NAMESPACE
@@ -90,27 +91,27 @@ namespace QTest {
}
-QXmlTestLogger::QXmlTestLogger(XmlMode mode ):
- xmlmode(mode)
+QXmlTestLogger::QXmlTestLogger(XmlMode mode )
+ :xmlmode(mode)
{
}
QXmlTestLogger::~QXmlTestLogger()
{
-
}
-
void QXmlTestLogger::startLogging()
{
QAbstractTestLogger::startLogging();
char buf[1024];
if (xmlmode == QXmlTestLogger::Complete) {
+ char quotedTc[900];
+ xmlQuote(quotedTc, QTestResult::currentTestObjectName(), sizeof(quotedTc));
QTest::qt_snprintf(buf, sizeof(buf),
"<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n"
- "<TestCase name=\"%s\">\n", QTestResult::currentTestObjectName());
+ "<TestCase name=\"%s\">\n", quotedTc);
outputString(buf);
}
@@ -134,7 +135,9 @@ void QXmlTestLogger::stopLogging()
void QXmlTestLogger::enterTestFunction(const char *function)
{
char buf[1024];
- QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", function);
+ char quotedFunction[950];
+ xmlQuote(quotedFunction, function, sizeof(quotedFunction));
+ QTest::qt_snprintf(buf, sizeof(buf), "<TestFunction name=\"%s\">\n", quotedFunction);
outputString(buf);
}
@@ -158,18 +161,18 @@ static const char *incidentFormatString(bool noDescription, bool noTag)
return "<Incident type=\"%s\" file=\"%s\" line=\"%d\" />\n";
else
return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
- "</Incident>\n";
+ " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
+ "</Incident>\n";
} else {
if (noTag)
return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <Description><![CDATA[%s%s%s%s]]></Description>\n"
- "</Incident>\n";
+ " <Description><![CDATA[%s%s%s%s]]></Description>\n"
+ "</Incident>\n";
else
return "<Incident type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
- " <Description><![CDATA[%s]]></Description>\n"
- "</Incident>\n";
+ " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
+ " <Description><![CDATA[%s]]></Description>\n"
+ "</Incident>\n";
}
}
@@ -185,40 +188,51 @@ static const char *messageFormatString(bool noDescription, bool noTag)
return "<Message type=\"%s\" file=\"%s\" line=\"%d\" />\n";
else
return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
- "</Message>\n";
+ " <DataTag><![CDATA[%s%s%s%s]]></DataTag>\n"
+ "</Message>\n";
} else {
if (noTag)
return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <Description><![CDATA[%s%s%s%s]]></Description>\n"
- "</Message>\n";
+ " <Description><![CDATA[%s%s%s%s]]></Description>\n"
+ "</Message>\n";
else
return "<Message type=\"%s\" file=\"%s\" line=\"%d\">\n"
- " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
- " <Description><![CDATA[%s]]></Description>\n"
- "</Message>\n";
+ " <DataTag><![CDATA[%s%s%s]]></DataTag>\n"
+ " <Description><![CDATA[%s]]></Description>\n"
+ "</Message>\n";
}
}
} // namespace
void QXmlTestLogger::addIncident(IncidentTypes type, const char *description,
- const char *file, int line)
+ const char *file, int line)
{
- char buf[1536];
+ // buffer must be large enough to hold all quoted/cdata buffers plus the format string itself
+ char buf[5000];
const char *tag = QTestResult::currentDataTag();
const char *gtag = QTestResult::currentGlobalDataTag();
const char *filler = (tag && gtag) ? ":" : "";
const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag);
+ char quotedFile[1024];
+ char cdataGtag[1024];
+ char cdataTag[1024];
+ char cdataDescription[1024];
+
+ xmlQuote(quotedFile, file, sizeof(quotedFile));
+ xmlCdata(cdataGtag, gtag, sizeof(cdataGtag));
+ xmlCdata(cdataTag, tag, sizeof(cdataTag));
+ xmlCdata(cdataDescription, description, sizeof(cdataDescription));
+
QTest::qt_snprintf(buf, sizeof(buf),
QTest::incidentFormatString(QTest::isEmpty(description), notag),
QTest::xmlIncidentType2String(type),
- file ? file : "", line,
- gtag ? gtag : "",
+ quotedFile, line,
+ cdataGtag,
filler,
- tag ? tag : "",
- description ? description : "");
+ cdataTag,
+ cdataDescription);
outputString(buf);
}
@@ -226,39 +240,156 @@ void QXmlTestLogger::addIncident(IncidentTypes type, const char *description,
void QXmlTestLogger::addBenchmarkResult(const QBenchmarkResult &result)
{
char buf[1536];
+ char quotedMetric[64];
+ char quotedTag[1024];
+
+ xmlQuote(quotedMetric,
+ QBenchmarkGlobalData::current->measurer->metricText().toAscii().constData(),
+ sizeof(quotedMetric));
+ xmlQuote(quotedTag, result.context.tag.toAscii().constData(), sizeof(quotedTag));
+
QTest::qt_snprintf(
buf, sizeof(buf),
QTest::benchmarkResultFormatString(),
- QBenchmarkGlobalData::current->measurer->metricText().toAscii().data(),
- result.context.tag.toAscii().data(),
+ quotedMetric,
+ quotedTag,
QByteArray::number(result.value).constData(), //no 64-bit qt_snprintf support
- result.iterations);
+ result.iterations);
outputString(buf);
}
void QXmlTestLogger::addMessage(MessageTypes type, const char *message,
const char *file, int line)
{
- char buf[1536];
- char msgbuf[1024];
+ char buf[5000];
const char *tag = QTestResult::currentDataTag();
const char *gtag = QTestResult::currentGlobalDataTag();
const char *filler = (tag && gtag) ? ":" : "";
const bool notag = QTest::isEmpty(tag) && QTest::isEmpty(gtag);
- QTest::qt_snprintf(msgbuf, sizeof(msgbuf), "%s",
- message ? message : "");
+ char quotedFile[1024];
+ char cdataGtag[1024];
+ char cdataTag[1024];
+ char cdataDescription[1024];
+
+ xmlQuote(quotedFile, file, sizeof(quotedFile));
+ xmlCdata(cdataGtag, gtag, sizeof(cdataGtag));
+ xmlCdata(cdataTag, tag, sizeof(cdataTag));
+ xmlCdata(cdataDescription, message, sizeof(cdataDescription));
QTest::qt_snprintf(buf, sizeof(buf),
QTest::messageFormatString(QTest::isEmpty(message), notag),
QTest::xmlMessageType2String(type),
- file ? file : "", line,
- gtag ? gtag : "",
+ quotedFile, line,
+ cdataGtag,
filler,
- tag ? tag : "",
- msgbuf);
+ cdataTag,
+ cdataDescription);
outputString(buf);
}
+/*
+ Copy up to n characters from the src string into dest, escaping any special
+ XML characters as necessary so that dest is suitable for use in an XML
+ quoted attribute string.
+*/
+void QXmlTestLogger::xmlQuote(char* dest, char const* src, size_t n)
+{
+ if (n == 0) return;
+
+ *dest = 0;
+ if (!src) return;
+
+ char* end = dest + n;
+
+ while (dest < end) {
+ switch (*src) {
+
+#define MAP_ENTITY(chr, ent) \
+ case chr: \
+ if (dest + sizeof(ent) < end) { \
+ strcpy(dest, ent); \
+ dest += sizeof(ent) - 1; \
+ } \
+ else { \
+ *dest = 0; \
+ return; \
+ } \
+ ++src; \
+ break;
+
+ MAP_ENTITY('>', "&gt;");
+ MAP_ENTITY('<', "&lt;");
+ MAP_ENTITY('\'', "&apos;");
+ MAP_ENTITY('"', "&quot;");
+ MAP_ENTITY('&', "&amp;");
+
+ // not strictly necessary, but allows handling of comments without
+ // having to explicitly look for `--'
+ MAP_ENTITY('-', "&#x002D;");
+
+#undef MAP_ENTITY
+
+ case 0:
+ *dest = 0;
+ return;
+
+ default:
+ *dest = *src;
+ ++dest;
+ ++src;
+ break;
+ }
+ }
+
+ // If we get here, dest was completely filled (dest == end)
+ *(dest-1) = 0;
+}
+
+/*
+ Copy up to n characters from the src string into dest, escaping any
+ special strings such that dest is suitable for use in an XML CDATA section.
+*/
+void QXmlTestLogger::xmlCdata(char* dest, char const* src, size_t n)
+{
+ if (!n) return;
+
+ if (!src || n == 1) {
+ *dest = 0;
+ return;
+ }
+
+ char const CDATA_END[] = "]]>";
+ char const CDATA_END_ESCAPED[] = "]]]><![CDATA[]>";
+
+ char* end = dest + n;
+ while (dest < end) {
+ if (!*src) {
+ *dest = 0;
+ return;
+ }
+
+ if (!strncmp(src, CDATA_END, sizeof(CDATA_END)-1)) {
+ if (dest + sizeof(CDATA_END_ESCAPED) < end) {
+ strcpy(dest, CDATA_END_ESCAPED);
+ src += sizeof(CDATA_END)-1;
+ dest += sizeof(CDATA_END_ESCAPED) - 1;
+ }
+ else {
+ *dest = 0;
+ return;
+ }
+ continue;
+ }
+
+ *dest = *src;
+ ++src;
+ ++dest;
+ }
+
+ // If we get here, dest was completely filled (dest == end)
+ *(dest-1) = 0;
+}
+
QT_END_NAMESPACE
diff --git a/src/testlib/qxmltestlogger_p.h b/src/testlib/qxmltestlogger_p.h
index 3e78969..79e34ff 100644
--- a/src/testlib/qxmltestlogger_p.h
+++ b/src/testlib/qxmltestlogger_p.h
@@ -79,6 +79,9 @@ public:
void addMessage(MessageTypes type, const char *message,
const char *file = 0, int line = 0);
+ static void xmlCdata(char* dest, char const* src, size_t n);
+ static void xmlQuote(char* dest, char const* src, size_t n);
+
private:
XmlMode xmlmode;
};
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index de42b6d..aa9f420 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -1,29 +1,70 @@
-TARGET = QtTest
+TARGET = QtTest
QPRO_PWD = $$PWD
-QT = core
+QT = core
INCLUDEPATH += .
-
-unix:!embedded {
- QMAKE_PKGCONFIG_DESCRIPTION = Qt Unit Testing Library
- QMAKE_PKGCONFIG_REQUIRES = QtCore
-}
+unix:!embedded:QMAKE_PKGCONFIG_DESCRIPTION = Qt \
+ Unit \
+ Testing \
+ Library
# Input
-HEADERS = qtest_global.h qtestcase.h qtestdata.h qtesteventloop.h
-SOURCES = qtestcase.cpp qtestlog.cpp qtesttable.cpp qtestdata.cpp qtestresult.cpp qasciikey.cpp qplaintestlogger.cpp qxmltestlogger.cpp qsignaldumper.cpp qabstracttestlogger.cpp qbenchmark.cpp qbenchmarkmeasurement.cpp qbenchmarkvalgrind.cpp qbenchmarkevent.cpp
-
-DEFINES += QT_NO_CAST_TO_ASCII QT_NO_CAST_FROM_ASCII QTESTLIB_MAKEDLL QT_NO_DATASTREAM
-
-wince*:{
- LIBS += libcmt.lib corelibc.lib ole32.lib oleaut32.lib uuid.lib commctrl.lib coredll.lib winsock.lib
-}
-
-mac {
- LIBS += -framework IOKit -framework Security
-}
-
+HEADERS = qtest_global.h \
+ qtestcase.h \
+ qtestdata.h \
+ qtesteventloop.h \
+ qtestcorelist.h \
+ qtestcoreelement.h \
+ qtestelement.h \
+ qtestelementattribute.h \
+ qtestbasicstreamer.h \
+ qtestxunitstreamer.h \
+ qtestxmlstreamer.h \
+ qtestlightxmlstreamer.h \
+ qtestfilelogger.h
+SOURCES = qtestcase.cpp \
+ qtestlog.cpp \
+ qtesttable.cpp \
+ qtestdata.cpp \
+ qtestresult.cpp \
+ qasciikey.cpp \
+ qplaintestlogger.cpp \
+ qxmltestlogger.cpp \
+ qsignaldumper.cpp \
+ qabstracttestlogger.cpp \
+ qbenchmark.cpp \
+ qbenchmarkmeasurement.cpp \
+ qbenchmarkvalgrind.cpp \
+ qbenchmarkevent.cpp \
+ qtestelement.cpp \
+ qtestelementattribute.cpp \
+ qtestbasicstreamer.cpp \
+ qtestxunitstreamer.cpp \
+ qtestxmlstreamer.cpp \
+ qtestlightxmlstreamer.cpp \
+ qtestlogger.cpp \
+ qtestfilelogger.cpp
+DEFINES += QT_NO_CAST_TO_ASCII \
+ QT_NO_CAST_FROM_ASCII \
+ QTESTLIB_MAKEDLL \
+ QT_NO_DATASTREAM
+embedded:QMAKE_CXXFLAGS += -fno-rtti
+wince*::LIBS += libcmt.lib \
+ corelibc.lib \
+ ole32.lib \
+ oleaut32.lib \
+ uuid.lib \
+ commctrl.lib \
+ coredll.lib \
+ winsock.lib
+mac:LIBS += -framework \
+ IOKit \
+ -framework \
+ Security
include(../qbase.pri)
QMAKE_TARGET_PRODUCT = QTestLib
-QMAKE_TARGET_DESCRIPTION = Qt Unit Testing Library
+QMAKE_TARGET_DESCRIPTION = Qt \
+ Unit \
+ Testing \
+ Library
symbian:TARGET.UID3=0x2001B2DF
diff --git a/src/tools/idc/main.cpp b/src/tools/idc/main.cpp
index eb04114..8d2f0cc 100644
--- a/src/tools/idc/main.cpp
+++ b/src/tools/idc/main.cpp
@@ -50,8 +50,8 @@ QT_BEGIN_NAMESPACE
static QString quotePath(const QString &s)
{
- if (!s.startsWith(QLatin1String("\"")) && s.contains(QLatin1Char(' ')))
- return QLatin1String("\"") + s + QLatin1String("\"");
+ if (!s.startsWith(QLatin1Char('\"')) && s.contains(QLatin1Char(' ')))
+ return QLatin1Char('\"') + s + QLatin1Char('\"');
return s;
}
@@ -282,7 +282,7 @@ int runIdc(int argc, char **argv)
fprintf(stderr, "Server unregistered successfully!\n");
return 0;
} else if (p[0] == QLatin1Char('/') || p[0] == QLatin1Char('-')) {
- error = QLatin1String("Unknown option \"") + p + QLatin1String("\"");
+ error = QLatin1String("Unknown option \"") + p + QLatin1Char('\"');
break;
} else {
input = QLatin1String(argv[i]);
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index ae8a76e..e4ad068 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -109,6 +109,14 @@ bool isVariantType(const char* type)
return qvariant_nameToType(type) != 0;
}
+/*!
+ Returns true if the type is qreal.
+*/
+static bool isQRealType(const char *type)
+{
+ return strcmp(type, "qreal") == 0;
+}
+
Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, FILE *outfile)
: out(outfile), cdef(classDef), metaTypes(metaTypes)
{
@@ -545,7 +553,7 @@ void Generator::generateProperties()
uint flags = Invalid;
if (!isVariantType(p.type)) {
flags |= EnumOrFlag;
- } else {
+ } else if (!isQRealType(p.type)) {
flags |= qvariant_nameToType(p.type) << 24;
}
if (!p.read.isEmpty())
@@ -589,10 +597,12 @@ void Generator::generateProperties()
if (p.notifyId != -1)
flags |= Notify;
- fprintf(out, " %4d, %4d, 0x%.8x,\n",
- strreg(p.name),
- strreg(p.type),
- flags);
+ fprintf(out, " %4d, %4d, ",
+ strreg(p.name),
+ strreg(p.type));
+ if (!(flags >> 24) && isQRealType(p.type))
+ fprintf(out, "(QMetaType::QReal << 24) | ");
+ fprintf(out, "0x%.8x,\n", flags);
}
if(cdef->notifyableProperties) {
@@ -1161,8 +1171,8 @@ void Generator::_generateFunctions(QList<FunctionDef> &list, int type)
for (int j = 0; j < f.arguments.count(); ++j) {
const ArgumentDef &a = f.arguments.at(j);
if (j) {
- sig += ",";
- arguments += ",";
+ sig += ',';
+ arguments += ',';
}
sig += a.normalizedType;
arguments += a.name;
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index a6a0ba1..a1738a5 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -752,14 +752,14 @@ void Moc::generate(FILE *out)
if (!noInclude) {
- if (includePath.size() && includePath.right(1) != "/")
- includePath += "/";
+ if (includePath.size() && !includePath.endsWith('/'))
+ includePath += '/';
for (int i = 0; i < includeFiles.size(); ++i) {
QByteArray inc = includeFiles.at(i);
if (inc[0] != '<' && inc[0] != '"') {
if (includePath.size() && includePath != "./")
inc.prepend(includePath);
- inc = "\"" + inc + "\"";
+ inc = '\"' + inc + '\"';
}
fprintf(out, "#include %s\n", inc.constData());
}
@@ -767,6 +767,9 @@ void Moc::generate(FILE *out)
if (classList.size() && classList.first().classname == "Qt")
fprintf(out, "#include <QtCore/qobject.h>\n");
+ if (mustIncludeQMetaTypeH)
+ fprintf(out, "#include <QtCore/qmetatype.h>\n");
+
fprintf(out, "#if !defined(Q_MOC_OUTPUT_REVISION)\n"
"#error \"The header file '%s' doesn't include <QObject>.\"\n", (const char *)fn);
fprintf(out, "#elif Q_MOC_OUTPUT_REVISION != %d\n", mocOutputRevision);
@@ -898,6 +901,9 @@ void Moc::parseProperty(ClassDef *def)
type = "qlonglong";
else if (type == "ULongLong")
type = "qulonglong";
+ else if (type == "qreal")
+ mustIncludeQMetaTypeH = true;
+
propDef.type = type;
next();
@@ -959,7 +965,7 @@ void Moc::parseProperty(ClassDef *def)
msg += " has no READ accessor function. The property will be invalid.";
warning(msg.constData());
}
- if(!propDef.notify.isEmpty())
+ if(!propDef.notify.isEmpty())
def->notifyableProperties++;
def->propertyList += propDef;
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 689104c..4a1dee9 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -177,13 +177,14 @@ class Moc : public Parser
{
public:
Moc()
- : noInclude(false), generatedCode(false)
+ : noInclude(false), generatedCode(false), mustIncludeQMetaTypeH(false)
{}
QByteArray filename;
bool noInclude;
bool generatedCode;
+ bool mustIncludeQMetaTypeH;
QByteArray includePath;
QList<QByteArray> includeFiles;
QList<ClassDef> classList;
diff --git a/src/tools/moc/outputrevision.h b/src/tools/moc/outputrevision.h
index 1e1d640..f577f6c 100644
--- a/src/tools/moc/outputrevision.h
+++ b/src/tools/moc/outputrevision.h
@@ -43,6 +43,6 @@
#define OUTPUTREVISION_H
// if the output revision changes, you MUST change it in qobjectdefs.h too
-enum { mocOutputRevision = 61 }; // moc format output revision
+enum { mocOutputRevision = 62 }; // moc format output revision
#endif // OUTPUTREVISION_H
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index d1703c8..51f3a9b 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -812,7 +812,7 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
continue;
QByteArray frameworkCandidate = include.left(slashPos);
frameworkCandidate.append(".framework/Headers/");
- fi.setFile(QString::fromLocal8Bit(p.path + "/" + frameworkCandidate), QString::fromLocal8Bit(include.mid(slashPos + 1)));
+ fi.setFile(QString::fromLocal8Bit(p.path + '/' + frameworkCandidate), QString::fromLocal8Bit(include.mid(slashPos + 1)));
} else {
fi.setFile(QString::fromLocal8Bit(p.path), QString::fromLocal8Bit(include));
}
diff --git a/src/tools/uic/cpp/cppwriteicondata.cpp b/src/tools/uic/cpp/cppwriteicondata.cpp
index 53b108f..08d552d 100644
--- a/src/tools/uic/cpp/cppwriteicondata.cpp
+++ b/src/tools/uic/cpp/cppwriteicondata.cpp
@@ -161,9 +161,9 @@ void WriteIconData::writeImage(QTextStream &output, const QString &indent, DomIm
for (a = 0; a < (int) (data.length()/2)-1; a++) {
output << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << ',';
if (a % 12 == 11)
- output << "\n" << indent;
+ output << '\n' << indent;
else
- output << " ";
+ output << ' ';
}
output << "0x" << QString(data[2*a]) << QString(data[2*a+1]) << '\n';
output << "};\n\n";
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 47566ad..5a2f487 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -2813,7 +2813,7 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
bool generateMultiDirective = false;
if (emptyItemPolicy == Item::ConstructItemOnly && m_children.size() == 0) {
if (m_setupUiData.policy == ItemData::DontGenerate) {
- m_setupUiStream << m_indent << "new " << m_itemClassName << "(" << parent << ");\n";
+ m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
return QString();
} else if (m_setupUiData.policy == ItemData::GenerateWithMultiDirective) {
generateMultiDirective = true;
@@ -2824,11 +2824,11 @@ QString WriteInitialization::Item::writeSetupUi(const QString &parent, Item::Emp
generateMultiDirectiveBegin(m_setupUiStream, m_setupUiData.directives);
const QString uniqueName = m_driver->unique(QLatin1String("__") + m_itemClassName.toLower());
- m_setupUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = new " << m_itemClassName << "(" << parent << ");\n";
+ m_setupUiStream << m_indent << m_itemClassName << " *" << uniqueName << " = new " << m_itemClassName << '(' << parent << ");\n";
if (generateMultiDirective) {
m_setupUiStream << "#else\n";
- m_setupUiStream << m_indent << "new " << m_itemClassName << "(" << parent << ");\n";
+ m_setupUiStream << m_indent << "new " << m_itemClassName << '(' << parent << ");\n";
generateMultiDirectiveEnd(m_setupUiStream, m_setupUiData.directives);
}
diff --git a/src/tools/uic/ui4.cpp b/src/tools/uic/ui4.cpp
index d6cd759..69d0c53 100644
--- a/src/tools/uic/ui4.cpp
+++ b/src/tools/uic/ui4.cpp
@@ -2368,6 +2368,7 @@ void DomCustomWidget::clear(bool clear_all)
delete m_script;
delete m_properties;
delete m_slots;
+ delete m_propertyspecifications;
if (clear_all) {
m_text.clear();
@@ -2381,6 +2382,7 @@ void DomCustomWidget::clear(bool clear_all)
m_script = 0;
m_properties = 0;
m_slots = 0;
+ m_propertyspecifications = 0;
}
DomCustomWidget::DomCustomWidget()
@@ -2393,6 +2395,7 @@ DomCustomWidget::DomCustomWidget()
m_script = 0;
m_properties = 0;
m_slots = 0;
+ m_propertyspecifications = 0;
}
DomCustomWidget::~DomCustomWidget()
@@ -2403,6 +2406,7 @@ DomCustomWidget::~DomCustomWidget()
delete m_script;
delete m_properties;
delete m_slots;
+ delete m_propertyspecifications;
}
void DomCustomWidget::read(QXmlStreamReader &reader)
@@ -2468,6 +2472,12 @@ void DomCustomWidget::read(QXmlStreamReader &reader)
setElementSlots(v);
continue;
}
+ if (tag == QLatin1String("propertyspecifications")) {
+ DomPropertySpecifications *v = new DomPropertySpecifications();
+ v->read(reader);
+ setElementPropertyspecifications(v);
+ continue;
+ }
reader.raiseError(QLatin1String("Unexpected element ") + tag);
}
break;
@@ -2548,6 +2558,12 @@ void DomCustomWidget::read(const QDomElement &node)
setElementSlots(v);
continue;
}
+ if (tag == QLatin1String("propertyspecifications")) {
+ DomPropertySpecifications *v = new DomPropertySpecifications();
+ v->read(e);
+ setElementPropertyspecifications(v);
+ continue;
+ }
}
m_text.clear();
for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
@@ -2605,6 +2621,10 @@ void DomCustomWidget::write(QXmlStreamWriter &writer, const QString &tagName) co
m_slots->write(writer, QLatin1String("slots"));
}
+ if (m_children & Propertyspecifications) {
+ m_propertyspecifications->write(writer, QLatin1String("propertyspecifications"));
+ }
+
if (!m_text.isEmpty())
writer.writeCharacters(m_text);
@@ -2731,6 +2751,21 @@ void DomCustomWidget::setElementSlots(DomSlots* a)
m_slots = a;
}
+DomPropertySpecifications* DomCustomWidget::takeElementPropertyspecifications()
+{
+ DomPropertySpecifications* a = m_propertyspecifications;
+ m_propertyspecifications = 0;
+ m_children ^= Propertyspecifications;
+ return a;
+}
+
+void DomCustomWidget::setElementPropertyspecifications(DomPropertySpecifications* a)
+{
+ delete m_propertyspecifications;
+ m_children |= Propertyspecifications;
+ m_propertyspecifications = a;
+}
+
void DomCustomWidget::clearElementClass()
{
m_children &= ~Class;
@@ -2798,6 +2833,13 @@ void DomCustomWidget::clearElementSlots()
m_children &= ~Slots;
}
+void DomCustomWidget::clearElementPropertyspecifications()
+{
+ delete m_propertyspecifications;
+ m_propertyspecifications = 0;
+ m_children &= ~Propertyspecifications;
+}
+
void DomProperties::clear(bool clear_all)
{
qDeleteAll(m_property);
@@ -10883,5 +10925,208 @@ void DomSlots::setElementSlot(const QStringList& a)
m_slot = a;
}
+void DomPropertySpecifications::clear(bool clear_all)
+{
+ qDeleteAll(m_stringpropertyspecification);
+ m_stringpropertyspecification.clear();
+
+ if (clear_all) {
+ m_text.clear();
+ }
+
+ m_children = 0;
+}
+
+DomPropertySpecifications::DomPropertySpecifications()
+{
+ m_children = 0;
+}
+
+DomPropertySpecifications::~DomPropertySpecifications()
+{
+ qDeleteAll(m_stringpropertyspecification);
+ m_stringpropertyspecification.clear();
+}
+
+void DomPropertySpecifications::read(QXmlStreamReader &reader)
+{
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ if (tag == QLatin1String("stringpropertyspecification")) {
+ DomStringPropertySpecification *v = new DomStringPropertySpecification();
+ v->read(reader);
+ m_stringpropertyspecification.append(v);
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomPropertySpecifications::read(const QDomElement &node)
+{
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ if (tag == QLatin1String("stringpropertyspecification")) {
+ DomStringPropertySpecification *v = new DomStringPropertySpecification();
+ v->read(e);
+ m_stringpropertyspecification.append(v);
+ continue;
+ }
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomPropertySpecifications::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("propertyspecifications") : tagName.toLower());
+
+ for (int i = 0; i < m_stringpropertyspecification.size(); ++i) {
+ DomStringPropertySpecification* v = m_stringpropertyspecification[i];
+ v->write(writer, QLatin1String("stringpropertyspecification"));
+ }
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
+void DomPropertySpecifications::setElementStringpropertyspecification(const QList<DomStringPropertySpecification*>& a)
+{
+ m_children |= Stringpropertyspecification;
+ m_stringpropertyspecification = a;
+}
+
+void DomStringPropertySpecification::clear(bool clear_all)
+{
+
+ if (clear_all) {
+ m_text.clear();
+ m_has_attr_name = false;
+ m_has_attr_type = false;
+ m_has_attr_notr = false;
+ }
+
+ m_children = 0;
+}
+
+DomStringPropertySpecification::DomStringPropertySpecification()
+{
+ m_children = 0;
+ m_has_attr_name = false;
+ m_has_attr_type = false;
+ m_has_attr_notr = false;
+}
+
+DomStringPropertySpecification::~DomStringPropertySpecification()
+{
+}
+
+void DomStringPropertySpecification::read(QXmlStreamReader &reader)
+{
+
+ foreach (const QXmlStreamAttribute &attribute, reader.attributes()) {
+ QStringRef name = attribute.name();
+ if (name == QLatin1String("name")) {
+ setAttributeName(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("type")) {
+ setAttributeType(attribute.value().toString());
+ continue;
+ }
+ if (name == QLatin1String("notr")) {
+ setAttributeNotr(attribute.value().toString());
+ continue;
+ }
+ reader.raiseError(QLatin1String("Unexpected attribute ") + name.toString());
+ }
+
+ for (bool finished = false; !finished && !reader.hasError();) {
+ switch (reader.readNext()) {
+ case QXmlStreamReader::StartElement : {
+ const QString tag = reader.name().toString().toLower();
+ reader.raiseError(QLatin1String("Unexpected element ") + tag);
+ }
+ break;
+ case QXmlStreamReader::EndElement :
+ finished = true;
+ break;
+ case QXmlStreamReader::Characters :
+ if (!reader.isWhitespace())
+ m_text.append(reader.text().toString());
+ break;
+ default :
+ break;
+ }
+ }
+}
+
+#ifdef QUILOADER_QDOM_READ
+void DomStringPropertySpecification::read(const QDomElement &node)
+{
+ if (node.hasAttribute(QLatin1String("name")))
+ setAttributeName(node.attribute(QLatin1String("name")));
+ if (node.hasAttribute(QLatin1String("type")))
+ setAttributeType(node.attribute(QLatin1String("type")));
+ if (node.hasAttribute(QLatin1String("notr")))
+ setAttributeNotr(node.attribute(QLatin1String("notr")));
+
+ for (QDomNode n = node.firstChild(); !n.isNull(); n = n.nextSibling()) {
+ if (!n.isElement())
+ continue;
+ QDomElement e = n.toElement();
+ QString tag = e.tagName().toLower();
+ }
+ m_text.clear();
+ for (QDomNode child = node.firstChild(); !child.isNull(); child = child.nextSibling()) {
+ if (child.isText())
+ m_text.append(child.nodeValue());
+ }
+}
+#endif
+
+void DomStringPropertySpecification::write(QXmlStreamWriter &writer, const QString &tagName) const
+{
+ writer.writeStartElement(tagName.isEmpty() ? QString::fromUtf8("stringpropertyspecification") : tagName.toLower());
+
+ if (hasAttributeName())
+ writer.writeAttribute(QLatin1String("name"), attributeName());
+
+ if (hasAttributeType())
+ writer.writeAttribute(QLatin1String("type"), attributeType());
+
+ if (hasAttributeNotr())
+ writer.writeAttribute(QLatin1String("notr"), attributeNotr());
+
+ if (!m_text.isEmpty())
+ writer.writeCharacters(m_text);
+
+ writer.writeEndElement();
+}
+
QT_END_NAMESPACE
diff --git a/src/tools/uic/ui4.h b/src/tools/uic/ui4.h
index df02a39..fa70573 100644
--- a/src/tools/uic/ui4.h
+++ b/src/tools/uic/ui4.h
@@ -161,6 +161,8 @@ class DomScript;
class DomWidgetData;
class DomDesignerData;
class DomSlots;
+class DomPropertySpecifications;
+class DomStringPropertySpecification;
/*******************************************************************************
** Declarations
@@ -1015,6 +1017,12 @@ public:
inline bool hasElementSlots() const { return m_children & Slots; }
void clearElementSlots();
+ inline DomPropertySpecifications* elementPropertyspecifications() const { return m_propertyspecifications; }
+ DomPropertySpecifications* takeElementPropertyspecifications();
+ void setElementPropertyspecifications(DomPropertySpecifications* a);
+ inline bool hasElementPropertyspecifications() const { return m_children & Propertyspecifications; }
+ void clearElementPropertyspecifications();
+
private:
QString m_text;
void clear(bool clear_all = true);
@@ -1033,6 +1041,7 @@ private:
DomScript* m_script;
DomProperties* m_properties;
DomSlots* m_slots;
+ DomPropertySpecifications* m_propertyspecifications;
enum Child {
Class = 1,
Extends = 2,
@@ -1044,7 +1053,8 @@ private:
Pixmap = 128,
Script = 256,
Properties = 512,
- Slots = 1024
+ Slots = 1024,
+ Propertyspecifications = 2048
};
DomCustomWidget(const DomCustomWidget &other);
@@ -3686,6 +3696,91 @@ private:
void operator = (const DomSlots&other);
};
+class QDESIGNER_UILIB_EXPORT DomPropertySpecifications {
+public:
+ DomPropertySpecifications();
+ ~DomPropertySpecifications();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ // child element accessors
+ inline QList<DomStringPropertySpecification*> elementStringpropertyspecification() const { return m_stringpropertyspecification; }
+ void setElementStringpropertyspecification(const QList<DomStringPropertySpecification*>& a);
+
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ // child element data
+ uint m_children;
+ QList<DomStringPropertySpecification*> m_stringpropertyspecification;
+ enum Child {
+ Stringpropertyspecification = 1
+ };
+
+ DomPropertySpecifications(const DomPropertySpecifications &other);
+ void operator = (const DomPropertySpecifications&other);
+};
+
+class QDESIGNER_UILIB_EXPORT DomStringPropertySpecification {
+public:
+ DomStringPropertySpecification();
+ ~DomStringPropertySpecification();
+
+ void read(QXmlStreamReader &reader);
+#ifdef QUILOADER_QDOM_READ
+ void read(const QDomElement &node);
+#endif
+ void write(QXmlStreamWriter &writer, const QString &tagName = QString()) const;
+ inline QString text() const { return m_text; }
+ inline void setText(const QString &s) { m_text = s; }
+
+ // attribute accessors
+ inline bool hasAttributeName() const { return m_has_attr_name; }
+ inline QString attributeName() const { return m_attr_name; }
+ inline void setAttributeName(const QString& a) { m_attr_name = a; m_has_attr_name = true; }
+ inline void clearAttributeName() { m_has_attr_name = false; }
+
+ inline bool hasAttributeType() const { return m_has_attr_type; }
+ inline QString attributeType() const { return m_attr_type; }
+ inline void setAttributeType(const QString& a) { m_attr_type = a; m_has_attr_type = true; }
+ inline void clearAttributeType() { m_has_attr_type = false; }
+
+ inline bool hasAttributeNotr() const { return m_has_attr_notr; }
+ inline QString attributeNotr() const { return m_attr_notr; }
+ inline void setAttributeNotr(const QString& a) { m_attr_notr = a; m_has_attr_notr = true; }
+ inline void clearAttributeNotr() { m_has_attr_notr = false; }
+
+ // child element accessors
+private:
+ QString m_text;
+ void clear(bool clear_all = true);
+
+ // attribute data
+ QString m_attr_name;
+ bool m_has_attr_name;
+
+ QString m_attr_type;
+ bool m_has_attr_type;
+
+ QString m_attr_notr;
+ bool m_has_attr_notr;
+
+ // child element data
+ uint m_children;
+
+ DomStringPropertySpecification(const DomStringPropertySpecification &other);
+ void operator = (const DomStringPropertySpecification&other);
+};
+
#ifdef QFORMINTERNAL_NAMESPACE
}
diff --git a/src/tools/uic3/embed.cpp b/src/tools/uic3/embed.cpp
index 882328a..b406c1f 100644
--- a/src/tools/uic3/embed.cpp
+++ b/src/tools/uic3/embed.cpp
@@ -238,7 +238,7 @@ void Ui3Reader::embed(const char *project, const QStringList &images)
out << "true, ";
else
out << "false, ";
- out << "\"" << e->name << "\" },\n";
+ out << '\"' << e->name << "\" },\n";
delete e;
}
#ifndef QT_NO_IMAGE_COLLECTION_COMPRESSION
diff --git a/src/tools/uic3/form.cpp b/src/tools/uic3/form.cpp
index d9e968b..b484210 100644
--- a/src/tools/uic3/form.cpp
+++ b/src/tools/uic3/form.cpp
@@ -185,14 +185,14 @@ void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes)
for (it = globalIncludes.constBegin(); it != globalIncludes.constEnd(); ++it) {
if (!(*it).isEmpty()) {
QString header = fixHeaderName(*it);
- out << "#include <" << header << ">" << endl;
+ out << "#include <" << header << '>' << endl;
}
}
localIncludes = unique(localIncludes);
for (it = localIncludes.constBegin(); it != localIncludes.constEnd(); ++it) {
if (!(*it).isEmpty()) {
QString header = fixHeaderName(*it);
- out << "#include \"" << header << "\"" << endl;
+ out << "#include \"" << header << '\"' << endl;
}
}
out << endl;
@@ -216,7 +216,7 @@ void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes)
typeDefs = unique(typeDefs);
for (it = typeDefs.constBegin(); it != typeDefs.constEnd(); ++it) {
if (!(*it).isEmpty())
- out << "typedef " << *it << ";" << endl;
+ out << "typedef " << *it << ';' << endl;
}
nl = e.parentNode().toElement().elementsByTagName(QLatin1String("forward"));
@@ -236,17 +236,17 @@ void Ui3Reader::createFormDecl(const QDomElement &e, bool implicitIncludes)
out << "namespace " << *ns << " {" << endl;
++ns;
}
- out << "class " << forwardName << ";" << endl;
+ out << "class " << forwardName << ';' << endl;
for (int i = 0; i < (int) forwardNamespaces.count(); i++)
- out << "}" << endl;
+ out << '}' << endl;
}
}
for (it = forwardDecl2.constBegin(); it != forwardDecl2.constEnd(); ++it) {
QString fd = *it;
fd = fd.trimmed();
- if (!fd.endsWith(QLatin1String(";")))
- fd += QLatin1String(";");
+ if (!fd.endsWith(QLatin1Char(';')))
+ fd += QLatin1Char(';');
out << fd << endl;
}
@@ -279,7 +279,7 @@ void Ui3Reader::createWrapperDecl(const QDomElement &e, const QString &converted
out << "#ifndef " << protector << endl;
out << "#define " << protector << endl;
out << endl;
- out << "#include \"" << convertedUiFile << "\"" << endl;
+ out << "#include \"" << convertedUiFile << '\"' << endl;
createWrapperDeclContents(e);
out << endl;
@@ -309,8 +309,8 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
out << "class ";
if (!exportMacro.isEmpty())
- out << exportMacro << " ";
- out << bareNameOfClass << " : public " << objClass << ", public Ui::" << bareNameOfClass << endl << "{" << endl;
+ out << exportMacro << ' ';
+ out << bareNameOfClass << " : public " << objClass << ", public Ui::" << bareNameOfClass << endl << '{' << endl;
/* qmake ignore Q_OBJECT */
out << " Q_OBJECT" << endl;
@@ -362,8 +362,8 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
continue;
QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
QString functionName = n.firstChild().toText().data().trimmed();
- if (functionName.endsWith(QLatin1String(";")))
- functionName = functionName.left(functionName.length() - 1);
+ if (functionName.endsWith(QLatin1Char(';')))
+ functionName.chop(1);
QString specifier = n.attribute(QLatin1String("specifier"));
QString access = n.attribute(QLatin1String("access"));
if (access == QLatin1String(QLatin1String("protected"))) {
@@ -394,8 +394,8 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
continue;
QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
QString functionName = n.firstChild().toText().data().trimmed();
- if (functionName.endsWith(QLatin1String(";")))
- functionName = functionName.left(functionName.length() - 1);
+ if (functionName.endsWith(QLatin1Char(';')))
+ functionName.chop(1);
QString specifier = n.attribute(QLatin1String("specifier"));
QString access = n.attribute(QLatin1String("access"));
if (access == QLatin1String("protected")) {
@@ -423,8 +423,8 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
// continue;
QString access = n.attribute(QLatin1String("access"), QLatin1String("protected"));
QString var = fixDeclaration(n.firstChild().toText().data().trimmed());
- if (!var.endsWith(QLatin1String(";")))
- var += QLatin1String(";");
+ if (!var.endsWith(QLatin1Char(';')))
+ var += QLatin1Char(';');
if (access == QLatin1String("public"))
publicVars += var;
else if (access == QLatin1String("private"))
@@ -458,7 +458,7 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
continue;
QString sigName = n.firstChild().toText().data().trimmed();
- if (sigName.endsWith(QLatin1String(";")))
+ if (sigName.endsWith(QLatin1Char(';')))
sigName = sigName.left(sigName.length() - 1);
extraSignals += fixDeclaration(sigName);
}
@@ -467,7 +467,7 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
if (!extraSignals.isEmpty()) {
out << "signals:" << endl;
for (it = extraSignals.constBegin(); it != extraSignals.constEnd(); ++it)
- out << " void " << (*it) << ";" << endl;
+ out << " void " << (*it) << ';' << endl;
out << endl;
}
@@ -513,7 +513,7 @@ void Ui3Reader::createWrapperDeclContents(const QDomElement &e)
out << "};" << endl;
for (i = 0; i < (int) namespaces.count(); i++)
- out << "}" << endl;
+ out << '}' << endl;
out << endl;
}
@@ -543,7 +543,7 @@ void Ui3Reader::writeFunctionsDecl(const QStringList &fuLst, const QStringList &
signature = fixDeclaration(signature);
type = fixType(type);
- out << " " << specifier << type << " " << signature << pure << ";" << endl;
+ out << " " << specifier << type << ' ' << signature << pure << ';' << endl;
}
out << endl;
}
@@ -583,8 +583,8 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
continue;
QString functionName = n.firstChild().toText().data().trimmed();
- if (functionName.endsWith(QLatin1String(";")))
- functionName = functionName.left(functionName.length() - 1);
+ if (functionName.endsWith(QLatin1Char(';')))
+ functionName.chop(1);
extraFuncts += functionName;
extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void"));
extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual"));
@@ -598,8 +598,8 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
if (n.attribute(QLatin1String("language"), QLatin1String("C++")) != QLatin1String("C++"))
continue;
QString functionName = n.firstChild().toText().data().trimmed();
- if (functionName.endsWith(QLatin1String(";")))
- functionName = functionName.left(functionName.length() - 1);
+ if (functionName.endsWith(QLatin1Char(';')))
+ functionName.chop(1);
extraFuncts += functionName;
extraFunctTyp += n.attribute(QLatin1String("returnType"), QLatin1String("void"));
extraFunctSpecifier += n.attribute(QLatin1String("specifier"), QLatin1String("virtual"));
@@ -663,7 +663,7 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
globalIncludes = unique(globalIncludes);
for (it = globalIncludes.begin(); it != globalIncludes.end(); ++it) {
if (!(*it).isEmpty())
- out << "#include <" << fixHeaderName(*it) << ">" << endl;
+ out << "#include <" << fixHeaderName(*it) << '>' << endl;
}
if (externPixmaps) {
@@ -677,14 +677,14 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
localIncludes = unique(localIncludes);
for (it = localIncludes.begin(); it != localIncludes.end(); ++it) {
if (!(*it).isEmpty() && *it != QFileInfo(fileName + QLatin1String(".h")).fileName())
- out << "#include \"" << fixHeaderName(*it) << "\"" << endl;
+ out << "#include \"" << fixHeaderName(*it) << '\"' << endl;
}
QString uiDotH = fileName + QLatin1String(".h");
if (QFile::exists(uiDotH)) {
if (!outputFileName.isEmpty())
uiDotH = QString::fromUtf8(combinePath(uiDotH.ascii(), outputFileName.ascii()));
- out << "#include \"" << uiDotH << "\"" << endl;
+ out << "#include \"" << uiDotH << '\"' << endl;
writeFunctImpl = false;
}
@@ -702,7 +702,7 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
out << " * name 'name' and widget flags set to 'f'." << endl;
out << " *" << endl;
out << " * The " << objClass.mid(1).toLower() << " will by default be modeless, unless you set 'modal' to" << endl;
- out << " * true to construct a modal " << objClass.mid(1).toLower() << "." << endl;
+ out << " * true to construct a modal " << objClass.mid(1).toLower() << '.' << endl;
out << " */" << endl;
out << nameOfClass << "::" << bareNameOfClass << "(QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl)" << endl;
out << " : " << objClass << "(parent, name, modal, fl)";
@@ -733,7 +733,7 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
out << endl;
- out << "{" << endl;
+ out << '{' << endl;
//
// setup the gui
@@ -775,7 +775,7 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
out << indent << "init();" << endl;
// end of constructor
- out << "}" << endl;
+ out << '}' << endl;
out << endl;
// destructor
@@ -783,11 +783,11 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
out << " * Destroys the object and frees any allocated resources" << endl;
out << " */" << endl;
out << nameOfClass << "::~" << bareNameOfClass << "()" << endl;
- out << "{" << endl;
+ out << '{' << endl;
if (extraFuncts.contains(QLatin1String("destroy()")))
out << indent << "destroy();" << endl;
out << indent << "// no need to delete child widgets, Qt does it all for us" << endl;
- out << "}" << endl;
+ out << '}' << endl;
out << endl;
// handle application events if required
@@ -816,9 +816,9 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
out << " * language." << endl;
out << " */" << endl;
out << "void " << nameOfClass << "::languageChange()" << endl;
- out << "{" << endl;
+ out << '{' << endl;
out << " retranslateUi(this);" << endl;
- out << "}" << endl;
+ out << '}' << endl;
out << endl;
// create stubs for additional slots if necessary
@@ -833,8 +833,8 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
type = type.simplified();
QString fname = fixDeclaration(Parser::cleanArgs(*it));
if (!(*it3).startsWith(QLatin1String("pure"))) { // "pure virtual" or "pureVirtual"
- out << type << " " << nameOfClass << "::" << fname << endl;
- out << "{" << endl;
+ out << type << ' ' << nameOfClass << "::" << fname << endl;
+ out << '{' << endl;
if (*it != QLatin1String("init()") && *it != QLatin1String("destroy()")) {
QRegExp numeric(QLatin1String("^(?:signed|unsigned|u?char|u?short|u?int"
"|u?long|Q_U?INT(?:8|16|32)|Q_U?LONG|float"
@@ -868,14 +868,14 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
if (type == QLatin1String("bool")) {
retVal = QLatin1String("false");
- } else if (isBasicNumericType || type.endsWith(QLatin1String("*"))) {
+ } else if (isBasicNumericType || type.endsWith(QLatin1Char('*'))) {
retVal = QLatin1String("0");
- } else if (type.endsWith(QLatin1String("&"))) {
+ } else if (type.endsWith(QLatin1Char('&'))) {
do {
type.chop(1);
- } while (type.endsWith(QLatin1String(" ")));
+ } while (type.endsWith(QLatin1Char(' ')));
retVal = QLatin1String("uic_temp_var");
- out << indent << "static " << type << " " << retVal << ";" << endl;
+ out << indent << "static " << type << ' ' << retVal << ';' << endl;
} else {
retVal = type + QLatin1String("()");
}
@@ -883,9 +883,9 @@ void Ui3Reader::createFormImpl(const QDomElement &e)
out << indent << "qWarning(\"" << nameOfClass << "::" << fname << ": Not implemented yet\");" << endl;
if (!retVal.isEmpty())
- out << indent << "return " << retVal << ";" << endl;
+ out << indent << "return " << retVal << ';' << endl;
}
- out << "}" << endl;
+ out << '}' << endl;
out << endl;
}
++it;
diff --git a/src/tools/uic3/main.cpp b/src/tools/uic3/main.cpp
index d581016..9535b91 100644
--- a/src/tools/uic3/main.cpp
+++ b/src/tools/uic3/main.cpp
@@ -367,7 +367,7 @@ int runUic3(int argc, char * argv[])
}
if (headerFile) {
- out << "#include \"" << headerFile << "\"" << endl << endl;
+ out << "#include \"" << headerFile << '\"' << endl << endl;
}
QString convertedUi;
diff --git a/src/tools/uic3/parser.cpp b/src/tools/uic3/parser.cpp
index 744dd30..395cc4d 100644
--- a/src/tools/uic3/parser.cpp
+++ b/src/tools/uic3/parser.cpp
@@ -48,14 +48,14 @@ QT_BEGIN_NAMESPACE
QString Parser::cleanArgs(const QString &func)
{
QString slot(func);
- int begin = slot.indexOf(QLatin1String("(")) + 1;
+ int begin = slot.indexOf(QLatin1Char('(')) + 1;
QString args = slot.mid(begin);
- args = args.left(args.indexOf(QLatin1String(")")));
+ args = args.left(args.indexOf(QLatin1Char(')')));
QStringList lst = args.split(QLatin1Char(','));
QString res = slot.left(begin);
for (QStringList::Iterator it = lst.begin(); it != lst.end(); ++it) {
if (it != lst.begin())
- res += QLatin1String(",");
+ res += QLatin1Char(',');
QString arg = *it;
int pos = 0;
if ((pos = arg.indexOf(QLatin1Char('&'))) != -1) {
@@ -65,7 +65,7 @@ QString Parser::cleanArgs(const QString &func)
} else {
arg = arg.simplified();
if ((pos = arg.indexOf(QLatin1Char(':'))) != -1)
- arg = arg.left(pos).simplified() + QLatin1String(":") + arg.mid(pos + 1).simplified();
+ arg = arg.left(pos).simplified() + QLatin1Char(':') + arg.mid(pos + 1).simplified();
QStringList l = arg.split(QLatin1Char(' '));
if (l.count() == 2) {
if (l[0] != QLatin1String("const")
@@ -73,12 +73,12 @@ QString Parser::cleanArgs(const QString &func)
&& l[0] != QLatin1String("var"))
arg = l[0];
} else if (l.count() == 3) {
- arg = l[0] + QLatin1String(" ") + l[1];
+ arg = l[0] + QLatin1Char(' ') + l[1];
}
}
res += arg;
}
- res += QLatin1String(")");
+ res += QLatin1Char(')');
return res;
}
diff --git a/src/tools/uic3/qt3to4.cpp b/src/tools/uic3/qt3to4.cpp
index 9e5b64b..2862727 100644
--- a/src/tools/uic3/qt3to4.cpp
+++ b/src/tools/uic3/qt3to4.cpp
@@ -149,7 +149,7 @@ void Porting::readXML(RuleList *renamedHeaders, RuleList *renamedClasses, RuleLi
QString fileName = QLatin1String("q3porting.xml");
QString filePath;
//check QLibraryInfo::DataPath/filename
- filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1String("/") + fileName) ;
+ filePath = QDir::cleanPath(QLibraryInfo::location(QLibraryInfo::DataPath) + QLatin1Char('/') + fileName) ;
//check QLibraryInfo::PrefixPath/tools/porting/src/filename
if (!QFile::exists(filePath))
diff --git a/src/tools/uic3/subclassing.cpp b/src/tools/uic3/subclassing.cpp
index e590ab7..85c2218 100644
--- a/src/tools/uic3/subclassing.cpp
+++ b/src/tools/uic3/subclassing.cpp
@@ -69,7 +69,7 @@ void Ui3Reader::createSubDecl( const QDomElement &e, const QString& subClass )
return;
out << "class " << subClass << " : public " << nameOfClass << endl;
- out << "{" << endl;
+ out << '{' << endl;
/* tmake ignore Q_OBJECT */
out << " Q_OBJECT" << endl;
@@ -105,8 +105,8 @@ void Ui3Reader::createSubDecl( const QDomElement &e, const QString& subClass )
continue;
QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
QString functionName = n.firstChild().toText().data().trimmed();
- if ( functionName.endsWith(QLatin1String(";")))
- functionName = functionName.left( functionName.length() - 1 );
+ if ( functionName.endsWith(QLatin1Char(';')))
+ functionName.chop(1);
QString specifier = n.attribute(QLatin1String("specifier"));
QString access = n.attribute(QLatin1String("access"));
if ( access == QLatin1String("protected") ) {
@@ -133,8 +133,8 @@ void Ui3Reader::createSubDecl( const QDomElement &e, const QString& subClass )
continue;
QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
QString functionName = n.firstChild().toText().data().trimmed();
- if ( functionName.endsWith(QLatin1String(";")) )
- functionName = functionName.left( functionName.length() - 1 );
+ if ( functionName.endsWith(QLatin1Char(';')) )
+ functionName.chop(1);
QString specifier = n.attribute(QLatin1String("specifier"));
QString access = n.attribute(QLatin1String("access"));
if ( access == QLatin1String("protected") ) {
@@ -195,7 +195,7 @@ void Ui3Reader::writeFunctionsSubDecl( const QStringList &fuLst, const QStringLi
type = QLatin1String("void");
if ( *it3 == QLatin1String("non virtual") )
continue;
- out << " " << type << " " << fixDeclaration(*it) << ";" << endl;
+ out << " " << type << ' ' << fixDeclaration(*it) << ';' << endl;
}
out << endl;
}
@@ -223,7 +223,7 @@ void Ui3Reader::createSubImpl( const QDomElement &e, const QString& subClass )
out << " * name 'name' and widget flags set to 'f' " << endl;
out << " *" << endl;
out << " * The " << objClass.mid(1).toLower() << " will by default be modeless, unless you set 'modal' to" << endl;
- out << " * true to construct a modal " << objClass.mid(1).toLower() << "." << endl;
+ out << " * true to construct a modal " << objClass.mid(1).toLower() << '.' << endl;
out << " */" << endl;
out << subClass << "::" << subClass << "( QWidget* parent, const char* name, bool modal, Qt::WindowFlags fl )" << endl;
out << " : " << nameOfClass << "( parent, name, modal, fl )" << endl;
@@ -235,8 +235,8 @@ void Ui3Reader::createSubImpl( const QDomElement &e, const QString& subClass )
out << subClass << "::" << subClass << "( QWidget* parent, const char* name, Qt::WindowFlags fl )" << endl;
out << " : " << nameOfClass << "( parent, name, fl )" << endl;
}
- out << "{" << endl;
- out << "}" << endl;
+ out << '{' << endl;
+ out << '}' << endl;
out << endl;
// destructor
@@ -244,9 +244,9 @@ void Ui3Reader::createSubImpl( const QDomElement &e, const QString& subClass )
out << " * Destroys the object and frees any allocated resources" << endl;
out << " */" << endl;
out << subClass << "::~" << subClass << "()" << endl;
- out << "{" << endl;
+ out << '{' << endl;
out << " // no need to delete child widgets, Qt does it all for us" << endl;
- out << "}" << endl;
+ out << '}' << endl;
out << endl;
@@ -268,8 +268,8 @@ void Ui3Reader::createSubImpl( const QDomElement &e, const QString& subClass )
continue;
QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
QString functionName = n.firstChild().toText().data().trimmed();
- if ( functionName.endsWith(QLatin1String(";")) )
- functionName = functionName.left( functionName.length() - 1 );
+ if ( functionName.endsWith(QLatin1Char(';')) )
+ functionName.chop(1);
QString specifier = n.attribute(QLatin1String("specifier"));
QString access = n.attribute(QLatin1String("access"));
if ( access == QLatin1String("protected") ) {
@@ -296,8 +296,8 @@ void Ui3Reader::createSubImpl( const QDomElement &e, const QString& subClass )
continue;
QString returnType = n.attribute(QLatin1String("returnType"), QLatin1String("void"));
QString functionName = n.firstChild().toText().data().trimmed();
- if ( functionName.endsWith(QLatin1String(";")) )
- functionName = functionName.left( functionName.length() - 1 );
+ if ( functionName.endsWith(QLatin1Char(';')) )
+ functionName.chop(1);
QString specifier = n.attribute(QLatin1String("specifier"));
QString access = n.attribute(QLatin1String("access"));
if ( access == QLatin1String("protected") ) {
@@ -351,10 +351,10 @@ void Ui3Reader::writeFunctionsSubImpl( const QStringList &fuLst, const QStringLi
out << "/*" << endl;
out << " * " << descr << endl;
out << " */" << endl;
- out << type << " " << subClass << "::" << fixDeclaration(*it) << endl;
- out << "{" << endl;
+ out << type << ' ' << subClass << "::" << fixDeclaration(*it) << endl;
+ out << '{' << endl;
out << " qWarning( \"" << subClass << "::" << fixDeclaration(*it) << " not yet implemented!\" );" << endl;
- out << "}" << endl << endl;
+ out << '}' << endl << endl;
}
out << endl;
}
diff --git a/src/tools/uic3/ui3reader.cpp b/src/tools/uic3/ui3reader.cpp
index 1ba4b2f..539565c 100644
--- a/src/tools/uic3/ui3reader.cpp
+++ b/src/tools/uic3/ui3reader.cpp
@@ -125,10 +125,10 @@ QString Ui3Reader::fixString(const QString &str, bool encode)
QString s;
if (!encode) {
s = str;
- s.replace(QLatin1String("\\"), QLatin1String("\\\\"));
- s.replace(QLatin1String("\""), QLatin1String("\\\""));
- s.replace(QLatin1String("\r"), QLatin1String(""));
- s.replace(QLatin1String("\n"), QLatin1String("\\n\"\n\""));
+ s.replace(QLatin1Char('\\'), QLatin1String("\\\\"));
+ s.replace(QLatin1Char('\"'), QLatin1String("\\\""));
+ s.remove(QLatin1Char('\r'));
+ s.replace(QLatin1Char('\n'), QLatin1String("\\n\"\n\""));
} else {
QByteArray utf8 = str.utf8();
const int l = utf8.length();
@@ -136,7 +136,7 @@ QString Ui3Reader::fixString(const QString &str, bool encode)
s += QLatin1String("\\x") + QString::number((uchar)utf8[i], 16);
}
- return QLatin1String("\"") + s + QLatin1String("\"");
+ return QLatin1Char('\"') + s + QLatin1Char('\"');
}
QString Ui3Reader::trcall(const QString& sourceText, const QString& comment)
@@ -158,12 +158,12 @@ QString Ui3Reader::trcall(const QString& sourceText, const QString& comment)
}
if (comment.isEmpty()) {
- return t + QLatin1String("(") + fixString(sourceText, encode) + QLatin1String(")");
+ return t + QLatin1Char('(') + fixString(sourceText, encode) + QLatin1Char(')');
} else {
- return t + QLatin1String("(")
+ return t + QLatin1Char('(')
+ fixString(sourceText, encode)
+ QLatin1String(", ")
- + fixString(comment, encode) + QLatin1String(")");
+ + fixString(comment, encode) + QLatin1Char(')');
}
}
@@ -480,10 +480,10 @@ void Ui3Reader::createColorGroupImpl(const QString& name, const QDomElement& e)
QString pixmap = n.firstChild().toText().data();
if (!pixmapLoaderFunction.isEmpty()) {
pixmap.prepend(pixmapLoaderFunction
- + QLatin1String("(")
+ + QLatin1Char('(')
+ QLatin1String(externPixmaps ? "\"" : ""));
- pixmap.append(QLatin1String(externPixmaps ? "\"" : "") + QLatin1String(")"));
+ pixmap.append(QLatin1String(externPixmaps ? "\"" : "") + QLatin1Char(')'));
}
out << indent << name << ".setBrush(QColorGroup::"
<< ColorRole[r] << ", QBrush(" << color << ", " << pixmap << "));" << endl;
@@ -578,9 +578,9 @@ QString Ui3Reader::registerObject(const QString& name)
if (objectNames.contains(result)) {
int i = 2;
- while (objectNames.contains(result + QLatin1String("_") + QString::number(i)))
+ while (objectNames.contains(result + QLatin1Char('_') + QString::number(i)))
i++;
- result += QLatin1String("_");
+ result += QLatin1Char('_');
result += QString::number(i);
}
objectNames += result;
diff --git a/src/winmain/qtmain_win.cpp b/src/winmain/qtmain_win.cpp
index a3bc0e0..e5b3259 100644
--- a/src/winmain/qtmain_win.cpp
+++ b/src/winmain/qtmain_win.cpp
@@ -100,7 +100,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR /*cmdPara
#if defined(Q_OS_WINCE)
TCHAR appName[256];
GetModuleFileName(0, appName, 255);
- cmdParam = QString(QLatin1String("\"%1\" ")).arg(QString::fromUtf16((const unsigned short *)appName)).toLocal8Bit() + cmdParam;
+ cmdParam.prepend(QString::fromLatin1("\"%1\" ").arg(QString::fromUtf16((const unsigned short *)appName)).toLocal8Bit());
#endif
int argc = 0;
@@ -110,7 +110,7 @@ int APIENTRY WinMain(HINSTANCE instance, HINSTANCE prevInstance, LPSTR /*cmdPara
#if defined(Q_OS_WINCE)
TCHAR uniqueAppID[256];
GetModuleFileName(0, uniqueAppID, 255);
- QString uid = QString::fromUtf16((const unsigned short *)uniqueAppID).toLower().replace(QString(QLatin1String("\\")), QString(QLatin1String("_")));
+ QString uid = QString::fromUtf16((const unsigned short *)uniqueAppID).toLower().replace(QLatin1Char('\\'), QLatin1Char('_'));
// If there exists an other instance of this application
// it will be the owner of a mutex with the unique ID.
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
index 5e2c74b..0e23f05 100644
--- a/src/xml/dom/qdom.cpp
+++ b/src/xml/dom/qdom.cpp
@@ -2694,7 +2694,7 @@ void QDomNode::save(QTextStream& str, int indent) const
If the document contains invalid XML characters or characters that cannot be
encoded in the given encoding, the result and behavior is undefined.
- \since 4.2
+ \since 4.2
*/
void QDomNode::save(QTextStream& str, int indent, EncodingPolicy encodingPolicy) const
{
@@ -4594,7 +4594,7 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
qName = prefix + QLatin1Char(':') + name;
nsDecl = QLatin1String(" xmlns:") + prefix;
}
- nsDecl += QLatin1String("=\"") + encodeText(namespaceURI, s) + QLatin1String("\"");
+ nsDecl += QLatin1String("=\"") + encodeText(namespaceURI, s) + QLatin1Char('\"');
}
s << '<' << qName << nsDecl;
@@ -4602,9 +4602,9 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
/* Write out attributes. */
if (!m_attr->map.isEmpty()) {
- s << ' ';
QHash<QString, QDomNodePrivate *>::const_iterator it = m_attr->map.constBegin();
for (; it != m_attr->map.constEnd(); ++it) {
+ s << ' ';
if (it.value()->namespaceURI.isNull()) {
s << it.value()->name << "=\"" << encodeText(it.value()->value, s, true, true) << '\"';
} else {
@@ -4627,7 +4627,6 @@ void QDomElementPrivate::save(QTextStream& s, int depth, int indent) const
outputtedPrefixes.insert(it.value()->prefix);
}
}
- s << ' ';
}
}
diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
index 1655642..8ad9f77 100644
--- a/src/xml/sax/qxml.cpp
+++ b/src/xml/sax/qxml.cpp
@@ -5469,7 +5469,7 @@ bool QXmlSimpleReaderPrivate::parsePEReference()
if (skipIt) {
if (contentHnd) {
- if (!contentHnd->skippedEntity(QString::fromLatin1("%") + ref())) {
+ if (!contentHnd->skippedEntity(QLatin1Char('%') + ref())) {
reportParseError(contentHnd->errorString());
return false;
}
@@ -5481,7 +5481,7 @@ bool QXmlSimpleReaderPrivate::parsePEReference()
return false;
} else if (parsePEReference_context == InDTD) {
// Included as PE
- if (!insertXmlRef(QString::fromLatin1(" ")+xmlRefString+QString::fromLatin1(" "), ref(), false))
+ if (!insertXmlRef(QLatin1Char(' ') + xmlRefString + QLatin1Char(' '), ref(), false))
return false;
}
}
@@ -6733,7 +6733,7 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
if ( !entityExist(name())) {
parameterEntities.insert(name(), string());
if (declHnd) {
- if (!declHnd->internalEntityDecl(QString::fromLatin1("%")+name(), string())) {
+ if (!declHnd->internalEntityDecl(QLatin1Char('%') + name(), string())) {
reportParseError(declHnd->errorString());
return false;
}
@@ -6745,7 +6745,7 @@ bool QXmlSimpleReaderPrivate::parseEntityDecl()
if ( !entityExist(name())) {
externParameterEntities.insert(name(), QXmlSimpleReaderPrivate::ExternParameterEntity(publicId, systemId));
if (declHnd) {
- if (!declHnd->externalEntityDecl(QString::fromLatin1("%")+name(), publicId, systemId)) {
+ if (!declHnd->externalEntityDecl(QLatin1Char('%') + name(), publicId, systemId)) {
reportParseError(declHnd->errorString());
return false;
}
@@ -7869,8 +7869,8 @@ bool QXmlSimpleReaderPrivate::insertXmlRef(const QString &data, const QString &n
{
if (inLiteral) {
QString tmp = data;
- xmlRefStack.push(XmlRef(name, tmp.replace(QLatin1String("\""),
- QLatin1String("&quot;")).replace(QLatin1String("'"), QLatin1String("&apos;"))));
+ xmlRefStack.push(XmlRef(name, tmp.replace(QLatin1Char('\"'),
+ QLatin1String("&quot;")).replace(QLatin1Char('\''), QLatin1String("&apos;"))));
} else {
xmlRefStack.push(XmlRef(name, data));
}
diff --git a/src/xmlpatterns/acceltree/qacceltree.cpp b/src/xmlpatterns/acceltree/qacceltree.cpp
index 60e6e27..6bc1794 100644
--- a/src/xmlpatterns/acceltree/qacceltree.cpp
+++ b/src/xmlpatterns/acceltree/qacceltree.cpp
@@ -71,7 +71,7 @@ void AccelTree::printStats(const NamePool::Ptr &np) const
for(int i = 0; i < len; ++i)
{
const BasicNodeData &v = basicData.at(i);
- pDebug() << "|" << i
+ pDebug() << '|' << i
<< "\t\t|" << v.depth()
<< "\t|" << v.size()
<< "\t|" << postNumber(i)
@@ -81,12 +81,12 @@ void AccelTree::printStats(const NamePool::Ptr &np) const
: data.value(i))
<< "\t|";
/*
- pDebug() << "|" << QString().arg(i, 14)
- << "|" << QString().arg(v.depth(), 6)
- << "|" << QString().arg(v.size(), 6)
- << "|" << QString().arg(postNumber(i), 14)
- << "|" << QString().arg(v.kind(), 6)
- << "|";
+ pDebug() << '|' << QString().arg(i, 14)
+ << '|' << QString().arg(v.depth(), 6)
+ << '|' << QString().arg(v.size(), 6)
+ << '|' << QString().arg(postNumber(i), 14)
+ << '|' << QString().arg(v.kind(), 6)
+ << '|';
*/
}
pDebug() << "+---------------+-------+-------+---------------+-------+--------------+";
diff --git a/src/xmlpatterns/api/qsourcelocation.cpp b/src/xmlpatterns/api/qsourcelocation.cpp
index 4eee39c..1dd8ffd 100644
--- a/src/xmlpatterns/api/qsourcelocation.cpp
+++ b/src/xmlpatterns/api/qsourcelocation.cpp
@@ -206,7 +206,7 @@ QDebug operator<<(QDebug debug, const QSourceLocation &sourceLocation)
<< sourceLocation.line()
<< ", column:"
<< sourceLocation.column()
- << ")";
+ << ')';
return debug;
}
#endif
diff --git a/src/xmlpatterns/data/qabstractfloat.cpp b/src/xmlpatterns/data/qabstractfloat.cpp
index b6226b5..a45b0fd 100644
--- a/src/xmlpatterns/data/qabstractfloat.cpp
+++ b/src/xmlpatterns/data/qabstractfloat.cpp
@@ -186,7 +186,7 @@ QString AbstractFloat<isDouble>::stringValue() const
if(sign)
valueAsString += QLatin1Char('-');
- valueAsString += qret.left(1);
+ valueAsString += qret.at(0);
valueAsString += QLatin1Char('.');
if(1 == qret.size())
diff --git a/src/xmlpatterns/data/qcommonvalues.cpp b/src/xmlpatterns/data/qcommonvalues.cpp
index 07a273d..99a8086 100644
--- a/src/xmlpatterns/data/qcommonvalues.cpp
+++ b/src/xmlpatterns/data/qcommonvalues.cpp
@@ -57,7 +57,7 @@ using namespace QPatternist;
// STATIC DATA
const AtomicString::Ptr CommonValues::EmptyString
- (new AtomicString(QString(QLatin1String(""))));
+ (new AtomicString(QLatin1String("")));
const AtomicString::Ptr CommonValues::TrueString
(new AtomicString(QLatin1String("true")));
const AtomicString::Ptr CommonValues::FalseString
diff --git a/src/xmlpatterns/expr/qexpression_p.h b/src/xmlpatterns/expr/qexpression_p.h
index 5eb63de..65918e6 100644
--- a/src/xmlpatterns/expr/qexpression_p.h
+++ b/src/xmlpatterns/expr/qexpression_p.h
@@ -884,7 +884,7 @@ namespace QPatternist
{
pDebug() << "AST REWRITE:" << old.data() << "to" << New.data()
<< '(' << old->actualReflection() << "to" << New->actualReflection() << ", "
- << old->description() << "to" << New->description() << ")";
+ << old->description() << "to" << New->description() << ')';
/* The order of these two lines is significant.. */
context->addLocation(New.data(), context->locationFor(old->actualReflection()));