summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/phonon/CMakeLists.txt6
-rw-r--r--src/3rdparty/phonon/ds9/abstractvideorenderer.cpp4
-rw-r--r--src/3rdparty/phonon/ds9/backend.cpp14
-rw-r--r--src/3rdparty/phonon/ds9/backend.h4
-rw-r--r--src/3rdparty/phonon/ds9/backendnode.cpp19
-rw-r--r--src/3rdparty/phonon/ds9/ds9.desktop17
-rw-r--r--src/3rdparty/phonon/ds9/effect.cpp4
-rw-r--r--src/3rdparty/phonon/ds9/fakesource.cpp34
-rw-r--r--src/3rdparty/phonon/ds9/iodevicereader.cpp91
-rw-r--r--src/3rdparty/phonon/ds9/iodevicereader.h1
-rw-r--r--src/3rdparty/phonon/ds9/mediagraph.cpp38
-rw-r--r--src/3rdparty/phonon/ds9/mediaobject.cpp201
-rw-r--r--src/3rdparty/phonon/ds9/mediaobject.h8
-rw-r--r--src/3rdparty/phonon/ds9/qasyncreader.cpp72
-rw-r--r--src/3rdparty/phonon/ds9/qasyncreader.h6
-rw-r--r--src/3rdparty/phonon/ds9/qaudiocdreader.cpp54
-rw-r--r--src/3rdparty/phonon/ds9/qaudiocdreader.h2
-rw-r--r--src/3rdparty/phonon/ds9/qbasefilter.cpp33
-rw-r--r--src/3rdparty/phonon/ds9/qbasefilter.h4
-rw-r--r--src/3rdparty/phonon/ds9/qevr9.h143
-rw-r--r--src/3rdparty/phonon/ds9/qmeminputpin.cpp113
-rw-r--r--src/3rdparty/phonon/ds9/qmeminputpin.h9
-rw-r--r--src/3rdparty/phonon/ds9/qpin.cpp73
-rw-r--r--src/3rdparty/phonon/ds9/qpin.h7
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_default.cpp153
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_default.h55
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_evr.cpp215
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_evr.h56
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_soft.cpp15
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp113
-rw-r--r--src/3rdparty/phonon/ds9/videorenderer_vmr9.h1
-rw-r--r--src/3rdparty/phonon/ds9/videowidget.cpp50
-rw-r--r--src/3rdparty/phonon/ds9/volumeeffect.cpp5
-rw-r--r--src/3rdparty/phonon/ds9/volumeeffect.h2
-rw-r--r--src/3rdparty/phonon/gstreamer/CMakeLists.txt18
-rw-r--r--src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake7
-rw-r--r--src/3rdparty/phonon/gstreamer/audiodataoutput.cpp143
-rw-r--r--src/3rdparty/phonon/gstreamer/audiodataoutput.h84
-rw-r--r--src/3rdparty/phonon/gstreamer/audiooutput.cpp16
-rw-r--r--src/3rdparty/phonon/gstreamer/backend.cpp73
-rw-r--r--src/3rdparty/phonon/gstreamer/backend.h1
-rw-r--r--src/3rdparty/phonon/gstreamer/devicemanager.cpp70
-rw-r--r--src/3rdparty/phonon/gstreamer/devicemanager.h6
-rw-r--r--src/3rdparty/phonon/gstreamer/effectmanager.cpp2
-rw-r--r--src/3rdparty/phonon/gstreamer/glrenderer.cpp2
-rw-r--r--src/3rdparty/phonon/gstreamer/gsthelper.cpp2
-rw-r--r--src/3rdparty/phonon/gstreamer/gstreamer.desktop57
-rw-r--r--src/3rdparty/phonon/gstreamer/medianode.cpp4
-rw-r--r--src/3rdparty/phonon/gstreamer/mediaobject.cpp296
-rw-r--r--src/3rdparty/phonon/gstreamer/mediaobject.h12
-rw-r--r--src/3rdparty/phonon/gstreamer/qwidgetvideosink.h1
-rw-r--r--src/3rdparty/phonon/gstreamer/videowidget.h1
-rw-r--r--src/3rdparty/phonon/gstreamer/x11renderer.cpp3
-rw-r--r--src/3rdparty/phonon/mmf/videoplayer_dsa.cpp8
-rw-r--r--src/3rdparty/phonon/phonon/CMakeLists.txt35
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutput.cpp66
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutput.h129
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutput_p.h48
-rw-r--r--src/3rdparty/phonon/phonon/audiodataoutputinterface.h44
-rw-r--r--src/3rdparty/phonon/phonon/audiooutput.cpp107
-rw-r--r--src/3rdparty/phonon/phonon/audiooutput.h1
-rw-r--r--src/3rdparty/phonon/phonon/audiooutput_p.h8
-rw-r--r--src/3rdparty/phonon/phonon/audiooutputinterface.h2
-rw-r--r--src/3rdparty/phonon/phonon/backendcapabilities.cpp2
-rw-r--r--src/3rdparty/phonon/phonon/factory.cpp25
-rw-r--r--src/3rdparty/phonon/phonon/factory_p.h7
-rw-r--r--src/3rdparty/phonon/phonon/globalconfig.cpp358
-rw-r--r--src/3rdparty/phonon/phonon/globalconfig.h71
-rw-r--r--src/3rdparty/phonon/phonon/globalconfig_p.h31
-rw-r--r--src/3rdparty/phonon/phonon/mediaobject.cpp12
-rw-r--r--src/3rdparty/phonon/phonon/objectdescription.cpp44
-rw-r--r--src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp2
-rw-r--r--src/3rdparty/phonon/phonon/objectdescriptionmodel.h36
-rw-r--r--src/3rdparty/phonon/phonon/path.cpp8
-rw-r--r--src/3rdparty/phonon/phonon/phonondefs.h5
-rw-r--r--src/3rdparty/phonon/phonon/pulsesupport.cpp1040
-rw-r--r--src/3rdparty/phonon/phonon/pulsesupport.h78
-rw-r--r--src/3rdparty/phonon/phonon/seekslider.cpp4
-rw-r--r--src/3rdparty/phonon/phonon/seekslider_p.h4
-rw-r--r--src/3rdparty/phonon/phonon/swiftslider.cpp103
-rw-r--r--src/3rdparty/phonon/phonon/swiftslider_p.h68
-rw-r--r--src/3rdparty/phonon/phonon/videowidget.cpp16
-rw-r--r--src/3rdparty/phonon/phonon/videowidget.h1
-rw-r--r--src/3rdparty/phonon/phonon/videowidgetinterface.h13
-rw-r--r--src/3rdparty/phonon/phonon/volumeslider_p.h4
-rw-r--r--src/3rdparty/phonon/qt7/audionode.h2
-rw-r--r--src/3rdparty/phonon/qt7/audionode.mm1
-rw-r--r--src/3rdparty/phonon/qt7/backendinfo.mm13
-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/mediaobjectaudionode.mm2
-rw-r--r--src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm2
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.h8
-rw-r--r--src/3rdparty/phonon/qt7/quicktimemetadata.mm43
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.h28
-rw-r--r--src/3rdparty/phonon/qt7/quicktimevideoplayer.mm265
-rw-r--r--src/3rdparty/phonon/qt7/videoframe.mm24
-rw-r--r--src/3rdparty/webkit/.gitattributes4
-rw-r--r--src/3rdparty/webkit/ChangeLog8
-rw-r--r--src/3rdparty/webkit/VERSION2
-rw-r--r--src/3rdparty/webkit/WebCore/ChangeLog271
-rw-r--r--src/3rdparty/webkit/WebCore/WebCore.pro13
-rw-r--r--src/3rdparty/webkit/WebCore/config.h2
-rw-r--r--src/3rdparty/webkit/WebCore/css/CSSParser.cpp8
-rw-r--r--src/3rdparty/webkit/WebCore/dom/XMLTokenizer.cpp3
-rw-r--r--src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h20
-rw-r--r--src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp59
-rw-r--r--src/3rdparty/webkit/WebCore/html/HTMLFormElement.cpp2
-rw-r--r--src/3rdparty/webkit/WebCore/html/HTMLImageElement.cpp24
-rw-r--r--src/3rdparty/webkit/WebCore/html/HTMLImageElement.h7
-rw-r--r--src/3rdparty/webkit/WebCore/html/HTMLInputElement.cpp7
-rw-r--r--src/3rdparty/webkit/WebCore/html/HTMLParser.cpp3
-rw-r--r--src/3rdparty/webkit/WebCore/loader/FrameLoader.cpp8
-rw-r--r--src/3rdparty/webkit/WebCore/page/FrameView.cpp75
-rw-r--r--src/3rdparty/webkit/WebCore/page/FrameView.h7
-rw-r--r--src/3rdparty/webkit/WebCore/platform/MIMETypeRegistry.cpp2
-rw-r--r--src/3rdparty/webkit/WebCore/platform/ScrollView.cpp7
-rw-r--r--src/3rdparty/webkit/WebCore/platform/ScrollView.h3
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp10
-rw-r--r--src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h4
-rw-r--r--src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp8
-rw-r--r--src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h7
-rw-r--r--src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp24
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBlock.h1
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp10
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp11
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp15
-rw-r--r--src/3rdparty/webkit/WebCore/rendering/RenderText.cpp11
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp9
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h3
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp36
-rw-r--r--src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp4
-rw-r--r--src/3rdparty/webkit/WebKit/qt/ChangeLog84
-rw-r--r--src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def4
-rw-r--r--src/3rdparty/webkit/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp27
-rw-r--r--src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp67
-rw-r--r--src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp20
-rw-r--r--src/corelib/corelib.pro1
-rw-r--r--src/corelib/io/qfile.cpp46
-rw-r--r--src/corelib/io/qfile_p.h2
-rw-r--r--src/corelib/io/qfsfileengine_p.h4
-rw-r--r--src/corelib/io/qfsfileengine_unix.cpp40
-rw-r--r--src/corelib/io/qiodevice.cpp163
-rw-r--r--src/corelib/io/qiodevice_p.h127
-rw-r--r--src/corelib/kernel/qeventdispatcher_symbian.cpp13
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp11
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h2
-rw-r--r--src/corelib/tools/qchar.cpp8
-rw-r--r--src/corelib/tools/qdatetime.cpp5
-rw-r--r--src/corelib/tools/qvarlengtharray.h19
-rw-r--r--src/corelib/tools/qvarlengtharray.qdoc32
-rw-r--r--src/declarative/QmlChanges.txt39
-rw-r--r--src/declarative/graphicsitems/graphicsitems.pri2
-rw-r--r--src/declarative/graphicsitems/qdeclarativeborderimage.cpp25
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp7
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable_p.h4
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflipable.cpp21
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflipable_p.h12
-rw-r--r--src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp10
-rw-r--r--src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h1
-rw-r--r--src/declarative/graphicsitems/qdeclarativegridview.cpp53
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimage.cpp25
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase.cpp40
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p.h6
-rw-r--r--src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h1
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.cpp277
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem.h9
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitem_p.h37
-rw-r--r--src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp10
-rw-r--r--src/declarative/graphicsitems/qdeclarativelistview.cpp68
-rw-r--r--src/declarative/graphicsitems/qdeclarativeloader.cpp8
-rw-r--r--src/declarative/graphicsitems/qdeclarativemousearea.cpp1
-rw-r--r--src/declarative/graphicsitems/qdeclarativepainteditem.cpp4
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview.cpp901
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview_p.h46
-rw-r--r--src/declarative/graphicsitems/qdeclarativepathview_p_p.h48
-rw-r--r--src/declarative/graphicsitems/qdeclarativepositioners.cpp7
-rw-r--r--src/declarative/graphicsitems/qdeclarativerectangle.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativerepeater.cpp10
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextedit.cpp2
-rw-r--r--src/declarative/graphicsitems/qdeclarativetextinput.cpp19
-rw-r--r--src/declarative/graphicsitems/qdeclarativetranslate.cpp136
-rw-r--r--src/declarative/graphicsitems/qdeclarativetranslate_p.h (renamed from src/declarative/qml/qdeclarativescript.cpp)94
-rw-r--r--src/declarative/qml/parser/qdeclarativejs.g11
-rw-r--r--src/declarative/qml/parser/qdeclarativejsparser.cpp11
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings.cpp88
-rw-r--r--src/declarative/qml/qdeclarativecompiler.cpp55
-rw-r--r--src/declarative/qml/qdeclarativecompiler_p.h7
-rw-r--r--src/declarative/qml/qdeclarativecontext.cpp85
-rw-r--r--src/declarative/qml/qdeclarativedom.cpp6
-rw-r--r--src/declarative/qml/qdeclarativeengine.cpp132
-rw-r--r--src/declarative/qml/qdeclarativeengine.h3
-rw-r--r--src/declarative/qml/qdeclarativeengine_p.h3
-rw-r--r--src/declarative/qml/qdeclarativefastproperties.cpp92
-rw-r--r--src/declarative/qml/qdeclarativefastproperties_p.h75
-rw-r--r--src/declarative/qml/qdeclarativeimageprovider.cpp6
-rw-r--r--src/declarative/qml/qdeclarativeimageprovider.h2
-rw-r--r--src/declarative/qml/qdeclarativelist.h7
-rw-r--r--src/declarative/qml/qdeclarativeparser_p.h2
-rw-r--r--src/declarative/qml/qdeclarativeproperty.h5
-rw-r--r--src/declarative/qml/qdeclarativescriptparser.cpp11
-rw-r--r--src/declarative/qml/qdeclarativesqldatabase.cpp4
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject.cpp461
-rw-r--r--src/declarative/qml/qdeclarativevmemetaobject_p.h17
-rw-r--r--src/declarative/qml/qdeclarativeworkerscript.cpp6
-rw-r--r--src/declarative/qml/qml.pri3
-rw-r--r--src/declarative/util/qdeclarativeanimation.cpp19
-rw-r--r--src/declarative/util/qdeclarativeanimation_p.h10
-rw-r--r--src/declarative/util/qdeclarativeanimation_p_p.h31
-rw-r--r--src/declarative/util/qdeclarativebehavior.cpp15
-rw-r--r--src/declarative/util/qdeclarativeeasefollow.cpp537
-rw-r--r--src/declarative/util/qdeclarativelistmodel.cpp19
-rw-r--r--src/declarative/util/qdeclarativelistmodel_p.h2
-rw-r--r--src/declarative/util/qdeclarativelistmodelworkeragent.cpp2
-rw-r--r--src/declarative/util/qdeclarativeopenmetaobject.cpp12
-rw-r--r--src/declarative/util/qdeclarativeopenmetaobject_p.h2
-rw-r--r--src/declarative/util/qdeclarativepixmapcache.cpp207
-rw-r--r--src/declarative/util/qdeclarativepixmapcache_p.h9
-rw-r--r--src/declarative/util/qdeclarativepropertymap.cpp31
-rw-r--r--src/declarative/util/qdeclarativepropertymap.h2
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation.cpp483
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation_p.h (renamed from src/declarative/util/qdeclarativeeasefollow_p.h)48
-rw-r--r--src/declarative/util/qdeclarativesmoothedanimation_p_p.h134
-rw-r--r--src/declarative/util/qdeclarativespringfollow.cpp2
-rw-r--r--src/declarative/util/qdeclarativestategroup.cpp26
-rw-r--r--src/declarative/util/qdeclarativestateoperations.cpp474
-rw-r--r--src/declarative/util/qdeclarativestateoperations_p.h123
-rw-r--r--src/declarative/util/qdeclarativetransition.cpp6
-rw-r--r--src/declarative/util/qdeclarativeutilmodule.cpp5
-rw-r--r--src/declarative/util/qdeclarativeview.cpp6
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel.cpp173
-rw-r--r--src/declarative/util/qdeclarativexmllistmodel_p.h3
-rw-r--r--src/declarative/util/util.pri5
-rw-r--r--src/gui/dialogs/qdialog.cpp14
-rw-r--r--src/gui/dialogs/qfiledialog.cpp6
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp10
-rw-r--r--src/gui/dialogs/qmessagebox.cpp14
-rw-r--r--src/gui/egl/qegl.cpp4
-rw-r--r--src/gui/egl/qegl_p.h35
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp169
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h11
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h69
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp13
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp23
-rw-r--r--src/gui/graphicsview/qgraphicswidget.h2
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp51
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h9
-rw-r--r--src/gui/gui.pro2
-rw-r--r--src/gui/inputmethod/inputmethod.pri2
-rw-r--r--src/gui/inputmethod/qinputcontextfactory.cpp47
-rw-r--r--src/gui/kernel/qapplication.h1
-rw-r--r--src/gui/kernel/qapplication_s60.cpp45
-rw-r--r--src/gui/kernel/qsoftkeymanager.cpp60
-rw-r--r--src/gui/kernel/qsoftkeymanager_p.h5
-rw-r--r--src/gui/kernel/qsoftkeymanager_s60.cpp7
-rw-r--r--src/gui/kernel/qsound.cpp3
-rw-r--r--src/gui/kernel/qt_s60_p.h1
-rw-r--r--src/gui/kernel/qwidget_p.h20
-rw-r--r--src/gui/kernel/qwidget_s60.cpp8
-rw-r--r--src/gui/painting/qpaintbuffer.cpp33
-rw-r--r--src/gui/painting/qpainter.cpp66
-rw-r--r--src/gui/painting/qpainter.h6
-rw-r--r--src/gui/styles/qgtkstyle.cpp3
-rw-r--r--src/gui/styles/qs60style.cpp159
-rw-r--r--src/gui/styles/qs60style.h10
-rw-r--r--src/gui/styles/qs60style_p.h15
-rw-r--r--src/gui/styles/qs60style_s60.cpp28
-rw-r--r--src/gui/text/qfontdatabase_s60.cpp5
-rw-r--r--src/gui/text/qfontengine.cpp15
-rw-r--r--src/gui/text/qfontengine_p.h3
-rw-r--r--src/gui/text/qfontengine_win.cpp31
-rw-r--r--src/gui/text/qfontengine_win_p.h4
-rw-r--r--src/gui/text/qfontmetrics.cpp21
-rw-r--r--src/gui/text/qstatictext.cpp168
-rw-r--r--src/gui/text/qstatictext.h8
-rw-r--r--src/gui/text/qstatictext_p.h13
-rw-r--r--src/gui/text/qtextlayout.cpp6
-rw-r--r--src/gui/widgets/qmenu.cpp4
-rw-r--r--src/gui/widgets/qmenubar.cpp1
-rw-r--r--src/gui/widgets/qspinbox.cpp15
-rw-r--r--src/imports/multimedia/multimedia.pro13
-rw-r--r--src/imports/particles/particles.pro13
-rw-r--r--src/imports/particles/qdeclarativeparticles.cpp5
-rw-r--r--src/imports/webkit/qdeclarativewebview.cpp4
-rw-r--r--src/imports/webkit/webkit.pro13
-rw-r--r--src/imports/widgets/widgets.pro13
-rw-r--r--src/multimedia/audio/qaudioinput_mac_p.cpp4
-rw-r--r--src/multimedia/audio/qaudiooutput_symbian_p.cpp3
-rw-r--r--src/multimedia/base/base.pri8
-rw-r--r--src/multimedia/base/qpaintervideosurface.cpp31
-rw-r--r--src/multimedia/base/qpaintervideosurface_mac.mm274
-rw-r--r--src/multimedia/base/qpaintervideosurface_mac_p.h100
-rw-r--r--src/multimedia/base/qpaintervideosurface_p.h22
-rw-r--r--src/multimedia/base/qvideowidget.cpp34
-rw-r--r--src/multimedia/effects/effects.pri3
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp41
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h20
-rw-r--r--src/network/kernel/qhostinfo.cpp1
-rw-r--r--src/network/kernel/qhostinfo_p.h3
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/openvg/qpaintengine_vg.cpp2
-rw-r--r--src/openvg/qpixmapdata_vg.cpp19
-rw-r--r--src/phonon/phonon.pro64
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp25
-rw-r--r--src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp1
-rw-r--r--src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp9
-rw-r--r--src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp2
-rw-r--r--src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm39
-rw-r--r--src/plugins/mediaservices/qt7/qt7.pro2
-rw-r--r--src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.h90
-rw-r--r--src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm104
-rw-r--r--src/plugins/mediaservices/qt7/qt7movierenderer.h1
-rw-r--r--src/plugins/mediaservices/qt7/qt7movierenderer.mm17
-rw-r--r--src/plugins/mediaservices/qt7/qt7movievideowidget.h1
-rw-r--r--src/plugins/mediaservices/qt7/qt7movievideowidget.mm7
-rw-r--r--src/plugins/mediaservices/qt7/qt7movieviewoutput.h1
-rw-r--r--src/plugins/mediaservices/qt7/qt7movieviewoutput.mm4
-rw-r--r--src/plugins/mediaservices/qt7/qt7movieviewrenderer.h2
-rw-r--r--src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm85
-rw-r--r--src/plugins/mediaservices/qt7/qt7videooutputcontrol.h1
-rw-r--r--src/plugins/phonon/ds9/ds9.pro11
-rw-r--r--src/plugins/phonon/gstreamer/gstreamer.pro22
-rw-r--r--src/s60installs/bwins/QtGuiu.def128
-rw-r--r--src/s60installs/eabi/QtGuiu.def128
-rw-r--r--src/s60installs/s60installs.pro5
-rw-r--r--src/script/api/qscriptengine.cpp15
-rw-r--r--src/script/api/qscriptvalue.cpp78
-rw-r--r--src/script/api/qscriptvalueiterator.cpp15
-rw-r--r--src/script/bridge/qscriptdeclarativeclass.cpp12
-rw-r--r--src/sql/drivers/odbc/qsql_odbc.cpp157
-rw-r--r--src/xmlpatterns/api/qxmlresultitems.cpp4
331 files changed, 10351 insertions, 4852 deletions
diff --git a/src/3rdparty/phonon/CMakeLists.txt b/src/3rdparty/phonon/CMakeLists.txt
index a25ec5d..ef7d6f5 100644
--- a/src/3rdparty/phonon/CMakeLists.txt
+++ b/src/3rdparty/phonon/CMakeLists.txt
@@ -70,6 +70,10 @@ if (CMAKE_COMPILER_IS_GNUCXX)
add_definitions(-DQT_NO_DEBUG)
endif (MINGW)
+ if (QT_USE_FRAMEWORKS)
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F${QT_LIBRARY_DIR}")
+ endif (QT_USE_FRAMEWORKS)
+
check_cxx_compiler_flag(-fPIE HAVE_FPIE_SUPPORT)
if(KDE4_ENABLE_FPIE)
if(HAVE_FPIE_SUPPORT)
@@ -149,7 +153,7 @@ set(CMAKE_COLOR_MAKEFILE ON)
set(PHONON_LIB_MAJOR_VERSION "4")
set(PHONON_LIB_MINOR_VERSION "3")
-set(PHONON_LIB_PATCH_VERSION "50")
+set(PHONON_LIB_PATCH_VERSION "80")
set(PHONON_LIB_VERSION "${PHONON_LIB_MAJOR_VERSION}.4.0")
set(PHONON_LIB_SOVERSION ${PHONON_LIB_MAJOR_VERSION})
diff --git a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp
index a9d0694..e932e70 100644
--- a/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp
+++ b/src/3rdparty/phonon/ds9/abstractvideorenderer.cpp
@@ -99,8 +99,8 @@ namespace Phonon
m_dstX = m_dstY = 0;
if (ratio > 0) {
- if ((realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView)
- || (realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop)) {
+ if (realWidth / realHeight > ratio && scaleMode == Phonon::VideoWidget::FitInView
+ || realWidth / realHeight < ratio && scaleMode == Phonon::VideoWidget::ScaleAndCrop) {
//the height is correct, let's change the width
m_dstWidth = qRound(realHeight * ratio);
m_dstX = qRound((realWidth - realHeight * ratio) / 2.);
diff --git a/src/3rdparty/phonon/ds9/backend.cpp b/src/3rdparty/phonon/ds9/backend.cpp
index fbc4bdc..2c56af7 100644
--- a/src/3rdparty/phonon/ds9/backend.cpp
+++ b/src/3rdparty/phonon/ds9/backend.cpp
@@ -41,8 +41,6 @@ namespace Phonon
{
namespace DS9
{
- QMutex *Backend::directShowMutex = 0;
-
bool Backend::AudioMoniker::operator==(const AudioMoniker &other)
{
return other->IsEqual(*this) == S_OK;
@@ -52,8 +50,6 @@ namespace Phonon
Backend::Backend(QObject *parent, const QVariantList &)
: QObject(parent)
{
- directShowMutex = &m_directShowMutex;
-
::CoInitialize(0);
//registering meta types
@@ -66,8 +62,6 @@ namespace Phonon
m_audioOutputs.clear();
m_audioEffects.clear();
::CoUninitialize();
-
- directShowMutex = 0;
}
QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const QList<QVariant> &args)
@@ -137,7 +131,6 @@ namespace Phonon
QList<int> Backend::objectDescriptionIndexes(Phonon::ObjectDescriptionType type) const
{
- QMutexLocker locker(&m_directShowMutex);
QList<int> ret;
switch(type)
@@ -164,7 +157,7 @@ namespace Phonon
while (S_OK == enumMon->Next(1, mon.pparam(), 0)) {
LPOLESTR str = 0;
mon->GetDisplayName(0,0,&str);
- const QString name = QString::fromWCharArray(str);
+ const QString name = QString::fromUtf16((unsigned short*)str);
ComPointer<IMalloc> alloc;
::CoGetMalloc(1, alloc.pparam());
alloc->Free(str);
@@ -211,7 +204,6 @@ namespace Phonon
QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(Phonon::ObjectDescriptionType type, int index) const
{
- QMutexLocker locker(&m_directShowMutex);
QHash<QByteArray, QVariant> ret;
switch (type)
{
@@ -224,7 +216,7 @@ namespace Phonon
LPOLESTR str = 0;
HRESULT hr = mon->GetDisplayName(0,0, &str);
if (SUCCEEDED(hr)) {
- QString name = QString::fromWCharArray(str);
+ QString name = QString::fromUtf16((unsigned short*)str);
ComPointer<IMalloc> alloc;
::CoGetMalloc(1, alloc.pparam());
alloc->Free(str);
@@ -239,7 +231,7 @@ namespace Phonon
WCHAR name[80]; // 80 is clearly stated in the MSDN doc
HRESULT hr = ::DMOGetName(m_audioEffects[index], name);
if (SUCCEEDED(hr)) {
- ret["name"] = QString::fromWCharArray(name);
+ ret["name"] = QString::fromUtf16((unsigned short*)name);
}
}
break;
diff --git a/src/3rdparty/phonon/ds9/backend.h b/src/3rdparty/phonon/ds9/backend.h
index 7c3c109..ad638f2 100644
--- a/src/3rdparty/phonon/ds9/backend.h
+++ b/src/3rdparty/phonon/ds9/backend.h
@@ -23,7 +23,6 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <phonon/phononnamespace.h>
#include <QtCore/QList>
-#include <QtCore/QMutex>
#include "compointer.h"
#include "backendnode.h"
@@ -64,8 +63,6 @@ namespace Phonon
Filter getAudioOutputFilter(int index) const;
- static QMutex *directShowMutex;
-
Q_SIGNALS:
void objectDescriptionChanged(ObjectDescriptionType);
@@ -77,7 +74,6 @@ namespace Phonon
};
mutable QVector<AudioMoniker> m_audioOutputs;
mutable QVector<CLSID> m_audioEffects;
- mutable QMutex m_directShowMutex;
};
}
}
diff --git a/src/3rdparty/phonon/ds9/backendnode.cpp b/src/3rdparty/phonon/ds9/backendnode.cpp
index 737ab7b..7e0b3cd 100644
--- a/src/3rdparty/phonon/ds9/backendnode.cpp
+++ b/src/3rdparty/phonon/ds9/backendnode.cpp
@@ -57,25 +57,6 @@ namespace Phonon
BackendNode::~BackendNode()
{
- //this will remove the filter from the graph
- FILTER_INFO info;
- for(int i = 0; i < FILTER_COUNT; ++i) {
- const Filter &filter = m_filters[i];
- if (!filter)
- continue;
- filter->QueryFilterInfo(&info);
- if (info.pGraph) {
- HRESULT hr = info.pGraph->RemoveFilter(filter);
-
- if (FAILED(hr) && m_mediaObject) {
- m_mediaObject->ensureStopped();
-
- hr = info.pGraph->RemoveFilter(filter);
- }
- Q_ASSERT(SUCCEEDED(hr));
- info.pGraph->Release();
- }
- }
}
void BackendNode::setMediaObject(MediaObject *mo)
diff --git a/src/3rdparty/phonon/ds9/ds9.desktop b/src/3rdparty/phonon/ds9/ds9.desktop
index 764390e..1bc3451 100644
--- a/src/3rdparty/phonon/ds9/ds9.desktop
+++ b/src/3rdparty/phonon/ds9/ds9.desktop
@@ -5,12 +5,13 @@ MimeType=application/x-annodex;video/quicktime;video/x-quicktime;audio/x-m4a;app
X-KDE-Library=phonon_ds9
X-KDE-PhononBackendInfo-InterfaceVersion=1
X-KDE-PhononBackendInfo-Version=0.1
-X-KDE-PhononBackendInfo-Website=http://qt.nokia.com/
+X-KDE-PhononBackendInfo-Website=http://www.trolltech.com/
InitialPreference=15
Name=DirectShow9
Name[bg]=DirectShow9
Name[ca]=DirectShow9
+Name[ca@valencia]=DirectShow9
Name[cs]=DirectShow9
Name[da]=DirectShow9
Name[de]=DirectShow9
@@ -19,11 +20,14 @@ Name[en_GB]=DirectShow9
Name[es]=DirectShow9
Name[et]=DirectShow9
Name[eu]=DirectShow9
+Name[fi]=DirectShow9
Name[fr]=DirectShow9
Name[ga]=DirectShow9
Name[gl]=DirectShow9
+Name[hr]=DirectShow9
Name[hsb]=DirectShow9
Name[hu]=DirectShow9
+Name[id]=DirectShow9
Name[is]=DirectShow9
Name[it]=DirectShow9
Name[ja]=DirectShow9
@@ -31,6 +35,7 @@ Name[ko]=DirectShow9
Name[ku]=DirectShow9
Name[lt]=DirectShow9
Name[lv]=DirectShow9
+Name[nb]=DirectShow9
Name[nds]=DirectShow9
Name[nl]=DirectShow9
Name[nn]=DirectShow9
@@ -38,10 +43,13 @@ Name[pa]=ਡਾਇਰੈਕਸ਼ੋ9
Name[pl]=DirectShow9
Name[pt]=DirectShow9
Name[pt_BR]=DirectShow9
+Name[ru]=DirectShow9
Name[se]=DirectShow9
Name[sk]=DirectShow 9
Name[sl]=DirectShow 9
Name[sr]=Директшоу‑9
+Name[sr@ijekavian]=Директшоу‑9
+Name[sr@ijekavianlatin]=DirectShow‑9
Name[sr@latin]=DirectShow‑9
Name[sv]=Directshow 9
Name[tr]=DirectShow9
@@ -53,6 +61,7 @@ Name[zh_TW]=DirectShow9
Comment=Phonon DirectShow9 backend
Comment[bg]=Phonon DirectShow9
Comment[ca]=Dorsal DirectShow9 del Phonon
+Comment[ca@valencia]=Dorsal DirectShow9 del Phonon
Comment[cs]=Phonon DirectShow9 backend
Comment[da]=DirectShow9-backend til Phonon
Comment[de]=Phonon-Treiber für DirectShow9
@@ -61,11 +70,13 @@ Comment[en_GB]=Phonon DirectShow9 backend
Comment[es]=Motor DirectShow9 para Phonon
Comment[et]=Phononi DirectShow9 taustaprogramm
Comment[eu]=Phonon DirectShow9 backend
+Comment[fi]=Phonon DirectShow9-taustaohjelma
Comment[fr]=Système de gestion DirectShow9 pour Phonon
Comment[ga]=Inneall DirectShow9 le haghaidh Phonon
Comment[gl]=Infraestrutura de DirectShow9 para Phonon
Comment[hsb]=Phonon DirectShow9 backend
Comment[hu]=Phonon DirectShow9 modul
+Comment[id]=Phonon DirectShow9 backend
Comment[is]=Phonon DirectShow9 bakendi
Comment[it]=Motore DirectShow9 di Phonon
Comment[ja]=Phonon DirectShow9 バックエンド
@@ -73,6 +84,7 @@ Comment[ko]=Phonon DirectShow9 백엔드
Comment[ku]=Binesaza Phonon DirectShow9
Comment[lt]=Phonon DirectShow9 galinė sąsaja
Comment[lv]=Phonon DirectShow9 aizmugure
+Comment[nb]=Phonon-motor for DirectShow9
Comment[nds]=Phonon-Hülpprogrmm DirectShow9
Comment[nl]=DirectShow9-backend (Phonon)
Comment[nn]=Phonon-motor for DirectShow9
@@ -80,10 +92,13 @@ Comment[pa]=ਫੋਨੋਨ ਡਾਇਰੈਕਟਸ਼ੋ9 ਬੈਕਐਂਡ
Comment[pl]=Obsługa DirectShow9 przez Phonon
Comment[pt]=Infra-estrutura do DirectShow9 para o Phonon
Comment[pt_BR]=Infraestrutura Phonon DirectShow9
+Comment[ru]=Механизм DirectShow9 для Phonon
Comment[se]=Phonon DirectShow9 duogášmohtor
Comment[sk]=Phonon DirectShow 9 podsystém
Comment[sl]=Phononova Hrbtenica DirectShow 9
Comment[sr]=Директшоу‑9 као позадина Фонона
+Comment[sr@ijekavian]=Директшоу‑9 као позадина Фонона
+Comment[sr@ijekavianlatin]=DirectShow‑9 kao pozadina Phonona
Comment[sr@latin]=DirectShow‑9 kao pozadina Phonona
Comment[sv]=Phonon Directshow 9-gränssnitt
Comment[tr]=Phonon DirectShow9 arka ucu
diff --git a/src/3rdparty/phonon/ds9/effect.cpp b/src/3rdparty/phonon/ds9/effect.cpp
index ebe976b..104a3c1 100644
--- a/src/3rdparty/phonon/ds9/effect.cpp
+++ b/src/3rdparty/phonon/ds9/effect.cpp
@@ -82,7 +82,7 @@ namespace Phonon
current += wcslen(current) + 1; //skip the name
current += wcslen(current) + 1; //skip the unit
for(; *current; current += wcslen(current) + 1) {
- values.append( QString::fromWCharArray(current) );
+ values.append( QString::fromUtf16((unsigned short*)current) );
}
}
//FALLTHROUGH
@@ -107,7 +107,7 @@ namespace Phonon
Phonon::EffectParameter::Hints hint = info.mopCaps == MP_CAPS_CURVE_INVSQUARE ?
Phonon::EffectParameter::LogarithmicHint : Phonon::EffectParameter::Hints(0);
- const QString n = QString::fromWCharArray(name);
+ const QString n = QString::fromUtf16((unsigned short*)name);
ret.append(Phonon::EffectParameter(i, n, hint, def, min, max, values));
::CoTaskMemFree(name); //let's free the memory
}
diff --git a/src/3rdparty/phonon/ds9/fakesource.cpp b/src/3rdparty/phonon/ds9/fakesource.cpp
index 4dce138..9a61a2e 100644
--- a/src/3rdparty/phonon/ds9/fakesource.cpp
+++ b/src/3rdparty/phonon/ds9/fakesource.cpp
@@ -29,10 +29,8 @@ namespace Phonon
namespace DS9
{
static WAVEFORMATEX g_defaultWaveFormat = {WAVE_FORMAT_PCM, 2, 44100, 176400, 4, 16, 0};
- static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, {0}, 0, {sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0} };
-
- static const AM_MEDIA_TYPE g_fakeAudioType = {MEDIATYPE_Audio, MEDIASUBTYPE_PCM, 0, 0, 2, FORMAT_WaveFormatEx, 0, sizeof(WAVEFORMATEX), reinterpret_cast<BYTE*>(&g_defaultWaveFormat)};
- static const AM_MEDIA_TYPE g_fakeVideoType = {MEDIATYPE_Video, MEDIASUBTYPE_RGB32, TRUE, FALSE, 0, FORMAT_VideoInfo2, 0, sizeof(VIDEOINFOHEADER2), reinterpret_cast<BYTE*>(&g_defaultVideoInfo)};
+ static BITMAPINFOHEADER g_defautBitmapHeader = { sizeof(BITMAPINFOHEADER), 1, 1, 1, 0, 0, 0, 0, 0, 0, 0};
+ static VIDEOINFOHEADER2 g_defaultVideoInfo = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
class FakePin : public QPin
{
@@ -130,12 +128,36 @@ namespace Phonon
void FakeSource::createFakeAudioPin()
{
- new FakePin(this, g_fakeAudioType);
+ AM_MEDIA_TYPE mt;
+ qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE));
+ mt.majortype = MEDIATYPE_Audio;
+ mt.subtype = MEDIASUBTYPE_PCM;
+ mt.formattype = FORMAT_WaveFormatEx;
+ mt.lSampleSize = 2;
+
+ //fake the format (stereo 44.1 khz stereo 16 bits)
+ mt.cbFormat = sizeof(WAVEFORMATEX);
+ mt.pbFormat = reinterpret_cast<BYTE*>(&g_defaultWaveFormat);
+
+ new FakePin(this, mt);
}
void FakeSource::createFakeVideoPin()
{
- new FakePin(this, g_fakeVideoType);
+ AM_MEDIA_TYPE mt;
+ qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE));
+ mt.majortype = MEDIATYPE_Video;
+ mt.subtype = MEDIASUBTYPE_RGB32;
+ mt.formattype = FORMAT_VideoInfo2;
+ mt.bFixedSizeSamples = 1;
+
+ g_defaultVideoInfo.bmiHeader = g_defautBitmapHeader;
+
+ //fake the format
+ mt.cbFormat = sizeof(VIDEOINFOHEADER2);
+ mt.pbFormat = reinterpret_cast<BYTE*>(&g_defaultVideoInfo);
+
+ new FakePin(this, mt);
}
}
diff --git a/src/3rdparty/phonon/ds9/iodevicereader.cpp b/src/3rdparty/phonon/ds9/iodevicereader.cpp
index d706c82..9152712 100644
--- a/src/3rdparty/phonon/ds9/iodevicereader.cpp
+++ b/src/3rdparty/phonon/ds9/iodevicereader.cpp
@@ -36,20 +36,18 @@ namespace Phonon
//these mediatypes define a stream, its type will be autodetected by DirectShow
static QVector<AM_MEDIA_TYPE> getMediaTypes()
{
- //the order here is important because otherwise,
- //directshow might not be able to detect the stream type correctly
-
- AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_Avi, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
+ AM_MEDIA_TYPE mt = { MEDIATYPE_Stream, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
QVector<AM_MEDIA_TYPE> ret;
+ //normal auto-detect stream
+ mt.subtype = MEDIASUBTYPE_NULL;
+ ret << mt;
//AVI stream
+ mt.subtype = MEDIASUBTYPE_Avi;
ret << mt;
//WAVE stream
mt.subtype = MEDIASUBTYPE_WAVE;
ret << mt;
- //normal auto-detect stream (must be at the end!)
- mt.subtype = MEDIASUBTYPE_NULL;
- ret << mt;
return ret;
}
@@ -66,6 +64,7 @@ namespace Phonon
//for Phonon::StreamInterface
void writeData(const QByteArray &data)
{
+ QWriteLocker locker(&m_lock);
m_pos += data.size();
m_buffer += data;
}
@@ -76,22 +75,54 @@ namespace Phonon
void setStreamSize(qint64 newSize)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_size = newSize;
}
+ qint64 streamSize() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_size;
+ }
+
void setStreamSeekable(bool s)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_seekable = s;
}
+ bool streamSeekable() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_seekable;
+ }
+
+ void setCurrentPos(qint64 pos)
+ {
+ QWriteLocker locker(&m_lock);
+ m_pos = pos;
+ seekStream(pos);
+ m_buffer.clear();
+ }
+
+ qint64 currentPos() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_pos;
+ }
+
+ int currentBufferSize() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_buffer.size();
+ }
+
//virtual pure members
//implementation from IAsyncReader
STDMETHODIMP Length(LONGLONG *total, LONGLONG *available)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (total) {
*total = m_size;
}
@@ -106,36 +137,37 @@ namespace Phonon
HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual)
{
- Q_ASSERT(!m_mutex.tryLock());
+ QMutexLocker locker(&m_mutexRead);
- if(m_size != 1 && pos + length > m_size) {
+ if(streamSize() != 1 && pos + length > streamSize()) {
//it tries to read outside of the boundaries
return E_FAIL;
}
- if (m_pos - m_buffer.size() != pos) {
- if (!m_seekable) {
+ if (currentPos() - currentBufferSize() != pos) {
+ if (!streamSeekable()) {
return S_FALSE;
}
- m_pos = pos;
- seekStream(pos);
- m_buffer.clear();
+ setCurrentPos(pos);
}
- int oldSize = m_buffer.size();
- while (m_buffer.size() < int(length)) {
+ int oldSize = currentBufferSize();
+ while (currentBufferSize() < int(length)) {
needData();
- if (oldSize == m_buffer.size()) {
+ if (oldSize == currentBufferSize()) {
break; //we didn't get any data
}
- oldSize = m_buffer.size();
+ oldSize = currentBufferSize();
}
- int bytesRead = qMin(m_buffer.size(), int(length));
- qMemCopy(buffer, m_buffer.data(), bytesRead);
- //truncate the buffer
- m_buffer = m_buffer.mid(bytesRead);
+ DWORD bytesRead = qMin(currentBufferSize(), int(length));
+ {
+ QWriteLocker locker(&m_lock);
+ qMemCopy(buffer, m_buffer.data(), bytesRead);
+ //truncate the buffer
+ m_buffer = m_buffer.mid(bytesRead);
+ }
if (actual) {
*actual = bytesRead; //initialization
@@ -151,6 +183,7 @@ namespace Phonon
qint64 m_pos;
qint64 m_size;
+ QMutex m_mutexRead;
const MediaGraph *m_mediaGraph;
};
@@ -164,6 +197,14 @@ namespace Phonon
IODeviceReader::~IODeviceReader()
{
}
+
+ STDMETHODIMP IODeviceReader::Stop()
+ {
+ HRESULT hr = QBaseFilter::Stop();
+ m_streamReader->enoughData(); //this asks to cancel any blocked call to needData
+ return hr;
+ }
+
}
}
diff --git a/src/3rdparty/phonon/ds9/iodevicereader.h b/src/3rdparty/phonon/ds9/iodevicereader.h
index c8b91c3..af4b271 100644
--- a/src/3rdparty/phonon/ds9/iodevicereader.h
+++ b/src/3rdparty/phonon/ds9/iodevicereader.h
@@ -41,6 +41,7 @@ namespace Phonon
public:
IODeviceReader(const MediaSource &source, const MediaGraph *);
~IODeviceReader();
+ STDMETHODIMP Stop();
private:
StreamReader *m_streamReader;
diff --git a/src/3rdparty/phonon/ds9/mediagraph.cpp b/src/3rdparty/phonon/ds9/mediagraph.cpp
index 3e7a68b..db0ec84 100644
--- a/src/3rdparty/phonon/ds9/mediagraph.cpp
+++ b/src/3rdparty/phonon/ds9/mediagraph.cpp
@@ -68,8 +68,6 @@ namespace Phonon
return ret;
}
-
-/*
static HRESULT saveToFile(Graph graph, const QString &filepath)
{
const WCHAR wszStreamName[] = L"ActiveMovieGraph";
@@ -105,7 +103,7 @@ namespace Phonon
return hr;
}
-*/
+
MediaGraph::MediaGraph(MediaObject *mo, short index) :
m_graph(CLSID_FilterGraph, IID_IGraphBuilder),
@@ -379,12 +377,11 @@ namespace Phonon
FILTER_INFO info;
filter->QueryFilterInfo(&info);
#ifdef GRAPH_DEBUG
- qDebug() << "removeFilter" << QString((const QChar *)info.achName);
+ qDebug() << "removeFilter" << QString::fromUtf16(info.achName);
#endif
if (info.pGraph) {
info.pGraph->Release();
- if (info.pGraph == m_graph)
- return m_graph->RemoveFilter(filter);
+ return m_graph->RemoveFilter(filter);
}
//already removed
@@ -540,11 +537,11 @@ namespace Phonon
const QList<OutputPin> outputs = BackendNode::pins(filter, PINDIR_OUTPUT);
for(int i = 0; i < outputs.count(); ++i) {
const OutputPin &pin = outputs.at(i);
- if (HRESULT(VFW_E_NOT_CONNECTED) == pin->ConnectedTo(inPin.pparam())) {
+ if (VFW_E_NOT_CONNECTED == pin->ConnectedTo(inPin.pparam())) {
return SUCCEEDED(pin->Connect(newIn, 0));
}
}
- //we shoud never go here
+ //we should never go here
return false;
} else {
QAMMediaType type;
@@ -682,6 +679,7 @@ namespace Phonon
#ifndef QT_NO_PHONON_MEDIACONTROLLER
} else if (source.discType() == Phonon::Cd) {
m_realSource = Filter(new QAudioCDPlayer);
+ m_result = m_graph->AddFilter(m_realSource, 0);
#endif //QT_NO_PHONON_MEDIACONTROLLER
} else {
@@ -811,7 +809,7 @@ namespace Phonon
for (int i = 0; i < outputs.count(); ++i) {
const OutputPin &out = outputs.at(i);
InputPin pin;
- if (out->ConnectedTo(pin.pparam()) == HRESULT(VFW_E_NOT_CONNECTED)) {
+ if (out->ConnectedTo(pin.pparam()) == VFW_E_NOT_CONNECTED) {
m_decoderPins += out; //unconnected outputs can be decoded outputs
}
}
@@ -822,7 +820,7 @@ namespace Phonon
//let's reestablish the connections
for (int i = 0; i < connections.count(); ++i) {
const GraphConnection &connection = connections.at(i);
- //check if we shoud transfer the sink node
+ //check if we should transfer the sink node
grabFilter(connection.input);
grabFilter(connection.output);
@@ -875,7 +873,7 @@ namespace Phonon
{
FILTER_INFO info;
filter->QueryFilterInfo(&info);
- qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName);
+ qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName);
if (info.pGraph) {
info.pGraph->Release();
}
@@ -921,7 +919,7 @@ namespace Phonon
{
FILTER_INFO info;
filter->QueryFilterInfo(&info);
- qDebug() << "found a decoder filter" << QString((const QChar *)info.achName);
+ qDebug() << "found a decoder filter" << QString::fromUtf16(info.achName);
if (info.pGraph) {
info.pGraph->Release();
}
@@ -937,7 +935,7 @@ namespace Phonon
{
FILTER_INFO info;
filter->QueryFilterInfo(&info);
- qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName);
+ qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName);
if (info.pGraph) {
info.pGraph->Release();
}
@@ -956,7 +954,7 @@ namespace Phonon
{
FILTER_INFO info;
filter->QueryFilterInfo(&info);
- qDebug() << Q_FUNC_INFO << QString((const QChar *)info.achName);
+ qDebug() << Q_FUNC_INFO << QString::fromUtf16(info.achName);
if (info.pGraph) {
info.pGraph->Release();
}
@@ -990,7 +988,7 @@ namespace Phonon
{
FILTER_INFO info;
filter->QueryFilterInfo(&info);
- qDebug() << "found a demuxer filter" << QString((const QChar *)info.achName);
+ qDebug() << "found a demuxer filter" << QString::fromUtf16(info.achName);
if (info.pGraph) {
info.pGraph->Release();
}
@@ -1008,27 +1006,27 @@ namespace Phonon
BSTR str;
HRESULT hr = mediaContent->get_AuthorName(&str);
if (SUCCEEDED(hr)) {
- ret.insert(QLatin1String("ARTIST"), QString::fromWCharArray(str));
+ ret.insert(QLatin1String("ARTIST"), QString::fromUtf16((const unsigned short*)str));
SysFreeString(str);
}
hr = mediaContent->get_Title(&str);
if (SUCCEEDED(hr)) {
- ret.insert(QLatin1String("TITLE"), QString::fromWCharArray(str));
+ ret.insert(QLatin1String("TITLE"), QString::fromUtf16((const unsigned short*)str));
SysFreeString(str);
}
hr = mediaContent->get_Description(&str);
if (SUCCEEDED(hr)) {
- ret.insert(QLatin1String("DESCRIPTION"), QString::fromWCharArray(str));
+ ret.insert(QLatin1String("DESCRIPTION"), QString::fromUtf16((const unsigned short*)str));
SysFreeString(str);
}
hr = mediaContent->get_Copyright(&str);
if (SUCCEEDED(hr)) {
- ret.insert(QLatin1String("COPYRIGHT"), QString::fromWCharArray(str));
+ ret.insert(QLatin1String("COPYRIGHT"), QString::fromUtf16((const unsigned short*)str));
SysFreeString(str);
}
hr = mediaContent->get_MoreInfoText(&str);
if (SUCCEEDED(hr)) {
- ret.insert(QLatin1String("MOREINFO"), QString::fromWCharArray(str));
+ ret.insert(QLatin1String("MOREINFO"), QString::fromUtf16((const unsigned short*)str));
SysFreeString(str);
}
}
diff --git a/src/3rdparty/phonon/ds9/mediaobject.cpp b/src/3rdparty/phonon/ds9/mediaobject.cpp
index 34f92c2..d1e15c0 100644
--- a/src/3rdparty/phonon/ds9/mediaobject.cpp
+++ b/src/3rdparty/phonon/ds9/mediaobject.cpp
@@ -23,10 +23,11 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#ifndef Q_CC_MSVC
#include <dshow.h>
-#endif
+#endif //Q_CC_MSVC
#include <objbase.h>
#include <initguid.h>
#include <qnetwork.h>
+#include <comdef.h>
#include <evcode.h>
#include "mediaobject.h"
@@ -49,7 +50,7 @@ namespace Phonon
//first the definition of the WorkerThread class
WorkerThread::WorkerThread()
- : QThread(), m_finished(false), m_currentWorkId(1)
+ : QThread(), m_currentRenderId(0), m_finished(false), m_currentWorkId(1)
{
}
@@ -57,6 +58,24 @@ namespace Phonon
{
}
+ WorkerThread::Work WorkerThread::dequeueWork()
+ {
+ QMutexLocker locker(&m_mutex);
+ if (m_finished) {
+ return Work();
+ }
+ Work ret = m_queue.dequeue();
+
+ //we ensure to have the wait condition in the right state
+ if (m_queue.isEmpty()) {
+ m_waitCondition.reset();
+ } else {
+ m_waitCondition.set();
+ }
+
+ return ret;
+ }
+
void WorkerThread::run()
{
while (m_finished == false) {
@@ -70,6 +89,11 @@ namespace Phonon
}
DWORD result = ::WaitForMultipleObjects(count, handles, FALSE, INFINITE);
if (result == WAIT_OBJECT_0) {
+ if (m_finished) {
+ //that's the end of the thread execution
+ return;
+ }
+
handleTask();
} else {
//this is the event management
@@ -157,7 +181,6 @@ namespace Phonon
//we create a new graph
w.graph = Graph(CLSID_FilterGraph, IID_IGraphBuilder);
w.filter = filter;
- w.graph->AddFilter(filter, 0);
w.id = m_currentWorkId++;
m_queue.enqueue(w);
m_waitCondition.set();
@@ -177,29 +200,23 @@ namespace Phonon
void WorkerThread::handleTask()
{
- QMutexLocker locker(Backend::directShowMutex);
- {
- QMutexLocker locker(&m_mutex);
- if (m_finished || m_queue.isEmpty()) {
- return;
- }
-
- m_currentWork = m_queue.dequeue();
+ const Work w = dequeueWork();
- //we ensure to have the wait condition in the right state
- if (m_queue.isEmpty()) {
- m_waitCondition.reset();
- } else {
- m_waitCondition.set();
- }
+ if (m_finished) {
+ return;
}
HRESULT hr = S_OK;
- if (m_currentWork.task == ReplaceGraph) {
+ m_currentRender = w.graph;
+ m_currentRenderId = w.id;
+ if (w.task == ReplaceGraph) {
+ QMutexLocker locker(&m_mutex);
+ HANDLE h;
+
int index = -1;
for(int i = 0; i < FILTER_COUNT; ++i) {
- if (m_graphHandle[i].graph == m_currentWork.oldGraph) {
+ if (m_graphHandle[i].graph == w.oldGraph) {
m_graphHandle[i].graph = Graph();
index = i;
break;
@@ -212,40 +229,51 @@ namespace Phonon
Q_ASSERT(index != -1);
//add the new graph
- HANDLE h;
- if (SUCCEEDED(ComPointer<IMediaEvent>(m_currentWork.graph, IID_IMediaEvent)
+ if (SUCCEEDED(ComPointer<IMediaEvent>(w.graph, IID_IMediaEvent)
->GetEventHandle(reinterpret_cast<OAEVENT*>(&h)))) {
- m_graphHandle[index].graph = m_currentWork.graph;
+ m_graphHandle[index].graph = w.graph;
m_graphHandle[index].handle = h;
}
- } else if (m_currentWork.task == Render) {
- if (m_currentWork.filter) {
+ } else if (w.task == Render) {
+ if (w.filter) {
//let's render pins
- const QList<OutputPin> outputs = BackendNode::pins(m_currentWork.filter, PINDIR_OUTPUT);
- for (int i = 0; SUCCEEDED(hr) && i < outputs.count(); ++i) {
- hr = m_currentWork.graph->Render(outputs.at(i));
+ w.graph->AddFilter(w.filter, 0);
+ const QList<OutputPin> outputs = BackendNode::pins(w.filter, PINDIR_OUTPUT);
+ for (int i = 0; i < outputs.count(); ++i) {
+ //blocking call
+ hr = w.graph->Render(outputs.at(i));
+ if (FAILED(hr)) {
+ break;
+ }
}
- } else if (!m_currentWork.url.isEmpty()) {
+ } else if (!w.url.isEmpty()) {
//let's render a url (blocking call)
- hr = m_currentWork.graph->RenderFile(reinterpret_cast<const wchar_t *>(m_currentWork.url.utf16()), 0);
+ hr = w.graph->RenderFile(reinterpret_cast<const wchar_t *>(w.url.utf16()), 0);
}
if (hr != E_ABORT) {
- emit asyncRenderFinished(m_currentWork.id, hr, m_currentWork.graph);
+ emit asyncRenderFinished(w.id, hr, w.graph);
}
- } else if (m_currentWork.task == Seek) {
+ } else if (w.task == Seek) {
//that's a seekrequest
- ComPointer<IMediaSeeking> mediaSeeking(m_currentWork.graph, IID_IMediaSeeking);
- qint64 newtime = m_currentWork.time * 10000;
+ ComPointer<IMediaSeeking> mediaSeeking(w.graph, IID_IMediaSeeking);
+ qint64 newtime = w.time * 10000;
hr = mediaSeeking->SetPositions(&newtime, AM_SEEKING_AbsolutePositioning,
0, AM_SEEKING_NoPositioning);
- emit asyncSeekingFinished(m_currentWork.id, newtime / 10000);
+ qint64 currentTime = -1;
+ if (SUCCEEDED(hr)) {
+ hr = mediaSeeking->GetCurrentPosition(&currentTime);
+ if (SUCCEEDED(hr)) {
+ currentTime /= 10000; //convert to ms
+ }
+ }
+ emit asyncSeekingFinished(w.id, currentTime);
hr = E_ABORT; //to avoid emitting asyncRenderFinished
- } else if (m_currentWork.task == ChangeState) {
+ } else if (w.task == ChangeState) {
//remove useless decoders
QList<Filter> unused;
- for (int i = 0; i < m_currentWork.decoders.count(); ++i) {
- const Filter &filter = m_currentWork.decoders.at(i);
+ for (int i = 0; i < w.decoders.count(); ++i) {
+ const Filter &filter = w.decoders.at(i);
bool used = false;
const QList<OutputPin> pins = BackendNode::pins(filter, PINDIR_OUTPUT);
for( int i = 0; i < pins.count(); ++i) {
@@ -262,15 +290,15 @@ namespace Phonon
//we can get the state
for (int i = 0; i < unused.count(); ++i) {
//we should remove this filter from the graph
- m_currentWork.graph->RemoveFilter(unused.at(i));
+ w.graph->RemoveFilter(unused.at(i));
}
//we can get the state
- ComPointer<IMediaControl> mc(m_currentWork.graph, IID_IMediaControl);
+ ComPointer<IMediaControl> mc(w.graph, IID_IMediaControl);
//we change the state here
- switch(m_currentWork.state)
+ switch(w.state)
{
case State_Stopped:
mc->Stop();
@@ -288,38 +316,36 @@ namespace Phonon
if (SUCCEEDED(hr)) {
if (s == State_Stopped) {
- emit stateReady(m_currentWork.graph, Phonon::StoppedState);
+ emit stateReady(w.graph, Phonon::StoppedState);
} else if (s == State_Paused) {
- emit stateReady(m_currentWork.graph, Phonon::PausedState);
+ emit stateReady(w.graph, Phonon::PausedState);
} else /*if (s == State_Running)*/ {
- emit stateReady(m_currentWork.graph, Phonon::PlayingState);
+ emit stateReady(w.graph, Phonon::PlayingState);
}
}
}
- {
- QMutexLocker locker(&m_mutex);
- m_currentWork = Work(); //reinitialize
- }
+ m_currentRender = Graph();
+ m_currentRenderId = 0;
+
}
- void WorkerThread::abortCurrentRender(qint16 renderId)
- {
+ void WorkerThread::abortCurrentRender(qint16 renderId)
+ {
QMutexLocker locker(&m_mutex);
- if (m_currentWork.id == renderId) {
- m_currentWork.graph->Abort();
- }
bool found = false;
+ //we try to see if there is already an attempt to seek and we remove it
for(int i = 0; !found && i < m_queue.size(); ++i) {
const Work &w = m_queue.at(i);
if (w.id == renderId) {
found = true;
m_queue.removeAt(i);
- if (m_queue.isEmpty()) {
- m_waitCondition.reset();
- }
}
}
+
+ if (m_currentRender && m_currentRenderId == renderId) {
+ m_currentRender->Abort();
+ }
}
//tells the thread to stop processing
@@ -327,9 +353,9 @@ namespace Phonon
{
QMutexLocker locker(&m_mutex);
m_queue.clear();
- if (m_currentWork.graph) {
+ if (m_currentRender) {
//in case we're currently rendering something
- m_currentWork.graph->Abort();
+ m_currentRender->Abort();
}
@@ -361,17 +387,17 @@ namespace Phonon
m_graphs[i] = new MediaGraph(this, i);
}
- connect(&m_thread, SIGNAL(stateReady(Graph,Phonon::State)),
- SLOT(slotStateReady(Graph,Phonon::State)));
+ connect(&m_thread, SIGNAL(stateReady(Graph, Phonon::State)),
+ SLOT(slotStateReady(Graph, Phonon::State)));
- connect(&m_thread, SIGNAL(eventReady(Graph,long,long)),
- SLOT(handleEvents(Graph,long,long)));
+ connect(&m_thread, SIGNAL(eventReady(Graph, long, long)),
+ SLOT(handleEvents(Graph, long, long)));
- connect(&m_thread, SIGNAL(asyncRenderFinished(quint16,HRESULT,Graph)),
- SLOT(finishLoading(quint16,HRESULT,Graph)));
+ connect(&m_thread, SIGNAL(asyncRenderFinished(quint16, HRESULT, Graph)),
+ SLOT(finishLoading(quint16, HRESULT, Graph)));
- connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16,qint64)),
- SLOT(finishSeeking(quint16,qint64)));
+ connect(&m_thread, SIGNAL(asyncSeekingFinished(quint16, qint64)),
+ SLOT(finishSeeking(quint16, qint64)));
//really special case
m_mediaObject = this;
m_thread.start();
@@ -494,18 +520,6 @@ namespace Phonon
qSwap(m_graphs[0], m_graphs[1]); //swap the graphs
- if (m_transitionTime >= 0)
- m_graphs[1]->stop(); //make sure we stop the previous graph
-
- if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid &&
- catchComError(currentGraph()->renderResult())) {
- setState(Phonon::ErrorState);
- return;
- }
-
- //we need to play the next media
- play();
-
//we tell the video widgets to switch now to the new source
#ifndef QT_NO_PHONON_VIDEO
for (int i = 0; i < m_videoWidgets.count(); ++i) {
@@ -514,6 +528,15 @@ namespace Phonon
#endif //QT_NO_PHONON_VIDEO
emit currentSourceChanged(currentGraph()->mediaSource());
+
+ if (currentGraph()->isLoading()) {
+ //will simply tell that when loading is finished
+ //it should start the playback
+ play();
+ }
+
+
+
emit metaDataChanged(currentGraph()->metadata());
if (nextGraph()->hasVideo() != currentGraph()->hasVideo()) {
@@ -526,6 +549,15 @@ namespace Phonon
#ifndef QT_NO_PHONON_MEDIACONTROLLER
setTitles(currentGraph()->titles());
#endif //QT_NO_PHONON_MEDIACONTROLLER
+
+ //this manages only gapless transitions
+ if (currentGraph()->mediaSource().type() != Phonon::MediaSource::Invalid) {
+ if (catchComError(currentGraph()->renderResult())) {
+ setState(Phonon::ErrorState);
+ } else {
+ play();
+ }
+ }
}
Phonon::State MediaObject::state() const
@@ -760,16 +792,15 @@ namespace Phonon
case Phonon::PausedState:
pause();
break;
+ case Phonon::StoppedState:
+ stop();
+ break;
case Phonon::PlayingState:
play();
break;
case Phonon::ErrorState:
setState(Phonon::ErrorState);
break;
- case Phonon::StoppedState:
- default:
- stop();
- break;
}
}
}
@@ -817,11 +848,11 @@ namespace Phonon
#endif
LPAMGETERRORTEXT getErrorText = (LPAMGETERRORTEXT)QLibrary::resolve(QLatin1String("quartz"), "AMGetErrorTextW");
- WCHAR buffer[MAX_ERROR_TEXT_LEN];
- if (getErrorText && getErrorText(hr, buffer, MAX_ERROR_TEXT_LEN)) {
- m_errorString = QString::fromWCharArray(buffer);
+ ushort buffer[MAX_ERROR_TEXT_LEN];
+ if (getErrorText && getErrorText(hr, (WCHAR*)buffer, MAX_ERROR_TEXT_LEN)) {
+ m_errorString = QString::fromUtf16(buffer);
} else {
- m_errorString = QString::fromLatin1("Unknown error");
+ m_errorString = QString::fromUtf16((ushort*)_com_error(hr).ErrorMessage());
}
const QString comError = QString::number(uint(hr), 16);
if (!m_errorString.toLower().contains(comError.toLower())) {
diff --git a/src/3rdparty/phonon/ds9/mediaobject.h b/src/3rdparty/phonon/ds9/mediaobject.h
index 34aa666..2c34ffc 100644
--- a/src/3rdparty/phonon/ds9/mediaobject.h
+++ b/src/3rdparty/phonon/ds9/mediaobject.h
@@ -114,7 +114,6 @@ namespace Phonon
enum Task
{
- None,
Render,
Seek,
ChangeState,
@@ -123,7 +122,6 @@ namespace Phonon
struct Work
{
- Work() : task(None), id(0), time(0) { }
Task task;
quint16 id;
Graph graph;
@@ -137,14 +135,16 @@ namespace Phonon
};
QList<Filter> decoders; //for the state change requests
};
+ Work dequeueWork();
void handleTask();
- Work m_currentWork;
+ Graph m_currentRender;
+ qint16 m_currentRenderId;
QQueue<Work> m_queue;
bool m_finished;
quint16 m_currentWorkId;
QWinWaitCondition m_waitCondition;
- QMutex m_mutex; // mutex for the m_queue, m_finished and m_currentWorkId
+ QMutex m_mutex;
//this is for WaitForMultipleObjects
struct
diff --git a/src/3rdparty/phonon/ds9/qasyncreader.cpp b/src/3rdparty/phonon/ds9/qasyncreader.cpp
index a3f9cda..68ec1f8 100644
--- a/src/3rdparty/phonon/ds9/qasyncreader.cpp
+++ b/src/3rdparty/phonon/ds9/qasyncreader.cpp
@@ -15,6 +15,8 @@ You should have received a copy of the GNU Lesser General Public License
along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <QtCore/QFile>
+
#include "qasyncreader.h"
#include "qbasefilter.h"
@@ -78,7 +80,8 @@ namespace Phonon
STDMETHODIMP QAsyncReader::Request(IMediaSample *sample,DWORD_PTR user)
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker mutexLocker(&m_mutexWait);
+ QWriteLocker locker(&m_lock);
if (m_flushing) {
return VFW_E_WRONG_STATE;
}
@@ -90,28 +93,33 @@ namespace Phonon
STDMETHODIMP QAsyncReader::WaitForNext(DWORD timeout, IMediaSample **sample, DWORD_PTR *user)
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker locker(&m_mutexWait);
if (!sample ||!user) {
return E_POINTER;
}
- //msdn says to return immediately if we're flushing but that doesn't seem to be true
- //since it triggers a dead-lock somewhere inside directshow (see task 258830)
-
*sample = 0;
*user = 0;
- if (m_requestQueue.isEmpty()) {
- if (m_requestWait.wait(&m_mutex, timeout) == false) {
- return VFW_E_TIMEOUT;
- }
- if (m_requestQueue.isEmpty()) {
+ AsyncRequest r = getNextRequest();
+
+ if (r.sample == 0) {
+ //there is no request in the queue
+ if (isFlushing()) {
return VFW_E_WRONG_STATE;
+ } else {
+ //First we need to lock the mutex
+ if (m_requestWait.wait(&m_mutexWait, timeout) == false) {
+ return VFW_E_TIMEOUT;
+ }
+ if (isFlushing()) {
+ return VFW_E_WRONG_STATE;
+ }
+
+ r = getNextRequest();
}
}
- AsyncRequest r = m_requestQueue.dequeue();
-
//at this point we're sure to have a request to proceed
if (r.sample == 0) {
return E_FAIL;
@@ -119,12 +127,14 @@ namespace Phonon
*sample = r.sample;
*user = r.user;
- return syncReadAlignedUnlocked(r.sample);
+
+ return SyncReadAligned(r.sample);
}
STDMETHODIMP QAsyncReader::BeginFlush()
{
- QMutexLocker locker(&m_mutex);
+ QMutexLocker mutexLocker(&m_mutexWait);
+ QWriteLocker locker(&m_lock);
m_flushing = true;
m_requestWait.wakeOne();
return S_OK;
@@ -132,28 +142,13 @@ namespace Phonon
STDMETHODIMP QAsyncReader::EndFlush()
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_flushing = false;
return S_OK;
}
STDMETHODIMP QAsyncReader::SyncReadAligned(IMediaSample *sample)
{
- QMutexLocker locker(&m_mutex);
- return syncReadAlignedUnlocked(sample);
- }
-
- STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer)
- {
- QMutexLocker locker(&m_mutex);
- return read(pos, length, buffer, 0);
- }
-
-
- STDMETHODIMP QAsyncReader::syncReadAlignedUnlocked(IMediaSample *sample)
- {
- Q_ASSERT(!m_mutex.tryLock());
-
if (!sample) {
return E_POINTER;
}
@@ -180,6 +175,23 @@ namespace Phonon
return sample->SetActualDataLength(actual);
}
+ STDMETHODIMP QAsyncReader::SyncRead(LONGLONG pos, LONG length, BYTE *buffer)
+ {
+ return read(pos, length, buffer, 0);
+ }
+
+
+ //addition
+ QAsyncReader::AsyncRequest QAsyncReader::getNextRequest()
+ {
+ QWriteLocker locker(&m_lock);
+ AsyncRequest ret;
+ if (!m_requestQueue.isEmpty()) {
+ ret = m_requestQueue.dequeue();
+ }
+
+ return ret;
+ }
}
}
diff --git a/src/3rdparty/phonon/ds9/qasyncreader.h b/src/3rdparty/phonon/ds9/qasyncreader.h
index 95872f9..cb789ee 100644
--- a/src/3rdparty/phonon/ds9/qasyncreader.h
+++ b/src/3rdparty/phonon/ds9/qasyncreader.h
@@ -48,12 +48,11 @@ namespace Phonon
STDMETHODIMP WaitForNext(DWORD,IMediaSample **,DWORD_PTR *);
STDMETHODIMP SyncReadAligned(IMediaSample *);
STDMETHODIMP SyncRead(LONGLONG,LONG,BYTE *);
- STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0;
+ virtual STDMETHODIMP Length(LONGLONG *,LONGLONG *) = 0;
STDMETHODIMP BeginFlush();
STDMETHODIMP EndFlush();
protected:
- STDMETHODIMP syncReadAlignedUnlocked(IMediaSample *);
virtual HRESULT read(LONGLONG pos, LONG length, BYTE *buffer, LONG *actual) = 0;
private:
@@ -63,6 +62,9 @@ namespace Phonon
IMediaSample *sample;
DWORD_PTR user;
};
+ AsyncRequest getNextRequest();
+
+ QMutex m_mutexWait;
QQueue<AsyncRequest> m_requestQueue;
QWaitCondition m_requestWait;
diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp
index 6d0f335..b9f9fd6 100644
--- a/src/3rdparty/phonon/ds9/qaudiocdreader.cpp
+++ b/src/3rdparty/phonon/ds9/qaudiocdreader.cpp
@@ -103,8 +103,8 @@ namespace Phonon
private:
HANDLE m_cddrive;
- CDROM_TOC m_toc;
- WaveStructure m_waveHeader;
+ CDROM_TOC *m_toc;
+ WaveStructure *m_waveHeader;
qint64 m_trackAddress;
};
@@ -112,8 +112,19 @@ namespace Phonon
#define SECTOR_SIZE 2352
#define NB_SECTORS_READ 20
- static const AM_MEDIA_TYPE audioCDMediaType = { MEDIATYPE_Stream, MEDIASUBTYPE_WAVE, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
-
+ static AM_MEDIA_TYPE getAudioCDMediaType()
+ {
+ AM_MEDIA_TYPE mt;
+ qMemSet(&mt, 0, sizeof(AM_MEDIA_TYPE));
+ mt.majortype = MEDIATYPE_Stream;
+ mt.subtype = MEDIASUBTYPE_WAVE;
+ mt.bFixedSizeSamples = TRUE;
+ mt.bTemporalCompression = FALSE;
+ mt.lSampleSize = 1;
+ mt.formattype = GUID_NULL;
+ return mt;
+ }
+
int addressToSectors(UCHAR address[4])
{
return ((address[0] * 60 + address[1]) * 60 + address[2]) * 75 + address[3] - 150;
@@ -130,8 +141,11 @@ namespace Phonon
}
- QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << audioCDMediaType)
+ QAudioCDReader::QAudioCDReader(QBaseFilter *parent, QChar drive) : QAsyncReader(parent, QVector<AM_MEDIA_TYPE>() << getAudioCDMediaType())
{
+ m_toc = new CDROM_TOC;
+ m_waveHeader = new WaveStructure;
+
//now open the cd-drive
QString path;
if (drive.isNull()) {
@@ -140,30 +154,36 @@ namespace Phonon
path = QString::fromLatin1("\\\\.\\%1:").arg(drive);
}
- m_cddrive = ::CreateFile((const wchar_t *)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+ m_cddrive = QT_WA_INLINE (
+ ::CreateFile( (TCHAR*)path.utf16(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL ),
+ ::CreateFileA( path.toLocal8Bit().constData(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL )
+ );
- qMemSet(&m_toc, 0, sizeof(CDROM_TOC));
+ qMemSet(m_toc, 0, sizeof(CDROM_TOC));
//read the TOC
DWORD bytesRead = 0;
- bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, &m_toc, sizeof(CDROM_TOC), &bytesRead, 0);
+ bool tocRead = ::DeviceIoControl(m_cddrive, IOCTL_CDROM_READ_TOC, 0, 0, m_toc, sizeof(CDROM_TOC), &bytesRead, 0);
if (!tocRead) {
qWarning("unable to load the TOC from the CD");
return;
}
- m_trackAddress = addressToSectors(m_toc.TrackData[0].Address);
- const qint32 nbSectorsToRead = (addressToSectors(m_toc.TrackData[m_toc.LastTrack + 1 - m_toc.FirstTrack].Address)
+ m_trackAddress = addressToSectors(m_toc->TrackData[0].Address);
+ const qint32 nbSectorsToRead = (addressToSectors(m_toc->TrackData[m_toc->LastTrack + 1 - m_toc->FirstTrack].Address)
- m_trackAddress);
const qint32 dataLength = nbSectorsToRead * SECTOR_SIZE;
- m_waveHeader.chunksize = 4 + (8 + m_waveHeader.chunksize2) + (8 + dataLength);
- m_waveHeader.dataLength = dataLength;
+ m_waveHeader->chunksize = 4 + (8 + m_waveHeader->chunksize2) + (8 + dataLength);
+ m_waveHeader->dataLength = dataLength;
}
QAudioCDReader::~QAudioCDReader()
{
::CloseHandle(m_cddrive);
+ delete m_toc;
+ delete m_waveHeader;
+
}
STDMETHODIMP_(ULONG) QAudioCDReader::AddRef()
@@ -179,7 +199,7 @@ namespace Phonon
STDMETHODIMP QAudioCDReader::Length(LONGLONG *total,LONGLONG *available)
{
- const LONGLONG length = sizeof(WaveStructure) + m_waveHeader.dataLength;
+ const LONGLONG length = sizeof(WaveStructure) + m_waveHeader->dataLength;
if (total) {
*total = length;
}
@@ -218,11 +238,11 @@ namespace Phonon
if (pos < sizeof(WaveStructure)) {
//we first copy the content of the structure
nbRead = qMin(LONG(sizeof(WaveStructure) - pos), length);
- qMemCopy(buffer, reinterpret_cast<char*>(&m_waveHeader) + pos, nbRead);
+ qMemCopy(buffer, reinterpret_cast<char*>(m_waveHeader) + pos, nbRead);
}
const LONGLONG posInTrack = pos - sizeof(WaveStructure) + nbRead;
- const int bytesLeft = qMin(m_waveHeader.dataLength - posInTrack, LONGLONG(length - nbRead));
+ const int bytesLeft = qMin(m_waveHeader->dataLength - posInTrack, LONGLONG(length - nbRead));
if (bytesLeft > 0) {
@@ -277,8 +297,8 @@ namespace Phonon
{
QList<qint64> ret;
ret << 0;
- for(int i = m_toc.FirstTrack; i <= m_toc.LastTrack ; ++i) {
- const uchar *address = m_toc.TrackData[i].Address;
+ for(int i = m_toc->FirstTrack; i <= m_toc->LastTrack ; ++i) {
+ const uchar *address = m_toc->TrackData[i].Address;
ret << ((address[0] * 60 + address[1]) * 60 + address[2]) * 1000 + address[3]*1000/75 - 2000;
}
diff --git a/src/3rdparty/phonon/ds9/qaudiocdreader.h b/src/3rdparty/phonon/ds9/qaudiocdreader.h
index eff845d..9049b66 100644
--- a/src/3rdparty/phonon/ds9/qaudiocdreader.h
+++ b/src/3rdparty/phonon/ds9/qaudiocdreader.h
@@ -31,7 +31,7 @@ namespace Phonon
{
struct CDROM_TOC;
struct WaveStructure;
- EXTERN_C const IID IID_ITitleInterface;
+ extern const IID IID_ITitleInterface;
//interface for the Titles
struct ITitleInterface : public IUnknown
diff --git a/src/3rdparty/phonon/ds9/qbasefilter.cpp b/src/3rdparty/phonon/ds9/qbasefilter.cpp
index 78b8b8f..95cab92 100644
--- a/src/3rdparty/phonon/ds9/qbasefilter.cpp
+++ b/src/3rdparty/phonon/ds9/qbasefilter.cpp
@@ -92,8 +92,8 @@ namespace Phonon
return E_POINTER;
}
- uint nbfetched = 0;
- while (nbfetched < count && m_index < m_pins.count()) {
+ int nbfetched = 0;
+ while (nbfetched < int(count) && m_index < m_pins.count()) {
IPin *current = m_pins[m_index];
current->AddRef();
ret[nbfetched] = current;
@@ -166,19 +166,19 @@ namespace Phonon
const QList<QPin *> QBaseFilter::pins() const
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
return m_pins;
}
void QBaseFilter::addPin(QPin *pin)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_pins.append(pin);
}
void QBaseFilter::removePin(QPin *pin)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_pins.removeAll(pin);
}
@@ -211,8 +211,7 @@ namespace Phonon
}
else if (iid == IID_IMediaPosition || iid == IID_IMediaSeeking) {
if (inputPins().isEmpty()) {
- *out = getUpStreamInterface(iid);
- if (*out) {
+ if (*out = getUpStreamInterface(iid)) {
return S_OK; //we return here to avoid adding a reference
} else {
hr = E_NOINTERFACE;
@@ -251,35 +250,35 @@ namespace Phonon
STDMETHODIMP QBaseFilter::GetClassID(CLSID *clsid)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
*clsid = m_clsid;
return S_OK;
}
STDMETHODIMP QBaseFilter::Stop()
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_state = State_Stopped;
return S_OK;
}
STDMETHODIMP QBaseFilter::Pause()
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_state = State_Paused;
return S_OK;
}
STDMETHODIMP QBaseFilter::Run(REFERENCE_TIME)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_state = State_Running;
return S_OK;
}
STDMETHODIMP QBaseFilter::GetState(DWORD, FILTER_STATE *state)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (!state) {
return E_POINTER;
}
@@ -290,7 +289,7 @@ namespace Phonon
STDMETHODIMP QBaseFilter::SetSyncSource(IReferenceClock *clock)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
if (clock) {
clock->AddRef();
}
@@ -303,7 +302,7 @@ namespace Phonon
STDMETHODIMP QBaseFilter::GetSyncSource(IReferenceClock **clock)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (!clock) {
return E_POINTER;
}
@@ -342,7 +341,7 @@ namespace Phonon
STDMETHODIMP QBaseFilter::QueryFilterInfo(FILTER_INFO *info )
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (!info) {
return E_POINTER;
}
@@ -356,9 +355,9 @@ namespace Phonon
STDMETHODIMP QBaseFilter::JoinFilterGraph(IFilterGraph *graph, LPCWSTR name)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_graph = graph;
- m_name = QString::fromWCharArray(name);
+ m_name = QString::fromUtf16((const unsigned short*)name);
return S_OK;
}
diff --git a/src/3rdparty/phonon/ds9/qbasefilter.h b/src/3rdparty/phonon/ds9/qbasefilter.h
index a72d6fe..85f1431 100644
--- a/src/3rdparty/phonon/ds9/qbasefilter.h
+++ b/src/3rdparty/phonon/ds9/qbasefilter.h
@@ -22,7 +22,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <QtCore/QString>
#include <QtCore/QList>
-#include <QtCore/QMutex>
+#include <QtCore/QReadWriteLock>
#include <dshow.h>
@@ -127,7 +127,7 @@ namespace Phonon
IFilterGraph *m_graph;
FILTER_STATE m_state;
QList<QPin *> m_pins;
- mutable QMutex m_mutex;
+ mutable QReadWriteLock m_lock;
};
}
}
diff --git a/src/3rdparty/phonon/ds9/qevr9.h b/src/3rdparty/phonon/ds9/qevr9.h
deleted file mode 100644
index 8599fce..0000000
--- a/src/3rdparty/phonon/ds9/qevr9.h
+++ /dev/null
@@ -1,143 +0,0 @@
-/* This file is part of the KDE project.
-
-Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-
-This library is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 2.1 or 3 of the License.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#include <d3d9.h>
-
-#define DXVA2_ProcAmp_Brightness 1
-#define DXVA2_ProcAmp_Contrast 2
-#define DXVA2_ProcAmp_Hue 4
-#define DXVA2_ProcAmp_Saturation 8
-
-typedef enum {
- MFVideoARMode_None = 0x00000000,
- MFVideoARMode_PreservePicture = 0x00000001,
- MFVideoARMode_PreservePixel = 0x00000002,
- MFVideoARMode_NonLinearStretch = 0x00000004,
- MFVideoARMode_Mask = 0x00000007
-} MFVideoAspectRatioMode;
-
-typedef struct {
- float left;
- float top;
- float right;
- float bottom;
-} MFVideoNormalizedRect;
-
-typedef struct {
- UINT DeviceCaps;
- D3DPOOL InputPool;
- UINT NumForwardRefSamples;
- UINT NumBackwardRefSamples;
- UINT Reserved;
- UINT DeinterlaceTechnology;
- UINT ProcAmpControlCaps;
- UINT VideoProcessorOperations;
- UINT NoiseFilterTechnology;
- UINT DetailFilterTechnology;
-} DXVA2_VideoProcessorCaps;
-
-typedef struct {
- union {
- struct {
- USHORT Fraction;
- SHORT Value;
- };
- LONG ll;
- };
-} DXVA2_Fixed32;
-
-typedef struct {
- DXVA2_Fixed32 MinValue;
- DXVA2_Fixed32 MaxValue;
- DXVA2_Fixed32 DefaultValue;
- DXVA2_Fixed32 StepSize;
-} DXVA2_ValueRange;
-
-typedef struct {
- DXVA2_Fixed32 Brightness;
- DXVA2_Fixed32 Contrast;
- DXVA2_Fixed32 Hue;
- DXVA2_Fixed32 Saturation;
-} DXVA2_ProcAmpValues;
-
-DXVA2_Fixed32 DXVA2FloatToFixed(const float _float_)
-{
- DXVA2_Fixed32 _fixed_;
- _fixed_.Fraction = LOWORD(_float_ * 0x10000);
- _fixed_.Value = HIWORD(_float_ * 0x10000);
- return _fixed_;
-}
-
-float DXVA2FixedToFloat(const DXVA2_Fixed32 _fixed_)
-{
- return (FLOAT)_fixed_.Value + (FLOAT)_fixed_.Fraction / 0x10000;
-}
-
-#undef INTERFACE
-#define INTERFACE IMFVideoDisplayControl
-DECLARE_INTERFACE_(IMFVideoDisplayControl, IUnknown)
-{
- STDMETHOD(GetNativeVideoSize)(THIS_ SIZE* pszVideo, SIZE* pszARVideo) PURE;
- STDMETHOD(GetIdealVideoSize)(THIS_ SIZE* pszMin, SIZE* pszMax) PURE;
- STDMETHOD(SetVideoPosition)(THIS_ const MFVideoNormalizedRect* pnrcSource, const LPRECT prcDest) PURE;
- STDMETHOD(GetVideoPosition)(THIS_ MFVideoNormalizedRect* pnrcSource, LPRECT prcDest) PURE;
- STDMETHOD(SetAspectRatioMode)(THIS_ DWORD dwAspectRatioMode) PURE;
- STDMETHOD(GetAspectRatioMode)(THIS_ DWORD* pdwAspectRatioMode) PURE;
- STDMETHOD(SetVideoWindow)(THIS_ HWND hwndVideo) PURE;
- STDMETHOD(GetVideoWindow)(THIS_ HWND* phwndVideo) PURE;
- STDMETHOD(RepaintVideo)(THIS_) PURE;
- STDMETHOD(GetCurrentImage)(THIS_ BITMAPINFOHEADER* pBih, BYTE** pDib, DWORD* pcbDib, LONGLONG* pTimeStamp) PURE;
- STDMETHOD(SetBorderColor)(THIS_ COLORREF Clr) PURE;
- STDMETHOD(GetBorderColor)(THIS_ COLORREF* pClr) PURE;
- STDMETHOD(SetRenderingPrefs)(THIS_ DWORD dwRenderFlags) PURE;
- STDMETHOD(GetRenderingPrefs)(THIS_ DWORD* pdwRenderFlags) PURE;
- STDMETHOD(SetFullScreen)(THIS_ BOOL fFullscreen) PURE;
- STDMETHOD(GetFullScreen)(THIS_ BOOL* pfFullscreen) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMFVideoMixerControl
-DECLARE_INTERFACE_(IMFVideoMixerControl, IUnknown)
-{
- STDMETHOD(SetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD dwZ) PURE;
- STDMETHOD(GetStreamZOrder)(THIS_ DWORD dwStreamID, DWORD* pdwZ) PURE;
- STDMETHOD(SetStreamOutputRect)(THIS_ DWORD dwStreamID, const MFVideoNormalizedRect* pnrcOutput) PURE;
- STDMETHOD(GetStreamOutputRect)(THIS_ DWORD dwStreamID, MFVideoNormalizedRect* pnrcOutput) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMFVideoProcessor
-DECLARE_INTERFACE_(IMFVideoProcessor, IUnknown)
-{
- STDMETHOD(GetAvailableVideoProcessorModes)(THIS_ UINT* lpdwNumProcessingModes, GUID** ppVideoProcessingModes) PURE;
- STDMETHOD(GetVideoProcessorCaps)(THIS_ LPGUID lpVideoProcessorMode, DXVA2_VideoProcessorCaps* lpVideoProcessorCaps) PURE;
- STDMETHOD(GetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE;
- STDMETHOD(SetVideoProcessorMode)(THIS_ LPGUID lpMode) PURE;
- STDMETHOD(GetProcAmpRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE;
- STDMETHOD(GetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* Values) PURE;
- STDMETHOD(SetProcAmpValues)(THIS_ DWORD dwFlags, DXVA2_ProcAmpValues* pValues) PURE;
- STDMETHOD(GetFilteringRange)(THIS_ DWORD dwProperty, DXVA2_ValueRange* pPropRange) PURE;
- STDMETHOD(GetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE;
- STDMETHOD(SetFilteringValue)(THIS_ DWORD dwProperty, DXVA2_Fixed32* pValue) PURE;
- STDMETHOD(GetBackgroundColor)(THIS_ COLORREF* lpClrBkg) PURE;
- STDMETHOD(SetBackgroundColor)(THIS_ COLORREF ClrBkg) PURE;
-};
-#undef INTERFACE
-#define INTERFACE IMFGetService
-DECLARE_INTERFACE_(IMFGetService, IUnknown)
-{
- STDMETHOD(GetService)(THIS_ REFGUID guidService, REFIID riid, LPVOID* ppvObject) PURE;
-};
-#undef INTERFACE
diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.cpp b/src/3rdparty/phonon/ds9/qmeminputpin.cpp
index a21fbe7..dca99db 100644
--- a/src/3rdparty/phonon/ds9/qmeminputpin.cpp
+++ b/src/3rdparty/phonon/ds9/qmeminputpin.cpp
@@ -28,8 +28,8 @@ namespace Phonon
namespace DS9
{
- QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, bool transform, QPin *output) :
- QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform), m_output(output)
+ QMemInputPin::QMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, bool transform) :
+ QPin(parent, PINDIR_INPUT, mt), m_shouldDuplicateSamples(true), m_transform(transform)
{
}
@@ -66,9 +66,11 @@ namespace Phonon
{
//this allows to serialize with Receive calls
QMutexLocker locker(&m_mutexReceive);
- IPin *conn = m_output ? m_output->connected() : 0;
- if (conn) {
- conn->EndOfStream();
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ IPin *conn = m_outputs.at(i)->connected();
+ if (conn) {
+ conn->EndOfStream();
+ }
}
return S_OK;
}
@@ -76,11 +78,13 @@ namespace Phonon
STDMETHODIMP QMemInputPin::BeginFlush()
{
//pass downstream
- IPin *conn = m_output ? m_output->connected() : 0;
- if (conn) {
- conn->BeginFlush();
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ IPin *conn = m_outputs.at(i)->connected();
+ if (conn) {
+ conn->BeginFlush();
+ }
}
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_flushing = true;
return S_OK;
}
@@ -88,19 +92,22 @@ namespace Phonon
STDMETHODIMP QMemInputPin::EndFlush()
{
//pass downstream
- IPin *conn = m_output ? m_output->connected() : 0;
- if (conn) {
- conn->EndFlush();
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ IPin *conn = m_outputs.at(i)->connected();
+ if (conn) {
+ conn->EndFlush();
+ }
}
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_flushing = false;
return S_OK;
}
STDMETHODIMP QMemInputPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
{
- if (m_output)
- m_output->NewSegment(start, stop, rate);
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ m_outputs.at(i)->NewSegment(start, stop, rate);
+ }
return S_OK;
}
@@ -112,9 +119,14 @@ namespace Phonon
if (hr == S_OK &&
mt->majortype != MEDIATYPE_NULL &&
mt->subtype != MEDIASUBTYPE_NULL &&
- mt->formattype != GUID_NULL && m_output) {
- //we tell the output pin that it should connect with this type
- hr = m_output->setAcceptedMediaType(connectedType());
+ mt->formattype != GUID_NULL) {
+ //we tell the output pins that they should connect with this type
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ hr = m_outputs.at(i)->setAcceptedMediaType(connectedType());
+ if (FAILED(hr)) {
+ break;
+ }
+ }
}
return hr;
}
@@ -125,8 +137,7 @@ namespace Phonon
return E_POINTER;
}
- *alloc = memoryAllocator(true);
- if (*alloc) {
+ if (*alloc = memoryAllocator(true)) {
return S_OK;
}
@@ -140,15 +151,18 @@ namespace Phonon
}
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
m_shouldDuplicateSamples = m_transform && readonly;
}
setMemoryAllocator(alloc);
- if (m_output) {
- ComPointer<IMemInputPin> input(m_output, IID_IMemInputPin);
- input->NotifyAllocator(alloc, m_shouldDuplicateSamples);
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ IPin *pin = m_outputs.at(i)->connected();
+ if (pin) {
+ ComPointer<IMemInputPin> input(pin, IID_IMemInputPin);
+ input->NotifyAllocator(alloc, m_shouldDuplicateSamples);
+ }
}
return S_OK;
@@ -187,18 +201,22 @@ namespace Phonon
}
}
- if (m_output) {
+ for (int i = 0; i < m_outputs.count(); ++i) {
+ QPin *current = m_outputs.at(i);
IMediaSample *outSample = m_shouldDuplicateSamples ?
- duplicateSampleForOutput(sample, m_output->memoryAllocator())
+ duplicateSampleForOutput(sample, current->memoryAllocator())
: sample;
if (m_shouldDuplicateSamples) {
m_parent->processSample(outSample);
}
- ComPointer<IMemInputPin> input(m_output->connected(), IID_IMemInputPin);
- if (input) {
- input->Receive(outSample);
+ IPin *pin = current->connected();
+ if (pin) {
+ ComPointer<IMemInputPin> input(pin, IID_IMemInputPin);
+ if (input) {
+ input->Receive(outSample);
+ }
}
if (m_shouldDuplicateSamples) {
@@ -229,16 +247,39 @@ namespace Phonon
STDMETHODIMP QMemInputPin::ReceiveCanBlock()
{
- //we test the output to see if it can block
- if (m_output) {
- ComPointer<IMemInputPin> meminput(m_output->connected(), IID_IMemInputPin);
- if (meminput && meminput->ReceiveCanBlock() != S_FALSE) {
- return S_OK;
+ //we test the output to see if they can block
+ for(int i = 0; i < m_outputs.count(); ++i) {
+ IPin *input = m_outputs.at(i)->connected();
+ if (input) {
+ ComPointer<IMemInputPin> meminput(input, IID_IMemInputPin);
+ if (meminput && meminput->ReceiveCanBlock() != S_FALSE) {
+ return S_OK;
+ }
}
}
return S_FALSE;
}
+ //addition
+ //this should be used by the filter to tell its input pins to which output they should route the samples
+
+ void QMemInputPin::addOutput(QPin *output)
+ {
+ QWriteLocker locker(&m_lock);
+ m_outputs += output;
+ }
+
+ void QMemInputPin::removeOutput(QPin *output)
+ {
+ QWriteLocker locker(&m_lock);
+ m_outputs.removeOne(output);
+ }
+
+ QList<QPin*> QMemInputPin::outputs() const
+ {
+ QReadLocker locker(&m_lock);
+ return m_outputs;
+ }
ALLOCATOR_PROPERTIES QMemInputPin::getDefaultAllocatorProperties() const
{
@@ -253,7 +294,7 @@ namespace Phonon
LONG length = sample->GetActualDataLength();
HRESULT hr = alloc->Commit();
- if (hr == HRESULT(VFW_E_SIZENOTSET)) {
+ if (hr == VFW_E_SIZENOTSET) {
ALLOCATOR_PROPERTIES prop = getDefaultAllocatorProperties();
prop.cbBuffer = qMax(prop.cbBuffer, length);
ALLOCATOR_PROPERTIES actual;
@@ -283,7 +324,7 @@ namespace Phonon
{
LONGLONG start, end;
hr = sample->GetMediaTime(&start, &end);
- if (hr != HRESULT(VFW_E_MEDIA_TIME_NOT_SET)) {
+ if (hr != VFW_E_MEDIA_TIME_NOT_SET) {
hr = out->SetMediaTime(&start, &end);
Q_ASSERT(SUCCEEDED(hr));
}
diff --git a/src/3rdparty/phonon/ds9/qmeminputpin.h b/src/3rdparty/phonon/ds9/qmeminputpin.h
index d74c451..c449721 100644
--- a/src/3rdparty/phonon/ds9/qmeminputpin.h
+++ b/src/3rdparty/phonon/ds9/qmeminputpin.h
@@ -37,7 +37,7 @@ namespace Phonon
class QMemInputPin : public QPin, public IMemInputPin
{
public:
- QMemInputPin(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &, bool transform, QPin *output);
+ QMemInputPin(QBaseFilter *, const QVector<AM_MEDIA_TYPE> &, bool transform);
~QMemInputPin();
//reimplementation from IUnknown
@@ -60,13 +60,18 @@ namespace Phonon
STDMETHODIMP ReceiveMultiple(IMediaSample **,long,long *);
STDMETHODIMP ReceiveCanBlock();
+ //addition
+ void addOutput(QPin *output);
+ void removeOutput(QPin *output);
+ QList<QPin*> outputs() const;
+
private:
IMediaSample *duplicateSampleForOutput(IMediaSample *, IMemAllocator *);
ALLOCATOR_PROPERTIES getDefaultAllocatorProperties() const;
bool m_shouldDuplicateSamples;
const bool m_transform; //defines if the pin is transforming the samples
- QPin* const m_output;
+ QList<QPin*> m_outputs;
QMutex m_mutexReceive;
};
}
diff --git a/src/3rdparty/phonon/ds9/qpin.cpp b/src/3rdparty/phonon/ds9/qpin.cpp
index b4afd10..37fe48d 100644
--- a/src/3rdparty/phonon/ds9/qpin.cpp
+++ b/src/3rdparty/phonon/ds9/qpin.cpp
@@ -28,7 +28,20 @@ namespace Phonon
namespace DS9
{
- static const AM_MEDIA_TYPE defaultMediaType = { MEDIATYPE_NULL, MEDIASUBTYPE_NULL, TRUE, FALSE, 1, GUID_NULL, 0, 0, 0};
+ static const AM_MEDIA_TYPE defaultMediaType()
+ {
+ AM_MEDIA_TYPE ret;
+ ret.majortype = MEDIATYPE_NULL;
+ ret.subtype = MEDIASUBTYPE_NULL;
+ ret.bFixedSizeSamples = TRUE;
+ ret.bTemporalCompression = FALSE;
+ ret.lSampleSize = 1;
+ ret.formattype = GUID_NULL;
+ ret.pUnk = 0;
+ ret.cbFormat = 0;
+ ret.pbFormat = 0;
+ return ret;
+ }
class QEnumMediaTypes : public IEnumMediaTypes
{
@@ -91,8 +104,8 @@ namespace Phonon
return E_INVALIDARG;
}
- uint nbFetched = 0;
- while (nbFetched < count && m_index < m_pin->mediaTypes().count()) {
+ int nbFetched = 0;
+ while (nbFetched < int(count) && m_index < m_pin->mediaTypes().count()) {
//the caller will deallocate the memory
*out = static_cast<AM_MEDIA_TYPE *>(::CoTaskMemAlloc(sizeof(AM_MEDIA_TYPE)));
const AM_MEDIA_TYPE original = m_pin->mediaTypes().at(m_index);
@@ -145,9 +158,9 @@ namespace Phonon
QPin::QPin(QBaseFilter *parent, PIN_DIRECTION dir, const QVector<AM_MEDIA_TYPE> &mt) :
- m_parent(parent), m_flushing(false), m_refCount(1), m_connected(0),
- m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType),
- m_memAlloc(0)
+ m_memAlloc(0), m_parent(parent), m_refCount(1), m_connected(0),
+ m_direction(dir), m_mediaTypes(mt), m_connectedType(defaultMediaType()),
+ m_flushing(false)
{
Q_ASSERT(m_parent);
m_parent->addPin(this);
@@ -260,7 +273,7 @@ namespace Phonon
if (FAILED(hr)) {
setConnected(0);
- setConnectedType(defaultMediaType);
+ setConnectedType(defaultMediaType());
} else {
ComPointer<IMemInputPin> input(pin, IID_IMemInputPin);
if (input) {
@@ -302,8 +315,10 @@ namespace Phonon
}
setConnected(0);
- setConnectedType(defaultMediaType);
- setMemoryAllocator(0);
+ setConnectedType(defaultMediaType());
+ if (m_direction == PINDIR_INPUT) {
+ setMemoryAllocator(0);
+ }
return S_OK;
}
@@ -323,7 +338,7 @@ namespace Phonon
STDMETHODIMP QPin::ConnectionMediaType(AM_MEDIA_TYPE *type)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (!type) {
return E_POINTER;
}
@@ -338,6 +353,7 @@ namespace Phonon
STDMETHODIMP QPin::QueryPinInfo(PIN_INFO *info)
{
+ QReadLocker locker(&m_lock);
if (!info) {
return E_POINTER;
}
@@ -345,12 +361,14 @@ namespace Phonon
info->dir = m_direction;
info->pFilter = m_parent;
m_parent->AddRef();
- info->achName[0] = 0;
+ qMemCopy(info->achName, m_name.utf16(), qMin(MAX_FILTER_NAME, m_name.length()+1) *2);
+
return S_OK;
}
STDMETHODIMP QPin::QueryDirection(PIN_DIRECTION *dir)
{
+ QReadLocker locker(&m_lock);
if (!dir) {
return E_POINTER;
}
@@ -361,18 +379,20 @@ namespace Phonon
STDMETHODIMP QPin::QueryId(LPWSTR *id)
{
+ QReadLocker locker(&m_lock);
if (!id) {
return E_POINTER;
}
- *id = static_cast<LPWSTR>(::CoTaskMemAlloc(2));
- *id[0] = 0;
+ int nbBytes = (m_name.length()+1)*2;
+ *id = static_cast<LPWSTR>(::CoTaskMemAlloc(nbBytes));
+ qMemCopy(*id, m_name.utf16(), nbBytes);
return S_OK;
}
STDMETHODIMP QPin::QueryAccept(const AM_MEDIA_TYPE *type)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (!type) {
return E_POINTER;
}
@@ -419,7 +439,7 @@ namespace Phonon
STDMETHODIMP QPin::NewSegment(REFERENCE_TIME start, REFERENCE_TIME stop, double rate)
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (m_direction == PINDIR_OUTPUT && m_connected) {
//we deliver this downstream
m_connected->NewSegment(start, stop, rate);
@@ -436,8 +456,8 @@ namespace Phonon
HRESULT QPin::checkOutputMediaTypesConnection(IPin *pin)
{
- ComPointer<IEnumMediaTypes> emt;
- HRESULT hr = pin->EnumMediaTypes(emt.pparam());
+ IEnumMediaTypes *emt = 0;
+ HRESULT hr = pin->EnumMediaTypes(&emt);
if (hr != S_OK) {
return hr;
}
@@ -450,7 +470,7 @@ namespace Phonon
freeMediaType(type);
return S_OK;
} else {
- setConnectedType(defaultMediaType);
+ setConnectedType(defaultMediaType());
freeMediaType(type);
}
}
@@ -500,7 +520,7 @@ namespace Phonon
void QPin::setConnectedType(const AM_MEDIA_TYPE &type)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
//1st we free memory
freeMediaType(m_connectedType);
@@ -510,13 +530,13 @@ namespace Phonon
const AM_MEDIA_TYPE &QPin::connectedType() const
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
return m_connectedType;
}
void QPin::setConnected(IPin *pin)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
if (pin) {
pin->AddRef();
}
@@ -528,7 +548,7 @@ namespace Phonon
IPin *QPin::connected(bool addref) const
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (addref && m_connected) {
m_connected->AddRef();
}
@@ -537,12 +557,13 @@ namespace Phonon
bool QPin::isFlushing() const
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
return m_flushing;
}
FILTER_STATE QPin::filterState() const
{
+ QReadLocker locker(&m_lock);
FILTER_STATE fstate = State_Stopped;
m_parent->GetState(0, &fstate);
return fstate;
@@ -550,7 +571,7 @@ namespace Phonon
QVector<AM_MEDIA_TYPE> QPin::mediaTypes() const
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
return m_mediaTypes;
}
@@ -586,7 +607,7 @@ namespace Phonon
void QPin::setMemoryAllocator(IMemAllocator *alloc)
{
- QMutexLocker locker(&m_mutex);
+ QWriteLocker locker(&m_lock);
if (alloc) {
alloc->AddRef();
}
@@ -598,7 +619,7 @@ namespace Phonon
IMemAllocator *QPin::memoryAllocator(bool addref) const
{
- QMutexLocker locker(&m_mutex);
+ QReadLocker locker(&m_lock);
if (addref && m_memAlloc) {
m_memAlloc->AddRef();
}
diff --git a/src/3rdparty/phonon/ds9/qpin.h b/src/3rdparty/phonon/ds9/qpin.h
index 280ad61..a3287c4 100644
--- a/src/3rdparty/phonon/ds9/qpin.h
+++ b/src/3rdparty/phonon/ds9/qpin.h
@@ -22,7 +22,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <QtCore/QString>
#include <QtCore/QVector>
-#include <QtCore/QMutex>
+#include <QtCore/QReadWriteLock>
#include <dshow.h>
@@ -85,8 +85,8 @@ namespace Phonon
protected:
//this can be used by sub-classes
- mutable QMutex m_mutex;
- QBaseFilter * const m_parent;
+ mutable QReadWriteLock m_lock;
+ QBaseFilter *m_parent;
bool m_flushing;
private:
@@ -98,6 +98,7 @@ namespace Phonon
const PIN_DIRECTION m_direction;
QVector<AM_MEDIA_TYPE> m_mediaTypes; //accepted media types
AM_MEDIA_TYPE m_connectedType;
+ QString m_name;
IMemAllocator *m_memAlloc;
};
diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.cpp b/src/3rdparty/phonon/ds9/videorenderer_default.cpp
deleted file mode 100644
index 0045a49..0000000
--- a/src/3rdparty/phonon/ds9/videorenderer_default.cpp
+++ /dev/null
@@ -1,153 +0,0 @@
-/* This file is part of the KDE project.
-
-Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-
-This library is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 2.1 or 3 of the License.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-
-#include "videorenderer_default.h"
-
-#ifndef QT_NO_PHONON_VIDEO
-
-#include <QtGui/QWidget>
-#include <QtGui/QPainter>
-
-#include <uuids.h>
-
-QT_BEGIN_NAMESPACE
-
-
-namespace Phonon
-{
- namespace DS9
- {
- VideoRendererDefault::~VideoRendererDefault()
- {
- }
-
- bool VideoRendererDefault::isNative() const
- {
- return true;
- }
-
-
- VideoRendererDefault::VideoRendererDefault(QWidget *target) : m_target(target)
- {
- m_target->setAttribute(Qt::WA_PaintOnScreen, true);
- m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter);
- }
-
- QSize VideoRendererDefault::videoSize() const
- {
- LONG w = 0,
- h = 0;
- ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
- if (basic) {
- basic->GetVideoSize( &w, &h);
- }
- return QSize(w, h);
- }
-
- void VideoRendererDefault::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/)
- {
- //nothing to do here: the renderer paints everything
- }
-
- void VideoRendererDefault::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
- Phonon::VideoWidget::ScaleMode scaleMode)
- {
- if (!isActive()) {
- ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
- if (basic) {
- basic->SetDestinationPosition(0, 0, 0, 0);
- }
- return;
- }
-
- ComPointer<IVideoWindow> video(m_filter, IID_IVideoWindow);
-
- OAHWND owner;
- HRESULT hr = video->get_Owner(&owner);
- if (FAILED(hr)) {
- return;
- }
-
- const OAHWND newOwner = reinterpret_cast<OAHWND>(m_target->winId());
- if (owner != newOwner) {
- video->put_Owner(newOwner);
- video->put_MessageDrain(newOwner);
- video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
- }
-
- //make sure the widget takes the whole size of the parent
- video->SetWindowPosition(0, 0, size.width(), size.height());
-
- const QSize vsize = videoSize();
- internalNotifyResize(size, vsize, aspectRatio, scaleMode);
-
- ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
- if (basic) {
- basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight);
- }
- }
-
- void VideoRendererDefault::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/)
- {
- //this can't be supported for the default renderer
- }
-
- QImage VideoRendererDefault::snapshot() const
- {
- ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
- if (basic) {
- LONG bufferSize = 0;
- //1st we get the buffer size
- basic->GetCurrentImage(&bufferSize, 0);
-
- QByteArray buffer;
- buffer.resize(bufferSize);
- HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast<long*>(buffer.data()));
-
- if (SUCCEEDED(hr)) {
-
- const BITMAPINFOHEADER *bmi = reinterpret_cast<const BITMAPINFOHEADER*>(buffer.constData());
-
- const int w = qAbs(bmi->biWidth),
- h = qAbs(bmi->biHeight);
-
- // Create image and copy data into image.
- QImage ret(w, h, QImage::Format_RGB32);
-
- if (!ret.isNull()) {
- const char *data = buffer.constData() + bmi->biSize;
- const int bytes_per_line = w * sizeof(QRgb);
- for (int y = h - 1; y >= 0; --y) {
- qMemCopy(ret.scanLine(y), //destination
- data, //source
- bytes_per_line);
- data += bytes_per_line;
- }
- }
- return ret;
- }
- }
- return QImage();
- }
-
- }
-}
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/videorenderer_default.h b/src/3rdparty/phonon/ds9/videorenderer_default.h
deleted file mode 100644
index 43768d9..0000000
--- a/src/3rdparty/phonon/ds9/videorenderer_default.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* This file is part of the KDE project.
-
-Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-
-This library is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 2.1 or 3 of the License.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef PHONON_VIDEORENDERER_DEFAULT_H
-#define PHONON_VIDEORENDERER_DEFAULT_H
-
-#include "abstractvideorenderer.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_PHONON_VIDEO
-
-namespace Phonon
-{
- namespace DS9
- {
- class VideoRendererDefault : public AbstractVideoRenderer
- {
- public:
- VideoRendererDefault(QWidget *target);
- ~VideoRendererDefault();
-
- //Implementation from AbstractVideoRenderer
- void repaintCurrentFrame(QWidget *target, const QRect &rect);
- void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode);
- QSize videoSize() const;
- QImage snapshot() const;
- void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation);
- bool isNative() const;
- private:
- QWidget *m_target;
- };
- }
-}
-
-#endif //QT_NO_PHONON_VIDEO
-
-QT_END_NAMESPACE
-
-#endif
-
diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp b/src/3rdparty/phonon/ds9/videorenderer_evr.cpp
deleted file mode 100644
index d23d9ce..0000000
--- a/src/3rdparty/phonon/ds9/videorenderer_evr.cpp
+++ /dev/null
@@ -1,215 +0,0 @@
-/* This file is part of the KDE project.
-
-Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-
-This library is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 2.1 or 3 of the License.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-
-#include "videorenderer_evr.h"
-#include "qevr9.h"
-
-#ifndef QT_NO_PHONON_VIDEO
-
-#include <QtGui/QWidget>
-#include <QtGui/QPainter>
-
-QT_BEGIN_NAMESPACE
-
-namespace Phonon
-{
- namespace DS9
- {
- //we have to define them here because not all compilers/sdk have them
- static const GUID MR_VIDEO_RENDER_SERVICE = {0x1092a86c, 0xab1a, 0x459a, {0xa3, 0x36, 0x83, 0x1f, 0xbc, 0x4d, 0x11, 0xff} };
- static const GUID MR_VIDEO_MIXER_SERVICE = { 0x73cd2fc, 0x6cf4, 0x40b7, {0x88, 0x59, 0xe8, 0x95, 0x52, 0xc8, 0x41, 0xf8} };
- static const IID IID_IMFVideoDisplayControl = {0xa490b1e4, 0xab84, 0x4d31, {0xa1, 0xb2, 0x18, 0x1e, 0x03, 0xb1, 0x07, 0x7a} };
- static const IID IID_IMFVideoMixerControl = {0xA5C6C53F, 0xC202, 0x4aa5, {0x96, 0x95, 0x17, 0x5B, 0xA8, 0xC5, 0x08, 0xA5} };
- static const IID IID_IMFVideoProcessor = {0x6AB0000C, 0xFECE, 0x4d1f, {0xA2, 0xAC, 0xA9, 0x57, 0x35, 0x30, 0x65, 0x6E} };
- static const IID IID_IMFGetService = {0xFA993888, 0x4383, 0x415A, {0xA9, 0x30, 0xDD, 0x47, 0x2A, 0x8C, 0xF6, 0xF7} };
- static const GUID CLSID_EnhancedVideoRenderer = {0xfa10746c, 0x9b63, 0x4b6c, {0xbc, 0x49, 0xfc, 0x30, 0xe, 0xa5, 0xf2, 0x56} };
-
- template <typename T> ComPointer<T> getService(const Filter &filter, REFGUID guidService, REFIID riid)
- {
- //normally we should use IID_IMFGetService but this introduces another dependency
- //so here we simply define our own IId with the same value
- ComPointer<IMFGetService> getService(filter, IID_IMFGetService);
- Q_ASSERT(getService);
- T *ptr = 0;
- HRESULT hr = getService->GetService(guidService, riid, reinterpret_cast<void **>(&ptr));
- if (!SUCCEEDED(hr) || ptr == 0)
- Q_ASSERT(!SUCCEEDED(hr) && ptr != 0);
- ComPointer<T> service(ptr);
- return service;
- }
-
- VideoRendererEVR::~VideoRendererEVR()
- {
- }
-
- bool VideoRendererEVR::isNative() const
- {
- return true;
- }
-
- VideoRendererEVR::VideoRendererEVR(QWidget *target) : m_target(target)
- {
- m_filter = Filter(CLSID_EnhancedVideoRenderer, IID_IBaseFilter);
- if (!m_filter) {
- return;
- }
-
- ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
-
- filterControl->SetVideoWindow(reinterpret_cast<HWND>(target->winId()));
- filterControl->SetAspectRatioMode(MFVideoARMode_None); // We're in control of the size
- }
-
- QImage VideoRendererEVR::snapshot() const
- {
- // This will always capture black areas where no video is drawn, if any are present.
- // Due to the hack in notifyResize()
- ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
- if (filterControl) {
- BITMAPINFOHEADER bmi;
- BYTE *buffer = 0;
- DWORD bufferSize;
- LONGLONG timeStamp;
-
- bmi.biSize = sizeof(BITMAPINFOHEADER);
-
- HRESULT hr = filterControl->GetCurrentImage(&bmi, &buffer, &bufferSize, &timeStamp);
- if (SUCCEEDED(hr)) {
-
- const int w = qAbs(bmi.biWidth),
- h = qAbs(bmi.biHeight);
-
- // Create image and copy data into image.
- QImage ret(w, h, QImage::Format_RGB32);
-
- if (!ret.isNull()) {
- uchar *data = buffer;
- const int bytes_per_line = w * sizeof(QRgb);
- for (int y = h - 1; y >= 0; --y) {
- qMemCopy(ret.scanLine(y), //destination
- data, //source
- bytes_per_line);
- data += bytes_per_line;
- }
- }
- ::CoTaskMemFree(buffer);
- return ret;
- }
- }
- return QImage();
- }
-
- QSize VideoRendererEVR::videoSize() const
- {
- SIZE nativeSize;
- SIZE aspectRatioSize;
-
- ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
-
- filterControl->GetNativeVideoSize(&nativeSize, &aspectRatioSize);
-
- return QSize(nativeSize.cx, nativeSize.cy);
- }
-
- void VideoRendererEVR::repaintCurrentFrame(QWidget *target, const QRect &rect)
- {
- // repaint the video
- ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
- // All failed results can be safely ignored
- filterControl->RepaintVideo();
- }
-
- void VideoRendererEVR::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
- Phonon::VideoWidget::ScaleMode scaleMode)
- {
- if (!isActive()) {
- RECT dummyRect = { 0, 0, 0, 0};
- ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
- filterControl->SetVideoPosition(0, &dummyRect);
- return;
- }
-
- const QSize vsize = videoSize();
- internalNotifyResize(size, vsize, aspectRatio, scaleMode);
-
- RECT dstRectWin = { 0, 0, size.width(), size.height()};
-
- // Resize the Stream output rect instead of the destination rect.
- // Hacky workaround for flicker in the areas outside of the destination rect
- // This way these areas don't exist
- MFVideoNormalizedRect streamOutputRect = { float(m_dstX) / float(size.width()), float(m_dstY) / float(size.height()),
- float(m_dstWidth + m_dstX) / float(size.width()), float(m_dstHeight + m_dstY) / float(size.height())};
-
- ComPointer<IMFVideoMixerControl> filterMixer = getService<IMFVideoMixerControl>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoMixerControl);
- ComPointer<IMFVideoDisplayControl> filterControl = getService<IMFVideoDisplayControl>(m_filter, MR_VIDEO_RENDER_SERVICE, IID_IMFVideoDisplayControl);
-
- filterMixer->SetStreamOutputRect(0, &streamOutputRect);
- filterControl->SetVideoPosition(0, &dstRectWin);
- }
-
- void VideoRendererEVR::applyMixerSettings(qreal brightness, qreal contrast, qreal hue, qreal saturation)
- {
- InputPin sink = BackendNode::pins(m_filter, PINDIR_INPUT).first();
- OutputPin source;
- if (FAILED(sink->ConnectedTo(source.pparam()))) {
- return; //it must be connected to work
- }
-
- // Get the "Video Processor" (used for brightness/contrast/saturation/hue)
- ComPointer<IMFVideoProcessor> processor = getService<IMFVideoProcessor>(m_filter, MR_VIDEO_MIXER_SERVICE, IID_IMFVideoProcessor);
- Q_ASSERT(processor);
-
- DXVA2_ValueRange contrastRange;
- DXVA2_ValueRange brightnessRange;
- DXVA2_ValueRange saturationRange;
- DXVA2_ValueRange hueRange;
-
- if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Contrast, &contrastRange)))
- return;
- if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Brightness, &brightnessRange)))
- return;
- if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Saturation, &saturationRange)))
- return;
- if (FAILED(processor->GetProcAmpRange(DXVA2_ProcAmp_Hue, &hueRange)))
- return;
-
- DXVA2_ProcAmpValues values;
-
- values.Contrast = DXVA2FloatToFixed(((contrast < 0
- ? DXVA2FixedToFloat(contrastRange.MinValue) : DXVA2FixedToFloat(contrastRange.MaxValue))
- - DXVA2FixedToFloat(contrastRange.DefaultValue)) * qAbs(contrast) + DXVA2FixedToFloat(contrastRange.DefaultValue));
- values.Brightness = DXVA2FloatToFixed(((brightness < 0
- ? DXVA2FixedToFloat(brightnessRange.MinValue) : DXVA2FixedToFloat(brightnessRange.MaxValue))
- - DXVA2FixedToFloat(brightnessRange.DefaultValue)) * qAbs(brightness) + DXVA2FixedToFloat(brightnessRange.DefaultValue));
- values.Saturation = DXVA2FloatToFixed(((saturation < 0
- ? DXVA2FixedToFloat(saturationRange.MinValue) : DXVA2FixedToFloat(saturationRange.MaxValue))
- - DXVA2FixedToFloat(saturationRange.DefaultValue)) * qAbs(saturation) + DXVA2FixedToFloat(saturationRange.DefaultValue));
- values.Hue = DXVA2FloatToFixed(((hue < 0
- ? DXVA2FixedToFloat(hueRange.MinValue) : DXVA2FixedToFloat(hueRange.MaxValue))
- - DXVA2FixedToFloat(hueRange.DefaultValue)) * qAbs(hue) + DXVA2FixedToFloat(hueRange.DefaultValue));
-
- //finally set the settings
- processor->SetProcAmpValues(DXVA2_ProcAmp_Contrast | DXVA2_ProcAmp_Brightness | DXVA2_ProcAmp_Saturation | DXVA2_ProcAmp_Hue, &values);
-
- }
- }
-}
-
-QT_END_NAMESPACE
-
-#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/ds9/videorenderer_evr.h b/src/3rdparty/phonon/ds9/videorenderer_evr.h
deleted file mode 100644
index 229c36d..0000000
--- a/src/3rdparty/phonon/ds9/videorenderer_evr.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* This file is part of the KDE project.
-
-Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-
-This library is free software: you can redistribute it and/or modify
-it under the terms of the GNU Lesser General Public License as published by
-the Free Software Foundation, either version 2.1 or 3 of the License.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public License
-along with this library. If not, see <http://www.gnu.org/licenses/>.
-*/
-
-#ifndef PHONON_VIDEORENDERER_EVR_H
-#define PHONON_VIDEORENDERER_EVR_H
-
-#include "abstractvideorenderer.h"
-#include "compointer.h"
-
-QT_BEGIN_NAMESPACE
-
-#ifndef QT_NO_PHONON_VIDEO
-
-namespace Phonon
-{
- namespace DS9
- {
- class VideoRendererEVR : public AbstractVideoRenderer
- {
- public:
- VideoRendererEVR(QWidget *target);
- ~VideoRendererEVR();
-
- //Implementation from AbstractVideoRenderer
- void repaintCurrentFrame(QWidget *target, const QRect &rect);
- void notifyResize(const QSize&, Phonon::VideoWidget::AspectRatio, Phonon::VideoWidget::ScaleMode);
- QSize videoSize() const;
- QImage snapshot() const;
- void applyMixerSettings(qreal brightness, qreal contrast, qreal m_hue, qreal saturation);
- bool isNative() const;
- private:
- QWidget *m_target;
- };
- }
-}
-
-#endif //QT_NO_PHONON_VIDEO
-
-QT_END_NAMESPACE
-
-#endif
-
diff --git a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp
index 9c7993c..491d1bd 100644
--- a/src/3rdparty/phonon/ds9/videorenderer_soft.cpp
+++ b/src/3rdparty/phonon/ds9/videorenderer_soft.cpp
@@ -194,8 +194,8 @@ namespace Phonon
m_sampleBuffer = ComPointer<IMediaSample>();
#ifndef QT_NO_OPENGL
freeGLResources();
- m_textureUploaded = false;
#endif // QT_NO_OPENGL
+ m_textureUploaded = false;
}
void endOfStream()
@@ -314,6 +314,7 @@ namespace Phonon
REFERENCE_TIME m_start;
HANDLE m_renderEvent, m_receiveCanWait; // Signals sample to render
QSize m_size;
+ bool m_textureUploaded;
//mixer settings
qreal m_brightness,
@@ -355,7 +356,6 @@ namespace Phonon
bool m_checkedPrograms;
bool m_usingOpenGL;
- bool m_textureUploaded;
GLuint m_program[2];
GLuint m_texture[3];
#endif
@@ -365,7 +365,7 @@ namespace Phonon
{
public:
VideoRendererSoftPin(VideoRendererSoftFilter *parent) :
- QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/, 0),
+ QMemInputPin(parent, videoMediaTypes(), false /*no transformation of the samples*/),
m_renderer(parent)
{
}
@@ -436,7 +436,7 @@ namespace Phonon
QBaseFilter(CLSID_NULL), m_inputPin(new VideoRendererSoftPin(this)),
m_renderer(renderer), m_start(0)
#ifndef QT_NO_OPENGL
- , m_checkedPrograms(false), m_usingOpenGL(false), m_textureUploaded(false)
+ ,m_usingOpenGL(false), m_checkedPrograms(false), m_textureUploaded(false)
#endif
{
m_renderEvent = ::CreateEvent(0, 0, 0, 0);
@@ -661,10 +661,7 @@ namespace Phonon
#ifndef QT_NO_OPENGL
- if (painter.paintEngine() &&
- (painter.paintEngine()->type() == QPaintEngine::OpenGL || painter.paintEngine()->type() == QPaintEngine::OpenGL2)
- && checkGLPrograms()) {
-
+ if (painter.paintEngine() && painter.paintEngine()->type() == QPaintEngine::OpenGL && checkGLPrograms()) {
//for now we only support YUV (both YV12 and YUY2)
updateTexture();
@@ -676,7 +673,6 @@ namespace Phonon
}
//let's draw the texture
- painter.beginNativePainting();
//Let's pass the other arguments
const Program prog = (m_inputPin->connectedType().subtype == MEDIASUBTYPE_YV12) ? YV12toRGB : YUY2toRGB;
@@ -726,7 +722,6 @@ namespace Phonon
glDisableClientState(GL_VERTEX_ARRAY);
glDisable(GL_FRAGMENT_PROGRAM_ARB);
- painter.endNativePainting();
return;
} else
#endif
diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp
index 545b31e..298e9fa 100644
--- a/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp
+++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.cpp
@@ -22,9 +22,14 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include <QtGui/QWidget>
#include <QtGui/QPainter>
+#include <QtCore/QTimerEvent>
+#ifndef Q_OS_WINCE
#include <d3d9.h>
#include <vmr9.h>
+#else
+#include <uuids.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -43,10 +48,116 @@ namespace Phonon
}
+#ifdef Q_OS_WINCE
+ VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target)
+ {
+ m_target->setAttribute(Qt::WA_PaintOnScreen, true);
+ m_filter = Filter(CLSID_VideoRenderer, IID_IBaseFilter);
+ }
+
+ QSize VideoRendererVMR9::videoSize() const
+ {
+ LONG w = 0,
+ h = 0;
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->GetVideoSize( &w, &h);
+ }
+ return QSize(w, h);
+ }
+
+ void VideoRendererVMR9::repaintCurrentFrame(QWidget * /*target*/, const QRect & /*rect*/)
+ {
+ //nothing to do here: the renderer paints everything
+ }
+
+ void VideoRendererVMR9::notifyResize(const QSize &size, Phonon::VideoWidget::AspectRatio aspectRatio,
+ Phonon::VideoWidget::ScaleMode scaleMode)
+ {
+ if (!isActive()) {
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->SetDestinationPosition(0, 0, 0, 0);
+ }
+ return;
+ }
+
+ ComPointer<IVideoWindow> video(m_filter, IID_IVideoWindow);
+
+ OAHWND owner;
+ HRESULT hr = video->get_Owner(&owner);
+ if (FAILED(hr)) {
+ return;
+ }
+
+ const OAHWND newOwner = reinterpret_cast<OAHWND>(m_target->winId());
+ if (owner != newOwner) {
+ video->put_Owner(newOwner);
+ video->put_MessageDrain(newOwner);
+ video->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS);
+ }
+
+ //make sure the widget takes the whole size of the parent
+ video->SetWindowPosition(0, 0, size.width(), size.height());
+
+ const QSize vsize = videoSize();
+ internalNotifyResize(size, vsize, aspectRatio, scaleMode);
+
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ basic->SetDestinationPosition(m_dstX, m_dstY, m_dstWidth, m_dstHeight);
+ }
+ }
+
+ void VideoRendererVMR9::applyMixerSettings(qreal /*brightness*/, qreal /*contrast*/, qreal /*m_hue*/, qreal /*saturation*/)
+ {
+ //this can't be supported for WinCE
+ }
+
+ QImage VideoRendererVMR9::snapshot() const
+ {
+ ComPointer<IBasicVideo> basic(m_filter, IID_IBasicVideo);
+ if (basic) {
+ LONG bufferSize = 0;
+ //1st we get the buffer size
+ basic->GetCurrentImage(&bufferSize, 0);
+
+ QByteArray buffer;
+ buffer.resize(bufferSize);
+ HRESULT hr = basic->GetCurrentImage(&bufferSize, reinterpret_cast<long*>(buffer.data()));
+
+ if (SUCCEEDED(hr)) {
+
+ const BITMAPINFOHEADER *bmi = reinterpret_cast<const BITMAPINFOHEADER*>(buffer.constData());
+
+ const int w = qAbs(bmi->biWidth),
+ h = qAbs(bmi->biHeight);
+
+ // Create image and copy data into image.
+ QImage ret(w, h, QImage::Format_RGB32);
+
+ if (!ret.isNull()) {
+ const char *data = buffer.constData() + bmi->biSize;
+ const int bytes_per_line = w * sizeof(QRgb);
+ for (int y = h - 1; y >= 0; --y) {
+ qMemCopy(ret.scanLine(y), //destination
+ data, //source
+ bytes_per_line);
+ data += bytes_per_line;
+ }
+ }
+ return ret;
+ }
+ }
+ return QImage();
+ }
+
+#else
VideoRendererVMR9::VideoRendererVMR9(QWidget *target) : m_target(target)
{
m_filter = Filter(CLSID_VideoMixingRenderer9, IID_IBaseFilter);
if (!m_filter) {
+ qWarning("the video widget could not be initialized correctly");
return;
}
@@ -58,7 +169,6 @@ namespace Phonon
Q_ASSERT(SUCCEEDED(hr));
ComPointer<IVMRWindowlessControl9> windowlessControl(m_filter, IID_IVMRWindowlessControl9);
windowlessControl->SetVideoClippingWindow(reinterpret_cast<HWND>(target->winId()));
- windowlessControl->SetAspectRatioMode(VMR9ARMode_None); //we're in control of the size
}
QImage VideoRendererVMR9::snapshot() const
@@ -214,6 +324,7 @@ namespace Phonon
//finally set the settings
mixer->SetProcAmpControl(0, &ctrl);
}
+#endif
}
}
diff --git a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h
index 516d79d..4eb237e 100644
--- a/src/3rdparty/phonon/ds9/videorenderer_vmr9.h
+++ b/src/3rdparty/phonon/ds9/videorenderer_vmr9.h
@@ -19,6 +19,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#define PHONON_VIDEORENDERER_VMR9_H
#include "abstractvideorenderer.h"
+#include "compointer.h"
QT_BEGIN_NAMESPACE
diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp
index 09d42a4..de7ce5f 100644
--- a/src/3rdparty/phonon/ds9/videowidget.cpp
+++ b/src/3rdparty/phonon/ds9/videowidget.cpp
@@ -24,12 +24,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>.
#include "mediaobject.h"
-#ifndef Q_OS_WINCE
-#include "videorenderer_evr.h"
#include "videorenderer_vmr9.h"
-#else
-#include "videorenderer_default.h"
-#endif
#include "videorenderer_soft.h"
QT_BEGIN_NAMESPACE
@@ -89,19 +84,7 @@ namespace Phonon
void setCurrentRenderer(AbstractVideoRenderer *renderer)
{
m_currentRenderer = renderer;
- //we disallow repaint on that widget for just a fraction of second
- //this allows better transition between videos
- setUpdatesEnabled(false);
- m_flickerFreeTimer.start(20, this);
- }
-
- void timerEvent(QTimerEvent *e)
- {
- if (e->timerId() == m_flickerFreeTimer.timerId()) {
- m_flickerFreeTimer.stop();
- setUpdatesEnabled(true);
- }
- QWidget::timerEvent(e);
+ update();
}
QSize sizeHint() const
@@ -123,8 +106,6 @@ namespace Phonon
void paintEvent(QPaintEvent *e)
{
- if (!updatesEnabled())
- return; //this avoids repaint from native events
checkCurrentRenderingMode();
m_currentRenderer->repaintCurrentFrame(this, e->rect());
}
@@ -172,14 +153,13 @@ namespace Phonon
}
} else if (!isEmbedded()) {
m_currentRenderer = m_node->switchRendering(m_currentRenderer);
- setAttribute(Qt::WA_PaintOnScreen, false);
+ setAttribute(Qt::WA_PaintOnScreen, true);
}
}
VideoWidget *m_node;
AbstractVideoRenderer *m_currentRenderer;
QVariant m_restoreScreenSaverActive;
- QBasicTimer m_flickerFreeTimer;
};
VideoWidget::VideoWidget(QWidget *parent)
@@ -223,9 +203,6 @@ namespace Phonon
if (toNative && m_noNativeRendererSupported)
return current; //no switch here
- if (!mediaObject())
- return current;
-
//firt we delete the renderer
//initialization of the widgets
for(int i = 0; i < FILTER_COUNT; ++i) {
@@ -284,7 +261,6 @@ namespace Phonon
{
m_aspectRatio = aspectRatio;
updateVideoSize();
- m_widget->update();
}
Phonon::VideoWidget::ScaleMode VideoWidget::scaleMode() const
@@ -303,7 +279,6 @@ namespace Phonon
{
m_scaleMode = scaleMode;
updateVideoSize();
- m_widget->update();
}
void VideoWidget::setBrightness(qreal b)
@@ -357,29 +332,14 @@ namespace Phonon
int index = graphIndex * 2 + type;
if (m_renderers[index] == 0 && autoCreate) {
AbstractVideoRenderer *renderer = 0;
- if (type == Native) {
-#ifndef Q_OS_WINCE
- renderer = new VideoRendererEVR(m_widget);
- if (renderer->getFilter() == 0) {
- delete renderer;
- //EVR not present, let's try VMR
- renderer = new VideoRendererVMR9(m_widget);
- if (renderer->getFilter() == 0) {
- //instanciating the renderer might fail
- m_noNativeRendererSupported = true;
- delete renderer;
- renderer = 0;
- }
- }
-#else
- renderer = new VideoRendererDefault(m_widget);
+ if (type == Native) {
+ renderer = new VideoRendererVMR9(m_widget);
if (renderer->getFilter() == 0) {
- //instanciating the renderer might fail
+ //instanciating the renderer might fail with error VFW_E_DDRAW_CAPS_NOT_SUITABLE (0x80040273)
m_noNativeRendererSupported = true;
delete renderer;
renderer = 0;
}
-#endif
}
if (renderer == 0) {
diff --git a/src/3rdparty/phonon/ds9/volumeeffect.cpp b/src/3rdparty/phonon/ds9/volumeeffect.cpp
index a93b074..b9a5fce 100644
--- a/src/3rdparty/phonon/ds9/volumeeffect.cpp
+++ b/src/3rdparty/phonon/ds9/volumeeffect.cpp
@@ -76,7 +76,7 @@ namespace Phonon
class VolumeMemInputPin : public QMemInputPin
{
public:
- VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt, QPin *output) : QMemInputPin(parent, mt, true /*transform*/, output)
+ VolumeMemInputPin(QBaseFilter *parent, const QVector<AM_MEDIA_TYPE> &mt) : QMemInputPin(parent, mt, true /*transform*/)
{
}
@@ -139,7 +139,8 @@ namespace Phonon
//then creating the input
mt << audioMediaType();
- m_input = new VolumeMemInputPin(this, mt, m_output);
+ m_input = new VolumeMemInputPin(this, mt);
+ m_input->addOutput(m_output); //make the connection here
}
void VolumeEffectFilter::treatOneSamplePerChannel(BYTE **buffer, int sampleSize, int channelCount, int frequency)
diff --git a/src/3rdparty/phonon/ds9/volumeeffect.h b/src/3rdparty/phonon/ds9/volumeeffect.h
index d1b0186..39b20d0 100644
--- a/src/3rdparty/phonon/ds9/volumeeffect.h
+++ b/src/3rdparty/phonon/ds9/volumeeffect.h
@@ -47,7 +47,7 @@ namespace Phonon
private:
float m_volume;
- //paramaters used to fade
+ //parameters used to fade
Phonon::VolumeFaderEffect::FadeCurve m_fadeCurve;
bool m_fading; //determines if we should be fading.
diff --git a/src/3rdparty/phonon/gstreamer/CMakeLists.txt b/src/3rdparty/phonon/gstreamer/CMakeLists.txt
index 08f892a..2249ac3 100644
--- a/src/3rdparty/phonon/gstreamer/CMakeLists.txt
+++ b/src/3rdparty/phonon/gstreamer/CMakeLists.txt
@@ -19,7 +19,7 @@ include(ConfigureChecks.cmake)
if (BUILD_PHONON_GSTREAMER)
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
- ${GSTREAMER_INCLUDE_DIR}
+ ${GSTREAMER_INCLUDE_DIR}
${GLIB2_INCLUDE_DIR}
${LIBXML2_INCLUDE_DIR}
${X11_X11_INCLUDE_PATH})
@@ -34,7 +34,6 @@ if (BUILD_PHONON_GSTREAMER)
set(phonon_gstreamer_SRCS
audiooutput.cpp
- artssink.cpp
backend.cpp
devicemanager.cpp
effectmanager.cpp
@@ -50,14 +49,20 @@ if (BUILD_PHONON_GSTREAMER)
message.cpp
audioeffect.cpp
abstractrenderer.cpp
- x11renderer.cpp
widgetrenderer.cpp
glrenderer.cpp
volumefadereffect.cpp
+ audiodataoutput.cpp
)
- find_package(Alsa)
- macro_ensure_version("0.10.22" ${GSTREAMER_VERSION} GSTREAMER_HAS_NONBLOCKING_ALSASINK)
+ if(NOT WIN32)
+ set(phonon_gstreamer_SRCS
+ ${phonon_gstreamer_SRCS}
+ artssink.cpp
+ x11renderer.cpp)
+ macro_optional_find_package(Alsa)
+ macro_ensure_version("0.10.22" ${GSTREAMER_VERSION} GSTREAMER_HAS_NONBLOCKING_ALSASINK)
+ endif(NOT WIN32)
if(ALSA_FOUND AND NOT GSTREAMER_HAS_NONBLOCKING_ALSASINK)
add_definitions(-DUSE_ALSASINK2)
include_directories(${ALSA_INCLUDES})
@@ -78,6 +83,9 @@ if (BUILD_PHONON_GSTREAMER)
if(ALSA_FOUND)
target_link_libraries(phonon_gstreamer ${ASOUND_LIBRARY})
endif(ALSA_FOUND)
+ if(USE_INSTALL_PLUGIN)
+ target_link_libraries(phonon_gstreamer ${GSTREAMER_PLUGIN_PBUTILS_LIBRARIES})
+ endif(USE_INSTALL_PLUGIN)
install(TARGETS phonon_gstreamer DESTINATION ${PLUGIN_INSTALL_DIR}/plugins/phonon_backend)
install(FILES gstreamer.desktop DESTINATION ${SERVICES_INSTALL_DIR}/phononbackends)
diff --git a/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake b/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake
index f2922e1..eaf5b99 100644
--- a/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake
+++ b/src/3rdparty/phonon/gstreamer/ConfigureChecks.cmake
@@ -17,6 +17,7 @@ macro_log_feature(GSTREAMER_FOUND "GStreamer" "gstreamer 0.10 is required for th
macro_optional_find_package(GStreamerPlugins)
macro_log_feature(GSTREAMER_PLUGIN_VIDEO_LIBRARIES "GStreamer video plugin" "The gstreamer video plugin (part of gstreamer-plugins-base 0.10) is required for the multimedia gstreamer backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10")
+macro_log_feature(GSTREAMER_PLUGIN_AUDIO_LIBRARIES "GStreamer audio plugin" "The gstreamer audio plugin (part of gstreamer-plugins-base 0.10) is required for the multimedia gstreamer backend" "http://gstreamer.freedesktop.org/modules/" FALSE "0.10")
macro_optional_find_package(GLIB2)
macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the gstreamer backend for Phonon" "http://www.gtk.org/download/" FALSE)
@@ -30,8 +31,8 @@ macro_log_feature(LIBXML2_FOUND "LibXml2" "LibXml2 is required to compile the gs
macro_optional_find_package(OpenGL)
macro_log_feature(OPENGL_FOUND "OpenGL" "OpenGL support is required to compile the gstreamer backend for Phonon" "" FALSE)
-if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
+if (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
set(BUILD_PHONON_GSTREAMER TRUE)
-else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
+else (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
set(BUILD_PHONON_GSTREAMER FALSE)
-endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
+endif (GSTREAMER_FOUND AND GSTREAMER_PLUGIN_VIDEO_LIBRARIES AND GSTREAMER_PLUGIN_AUDIO_LIBRARIES AND GLIB2_FOUND AND GOBJECT_FOUND AND LIBXML2_FOUND AND OPENGL_FOUND)
diff --git a/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp b/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp
new file mode 100644
index 0000000..30dabdf
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audiodataoutput.cpp
@@ -0,0 +1,143 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "audiodataoutput.h"
+#include "gsthelper.h"
+#include "medianode.h"
+#include "mediaobject.h"
+#include <QtCore/QVector>
+#include <QtCore/QMap>
+#include <phonon/audiooutput.h>
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+AudioDataOutput::AudioDataOutput(Backend *backend, QObject *parent)
+ : QObject(parent),
+ MediaNode(backend, AudioSink | AudioSource)
+{
+ static int count = 0;
+ m_name = "AudioDataOutput" + QString::number(count++);
+
+ m_queue = gst_element_factory_make ("identity", NULL);
+ gst_object_ref(m_queue);
+ m_isValid = true;
+}
+
+AudioDataOutput::~AudioDataOutput()
+{
+ gst_element_set_state(m_queue, GST_STATE_NULL);
+ gst_object_unref(m_queue);
+}
+
+int AudioDataOutput::dataSize() const
+{
+ return m_dataSize;
+}
+
+int AudioDataOutput::sampleRate() const
+{
+ return 44100;
+}
+
+void AudioDataOutput::setDataSize(int size)
+{
+ m_dataSize = size;
+}
+
+typedef QMap<Phonon::AudioDataOutput::Channel, QVector<float> > FloatMap;
+typedef QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > IntMap;
+
+inline void AudioDataOutput::convertAndEmit(const QVector<qint16> &leftBuffer, const QVector<qint16> &rightBuffer)
+{
+ //TODO: Floats
+ IntMap map;
+ map.insert(Phonon::AudioDataOutput::LeftChannel, leftBuffer);
+ map.insert(Phonon::AudioDataOutput::RightChannel, rightBuffer);
+ emit dataReady(map);
+}
+
+void AudioDataOutput::processBuffer(GstPad*, GstBuffer* buffer, gpointer gThat)
+{
+ // TODO emit endOfMedia
+ AudioDataOutput *that = reinterpret_cast<AudioDataOutput*>(gThat);
+
+ // determine the number of channels
+ GstStructure* structure = gst_caps_get_structure (GST_BUFFER_CAPS(buffer), 0);
+ gst_structure_get_int (structure, "channels", &that->m_channels);
+
+ if (that->m_channels > 2 || that->m_channels < 0) {
+ qWarning() << Q_FUNC_INFO << ": Number of channels not supported: " << that->m_channels;
+ return;
+ }
+
+ gint16 *data = reinterpret_cast<gint16*>(GST_BUFFER_DATA(buffer));
+ guint size = GST_BUFFER_SIZE(buffer) / sizeof(gint16);
+
+ that->m_pendingData.reserve(that->m_pendingData.size() + size);
+
+ for (uint i=0; i<size; i++) {
+ // 8 bit? interleaved? yay for lacking documentation!
+ that->m_pendingData.append(data[i]);
+ }
+
+ while (that->m_pendingData.size() > that->m_dataSize * that->m_channels) {
+ if (that->m_channels == 1) {
+ QVector<qint16> intBuffer(that->m_dataSize);
+ memcpy(intBuffer.data(), that->m_pendingData.constData(), that->m_dataSize * sizeof(qint16));
+
+ that->convertAndEmit(intBuffer, intBuffer);
+ int newSize = that->m_pendingData.size() - that->m_dataSize;
+ memmove(that->m_pendingData.data(), that->m_pendingData.constData() + that->m_dataSize, newSize * sizeof(qint16));
+ that->m_pendingData.resize(newSize);
+ } else {
+ QVector<qint16> left(that->m_dataSize), right(that->m_dataSize);
+ for (int i=0; i<that->m_dataSize; i++) {
+ left[i] = that->m_pendingData[i*2];
+ right[i] = that->m_pendingData[i*2+1];
+ }
+ that->m_pendingData.resize(that->m_pendingData.size() - that->m_dataSize*2);
+ that->convertAndEmit(left, right);
+ }
+ }
+}
+
+void AudioDataOutput::mediaNodeEvent(const MediaNodeEvent *event)
+{
+ if (event->type() == MediaNodeEvent::MediaObjectConnected && root()) {
+ g_object_set(G_OBJECT(audioElement()), "sync", true, (const char*)NULL);
+ GstPad *audiopad = gst_element_get_pad (audioElement(), "src");
+ gst_pad_add_buffer_probe (audiopad, G_CALLBACK(processBuffer), this);
+ gst_object_unref (audiopad);
+ return;
+ }
+
+ MediaNode::mediaNodeEvent(event);
+}
+
+}} //namespace Phonon::Gstreamer
+
+#include "moc_audiodataoutput.cpp"
+// vim: sw=4 ts=4
+
diff --git a/src/3rdparty/phonon/gstreamer/audiodataoutput.h b/src/3rdparty/phonon/gstreamer/audiodataoutput.h
new file mode 100644
index 0000000..5e30a1d
--- /dev/null
+++ b/src/3rdparty/phonon/gstreamer/audiodataoutput.h
@@ -0,0 +1,84 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+ Copyright (C) 2009 Martin Sandsmark <sandsmark@samfundet.no>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef Phonon_GSTREAMER_AUDIODATAOUTPUT_H
+#define Phonon_GSTREAMER_AUDIODATAOUTPUT_H
+
+#include "abstractaudiooutput.h"
+#include "backend.h"
+#include "medianode.h"
+#include <phonon/audiodataoutput.h>
+#include <phonon/audiodataoutputinterface.h>
+
+namespace Phonon
+{
+namespace Gstreamer
+{
+ /**
+ * \author Martin Sandsmark <sandsmark@samfundet.no>
+ */
+ class AudioDataOutput : public QObject,
+ public AudioDataOutputInterface,
+ public MediaNode
+ {
+ Q_OBJECT
+ Q_INTERFACES(Phonon::AudioDataOutputInterface Phonon::Gstreamer::MediaNode)
+
+ public:
+ AudioDataOutput(Backend *, QObject *);
+ ~AudioDataOutput();
+
+ public Q_SLOTS:
+ int dataSize() const;
+ int sampleRate() const;
+ void setDataSize(int size);
+
+ public:
+ /// callback function for handling new audio data
+ static void processBuffer(GstPad*, GstBuffer*, gpointer);
+
+ Phonon::AudioDataOutput* frontendObject() const { return m_frontend; }
+ void setFrontendObject(Phonon::AudioDataOutput *frontend) { m_frontend = frontend; }
+
+ GstElement *audioElement() { return m_queue; }
+
+ void mediaNodeEvent(const MediaNodeEvent *event);
+
+
+ signals:
+ void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &data);
+ void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<float> > &data);
+ void endOfMedia(int remainingSamples);
+
+ private:
+ void convertAndEmit(const QVector<qint16>&, const QVector<qint16>&);
+
+ GstElement *m_queue;
+ int m_dataSize;
+ QVector<qint16> m_pendingData;
+ Phonon::AudioDataOutput *m_frontend;
+ int m_channels;
+ };
+}} //namespace Phonon::Gstreamer
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_FAKE_AUDIODATAOUTPUT_H
diff --git a/src/3rdparty/phonon/gstreamer/audiooutput.cpp b/src/3rdparty/phonon/gstreamer/audiooutput.cpp
index 641ff6b..f3137b2 100644
--- a/src/3rdparty/phonon/gstreamer/audiooutput.cpp
+++ b/src/3rdparty/phonon/gstreamer/audiooutput.cpp
@@ -125,6 +125,7 @@ void AudioOutput::setVolume(qreal newVolume)
bool AudioOutput::setOutputDevice(int newDevice)
{
m_backend->logMessage(Q_FUNC_INFO + QString::number(newDevice), Backend::Info, this);
+
if (newDevice == m_device)
return true;
@@ -135,20 +136,11 @@ bool AudioOutput::setOutputDevice(int newDevice)
}
bool success = false;
- const QList<AudioDevice> deviceList = m_backend->deviceManager()->audioOutputDevices();
- int deviceIdx = -1;
- for (int i=0; i<deviceList.size(); i++) {
- if (deviceList.at(i).id == newDevice) {
- deviceIdx = i;
- break;
- }
- }
-
- if (m_audioSink && deviceIdx >= 0) {
+ if (m_audioSink && newDevice >= 0) {
// Save previous state
GstState oldState = GST_STATE(m_audioSink);
const QByteArray oldDeviceValue = GstHelper::property(m_audioSink, "device");
- const QByteArray deviceId = deviceList.at(deviceIdx).gstId;
+ const QByteArray deviceId = m_backend->deviceManager()->gstId(newDevice);
m_device = newDevice;
// We test if the device can be opened by checking if it can go from NULL to READY state
@@ -170,7 +162,7 @@ bool AudioOutput::setOutputDevice(int newDevice)
deviceId, Backend::Info, this);
}
- // Note the stopped state should not really be neccessary, but seems to be required to
+ // Note the stopped state should not really be necessary, but seems to be required to
// properly reset after changing the audio state
if (root()) {
QMetaObject::invokeMethod(root(), "setState", Qt::QueuedConnection, Q_ARG(State, StoppedState));
diff --git a/src/3rdparty/phonon/gstreamer/backend.cpp b/src/3rdparty/phonon/gstreamer/backend.cpp
index dab6f35..729a1d3 100644
--- a/src/3rdparty/phonon/gstreamer/backend.cpp
+++ b/src/3rdparty/phonon/gstreamer/backend.cpp
@@ -18,6 +18,7 @@
#include "common.h"
#include "backend.h"
#include "audiooutput.h"
+#include "audiodataoutput.h"
#include "audioeffect.h"
#include "mediaobject.h"
#include "videowidget.h"
@@ -26,6 +27,7 @@
#include "message.h"
#include "volumefadereffect.h"
#include <gst/interfaces/propertyprobe.h>
+#include <phonon/pulsesupport.h>
#include <QtCore/QSet>
#include <QtCore/QVariant>
@@ -49,13 +51,17 @@ Backend::Backend(QObject *parent, const QVariantList &)
, m_debugLevel(Warning)
, m_isValid(false)
{
+ // Initialise PulseAudio support
+ PulseSupport *pulse = PulseSupport::getInstance();
+ pulse->enable();
+ connect(pulse, SIGNAL(objectDescriptionChanged(ObjectDescriptionType)), SIGNAL(objectDescriptionChanged(ObjectDescriptionType)));
+
// In order to support reloading, we only set the app name once...
static bool first = true;
if (first) {
first = false;
g_set_application_name(qApp->applicationName().toUtf8());
}
-
GError *err = 0;
bool wasInit = gst_init_check(0, 0, &err); //init gstreamer: must be called before any gst-related functions
if (err)
@@ -92,6 +98,9 @@ Backend::Backend(QObject *parent, const QVariantList &)
Backend::~Backend()
{
+ delete m_effectManager;
+ delete m_deviceManager;
+ PulseSupport::shutdown();
}
gboolean Backend::busCall(GstBus *bus, GstMessage *msg, gpointer data)
@@ -119,18 +128,15 @@ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const
case MediaObjectClass:
return new MediaObject(this, parent);
- case AudioOutputClass: {
- AudioOutput *ao = new AudioOutput(this, parent);
- m_audioOutputs.append(ao);
- return ao;
- }
+ case AudioOutputClass:
+ return new AudioOutput(this, parent);
+
#ifndef QT_NO_PHONON_EFFECT
case EffectClass:
return new AudioEffect(this, args[0].toInt(), parent);
#endif //QT_NO_PHONON_EFFECT
case AudioDataOutputClass:
- logMessage("createObject() : AudioDataOutput not implemented");
- break;
+ return new AudioDataOutput(this, parent);
#ifndef QT_NO_PHONON_VIDEO
case VideoDataOutputClass:
@@ -214,14 +220,14 @@ QStringList Backend::availableMimeTypes() const
GstPluginFeature *feature = GST_PLUGIN_FEATURE(iter->data);
QString klass = gst_element_factory_get_klass(GST_ELEMENT_FACTORY(feature));
- if (klass == QLatin1String("Codec/Decoder") ||
- klass == QLatin1String("Codec/Decoder/Audio") ||
- klass == QLatin1String("Codec/Decoder/Video") ||
- klass == QLatin1String("Codec/Demuxer") ||
- klass == QLatin1String("Codec/Demuxer/Audio") ||
- klass == QLatin1String("Codec/Demuxer/Video") ||
- klass == QLatin1String("Codec/Parser") ||
- klass == QLatin1String("Codec/Parser/Audio") ||
+ if (klass == QLatin1String("Codec/Decoder") ||
+ klass == QLatin1String("Codec/Decoder/Audio") ||
+ klass == QLatin1String("Codec/Decoder/Video") ||
+ klass == QLatin1String("Codec/Demuxer") ||
+ klass == QLatin1String("Codec/Demuxer/Audio") ||
+ klass == QLatin1String("Codec/Demuxer/Video") ||
+ klass == QLatin1String("Codec/Parser") ||
+ klass == QLatin1String("Codec/Parser/Audio") ||
klass == QLatin1String("Codec/Parser/Video")) {
const GList *static_templates;
@@ -234,16 +240,28 @@ QStringList Backend::availableMimeTypes() const
GstCaps *caps = gst_static_pad_template_get_caps (padTemplate);
if (caps) {
- const GstStructure* capsStruct = gst_caps_get_structure (caps, 0);
- QString mime = QString::fromUtf8(gst_structure_get_name (capsStruct));
- if (!availableMimeTypes.contains(mime))
- availableMimeTypes.append(mime);
+ for (unsigned int struct_idx = 0; struct_idx < gst_caps_get_size (caps); struct_idx++) {
+
+ const GstStructure* capsStruct = gst_caps_get_structure (caps, struct_idx);
+ QString mime = QString::fromUtf8(gst_structure_get_name (capsStruct));
+ if (!availableMimeTypes.contains(mime))
+ availableMimeTypes.append(mime);
+ }
}
}
}
}
}
g_list_free(factoryList);
+ if (availableMimeTypes.contains("audio/x-vorbis")
+ && availableMimeTypes.contains("application/x-ogm-audio")) {
+ if (!availableMimeTypes.contains("audio/x-vorbis+ogg"))
+ availableMimeTypes.append("audio/x-vorbis+ogg");
+ if (!availableMimeTypes.contains("application/ogg")) /* *.ogg */
+ availableMimeTypes.append("application/ogg");
+ if (!availableMimeTypes.contains("audio/ogg")) /* *.oga */
+ availableMimeTypes.append("audio/ogg");
+ }
availableMimeTypes.sort();
return availableMimeTypes;
}
@@ -293,14 +311,11 @@ QHash<QByteArray, QVariant> Backend::objectDescriptionProperties(ObjectDescripti
switch (type) {
case Phonon::AudioOutputDeviceType: {
- QList<AudioDevice> audioDevices = deviceManager()->audioOutputDevices();
- foreach(const AudioDevice &device, audioDevices) {
- if (device.id == index) {
- ret.insert("name", device.gstId);
- ret.insert("description", device.description);
- ret.insert("icon", QLatin1String("audio-card"));
- break;
- }
+ AudioDevice* ad;
+ if ((ad = deviceManager()->audioDevice(index))) {
+ ret.insert("name", ad->gstId);
+ ret.insert("description", ad->description);
+ ret.insert("icon", ad->icon);
}
}
break;
@@ -429,7 +444,7 @@ EffectManager* Backend::effectManager() const
/**
* Returns a debuglevel that is determined by the
- * PHONON_GSTREAMER_DEBUG environment variable.
+ * PHONON_GST_DEBUG environment variable.
*
* Warning - important warnings
* Info - general info
diff --git a/src/3rdparty/phonon/gstreamer/backend.h b/src/3rdparty/phonon/gstreamer/backend.h
index 2aab6fa..d157f11 100644
--- a/src/3rdparty/phonon/gstreamer/backend.h
+++ b/src/3rdparty/phonon/gstreamer/backend.h
@@ -86,7 +86,6 @@ private Q_SLOTS:
private:
static gboolean busCall(GstBus *bus, GstMessage *msg, gpointer data);
- QList<QPointer<AudioOutput> > m_audioOutputs;
DeviceManager *m_deviceManager;
EffectManager *m_effectManager;
diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.cpp b/src/3rdparty/phonon/gstreamer/devicemanager.cpp
index 60e860f..c3826eb 100644
--- a/src/3rdparty/phonon/gstreamer/devicemanager.cpp
+++ b/src/3rdparty/phonon/gstreamer/devicemanager.cpp
@@ -24,6 +24,7 @@
#include "widgetrenderer.h"
#include "x11renderer.h"
#include "artssink.h"
+#include "pulsesupport.h"
#ifdef USE_ALSASINK2
#include "alsasink2.h"
@@ -44,9 +45,12 @@ namespace Gstreamer
AudioDevice::AudioDevice(DeviceManager *manager, const QByteArray &gstId)
: gstId(gstId)
{
- //get an id
- static int counter = 0;
- id = counter++;
+ // This should never be called when PulseAudio is active.
+ Q_ASSERT(!PulseSupport::getInstance()->isActive());
+
+ id = manager->allocateDeviceId();
+ icon = "audio-card";
+
//get name from device
if (gstId == "default") {
description = "Default audio device";
@@ -71,22 +75,25 @@ AudioDevice::AudioDevice(DeviceManager *manager, const QByteArray &gstId)
DeviceManager::DeviceManager(Backend *backend)
: QObject(backend)
, m_backend(backend)
+ , m_audioDeviceCounter(0)
{
- m_audioSink = qgetenv("PHONON_GST_AUDIOSINK");
- m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE");
-
-#ifndef QT_NO_SETTINGS
QSettings settings(QLatin1String("Trolltech"));
settings.beginGroup(QLatin1String("Qt"));
+ PulseSupport *pulse = PulseSupport::getInstance();
+ m_audioSink = qgetenv("PHONON_GST_AUDIOSINK");
if (m_audioSink.isEmpty()) {
m_audioSink = settings.value(QLatin1String("audiosink"), "Auto").toByteArray().toLower();
+ if (m_audioSink == "auto" && pulse->isActive())
+ m_audioSink = "pulsesink";
}
+ if ("pulsesink" != m_audioSink)
+ pulse->enable(false);
+ m_videoSinkWidget = qgetenv("PHONON_GST_VIDEOMODE");
if (m_videoSinkWidget.isEmpty()) {
m_videoSinkWidget = settings.value(QLatin1String("videomode"), "Auto").toByteArray().toLower();
}
-#endif //QT_NO_SETTINGS
if (m_backend->isValid())
updateDeviceList();
@@ -271,9 +278,17 @@ AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent)
}
#endif //QT_NO_PHONON_VIDEO
-/*
- * Returns a positive device id or -1 if device
- * does not exist
+/**
+ * Allocate a device id for a new audio device
+ */
+int DeviceManager::allocateDeviceId()
+{
+ return m_audioDeviceCounter++;
+}
+
+
+/**
+ * Returns a positive device id or -1 if device does not exist
*
* The gstId is typically in the format hw:1,0
*/
@@ -288,16 +303,30 @@ int DeviceManager::deviceId(const QByteArray &gstId) const
}
/**
- * Get a human-readable description from a device id
+ * Returns a gstId or "default" if device does not exist
+ *
+ * The gstId is typically in the format hw:1,0
*/
-QByteArray DeviceManager::deviceDescription(int id) const
+const QByteArray DeviceManager::gstId(int deviceId)
+{
+ if (!PulseSupport::getInstance()->isActive()) {
+ AudioDevice *ad = audioDevice(deviceId);
+ if (ad)
+ return QByteArray(ad->gstId);
+ }
+ return QByteArray("default");
+}
+
+/**
+* Get the AudioDevice for a given device id
+*/
+AudioDevice* DeviceManager::audioDevice(int id)
{
for (int i = 0 ; i < m_audioDeviceList.size() ; ++i) {
- if (m_audioDeviceList[i].id == id) {
- return m_audioDeviceList[i].description;
- }
+ if (m_audioDeviceList[i].id == id)
+ return &m_audioDeviceList[i];
}
- return QByteArray();
+ return NULL;
}
/**
@@ -311,8 +340,11 @@ void DeviceManager::updateDeviceList()
QList<QByteArray> list;
if (audioSink) {
- list = GstHelper::extractProperties(audioSink, "device");
- list.prepend("default");
+ if (!PulseSupport::getInstance()->isActive()) {
+ // If we're using pulse, the PulseSupport class takes care of things for us.
+ list = GstHelper::extractProperties(audioSink, "device");
+ list.prepend("default");
+ }
for (int i = 0 ; i < list.size() ; ++i) {
QByteArray gstId = list.at(i);
diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.h b/src/3rdparty/phonon/gstreamer/devicemanager.h
index a5e8289..9c6aa8d 100644
--- a/src/3rdparty/phonon/gstreamer/devicemanager.h
+++ b/src/3rdparty/phonon/gstreamer/devicemanager.h
@@ -42,6 +42,7 @@ public :
int id;
QByteArray gstId;
QByteArray description;
+ QString icon;
};
class DeviceManager : public QObject {
@@ -51,8 +52,10 @@ public:
virtual ~DeviceManager();
const QList<AudioDevice> audioOutputDevices() const;
GstPad *requestPad(int device) const;
+ int allocateDeviceId();
int deviceId(const QByteArray &gstId) const;
- QByteArray deviceDescription(int id) const;
+ const QByteArray gstId(int id);
+ AudioDevice* audioDevice(int id);
GstElement *createGNOMEAudioSink(Category category);
GstElement *createAudioSink(Category category = NoCategory);
AbstractRenderer *createVideoRenderer(VideoWidget *parent);
@@ -68,6 +71,7 @@ private:
bool canOpenDevice(GstElement *element) const;
Backend *m_backend;
QList <AudioDevice> m_audioDeviceList;
+ int m_audioDeviceCounter;
QTimer m_devicePollTimer;
QByteArray m_audioSink;
QByteArray m_videoSinkWidget;
diff --git a/src/3rdparty/phonon/gstreamer/effectmanager.cpp b/src/3rdparty/phonon/gstreamer/effectmanager.cpp
index 563e6fc..6c88148 100644
--- a/src/3rdparty/phonon/gstreamer/effectmanager.cpp
+++ b/src/3rdparty/phonon/gstreamer/effectmanager.cpp
@@ -54,7 +54,7 @@ EffectManager::EffectManager(Backend *backend)
// "volume" not needed
// "equalizer-nbands" not really useful at the moment
- // These plugins simply dont work or have major stability issues:
+ // These plugins simply don't work or have major stability issues:
// "iir" Does not seem to do much at the moment
// "audioinvert" Only works for some streams, should be invesigated
// "lpwsinc" Crashes for large values of filter kernel
diff --git a/src/3rdparty/phonon/gstreamer/glrenderer.cpp b/src/3rdparty/phonon/gstreamer/glrenderer.cpp
index 0203028..106884f 100644
--- a/src/3rdparty/phonon/gstreamer/glrenderer.cpp
+++ b/src/3rdparty/phonon/gstreamer/glrenderer.cpp
@@ -266,7 +266,7 @@ GLRenderWidgetImplementation::GLRenderWidgetImplementation(VideoWidget*videoWidg
palette.setColor(QPalette::Background, Qt::black);
setPalette(palette);
setAutoFillBackground(true);
- // Videowidget allways have this property to allow hiding the mouse cursor
+ // Videowidget always have this property to allow hiding the mouse cursor
setMouseTracking(true);
}
diff --git a/src/3rdparty/phonon/gstreamer/gsthelper.cpp b/src/3rdparty/phonon/gstreamer/gsthelper.cpp
index 34d99fa..69bb75c 100644
--- a/src/3rdparty/phonon/gstreamer/gsthelper.cpp
+++ b/src/3rdparty/phonon/gstreamer/gsthelper.cpp
@@ -121,7 +121,7 @@ GstElement* GstHelper::createPluggablePlaybin()
{
GstElement *playbin = 0;
//init playbin and add to our pipeline
- playbin = gst_element_factory_make("playbin", NULL);
+ playbin = gst_element_factory_make("playbin2", NULL);
//Create an identity element to redirect sound
GstElement *audioSinkBin = gst_bin_new (NULL);
diff --git a/src/3rdparty/phonon/gstreamer/gstreamer.desktop b/src/3rdparty/phonon/gstreamer/gstreamer.desktop
index b62472b..0861762 100644
--- a/src/3rdparty/phonon/gstreamer/gstreamer.desktop
+++ b/src/3rdparty/phonon/gstreamer/gstreamer.desktop
@@ -10,28 +10,81 @@ Icon=phonon-gstreamer
InitialPreference=10
Name=GStreamer
+Name[bg]=GStreamer
+Name[ca]=GStreamer
+Name[ca@valencia]=GStreamer
+Name[cs]=GStreamer
+Name[da]=GStreamer
+Name[de]=GStreamer
+Name[el]=GStreamer
+Name[en_GB]=GStreamer
+Name[es]=GStreamer
+Name[et]=GStreamer
+Name[eu]=GStreamer
+Name[fi]=GStreamer
+Name[fr]=GStreamer
+Name[ga]=GStreamer
+Name[gl]=GStreamer
+Name[hsb]=GStreamer
+Name[hu]=GStreamer
+Name[id]=GStreamer
+Name[is]=GStreamer
+Name[it]=GStreamer
+Name[ja]=GStreamer
+Name[ko]=GStreamer
+Name[ku]=GStreamer
+Name[lt]=GStreamer
+Name[lv]=GStreamer
+Name[nb]=GStreamer
+Name[nds]=GStreamer
+Name[nl]=GStreamer
+Name[nn]=GStreamer
Name[pa]=ਜੀਸਟੀਰਮਰ
+Name[pl]=GStreamer
+Name[pt]=GStreamer
+Name[pt_BR]=GStreamer
+Name[ru]=GStreamer
+Name[se]=GStreamer
+Name[sk]=GStreamer
+Name[sl]=GStreamer
Name[sr]=Гстример
+Name[sr@ijekavian]=Гстример
+Name[sr@ijekavianlatin]=GStreamer
+Name[sr@latin]=GStreamer
Name[sv]=Gstreamer
+Name[tr]=GStreamer
+Name[uk]=GStreamer
Name[x-test]=xxGStreamerxx
+Name[zh_CN]=GStreamer
+Name[zh_TW]=GStreamer
Comment=Phonon GStreamer backend
Comment[bg]=Phonon GStreamer
Comment[ca]=Dorsal GStreamer del Phonon
+Comment[ca@valencia]=Dorsal GStreamer del Phonon
+Comment[cs]=Phonon GStreamer backend
Comment[da]=GStreamer-backend til Phonon
Comment[de]=Phonon-Treiber für GStreamer
Comment[el]=Σύστημα υποστήριξης GStreamer του Phonon
+Comment[en_GB]=Phonon GStreamer backend
Comment[es]=Motor GStreamer para Phonon
Comment[et]=Phononi GStreameri taustaprogramm
+Comment[eu]=Phonon GStreamer backend
+Comment[fi]=Phonon GStreamer-taustaohjelma
Comment[fr]=Système de gestion GStreamer pour Phonon
Comment[ga]=Inneall GStreamer le haghaidh Phonon
Comment[gl]=Infraestrutura de GStreamer para Phonon
+Comment[hsb]=Phonon GStreamer backend
+Comment[hu]=Phonon GStreamer modul
+Comment[id]=Phonon GStreamer backend
Comment[is]=Phonon GStreamer bakendi
Comment[it]=Motore Gstreamer di Phonon
Comment[ja]=Phonon GStreamer バックエンド
Comment[ko]=Phonon GStreamer 백엔드
Comment[ku]=Binesaza Phonon GStreamer
+Comment[lt]=Phonon GStreamer galinė sąsaja
Comment[lv]=Phonon GStreamer aizmugure
+Comment[nb]=Phonon-motor for GStreamer
Comment[nds]=Phonon-Hülpprogramm GStreamer
Comment[nl]=GStreamer-backend (Phonon)
Comment[nn]=Phonon-motor for GStreamer
@@ -39,9 +92,13 @@ Comment[pa]=ਫੋਨੋਨ ਜਸਟੀਰਮਰ ਬੈਕਐਂਡ
Comment[pl]=Obsługa GStreamera przez Phonon
Comment[pt]=Infra-estrutura do GStreamer para o Phonon
Comment[pt_BR]=Infraestrutura Phonon GStreamer
+Comment[ru]=Механизм GStreamer для Phonon
+Comment[se]=Phonon GStreamer duogášmohtor
Comment[sk]=GStreamer podsystém
Comment[sl]=Phononova hrbtenica GStreamer
Comment[sr]=Гстример као позадина Фонона
+Comment[sr@ijekavian]=Гстример као позадина Фонона
+Comment[sr@ijekavianlatin]=GStreamer kao pozadina Phonona
Comment[sr@latin]=GStreamer kao pozadina Phonona
Comment[sv]=Phonon Gstreamer-gränssnitt
Comment[tr]=Phonon GStreamer arka ucu
diff --git a/src/3rdparty/phonon/gstreamer/medianode.cpp b/src/3rdparty/phonon/gstreamer/medianode.cpp
index 7257972..1a84592 100644
--- a/src/3rdparty/phonon/gstreamer/medianode.cpp
+++ b/src/3rdparty/phonon/gstreamer/medianode.cpp
@@ -198,9 +198,9 @@ bool MediaNode::disconnectNode(QObject *obj)
// Disconnecting elements while playing or paused seems to cause
// potential deadlock. Hence we force the pipeline into ready state
// before any nodes are disconnected.
- gst_element_set_state(root()->pipeline(), GST_STATE_READY);
+ gst_element_set_state(root()->pipeline(), GST_STATE_READY);
- Q_ASSERT(sink->root()); //sink has to have a root since it is onnected
+ Q_ASSERT(sink->root()); //sink has to have a root since it is connected
if (sink->description() & (AudioSink)) {
GstPad *sinkPad = gst_element_get_pad(sink->audioElement(), "sink");
diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.cpp b/src/3rdparty/phonon/gstreamer/mediaobject.cpp
index b6d23ec..3e0addc 100644
--- a/src/3rdparty/phonon/gstreamer/mediaobject.cpp
+++ b/src/3rdparty/phonon/gstreamer/mediaobject.cpp
@@ -16,6 +16,7 @@
*/
#include <cmath>
#include <gst/interfaces/propertyprobe.h>
+#include <gst/pbutils/install-plugins.h>
#include "common.h"
#include "mediaobject.h"
#include "videowidget.h"
@@ -53,6 +54,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent)
, m_tickTimer(new QTimer(this))
, m_prefinishMark(0)
, m_transitionTime(0)
+ , m_isStream(false)
, m_posAtSeek(-1)
, m_prefinishMarkReachedNotEmitted(true)
, m_aboutToFinishEmitted(false)
@@ -79,6 +81,7 @@ MediaObject::MediaObject(Backend *backend, QObject *parent)
, m_autoplayTitles(true)
, m_availableTitles(0)
, m_currentTitle(1)
+ , m_pendingTitle(1)
{
qRegisterMetaType<GstCaps*>("GstCaps*");
qRegisterMetaType<State>("State");
@@ -95,8 +98,8 @@ MediaObject::MediaObject(Backend *backend, QObject *parent)
m_backend->addBusWatcher(this);
connect(m_tickTimer, SIGNAL(timeout()), SLOT(emitTick()));
}
- connect(this, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
- this, SLOT(notifyStateChange(Phonon::State,Phonon::State)));
+ connect(this, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
+ this, SLOT(notifyStateChange(Phonon::State, Phonon::State)));
}
@@ -136,6 +139,14 @@ QString stateString(const Phonon::State &state)
return QString();
}
+void
+pluginInstallationDone( GstInstallPluginsReturn res, gpointer userData )
+{
+ // Nothing inside yet
+ Q_UNUSED(res);
+ Q_UNUSED(userData);
+}
+
void MediaObject::saveState()
{
//Only first resumeState is respected
@@ -195,13 +206,35 @@ void MediaObject::noMorePadsAvailable ()
if (m_missingCodecs.size() > 0) {
bool canPlay = (m_hasAudio || m_videoStreamFound);
Phonon::ErrorType error = canPlay ? Phonon::NormalError : Phonon::FatalError;
+#ifdef PLUGIN_INSTALL_API
+ GstInstallPluginsContext *ctx = gst_install_plugins_context_new ();
+ gchar *details[2];
+ details[0] = m_missingCodecs[0].toLocal8Bit().data();
+ details[1] = NULL;
+ GstInstallPluginsReturn status;
+
+ status = gst_install_plugins_async( details, ctx, pluginInstallationDone, NULL );
+ gst_install_plugins_context_free ( ctx );
+
+ if ( status != GST_INSTALL_PLUGINS_STARTED_OK )
+ {
+ if( status == GST_INSTALL_PLUGINS_HELPER_MISSING )
+ setError(QString(tr("Missing codec helper script assistant.")), Phonon::FatalError );
+ else
+ setError(QString(tr("Plugin codec installation failed for codec: %0"))
+ .arg(m_missingCodecs[0].split("|")[3]), error);
+ }
+ m_missingCodecs.clear();
+#else
+ QString codecs = m_missingCodecs.join(", ");
+
if (error == Phonon::NormalError && m_hasVideo && !m_videoStreamFound) {
m_hasVideo = false;
emit hasVideoChanged(false);
}
- QString codecs = m_missingCodecs.join(", ");
setError(QString(tr("A required codec is missing. You need to install the following codec(s) to play this content: %0")).arg(codecs), error);
m_missingCodecs.clear();
+#endif
}
}
@@ -248,7 +281,16 @@ void MediaObject::cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps *
value = QString::fromUtf8(gst_structure_get_name (str));
}
- media->addMissingCodecName(value);
+
+#ifdef PLUGIN_INSTALL_API
+ QString plugins = QString("gstreamer|0.10|%0|%1|decoder-%2")
+ .arg( qApp->applicationName() )
+ .arg( value )
+ .arg( QString::fromUtf8(gst_caps_to_string (caps) ) );
+ media->addMissingCodecName( plugins );
+#else
+ media->addMissingCodecName( value );
+#endif
}
static void notifyVideoCaps(GObject *obj, GParamSpec *, gpointer data)
@@ -309,7 +351,7 @@ void MediaObject::connectVideo(GstPad *pad)
m_backend->logMessage("Video track connected", Backend::Info, this);
// Note that the notify::caps _must_ be installed after linking to work with Dapper
m_capsHandler = g_signal_connect(pad, "notify::caps", G_CALLBACK(notifyVideoCaps), this);
-
+
if (!m_loading && !m_hasVideo) {
m_hasVideo = m_videoStreamFound;
emit hasVideoChanged(m_hasVideo);
@@ -368,7 +410,10 @@ bool MediaObject::createPipefromURL(const QUrl &url)
}
// Create a new datasource based on the input URL
- QByteArray encoded_cstr_url = url.toEncoded();
+ // add the 'file' scheme if it's missing; the double '/' is needed!
+ QByteArray encoded_cstr_url = (url.scheme() == QLatin1String("") ?
+ "file://" + url.toEncoded() :
+ url.toEncoded());
m_datasource = gst_element_make_from_uri(GST_URI_SRC, encoded_cstr_url.constData(), (const char*)NULL);
if (!m_datasource)
return false;
@@ -388,6 +433,14 @@ bool MediaObject::createPipefromURL(const QUrl &url)
g_object_set (G_OBJECT (m_datasource), "read-speed", 2, (const char*)NULL);
m_backend->logMessage(QString("new device speed : 2X"), Backend::Info, this);
}
+ }
+
+ /* make HTTP sources send extra headers so we get icecast
+ * metadata in case the stream is an icecast stream */
+ if (encoded_cstr_url.startsWith("http://")
+ && g_object_class_find_property (G_OBJECT_GET_CLASS (m_datasource), "iradio-mode")) {
+ g_object_set (m_datasource, "iradio-mode", TRUE, NULL);
+ m_isStream = true;
}
// Link data source into pipeline
@@ -442,7 +495,7 @@ void MediaObject::createPipeline()
gst_object_ref (GST_OBJECT (m_pipeline));
gst_object_sink (GST_OBJECT (m_pipeline));
- m_decodebin = gst_element_factory_make ("decodebin", NULL);
+ m_decodebin = gst_element_factory_make ("decodebin2", NULL);
g_signal_connect (m_decodebin, "new-decoded-pad", G_CALLBACK (&cb_newpad), this);
g_signal_connect (m_decodebin, "unknown-type", G_CALLBACK (&cb_unknown_type), this);
g_signal_connect (m_decodebin, "no-more-pads", G_CALLBACK (&cb_no_more_pads), this);
@@ -646,7 +699,7 @@ void MediaObject::setState(State newstate)
m_backend->logMessage("EOS already reached", Backend::Info, this);
} else if (currentState == GST_STATE_PLAYING) {
changeState(Phonon::PlayingState);
- } else if (!m_atEndOfStream && gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
+ } else if (gst_element_set_state(m_pipeline, GST_STATE_PLAYING) != GST_STATE_CHANGE_FAILURE) {
m_pendingState = Phonon::PlayingState;
} else {
m_backend->logMessage("phonon state request failed", Backend::Info, this);
@@ -676,7 +729,7 @@ void MediaObject::changeState(State newstate)
return;
Phonon::State oldState = m_state;
- m_state = newstate; // m_state must be set before emitting, since
+ m_state = newstate; // m_state must be set before emitting, since
// Error state requires that state() will return the new value
m_pendingState = newstate;
emit stateChanged(newstate, oldState);
@@ -696,6 +749,8 @@ void MediaObject::changeState(State newstate)
case Phonon::StoppedState:
m_backend->logMessage("phonon state changed: Stopped", Backend::Info, this);
+ // We must reset the pipeline when playing again
+ m_resetNeeded = true;
m_tickTimer->stop();
break;
@@ -861,7 +916,7 @@ void MediaObject::setSource(const MediaSource &source)
// such as failing duration queries etc
GstState state;
gst_element_set_state(m_pipeline, GST_STATE_NULL);
- gst_element_get_state (m_pipeline, &state, NULL, 2000);
+ gst_element_get_state(m_pipeline, &state, NULL, 2000);
m_source = source;
emit currentSourceChanged(m_source);
@@ -871,7 +926,9 @@ void MediaObject::setSource(const MediaSource &source)
// Go into to loading state
changeState(Phonon::LoadingState);
m_loading = true;
- m_resetNeeded = false;
+ // IMPORTANT: Honor the m_resetNeeded flag as it currently stands.
+ // See https://qa.mandriva.com/show_bug.cgi?id=56807
+ //m_resetNeeded = false;
m_resumeState = false;
m_pendingState = Phonon::StoppedState;
@@ -884,8 +941,8 @@ void MediaObject::setSource(const MediaSource &source)
// Clear any existing errors
m_aboutToFinishEmitted = false;
m_error = NoError;
- m_errorString = QString();
-
+ m_errorString.clear();
+
m_bufferPercent = 0;
m_prefinishMarkReachedNotEmitted = true;
m_aboutToFinishEmitted = false;
@@ -894,22 +951,23 @@ void MediaObject::setSource(const MediaSource &source)
setTotalTime(-1);
m_atEndOfStream = false;
- // Clear exising meta tags
+ m_availableTitles = 0;
+ m_pendingTitle = 1;
+ m_currentTitle = 1;
+
+ // Clear existing meta tags
m_metaData.clear();
+ m_isStream = false;
switch (source.type()) {
- case MediaSource::Url: {
- if (createPipefromURL(source.url()))
- m_loading = true;
- else
+ case MediaSource::Url: {
+ if (!createPipefromURL(source.url()))
setError(tr("Could not open media source."));
}
break;
case MediaSource::LocalFile: {
- if (createPipefromURL(QUrl::fromLocalFile(source.fileName())))
- m_loading = true;
- else
+ if (!createPipefromURL(QUrl::fromLocalFile(source.fileName())))
setError(tr("Could not open media source."));
}
break;
@@ -922,17 +980,15 @@ void MediaObject::setSource(const MediaSource &source)
break;
case MediaSource::Stream:
- if (createPipefromStream(source))
- m_loading = true;
- else
+ if (!createPipefromStream(source))
setError(tr("Could not open media source."));
break;
case MediaSource::Disc:
{
- QString mediaUrl;
- switch (source.discType()) {
- case Phonon::NoDisc:
+ QString mediaUrl;
+ switch (source.discType()) {
+ case Phonon::NoDisc:
qWarning() << "I should never get to see a MediaSource that is a disc but doesn't specify which one";
return;
case Phonon::Cd: // CD tracks can be specified by setting the url in the following way uri=cdda:4
@@ -948,9 +1004,7 @@ void MediaObject::setSource(const MediaSource &source)
qWarning() << "media " << source.discType() << " not implemented";
return;
}
- if (!mediaUrl.isEmpty() && createPipefromURL(QUrl(mediaUrl)))
- m_loading = true;
- else
+ if (mediaUrl.isEmpty() || !createPipefromURL(QUrl(mediaUrl)))
setError(tr("Could not open media source."));
}
break;
@@ -966,8 +1020,7 @@ void MediaObject::setSource(const MediaSource &source)
// We need to link this node to ensure that fake sinks are connected
// before loading, otherwise the stream will be blocked
- if (m_loading)
- link();
+ link();
beginLoad();
}
@@ -1004,22 +1057,22 @@ void MediaObject::getStreamInfo()
emit hasVideoChanged(m_hasVideo);
}
- m_availableTitles = 1;
- gint64 titleCount;
- GstFormat format = gst_format_get_by_nick("track");
- if (gst_element_query_duration (m_pipeline, &format, &titleCount)) {
+ if (m_source.discType() == Phonon::Cd) {
+ gint64 titleCount;
+ GstFormat format = gst_format_get_by_nick("track");
+ if (gst_element_query_duration (m_pipeline, &format, &titleCount)) {
//check if returned format is still "track",
//gstreamer sometimes returns the total time, if tracks information is not available.
- if (qstrcmp(gst_format_get_name(format), "track") == 0) {
- int oldAvailableTitles = m_availableTitles;
- m_availableTitles = (int)titleCount;
- if (m_availableTitles != oldAvailableTitles) {
- emit availableTitlesChanged(m_availableTitles);
- m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this);
+ if (qstrcmp(gst_format_get_name(format), "track") == 0) {
+ int oldAvailableTitles = m_availableTitles;
+ m_availableTitles = (int)titleCount;
+ if (m_availableTitles != oldAvailableTitles) {
+ emit availableTitlesChanged(m_availableTitles);
+ m_backend->logMessage(QString("Available titles changed: %0").arg(m_availableTitles), Backend::Info, this);
+ }
}
}
}
-
}
void MediaObject::setPrefinishMark(qint32 newPrefinishMark)
@@ -1077,7 +1130,7 @@ void MediaObject::seek(qint64 time)
}
quint64 current = currentTime();
- quint64 total = totalTime();
+ quint64 total = totalTime();
if (current < total - m_prefinishMark)
m_prefinishMarkReachedNotEmitted = true;
@@ -1098,7 +1151,7 @@ void MediaObject::emitTick()
if (m_tickInterval > 0 && currentTime != m_previousTickTime) {
emit tick(currentTime);
- m_previousTickTime = currentTime;
+ m_previousTickTime = currentTime;
}
if (m_state == Phonon::PlayingState) {
if (currentTime >= totalTime - m_prefinishMark) {
@@ -1109,7 +1162,12 @@ void MediaObject::emitTick()
}
// Prepare load of next source
if (currentTime >= totalTime - ABOUT_TO_FINNISH_TIME) {
- if (!m_aboutToFinishEmitted) {
+ if (m_source.type() == MediaSource::Disc &&
+ m_autoplayTitles &&
+ m_availableTitles > 1 &&
+ m_currentTitle < m_availableTitles) {
+ m_aboutToFinishEmitted = false;
+ } else if (!m_aboutToFinishEmitted) {
m_aboutToFinishEmitted = true; // track is about to finish
emit aboutToFinish();
}
@@ -1213,8 +1271,8 @@ void MediaObject::handleBusMessage(const Message &message)
switch (GST_MESSAGE_TYPE (gstMessage)) {
- case GST_MESSAGE_EOS:
- m_backend->logMessage("EOS recieved", Backend::Info, this);
+ case GST_MESSAGE_EOS:
+ m_backend->logMessage("EOS received", Backend::Info, this);
handleEndOfStream();
break;
@@ -1222,14 +1280,98 @@ void MediaObject::handleBusMessage(const Message &message)
GstTagList* tag_list = 0;
gst_message_parse_tag(gstMessage, &tag_list);
if (tag_list) {
+ TagMap newTags;
+ gst_tag_list_foreach (tag_list, &foreach_tag_function, &newTags);
+ gst_tag_list_free(tag_list);
+
+ // Determine if we should no fake the album/artist tags.
+ // This is a little confusing as we want to fake it on initial
+ // connection where title, album and artist are all missing.
+ // There are however times when we get just other information,
+ // e.g. codec, and so we want to only do clever stuff if we
+ // have a commonly available tag (ORGANIZATION) or we have a
+ // change in title
+ bool fake_it =
+ (m_isStream
+ && ((!newTags.contains("TITLE")
+ && newTags.contains("ORGANIZATION"))
+ || (newTags.contains("TITLE")
+ && m_metaData.value("TITLE") != newTags.value("TITLE")))
+ && !newTags.contains("ALBUM")
+ && !newTags.contains("ARTIST"));
+
TagMap oldMap = m_metaData; // Keep a copy of the old one for reference
- // Append any new meta tags to the existing tag list
- gst_tag_list_foreach (tag_list, &foreach_tag_function, &m_metaData);
+
+ // Now we've checked the new data, append any new meta tags to the existing tag list
+ // We cannot use TagMap::iterator as this is a multimap and when streaming data
+ // could in theory be lost.
+ QList<QString> keys = newTags.keys();
+ for (QList<QString>::iterator i = keys.begin(); i != keys.end(); ++i) {
+ QString key = *i;
+ if (m_isStream) {
+ // If we're streaming, we need to remove data in m_metaData
+ // in order to stop it filling up indefinitely (as it's a multimap)
+ m_metaData.remove(key);
+ }
+ QList<QString> values = newTags.values(key);
+ for (QList<QString>::iterator j = values.begin(); j != values.end(); ++j) {
+ QString value = *j;
+ QString currVal = m_metaData.value(key);
+ if (!m_metaData.contains(key) || currVal != value) {
+ m_metaData.insert(key, value);
+ }
+ }
+ }
+
m_backend->logMessage("Meta tags found", Backend::Info, this);
- if (oldMap != m_metaData && !m_loading)
- emit metaDataChanged(m_metaData);
- gst_tag_list_free(tag_list);
- }
+ if (oldMap != m_metaData) {
+ // This is a bit of a hack to ensure that stream metadata is
+ // returned. We get as much as we can from the Shoutcast server's
+ // StreamTitle= header. If further info is decoded from the stream
+ // itself later, then it will overwrite this info.
+ if (m_isStream && fake_it) {
+ m_metaData.remove("ALBUM");
+ m_metaData.remove("ARTIST");
+
+ // Detect whether we want to "fill in the blanks"
+ QString str;
+ if (m_metaData.contains("TITLE"))
+ {
+ str = m_metaData.value("TITLE");
+ int splitpoint;
+ // Check to see if our title matches "%s - %s"
+ // Where neither %s are empty...
+ if ((splitpoint = str.indexOf(" - ")) > 0
+ && str.size() > (splitpoint+3)) {
+ m_metaData.insert("ARTIST", str.left(splitpoint));
+ m_metaData.replace("TITLE", str.mid(splitpoint+3));
+ }
+ } else {
+ str = m_metaData.value("GENRE");
+ if (!str.isEmpty())
+ m_metaData.insert("TITLE", str);
+ else
+ m_metaData.insert("TITLE", "Streaming Data");
+ }
+ if (!m_metaData.contains("ARTIST")) {
+ str = m_metaData.value("LOCATION");
+ if (!str.isEmpty())
+ m_metaData.insert("ARTIST", str);
+ else
+ m_metaData.insert("ARTIST", "Streaming Data");
+ }
+ str = m_metaData.value("ORGANIZATION");
+ if (!str.isEmpty())
+ m_metaData.insert("ALBUM", str);
+ else
+ m_metaData.insert("ALBUM", "Streaming Data");
+ }
+ // As we manipulate the title, we need to recompare
+ // oldMap and m_metaData here...
+ if (oldMap != m_metaData && !m_loading)
+ emit metaDataChanged(m_metaData);
+ }
+ }
}
break;
@@ -1255,6 +1397,9 @@ void MediaObject::handleBusMessage(const Message &message)
m_backend->logMessage("gstreamer: pipeline state set to playing", Backend::Info, this);
m_tickTimer->start();
changeState(Phonon::PlayingState);
+ if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) {
+ setTrack(m_pendingTitle);
+ }
if (m_resumeState && m_oldState == Phonon::PlayingState) {
seek(m_oldPos);
m_resumeState = false;
@@ -1290,6 +1435,9 @@ void MediaObject::handleBusMessage(const Message &message)
changeState(Phonon::StoppedState);
m_backend->logMessage("gstreamer: pipeline state set to ready", Backend::Debug, this);
m_tickTimer->stop();
+ if ((m_source.type() == MediaSource::Disc) && (m_currentTitle != m_pendingTitle)) {
+ setTrack(m_pendingTitle);
+ }
break;
case GST_STATE_VOID_PENDING :
@@ -1328,7 +1476,7 @@ void MediaObject::handleBusMessage(const Message &message)
setError(err->message, Phonon::FatalError);
gst_caps_unref (caps);
gst_object_unref (sinkPad);
- }
+ }
} else {
setError(QString(err->message), Phonon::FatalError);
}
@@ -1400,8 +1548,8 @@ void MediaObject::handleBusMessage(const Message &message)
//case GST_MESSAGE_STEP_DONE:
//case GST_MESSAGE_LATENCY: only from 0.10.12
//case GST_MESSAGE_ASYNC_DONE: only from 0.10.13
- default:
- break;
+ default:
+ break;
}
}
@@ -1417,7 +1565,8 @@ void MediaObject::handleEndOfStream()
if (!m_seekable)
m_atEndOfStream = true;
- if (m_autoplayTitles &&
+ if (m_source.type() == MediaSource::Disc &&
+ m_autoplayTitles &&
m_availableTitles > 1 &&
m_currentTitle < m_availableTitles) {
_iface_setCurrentTitle(m_currentTitle + 1);
@@ -1444,6 +1593,14 @@ void MediaObject::handleEndOfStream()
}
}
+void MediaObject::invalidateGraph()
+{
+ m_resetNeeded = true;
+ if (m_state == Phonon::PlayingState || m_state == Phonon::PausedState) {
+ changeState(Phonon::StoppedState);
+ }
+}
+
// Notifes the pipeline about state changes in the media object
void MediaObject::notifyStateChange(Phonon::State newstate, Phonon::State oldstate)
{
@@ -1502,15 +1659,30 @@ int MediaObject::_iface_currentTitle() const
void MediaObject::_iface_setCurrentTitle(int title)
{
- GstFormat trackFormat = gst_format_get_by_nick("track");
m_backend->logMessage(QString("setCurrentTitle %0").arg(title), Backend::Info, this);
- if ((title == m_currentTitle) || (title < 1) || (title > m_availableTitles))
+ if ((title == m_currentTitle) || (title == m_pendingTitle))
+ return;
+
+ m_pendingTitle = title;
+
+ if (m_state == Phonon::PlayingState || m_state == Phonon::StoppedState) {
+ setTrack(m_pendingTitle);
+ } else {
+ setState(Phonon::StoppedState);
+ }
+}
+
+void MediaObject::setTrack(int title)
+{
+ if (((m_state != Phonon::PlayingState) && (m_state != Phonon::StoppedState)) || (title < 1) || (title > m_availableTitles))
return;
- m_currentTitle = title;
//let's seek to the beginning of the song
- if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, m_currentTitle - 1)) {
+ GstFormat trackFormat = gst_format_get_by_nick("track");
+ m_backend->logMessage(QString("setTrack %0").arg(title), Backend::Info, this);
+ if (gst_element_seek_simple(m_pipeline, trackFormat, GST_SEEK_FLAG_FLUSH, title - 1)) {
+ m_currentTitle = title;
updateTotalTime();
m_atEndOfStream = false;
emit titleChanged(title);
diff --git a/src/3rdparty/phonon/gstreamer/mediaobject.h b/src/3rdparty/phonon/gstreamer/mediaobject.h
index 64b3510..d588ffc 100644
--- a/src/3rdparty/phonon/gstreamer/mediaobject.h
+++ b/src/3rdparty/phonon/gstreamer/mediaobject.h
@@ -55,6 +55,7 @@ class MediaObject : public QObject, public MediaObjectInterface
, public MediaNode
{
friend class Stream;
+ friend class AudioDataOutput;
Q_OBJECT
Q_INTERFACES(Phonon::MediaObjectInterface
#ifndef QT_NO_PHONON_MEDIACONTROLLER
@@ -144,12 +145,8 @@ public:
void handleBusMessage(const Message &msg);
void handleEndOfStream();
void addMissingCodecName(const QString &codec) { m_missingCodecs.append(codec); }
- void invalidateGraph() {
- m_resetNeeded = true;
- if (m_state == Phonon::PlayingState || m_state == Phonon::PausedState) {
- changeState(Phonon::StoppedState);
- }
- }
+ void invalidateGraph();
+
static void cb_newpad (GstElement *decodebin, GstPad *pad, gboolean last, gpointer data);
static void cb_pad_added (GstElement *decodebin, GstPad *pad, gpointer data);
static void cb_unknown_type (GstElement *decodebin, GstPad *pad, GstCaps *caps, gpointer data);
@@ -236,6 +233,7 @@ private:
int _iface_availableTitles() const;
int _iface_currentTitle() const;
void _iface_setCurrentTitle(int title);
+ void setTrack(int title);
bool m_resumeState;
State m_oldState;
@@ -250,6 +248,7 @@ private:
MediaSource m_nextSource;
qint32 m_prefinishMark;
qint32 m_transitionTime;
+ bool m_isStream;
qint64 m_posAtSeek;
@@ -285,6 +284,7 @@ private:
bool m_autoplayTitles;
int m_availableTitles;
int m_currentTitle;
+ int m_pendingTitle;
};
}
} //namespace Phonon::Gstreamer
diff --git a/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h
index 73a494a..f83dba5 100644
--- a/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h
+++ b/src/3rdparty/phonon/gstreamer/qwidgetvideosink.h
@@ -19,6 +19,7 @@
#define Phonon_GSTREAMER_VIDEOSINK_H
#include "common.h"
+#include "qwidgetvideosink.h"
#include <QtCore/QByteArray>
#include <QtCore/QEvent>
diff --git a/src/3rdparty/phonon/gstreamer/videowidget.h b/src/3rdparty/phonon/gstreamer/videowidget.h
index dc0754d..8603f6a 100644
--- a/src/3rdparty/phonon/gstreamer/videowidget.h
+++ b/src/3rdparty/phonon/gstreamer/videowidget.h
@@ -25,6 +25,7 @@
#include "common.h"
#include "medianode.h"
#include "abstractrenderer.h"
+#include "videowidget.h"
#include <gst/gst.h>
diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.cpp b/src/3rdparty/phonon/gstreamer/x11renderer.cpp
index 73877a8..968f3a8 100644
--- a/src/3rdparty/phonon/gstreamer/x11renderer.cpp
+++ b/src/3rdparty/phonon/gstreamer/x11renderer.cpp
@@ -90,7 +90,7 @@ GstElement* X11Renderer::createVideoSink()
gst_object_unref(GST_OBJECT(videoSink));
videoSink = 0;
} else {
- // Note that this should not really be neccessary as these are
+ // Note that this should not really be necessary as these are
// default values, though under certain conditions values are retained
// even between application instances. (reproducible on 0.10.16/Gutsy)
g_object_set(G_OBJECT(videoSink), "brightness", 0, (const char*)NULL);
@@ -138,6 +138,7 @@ void X11Renderer::scaleModeChanged(Phonon::VideoWidget::ScaleMode)
void X11Renderer::movieSizeChanged(const QSize &movieSize)
{
Q_UNUSED(movieSize);
+
if (m_renderWidget) {
m_renderWidget->setGeometry(m_videoWidget->calculateDrawFrameRect());
}
diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp
index 21cdb16..732d2d9 100644
--- a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp
+++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp
@@ -162,7 +162,10 @@ void MMF::DsaVideoPlayer::prepareCompleted()
void MMF::DsaVideoPlayer::handleVideoWindowChanged()
{
if (!m_window) {
- m_window = QApplication::activeWindow()->effectiveWinId()->DrawableWindow();
+ if (QWidget *window = QApplication::activeWindow())
+ m_window = window->effectiveWinId()->DrawableWindow();
+ else
+ m_window = 0;
m_videoScreenRect = TRect();
}
@@ -213,6 +216,9 @@ void MMF::DsaVideoPlayer::handleParametersChanged(VideoParameters parameters)
TRACE_CONTEXT(DsaVideoPlayer::handleParametersChanged, EVideoInternal);
TRACE_ENTRY_0();
+ if (!m_window)
+ return;
+
#ifndef QT_NO_DEBUG
getDsaRegion(m_wsSession, *m_window);
#endif
diff --git a/src/3rdparty/phonon/phonon/CMakeLists.txt b/src/3rdparty/phonon/phonon/CMakeLists.txt
index 11d7913..ace934a 100644
--- a/src/3rdparty/phonon/phonon/CMakeLists.txt
+++ b/src/3rdparty/phonon/phonon/CMakeLists.txt
@@ -8,6 +8,30 @@ endif (PHONON_BUILD_EXAMPLES)
add_subdirectory(experimental)
+set(PULSEAUDIO_MINIMUM_VERSION "0.9.15")
+macro_optional_find_package(PulseAudio)
+if (PULSEAUDIO_FOUND)
+ # PULSEAUDIO_DEVICE_MANAGER feature check could be moved to FindPulseAudio.cmake, hint hint. -- Rex
+ macro_ensure_version("0.9.21" "${PULSEAUDIO_VERSION}" PULSEAUDIO_DEVICE_MANAGER)
+endif (PULSEAUDIO_FOUND)
+macro_log_feature(PULSEAUDIO_FOUND "PulseAudio" "A cross-platform, networked sound server." "http://www.pulseaudio.org" FALSE "" "Allows audio playback via the PulseAudio soundserver when it is running")
+macro_optional_find_package(GLIB2)
+macro_log_feature(GLIB2_FOUND "GLib2" "GLib 2 is required to compile the pulseaudio for Phonon" "http://www.gtk.org/download/" FALSE)
+
+
+if (GLIB2_FOUND AND PULSEAUDIO_FOUND)
+ add_definitions(-DHAVE_PULSEAUDIO)
+ include_directories(${GLIB2_INCLUDE_DIR} ${PULSEAUDIO_INCLUDE_DIR})
+ if (PULSEAUDIO_DEVICE_MANAGER)
+ add_definitions(-DHAVE_PULSEAUDIO_DEVICE_MANAGER)
+ endif(PULSEAUDIO_DEVICE_MANAGER)
+else(GLIB2_FOUND AND PULSEAUDIO_FOUND)
+ set(PULSEAUDIO_INCLUDE_DIR "")
+ set(PULSEAUDIO_LIBRARY "")
+ set(PULSEAUDIO_MAINLOOP_LIBRARY "")
+endif(GLIB2_FOUND AND PULSEAUDIO_FOUND)
+
+
set(phonon_LIB_SRCS
objectdescription.cpp
objectdescriptionmodel.cpp
@@ -35,9 +59,12 @@ set(phonon_LIB_SRCS
videowidget.cpp
videoplayer.cpp
seekslider.cpp
+ swiftslider.cpp
volumeslider.cpp
effectwidget.cpp
iodevicestream.cpp
+ audiodataoutput.cpp
+ pulsesupport.cpp
)
if (QT_QTDBUS_FOUND)
@@ -50,6 +77,10 @@ endif (QT_QTDBUS_FOUND)
add_definitions(-DPHONON_LIBRARY_PATH="${PLUGIN_INSTALL_DIR}/plugins")
automoc4_add_library(phonon SHARED ${phonon_LIB_SRCS})
target_link_libraries(phonon ${QT_QTCORE_LIBRARY} ${QT_QTGUI_LIBRARY})
+if (GLIB2_FOUND AND PULSEAUDIO_FOUND)
+target_link_libraries(phonon ${GLIB2_LIBRARIES} ${GOBJECT_LIBRARIES} ${PULSEAUDIO_LIBRARY} ${PULSEAUDIO_MAINLOOP_LIBRARY})
+endif (GLIB2_FOUND AND PULSEAUDIO_FOUND)
+
if (QT_QTDBUS_FOUND)
target_link_libraries(phonon ${QT_QTDBUS_LIBRARY})
endif (QT_QTDBUS_FOUND)
@@ -99,6 +130,10 @@ install(FILES
volumeslider.h
effectwidget.h
platformplugin.h
+ audiodataoutput.h
+ audiodataoutputinterface.h
+ globalconfig.h
+ pulsesupport.h
DESTINATION ${INCLUDE_INSTALL_DIR}/phonon COMPONENT Devel)
install(FILES org.kde.Phonon.AudioOutput.xml DESTINATION ${DBUS_INTERFACES_INSTALL_DIR})
diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.cpp b/src/3rdparty/phonon/phonon/audiodataoutput.cpp
new file mode 100644
index 0000000..3a7d3a1
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutput.cpp
@@ -0,0 +1,66 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "audiodataoutput.h"
+#include "audiodataoutput_p.h"
+#include "factory_p.h"
+
+#define PHONON_CLASSNAME AudioDataOutput
+
+namespace Phonon
+{
+
+PHONON_HEIR_IMPL(AbstractAudioOutput)
+
+PHONON_GETTER(int, dataSize, d->dataSize)
+PHONON_GETTER(int, sampleRate, -1)
+PHONON_SETTER(setDataSize, dataSize, int)
+
+bool AudioDataOutputPrivate::aboutToDeleteBackendObject()
+{
+ Q_ASSERT(m_backendObject);
+ pBACKEND_GET(int, dataSize, "dataSize");
+
+ return AbstractAudioOutputPrivate::aboutToDeleteBackendObject();
+}
+
+void AudioDataOutputPrivate::setupBackendObject()
+{
+ Q_Q(AudioDataOutput);
+ Q_ASSERT(m_backendObject);
+ AbstractAudioOutputPrivate::setupBackendObject();
+
+ // set up attributes
+ pBACKEND_CALL1("setDataSize", int, dataSize);
+
+ qRegisterMetaType<QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > >("QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> >");
+
+ QObject::connect(m_backendObject,
+ SIGNAL(dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &)),
+ q, SIGNAL(dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &)));
+ QObject::connect(m_backendObject, SIGNAL(endOfMedia(int)), q, SIGNAL(endOfMedia(int)));
+}
+
+} // namespace Phonon
+
+#undef PHONON_CLASSNAME
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/audiodataoutput.h b/src/3rdparty/phonon/phonon/audiodataoutput.h
new file mode 100644
index 0000000..8e8f8e0
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutput.h
@@ -0,0 +1,129 @@
+/* This file is part of the KDE project
+ Copyright (C) 2005-2006 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+#ifndef Phonon_AUDIODATAOUTPUT_H
+#define Phonon_AUDIODATAOUTPUT_H
+
+#include "phonon_export.h"
+#include "abstractaudiooutput.h"
+#include "phonondefs.h"
+
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
+template<typename T> class QVector;
+template<typename Key, typename T> class QMap;
+#endif
+
+namespace Phonon
+{
+ class AudioDataOutputPrivate;
+
+ /**
+ * \short This class gives you the audio data (for visualizations).
+ *
+ * This class implements a special AbstractAudioOutput that gives your
+ * application the audio data. Don't expect realtime performance. But
+ * the latencies should be low enough to use the audio data for
+ * visualizations. You can also use the audio data for further processing
+ * (e.g. encoding and saving to a file).
+ *
+ * \author Matthias Kretz <kretz@kde.org>
+ */
+ class PHONON_EXPORT AudioDataOutput : public AbstractAudioOutput
+ {
+ Q_OBJECT
+ K_DECLARE_PRIVATE(AudioDataOutput)
+ Q_ENUMS(Channel)
+ Q_PROPERTY(int dataSize READ dataSize WRITE setDataSize)
+ PHONON_HEIR(AudioDataOutput)
+ public:
+ /**
+ * Specifies the channel the audio data belongs to.
+ */
+ enum Channel
+ {
+ LeftChannel,
+ RightChannel,
+ CenterChannel,
+ LeftSurroundChannel,
+ RightSurroundChannel,
+ SubwooferChannel
+ };
+
+ /**
+ * Returns the currently used number of samples passed through
+ * the signal.
+ *
+ * \see setDataSize
+ */
+ int dataSize() const;
+
+ /**
+ * Returns the sample rate in Hz. Common sample rates are 44100 Hz
+ * and 48000 Hz. AudioDataOutput will not do any sample rate
+ * conversion for you. If you need to convert the sample rate you
+ * might want to take a look at libsamplerate. For visualizations it
+ * is often enough to do simple interpolation or even drop/duplicate
+ * samples.
+ *
+ * \return The sample rate as reported by the backend. If the
+ * backend is unavailable -1 is returned.
+ */
+ int sampleRate() const;
+
+ public Q_SLOTS:
+ /**
+ * Sets the number of samples to be passed in one signal emission.
+ *
+ * Defaults to 512 samples per emitted signal.
+ *
+ * \param size the number of samples
+ */
+ void setDataSize(int size);
+
+ Q_SIGNALS:
+ /**
+ * Emitted whenever another dataSize number of samples are ready.
+ *
+ * \param data A mapping of Channel to a vector holding the audio data.
+ */
+ void dataReady(const QMap<Phonon::AudioDataOutput::Channel, QVector<qint16> > &data);
+
+
+ /**
+ * This signal is emitted before the last dataReady signal of a
+ * media is emitted.
+ *
+ * If, for example, the playback of a media file has finished and the
+ * last audio data of that file is going to be passed with the next
+ * dataReady signal, and only the 28 first samples of the data
+ * vector are from that media file endOfMedia will be emitted right
+ * before dataReady with \p remainingSamples = 28.
+ *
+ * \param remainingSamples The number of samples in the next
+ * dataReady vector that belong to the media that was playing to
+ * this point.
+ */
+ void endOfMedia(int remainingSamples);
+ };
+} // namespace Phonon
+
+// vim: sw=4 ts=4 tw=80
+#endif // Phonon_AUDIODATAOUTPUT_H
diff --git a/src/3rdparty/phonon/phonon/audiodataoutput_p.h b/src/3rdparty/phonon/phonon/audiodataoutput_p.h
new file mode 100644
index 0000000..91103a9
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutput_p.h
@@ -0,0 +1,48 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef AUDIODATAOUTPUT_P_H
+#define AUDIODATAOUTPUT_P_H
+
+#include "audiodataoutput.h"
+#include "abstractaudiooutput_p.h"
+
+namespace Phonon
+{
+
+class AudioDataOutputPrivate : public AbstractAudioOutputPrivate
+{
+ Q_DECLARE_PUBLIC(AudioDataOutput)
+ PHONON_PRIVATECLASS
+ protected:
+ AudioDataOutputPrivate()
+ : dataSize(512)
+ {
+ }
+
+ int dataSize;
+};
+
+} // namespace Phonon
+
+#endif // AUDIODATAOUTPUT_P_H
+// vim: sw=4 ts=4 tw=80
diff --git a/src/3rdparty/phonon/phonon/audiodataoutputinterface.h b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h
new file mode 100644
index 0000000..bc1aad0
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/audiodataoutputinterface.h
@@ -0,0 +1,44 @@
+/* This file is part of the KDE project
+ Copyright (C) 2008 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_AUDIODATAOUTPUTINTERFACE_H
+#define PHONON_AUDIODATAOUTPUTINTERFACE_H
+
+namespace Phonon
+{
+
+class AudioDataOutput;
+
+class AudioDataOutputInterface
+{
+ public:
+ virtual ~AudioDataOutputInterface() {}
+
+ virtual AudioDataOutput *frontendObject() const = 0;
+ virtual void setFrontendObject(AudioDataOutput *) = 0;
+};
+
+} // namespace Phonon
+
+Q_DECLARE_INTERFACE(Phonon::AudioDataOutputInterface, "0AudioDataOutputInterface.phonon.kde.org")
+
+#endif // PHONON_AUDIODATAOUTPUTINTERFACE_H
diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp
index 0f6a49b..e94caad 100644
--- a/src/3rdparty/phonon/phonon/audiooutput.cpp
+++ b/src/3rdparty/phonon/phonon/audiooutput.cpp
@@ -24,12 +24,14 @@
#include "factory_p.h"
#include "objectdescription.h"
#include "audiooutputadaptor_p.h"
-#include "globalconfig_p.h"
+#include "globalconfig.h"
#include "audiooutputinterface.h"
#include "phononnamespace_p.h"
#include "platform_p.h"
+#include "pulsesupport.h"
#include <QtCore/qmath.h>
+#include <QtCore/quuid.h>
#define PHONON_CLASSNAME AudioOutput
#define IFACES2 AudioOutputInterface42
@@ -42,8 +44,12 @@ QT_BEGIN_NAMESPACE
namespace Phonon
{
-static inline bool callSetOutputDevice(MediaNodePrivate *const d, int index)
+static inline bool callSetOutputDevice(AudioOutputPrivate *const d, int index)
{
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive())
+ return pulse->setOutputDevice(d->getStreamUuid(), index);
+
Iface<IFACES2> iface(d);
if (iface) {
return iface->setOutputDevice(AudioOutputDevice::fromIndex(index));
@@ -51,8 +57,12 @@ static inline bool callSetOutputDevice(MediaNodePrivate *const d, int index)
return Iface<IFACES0>::cast(d)->setOutputDevice(index);
}
-static inline bool callSetOutputDevice(MediaNodePrivate *const d, const AudioOutputDevice &dev)
+static inline bool callSetOutputDevice(AudioOutputPrivate *const d, const AudioOutputDevice &dev)
{
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive())
+ return pulse->setOutputDevice(d->getStreamUuid(), dev.index());
+
Iface<IFACES2> iface(d);
if (iface) {
return iface->setOutputDevice(dev);
@@ -89,16 +99,20 @@ void AudioOutputPrivate::init(Phonon::Category c)
#endif
category = c;
-
- // select hardware device according to the category
- device = AudioOutputDevice::fromIndex(GlobalConfig().audioOutputDeviceFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices));
+ streamUuid = QUuid::createUuid().toString();
+ PulseSupport *pulse = PulseSupport::getInstance();
+ pulse->setStreamPropList(category, streamUuid);
+ q->connect(pulse, SIGNAL(usingDevice(QString,int)), SLOT(_k_deviceChanged(QString,int)));
createBackendObject();
q->connect(Factory::sender(), SIGNAL(availableAudioOutputDevicesChanged()), SLOT(_k_deviceListChanged()));
}
-
+QString AudioOutputPrivate::getStreamUuid()
+{
+ return streamUuid;
+}
void AudioOutputPrivate::createBackendObject()
{
@@ -106,6 +120,7 @@ void AudioOutputPrivate::createBackendObject()
return;
Q_Q(AudioOutput);
m_backendObject = Factory::createAudioOutput(q);
+ device = AudioOutputDevice::fromIndex(GlobalConfig().audioOutputDeviceFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices));
if (m_backendObject) {
setupBackendObject();
}
@@ -220,21 +235,21 @@ bool AudioOutput::setOutputDevice(const AudioOutputDevice &newAudioOutputDevice)
{
K_D(AudioOutput);
if (!newAudioOutputDevice.isValid()) {
- d->outputDeviceOverridden = false;
+ d->outputDeviceOverridden = d->forceMove = false;
const int newIndex = GlobalConfig().audioOutputDeviceFor(d->category);
if (newIndex == d->device.index()) {
return true;
}
d->device = AudioOutputDevice::fromIndex(newIndex);
} else {
- d->outputDeviceOverridden = true;
+ d->outputDeviceOverridden = d->forceMove = true;
if (d->device == newAudioOutputDevice) {
return true;
}
d->device = newAudioOutputDevice;
}
if (k_ptr->backendObject()) {
- return callSetOutputDevice(k_ptr, d->device.index());
+ return callSetOutputDevice(d, d->device.index());
}
return true;
}
@@ -261,7 +276,10 @@ void AudioOutputPrivate::setupBackendObject()
#ifndef QT_NO_PHONON_SETTINGSGROUP
// if the output device is not available and the device was not explicitly set
- if (!callSetOutputDevice(this, device) && !outputDeviceOverridden) {
+ // There is no need to set the output device initially if PA is used as
+ // we know it will not work (stream doesn't exist yet) and that this will be
+ // handled by _k_deviceChanged()
+ if (!PulseSupport::getInstance()->isActive() && !callSetOutputDevice(this, device) && !outputDeviceOverridden) {
// fall back in the preference list of output devices
QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices);
if (deviceList.isEmpty()) {
@@ -306,10 +324,14 @@ void AudioOutputPrivate::_k_revertFallback()
void AudioOutputPrivate::_k_audioDeviceFailed()
{
+ if (PulseSupport::getInstance()->isActive())
+ return;
+
+#ifndef QT_NO_PHONON_SETTINGSGROUP
+
pDebug() << Q_FUNC_INFO;
// outputDeviceIndex identifies a failing device
// fall back in the preference list of output devices
-#ifndef QT_NO_PHONON_SETTINGSGROUP
const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices);
for (int i = 0; i < deviceList.count(); ++i) {
const int devIndex = deviceList.at(i);
@@ -331,8 +353,15 @@ void AudioOutputPrivate::_k_audioDeviceFailed()
void AudioOutputPrivate::_k_deviceListChanged()
{
- pDebug() << Q_FUNC_INFO;
+ if (PulseSupport::getInstance()->isActive())
+ return;
+
#ifndef QT_NO_PHONON_SETTINGSGROUP
+ pDebug() << Q_FUNC_INFO;
+ // Check to see if we have an override and do not change to a higher priority device if the overridden device is still present.
+ if (outputDeviceOverridden && device.property("available").toBool()) {
+ return;
+ }
// let's see if there's a usable device higher in the preference list
const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings);
DeviceChangeType changeType = HigherPreferenceChange;
@@ -361,6 +390,36 @@ void AudioOutputPrivate::_k_deviceListChanged()
#endif //QT_NO_PHONON_SETTINGSGROUP
}
+void AudioOutputPrivate::_k_deviceChanged(QString inStreamUuid, int deviceIndex)
+{
+ // Note that this method is only used by PulseAudio at present.
+ if (inStreamUuid == streamUuid) {
+ // 1. Check to see if we are overridden. If we are, and devices do not match,
+ // then try and apply our own device as the output device.
+ // We only do this the first time
+ if (outputDeviceOverridden && forceMove) {
+ forceMove = false;
+ const AudioOutputDevice &currentDevice = AudioOutputDevice::fromIndex(deviceIndex);
+ if (currentDevice != device) {
+ if (!callSetOutputDevice(this, device)) {
+ // What to do if we are overridden and cannot change to our preferred device?
+ }
+ }
+ }
+ // 2. If we are not overridden, then we need to update our perception of what
+ // device we are using. If the devices do not match, something lower in the
+ // stack is overriding our preferences (e.g. a per-application stream preference,
+ // specific application move, priority list changed etc. etc.)
+ else if (!outputDeviceOverridden) {
+ const AudioOutputDevice &currentDevice = AudioOutputDevice::fromIndex(deviceIndex);
+ if (currentDevice != device) {
+ // The device is not what we think it is, so lets say what is happening.
+ handleAutomaticDeviceChange(currentDevice, SoundSystemChange);
+ }
+ }
+ }
+}
+
static struct
{
int first;
@@ -405,11 +464,33 @@ void AudioOutputPrivate::handleAutomaticDeviceChange(const AudioOutputDevice &de
g_lastFallback.second = 0;
}
break;
+ case SoundSystemChange:
+ {
+#ifndef QT_NO_PHONON_PLATFORMPLUGIN
+ if (device1.property("available").toBool()) {
+ const QString text = AudioOutput::tr("<html>Switching to the audio playback device <b>%1</b><br/>"
+ "which has higher preference or is specifically configured for this stream.</html>").arg(device2.name());
+ Platform::notification("AudioDeviceFallback", text,
+ QStringList(AudioOutput::tr("Revert back to device '%1'").arg(device1.name())),
+ q, SLOT(_k_revertFallback()));
+ } else {
+ const QString &text =
+ AudioOutput::tr("<html>The audio playback device <b>%1</b> does not work.<br/>"
+ "Falling back to <b>%2</b>.</html>").arg(device1.name()).arg(device2.name());
+ Platform::notification("AudioDeviceFallback", text);
+ }
+#endif //QT_NO_PHONON_PLATFORMPLUGIN
+ //outputDeviceOverridden = true;
+ g_lastFallback.first = 0;
+ g_lastFallback.second = 0;
+ }
+ break;
}
}
AudioOutputPrivate::~AudioOutputPrivate()
{
+ PulseSupport::getInstance()->clearStreamCache(streamUuid);
#ifndef QT_NO_DBUS
if (adaptor) {
emit adaptor->outputDestroyed();
diff --git a/src/3rdparty/phonon/phonon/audiooutput.h b/src/3rdparty/phonon/phonon/audiooutput.h
index 4edf135..513a863 100644
--- a/src/3rdparty/phonon/phonon/audiooutput.h
+++ b/src/3rdparty/phonon/phonon/audiooutput.h
@@ -169,6 +169,7 @@ namespace Phonon
Q_PRIVATE_SLOT(k_func(), void _k_revertFallback())
Q_PRIVATE_SLOT(k_func(), void _k_audioDeviceFailed())
Q_PRIVATE_SLOT(k_func(), void _k_deviceListChanged())
+ Q_PRIVATE_SLOT(k_func(), void _k_deviceChanged(QString streamUuid, int device))
};
} //namespace Phonon
diff --git a/src/3rdparty/phonon/phonon/audiooutput_p.h b/src/3rdparty/phonon/phonon/audiooutput_p.h
index fdee299..01dc48f 100644
--- a/src/3rdparty/phonon/phonon/audiooutput_p.h
+++ b/src/3rdparty/phonon/phonon/audiooutput_p.h
@@ -46,6 +46,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate
return 0;
}
void init(Phonon::Category c);
+ QString getStreamUuid();
protected:
@@ -58,6 +59,7 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate
#endif
deviceBeforeFallback(-1),
outputDeviceOverridden(false),
+ forceMove(false),
muted(false)
{
}
@@ -66,7 +68,8 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate
enum DeviceChangeType {
FallbackChange,
- HigherPreferenceChange
+ HigherPreferenceChange,
+ SoundSystemChange
};
void handleAutomaticDeviceChange(const AudioOutputDevice &newDev, DeviceChangeType type);
@@ -74,17 +77,20 @@ class AudioOutputPrivate : public AbstractAudioOutputPrivate
void _k_revertFallback();
void _k_audioDeviceFailed();
void _k_deviceListChanged();
+ void _k_deviceChanged(QString streamUuid, int deviceIndex);
private:
QString name;
Phonon::AudioOutputDevice device;
qreal volume;
+ QString streamUuid;
#ifndef QT_NO_DBUS
Phonon::AudioOutputAdaptor *adaptor;
#endif
Category category;
int deviceBeforeFallback;
bool outputDeviceOverridden;
+ bool forceMove;
bool muted;
};
} //namespace Phonon
diff --git a/src/3rdparty/phonon/phonon/audiooutputinterface.h b/src/3rdparty/phonon/phonon/audiooutputinterface.h
index 80ba11c..cce12b2 100644
--- a/src/3rdparty/phonon/phonon/audiooutputinterface.h
+++ b/src/3rdparty/phonon/phonon/audiooutputinterface.h
@@ -64,7 +64,7 @@ class AudioOutputInterface40
* A value of 0.0 means muted, 1.0 means unchanged, 2.0 means double voltage (i.e. all
* samples are multiplied by 2).
*
- * Everytime the volume in the backend changes it should emit volumeChanged(qreal), also
+ * Every time the volume in the backend changes it should emit volumeChanged(qreal), also
* inside this function.
*/
virtual void setVolume(qreal) = 0;
diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp
index fbeb020..8dad589 100644
--- a/src/3rdparty/phonon/phonon/backendcapabilities.cpp
+++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp
@@ -26,7 +26,7 @@
#include "phonondefs_p.h"
#include "backendinterface.h"
#include "factory_p.h"
-#include "globalconfig_p.h"
+#include "globalconfig.h"
#include "globalstatic_p.h"
#include "objectdescription.h"
diff --git a/src/3rdparty/phonon/phonon/factory.cpp b/src/3rdparty/phonon/phonon/factory.cpp
index 9967c971..2785dff 100644
--- a/src/3rdparty/phonon/phonon/factory.cpp
+++ b/src/3rdparty/phonon/phonon/factory.cpp
@@ -134,30 +134,24 @@ bool FactoryPrivate::createBackend()
continue;
}
- QStringList plugins(dir.entryList(QDir::Files));
+ QStringList plugins(dir.entryList(QDir::Files));
#ifdef Q_OS_SYMBIAN
/* On Symbian OS we might have two plugins, one which uses Symbian
- * MMF framework("phonon_mmf"), and one which uses Real Networks's
+ * MMF framework("mmf"), and one which uses Real Networks's
* Helix("hxphonon"). We prefer the latter because it's more
* sophisticated, so we make sure the Helix backend is attempted
* to be loaded first, and the MMF backend is used for backup. */
{
-
- const int hxphonon = plugins.indexOf(QLatin1String("hxphonon"));
- if (hxphonon != -1)
- plugins.move(hxphonon, 0);
-
- // Code for debugging the MMF backend.
- if(hxphonon != -1) {
- qDebug() << "Found hxphonon backend and removed it from the lookup list.";
- plugins.removeAll(QLatin1String("hxphonon"));
- }
+ const int helix = plugins.indexOf(QLatin1String("hxphonon"));
+ if (helix != -1)
+ plugins.move(helix, 0);
}
#endif
- for (int i = 0; i < plugins.count(); ++i) {
- QPluginLoader pluginLoader(libPath + plugins.at(i));
+ const QStringList files = dir.entryList(QDir::Files);
+ for (int i = 0; i < files.count(); ++i) {
+ QPluginLoader pluginLoader(libPath + files.at(i));
if (!pluginLoader.load()) {
pDebug() << Q_FUNC_INFO << " load failed:"
<< pluginLoader.errorString();
@@ -350,6 +344,7 @@ FACTORY_IMPL(AudioOutput)
#ifndef QT_NO_PHONON_VIDEO
FACTORY_IMPL(VideoWidget)
#endif //QT_NO_PHONON_VIDEO
+FACTORY_IMPL(AudioDataOutput)
#undef FACTORY_IMPL
@@ -469,7 +464,7 @@ GET_STRING_PROPERTY(backendWebsite)
QObject *Factory::registerQObject(QObject *o)
{
if (o) {
- QObject::connect(o, SIGNAL(destroyed(QObject*)), globalFactory, SLOT(objectDestroyed(QObject*)), Qt::DirectConnection);
+ QObject::connect(o, SIGNAL(destroyed(QObject *)), globalFactory, SLOT(objectDestroyed(QObject *)), Qt::DirectConnection);
globalFactory->objects.append(o);
}
return o;
diff --git a/src/3rdparty/phonon/phonon/factory_p.h b/src/3rdparty/phonon/phonon/factory_p.h
index dee2b56..41b8c5b 100644
--- a/src/3rdparty/phonon/phonon/factory_p.h
+++ b/src/3rdparty/phonon/phonon/factory_p.h
@@ -122,6 +122,13 @@ namespace Factory
#endif //QT_NO_PHONON_VIDEO
/**
+ * Create a new backend object for a AudioDataOutput.
+ *
+ * \return a pointer to the AudioDataOutput the backend provides.
+ */
+ PHONON_EXPORT QObject *createAudioDataOutput(QObject *parent = 0);
+
+ /**
* \return a pointer to the backend interface.
*/
PHONON_EXPORT QObject *backend(bool createWhenNull = true);
diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp
index 3b77a18..be751ce 100644
--- a/src/3rdparty/phonon/phonon/globalconfig.cpp
+++ b/src/3rdparty/phonon/phonon/globalconfig.cpp
@@ -20,6 +20,7 @@
*/
+#include "globalconfig.h"
#include "globalconfig_p.h"
#include "factory_p.h"
@@ -29,6 +30,7 @@
#include "backendinterface.h"
#include "qsettingsgroup_p.h"
#include "phononnamespace_p.h"
+#include "pulsesupport.h"
#include <QtCore/QList>
#include <QtCore/QVariant>
@@ -38,15 +40,18 @@ QT_BEGIN_NAMESPACE
namespace Phonon
{
+GlobalConfigPrivate::GlobalConfigPrivate() : config(QLatin1String("kde.org"), QLatin1String("libphonon"))
+{
+}
+
GlobalConfig::GlobalConfig()
-#ifndef QT_NO_SETTINGS
- : m_config(QLatin1String("kde.org"), QLatin1String("libphonon"))
-#endif //QT_NO_SETTINGS
+ : k_ptr(new GlobalConfigPrivate)
{
}
GlobalConfig::~GlobalConfig()
{
+ delete k_ptr;
}
enum WhatToFilter {
@@ -59,7 +64,11 @@ static void filter(ObjectDescriptionType type, BackendInterface *backendIface, Q
{
QMutableListIterator<int> it(*list);
while (it.hasNext()) {
- const QHash<QByteArray, QVariant> properties = backendIface->objectDescriptionProperties(type, it.next());
+ QHash<QByteArray, QVariant> properties;
+ if (backendIface)
+ properties = backendIface->objectDescriptionProperties(type, it.next());
+ else
+ properties = PulseSupport::getInstance()->objectDescriptionProperties(type, it.next());
QVariant var;
if (whatToFilter & FilterAdvancedDevices) {
var = properties.value("isAdvanced");
@@ -73,6 +82,7 @@ static void filter(ObjectDescriptionType type, BackendInterface *backendIface, Q
if (var.isValid() && var.toBool()) {
it.remove();
continue;
+#ifndef QT_NO_PHONON_SETTINGSGROUP
}
}
if (whatToFilter & FilterUnavailableDevices) {
@@ -85,9 +95,12 @@ static void filter(ObjectDescriptionType type, BackendInterface *backendIface, Q
}
}
-#ifndef QT_NO_PHONON_SETTINGSGROUP
-static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon::Category category, QList<int> &defaultList)
+static QList<int> sortDevicesByCategoryPriority(const GlobalConfig *config, const QSettingsGroup *backendConfig, ObjectDescriptionType type, Phonon::Category category, QList<int> &defaultList)
{
+ Q_ASSERT(config);
+ Q_ASSERT(backendConfig);
+ Q_ASSERT(type == AudioOutputDeviceType || type == AudioCaptureDeviceType);
+
if (defaultList.size() <= 1) {
// nothing to sort
return defaultList;
@@ -104,20 +117,26 @@ static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon
}
}
- QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
- if (!backendConfig.hasKey(categoryKey)) {
- // no list in config for the given category
- categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
- if (!backendConfig.hasKey(categoryKey)) {
- // no list in config for NoCategory
- return defaultList;
+ QList<int> deviceList;
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ deviceList = pulse->objectIndexesByCategory(type, category);
+ } else {
+ QString categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(category));
+ if (!backendConfig->hasKey(categoryKey)) {
+ // no list in config for the given category
+ categoryKey = QLatin1String("Category_") + QString::number(static_cast<int>(Phonon::NoCategory));
+ if (!backendConfig->hasKey(categoryKey)) {
+ // no list in config for NoCategory
+ return defaultList;
+ }
}
- }
- //Now the list from m_config
- QList<int> deviceList = backendConfig.value(categoryKey, QList<int>());
+ //Now the list from d->config
+ deviceList = backendConfig->value(categoryKey, QList<int>());
+ }
- //if there are devices in m_config that the backend doesn't report, remove them from the list
+ //if there are devices in d->config that the backend doesn't report, remove them from the list
QMutableListIterator<int> i(deviceList);
while (i.hasNext()) {
if (0 == defaultList.removeAll(i.next())) {
@@ -125,58 +144,198 @@ static QList<int> listSortedByConfig(const QSettingsGroup &backendConfig, Phonon
}
}
- //if the backend reports more devices that are not in m_config append them to the list
+ //if the backend reports more devices that are not in d->config append them to the list
deviceList += defaultList;
return deviceList;
}
+
+bool GlobalConfig::hideAdvancedDevices() const
+{
+ K_D(const GlobalConfig);
+ //The devices need to be stored independently for every backend
+ const QSettingsGroup generalGroup(&d->config, QLatin1String("General"));
+ return generalGroup.value(QLatin1String("HideAdvancedDevices"), true);
+}
+
+void GlobalConfig::setHideAdvancedDevices(bool hide)
+{
+ K_D(GlobalConfig);
+ QSettingsGroup generalGroup(&d->config, QLatin1String("General"));
+ generalGroup.setValue(QLatin1String("HideAdvancedDevices"), hide);
+}
+
+static bool isHiddenAudioOutputDevice(const GlobalConfig *config, int i)
+{
+ Q_ASSERT(config);
+
+ if (!config->hideAdvancedDevices())
+ return false;
+
+ AudioOutputDevice ad = AudioOutputDevice::fromIndex(i);
+ const QVariant var = ad.property("isAdvanced");
+ return (var.isValid() && var.toBool());
+}
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+static bool isHiddenAudioCaptureDevice(const GlobalConfig *config, int i)
+{
+ Q_ASSERT(config);
+
+ if (!config->hideAdvancedDevices())
+ return false;
+
+ AudioCaptureDevice ad = AudioCaptureDevice::fromIndex(i);
+ const QVariant var = ad.property("isAdvanced");
+ return (var.isValid() && var.toBool());
+}
+#endif
+
+static QList<int> reindexList(const GlobalConfig *config, Phonon::Category category, QList<int>newOrder, bool output)
+{
+ Q_ASSERT(config);
+#ifdef QT_NO_PHONON_AUDIOCAPTURE
+ Q_ASSERT(output);
+#endif
+
+ /*QString sb;
+ sb = QString("(Size %1)").arg(currentList.size());
+ foreach (int i, currentList)
+ sb += QString("%1, ").arg(i);
+ fprintf(stderr, "=== Reindex Current: %s\n", sb.toUtf8().constData());
+ sb = QString("(Size %1)").arg(newOrder.size());
+ foreach (int i, newOrder)
+ sb += QString("%1, ").arg(i);
+ fprintf(stderr, "=== Reindex Before : %s\n", sb.toUtf8().constData());*/
+
+ QList<int> currentList;
+ if (output)
+ currentList = config->audioOutputDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices);
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ else
+ currentList = config->audioCaptureDeviceListFor(category, GlobalConfig::ShowUnavailableDevices|GlobalConfig::ShowAdvancedDevices);
+#endif
+
+ QList<int> newList;
+
+ foreach (int i, newOrder) {
+ int found = currentList.indexOf(i);
+ if (found < 0) {
+ // It's not in the list, so something is odd (e.g. client error). Ignore it.
+ continue;
+ }
+
+ // Iterate through the list from this point onward. If there are hidden devices
+ // immediately following, take them too.
+ newList.append(currentList.takeAt(found));
+ while (found < currentList.size()) {
+ bool hidden = true;
+ if (output)
+ hidden = isHiddenAudioOutputDevice(config, currentList.at(found));
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ else
+ hidden = isHiddenAudioCaptureDevice(config, currentList.at(found));
+#endif
+
+ if (!hidden)
+ break;
+ newList.append(currentList.takeAt(found));
+ }
+ }
+
+ // If there are any devices left in.. just tack them on the end.
+ if (currentList.size() > 0)
+ newList += currentList;
+
+ /*sb = QString("(Size %1)").arg(newList.size());
+ foreach (int i, newList)
+ sb += QString("%1, ").arg(i);
+ fprintf(stderr, "=== Reindex After : %s\n", sb.toUtf8().constData());*/
+ return newList;
+}
+
+
+void GlobalConfig::setAudioOutputDeviceListFor(Phonon::Category category, QList<int> order)
+{
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ pulse->setOutputDevicePriorityForCategory(category, order);
+ return;
+ }
+
+ K_D(GlobalConfig);
+ QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
+
+ order = reindexList(this, category, order, true);
+
+ const QList<int> noCategoryOrder = audioOutputDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices);
+ if (category != Phonon::NoCategory && order == noCategoryOrder) {
+ backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
+ } else {
+ backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
+ }
+}
#endif //QT_NO_PHONON_SETTINGSGROUP
#ifndef QT_NO_PHONON_SETTINGSGROUP
QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int override) const
{
- //The devices need to be stored independently for every backend
- const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
- const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
- const bool hideAdvancedDevices = ((override & AdvancedDevicesFromSettings)
- ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
+ K_D(const GlobalConfig);
+
+ const bool hide = ((override & AdvancedDevicesFromSettings)
+ ? hideAdvancedDevices()
: static_cast<bool>(override & HideAdvancedDevices));
QList<int> defaultList;
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ defaultList = pulse->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
+ if (hide || (override & HideUnavailableDevices)) {
+ filter(AudioOutputDeviceType, NULL, &defaultList,
+ (hide ? FilterAdvancedDevices : 0)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ } else {
+ BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
+
#ifndef QT_NO_PHONON_PLATFORMPLUGIN
- if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
- // the platform plugin lists the audio devices for the platform
- // this list already is in default order (as defined by the platform plugin)
- defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
- if (hideAdvancedDevices) {
- QMutableListIterator<int> it(defaultList);
- while (it.hasNext()) {
- AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
- const QVariant var = objDesc.property("isAdvanced");
- if (var.isValid() && var.toBool()) {
- it.remove();
+ if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
+ // the platform plugin lists the audio devices for the platform
+ // this list already is in default order (as defined by the platform plugin)
+ defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
+ if (hide) {
+ QMutableListIterator<int> it(defaultList);
+ while (it.hasNext()) {
+ AudioOutputDevice objDesc = AudioOutputDevice::fromIndex(it.next());
+ const QVariant var = objDesc.property("isAdvanced");
+ if (var.isValid() && var.toBool()) {
+ it.remove();
+ }
}
}
}
- }
#endif //QT_NO_PHONON_PLATFORMPLUGIN
- // lookup the available devices directly from the backend (mostly for virtual devices)
- if (BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend())) {
- // this list already is in default order (as defined by the backend)
- QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
- if (hideAdvancedDevices || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
- filter(AudioOutputDeviceType, backendIface, &list,
- (hideAdvancedDevices ? FilterAdvancedDevices : 0)
- // the platform plugin already provided the hardware devices
- | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
- | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
- );
+ // lookup the available devices directly from the backend
+ if (backendIface) {
+ // this list already is in default order (as defined by the backend)
+ QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioOutputDeviceType);
+ if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
+ filter(AudioOutputDeviceType, backendIface, &list,
+ (hide ? FilterAdvancedDevices : 0)
+ // the platform plugin maybe already provided the hardware devices?
+ | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ defaultList += list;
}
- defaultList += list;
}
- return listSortedByConfig(backendConfig, category, defaultList);
+ const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioOutputDevice")); // + Factory::identifier());
+ return sortDevicesByCategoryPriority(this, &backendConfig, AudioOutputDeviceType, category, defaultList);
}
#endif //QT_NO_PHONON_SETTINGSGROUP
int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) const
@@ -190,54 +349,89 @@ int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override)
}
#ifndef QT_NO_PHONON_AUDIOCAPTURE
-QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, int override) const
+void GlobalConfig::setAudioCaptureDeviceListFor(Phonon::Category category, QList<int> order)
{
#ifndef QT_NO_PHONON_SETTINGSGROUP
- //The devices need to be stored independently for every backend
- const QSettingsGroup backendConfig(&m_config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
- const QSettingsGroup generalGroup(&m_config, QLatin1String("General"));
- const bool hideAdvancedDevices = ((override & AdvancedDevicesFromSettings)
- ? generalGroup.value(QLatin1String("HideAdvancedDevices"), true)
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ pulse->setCaptureDevicePriorityForCategory(category, order);
+ return;
+ }
+
+ K_D(GlobalConfig);
+ QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
+
+ order = reindexList(this, category, order, false);
+
+ const QList<int> noCategoryOrder = audioCaptureDeviceListFor(Phonon::NoCategory, ShowUnavailableDevices|ShowAdvancedDevices);
+ if (category != Phonon::NoCategory && order == noCategoryOrder) {
+ backendConfig.removeEntry(QLatin1String("Category_") + QString::number(category));
+ } else {
+ backendConfig.setValue(QLatin1String("Category_") + QString::number(category), order);
+ }
+}
+
+QList<int> GlobalConfig::audioCaptureDeviceListFor(Phonon::Category category, int override) const
+{
+ K_D(const GlobalConfig);
+
+ const bool hide = ((override & AdvancedDevicesFromSettings)
+ ? hideAdvancedDevices()
: static_cast<bool>(override & HideAdvancedDevices));
QList<int> defaultList;
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (pulse->isActive()) {
+ defaultList = pulse->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
+ if (hide || (override & HideUnavailableDevices)) {
+ filter(AudioCaptureDeviceType, NULL, &defaultList,
+ (hide ? FilterAdvancedDevices : 0)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ } else {
+ BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend());
+
#ifndef QT_NO_PHONON_PLATFORMPLUGIN
- if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
- // the platform plugin lists the audio devices for the platform
- // this list already is in default order (as defined by the platform plugin)
- defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
- if (hideAdvancedDevices) {
- QMutableListIterator<int> it(defaultList);
- while (it.hasNext()) {
- AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
- const QVariant var = objDesc.property("isAdvanced");
- if (var.isValid() && var.toBool()) {
- it.remove();
+#else //QT_NO_SETTINGSGROUP
+ return QList<int>();
+#endif //QT_NO_SETTINGSGROUP
+ if (PlatformPlugin *platformPlugin = Factory::platformPlugin()) {
+ // the platform plugin lists the audio devices for the platform
+ // this list already is in default order (as defined by the platform plugin)
+ defaultList = platformPlugin->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
+ if (hide) {
+ QMutableListIterator<int> it(defaultList);
+ while (it.hasNext()) {
+ AudioCaptureDevice objDesc = AudioCaptureDevice::fromIndex(it.next());
+ const QVariant var = objDesc.property("isAdvanced");
+ if (var.isValid() && var.toBool()) {
+ it.remove();
+ }
}
}
}
- }
#endif //QT_NO_PHONON_PLATFORMPLUGIN
- // lookup the available devices directly from the backend (mostly for virtual devices)
- if (BackendInterface *backendIface = qobject_cast<BackendInterface *>(Factory::backend())) {
- // this list already is in default order (as defined by the backend)
- QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
- if (hideAdvancedDevices || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
- filter(AudioCaptureDeviceType, backendIface, &list,
- (hideAdvancedDevices ? FilterAdvancedDevices : 0)
- // the platform plugin already provided the hardware devices
- | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
- | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
- );
+ // lookup the available devices directly from the backend
+ if (backendIface) {
+ // this list already is in default order (as defined by the backend)
+ QList<int> list = backendIface->objectDescriptionIndexes(Phonon::AudioCaptureDeviceType);
+ if (hide || !defaultList.isEmpty() || (override & HideUnavailableDevices)) {
+ filter(AudioCaptureDeviceType, backendIface, &list,
+ (hide ? FilterAdvancedDevices : 0)
+ // the platform plugin maybe already provided the hardware devices?
+ | (defaultList.isEmpty() ? 0 : FilterHardwareDevices)
+ | ((override & HideUnavailableDevices) ? FilterUnavailableDevices : 0)
+ );
+ }
+ defaultList += list;
}
- defaultList += list;
}
- return listSortedByConfig(backendConfig, category, defaultList);
-#else //QT_NO_SETTINGSGROUP
- return QList<int>();
-#endif //QT_NO_SETTINGSGROUP
+ const QSettingsGroup backendConfig(&d->config, QLatin1String("AudioCaptureDevice")); // + Factory::identifier());
+ return sortDevicesByCategoryPriority(this, &backendConfig, AudioCaptureDeviceType, category, defaultList);
}
int GlobalConfig::audioCaptureDeviceFor(Phonon::Category category, int override) const
diff --git a/src/3rdparty/phonon/phonon/globalconfig.h b/src/3rdparty/phonon/phonon/globalconfig.h
new file mode 100644
index 0000000..5233c7b
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/globalconfig.h
@@ -0,0 +1,71 @@
+/* This file is part of the KDE project
+Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_GLOBALCONFIG_H
+#define PHONON_GLOBALCONFIG_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include "phonondefs.h"
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class GlobalConfigPrivate;
+
+ class PHONON_EXPORT GlobalConfig
+ {
+ K_DECLARE_PRIVATE(GlobalConfig)
+ public:
+ GlobalConfig();
+ virtual ~GlobalConfig();
+
+ enum DevicesToHideFlag {
+ ShowUnavailableDevices = 0,
+ ShowAdvancedDevices = 0,
+ HideAdvancedDevices = 1,
+ AdvancedDevicesFromSettings = 2,
+ HideUnavailableDevices = 4
+ };
+ bool hideAdvancedDevices() const;
+ void setHideAdvancedDevices(bool hide = true);
+ void setAudioOutputDeviceListFor(Phonon::Category category, QList<int> order);
+ QList<int> audioOutputDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+ int audioOutputDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+
+#ifndef QT_NO_PHONON_AUDIOCAPTURE
+ void setAudioCaptureDeviceListFor(Phonon::Category category, QList<int> order);
+ QList<int> audioCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+ int audioCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
+#endif //QT_NO_PHONON_AUDIOCAPTURE
+
+ protected:
+ GlobalConfigPrivate *const k_ptr;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_GLOBALCONFIG_H
diff --git a/src/3rdparty/phonon/phonon/globalconfig_p.h b/src/3rdparty/phonon/phonon/globalconfig_p.h
index ec70b6f..090ca6b 100644
--- a/src/3rdparty/phonon/phonon/globalconfig_p.h
+++ b/src/3rdparty/phonon/phonon/globalconfig_p.h
@@ -26,40 +26,19 @@ Copyright (C) 2006-2008 Matthias Kretz <kretz@kde.org>
#include <QtCore/QSettings>
#include "phonon_export.h"
-#include "phononnamespace.h"
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
namespace Phonon
{
- class PHONON_EXPORT GlobalConfig
+ class GlobalConfigPrivate
{
- public:
- GlobalConfig();
- virtual ~GlobalConfig();
+ public:
+ GlobalConfigPrivate();
+ virtual ~GlobalConfigPrivate() {}
- enum DevicesToHideFlag {
- ShowUnavailableDevices = 0,
- ShowAdvancedDevices = 0,
- HideAdvancedDevices = 1,
- AdvancedDevicesFromSettings = 2,
- HideUnavailableDevices = 4
- };
-#ifndef QT_NO_PHONON_SETTINGSGROUP
- QList<int> audioOutputDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
-#endif //QT_NO_PHONON_SETTINGSGROUP
- int audioOutputDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
-
-#ifndef QT_NO_PHONON_AUDIOCAPTURE
- QList<int> audioCaptureDeviceListFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
- int audioCaptureDeviceFor(Phonon::Category category, int override = AdvancedDevicesFromSettings) const;
-#endif //QT_NO_PHONON_AUDIOCAPTURE
-
- protected:
-#ifndef QT_NO_SETTINGS
- QSettings m_config;
-#endif //QT_NO_SETTINGS
+ QSettings config;
};
} // namespace Phonon
diff --git a/src/3rdparty/phonon/phonon/mediaobject.cpp b/src/3rdparty/phonon/phonon/mediaobject.cpp
index 41e8dc2..13d303c 100644
--- a/src/3rdparty/phonon/phonon/mediaobject.cpp
+++ b/src/3rdparty/phonon/phonon/mediaobject.cpp
@@ -453,9 +453,9 @@ void MediaObjectPrivate::setupBackendObject()
//pDebug() << Q_FUNC_INFO;
#ifndef QT_NO_PHONON_ABSTRACTMEDIASTREAM
- QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), q, SLOT(_k_stateChanged(Phonon::State,Phonon::State)));
+ QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), q, SLOT(_k_stateChanged(Phonon::State, Phonon::State)));
#else
- QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State,Phonon::State)), q, SIGNAL(stateChanged(Phonon::State,Phonon::State)));
+ QObject::connect(m_backendObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)), q, SIGNAL(stateChanged(Phonon::State, Phonon::State)));
#endif // QT_NO_PHONON_ABSTRACTMEDIASTREAM
QObject::connect(m_backendObject, SIGNAL(tick(qint64)), q, SIGNAL(tick(qint64)));
QObject::connect(m_backendObject, SIGNAL(seekableChanged(bool)), q, SIGNAL(seekableChanged(bool)));
@@ -467,10 +467,10 @@ void MediaObjectPrivate::setupBackendObject()
QObject::connect(m_backendObject, SIGNAL(aboutToFinish()), q, SLOT(_k_aboutToFinish()));
QObject::connect(m_backendObject, SIGNAL(prefinishMarkReached(qint32)), q, SIGNAL(prefinishMarkReached(qint32)));
QObject::connect(m_backendObject, SIGNAL(totalTimeChanged(qint64)), q, SIGNAL(totalTimeChanged(qint64)));
- QObject::connect(m_backendObject, SIGNAL(metaDataChanged(QMultiMap<QString,QString>)),
- q, SLOT(_k_metaDataChanged(QMultiMap<QString,QString>)));
- QObject::connect(m_backendObject, SIGNAL(currentSourceChanged(MediaSource)),
- q, SLOT(_k_currentSourceChanged(MediaSource)));
+ QObject::connect(m_backendObject, SIGNAL(metaDataChanged(const QMultiMap<QString, QString> &)),
+ q, SLOT(_k_metaDataChanged(const QMultiMap<QString, QString> &)));
+ QObject::connect(m_backendObject, SIGNAL(currentSourceChanged(const MediaSource&)),
+ q, SLOT(_k_currentSourceChanged(const MediaSource&)));
// set up attributes
pINTERFACE_CALL(setTickInterval(tickInterval));
diff --git a/src/3rdparty/phonon/phonon/objectdescription.cpp b/src/3rdparty/phonon/phonon/objectdescription.cpp
index e058b89..55e74b5 100644
--- a/src/3rdparty/phonon/phonon/objectdescription.cpp
+++ b/src/3rdparty/phonon/phonon/objectdescription.cpp
@@ -29,6 +29,7 @@
#include <QtCore/QStringList>
#include "backendinterface.h"
#include "platformplugin.h"
+#include "pulsesupport.h"
QT_BEGIN_NAMESPACE
@@ -108,27 +109,38 @@ bool ObjectDescriptionData::isValid() const
ObjectDescriptionData *ObjectDescriptionData::fromIndex(ObjectDescriptionType type, int index)
{
- // prefer to get the ObjectDescriptionData from the platform plugin for audio devices
+ bool is_audio_device = (AudioOutputDeviceType == type || AudioCaptureDeviceType == type);
+
+ PulseSupport *pulse = PulseSupport::getInstance();
+ if (is_audio_device && pulse->isActive()) {
+ QList<int> indexes = pulse->objectDescriptionIndexes(type);
+ if (indexes.contains(index)) {
+ QHash<QByteArray, QVariant> properties = pulse->objectDescriptionProperties(type, index);
+ return new ObjectDescriptionData(index, properties);
+ }
+ } else {
+ BackendInterface *iface = qobject_cast<BackendInterface *>(Factory::backend());
+
+ // prefer to get the ObjectDescriptionData from the platform plugin for audio devices
#ifndef QT_NO_PHONON_PLATFORMPLUGIN
- if (type == AudioOutputDeviceType || type == AudioCaptureDeviceType) {
- PlatformPlugin *platformPlugin = Factory::platformPlugin();
- if (platformPlugin) {
- QList<int> indexes = platformPlugin->objectDescriptionIndexes(type);
- if (indexes.contains(index)) {
- QHash<QByteArray, QVariant> properties = platformPlugin->objectDescriptionProperties(type, index);
- return new ObjectDescriptionData(index, properties);
+ if (is_audio_device) {
+ PlatformPlugin *platformPlugin = Factory::platformPlugin();
+ if (platformPlugin) {
+ QList<int> indexes = platformPlugin->objectDescriptionIndexes(type);
+ if (indexes.contains(index)) {
+ QHash<QByteArray, QVariant> properties = platformPlugin->objectDescriptionProperties(type, index);
+ return new ObjectDescriptionData(index, properties);
+ }
}
}
- }
#endif //QT_NO_PHONON_PLATFORMPLUGIN
- QObject *b = Factory::backend();
- BackendInterface *iface = qobject_cast<BackendInterface *>(b);
- if (iface) {
- QList<int> indexes = iface->objectDescriptionIndexes(type);
- if (indexes.contains(index)) {
- QHash<QByteArray, QVariant> properties = iface->objectDescriptionProperties(type, index);
- return new ObjectDescriptionData(index, properties);
+ if (iface) {
+ QList<int> indexes = iface->objectDescriptionIndexes(type);
+ if (indexes.contains(index)) {
+ QHash<QByteArray, QVariant> properties = iface->objectDescriptionProperties(type, index);
+ return new ObjectDescriptionData(index, properties);
+ }
}
}
return new ObjectDescriptionData(0); // invalid
diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp
index bf5be6d..741a74c 100644
--- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp
+++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.cpp
@@ -362,6 +362,7 @@ QStringList ObjectDescriptionModelData::mimeTypes(ObjectDescriptionType type) co
return QStringList(QLatin1String("application/x-phonon-objectdescription") + QString::number(static_cast<int>(type)));
}
+#if !defined(Q_CC_MSVC) || _MSC_VER > 1300 || defined(Q_CC_INTEL) || defined(Q_CC_MINGW)
#define INSTANTIATE_META_FUNCTIONS(type) \
template const QMetaObject *ObjectDescriptionModel<type>::metaObject() const; \
template void *ObjectDescriptionModel<type>::qt_metacast(const char *)
@@ -371,6 +372,7 @@ INSTANTIATE_META_FUNCTIONS(AudioCaptureDeviceType);
INSTANTIATE_META_FUNCTIONS(EffectType);
INSTANTIATE_META_FUNCTIONS(AudioChannelType);
INSTANTIATE_META_FUNCTIONS(SubtitleType);
+#endif
/*INSTANTIATE_META_FUNCTIONS(VideoOutputDeviceType);
INSTANTIATE_META_FUNCTIONS(VideoCaptureDeviceType);
INSTANTIATE_META_FUNCTIONS(AudioCodecType);
diff --git a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h
index 8fd622f..a1540e8 100644
--- a/src/3rdparty/phonon/phonon/objectdescriptionmodel.h
+++ b/src/3rdparty/phonon/phonon/objectdescriptionmodel.h
@@ -35,6 +35,18 @@ QT_BEGIN_NAMESPACE
#ifndef QT_NO_PHONON_OBJECTDESCRIPTIONMODEL
+/* MinGW 3.4.x gives an ICE when trying to instantiate one of the
+ ObjectDescriptionModel<foo> classes because it can't handle
+ half exported classes correct. gcc 4.3.x has a fix for this but
+ we currently there's no official gcc 4.3 on windows available.
+ Because of this we need this little hack
+ */
+#if defined(Q_CC_MINGW)
+#define PHONON_EXPORT_ODM
+#else
+#define PHONON_EXPORT_ODM PHONON_EXPORT
+#endif
+
namespace Phonon
{
class ObjectDescriptionModelDataPrivate;
@@ -139,21 +151,6 @@ namespace Phonon
ObjectDescriptionModelDataPrivate *const d;
};
-/* Required to ensure template class vtables are exported on both symbian
-and existing builds. */
-#if defined(Q_OS_SYMBIAN) && defined(Q_CC_RVCT)
-// RVCT compiler (2.2.686) requires the export declaration to be on the class to export vtables
-// MWC compiler works both ways
-// GCCE compiler is unknown (it can't compile QtCore yet)
-#define PHONON_TEMPLATE_CLASS_EXPORT PHONON_EXPORT
-#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT
-#else
-// Windows builds (at least) do not support export declaration on templated class
-// But if you export a member function, the vtable is implicitly exported
-#define PHONON_TEMPLATE_CLASS_EXPORT
-#define PHONON_TEMPLATE_CLASS_MEMBER_EXPORT PHONON_EXPORT
-#endif
-
/** \class ObjectDescriptionModel objectdescriptionmodel.h Phonon/ObjectDescriptionModel
* \short The ObjectDescriptionModel class provides a model from
* a list of ObjectDescription objects.
@@ -190,17 +187,16 @@ and existing builds. */
* \author Matthias Kretz <kretz@kde.org>
*/
template<ObjectDescriptionType type>
- class PHONON_TEMPLATE_CLASS_EXPORT ObjectDescriptionModel : public QAbstractListModel
+ class ObjectDescriptionModel : public QAbstractListModel
{
public:
Q_OBJECT_CHECK
-
/** \internal */
- static PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject staticMetaObject;
+ static PHONON_EXPORT const QMetaObject staticMetaObject;
/** \internal */
- PHONON_TEMPLATE_CLASS_MEMBER_EXPORT const QMetaObject *metaObject() const;
+ PHONON_EXPORT_ODM const QMetaObject *metaObject() const;
/** \internal */
- PHONON_TEMPLATE_CLASS_MEMBER_EXPORT void *qt_metacast(const char *_clname);
+ PHONON_EXPORT_ODM void *qt_metacast(const char *_clname);
//int qt_metacall(QMetaObject::Call _c, int _id, void **_a);
/**
diff --git a/src/3rdparty/phonon/phonon/path.cpp b/src/3rdparty/phonon/phonon/path.cpp
index 51c33b2..1c25b89 100644
--- a/src/3rdparty/phonon/phonon/path.cpp
+++ b/src/3rdparty/phonon/phonon/path.cpp
@@ -310,8 +310,8 @@ bool PathPrivate::executeTransaction( const QList<QObjectPair> &disconnections,
if (!transaction)
return false;
- QList<QObjectPair>::const_iterator it = disconnections.constBegin();
- for(;it != disconnections.constEnd();++it) {
+ QList<QObjectPair>::const_iterator it = disconnections.begin();
+ for(;it != disconnections.end();++it) {
const QObjectPair &pair = *it;
if (!backend->disconnectNodes(pair.first, pair.second)) {
@@ -327,8 +327,8 @@ bool PathPrivate::executeTransaction( const QList<QObjectPair> &disconnections,
}
}
- for(it = connections.constBegin(); it != connections.constEnd(); ++it) {
- const QObjectPair pair = *it;
+ for(it = connections.begin(); it != connections.end();++it) {
+ const QObjectPair &pair = *it;
if (!backend->connectNodes(pair.first, pair.second)) {
//Error: a connection failed
QList<QObjectPair>::const_iterator it2 = connections.begin();
diff --git a/src/3rdparty/phonon/phonon/phonondefs.h b/src/3rdparty/phonon/phonon/phonondefs.h
index 15a1815..765eb1c 100644
--- a/src/3rdparty/phonon/phonon/phonondefs.h
+++ b/src/3rdparty/phonon/phonon/phonondefs.h
@@ -29,6 +29,11 @@
QT_BEGIN_HEADER
QT_BEGIN_NAMESPACE
+#ifdef PHONON_BACKEND_VERSION_4_4
+# ifndef PHONON_BACKEND_VERSION_4_3
+# define PHONON_BACKEND_VERSION_4_3
+# endif
+#endif
#ifdef PHONON_BACKEND_VERSION_4_3
# ifndef PHONON_BACKEND_VERSION_4_2
# define PHONON_BACKEND_VERSION_4_2
diff --git a/src/3rdparty/phonon/phonon/pulsesupport.cpp b/src/3rdparty/phonon/phonon/pulsesupport.cpp
new file mode 100644
index 0000000..642843f
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/pulsesupport.cpp
@@ -0,0 +1,1040 @@
+/* This file is part of the KDE project
+ Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include <QtCore/QAbstractEventDispatcher>
+#include <QtCore/QEventLoop>
+#include <QtCore/QDebug>
+#include <QtCore/QStringList>
+
+#ifdef HAVE_PULSEAUDIO
+#include <glib.h>
+#include <pulse/pulseaudio.h>
+#include <pulse/xmalloc.h>
+#include <pulse/glib-mainloop.h>
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+# include <pulse/ext-device-manager.h>
+#endif
+#endif // HAVE_PULSEAUDIO
+
+#include "pulsesupport.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+
+static PulseSupport* s_instance = NULL;
+
+#ifdef HAVE_PULSEAUDIO
+/***
+* Prints a conditional debug message based on the current debug level
+* If obj is provided, classname and objectname will be printed as well
+*
+* see debugLevel()
+*/
+
+static int debugLevel() {
+ static int level = -1;
+ if (level < 1) {
+ level = 0;
+ QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DEBUG");
+ int l = pulseenv.toInt();
+ if (l > 0)
+ level = (l > 2 ? 2 : l);
+ }
+ return level;
+}
+
+static void logMessage(const QString &message, int priority = 2, QObject *obj=0);
+static void logMessage(const QString &message, int priority, QObject *obj)
+{
+ if (debugLevel() > 0) {
+ QString output;
+ if (obj) {
+ // Strip away namespace from className
+ QString className(obj->metaObject()->className());
+ int nameLength = className.length() - className.lastIndexOf(':') - 1;
+ className = className.right(nameLength);
+ output.sprintf("%s %s (%s %p)", message.toLatin1().constData(),
+ obj->objectName().toLatin1().constData(),
+ className.toLatin1().constData(), obj);
+ }
+ else {
+ output = message;
+ }
+ if (priority <= debugLevel()) {
+ qDebug() << QString("PulseSupport(%1): %2").arg(priority).arg(output);
+ }
+ }
+}
+
+
+class AudioDevice
+{
+ public:
+ inline
+ AudioDevice(QString name, QString desc, QString icon, uint32_t index)
+ : pulseName(name), pulseIndex(index)
+ {
+ properties["name"] = desc;
+ properties["description"] = ""; // We don't have descriptions (well we do, but we use them as the name!)
+ properties["icon"] = icon;
+ properties["available"] = (index != PA_INVALID_INDEX);
+ properties["isAdvanced"] = false; // Nothing is advanced!
+ }
+
+ // Needed for QMap
+ inline AudioDevice() {}
+
+ QString pulseName;
+ uint32_t pulseIndex;
+ QHash<QByteArray, QVariant> properties;
+};
+bool operator!=(const AudioDevice &a, const AudioDevice &b)
+{
+ return !(a.pulseName == b.pulseName && a.properties == b.properties);
+}
+
+class PulseUserData
+{
+ public:
+ inline
+ PulseUserData()
+ {
+ }
+
+ QMap<QString, AudioDevice> newOutputDevices;
+ QMap<Phonon::Category, QMap<int, int> > newOutputDevicePriorities; // prio, device
+
+ QMap<QString, AudioDevice> newCaptureDevices;
+ QMap<Phonon::Category, QMap<int, int> > newCaptureDevicePriorities; // prio, device
+};
+
+static QMap<QString, Phonon::Category> s_roleCategoryMap;
+
+static bool s_pulseActive = false;
+
+static pa_glib_mainloop *s_mainloop = NULL;
+static pa_context *s_context = NULL;
+
+
+
+static int s_deviceIndexCounter = 0;
+
+static QMap<QString, int> s_outputDeviceIndexes;
+static QMap<int, AudioDevice> s_outputDevices;
+static QMap<Phonon::Category, QMap<int, int> > s_outputDevicePriorities; // prio, device
+static QMap<QString, uint32_t> s_outputStreamIndexMap;
+
+static QMap<QString, int> s_captureDeviceIndexes;
+static QMap<int, AudioDevice> s_captureDevices;
+static QMap<Phonon::Category, QMap<int, int> > s_captureDevicePriorities; // prio, device
+static QMap<QString, uint32_t> s_captureStreamIndexMap;
+
+static void createGenericDevices()
+{
+ // OK so we don't have the device manager extension, but we can show a single device and fake it.
+ int index;
+ s_outputDeviceIndexes.clear();
+ s_outputDevices.clear();
+ s_outputDevicePriorities.clear();
+ index = s_deviceIndexCounter++;
+ s_outputDeviceIndexes.insert("sink:default", index);
+ s_outputDevices.insert(index, AudioDevice("sink:default", QObject::tr("PulseAudio Sound Server").toUtf8(), "audio-backend-pulseaudio", 0));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ s_outputDevicePriorities[cat].insert(0, index);
+ }
+
+ s_captureDeviceIndexes.clear();
+ s_captureDevices.clear();
+ s_captureDevicePriorities.clear();
+ index = s_deviceIndexCounter++;
+ s_captureDeviceIndexes.insert("source:default", index);
+ s_captureDevices.insert(index, AudioDevice("source:default", QObject::tr("PulseAudio Sound Server").toUtf8(), "audio-backend-pulseaudio", 0));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ s_captureDevicePriorities[cat].insert(0, index);
+ }
+}
+
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+static void ext_device_manager_read_cb(pa_context *c, const pa_ext_device_manager_info *info, int eol, void *userdata) {
+ Q_ASSERT(c);
+ Q_ASSERT(userdata);
+
+ PulseUserData *u = reinterpret_cast<PulseUserData*>(userdata);
+
+ if (eol < 0) {
+ logMessage(QString("Failed to initialize device manager extension: %1").arg(pa_strerror(pa_context_errno(c))));
+ logMessage("Falling back to single device mode");
+ createGenericDevices();
+ delete u;
+
+ // If this is our probe phase, exit now
+ if (s_context != c)
+ pa_context_disconnect(c);
+
+ return;
+ }
+
+ if (eol) {
+ // We're done reading the data, so order it by priority and copy it into the
+ // static variables where it can then be accessed by those classes that need it.
+
+ QMap<QString, AudioDevice>::iterator newdev_it;
+
+ // Check for new output devices or things changing about known output devices.
+ bool output_changed = false;
+ for (newdev_it = u->newOutputDevices.begin(); newdev_it != u->newOutputDevices.end(); ++newdev_it) {
+ QString name = newdev_it.key();
+
+ // The name + index map is always written when a new device is added.
+ Q_ASSERT(s_outputDeviceIndexes.contains(name));
+
+ int index = s_outputDeviceIndexes[name];
+ if (!s_outputDevices.contains(index)) {
+ // This is a totally new device
+ output_changed = true;
+ logMessage(QString("Brand New Output Device Found."));
+ s_outputDevices.insert(index, *newdev_it);
+ } else if (s_outputDevices[index] != *newdev_it) {
+ // We have this device already, but is it different?
+ output_changed = true;
+ logMessage(QString("Change to Existing Output Device (may be Added/Removed or something else)"));
+ s_outputDevices.remove(index);
+ s_outputDevices.insert(index, *newdev_it);
+ }
+ }
+ // Go through the output devices we know about and see if any are no longer mentioned in the list.
+ QMutableMapIterator<QString, int> output_existing_it(s_outputDeviceIndexes);
+ while (output_existing_it.hasNext()) {
+ output_existing_it.next();
+ if (!u->newOutputDevices.contains(output_existing_it.key())) {
+ output_changed = true;
+ logMessage(QString("Output Device Completely Removed"));
+ s_outputDevices.remove(output_existing_it.value());
+ output_existing_it.remove();
+ }
+ }
+
+ // Check for new capture devices or things changing about known capture devices.
+ bool capture_changed = false;
+ for (newdev_it = u->newCaptureDevices.begin(); newdev_it != u->newCaptureDevices.end(); ++newdev_it) {
+ QString name = newdev_it.key();
+
+ // The name + index map is always written when a new device is added.
+ Q_ASSERT(s_captureDeviceIndexes.contains(name));
+
+ int index = s_captureDeviceIndexes[name];
+ if (!s_captureDevices.contains(index)) {
+ // This is a totally new device
+ capture_changed = true;
+ logMessage(QString("Brand New Capture Device Found."));
+ s_captureDevices.insert(index, *newdev_it);
+ } else if (s_captureDevices[index] != *newdev_it) {
+ // We have this device already, but is it different?
+ capture_changed = true;
+ logMessage(QString("Change to Existing Capture Device (may be Added/Removed or something else)"));
+ s_captureDevices.remove(index);
+ s_captureDevices.insert(index, *newdev_it);
+ }
+ }
+ // Go through the capture devices we know about and see if any are no longer mentioned in the list.
+ QMutableMapIterator<QString, int> capture_existing_it(s_captureDeviceIndexes);
+ while (capture_existing_it.hasNext()) {
+ capture_existing_it.next();
+ if (!u->newCaptureDevices.contains(capture_existing_it.key())) {
+ capture_changed = true;
+ logMessage(QString("Capture Device Completely Removed"));
+ s_captureDevices.remove(capture_existing_it.value());
+ capture_existing_it.remove();
+ }
+ }
+
+ // Just copy accross the new priority lists as we know they are valid
+ if (s_outputDevicePriorities != u->newOutputDevicePriorities) {
+ output_changed = true;
+ s_outputDevicePriorities = u->newOutputDevicePriorities;
+ }
+ if (s_captureDevicePriorities != u->newCaptureDevicePriorities) {
+ capture_changed = true;
+ s_captureDevicePriorities = u->newCaptureDevicePriorities;
+ }
+
+ if (s_instance) {
+ // This wont be emitted durring the connection probe phase
+ // which is intensional
+ if (output_changed)
+ s_instance->emitObjectDescriptionChanged(AudioOutputDeviceType);
+ if (capture_changed)
+ s_instance->emitObjectDescriptionChanged(AudioCaptureDeviceType);
+ }
+
+ // We can free the user data as we will not be called again.
+ delete u;
+
+ // Some debug
+ logMessage(QString("Output Device Priority List:"));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ if (s_outputDevicePriorities.contains(cat)) {
+ logMessage(QString(" Phonon Category %1").arg(cat));
+ int count = 0;
+ foreach (int j, s_outputDevicePriorities[cat]) {
+ QHash<QByteArray, QVariant> &props = s_outputDevices[j].properties;
+ logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool()));
+ }
+ }
+ }
+ logMessage(QString("Capture Device Priority List:"));
+ for (int i = Phonon::NoCategory; i <= Phonon::LastCategory; ++i) {
+ Phonon::Category cat = static_cast<Phonon::Category>(i);
+ if (s_captureDevicePriorities.contains(cat)) {
+ logMessage(QString(" Phonon Category %1").arg(cat));
+ int count = 0;
+ foreach (int j, s_captureDevicePriorities[cat]) {
+ QHash<QByteArray, QVariant> &props = s_captureDevices[j].properties;
+ logMessage(QString(" %1. %2 (Available: %3)").arg(++count).arg(props["name"].toString()).arg(props["available"].toBool()));
+ }
+ }
+ }
+
+ // If this is our probe phase, exit now as we're finished reading
+ // our device info and can exit and reconnect
+ if (s_context != c)
+ pa_context_disconnect(c);
+ }
+
+ if (!info)
+ return;
+
+ Q_ASSERT(info->name);
+ Q_ASSERT(info->description);
+ Q_ASSERT(info->icon);
+
+ // QString wrapper
+ QString name(info->name);
+ int index;
+ QMap<Phonon::Category, QMap<int, int> > *new_prio_map_cats; // prio, device
+ QMap<QString, AudioDevice> *new_devices;
+
+ if (name.startsWith("sink:")) {
+ new_devices = &u->newOutputDevices;
+ new_prio_map_cats = &u->newOutputDevicePriorities;
+
+ if (s_outputDeviceIndexes.contains(name))
+ index = s_outputDeviceIndexes[name];
+ else
+ index = s_outputDeviceIndexes[name] = s_deviceIndexCounter++;
+ } else if (name.startsWith("source:")) {
+ new_devices = &u->newCaptureDevices;
+ new_prio_map_cats = &u->newCaptureDevicePriorities;
+
+ if (s_captureDeviceIndexes.contains(name))
+ index = s_captureDeviceIndexes[name];
+ else
+ index = s_captureDeviceIndexes[name] = s_deviceIndexCounter++;
+ } else {
+ // This indicates a bug in pulseaudio.
+ return;
+ }
+
+ // Add the new device itself.
+ new_devices->insert(name, AudioDevice(name, info->description, info->icon, info->index));
+
+ // For each role in the priority, map it to a phonon category and store the order.
+ for (uint32_t i = 0; i < info->n_role_priorities; ++i) {
+ pa_ext_device_manager_role_priority_info* role_prio = &info->role_priorities[i];
+ Q_ASSERT(role_prio->role);
+
+ if (s_roleCategoryMap.contains(role_prio->role)) {
+ Phonon::Category cat = s_roleCategoryMap[role_prio->role];
+
+ (*new_prio_map_cats)[cat].insert(role_prio->priority, index);
+ }
+ }
+}
+
+static void ext_device_manager_subscribe_cb(pa_context *c, void *) {
+ Q_ASSERT(c);
+
+ pa_operation *o;
+ PulseUserData *u = new PulseUserData;
+ if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) {
+ logMessage(QString("pa_ext_device_manager_read() failed."));
+ delete u;
+ return;
+ }
+ pa_operation_unref(o);
+}
+#endif
+
+void sink_input_cb(pa_context *c, const pa_sink_input_info *i, int eol, void *userdata) {
+ Q_UNUSED(userdata);
+ Q_ASSERT(c);
+
+ if (eol < 0) {
+ if (pa_context_errno(c) == PA_ERR_NOENTITY)
+ return;
+
+ logMessage(QString("Sink input callback failure"));
+ return;
+ }
+
+ if (eol > 0)
+ return;
+
+ Q_ASSERT(i);
+
+ // loop through (*i) and extract phonon->streamindex...
+ const char *t;
+ if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) {
+ logMessage(QString("Found PulseAudio stream index %1 for Phonon Output Stream %2").arg(i->index).arg(t));
+ s_outputStreamIndexMap[QString(t)] = i->index;
+
+ // Find the sink's phonon index and notify whoever cares...
+ if (PA_INVALID_INDEX != i->sink) {
+ bool found = false;
+ int device;
+ QMap<int, AudioDevice>::iterator it;
+ for (it = s_outputDevices.begin(); it != s_outputDevices.end(); ++it) {
+ if ((*it).pulseIndex == i->sink) {
+ found = true;
+ device = it.key();
+ break;
+ }
+ }
+ if (found) {
+ // OK so we just emit our signal
+ logMessage(QString("Letting the rest of phonon know about this"));
+ s_instance->emitUsingDevice(QString(t), device);
+ }
+ }
+ }
+}
+
+void source_output_cb(pa_context *c, const pa_source_output_info *i, int eol, void *userdata) {
+ Q_UNUSED(userdata);
+ Q_ASSERT(c);
+
+ if (eol < 0) {
+ if (pa_context_errno(c) == PA_ERR_NOENTITY)
+ return;
+
+ logMessage(QString("Source output callback failure"));
+ return;
+ }
+
+ if (eol > 0)
+ return;
+
+ Q_ASSERT(i);
+
+ // loop through (*i) and extract phonon->streamindex...
+ const char *t;
+ if ((t = pa_proplist_gets(i->proplist, "phonon.streamid"))) {
+ logMessage(QString("Found PulseAudio stream index %1 for Phonon Capture Stream %2").arg(i->index).arg(t));
+ s_captureStreamIndexMap[QString(t)] = i->index;
+
+ // Find the source's phonon index and notify whoever cares...
+ if (PA_INVALID_INDEX != i->source) {
+ bool found = false;
+ int device;
+ QMap<int, AudioDevice>::iterator it;
+ for (it = s_captureDevices.begin(); it != s_captureDevices.end(); ++it) {
+ if ((*it).pulseIndex == i->source) {
+ found = true;
+ device = it.key();
+ break;
+ }
+ }
+ if (found) {
+ // OK so we just emit our signal
+ logMessage(QString("Letting the rest of phonon know about this"));
+ s_instance->emitUsingDevice(QString(t), device);
+ }
+ }
+ }
+}
+
+static void subscribe_cb(pa_context *c, pa_subscription_event_type_t t, uint32_t index, void *userdata) {
+ Q_UNUSED(userdata);
+
+ switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
+ case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ QString phononid = s_outputStreamIndexMap.key(index);
+ if (!phononid.isEmpty()) {
+ if (s_outputStreamIndexMap.contains(phononid)) {
+ logMessage(QString("Phonon Output Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid));
+ s_outputStreamIndexMap[phononid] = PA_INVALID_INDEX;
+ } else {
+ logMessage(QString("Removing Phonon Output Stream %1 (it's gone!)").arg(phononid));
+ s_outputStreamIndexMap.remove(phononid);
+ }
+ }
+ } else {
+ pa_operation *o;
+ if (!(o = pa_context_get_sink_input_info(c, index, sink_input_cb, NULL))) {
+ logMessage(QString("pa_context_get_sink_input_info() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+ break;
+
+ case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
+ if ((t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE) {
+ QString phononid = s_captureStreamIndexMap.key(index);
+ if (!phononid.isEmpty()) {
+ if (s_captureStreamIndexMap.contains(phononid)) {
+ logMessage(QString("Phonon Capture Stream %1 is gone at the PA end. Marking it as invalid in our cache as we may reuse it.").arg(phononid));
+ s_captureStreamIndexMap[phononid] = PA_INVALID_INDEX;
+ } else {
+ logMessage(QString("Removing Phonon Capture Stream %1 (it's gone!)").arg(phononid));
+ s_captureStreamIndexMap.remove(phononid);
+ }
+ }
+ } else {
+ pa_operation *o;
+ if (!(o = pa_context_get_source_output_info(c, index, source_output_cb, NULL))) {
+ logMessage(QString("pa_context_get_sink_input_info() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+ break;
+ }
+}
+
+
+static const char* statename(pa_context_state_t state)
+{
+ switch (state)
+ {
+ case PA_CONTEXT_UNCONNECTED: return "Unconnected";
+ case PA_CONTEXT_CONNECTING: return "Connecting";
+ case PA_CONTEXT_AUTHORIZING: return "Authorizing";
+ case PA_CONTEXT_SETTING_NAME: return "Setting Name";
+ case PA_CONTEXT_READY: return "Ready";
+ case PA_CONTEXT_FAILED: return "Failed";
+ case PA_CONTEXT_TERMINATED: return "Terminated";
+ }
+
+ static QString unknown;
+ unknown = QString("Unknown state: %0").arg(state);
+ return unknown.toAscii().constData();
+}
+
+static void context_state_callback(pa_context *c, void *)
+{
+ Q_ASSERT(c);
+
+ logMessage(QString("context_state_callback %1").arg(statename(pa_context_get_state(c))));
+ pa_context_state_t state = pa_context_get_state(c);
+ if (state == PA_CONTEXT_READY) {
+ // We've connected to PA, so it is active
+ s_pulseActive = true;
+
+ // Attempt to load things up
+ pa_operation *o;
+
+ // 1. Register for the stream changes (except during probe)
+ if (s_context == c) {
+ pa_context_set_subscribe_callback(c, subscribe_cb, NULL);
+
+ if (!(o = pa_context_subscribe(c, (pa_subscription_mask_t)
+ (PA_SUBSCRIPTION_MASK_SINK_INPUT|
+ PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT), NULL, NULL))) {
+ logMessage(QString("pa_context_subscribe() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+ // 2a. Attempt to initialise Device Manager info (except during probe)
+ if (s_context == c) {
+ pa_ext_device_manager_set_subscribe_cb(c, ext_device_manager_subscribe_cb, NULL);
+ if (!(o = pa_ext_device_manager_subscribe(c, 1, NULL, NULL))) {
+ logMessage(QString("pa_ext_device_manager_subscribe() failed"));
+ return;
+ }
+ pa_operation_unref(o);
+ }
+
+ // 3. Attempt to read info from Device Manager
+ PulseUserData *u = new PulseUserData;
+ if (!(o = pa_ext_device_manager_read(c, ext_device_manager_read_cb, u))) {
+ logMessage(QString("pa_ext_device_manager_read() failed. Attempting to continue without device manager support"));
+ createGenericDevices();
+ delete u;
+
+ // If this is our probe phase, exit immediately
+ if (s_context != c)
+ pa_context_disconnect(c);
+
+ return;
+ }
+ pa_operation_unref(o);
+
+#else
+ // If we know do not have Device Manager support, we just create our dummy devices now
+ createGenericDevices();
+
+ // If this is our probe phase, exit immediately
+ if (s_context != c)
+ pa_context_disconnect(c);
+#endif
+ } else if (!PA_CONTEXT_IS_GOOD(state)) {
+ /// @todo Deal with reconnection...
+ //logMessage("Connection to PulseAudio lost");
+
+ // If this is our probe phase, exit our context immediately
+ if (s_context != c)
+ pa_context_disconnect(c);
+ }
+}
+#endif // HAVE_PULSEAUDIO
+
+
+PulseSupport* PulseSupport::getInstance()
+{
+ if (NULL == s_instance) {
+ s_instance = new PulseSupport();
+ }
+ return s_instance;
+}
+
+void PulseSupport::shutdown()
+{
+ if (NULL != s_instance) {
+ delete s_instance;
+ s_instance = NULL;
+ }
+}
+
+PulseSupport::PulseSupport()
+ : QObject(), mEnabled(false)
+{
+#ifdef HAVE_PULSEAUDIO
+ // Initialise our map (is there a better way to do this?)
+ s_roleCategoryMap["none"] = Phonon::NoCategory;
+ s_roleCategoryMap["video"] = Phonon::VideoCategory;
+ s_roleCategoryMap["music"] = Phonon::MusicCategory;
+ s_roleCategoryMap["game"] = Phonon::GameCategory;
+ s_roleCategoryMap["event"] = Phonon::NotificationCategory;
+ s_roleCategoryMap["phone"] = Phonon::CommunicationCategory;
+ //s_roleCategoryMap["animation"]; // No Mapping
+ //s_roleCategoryMap["production"]; // No Mapping
+ s_roleCategoryMap["a11y"] = Phonon::AccessibilityCategory;
+
+ // To allow for easy debugging, give an easy way to disable this pulseaudio check
+ QString pulseenv = qgetenv("PHONON_PULSEAUDIO_DISABLE");
+ if (pulseenv.toInt()) {
+ logMessage("PulseAudio support disabled: PHONON_PULSEAUDIO_DISABLE is set");
+ return;
+ }
+
+ // We require a glib event loop
+ if (QLatin1String(QAbstractEventDispatcher::instance()->metaObject()->className())
+ != "QGuiEventDispatcherGlib") {
+ logMessage("Disabling PulseAudio integration for lack of GLib event loop.");
+ return;
+ }
+
+ // First of all conenct to PA via simple/blocking means and if that succeeds,
+ // use a fully async integrated mainloop method to connect and get proper support.
+ pa_mainloop *p_test_mainloop;
+ if (!(p_test_mainloop = pa_mainloop_new())) {
+ logMessage("PulseAudio support disabled: Unable to create mainloop");
+ return;
+ }
+
+ pa_context *p_test_context;
+ if (!(p_test_context = pa_context_new(pa_mainloop_get_api(p_test_mainloop), "libphonon-probe"))) {
+ logMessage("PulseAudio support disabled: Unable to create context");
+ pa_mainloop_free(p_test_mainloop);
+ return;
+ }
+
+ logMessage("Probing for PulseAudio...");
+ // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required
+ if (pa_context_connect(p_test_context, NULL, static_cast<pa_context_flags_t>(0), NULL) < 0) {
+ logMessage(QString("PulseAudio support disabled: %1").arg(pa_strerror(pa_context_errno(p_test_context))));
+ pa_context_disconnect(p_test_context);
+ pa_context_unref(p_test_context);
+ pa_mainloop_free(p_test_mainloop);
+ return;
+ }
+
+ pa_context_set_state_callback(p_test_context, &context_state_callback, NULL);
+ for (;;) {
+ pa_mainloop_iterate(p_test_mainloop, 1, NULL);
+
+ if (!PA_CONTEXT_IS_GOOD(pa_context_get_state(p_test_context))) {
+ logMessage("PulseAudio probe complete.");
+ break;
+ }
+ }
+ pa_context_disconnect(p_test_context);
+ pa_context_unref(p_test_context);
+ pa_mainloop_free(p_test_mainloop);
+
+ if (!s_pulseActive) {
+ logMessage("PulseAudio support is not available.");
+ return;
+ }
+
+ // If we're still here, PA is available.
+ logMessage("PulseAudio support enabled");
+
+ // Now we connect for real using a proper main loop that we can forget
+ // all about processing.
+ s_mainloop = pa_glib_mainloop_new(NULL);
+ Q_ASSERT(s_mainloop);
+ pa_mainloop_api *api = pa_glib_mainloop_get_api(s_mainloop);
+
+ s_context = pa_context_new(api, "libphonon");
+ // (cg) Convert to PA_CONTEXT_NOFLAGS when PulseAudio 0.9.19 is required
+ if (pa_context_connect(s_context, NULL, static_cast<pa_context_flags_t>(0), 0) >= 0)
+ pa_context_set_state_callback(s_context, &context_state_callback, NULL);
+#endif
+}
+
+PulseSupport::~PulseSupport()
+{
+#ifdef HAVE_PULSEAUDIO
+ if (s_context) {
+ pa_context_disconnect(s_context);
+ s_context = NULL;
+ }
+
+ if (s_mainloop) {
+ pa_glib_mainloop_free(s_mainloop);
+ s_mainloop = NULL;
+ }
+#endif
+}
+
+bool PulseSupport::isActive()
+{
+#ifdef HAVE_PULSEAUDIO
+ return mEnabled && s_pulseActive;
+#else
+ return false;
+#endif
+}
+
+void PulseSupport::enable(bool enabled)
+{
+ mEnabled = enabled;
+}
+
+QList<int> PulseSupport::objectDescriptionIndexes(ObjectDescriptionType type) const
+{
+ QList<int> list;
+
+ if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType)
+ return list;
+
+#ifdef HAVE_PULSEAUDIO
+ if (s_pulseActive) {
+ switch (type) {
+
+ case AudioOutputDeviceType: {
+ QMap<QString, int>::iterator it;
+ for (it = s_outputDeviceIndexes.begin(); it != s_outputDeviceIndexes.end(); ++it) {
+ list.append(*it);
+ }
+ break;
+ }
+ case AudioCaptureDeviceType: {
+ QMap<QString, int>::iterator it;
+ for (it = s_captureDeviceIndexes.begin(); it != s_captureDeviceIndexes.end(); ++it) {
+ list.append(*it);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+#endif
+
+ return list;
+}
+
+QHash<QByteArray, QVariant> PulseSupport::objectDescriptionProperties(ObjectDescriptionType type, int index) const
+{
+ QHash<QByteArray, QVariant> ret;
+
+ if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType)
+ return ret;
+
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(index);
+#else
+ if (s_pulseActive) {
+ switch (type) {
+
+ case AudioOutputDeviceType:
+ Q_ASSERT(s_outputDevices.contains(index));
+ ret = s_outputDevices[index].properties;
+ break;
+
+ case AudioCaptureDeviceType:
+ Q_ASSERT(s_captureDevices.contains(index));
+ ret = s_captureDevices[index].properties;
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+QList<int> PulseSupport::objectIndexesByCategory(ObjectDescriptionType type, Category category) const
+{
+ QList<int> ret;
+
+ if (type != AudioOutputDeviceType && type != AudioCaptureDeviceType)
+ return ret;
+
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+#else
+ if (s_pulseActive) {
+ switch (type) {
+
+ case AudioOutputDeviceType:
+ if (s_outputDevicePriorities.contains(category))
+ ret = s_outputDevicePriorities[category].values();
+ break;
+
+ case AudioCaptureDeviceType:
+ if (s_captureDevicePriorities.contains(category))
+ ret = s_captureDevicePriorities[category].values();
+ break;
+
+ default:
+ break;
+ }
+ }
+#endif
+
+ return ret;
+}
+
+#ifdef HAVE_PULSEAUDIO
+static void setDevicePriority(Category category, QStringList list)
+{
+ QString role = s_roleCategoryMap.key(category);
+ if (role.isEmpty())
+ return;
+
+ logMessage(QString("Reindexing %1: %2").arg(role).arg(list.join(", ")));
+
+ char **devices;
+ devices = pa_xnew(char *, list.size()+1);
+ int i = 0;
+ foreach (QString str, list) {
+ devices[i++] = pa_xstrdup(str.toUtf8().constData());
+ }
+ devices[list.size()] = NULL;
+
+#ifdef HAVE_PULSEAUDIO_DEVICE_MANAGER
+ pa_operation *o;
+ if (!(o = pa_ext_device_manager_reorder_devices_for_role(s_context, role.toUtf8().constData(), (const char**)devices, NULL, NULL)))
+ logMessage(QString("pa_ext_device_manager_reorder_devices_for_role() failed"));
+ else
+ pa_operation_unref(o);
+#endif
+
+ for (i = 0; i < list.size(); ++i)
+ pa_xfree(devices[i]);
+ pa_xfree(devices);
+}
+#endif
+
+void PulseSupport::setOutputDevicePriorityForCategory(Category category, QList<int> order)
+{
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+ Q_UNUSED(order);
+#else
+ QStringList list;
+ QList<int>::iterator it;
+
+ for (it = order.begin(); it != order.end(); ++it) {
+ if (s_outputDevices.contains(*it)) {
+ list << s_outputDeviceIndexes.key(*it);
+ }
+ }
+ setDevicePriority(category, list);
+#endif
+}
+
+void PulseSupport::setCaptureDevicePriorityForCategory(Category category, QList<int> order)
+{
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+ Q_UNUSED(order);
+#else
+ QStringList list;
+ QList<int>::iterator it;
+
+ for (it = order.begin(); it != order.end(); ++it) {
+ if (s_captureDevices.contains(*it)) {
+ list << s_captureDeviceIndexes.key(*it);
+ }
+ }
+ setDevicePriority(category, list);
+#endif
+}
+
+void PulseSupport::setStreamPropList(Category category, QString streamUuid)
+{
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(category);
+ Q_UNUSED(streamUuid);
+#else
+ QString role = s_roleCategoryMap.key(category);
+ if (role.isEmpty())
+ return;
+
+ logMessage(QString("Setting role to %1 for streamindex %2").arg(role).arg(streamUuid));
+ setenv("PULSE_PROP_media.role", role.toLatin1().constData(), 1);
+ setenv("PULSE_PROP_phonon.streamid", streamUuid.toLatin1().constData(), 1);
+#endif
+}
+
+void PulseSupport::emitObjectDescriptionChanged(ObjectDescriptionType type)
+{
+ emit objectDescriptionChanged(type);
+}
+
+void PulseSupport::emitUsingDevice(QString streamUuid, int device)
+{
+ emit usingDevice(streamUuid, device);
+}
+
+bool PulseSupport::setOutputDevice(QString streamUuid, int device) {
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(streamUuid);
+ Q_UNUSED(device);
+ return false;
+#else
+ if (s_outputDevices.size() < 2)
+ return true;
+
+ if (!s_outputDevices.contains(device)) {
+ logMessage(QString("Attempting to set Output Device for invalid device id %1.").arg(device));
+ return false;
+ }
+ const QVariant var = s_outputDevices[device].properties["name"];
+ logMessage(QString("Attempting to set Output Device to '%1' for Output Stream %2").arg(var.toString()).arg(streamUuid));
+
+ // Attempt to look up the pulse stream index.
+ if (s_outputStreamIndexMap.contains(streamUuid) && s_outputStreamIndexMap[streamUuid] != PA_INVALID_INDEX) {
+ logMessage(QString("... Found in map. Moving now"));
+
+ uint32_t pulse_device_index = s_outputDevices[device].pulseIndex;
+ uint32_t pulse_stream_index = s_outputStreamIndexMap[streamUuid];
+
+ logMessage(QString("Moving Pulse Sink Input %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index));
+
+ /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db.
+ pa_operation* o;
+ if (!(o = pa_context_move_sink_input_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) {
+ logMessage(QString("pa_context_move_sink_input_by_index() failed"));
+ return false;
+ }
+ pa_operation_unref(o);
+ } else {
+ logMessage(QString("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then"));
+ }
+ return true;
+#endif
+}
+
+bool PulseSupport::setCaptureDevice(QString streamUuid, int device) {
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(streamUuid);
+ Q_UNUSED(device);
+ return false;
+#else
+ if (s_captureDevices.size() < 2)
+ return true;
+
+ if (!s_captureDevices.contains(device)) {
+ logMessage(QString("Attempting to set Capture Device for invalid device id %1.").arg(device));
+ return false;
+ }
+ const QVariant var = s_captureDevices[device].properties["name"];
+ logMessage(QString("Attempting to set Capture Device to '%1' for Capture Stream %2").arg(var.toString()).arg(streamUuid));
+
+ // Attempt to look up the pulse stream index.
+ if (s_captureStreamIndexMap.contains(streamUuid) && s_captureStreamIndexMap[streamUuid] == PA_INVALID_INDEX) {
+ logMessage(QString("... Found in map. Moving now"));
+
+ uint32_t pulse_device_index = s_captureDevices[device].pulseIndex;
+ uint32_t pulse_stream_index = s_captureStreamIndexMap[streamUuid];
+
+ logMessage(QString("Moving Pulse Source Output %1 to '%2' (Pulse Sink %3)").arg(pulse_stream_index).arg(var.toString()).arg(pulse_device_index));
+
+ /// @todo Find a way to move the stream without saving it... We don't want to pollute the stream restore db.
+ pa_operation* o;
+ if (!(o = pa_context_move_source_output_by_index(s_context, pulse_stream_index, pulse_device_index, NULL, NULL))) {
+ logMessage(QString("pa_context_move_source_output_by_index() failed"));
+ return false;
+ }
+ pa_operation_unref(o);
+ } else {
+ logMessage(QString("... Not found in map. We will be notified of the device when the stream appears and we can process any moves needed then"));
+ }
+ return true;
+#endif
+}
+
+void PulseSupport::clearStreamCache(QString streamUuid) {
+#ifndef HAVE_PULSEAUDIO
+ Q_UNUSED(streamUuid);
+ return;
+#else
+ logMessage(QString("Clearing stream cache for stream %1").arg(streamUuid));
+ s_outputStreamIndexMap.remove(streamUuid);
+ s_captureStreamIndexMap.remove(streamUuid);
+#endif
+}
+
+} // namespace Phonon
+
+QT_END_NAMESPACE
+
+#include "moc_pulsesupport.cpp"
+
+// vim: sw=4 ts=4
diff --git a/src/3rdparty/phonon/phonon/pulsesupport.h b/src/3rdparty/phonon/phonon/pulsesupport.h
new file mode 100644
index 0000000..c38bece
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/pulsesupport.h
@@ -0,0 +1,78 @@
+/* This file is part of the KDE project
+ Copyright (C) 2009 Colin Guthrie <cguthrie@mandriva.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef PHONON_PULSESUPPORT_H
+#define PHONON_PULSESUPPORT_H
+
+#include "phonon_export.h"
+#include "phononnamespace.h"
+#include "objectdescription.h"
+
+#include <QtCore/QtGlobal>
+#include <QtCore/QSet>
+
+QT_BEGIN_HEADER
+QT_BEGIN_NAMESPACE
+
+namespace Phonon
+{
+ class PHONON_EXPORT PulseSupport : public QObject
+ {
+ Q_OBJECT
+ public:
+ static PulseSupport* getInstance();
+ static void shutdown();
+
+ bool isActive();
+ void enable(bool enabled = true);
+
+ QList<int> objectDescriptionIndexes(ObjectDescriptionType type) const;
+ QHash<QByteArray, QVariant> objectDescriptionProperties(ObjectDescriptionType type, int index) const;
+ QList<int> objectIndexesByCategory(ObjectDescriptionType type, Category category) const;
+
+ void setOutputDevicePriorityForCategory(Category category, QList<int> order);
+ void setCaptureDevicePriorityForCategory(Category category, QList<int> order);
+
+ void setStreamPropList(Category category, QString streamUuid);
+ void emitObjectDescriptionChanged(ObjectDescriptionType);
+ void emitUsingDevice(QString streamUuid, int device);
+
+ bool setOutputDevice(QString streamUuid, int device);
+ bool setCaptureDevice(QString streamUuid, int device);
+ void clearStreamCache(QString streamUuid);
+
+ signals:
+ void objectDescriptionChanged(ObjectDescriptionType);
+ void usingDevice(QString streamUuid, int device);
+
+ private:
+ PulseSupport();
+ ~PulseSupport();
+
+ bool mEnabled;
+ };
+} // namespace Phonon
+
+QT_END_NAMESPACE
+QT_END_HEADER
+
+#endif // PHONON_PULSESUPPORT_H
diff --git a/src/3rdparty/phonon/phonon/seekslider.cpp b/src/3rdparty/phonon/phonon/seekslider.cpp
index 41baf2d..b5b25f0 100644
--- a/src/3rdparty/phonon/phonon/seekslider.cpp
+++ b/src/3rdparty/phonon/phonon/seekslider.cpp
@@ -72,12 +72,12 @@ void SeekSlider::setMediaObject(MediaObject *media)
d->media = media;
if (media) {
- connect(media, SIGNAL(stateChanged(Phonon::State,Phonon::State)),
+ connect(media, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
SLOT(_k_stateChanged(Phonon::State)));
connect(media, SIGNAL(totalTimeChanged(qint64)), SLOT(_k_length(qint64)));
connect(media, SIGNAL(tick(qint64)), SLOT(_k_tick(qint64)));
connect(media, SIGNAL(seekableChanged(bool)), SLOT(_k_seekableChanged(bool)));
- connect(media, SIGNAL(currentSourceChanged(Phonon::MediaSource)), SLOT(_k_currentSourceChanged()));
+ connect(media, SIGNAL(currentSourceChanged(const Phonon::MediaSource&)), SLOT(_k_currentSourceChanged()));
d->_k_stateChanged(media->state());
d->_k_seekableChanged(media->isSeekable());
d->_k_length(media->totalTime());
diff --git a/src/3rdparty/phonon/phonon/seekslider_p.h b/src/3rdparty/phonon/phonon/seekslider_p.h
index c87a4b0..911ab25 100644
--- a/src/3rdparty/phonon/phonon/seekslider_p.h
+++ b/src/3rdparty/phonon/phonon/seekslider_p.h
@@ -24,8 +24,8 @@
#define SEEKSLIDER_P_H
#include "seekslider.h"
+#include "swiftslider_p.h"
#include <QtGui/QBoxLayout>
-#include <QtGui/QSlider>
#include <QtGui/QLabel>
#include <QtGui/QPixmap>
#include <QtGui/QIcon>
@@ -84,7 +84,7 @@ class SeekSliderPrivate
void _k_currentSourceChanged();
QBoxLayout layout;
- QSlider slider;
+ SwiftSlider slider;
QLabel iconLabel;
QPointer<MediaObject> media;
bool ticking;
diff --git a/src/3rdparty/phonon/phonon/swiftslider.cpp b/src/3rdparty/phonon/phonon/swiftslider.cpp
new file mode 100644
index 0000000..1e274aa
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/swiftslider.cpp
@@ -0,0 +1,103 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#include "swiftslider_p.h"
+
+#include <QtGui/QMouseEvent>
+#include <QtGui/QStyle>
+#include <QtGui/QStyleOption>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER)
+
+namespace Phonon
+{
+
+SwiftSlider::SwiftSlider(Qt::Orientation orientation, QWidget * parent)
+ : QSlider(orientation, parent)
+{
+}
+
+SwiftSlider::~SwiftSlider()
+{
+}
+
+// Function copied from qslider.cpp
+inline int SwiftSlider::pick(const QPoint &pt) const
+{
+ return orientation() == Qt::Horizontal ? pt.x() : pt.y();
+}
+
+// Function copied from qslider.cpp and modified to make it compile
+int SwiftSlider::pixelPosToRangeValue(int pos) const
+{
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+ QRect gr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
+ QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
+ int sliderMin, sliderMax, sliderLength;
+
+ if (orientation() == Qt::Horizontal) {
+ sliderLength = sr.width();
+ sliderMin = gr.x();
+ sliderMax = gr.right() - sliderLength + 1;
+ } else {
+ sliderLength = sr.height();
+ sliderMin = gr.y();
+ sliderMax = gr.bottom() - sliderLength + 1;
+ }
+ return QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin,
+ sliderMax - sliderMin, opt.upsideDown);
+}
+
+// Based on code from qslider.cpp
+void SwiftSlider::mousePressEvent(QMouseEvent *event)
+{
+ if (event->button() == Qt::LeftButton) {
+ QStyleOptionSlider opt;
+ initStyleOption(&opt);
+ const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
+ const QPoint center = sliderRect.center() - sliderRect.topLeft();
+ // to take half of the slider off for the setSliderPosition call we use the center - topLeft
+
+ if (!sliderRect.contains(event->pos())) {
+ event->accept();
+
+ setSliderPosition(pixelPosToRangeValue(pick(event->pos() - center)));
+ triggerAction(SliderMove);
+ setRepeatAction(SliderNoAction);
+ } else {
+ QSlider::mousePressEvent(event);
+ }
+ } else {
+ QSlider::mousePressEvent(event);
+ }
+}
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+
+#include "moc_swiftslider_p.cpp"
diff --git a/src/3rdparty/phonon/phonon/swiftslider_p.h b/src/3rdparty/phonon/phonon/swiftslider_p.h
new file mode 100644
index 0000000..b063b47
--- /dev/null
+++ b/src/3rdparty/phonon/phonon/swiftslider_p.h
@@ -0,0 +1,68 @@
+/* This file is part of the KDE project
+ Copyright (C) 2006-2008 Ricardo Villalba <rvm@escomposlinux.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) version 3, or any
+ later version accepted by the membership of KDE e.V. (or its
+ successor approved by the membership of KDE e.V.), Nokia Corporation
+ (or its successors, if any) and the KDE Free Qt Foundation, which shall
+ act as a proxy defined in Section 6 of version 3 of the license.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library. If not, see <http://www.gnu.org/licenses/>.
+
+*/
+
+#ifndef SWIFTSLIDER_H
+#define SWIFTSLIDER_H
+
+#include <QtGui/QSlider>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_PHONON_SEEKSLIDER) && !defined(QT_NO_PHONON_VOLUMESLIDER)
+
+namespace Phonon
+{
+
+/** \class SwiftSlider swiftslider_p.h phonon/SwiftSlider
+ * \short Modified QSlider that allows sudden/quick moves instead of stepped moves ("Click'n'Go" QSlider)
+ *
+ * This is an internal class used by SeekSlider and VolumeSlider.
+ *
+ * Ricardo Villalba, the original author of MySlider.cpp (from the SMPlayer project)
+ * gave his permission for the inclusion of this code inside Phonon by
+ * switching MySlider.cpp to the LGPLv2.1+ license.
+ * See http://smplayer.svn.sourceforge.net/viewvc/smplayer/smplayer/trunk/src/myslider.cpp?revision=2406&view=markup
+ *
+ * The original discussion about a "Click'n'Go QSlider": http://lists.trolltech.com/qt-interest/2006-11/msg00363.html
+ *
+ * \ingroup PhononWidgets
+ */
+class SwiftSlider : public QSlider
+{
+ Q_OBJECT
+public:
+ SwiftSlider(Qt::Orientation orientation, QWidget * parent);
+ ~SwiftSlider();
+
+private:
+ void mousePressEvent(QMouseEvent *event);
+ inline int pick(const QPoint &pt) const;
+ int pixelPosToRangeValue(int pos) const;
+};
+
+} // namespace Phonon
+
+#endif //QT_NO_PHONON_VOLUMESLIDER && QT_NO_PHONON_VOLUMESLIDER
+
+QT_END_NAMESPACE
+
+#endif //SWIFTSLIDER_H
diff --git a/src/3rdparty/phonon/phonon/videowidget.cpp b/src/3rdparty/phonon/phonon/videowidget.cpp
index a9e83a6..4575dfd 100644
--- a/src/3rdparty/phonon/phonon/videowidget.cpp
+++ b/src/3rdparty/phonon/phonon/videowidget.cpp
@@ -28,8 +28,9 @@
#include "phononnamespace_p.h"
#include <QtGui/QAction>
-
-#define PHONON_INTERFACENAME VideoWidgetInterface
+#define IFACES4 VideoWidgetInterface44
+#define IFACES0 VideoWidgetInterface, IFACES4
+#define PHONON_INTERFACENAME IFACES0
QT_BEGIN_NAMESPACE
@@ -48,6 +49,8 @@ VideoWidget::VideoWidget(QWidget *parent)
setMouseTracking(true);
}
+
+
VideoWidget::VideoWidget(VideoWidgetPrivate &dd, QWidget *parent)
: QWidget(parent),
Phonon::AbstractVideoOutput(dd)
@@ -98,6 +101,15 @@ PHONON_INTERFACE_SETTER(setHue, hue, qreal)
PHONON_INTERFACE_GETTER(qreal, saturation, d->saturation)
PHONON_INTERFACE_SETTER(setSaturation, saturation, qreal)
+
+QImage VideoWidget::snapshot() const {
+ K_D(const VideoWidget);
+ ConstIface<IFACES4> iface(d);
+ if(iface) return iface->snapshot();
+ return QImage(); // TODO not implemented in VideoInterface
+}
+
+
void VideoWidget::setFullScreen(bool newFullScreen)
{
pDebug() << Q_FUNC_INFO << newFullScreen;
diff --git a/src/3rdparty/phonon/phonon/videowidget.h b/src/3rdparty/phonon/phonon/videowidget.h
index 1d95490..804e61a 100644
--- a/src/3rdparty/phonon/phonon/videowidget.h
+++ b/src/3rdparty/phonon/phonon/videowidget.h
@@ -172,6 +172,7 @@ class AbstractVideoOutput;
qreal contrast() const;
qreal hue() const;
qreal saturation() const;
+ QImage snapshot() const;
//TODO: bar colors property
public Q_SLOTS:
diff --git a/src/3rdparty/phonon/phonon/videowidgetinterface.h b/src/3rdparty/phonon/phonon/videowidgetinterface.h
index 3e6fd22..0c33956 100644
--- a/src/3rdparty/phonon/phonon/videowidgetinterface.h
+++ b/src/3rdparty/phonon/phonon/videowidgetinterface.h
@@ -53,8 +53,21 @@ class VideoWidgetInterface
//X virtual int overlayCapabilities() const = 0;
//X virtual bool createOverlay(QWidget *widget, int type) = 0;
};
+
+class VideoWidgetInterface44 : public VideoWidgetInterface
+{
+ public:
+ virtual QImage snapshot() const = 0;
+};
}
+#ifdef PHONON_BACKEND_VERSION_4_4
+namespace Phonon { typedef VideoWidgetInterface44 VideoWidgetInterfaceLatest; }
+#else
+namespace Phonon { typedef VideoWidgetInterface VideoWidgetInterfaceLatest; }
+#endif
+
+Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface44, "VideoWidgetInterface44.phonon.kde.org")
Q_DECLARE_INTERFACE(Phonon::VideoWidgetInterface, "VideoWidgetInterface3.phonon.kde.org")
#endif //QT_NO_PHONON_VIDEO
diff --git a/src/3rdparty/phonon/phonon/volumeslider_p.h b/src/3rdparty/phonon/phonon/volumeslider_p.h
index 3827659..623275f 100644
--- a/src/3rdparty/phonon/phonon/volumeslider_p.h
+++ b/src/3rdparty/phonon/phonon/volumeslider_p.h
@@ -24,8 +24,8 @@
#define VOLUMESLIDER_P_H
#include "volumeslider.h"
+#include "swiftslider_p.h"
#include <QtGui/QBoxLayout>
-#include <QtGui/QSlider>
#include <QtGui/QLabel>
#include <QtGui/QPixmap>
#include <QtGui/QToolButton>
@@ -83,7 +83,7 @@ class VolumeSliderPrivate
private:
QBoxLayout layout;
- QSlider slider;
+ SwiftSlider slider;
QToolButton muteButton;
QIcon volumeIcon;
QIcon mutedIcon;
diff --git a/src/3rdparty/phonon/qt7/audionode.h b/src/3rdparty/phonon/qt7/audionode.h
index 2498e49..dfec817f 100644
--- a/src/3rdparty/phonon/qt7/audionode.h
+++ b/src/3rdparty/phonon/qt7/audionode.h
@@ -72,7 +72,7 @@ namespace QT7
AudioUnit m_audioUnit;
// Only the following methods needs to
- // be overidden by only_one-audio-unit nodes:
+ // be overridden by only_one-audio-unit nodes:
virtual ComponentDescription getAudioNodeDescription() const;
virtual void initializeAudioUnit();
diff --git a/src/3rdparty/phonon/qt7/audionode.mm b/src/3rdparty/phonon/qt7/audionode.mm
index 961230c..77cd627 100644
--- a/src/3rdparty/phonon/qt7/audionode.mm
+++ b/src/3rdparty/phonon/qt7/audionode.mm
@@ -77,6 +77,7 @@ void AudioNode::createAndConnectAUNodes()
// AudioComponentDescription only exists on 10.6+. More fun than we need to
// deal with at the moment, so we'll take the "deprecated" warning instead.
err = AUGraphNewNode(m_audioGraph->audioGraphRef(), &description, 0, 0, &m_auNode);
+
BACKEND_ASSERT2(err != kAUGraphErr_OutputNodeErr, "A MediaObject can only be connected to one audio output device.", FATAL_ERROR)
BACKEND_ASSERT2(err == noErr, "Could not create new AUNode.", FATAL_ERROR)
}
diff --git a/src/3rdparty/phonon/qt7/backendinfo.mm b/src/3rdparty/phonon/qt7/backendinfo.mm
index 0d51db0..d84e014 100644
--- a/src/3rdparty/phonon/qt7/backendinfo.mm
+++ b/src/3rdparty/phonon/qt7/backendinfo.mm
@@ -15,6 +15,12 @@
along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#import <QTKit/QTMovie.h>
+#ifdef QUICKTIME_C_API_AVAILABLE
+ #include <QuickTime/QuickTime.h>
+ #undef check // avoid name clash;
+#endif
+
#include "backendinfo.h"
#include "backendheader.h"
@@ -22,13 +28,6 @@
#include <AudioUnit/AudioUnit.h>
#include <CoreServices/CoreServices.h>
-#include <QtGui/qmacdefines_mac.h>
-#import <QTKit/QTMovie.h>
-
-#ifdef QUICKTIME_C_API_AVAILABLE
- #include <QuickTime/QuickTime.h>
- #undef check // avoid name clash;
-#endif
QT_BEGIN_NAMESPACE
diff --git a/src/3rdparty/phonon/qt7/mediaobject.h b/src/3rdparty/phonon/qt7/mediaobject.h
index c93eddc..27949ec 100644
--- a/src/3rdparty/phonon/qt7/mediaobject.h
+++ b/src/3rdparty/phonon/qt7/mediaobject.h
@@ -25,10 +25,6 @@
#include "medianode.h"
-#if QT_ALLOW_QUICKTIME
- #include <QuickTime/QuickTime.h>
-#endif
-
QT_BEGIN_NAMESPACE
namespace Phonon
@@ -42,10 +38,7 @@ namespace QT7
class MediaObjectAudioNode;
class MediaObject : public MediaNode,
- public Phonon::MediaObjectInterface
-#ifndef QT_NO_PHONON_MEDIACONTROLLER
- , public Phonon::AddonInterface
-#endif
+ public Phonon::MediaObjectInterface, public Phonon::AddonInterface
{
Q_OBJECT
Q_INTERFACES(Phonon::MediaObjectInterface Phonon::AddonInterface)
@@ -99,10 +92,6 @@ namespace QT7
int videoOutputCount();
-#if QT_ALLOW_QUICKTIME
- void displayLinkEvent();
-#endif
-
signals:
void stateChanged(Phonon::State,Phonon::State);
void tick(qint64);
@@ -116,16 +105,6 @@ 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);
@@ -139,14 +118,7 @@ namespace QT7
QuickTimeVideoPlayer *m_nextVideoPlayer;
QuickTimeAudioPlayer *m_nextAudioPlayer;
MediaObjectAudioNode *m_mediaObjectAudioNode;
-
-#if QT_ALLOW_QUICKTIME
- CVDisplayLinkRef m_displayLink;
- QMutex m_displayLinkMutex;
- bool m_pendingDisplayLinkEvent;
- void startDisplayLink();
- void stopDisplayLink();
-#endif
+ QuickTimeMetaData *m_metaData;
qint32 m_tickInterval;
qint32 m_transitionTime;
@@ -155,14 +127,12 @@ namespace QT7
float m_percentageLoaded;
int m_tickTimer;
- int m_videoTimer;
- int m_audioTimer;
+ int m_bufferTimer;
int m_rapidTimer;
bool m_waitNextSwap;
int m_swapTimeLeft;
QTime m_swapTime;
- bool m_autoplayTitles;
void synchAudioVideo();
void updateCurrentTime();
@@ -171,7 +141,8 @@ namespace QT7
void pause_internal();
void play_internal();
void setupAudioSystem();
- void restartAudioVideoTimers();
+ void updateTimer(int &timer, int interval);
+ void bufferAudioVideo();
void updateRapidly();
void updateCrossFade();
void updateAudioBuffers();
@@ -183,7 +154,6 @@ 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 677640c..002c337 100644
--- a/src/3rdparty/phonon/qt7/mediaobject.mm
+++ b/src/3rdparty/phonon/qt7/mediaobject.mm
@@ -46,6 +46,7 @@ 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;
@@ -54,7 +55,6 @@ 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,28 +63,20 @@ MediaObject::MediaObject(QObject *parent) : MediaNode(AudioSource | VideoSource,
m_errorType = Phonon::NoError;
m_tickTimer = 0;
- m_videoTimer = 0;
- m_audioTimer = 0;
+ m_bufferTimer = 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.
-#if QT_ALLOW_QUICKTIME
- stopDisplayLink();
-#endif
+{
+ // m_mediaObjectAudioNode is owned by super class.
m_audioPlayer->unsetVideoPlayer();
m_nextAudioPlayer->unsetVideoPlayer();
delete m_videoPlayer;
delete m_nextVideoPlayer;
+ delete m_metaData;
checkForError();
}
@@ -96,7 +88,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;
}
}
@@ -130,7 +122,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;
@@ -142,7 +134,7 @@ void MediaObject::inspectGraph()
if (m_videoOutputCount != prevVideoOutputCount){
MediaNodeEvent e1(MediaNodeEvent::VideoOutputCountChanged, &m_videoOutputCount);
notify(&e1);
- }
+ }
}
void MediaObject::setupAudioSystem()
@@ -175,14 +167,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;
@@ -222,28 +214,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->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_currentTime = 0;
-
+
// Emit/notify information about the new source:
QRect videoRect = m_videoPlayer->videoRect();
MediaNodeEvent e1(MediaNodeEvent::VideoFrameSizeChanged, &videoRect);
@@ -254,14 +246,12 @@ void MediaObject::setSource(const MediaSource &source)
updateVideo(emptyFrame);
emit currentSourceChanged(source);
- emit metaDataChanged(m_videoPlayer->metaData());
+ emit metaDataChanged(m_metaData->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());
+ emit totalTimeChanged(totalTime());
if (checkForError())
return;
if (!m_videoPlayer->isDrmAuthorized())
@@ -270,7 +260,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:
@@ -297,30 +287,28 @@ 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_videoPlayer->metaData());
+ emit metaDataChanged(m_metaData->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())
@@ -339,107 +327,28 @@ void MediaObject::swapCurrentWithNext(qint32 transitionTime)
}
}
-#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()
+void MediaObject::updateTimer(int &timer, int 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();
+ if (timer)
+ killTimer(timer);
+ timer = 0;
+ if (interval >= 0)
+ timer = startTimer(interval);
}
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();
}
- restartAudioVideoTimers();
- if (!m_rapidTimer)
- m_rapidTimer = startTimer(100);
+ bufferAudioVideo();
+ updateTimer(m_rapidTimer, 100);
}
void MediaObject::pause_internal()
@@ -449,15 +358,9 @@ void MediaObject::pause_internal()
m_nextAudioPlayer->pause();
m_videoPlayer->pause();
m_nextVideoPlayer->pause();
- killTimer(m_rapidTimer);
- killTimer(m_videoTimer);
- killTimer(m_audioTimer);
- m_rapidTimer = 0;
- m_videoTimer = 0;
- m_audioTimer = 0;
-#if QT_ALLOW_QUICKTIME
- stopDisplayLink();
-#endif
+ updateTimer(m_rapidTimer, -1);
+ updateTimer(m_bufferTimer, -1);
+
if (m_waitNextSwap)
m_swapTimeLeft = m_swapTime.msecsTo(QTime::currentTime());
}
@@ -479,7 +382,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);
@@ -520,7 +423,7 @@ void MediaObject::stop()
if (!setState(Phonon::StoppedState))
return;
m_waitNextSwap = false;
- m_nextVideoPlayer->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_nextAudioPlayer->unsetVideoPlayer();
pause_internal();
seek(0);
@@ -532,9 +435,9 @@ void MediaObject::seek(qint64 milliseconds)
IMPLEMENTED;
if (m_state == Phonon::ErrorState)
return;
-
+
// Stop cross-fade if any:
- m_nextVideoPlayer->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_nextAudioPlayer->unsetVideoPlayer();
m_mediaObjectAudioNode->cancelCrossFade();
@@ -543,7 +446,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;
@@ -654,7 +557,7 @@ bool MediaObject::isSeekable() const
qint64 MediaObject::currentTime() const
{
IMPLEMENTED_SILENT;
- const_cast<MediaObject *>(this)->updateCurrentTime();
+ const_cast<MediaObject *>(this)->updateCurrentTime();
return m_currentTime;
}
@@ -664,24 +567,19 @@ void MediaObject::updateCurrentTime()
m_currentTime = (m_audioSystem == AS_Graph) ? m_audioPlayer->currentTime() : m_videoPlayer->currentTime();
quint64 total = m_videoPlayer->duration();
- 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);
+ // 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();
@@ -691,7 +589,7 @@ void MediaObject::updateCurrentTime()
} else {
// We have a next source.
// Check if it's time to swap to next source:
- quint32 mark = qMax(quint64(0), total + m_transitionTime);
+ mark = qMax(quint64(0), total + m_transitionTime);
if (m_waitNextSwap && m_state == Phonon::PlayingState &&
m_transitionTime < m_swapTime.msecsTo(QTime::currentTime())){
swapCurrentWithNext(0);
@@ -794,14 +692,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->unsetCurrentMediaSource();
+ m_nextVideoPlayer->unsetVideo();
m_nextAudioPlayer->unsetVideoPlayer();
}
- }
+ }
}
void MediaObject::updateBufferStatus()
@@ -830,7 +728,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()){
@@ -838,9 +736,9 @@ void MediaObject::updateVideoFrames()
frame.setBackgroundFrame(bgFrame);
frame.setBaseOpacity(m_mediaObjectAudioNode->m_volume1);
}
-
+
// Send the frame through the graph:
- updateVideo(frame);
+ updateVideo(frame);
checkForError();
}
}
@@ -851,7 +749,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)
@@ -865,6 +763,16 @@ 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();
@@ -889,8 +797,8 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
synchAudioVideo();
checkForError();
m_mediaObjectAudioNode->setMute(false);
- if (m_state == Phonon::PlayingState)
- restartAudioVideoTimers();
+ if (m_state == Phonon::PlayingState)
+ bufferAudioVideo();
break;
case MediaNodeEvent::AudioGraphCannotPlay:
case MediaNodeEvent::AudioGraphInitialized:
@@ -901,7 +809,7 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
checkForError();
m_mediaObjectAudioNode->setMute(false);
}
- break;
+ break;
default:
break;
}
@@ -910,67 +818,29 @@ void MediaObject::mediaNodeEvent(const MediaNodeEvent *event)
bool MediaObject::event(QEvent *event)
{
switch (event->type()){
-#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)
+ case QEvent::Timer: {
+ QTimerEvent *timerEvent = static_cast<QTimerEvent *>(event);
+ if (timerEvent->timerId() == m_rapidTimer)
updateRapidly();
- else if (timerId == m_tickTimer)
+ else if (timerEvent->timerId() == m_tickTimer)
emit tick(currentTime());
- else if (timerId == m_videoTimer)
- updateVideoFrames();
- else if (timerId == m_audioTimer)
- updateAudioBuffers();
- break; }
+ else if (timerEvent->timerId() == m_bufferTimer)
+ bufferAudioVideo();
+ }
+ break;
default:
break;
}
return QObject::event(event);
}
-void MediaObject::setCurrentTrack(int track)
+bool MediaObject::hasInterface(Interface /*interface*/) const
{
- if (track == m_videoPlayer->currentTrack() || track < 0 || track >= m_videoPlayer->trackCount())
- return;
-
- m_videoPlayer->setCurrentTrack(track);
- emit titleChanged(track);
- emit metaDataChanged(m_videoPlayer->metaData());
+ return false;
}
-bool MediaObject::hasInterface(Interface iface) const
+QVariant MediaObject::interfaceCall(Interface /*interface*/, int /*command*/, const QList<QVariant> &/*arguments*/)
{
- 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/mediaobjectaudionode.mm b/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
index 66d6041..39b0d4e 100644
--- a/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
+++ b/src/3rdparty/phonon/qt7/mediaobjectaudionode.mm
@@ -15,6 +15,8 @@
along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#import <QTKit/QTMovie.h>
+
#include "mediaobjectaudionode.h"
#include "quicktimeaudioplayer.h"
#include "quicktimevideoplayer.h"
diff --git a/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
index 61c97cc..aefec02 100644
--- a/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
+++ b/src/3rdparty/phonon/qt7/quicktimeaudioplayer.mm
@@ -15,6 +15,8 @@
along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
+#import <QTKit/QTMovie.h>
+
#include "quicktimeaudioplayer.h"
#include "quicktimevideoplayer.h"
#include "audiograph.h"
diff --git a/src/3rdparty/phonon/qt7/quicktimemetadata.h b/src/3rdparty/phonon/qt7/quicktimemetadata.h
index c589535..d524183 100644
--- a/src/3rdparty/phonon/qt7/quicktimemetadata.h
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.h
@@ -38,8 +38,10 @@ namespace QT7
class QuickTimeMetaData
{
public:
- QuickTimeMetaData(QuickTimeVideoPlayer *videoPlayer);
- void update();
+ QuickTimeMetaData();
+ virtual ~QuickTimeMetaData();
+
+ void setVideo(QuickTimeVideoPlayer *videoPlayer);
QMultiMap<QString, QString> metaData();
private:
@@ -47,8 +49,6 @@ 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 2dcc152..4ae3e2c 100644
--- a/src/3rdparty/phonon/qt7/quicktimemetadata.mm
+++ b/src/3rdparty/phonon/qt7/quicktimemetadata.mm
@@ -15,7 +15,8 @@
along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <QtCore/QFileInfo>
+#import <QTKit/QTMovie.h>
+
#include "quicktimemetadata.h"
#include "quicktimevideoplayer.h"
@@ -26,14 +27,19 @@ namespace Phonon
namespace QT7
{
-QuickTimeMetaData::QuickTimeMetaData(QuickTimeVideoPlayer *videoPlayer)
+QuickTimeMetaData::QuickTimeMetaData()
{
- m_videoPlayer = videoPlayer;
+ m_videoPlayer = 0;
m_movieChanged = false;
}
-void QuickTimeMetaData::update()
+QuickTimeMetaData::~QuickTimeMetaData()
+{
+}
+
+void QuickTimeMetaData::setVideo(QuickTimeVideoPlayer *videoPlayer)
{
+ m_videoPlayer = videoPlayer;
m_movieChanged = true;
m_metaData.clear();
}
@@ -141,22 +147,14 @@ void QuickTimeMetaData::readFormattedData(QTMetaDataRef metaDataRef, OSType form
#endif // QUICKTIME_C_API_AVAILABLE
-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()
+void QuickTimeMetaData::readMetaData()
{
+ 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)
@@ -177,17 +175,6 @@ void QuickTimeMetaData::readMetaDataFromMovie()
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 98eacb5..0b3aec2 100644
--- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.h
@@ -20,7 +20,6 @@
#include "backendheader.h"
-#include <QtGui/qmacdefines_mac.h>
#import <QTKit/QTDataReference.h>
#import <QTKit/QTMovie.h>
@@ -39,7 +38,6 @@ namespace Phonon
namespace QT7
{
class QuickTimeStreamReader;
- class QuickTimeMetaData;
class VideoRenderWidgetQTMovieView;
class QuickTimeVideoPlayer : QObject
@@ -57,7 +55,7 @@ namespace QT7
void setMediaSource(const MediaSource &source);
MediaSource mediaSource() const;
- void unsetCurrentMediaSource();
+ void unsetVideo();
void play();
void pause();
@@ -68,13 +66,11 @@ 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);
@@ -87,7 +83,6 @@ namespace QT7
bool setAudioDevice(int id);
void setPlaybackRate(float rate);
QTMovie *qtMovie() const;
- QMultiMap<QString, QString> metaData();
float playbackRate() const;
float prefferedPlaybackRate() const;
@@ -107,12 +102,6 @@ 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:
@@ -126,10 +115,6 @@ 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;
@@ -140,18 +125,13 @@ 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;
@@ -159,26 +139,20 @@ 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 23c76e3..3f76132 100644
--- a/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
+++ b/src/3rdparty/phonon/qt7/quicktimevideoplayer.mm
@@ -20,7 +20,6 @@
#include "videowidget.h"
#include "audiodevice.h"
#include "quicktimestreamreader.h"
-#include "quicktimemetadata.h"
#include <QtCore/QCoreApplication>
#include <QtCore/QEventLoop>
@@ -53,7 +52,6 @@ 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;
@@ -63,16 +61,12 @@ 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();
@@ -83,9 +77,7 @@ QuickTimeVideoPlayer::QuickTimeVideoPlayer() : QObject(0)
QuickTimeVideoPlayer::~QuickTimeVideoPlayer()
{
- PhononAutoReleasePool pool;
- unsetCurrentMediaSource();
- delete m_metaData;
+ unsetVideo();
[(NSObject*)m_primaryRenderingTarget release];
m_primaryRenderingTarget = 0;
#ifdef QUICKTIME_C_API_AVAILABLE
@@ -94,15 +86,6 @@ 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
@@ -142,10 +125,7 @@ bool QuickTimeVideoPlayer::videoFrameChanged()
return false;
QTVisualContextTask(m_visualContext);
- bool changed = QTVisualContextIsNewImageAvailable(m_visualContext, 0);
- if (changed)
- releaseImageCache();
- return changed;
+ return QTVisualContextIsNewImageAvailable(m_visualContext, 0);
#elif defined(QT_MAC_USE_COCOA)
return true;
@@ -160,11 +140,10 @@ CVOpenGLTextureRef QuickTimeVideoPlayer::currentFrameAsCVTexture()
#ifdef QUICKTIME_C_API_AVAILABLE
if (!m_visualContext)
return 0;
- 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;
+ 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;
#else
return 0;
@@ -173,9 +152,6 @@ 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();
@@ -205,11 +181,12 @@ QImage QuickTimeVideoPlayer::currentFrameAsQImage()
glVertex2i(-1, -1);
glEnd();
- m_cachedQImage = m_QImagePixelBuffer->toImage();
+ QImage image = m_QImagePixelBuffer->toImage();
+ CVOpenGLTextureRelease(texture);
// Because of QuickTime, m_QImagePixelBuffer->doneCurrent() will fail.
// So we store, and restore, the context our selves:
prevContext->makeCurrent();
- return m_cachedQImage;
+ return image;
#else
CIImage *img = (CIImage *)currentFrameAsCIImage();
if (!img)
@@ -218,10 +195,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);
- m_cachedQImage = qImg.rgbSwapped();
+ QImage swapped = qImg.rgbSwapped();
[bitmap release];
[img release];
- return m_cachedQImage;
+ return swapped;
#endif
}
@@ -273,7 +250,8 @@ void *QuickTimeVideoPlayer::currentFrameAsCIImage()
#ifdef QUICKTIME_C_API_AVAILABLE
CVOpenGLTextureRef cvImg = currentFrameAsCVTexture();
CIImage *img = [[CIImage alloc] initWithCVImageBuffer:cvImg];
- return img;
+ CVOpenGLTextureRelease(cvImg);
+ return img;
#else
return 0;
#endif
@@ -295,7 +273,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,
@@ -324,7 +302,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)];
}
@@ -335,7 +313,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)];
@@ -348,7 +326,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)];
@@ -367,7 +345,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);
@@ -391,16 +369,11 @@ 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;
@@ -412,7 +385,6 @@ void QuickTimeVideoPlayer::setColors(qreal brightness, qreal contrast, qreal hue
value = saturation;
SetMovieVisualSaturation([m_QTMovie quickTimeMovie], value, 0);
#endif
- releaseImageCache();
}
QRect QuickTimeVideoPlayer::videoRect() const
@@ -425,7 +397,7 @@ QRect QuickTimeVideoPlayer::videoRect() const
return QRect(0, 0, size.width, size.height);
}
-void QuickTimeVideoPlayer::unsetCurrentMediaSource()
+void QuickTimeVideoPlayer::unsetVideo()
{
if (!m_QTMovie)
return;
@@ -438,17 +410,11 @@ void QuickTimeVideoPlayer::unsetCurrentMediaSource()
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
@@ -558,25 +524,18 @@ bool QuickTimeVideoPlayer::codecExistsAccordingToSuffix(const QString &fileName)
void QuickTimeVideoPlayer::setMediaSource(const MediaSource &mediaSource)
{
PhononAutoReleasePool pool;
- unsetCurrentMediaSource();
-
+ unsetVideo();
m_mediaSource = mediaSource;
if (mediaSource.type() == MediaSource::Empty || mediaSource.type() == MediaSource::Invalid){
m_state = NoMedia;
return;
}
-
openMovieFromCurrentMediaSource();
if (errorOccured()){
- unsetCurrentMediaSource();
+ unsetVideo();
return;
}
- prepareCurrentMovieForPlayback();
-}
-
-void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback()
-{
#ifdef QUICKTIME_C_API_AVAILABLE
if (m_visualContext)
SetMovieVisualContext([m_QTMovie quickTimeMovie], m_visualContext);
@@ -584,25 +543,23 @@ void QuickTimeVideoPlayer::prepareCurrentMovieForPlayback()
waitStatePlayable();
if (errorOccured()){
- unsetCurrentMediaSource();
+ unsetVideo();
return;
}
readProtection();
preRollMovie();
if (errorOccured()){
- unsetCurrentMediaSource();
+ unsetVideo();
return;
}
if (!m_playbackRateSat)
m_playbackRate = prefferedPlaybackRate();
checkIfVideoAwailable();
- calculateStaticFps();
enableAudio(m_audioEnabled);
setMute(m_mute);
setVolume(m_masterVolume, m_relativeVolume);
- m_metaData->update();
pause();
}
@@ -616,7 +573,7 @@ void QuickTimeVideoPlayer::openMovieFromCurrentMediaSource()
openMovieFromUrl();
break;
case MediaSource::Disc:
- openMovieFromCompactDisc();
+ CASE_UNSUPPORTED("Could not open media source.", FATAL_ERROR)
break;
case MediaSource::Stream:
openMovieFromStream();
@@ -678,7 +635,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, (char *)"."type); \
+ openMovieFromData(data, "."type); \
if (m_QTMovie) return;
TryOpenMovieWithCodec("avi");
@@ -718,50 +675,6 @@ 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;
@@ -807,44 +720,6 @@ 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;
@@ -1075,94 +950,6 @@ 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 7b67b5e..92a3cd5 100644
--- a/src/3rdparty/phonon/qt7/videoframe.mm
+++ b/src/3rdparty/phonon/qt7/videoframe.mm
@@ -20,8 +20,6 @@
#import <QuartzCore/CIFilter.h>
#import <QuartzCore/CIContext.h>
-//#define CACHE_CV_TEXTURE
-
QT_BEGIN_NAMESPACE
namespace Phonon
@@ -72,9 +70,7 @@ 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;
@@ -109,20 +105,11 @@ 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
@@ -342,12 +329,10 @@ 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;
@@ -361,10 +346,8 @@ 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)
@@ -375,12 +358,8 @@ namespace QT7
void VideoFrame::release() const
{
-#ifdef CACHE_CV_TEXTURE
- if (m_cachedCVTextureRef){
+ if (m_cachedCVTextureRef)
CVOpenGLTextureRelease(m_cachedCVTextureRef);
- (const_cast<VideoFrame *>(this))->m_cachedCVTextureRef = 0;
- }
-#endif
if (m_cachedCIImage)
[(CIImage *) m_cachedCIImage release];
if (m_backgroundFrame)
@@ -389,6 +368,7 @@ 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/.gitattributes b/src/3rdparty/webkit/.gitattributes
new file mode 100644
index 0000000..5b43bd0
--- /dev/null
+++ b/src/3rdparty/webkit/.gitattributes
@@ -0,0 +1,4 @@
+# To enable automatic merging of ChangeLog files, use the following command:
+# git config merge.changelog.driver "resolve-ChangeLogs --merge-driver %O %A %B"
+ChangeLog* merge=changelog
+
diff --git a/src/3rdparty/webkit/ChangeLog b/src/3rdparty/webkit/ChangeLog
index 1e89d1e..57cb0de 100644
--- a/src/3rdparty/webkit/ChangeLog
+++ b/src/3rdparty/webkit/ChangeLog
@@ -1,3 +1,11 @@
+2010-02-18 Tor Arne Vestbø <tor.arne.vestbo@nokia.com>
+
+ Reviewed by Eric Seidel.
+
+ Add .gitattributes file for custom ChangeLog merge-driver
+
+ * .gitattributes: Added.
+
2009-11-30 Jan-Arve Sæther <jan-arve.saether@nokia.com>
Reviewed by Simon Hausmann.
diff --git a/src/3rdparty/webkit/VERSION b/src/3rdparty/webkit/VERSION
index a2d5f37..a8889b3 100644
--- a/src/3rdparty/webkit/VERSION
+++ b/src/3rdparty/webkit/VERSION
@@ -8,4 +8,4 @@ The commit imported was from the
and has the sha1 checksum
- 266a6c4f1938dd9edf4a8125faf91c62495e3ce2
+ e9151b11e974f0aa47fd40c225f88f35ced91496
diff --git a/src/3rdparty/webkit/WebCore/ChangeLog b/src/3rdparty/webkit/WebCore/ChangeLog
index a3f70d3..2bd506b 100644
--- a/src/3rdparty/webkit/WebCore/ChangeLog
+++ b/src/3rdparty/webkit/WebCore/ChangeLog
@@ -1,3 +1,274 @@
+2010-03-25 yael aharon <yael.aharon@nokia.com>
+
+ Reviewed by Laszlo Gombos.
+
+ [Qt] Windowed netscape plugins don't work with QGraphicsWebView on Symbian
+ https://bugs.webkit.org/show_bug.cgi?id=35112
+
+ Add a proxy widget when loading a QWidget based plugin in a QGraphicsWebView.
+
+ * plugins/symbian/PluginContainerSymbian.cpp:
+ (PluginContainerSymbian::PluginContainerSymbian):
+ (PluginContainerSymbian::focusInEvent):
+ * plugins/symbian/PluginContainerSymbian.h:
+ (WebCore::PluginContainerSymbian::proxy):
+ * plugins/symbian/PluginViewSymbian.cpp:
+ (WebCore::PluginView::updatePluginWidget):
+ (WebCore::PluginView::platformStart):
+ (WebCore::PluginView::platformDestroy):
+
+2010-03-29 Laszlo Gombos <laszlo.1.gombos@nokia.com>
+
+ Reviewed for the Qt 4.6 branch by Simon Hausmann.
+
+ Accept XHTML-MP content type as XHTML content
+ https://bugs.webkit.org/show_bug.cgi?id=34262
+
+ Enable processing XHTML-MP mime type as an XHTML document
+ even if XHTML-MP support is not enabled.
+
+ * platform/MIMETypeRegistry.cpp:
+ (WebCore::initializeSupportedNonImageMimeTypes):
+
+2010-03-22 Jakub Wieczorek <jwieczorek@webkit.org>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Don't construct a QLineEdit every time when painting a text field
+ https://bugs.webkit.org/show_bug.cgi?id=36373
+
+ Instead, keep one instance per RenderTheme around.
+
+ * platform/qt/RenderThemeQt.cpp:
+ (WebCore::findFrameLineWidth):
+
+2010-03-26 Janne Koskinen <janne.p.koskinen@digia.com>
+
+ Reviewed by Laszlo Gombos.
+
+ Don't undefine SKIP_STATIC_CONSTRUCTORS_ON_GCC for Symbian HW targets.
+ https://bugs.webkit.org/show_bug.cgi?id=34081
+
+ Defining StringImpl instances as globals will cause a crash on process exit as
+ StringImpl::Remove expects TLS which was already deleted at time of exiting main and ends up
+ constructing one exiting thread.
+
+ * config.h:
+
+2010-02-02 Alexey Proskuryakov <ap@apple.com>
+
+ Reviewed by Darin Adler.
+
+ https://bugs.webkit.org/show_bug.cgi?id=34076
+ <rdar://problem/7594601> Crash in mangleme in WebCore::Element::getAttribute
+
+ Test: fast/forms/misplaced-img-form-registration.html
+
+ * html/HTMLFormElement.cpp:
+ (WebCore::HTMLFormElement::registerImgElement): Assert that the same image isn't added
+ to vector again.
+ (WebCore::HTMLFormElement::removeImgElement): Similarly, assert that we're removing something
+ that's actually registered.
+
+ * html/HTMLImageElement.cpp: (WebCore::HTMLImageElement::~HTMLImageElement): If parser fails
+ to insert the image element, then there will be no removed from tree notification either,
+ need to unregister right away.
+
+2010-01-25 Alexey Proskuryakov <ap@apple.com>
+
+ Rubber-stamped by Geoffrey Garen.
+
+ https://bugs.webkit.org/show_bug.cgi?id=34076
+ An image remains accessible via form.property syntax after being removed from document.
+
+ Fix crashing regression tests (tables/mozilla/bugs/bug4527.html et al.)
+
+ * html/HTMLImageElement.cpp: (WebCore::HTMLImageElement::insertedIntoTree): Remove incorrect
+ assertions added in the previous patch - it's mot true that m_for is always a parent; table
+ parsing can reparent the image element, but m_form still needs to be set.
+
+2010-01-25 Alexey Proskuryakov <ap@apple.com>
+
+ Reviewed by Geoffrey Garen.
+
+ https://bugs.webkit.org/show_bug.cgi?id=34076
+ An image remains accessible via form.property syntax after being removed from document.
+
+ Tests: fast/forms/removed-image-as-property.html
+ fast/forms/reparented-image-as-property.html
+
+ * html/HTMLImageElement.cpp:
+ (WebCore::HTMLImageElement::~HTMLImageElement): This is called during GC - not a good time
+ to make observable changes to DOM.
+ (WebCore::HTMLImageElement::insertedIntoTree): This is the right place to do any work that
+ depends on connectedness to some ancestor. We still allow for m_form to be set via constructor,
+ which happens during parsing.
+ (WebCore::HTMLImageElement::removedFromTree): Ditto.
+
+ * html/HTMLImageElement.h: Added removedFromTree/insertedIntoTree, moved removedFromDocument
+ and insertedIntoDocument to private section, as they shouldn't be called directly.
+
+2009-12-08 Brady Eidson <beidson@apple.com>
+
+ Reviewed by Darin Adler.
+
+ Navigating to a cached page can result in accessing a destroyed HTMLInputElement.
+ <rdar://problem/6856662> and https://webkit.org/b/32293
+
+ Test: fast/loader/input-element-page-cache-crash.html
+
+ * html/HTMLInputElement.cpp:
+ (WebCore::HTMLInputElement::parseMappedAttribute): Make sure to unregister for the activation
+ callback after the new m_autocomplete setting has been stored so the unregistration actually
+ takes place.
+
+2009-12-13 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Simon Fraser.
+
+ <rdar://problem/7341364> Crash at HTMLParser::popOneBlockCommon() after
+ handling misnested residual style tags
+
+ Test: fast/parser/residual-style-close-ref-clone.html
+
+ * html/HTMLParser.cpp:
+ (WebCore::HTMLParser::handleResidualStyleCloseTagAcrossBlocks): Gave the
+ block stack a strong reference to the cloned residual style element.
+
+2009-12-23 Dan Bernstein <mitz@apple.com>
+
+ Reviewed by Darin Adler.
+
+ <rdar://problem/7487164> First line of text cannot be selected
+ https://bugs.webkit.org/show_bug.cgi?id=32749
+
+ Test: fast/text/remove-zero-length-run.html
+
+ * rendering/RenderText.cpp:
+ (WebCore::RenderText::positionLineBox): Changed code that assumed that if a box was being
+ removed, it was the only box in the RenderText. Instead, correctly preserve the list of
+ text boxes.
+ (WebCore::RenderText::checkConsistency): Updated for earlier rename.
+
+2009-12-10 Oliver Hunt <oliver@apple.com>
+
+ Reviewed by Alexey Proskuryakov.
+
+ Crash in XMLTokenizer::popCurrentNode if window.close() is called during parsing
+ https://bugs.webkit.org/show_bug.cgi?id=31576
+
+ Add a RefCounted wrapper object around xmlParserCtxtPtr so we can
+ maintain it's lifetime more effectively.
+
+ Test: fast/parser/xhtml-close-while-parsing.xhtml
+
+ * dom/XMLTokenizer.cpp:
+ (WebCore::XMLTokenizer::popCurrentNode):
+ * dom/XMLTokenizer.h:
+ (WebCore::XMLParserContext::context):
+ (WebCore::XMLParserContext::XMLParserContext):
+ (WebCore::XMLTokenizer::context):
+ * dom/XMLTokenizerLibxml2.cpp:
+ (WebCore::XMLParserContext::createStringParser):
+ (WebCore::XMLParserContext::createMemoryParser):
+ (WebCore::XMLParserContext::~XMLParserContext):
+ (WebCore::XMLTokenizer::~XMLTokenizer):
+ (WebCore::XMLTokenizer::doWrite):
+ (WebCore::XMLTokenizer::initializeParserContext):
+ (WebCore::XMLTokenizer::doEnd):
+ (WebCore::XMLTokenizer::lineNumber):
+ (WebCore::XMLTokenizer::columnNumber):
+ (WebCore::XMLTokenizer::stopParsing):
+ (WebCore::parseXMLDocumentFragment):
+ (WebCore::parseAttributes):
+
+2009-11-09 Anders Carlsson <andersca@apple.com>
+
+ Reviewed by Darin Adler and Dan Bernstein.
+
+ <rdar://problem/7328395>
+ https://bugs.webkit.org/show_bug.cgi?id=31277
+
+ When an object tag's style changes (for example when child nodes are added/removed),
+ reuse its Frame (if it has one) instead of creating multiple Frames.
+
+ Test: fast/dom/HTMLObjectElement/children-changed.html
+
+ * loader/FrameLoader.cpp:
+ (WebCore::FrameLoader::requestObject):
+
+2009-12-05 Adam Langley <agl@google.com>
+
+ Reviewed by Adam Barth.
+
+ Check that a CSS format() argument is of a valid type.
+
+ https://bugs.webkit.org/show_bug.cgi?id=31815
+ http://code.google.com/p/chromium/issues/detail?id=28582
+
+ Test: fast/css/url-format-non-string.html
+
+ * css/CSSParser.cpp:
+ (WebCore::CSSParser::parseFontFaceSrc):
+
+2010-03-19 Miikka Heikkinen <miikka.heikkinen@digia.com>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Support for QT_LIBINFIX in Symbian builds
+
+ Configuring Qt with -qtlibinfix parameter will enable installing
+ an alternate version of Qt on devices that already have it on ROM.
+ This patch provides support for infixed builds of Webkit.
+
+ * WebCore.pro:
+
+2010-01-31 Benjamin Poulain <benjamin.poulain@nokia.com>
+
+ Reviewed by Eric Seidel.
+
+ [Qt] Enable FAST_MOBILE_SCROLLING on Qt embedded platforms
+ https://bugs.webkit.org/show_bug.cgi?id=34168
+
+ Enable FAST_MOBILE_SCROLLING for Qt on Maemo 5, Linux embedded
+ and Symbian
+
+ * WebCore.pro:
+
+2010-01-19 Daniel Bates <dbates@rim.com>
+
+ Reviewed by Adam Treat.
+
+ https://bugs.webkit.org/show_bug.cgi?id=33408
+
+ Implements an optimization to ignore fixed background images
+ (i.e. background-attachment: fixed) when a page does not contain
+ any fixed position elements so as to allow fast repaints (via bit
+ blit) when scrolling a page.
+
+ Currently, if a page has elements that specify either a fixed
+ background or a fixed position then we perform a slow repaint
+ (i.e disable blitting) so as to avoid rendering artifacts.
+ However, on low-powered/mobile devices slow repaints can cause
+ noticeable delays when scrolling a page with a fixed background
+ image. By sacrificing support for fixed background images when
+ there are no fixed elements on the page and with come care, we
+ don't need to force slow repaints and can avoid rendering artifacts.
+ Hence, on such devices we can improve the responsiveness of
+ scrolling a page with a fixed background image.
+
+ Note, this optimization is only enabled if the WebKit is built
+ with FAST_MOBILE_SCROLLING enabled.
+
+ Tests: fast/fast-mobile-scrolling/fixed-position-element.html
+ fast/fast-mobile-scrolling/no-fixed-position-elements.html
+
+ * rendering/RenderBoxModelObject.cpp:
+ (WebCore::RenderBoxModelObject::calculateBackgroundImageGeometry):
+ Disable fixed background attachment if we can blit on scroll.
+ * rendering/RenderObject.cpp:
+ (WebCore::RenderObject::styleWillChange):
+
2010-03-11 Simon Hausmann <simon.hausmann@nokia.com>
Reviewed by Tor Arne Vestbø.
diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro
index 2f85100..5fe9703 100644
--- a/src/3rdparty/webkit/WebCore/WebCore.pro
+++ b/src/3rdparty/webkit/WebCore/WebCore.pro
@@ -6,9 +6,12 @@ symbian: {
TARGET.EPOCALLOWDLLDATA=1
TARGET.EPOCHEAPSIZE = 0x20000 0x2000000 // Min 128kB, Max 32MB
TARGET.CAPABILITY = All -Tcb
- TARGET.UID3 = 0x200267C2
-
- webkitlibs.sources = $$QMAKE_LIBDIR_QT/QtWebKit.dll
+ isEmpty(QT_LIBINFIX) {
+ TARGET.UID3 = 0x200267C2
+ } else {
+ TARGET.UID3 = 0xE00267C2
+ }
+ webkitlibs.sources = $$QMAKE_LIBDIR_QT/QtWebKit$${QT_LIBINFIX}.dll
webkitlibs.path = /sys/bin
vendorinfo = \
"; Localised Vendor name" \
@@ -165,6 +168,10 @@ contains(DEFINES, ENABLE_SINGLE_THREADED=1) {
DEFINES += ENABLE_SVG_FONTS=0 ENABLE_SVG_FOREIGN_OBJECT=0 ENABLE_SVG_ANIMATION=0 ENABLE_SVG_AS_IMAGE=0 ENABLE_SVG_USE=0
}
+mameo5|symbian|embedded {
+ DEFINES += ENABLE_FAST_MOBILE_SCROLLING=1
+}
+
# HTML5 ruby support
!contains(DEFINES, ENABLE_RUBY=.): DEFINES += ENABLE_RUBY=1
diff --git a/src/3rdparty/webkit/WebCore/config.h b/src/3rdparty/webkit/WebCore/config.h
index 62a7f60a..003acbe 100644
--- a/src/3rdparty/webkit/WebCore/config.h
+++ b/src/3rdparty/webkit/WebCore/config.h
@@ -144,7 +144,9 @@
#if PLATFORM(SYMBIAN)
#undef WIN32
#undef _WIN32
+#if COMPILER(WINSCW)
#undef SKIP_STATIC_CONSTRUCTORS_ON_GCC
+#endif
#define USE_SYSTEM_MALLOC 1
#define U_HAVE_INT8_T 0
#define U_HAVE_INT16_T 0
diff --git a/src/3rdparty/webkit/WebCore/css/CSSParser.cpp b/src/3rdparty/webkit/WebCore/css/CSSParser.cpp
index 6024a5b..7750a80 100644
--- a/src/3rdparty/webkit/WebCore/css/CSSParser.cpp
+++ b/src/3rdparty/webkit/WebCore/css/CSSParser.cpp
@@ -3328,6 +3328,12 @@ bool CSSParser::parseFontWeight(bool important)
return false;
}
+static bool isValidFormatFunction(CSSParserValue* val)
+{
+ CSSParserValueList* args = val->function->args;
+ return equalIgnoringCase(val->function->name, "format(") && (args->current()->unit == CSSPrimitiveValue::CSS_STRING || args->current()->unit == CSSPrimitiveValue::CSS_IDENT);
+}
+
bool CSSParser::parseFontFaceSrc()
{
RefPtr<CSSValueList> values(CSSValueList::createCommaSeparated());
@@ -3355,7 +3361,7 @@ bool CSSParser::parseFontFaceSrc()
CSSParserValue* a = args->current();
uriValue.clear();
parsedValue = CSSFontFaceSrcValue::createLocal(a->string);
- } else if (equalIgnoringCase(val->function->name, "format(") && allowFormat && uriValue) {
+ } else if (allowFormat && uriValue && isValidFormatFunction(val)) {
expectComma = true;
allowFormat = false;
uriValue->setFormat(args->current()->string);
diff --git a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.cpp b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.cpp
index 30d39e0..56f8ff4 100644
--- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.cpp
+++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.cpp
@@ -91,7 +91,8 @@ void XMLTokenizer::pushCurrentNode(Node* n)
void XMLTokenizer::popCurrentNode()
{
- ASSERT(m_currentNode);
+ if (!m_currentNode)
+ return;
ASSERT(m_currentNodeStack.size());
if (m_currentNode != m_doc)
diff --git a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h
index a83e73a..3bd15c8 100644
--- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h
+++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizer.h
@@ -52,6 +52,23 @@ namespace WebCore {
class PendingCallbacks;
class ScriptElement;
+#if !USE(QXMLSTREAM)
+ class XMLParserContext : public RefCounted<XMLParserContext> {
+ public:
+ static PassRefPtr<XMLParserContext> createMemoryParser(xmlSAXHandlerPtr, void*, const char*);
+ static PassRefPtr<XMLParserContext> createStringParser(xmlSAXHandlerPtr, void*);
+ ~XMLParserContext();
+ xmlParserCtxtPtr context() const { return m_context; }
+
+ private:
+ XMLParserContext(xmlParserCtxtPtr context)
+ : m_context(context)
+ {
+ }
+ xmlParserCtxtPtr m_context;
+ };
+#endif
+
class XMLTokenizer : public Tokenizer, public CachedResourceClient {
public:
XMLTokenizer(Document*, FrameView* = 0);
@@ -146,7 +163,8 @@ public:
QXmlStreamReader m_stream;
bool m_wroteText;
#else
- xmlParserCtxtPtr m_context;
+ xmlParserCtxtPtr context() const { return m_context ? m_context->context() : 0; };
+ RefPtr<XMLParserContext> m_context;
OwnPtr<PendingCallbacks> m_pendingCallbacks;
Vector<xmlChar> m_bufferedText;
#endif
diff --git a/src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp b/src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp
index 9aa0961..42c8b9b 100644
--- a/src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp
+++ b/src/3rdparty/webkit/WebCore/dom/XMLTokenizerLibxml2.cpp
@@ -465,7 +465,7 @@ static void errorFunc(void*, const char*, ...)
static bool didInit = false;
-static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* userData)
+PassRefPtr<XMLParserContext> XMLParserContext::createStringParser(xmlSAXHandlerPtr handlers, void* userData)
{
if (!didInit) {
xmlInitParser();
@@ -482,12 +482,12 @@ static xmlParserCtxtPtr createStringParser(xmlSAXHandlerPtr handlers, void* user
const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
xmlSwitchEncoding(parser, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
- return parser;
+ return adoptRef(new XMLParserContext(parser));
}
// Chunk should be encoded in UTF-8
-static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
+PassRefPtr<XMLParserContext> XMLParserContext::createMemoryParser(xmlSAXHandlerPtr handlers, void* userData, const char* chunk)
{
if (!didInit) {
xmlInitParser();
@@ -518,8 +518,8 @@ static xmlParserCtxtPtr createMemoryParser(xmlSAXHandlerPtr handlers, void* user
parser->str_xmlns = xmlDictLookup(parser->dict, BAD_CAST "xmlns", 5);
parser->str_xml_ns = xmlDictLookup(parser->dict, XML_XML_NAMESPACE, 36);
parser->_private = userData;
-
- return parser;
+
+ return adoptRef(new XMLParserContext(parser));
}
// --------------------------------
@@ -609,6 +609,13 @@ XMLTokenizer::XMLTokenizer(DocumentFragment* fragment, Element* parentElement)
m_defaultNamespaceURI = parentElement->namespaceURI();
}
+XMLParserContext::~XMLParserContext()
+{
+ if (m_context->myDoc)
+ xmlFreeDoc(m_context->myDoc);
+ xmlFreeParserCtxt(m_context);
+}
+
XMLTokenizer::~XMLTokenizer()
{
clearCurrentNodeStack();
@@ -616,15 +623,16 @@ XMLTokenizer::~XMLTokenizer()
m_doc->deref();
if (m_pendingScript)
m_pendingScript->removeClient(this);
- if (m_context)
- xmlFreeParserCtxt(m_context);
}
void XMLTokenizer::doWrite(const String& parseString)
{
if (!m_context)
initializeParserContext();
-
+
+ // Protect the libxml context from deletion during a callback
+ RefPtr<XMLParserContext> context = m_context;
+
// libXML throws an error if you try to switch the encoding for an empty string.
if (parseString.length()) {
// Hack around libxml2's lack of encoding overide support by manually
@@ -633,15 +641,15 @@ void XMLTokenizer::doWrite(const String& parseString)
// and switch encodings, causing the parse to fail.
const UChar BOM = 0xFEFF;
const unsigned char BOMHighByte = *reinterpret_cast<const unsigned char*>(&BOM);
- xmlSwitchEncoding(m_context, BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
+ xmlSwitchEncoding(context->context(), BOMHighByte == 0xFF ? XML_CHAR_ENCODING_UTF16LE : XML_CHAR_ENCODING_UTF16BE);
XMLTokenizerScope scope(m_doc->docLoader());
- xmlParseChunk(m_context, reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
+ xmlParseChunk(context->context(), reinterpret_cast<const char*>(parseString.characters()), sizeof(UChar) * parseString.length(), 0);
}
if (m_doc->decoder() && m_doc->decoder()->sawError()) {
// If the decoder saw an error, report it as fatal (stops parsing)
- handleError(fatal, "Encoding error", lineNumber(), columnNumber());
+ handleError(fatal, "Encoding error", context->context()->input->line, context->context()->input->col);
}
return;
@@ -1277,9 +1285,9 @@ void XMLTokenizer::initializeParserContext(const char* chunk)
XMLTokenizerScope scope(m_doc->docLoader());
if (m_parsingFragment)
- m_context = createMemoryParser(&sax, this, chunk);
+ m_context = XMLParserContext::createMemoryParser(&sax, this, chunk);
else
- m_context = createStringParser(&sax, this);
+ m_context = XMLParserContext::createStringParser(&sax, this);
}
void XMLTokenizer::doEnd()
@@ -1300,12 +1308,9 @@ void XMLTokenizer::doEnd()
// Tell libxml we're done.
{
XMLTokenizerScope scope(m_doc->docLoader());
- xmlParseChunk(m_context, 0, 0, 1);
+ xmlParseChunk(context(), 0, 0, 1);
}
- if (m_context->myDoc)
- xmlFreeDoc(m_context->myDoc);
- xmlFreeParserCtxt(m_context);
m_context = 0;
}
}
@@ -1334,18 +1339,19 @@ void* xmlDocPtrForString(DocLoader* docLoader, const String& source, const Strin
int XMLTokenizer::lineNumber() const
{
- return m_context ? m_context->input->line : 1;
+ return context() ? context()->input->line : 1;
}
int XMLTokenizer::columnNumber() const
{
- return m_context ? m_context->input->col : 1;
+ return context() ? context()->input->col : 1;
}
void XMLTokenizer::stopParsing()
{
Tokenizer::stopParsing();
- xmlStopParser(m_context);
+ if (context())
+ xmlStopParser(context());
}
void XMLTokenizer::resumeParsing()
@@ -1384,17 +1390,17 @@ bool parseXMLDocumentFragment(const String& chunk, DocumentFragment* fragment, E
CString chunkAsUtf8 = chunk.utf8();
tokenizer.initializeParserContext(chunkAsUtf8.data());
- xmlParseContent(tokenizer.m_context);
+ xmlParseContent(tokenizer.context());
tokenizer.endDocument();
// Check if all the chunk has been processed.
- long bytesProcessed = xmlByteConsumed(tokenizer.m_context);
+ long bytesProcessed = xmlByteConsumed(tokenizer.context());
if (bytesProcessed == -1 || ((unsigned long)bytesProcessed) != chunkAsUtf8.length())
return false;
// No error if the chunk is well formed or it is not but we have no error.
- return tokenizer.m_context->wellFormed || xmlCtxtGetLastError(tokenizer.m_context) == 0;
+ return tokenizer.context()->wellFormed || xmlCtxtGetLastError(tokenizer.context()) == 0;
}
// --------------------------------
@@ -1437,12 +1443,9 @@ HashMap<String, String> parseAttributes(const String& string, bool& attrsOK)
memset(&sax, 0, sizeof(sax));
sax.startElementNs = attributesStartElementNsHandler;
sax.initialized = XML_SAX2_MAGIC;
- xmlParserCtxtPtr parser = createStringParser(&sax, &state);
+ RefPtr<XMLParserContext> parser = XMLParserContext::createStringParser(&sax, &state);
String parseString = "<?xml version=\"1.0\"?><attrs " + string + " />";
- xmlParseChunk(parser, reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
- if (parser->myDoc)
- xmlFreeDoc(parser->myDoc);
- xmlFreeParserCtxt(parser);
+ xmlParseChunk(parser->context(), reinterpret_cast<const char*>(parseString.characters()), parseString.length() * sizeof(UChar), 1);
attrsOK = state.gotAttributes;
return state.attributes;
}
diff --git a/src/3rdparty/webkit/WebCore/html/HTMLFormElement.cpp b/src/3rdparty/webkit/WebCore/html/HTMLFormElement.cpp
index ace0f2f..a74ff83 100644
--- a/src/3rdparty/webkit/WebCore/html/HTMLFormElement.cpp
+++ b/src/3rdparty/webkit/WebCore/html/HTMLFormElement.cpp
@@ -515,11 +515,13 @@ bool HTMLFormElement::isURLAttribute(Attribute* attr) const
void HTMLFormElement::registerImgElement(HTMLImageElement* e)
{
+ ASSERT(imgElements.find(e) == notFound);
imgElements.append(e);
}
void HTMLFormElement::removeImgElement(HTMLImageElement* e)
{
+ ASSERT(imgElements.find(e) != notFound);
removeFromVector(imgElements, e);
}
diff --git a/src/3rdparty/webkit/WebCore/html/HTMLImageElement.cpp b/src/3rdparty/webkit/WebCore/html/HTMLImageElement.cpp
index d353073..3db6811 100644
--- a/src/3rdparty/webkit/WebCore/html/HTMLImageElement.cpp
+++ b/src/3rdparty/webkit/WebCore/html/HTMLImageElement.cpp
@@ -209,6 +209,30 @@ void HTMLImageElement::removedFromDocument()
HTMLElement::removedFromDocument();
}
+void HTMLImageElement::insertedIntoTree(bool deep)
+{
+ if (!m_form) {
+ // m_form can be non-null if it was set in constructor.
+ for (Node* ancestor = parentNode(); ancestor; ancestor = ancestor->parentNode()) {
+ if (ancestor->hasTagName(formTag)) {
+ m_form = static_cast<HTMLFormElement*>(ancestor);
+ m_form->registerImgElement(this);
+ break;
+ }
+ }
+ }
+
+ HTMLElement::insertedIntoTree(deep);
+}
+
+void HTMLImageElement::removedFromTree(bool deep)
+{
+ if (m_form)
+ m_form->removeImgElement(this);
+ m_form = 0;
+ HTMLElement::removedFromTree(deep);
+}
+
int HTMLImageElement::width(bool ignorePendingStylesheets) const
{
if (!renderer()) {
diff --git a/src/3rdparty/webkit/WebCore/html/HTMLImageElement.h b/src/3rdparty/webkit/WebCore/html/HTMLImageElement.h
index f58574d..14e5fa3 100644
--- a/src/3rdparty/webkit/WebCore/html/HTMLImageElement.h
+++ b/src/3rdparty/webkit/WebCore/html/HTMLImageElement.h
@@ -45,8 +45,6 @@ public:
virtual void attach();
virtual RenderObject* createRenderer(RenderArena*, RenderStyle*);
- virtual void insertedIntoDocument();
- virtual void removedFromDocument();
virtual bool canStartSelection() const { return false; }
@@ -105,6 +103,11 @@ public:
virtual void addSubresourceAttributeURLs(ListHashSet<KURL>&) const;
private:
+ virtual void insertedIntoDocument();
+ virtual void removedFromDocument();
+ virtual void insertedIntoTree(bool deep);
+ virtual void removedFromTree(bool deep);
+
HTMLImageLoader m_imageLoader;
String usemap;
bool ismap;
diff --git a/src/3rdparty/webkit/WebCore/html/HTMLInputElement.cpp b/src/3rdparty/webkit/WebCore/html/HTMLInputElement.cpp
index f25c908..652bc40 100644
--- a/src/3rdparty/webkit/WebCore/html/HTMLInputElement.cpp
+++ b/src/3rdparty/webkit/WebCore/html/HTMLInputElement.cpp
@@ -701,12 +701,15 @@ void HTMLInputElement::parseMappedAttribute(MappedAttribute *attr)
m_autocomplete = Off;
registerForActivationCallbackIfNeeded();
} else {
- if (m_autocomplete == Off)
- unregisterForActivationCallbackIfNeeded();
+ bool needsToUnregister = m_autocomplete == Off;
+
if (attr->isEmpty())
m_autocomplete = Uninitialized;
else
m_autocomplete = On;
+
+ if (needsToUnregister)
+ unregisterForActivationCallbackIfNeeded();
}
} else if (attr->name() == typeAttr) {
setInputType(attr->value());
diff --git a/src/3rdparty/webkit/WebCore/html/HTMLParser.cpp b/src/3rdparty/webkit/WebCore/html/HTMLParser.cpp
index 1cb47ae..99c66de 100644
--- a/src/3rdparty/webkit/WebCore/html/HTMLParser.cpp
+++ b/src/3rdparty/webkit/WebCore/html/HTMLParser.cpp
@@ -1275,7 +1275,8 @@ void HTMLParser::handleResidualStyleCloseTagAcrossBlocks(HTMLStackElem* elem)
prevMaxElem->next = elem;
ASSERT(newNodePtr);
prevMaxElem->node = newNodePtr;
- prevMaxElem->didRefNode = false;
+ newNodePtr->ref();
+ prevMaxElem->didRefNode = true;
} else
delete elem;
}
diff --git a/src/3rdparty/webkit/WebCore/loader/FrameLoader.cpp b/src/3rdparty/webkit/WebCore/loader/FrameLoader.cpp
index a85dcf5..7d857d4 100644
--- a/src/3rdparty/webkit/WebCore/loader/FrameLoader.cpp
+++ b/src/3rdparty/webkit/WebCore/loader/FrameLoader.cpp
@@ -1260,9 +1260,11 @@ bool FrameLoader::requestObject(RenderPart* renderer, const String& url, const A
ASSERT(renderer->node()->hasTagName(objectTag) || renderer->node()->hasTagName(embedTag));
HTMLPlugInElement* element = static_cast<HTMLPlugInElement*>(renderer->node());
-
- // FIXME: OK to always make a new frame? When does the old frame get removed?
- return loadSubframe(element, completedURL, frameName, m_outgoingReferrer);
+
+ // If the plug-in element already contains a subframe, requestFrame will re-use it. Otherwise,
+ // it will create a new frame and set it as the RenderPart's widget, causing what was previously
+ // in the widget to be torn down.
+ return requestFrame(element, completedURL, frameName);
}
bool FrameLoader::shouldUsePlugin(const KURL& url, const String& mimeType, bool hasFallback, bool& useFallback)
diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.cpp b/src/3rdparty/webkit/WebCore/page/FrameView.cpp
index bc4e4f2..4c3a0ab 100644
--- a/src/3rdparty/webkit/WebCore/page/FrameView.cpp
+++ b/src/3rdparty/webkit/WebCore/page/FrameView.cpp
@@ -106,6 +106,7 @@ struct ScheduledEvent {
FrameView::FrameView(Frame* frame)
: m_frame(frame)
, m_slowRepaintObjectCount(0)
+ , m_fixedObjectCount(0)
, m_layoutTimer(this, &FrameView::layoutTimerFired)
, m_layoutRoot(0)
, m_postLayoutTasksTimer(this, &FrameView::postLayoutTimerFired)
@@ -735,7 +736,7 @@ String FrameView::mediaType() const
bool FrameView::useSlowRepaints() const
{
- return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || m_isOverlapped || !m_contentIsOpaque;
+ return m_useSlowRepaints || m_slowRepaintObjectCount > 0 || (platformWidget() && m_fixedObjectCount > 0) || m_isOverlapped || !m_contentIsOpaque;
}
void FrameView::setUseSlowRepaints()
@@ -759,6 +760,78 @@ void FrameView::removeSlowRepaintObject()
setCanBlitOnScroll(!useSlowRepaints());
}
+void FrameView::addFixedObject()
+{
+ if (!m_fixedObjectCount && platformWidget())
+ setCanBlitOnScroll(false);
+ ++m_fixedObjectCount;
+}
+
+void FrameView::removeFixedObject()
+{
+ ASSERT(m_fixedObjectCount > 0);
+ m_fixedObjectCount--;
+ if (!m_fixedObjectCount)
+ setCanBlitOnScroll(!useSlowRepaints());
+}
+
+void FrameView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
+{
+ const size_t fixedObjectThreshold = 5;
+
+ ListHashSet<RenderBox*>* positionedObjects = 0;
+ if (RenderView* root = m_frame->contentRenderer())
+ positionedObjects = root->positionedObjects();
+
+ if (!positionedObjects || positionedObjects->isEmpty()) {
+ hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
+ return;
+ }
+
+ // Get the rects of the fixed objects visible in the rectToScroll
+ Vector<IntRect, fixedObjectThreshold> subRectToUpdate;
+ bool updateInvalidatedSubRect = true;
+ ListHashSet<RenderBox*>::const_iterator end = positionedObjects->end();
+ for (ListHashSet<RenderBox*>::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+ RenderBox* renderBox = *it;
+ if (renderBox->style()->position() != FixedPosition)
+ continue;
+ IntRect topLevelRect;
+ IntRect updateRect = renderBox->paintingRootRect(topLevelRect);
+ updateRect.move(-scrollX(), -scrollY());
+ updateRect.intersect(rectToScroll);
+ if (!updateRect.isEmpty()) {
+ if (subRectToUpdate.size() >= fixedObjectThreshold) {
+ updateInvalidatedSubRect = false;
+ break;
+ }
+ subRectToUpdate.append(updateRect);
+ }
+ }
+
+ // Scroll the view
+ if (updateInvalidatedSubRect) {
+ // 1) scroll
+ hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
+
+ // 2) update the area of fixed objets that has been invalidated
+ size_t fixObjectsCount = subRectToUpdate.size();
+ for (size_t i = 0; i < fixObjectsCount; ++i) {
+ IntRect updateRect = subRectToUpdate[i];
+ IntRect scrolledRect = updateRect;
+ scrolledRect.move(scrollDelta);
+ updateRect.unite(scrolledRect);
+ updateRect.intersect(rectToScroll);
+ hostWindow()->repaint(updateRect, true, false, true);
+ }
+ } else {
+ // the number of fixed objects exceed the threshold, so we repaint everything.
+ IntRect updateRect = clipRect;
+ updateRect.intersect(rectToScroll);
+ hostWindow()->repaint(updateRect, true, false, true);
+ }
+}
+
void FrameView::setIsOverlapped(bool isOverlapped)
{
if (isOverlapped == m_isOverlapped)
diff --git a/src/3rdparty/webkit/WebCore/page/FrameView.h b/src/3rdparty/webkit/WebCore/page/FrameView.h
index 3d17d2c..5243c02 100644
--- a/src/3rdparty/webkit/WebCore/page/FrameView.h
+++ b/src/3rdparty/webkit/WebCore/page/FrameView.h
@@ -143,6 +143,9 @@ public:
void addSlowRepaintObject();
void removeSlowRepaintObject();
+ void addFixedObject();
+ void removeFixedObject();
+
void beginDeferredRepaints();
void endDeferredRepaints();
void checkStopDelayingDeferredRepaints();
@@ -196,6 +199,9 @@ public:
bool isFrameViewScrollCorner(RenderScrollbarPart* scrollCorner) const { return m_scrollCorner == scrollCorner; }
void invalidateScrollCorner();
+protected:
+ virtual void scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
+
private:
FrameView(Frame*);
@@ -261,6 +267,7 @@ private:
bool m_isOverlapped;
bool m_contentIsOpaque;
unsigned m_slowRepaintObjectCount;
+ unsigned m_fixedObjectCount;
int m_borderX, m_borderY;
diff --git a/src/3rdparty/webkit/WebCore/platform/MIMETypeRegistry.cpp b/src/3rdparty/webkit/WebCore/platform/MIMETypeRegistry.cpp
index 609a1b0..758863c 100644
--- a/src/3rdparty/webkit/WebCore/platform/MIMETypeRegistry.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/MIMETypeRegistry.cpp
@@ -200,9 +200,7 @@ static void initializeSupportedNonImageMimeTypes()
"text/",
"application/xml",
"application/xhtml+xml",
-#if ENABLE(XHTMLMP)
"application/vnd.wap.xhtml+xml",
-#endif
"application/rss+xml",
"application/atom+xml",
#if ENABLE(SVG)
diff --git a/src/3rdparty/webkit/WebCore/platform/ScrollView.cpp b/src/3rdparty/webkit/WebCore/platform/ScrollView.cpp
index e67daf9..9e15c43 100644
--- a/src/3rdparty/webkit/WebCore/platform/ScrollView.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/ScrollView.cpp
@@ -509,7 +509,7 @@ void ScrollView::scrollContents(const IntSize& scrollDelta)
if (canBlitOnScroll()) { // The main frame can just blit the WebView window
// FIXME: Find a way to blit subframes without blitting overlapping content
- hostWindow()->scroll(-scrollDelta, scrollViewRect, clipRect);
+ scrollContentsFastPath(-scrollDelta, scrollViewRect, clipRect);
} else {
// We need to go ahead and repaint the entire backing store. Do it now before moving the
// windowed plugins.
@@ -524,6 +524,11 @@ void ScrollView::scrollContents(const IntSize& scrollDelta)
hostWindow()->paint();
}
+void ScrollView::scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect)
+{
+ hostWindow()->scroll(scrollDelta, rectToScroll, clipRect);
+}
+
IntPoint ScrollView::windowToContents(const IntPoint& windowPoint) const
{
IntPoint viewPoint = convertFromContainingWindow(windowPoint);
diff --git a/src/3rdparty/webkit/WebCore/platform/ScrollView.h b/src/3rdparty/webkit/WebCore/platform/ScrollView.h
index 5dacff5..7060d07 100644
--- a/src/3rdparty/webkit/WebCore/platform/ScrollView.h
+++ b/src/3rdparty/webkit/WebCore/platform/ScrollView.h
@@ -244,6 +244,9 @@ protected:
IntRect scrollCornerRect() const;
virtual void updateScrollCorner();
virtual void paintScrollCorner(GraphicsContext*, const IntRect& cornerRect);
+
+ // Scroll the content by blitting the pixels
+ virtual void scrollContentsFastPath(const IntSize& scrollDelta, const IntRect& rectToScroll, const IntRect& clipRect);
private:
RefPtr<Scrollbar> m_horizontalScrollbar;
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp
index 37a6408..298d840 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp
+++ b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.cpp
@@ -126,6 +126,7 @@ PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
RenderThemeQt::RenderThemeQt(Page* page)
: RenderTheme()
, m_page(page)
+ , m_lineEdit(0)
{
QPushButton button;
button.setAttribute(Qt::WA_MacSmallSize);
@@ -142,6 +143,7 @@ RenderThemeQt::RenderThemeQt(Page* page)
RenderThemeQt::~RenderThemeQt()
{
delete m_fallbackStyle;
+ delete m_lineEdit;
}
// for some widget painting, we need to fallback to Windows style
@@ -207,11 +209,13 @@ bool RenderThemeQt::supportsControlTints() const
return true;
}
-static int findFrameLineWidth(QStyle* style)
+int RenderThemeQt::findFrameLineWidth(QStyle* style) const
{
- QLineEdit lineEdit;
+ if (!m_lineEdit)
+ m_lineEdit = new QLineEdit();
+
QStyleOptionFrameV2 opt;
- return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, &lineEdit);
+ return style->pixelMetric(QStyle::PM_DefaultFrameWidth, &opt, m_lineEdit);
}
static QRect inflateButtonRect(const QRect& originalRect, QStyle* style)
diff --git a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h
index 13fb42f..64921b1 100644
--- a/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h
+++ b/src/3rdparty/webkit/WebCore/platform/qt/RenderThemeQt.h
@@ -27,6 +27,7 @@
#include <QStyle>
QT_BEGIN_NAMESPACE
+class QLineEdit;
class QPainter;
class QWidget;
QT_END_NAMESPACE
@@ -140,6 +141,8 @@ private:
void setButtonPadding(RenderStyle*) const;
void setPopupPadding(RenderStyle*) const;
+ int findFrameLineWidth(QStyle* style) const;
+
QStyle* fallbackStyle() const;
Page* m_page;
@@ -150,6 +153,7 @@ private:
QString m_buttonFontFamily;
QStyle* m_fallbackStyle;
+ mutable QLineEdit* m_lineEdit;
};
class StylePainter {
diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp
index aece0e4..b839870 100644
--- a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp
+++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.cpp
@@ -32,12 +32,12 @@
using namespace WebCore;
-PluginContainerSymbian::PluginContainerSymbian(PluginView* view, QWidget* parent)
- : m_parent(parent)
+PluginContainerSymbian::PluginContainerSymbian(PluginView* view, QWidget* parent, QGraphicsProxyWidget* proxy)
+ : QWidget(parent)
, m_pluginView(view)
+ , m_proxy(proxy)
, m_hasPendingGeometryChange(false)
{
- setParent(m_parent);
}
PluginContainerSymbian::~PluginContainerSymbian()
@@ -62,7 +62,7 @@ void PluginContainerSymbian::adjustGeometry()
}
}
-void PluginContainerSymbian::focusInEvent(QFocusEvent* event)
+void PluginContainerSymbian::focusInEvent(QFocusEvent*)
{
if (Page* page = m_pluginView->parentFrame()->page())
page->focusController()->setActive(true);
diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h
index fce4a71..fead872 100644
--- a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h
+++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginContainerSymbian.h
@@ -22,6 +22,8 @@
#include <QWidget>
+class QGraphicsProxyWidget;
+
namespace WebCore {
class PluginView;
@@ -29,18 +31,19 @@ namespace WebCore {
class PluginContainerSymbian : public QWidget {
Q_OBJECT
public:
- PluginContainerSymbian(PluginView*, QWidget* parent);
+ PluginContainerSymbian(PluginView*, QWidget* parent, QGraphicsProxyWidget* proxy = 0);
~PluginContainerSymbian();
void requestGeometry(const QRect&, const QRegion& clip = QRegion());
void adjustGeometry();
+ QGraphicsProxyWidget* proxy() { return m_proxy; }
protected:
virtual void focusInEvent(QFocusEvent*);
virtual void focusOutEvent(QFocusEvent*);
private:
PluginView* m_pluginView;
- QWidget* m_parent;
+ QGraphicsProxyWidget* m_proxy;
QRect m_windowRect;
QRegion m_clipRegion;
bool m_hasPendingGeometryChange;
diff --git a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp
index fd604a0..9e107cd 100644
--- a/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp
+++ b/src/3rdparty/webkit/WebCore/plugins/symbian/PluginViewSymbian.cpp
@@ -52,6 +52,8 @@
#include "runtime.h"
#include "runtime_root.h"
#include "QWebPageClient.h"
+#include "qgraphicswebview.h"
+#include <QGraphicsProxyWidget>
#include <QKeyEvent>
#include <QPixmap>
#include <QRegion>
@@ -84,6 +86,7 @@ void PluginView::updatePluginWidget()
IntRect oldClipRect = m_clipRect;
m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());
+
m_clipRect = windowClipRect();
m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());
if (m_windowRect == oldWindowRect && m_clipRect == oldClipRect)
@@ -425,12 +428,15 @@ bool PluginView::platformStart()
if (m_isWindowed) {
QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
- // FIXME this will not work for QGraphicsView.
- // But we cannot use winId because it will create a window and on S60,
- // QWidgets should not create a window.
- Q_ASSERT(qobject_cast<QWidget*>(client->pluginParent()));
- setPlatformWidget(new PluginContainerSymbian(this,
- qobject_cast<QWidget*>(client->pluginParent())));
+ QGraphicsProxyWidget* proxy = 0;
+ if (QGraphicsWebView *webView = qobject_cast<QGraphicsWebView*>(client->pluginParent()))
+ proxy = new QGraphicsProxyWidget(webView);
+
+ PluginContainerSymbian* container = new PluginContainerSymbian(this, proxy ? 0 : client->ownerWidget(), proxy);
+ setPlatformWidget(container);
+ if (proxy)
+ proxy->setWidget(container);
+
m_npWindow.type = NPWindowTypeWindow;
m_npWindow.window = (void*)platformPluginWidget();
@@ -446,7 +452,11 @@ bool PluginView::platformStart()
void PluginView::platformDestroy()
{
- delete platformPluginWidget();
+ QWebPageClient* client = m_parentFrame->view()->hostWindow()->platformPageClient();
+ if (QGraphicsWebView *webView = qobject_cast<QGraphicsWebView*>(client->pluginParent()))
+ delete static_cast<PluginContainerSymbian*>(platformPluginWidget())->proxy();
+ else
+ delete platformPluginWidget();
}
void PluginView::halt()
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h b/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h
index 7ba5fce..3300d01 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBlock.h
@@ -75,6 +75,7 @@ public:
void insertPositionedObject(RenderBox*);
void removePositionedObject(RenderBox*);
void removePositionedObjects(RenderBlock*);
+ ListHashSet<RenderBox*>* positionedObjects() const { return m_positionedObjects; }
void addPercentHeightDescendant(RenderBox*);
static void removePercentHeightDescendant(RenderBox*);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp
index 1df82a4..7ca2ff8 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBox.cpp
@@ -145,6 +145,16 @@ void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyl
removeFloatingOrPositionedChildFromBlockLists();
}
}
+ if (FrameView *frameView = view()->frameView()) {
+ bool newStyleIsFixed = newStyle && newStyle->position() == FixedPosition;
+ bool oldStyleIsFixed = style() && style()->position() == FixedPosition;
+ if (newStyleIsFixed != oldStyleIsFixed) {
+ if (newStyleIsFixed)
+ frameView->addFixedObject();
+ else
+ frameView->removeFixedObject();
+ }
+ }
RenderBoxModelObject::styleWillChange(diff, newStyle);
}
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp
index 23dad2d..9d0f1ed 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderBoxModelObject.cpp
@@ -557,6 +557,17 @@ void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fil
// Determine the background positioning area and set destRect to the background painting area.
// destRect will be adjusted later if the background is non-repeating.
bool fixedAttachment = fillLayer->attachment() == FixedBackgroundAttachment;
+
+#if ENABLE(FAST_MOBILE_SCROLLING)
+ if (view()->frameView() && view()->frameView()->canBlitOnScroll()) {
+ // As a side effect of an optimization to blit on scroll, we do not honor the CSS
+ // property "background-attachment: fixed" because it may result in rendering
+ // artifacts. Note, these artifacts only appear if we are blitting on scroll of
+ // a page that has fixed background images.
+ fixedAttachment = false;
+ }
+#endif
+
if (!fixedAttachment) {
destRect = IntRect(tx, ty, w, h);
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp
index a10ffd9..199de4a 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderObject.cpp
@@ -1591,10 +1591,17 @@ void RenderObject::styleWillChange(StyleDifference diff, const RenderStyle* newS
s_affectsParentBlock = false;
if (view()->frameView()) {
- // FIXME: A better solution would be to only invalidate the fixed regions when scrolling. It's overkill to
- // prevent the entire view from blitting on a scroll.
- bool newStyleSlowScroll = newStyle && (newStyle->position() == FixedPosition || newStyle->hasFixedBackgroundImage());
- bool oldStyleSlowScroll = m_style && (m_style->position() == FixedPosition || m_style->hasFixedBackgroundImage());
+ bool shouldBlitOnFixedBackgroundImage = false;
+#if ENABLE(FAST_MOBILE_SCROLLING)
+ // On low-powered/mobile devices, preventing blitting on a scroll can cause noticeable delays
+ // when scrolling a page with a fixed background image. As an optimization, assuming there are
+ // no fixed positoned elements on the page, we can acclerate scrolling (via blitting) if we
+ // ignore the CSS property "background-attachment: fixed".
+ shouldBlitOnFixedBackgroundImage = true;
+#endif
+
+ bool newStyleSlowScroll = newStyle && !shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage();
+ bool oldStyleSlowScroll = m_style && !shouldBlitOnFixedBackgroundImage && m_style->hasFixedBackgroundImage();
if (oldStyleSlowScroll != newStyleSlowScroll) {
if (oldStyleSlowScroll)
view()->frameView()->removeSlowRepaintObject();
diff --git a/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp b/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp
index 40c3d75..88a05e5 100644
--- a/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp
+++ b/src/3rdparty/webkit/WebCore/rendering/RenderText.cpp
@@ -1047,8 +1047,15 @@ void RenderText::positionLineBox(InlineBox* box)
if (!s->len()) {
// We want the box to be destroyed.
s->remove();
+ if (m_firstTextBox == s)
+ m_firstTextBox = s->nextTextBox();
+ else
+ s->prevTextBox()->setNextLineBox(s->nextTextBox());
+ if (m_lastTextBox == s)
+ m_lastTextBox = s->prevTextBox();
+ else
+ s->nextTextBox()->setPreviousLineBox(s->prevTextBox());
s->destroy(renderArena());
- m_firstTextBox = m_lastTextBox = 0;
return;
}
@@ -1349,7 +1356,7 @@ void RenderText::checkConsistency() const
#ifdef CHECK_CONSISTENCY
const InlineTextBox* prev = 0;
for (const InlineTextBox* child = m_firstTextBox; child != 0; child = child->nextTextBox()) {
- ASSERT(child->object() == this);
+ ASSERT(child->renderer() == this);
ASSERT(child->prevTextBox() == prev);
prev = child;
}
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp
index a80c5d3..490ada1 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp
@@ -65,6 +65,7 @@ public:
void _q_doLoadFinished(bool success);
void _q_updateMicroFocus();
+ void _q_pageDestroyed();
QGraphicsWebView* q;
QWebPage* page;
@@ -97,6 +98,12 @@ void QGraphicsWebViewPrivate::_q_updateMicroFocus()
#endif
}
+void QGraphicsWebViewPrivate::_q_pageDestroyed()
+{
+ page = 0;
+ q->setPage(0);
+}
+
void QGraphicsWebViewPrivate::scroll(int dx, int dy, const QRect& rectToScroll)
{
q->scroll(qreal(dx), qreal(dy), QRectF(rectToScroll));
@@ -454,6 +461,8 @@ void QGraphicsWebView::setPage(QWebPage* page)
this, SIGNAL(linkClicked(QUrl)));
connect(d->page, SIGNAL(microFocusChanged()),
this, SLOT(_q_updateMicroFocus()));
+ connect(d->page, SIGNAL(destroyed()),
+ this, SLOT(_q_pageDestroyed()));
}
/*!
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h
index 68379a2..1b02f35 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h
@@ -134,10 +134,11 @@ protected:
private:
Q_PRIVATE_SLOT(d, void _q_doLoadFinished(bool success))
+ Q_PRIVATE_SLOT(d, void _q_updateMicroFocus())
+ Q_PRIVATE_SLOT(d, void _q_pageDestroyed())
QGraphicsWebViewPrivate* const d;
friend class QGraphicsWebViewPrivate;
};
#endif // QGraphicsWebView_h
- Q_PRIVATE_SLOT(d, void _q_updateMicroFocus())
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp
index e4c2afc..710e11b 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebframe.cpp
@@ -324,15 +324,12 @@ void QWebFramePrivate::renderPrivate(QPainter *painter, QWebFrame::RenderLayer l
}
}
-static bool webframe_scrollOverflow(WebCore::Frame* frame, int dx, int dy)
+static bool webframe_scrollOverflow(WebCore::Frame* frame, int dx, int dy, const QPoint& pos)
{
if (!frame || !frame->document() || !frame->eventHandler())
return false;
- Node* node = frame->document()->focusedNode();
- if (!node)
- node = frame->document()->elementFromPoint(frame->eventHandler()->currentMousePosition().x(),
- frame->eventHandler()->currentMousePosition().y());
+ Node* node = frame->document()->elementFromPoint(pos.x(), pos.y());
if (!node)
return false;
@@ -363,6 +360,10 @@ static bool webframe_scrollOverflow(WebCore::Frame* frame, int dx, int dy)
return (scrolledHorizontal || scrolledVertical);
}
+
+
+
+
/*!
\class QWebFrame
\since 4.4
@@ -1047,27 +1048,24 @@ void QWebFrame::scroll(int dx, int dy)
}
/*!
- \since 4.7
\internal
Scrolls nested frames starting at this frame, \a dx pixels to the right
and \a dy pixels downward. Both \a dx and \a dy may be negative. First attempts
- to scroll elements with CSS overflow followed by this frame. If this
+ to scroll elements with CSS overflow at position pos, followed by this frame. If this
frame doesn't scroll, attempts to scroll the parent
-
- \sa QWebFrame::scroll
*/
-bool QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy)
+void QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy, const QPoint& pos)
{
Frame* frame = QWebFramePrivate::core(qFrame);
- bool scrolledHorizontal = false;
- bool scrolledVertical = false;
- bool scrolledOverflow = webframe_scrollOverflow(frame, dx, dy);
-
- if (!scrolledOverflow) {
- if (!frame || !frame->view())
- return false;
+ if (!frame || !frame->view())
+ return;
+
+ if (!webframe_scrollOverflow(frame, dx, dy, pos)) {
do {
+ bool scrolledHorizontal = false;
+ bool scrolledVertical = false;
+
IntSize scrollOffset = frame->view()->scrollOffset();
IntPoint maxScrollOffset = frame->view()->maximumScrollPosition();
@@ -1083,12 +1081,12 @@ bool QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int d
if (scrolledHorizontal || scrolledVertical) {
frame->view()->scrollBy(IntSize(dx, dy));
- return true;
+ return;
}
+
frame = frame->tree()->parent();
} while (frame && frame->view());
}
- return (scrolledHorizontal || scrolledVertical || scrolledOverflow);
}
/*!
diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
index a289ec0..97a4e4e 100644
--- a/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/Api/qwebpage.cpp
@@ -1248,8 +1248,8 @@ void QWebPagePrivate::inputMethodEvent(QInputMethodEvent *ev)
#if QT_VERSION >= 0x040600
case QInputMethodEvent::Selection: {
if (renderTextControl) {
- renderTextControl->setSelectionStart(a.start);
- renderTextControl->setSelectionEnd(a.start + a.length);
+ renderTextControl->setSelectionStart(qMin(a.start, (a.start + a.length)));
+ renderTextControl->setSelectionEnd(qMax(a.start, (a.start + a.length)));
}
break;
}
diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog
index a5441cd..64726c2 100644
--- a/src/3rdparty/webkit/WebKit/qt/ChangeLog
+++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog
@@ -1,3 +1,87 @@
+2010-03-22 Jakub Wieczorek <jwieczorek@webkit.org>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] Don't construct a QLineEdit every time when painting a text field
+ https://bugs.webkit.org/show_bug.cgi?id=36373
+
+ Add a simple benchmark covering this area.
+
+ * tests/benchmarks/painting/tst_painting.cpp:
+ (tst_Painting::textAreas):
+
+2010-03-22 Yi Shen <shenyi2006@gmail.com>
+
+ Reviewed by Simon Hausmann.
+
+ https://bugs.webkit.org/show_bug.cgi?id=35933
+ [Qt] [Symbian] Can not backward select (highlight) text using virtual keyboard
+ Make sure the selection start index is smaller than the selection end index.
+
+ * Api/qwebpage.cpp:
+ (QWebPagePrivate::inputMethodEvent):
+ * tests/qwebpage/tst_qwebpage.cpp:
+ (tst_QWebPage::inputMethods):
+
+2010-03-25 Yael Aharon <yael.aharon@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] QtLauncher crashes on Mac OS and Linux when exiting with QGraphicsView mode enabled
+ https://bugs.webkit.org/show_bug.cgi?id=35251
+
+ Followed the way QWebView registers for the signal QWebPage::destroyed(), to prevent
+ QGraphicsWebView from referencing QWebPage after it was deleted.
+
+ * Api/qgraphicswebview.cpp:
+ (QGraphicsWebViewPrivate::_q_pageDestroyed):
+ (QGraphicsWebView::setPage):
+ * Api/qgraphicswebview.h:
+
+2010-03-23 David Leong <david.leong@nokia.com>
+
+ Reviewed by Laszlo Gombos.
+
+ Build fix for Symbian Def file.
+
+ * symbian/eabi/QtWebKitu.def:
+
+2010-03-18 Joe Ligman <joseph.ligman@nokia.com>
+
+ Reviewed by Simon Hausmann.
+
+ [Qt] New API scrollRecursively has several problems.
+ https://bugs.webkit.org/show_bug.cgi?id=35873
+
+ Remove scrollRecursively from the Qt 4.7 API
+ Update the internal API to accept a hit test position
+ for nested scrolling
+
+ * Api/qwebframe.cpp:
+ (webframe_scrollOverflow):
+ (qtwebkit_webframe_scrollRecursively):
+ * Api/qwebframe.h:
+ * Api/qwebframe_p.h:
+ * tests/qwebframe/tst_qwebframe.cpp:
+
+2009-12-18 Joe Ligman <joseph.ligman@nokia.com>
+
+ Reviewed by Kenneth Rohde Christiansen.
+
+ [Qt] Add new API to QWebFrame to scrollRecursively starting with any css overflow
+ then checking current frame and then ancestors
+ https://bugs.webkit.org/show_bug.cgi?id=32668
+
+ * Api/qwebframe.cpp:
+ (QWebFramePrivate::scrollOverflow):
+ (QWebFrame::scrollRecursively):
+ * Api/qwebframe.h:
+ * Api/qwebframe_p.h:
+ * tests/qwebframe/qwebframe.qrc:
+ * tests/qwebframe/testiframe.html: Added.
+ * tests/qwebframe/testiframe2.html: Added.
+ * tests/qwebframe/tst_qwebframe.cpp:
+
2010-03-21 Kristian Amlie <kristian.amlie@nokia.com>
Reviewed by Simon Hausmann.
diff --git a/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def
index 5dd2e20..cfa8f7f 100644
--- a/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def
+++ b/src/3rdparty/webkit/WebKit/qt/symbian/eabi/QtWebKitu.def
@@ -693,5 +693,5 @@ EXPORTS
_Z23qt_networkAccessAllowedb @ 692 NONAME
_Z25qt_resumeActiveDOMObjectsP9QWebFrame @ 693 NONAME
_Z26qt_suspendActiveDOMObjectsP9QWebFrame @ 694 NONAME
- _Z35qtwebkit_webframe_scrollRecursivelyP9QWebFrameii @ 695 NONAME
-
+ _Z35qtwebkit_webframe_scrollRecursivelyP9QWebFrameii @ 695 NONAME ABSENT
+ _Z35qtwebkit_webframe_scrollRecursivelyP9QWebFrameiiRK6QPoint @ 715 NONAME
diff --git a/src/3rdparty/webkit/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp b/src/3rdparty/webkit/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp
index f4531fd..fc5b8e3 100644
--- a/src/3rdparty/webkit/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/tests/benchmarks/painting/tst_painting.cpp
@@ -19,6 +19,7 @@
#include <QtTest/QtTest>
+#include <qwebelement.h>
#include <qwebframe.h>
#include <qwebview.h>
#include <qpainter.h>
@@ -59,6 +60,7 @@ public Q_SLOTS:
private Q_SLOTS:
void paint_data();
void paint();
+ void textAreas();
private:
QWebView* m_view;
@@ -105,5 +107,30 @@ void tst_Painting::paint()
}
}
+void tst_Painting::textAreas()
+{
+ m_view->load(QUrl("data:text/html;<html><body></body></html>"));
+ ::waitForSignal(m_view, SIGNAL(loadFinished(bool)));
+
+ QWebElement bodyElement = m_page->mainFrame()->findFirstElement("body");
+
+ int count = 100;
+ while (count--) {
+ QString markup("<textarea cols='1' rows='1'></textarea>");
+ bodyElement.appendInside(markup);
+ }
+
+ /* force a layout */
+ QWebFrame* mainFrame = m_page->mainFrame();
+ mainFrame->toPlainText();
+
+ QPixmap pixmap(mainFrame->contentsSize());
+ QBENCHMARK {
+ QPainter painter(&pixmap);
+ mainFrame->render(&painter, QRect(QPoint(0, 0), mainFrame->contentsSize()));
+ painter.end();
+ }
+}
+
QTEST_MAIN(tst_Painting)
#include "tst_painting.moc"
diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp
index 609f8b4..8cc7953 100644
--- a/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebframe/tst_qwebframe.cpp
@@ -606,7 +606,6 @@ private slots:
void scrollPosition();
void evaluateWillCauseRepaint();
void qObjectWrapperWithSameIdentity();
- void scrollRecursively();
private:
QString evalJS(const QString&s) {
@@ -2825,71 +2824,5 @@ void tst_QWebFrame::qObjectWrapperWithSameIdentity()
QCOMPARE(mainFrame->toPlainText(), QString("test2"));
}
-bool QWEBKIT_EXPORT qtwebkit_webframe_scrollRecursively(QWebFrame* qFrame, int dx, int dy);
-
-void tst_QWebFrame::scrollRecursively()
-{
- // The test content is
- // a nested frame set
- // The main frame scrolls
- // and has two children
- // an iframe and a div overflow
- // both scroll
- QWebView webView;
- QWebPage* webPage = webView.page();
- QSignalSpy loadSpy(webPage, SIGNAL(loadFinished(bool)));
- QUrl url = QUrl("qrc:///testiframe.html");
- webPage->mainFrame()->load(url);
- QTRY_COMPARE(loadSpy.count(), 1);
-
- QList<QWebFrame*> children = webPage->mainFrame()->childFrames();
- QVERIFY(children.count() == 1);
-
- // 1st test
- // call scrollRecursively over mainframe
- // verify scrolled
- // verify scroll postion changed
- QPoint scrollPosition(webPage->mainFrame()->scrollPosition());
- QVERIFY(qtwebkit_webframe_scrollRecursively(webPage->mainFrame(), 10, 10));
- QVERIFY(scrollPosition != webPage->mainFrame()->scrollPosition());
-
- // 2nd test
- // call scrollRecursively over child iframe
- // verify scrolled
- // verify child scroll position changed
- // verify parent's scroll position did not change
- scrollPosition = webPage->mainFrame()->scrollPosition();
- QPoint childScrollPosition = children.at(0)->scrollPosition();
- QVERIFY(qtwebkit_webframe_scrollRecursively(children.at(0), 10, 10));
- QVERIFY(scrollPosition == webPage->mainFrame()->scrollPosition());
- QVERIFY(childScrollPosition != children.at(0)->scrollPosition());
-
- // 3rd test
- // call scrollRecursively over div overflow
- // verify scrolled == true
- // verify parent and child frame's scroll postion did not change
- QWebElement div = webPage->mainFrame()->documentElement().findFirst("#content1");
- QMouseEvent evpres(QEvent::MouseMove, div.geometry().center(), Qt::NoButton, Qt::NoButton, Qt::NoModifier);
- webPage->event(&evpres);
- scrollPosition = webPage->mainFrame()->scrollPosition();
- childScrollPosition = children.at(0)->scrollPosition();
- QVERIFY(qtwebkit_webframe_scrollRecursively(webPage->mainFrame(), 5, 5));
- QVERIFY(childScrollPosition == children.at(0)->scrollPosition());
- QVERIFY(scrollPosition == webPage->mainFrame()->scrollPosition());
-
- // 4th test
- // call scrollRecursively twice over childs iframe
- // verify scrolled == true first time
- // verify parent's scroll == true second time
- // verify parent and childs scroll position changed
- childScrollPosition = children.at(0)->scrollPosition();
- QVERIFY(qtwebkit_webframe_scrollRecursively(children.at(0), -10, -10));
- QVERIFY(childScrollPosition != children.at(0)->scrollPosition());
- scrollPosition = webPage->mainFrame()->scrollPosition();
- QVERIFY(qtwebkit_webframe_scrollRecursively(children.at(0), -10, -10));
- QVERIFY(scrollPosition != webPage->mainFrame()->scrollPosition());
-
-}
-
QTEST_MAIN(tst_QWebFrame)
#include "tst_qwebframe.moc"
diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp
index 0e04acc..55ee42a 100644
--- a/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp
+++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebpage/tst_qwebpage.cpp
@@ -1451,6 +1451,26 @@ void tst_QWebPage::inputMethods()
variant = page->inputMethodQuery(Qt::ImCurrentSelection);
QString selectionValue = variant.value<QString>();
QCOMPARE(selectionValue, QString("eb"));
+
+ //Set selection with negative length
+ inputAttributes << QInputMethodEvent::Attribute(QInputMethodEvent::Selection, 6, -5, QVariant());
+ QInputMethodEvent eventSelection2("",inputAttributes);
+ page->event(&eventSelection2);
+
+ //ImAnchorPosition
+ variant = page->inputMethodQuery(Qt::ImAnchorPosition);
+ anchorPosition = variant.toInt();
+ QCOMPARE(anchorPosition, 1);
+
+ //ImCursorPosition
+ variant = page->inputMethodQuery(Qt::ImCursorPosition);
+ cursorPosition = variant.toInt();
+ QCOMPARE(cursorPosition, 6);
+
+ //ImCurrentSelection
+ variant = page->inputMethodQuery(Qt::ImCurrentSelection);
+ selectionValue = variant.value<QString>();
+ QCOMPARE(selectionValue, QString("tWebK"));
#endif
//ImSurroundingText
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 500cde6..83fa044 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -38,7 +38,6 @@ symbian: {
# Partial upgrade SIS file
vendorinfo = \
- "&EN" \
"; Localised Vendor name" \
"%{\"Nokia, Qt\"}" \
" " \
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index aa1c7d9..50e9a8f 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -90,7 +90,8 @@ QFile::DecoderFn QFilePrivate::decoder = locale_decode;
QFilePrivate::QFilePrivate()
: fileEngine(0), lastWasWrite(false),
- writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError)
+ writeBuffer(QFILE_WRITEBUFFER_SIZE), error(QFile::NoError),
+ cachedSize(0)
{
}
@@ -1257,8 +1258,10 @@ QFile::resize(qint64 sz)
seek(sz);
if(d->fileEngine->setSize(sz)) {
unsetError();
+ d->cachedSize = sz;
return true;
}
+ d->cachedSize = 0;
d->setError(QFile::ResizeError, d->fileEngine->errorString());
return false;
}
@@ -1420,7 +1423,8 @@ qint64 QFile::size() const
Q_D(const QFile);
if (!d->ensureFlushed())
return 0;
- return fileEngine()->size();
+ d->cachedSize = fileEngine()->size();
+ return d->cachedSize;
}
/*!
@@ -1446,16 +1450,16 @@ bool QFile::atEnd() const
{
Q_D(const QFile);
+ // If there's buffered data left, we're not at the end.
+ if (!d->buffer.isEmpty())
+ return false;
+
if (!isOpen())
return true;
if (!d->ensureFlushed())
return false;
- // If there's buffered data left, we're not at the end.
- if (!d->buffer.isEmpty())
- return false;
-
// If the file engine knows best, say what it says.
if (d->fileEngine->supportsExtension(QAbstractFileEngine::AtEndExtension)) {
// Check if the file engine supports AtEndExtension, and if it does,
@@ -1463,6 +1467,11 @@ bool QFile::atEnd() const
return d->fileEngine->atEnd();
}
+ // if it looks like we are at the end, or if size is not cached,
+ // fall through to bytesAvailable() to make sure.
+ if (pos() < d->cachedSize)
+ return false;
+
// Fall back to checking how much is available (will stat files).
return bytesAvailable() == 0;
}
@@ -1502,12 +1511,21 @@ qint64 QFile::readLineData(char *data, qint64 maxlen)
if (!d->ensureFlushed())
return -1;
- if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension))
- return d->fileEngine->readLine(data, maxlen);
+ qint64 read;
+ if (d->fileEngine->supportsExtension(QAbstractFileEngine::FastReadLineExtension)) {
+ read = d->fileEngine->readLine(data, maxlen);
+ } else {
+ // Fall back to QIODevice's readLine implementation if the engine
+ // cannot do it faster.
+ read = QIODevice::readLineData(data, maxlen);
+ }
+
+ if (read < maxlen) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
- // Fall back to QIODevice's readLine implementation if the engine
- // cannot do it faster.
- return QIODevice::readLineData(data, maxlen);
+ return read;
}
/*!
@@ -1528,6 +1546,12 @@ qint64 QFile::readData(char *data, qint64 len)
err = QFile::ReadError;
d->setError(err, d->fileEngine->errorString());
}
+
+ if (read < len) {
+ // failed to read all requested, may be at the end of file, stop caching size so that it's rechecked
+ d->cachedSize = 0;
+ }
+
return read;
}
diff --git a/src/corelib/io/qfile_p.h b/src/corelib/io/qfile_p.h
index f8f5f5c..cf76c09 100644
--- a/src/corelib/io/qfile_p.h
+++ b/src/corelib/io/qfile_p.h
@@ -84,6 +84,8 @@ protected:
void setError(QFile::FileError err, const QString &errorString);
void setError(QFile::FileError err, int errNum);
+ mutable qint64 cachedSize;
+
private:
static QFile::EncoderFn encoder;
static QFile::DecoderFn decoder;
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 55c779e..e9e55f3 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -155,6 +155,10 @@ public:
static bool uncListSharesOnServer(const QString &server, QStringList *list);
#endif
+#ifdef Q_OS_SYMBIAN
+ void setSymbianError(int symbianError, QFile::FileError defaultError, QString defaultString);
+#endif
+
protected:
QFSFileEnginePrivate();
diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp
index 3dcc1ad..1415e44 100644
--- a/src/corelib/io/qfsfileengine_unix.cpp
+++ b/src/corelib/io/qfsfileengine_unix.cpp
@@ -81,6 +81,40 @@ static bool isRelativePathSymbian(const QString& fileName)
&& ((fileName.at(0).isLetter() && fileName.at(1) == QLatin1Char(':'))
|| (fileName.at(0) == QLatin1Char('/') && fileName.at(1) == QLatin1Char('/')))));
}
+
+/*!
+ \internal
+ convert symbian error code to the one suitable for setError.
+ example usage: setSymbianError(err, QFile::CopyError, QLatin1String("copy error"))
+*/
+void QFSFileEnginePrivate::setSymbianError(int symbianError, QFile::FileError defaultError, QString defaultString)
+{
+ Q_Q(QFSFileEngine);
+ switch (symbianError) {
+ case KErrNone:
+ q->setError(QFile::NoError, QLatin1String(""));
+ break;
+ case KErrAccessDenied:
+ q->setError(QFile::PermissionsError, QLatin1String("access denied"));
+ break;
+ case KErrPermissionDenied:
+ q->setError(QFile::PermissionsError, QLatin1String("permission denied"));
+ break;
+ case KErrAbort:
+ q->setError(QFile::AbortError, QLatin1String("aborted"));
+ break;
+ case KErrCancel:
+ q->setError(QFile::AbortError, QLatin1String("cancelled"));
+ break;
+ case KErrTimedOut:
+ q->setError(QFile::TimeOutError, QLatin1String("timed out"));
+ break;
+ default:
+ q->setError(defaultError, defaultString);
+ break;
+ }
+}
+
#endif
/*!
@@ -427,8 +461,10 @@ bool QFSFileEngine::copy(const QString &newName)
}
) // End TRAP
delete fm;
- // ### Add error reporting on failure
- return (err == KErrNone);
+ if (err == KErrNone)
+ return true;
+ d->setSymbianError(err, QFile::CopyError, QLatin1String("copy error"));
+ return false;
#else
Q_UNUSED(newName);
// ### Add copy code for Unix here
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index c93f0c3..f83c142 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -84,10 +84,6 @@ void debugBinaryString(const char *data, qint64 maxlen)
}
#endif
-#ifndef QIODEVICE_BUFFERSIZE
-#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)
-#endif
-
#define Q_VOID
#define CHECK_MAXLEN(function, returnType) \
@@ -123,7 +119,9 @@ void debugBinaryString(const char *data, qint64 maxlen)
QIODevicePrivate::QIODevicePrivate()
: openMode(QIODevice::NotOpen), buffer(QIODEVICE_BUFFERSIZE),
pos(0), devicePos(0)
+ , pPos(&pos), pDevicePos(&devicePos)
, baseReadLineDataCalled(false)
+ , firstRead(true)
, accessMode(Unset)
#ifdef QT_NO_QOBJECT
, q_ptr(0)
@@ -449,11 +447,15 @@ QIODevice::OpenMode QIODevice::openMode() const
*/
void QIODevice::setOpenMode(OpenMode openMode)
{
+ Q_D(QIODevice);
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::setOpenMode(0x%x)\n", this, int(openMode));
#endif
- d_func()->openMode = openMode;
- d_func()->accessMode = QIODevicePrivate::Unset;
+ d->openMode = openMode;
+ d->accessMode = QIODevicePrivate::Unset;
+ d->firstRead = true;
+ if (!isReadable())
+ d->buffer.clear();
}
/*!
@@ -537,6 +539,7 @@ bool QIODevice::open(OpenMode mode)
d->pos = (mode & Append) ? size() : qint64(0);
d->buffer.clear();
d->accessMode = QIODevicePrivate::Unset;
+ d->firstRead = true;
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::open(0x%x)\n", this, quint32(mode));
#endif
@@ -566,6 +569,7 @@ void QIODevice::close()
d->errorString.clear();
d->pos = 0;
d->buffer.clear();
+ d->firstRead = true;
}
/*!
@@ -729,6 +733,12 @@ qint64 QIODevice::bytesToWrite() const
return qint64(0);
}
+#ifdef Q_CC_RVCT
+// arm mode makes the 64-bit integer operations much faster in RVCT 2.2
+#pragma push
+#pragma arm
+#endif
+
/*!
Reads at most \a maxSize bytes from the device into \a data, and
returns the number of bytes read. If an error occurs, such as when
@@ -745,21 +755,17 @@ qint64 QIODevice::bytesToWrite() const
qint64 QIODevice::read(char *data, qint64 maxSize)
{
Q_D(QIODevice);
- CHECK_READABLE(read, qint64(-1));
- CHECK_MAXLEN(read, qint64(-1));
#if defined QIODEVICE_DEBUG
printf("%p QIODevice::read(%p, %d), d->pos = %d, d->buffer.size() = %d\n",
this, data, int(maxSize), int(d->pos), int(d->buffer.size()));
#endif
- const bool sequential = d->isSequential();
// Short circuit for getChar()
if (maxSize == 1) {
int chint;
while ((chint = d->buffer.getChar()) != -1) {
- if (!sequential)
- ++d->pos;
+ ++(*d->pPos);
char c = char(uchar(chint));
if (c == '\r' && (d->openMode & Text))
@@ -773,61 +779,77 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
}
}
+ CHECK_MAXLEN(read, qint64(-1));
qint64 readSoFar = 0;
bool moreToRead = true;
do {
- int lastReadChunkSize = 0;
-
// Try reading from the buffer.
- if (!d->buffer.isEmpty()) {
- lastReadChunkSize = d->buffer.read(data + readSoFar, maxSize - readSoFar);
- readSoFar += lastReadChunkSize;
- if (!sequential)
- d->pos += lastReadChunkSize;
+ int lastReadChunkSize = d->buffer.read(data, maxSize);
+ *d->pPos += lastReadChunkSize;
+ readSoFar += lastReadChunkSize;
+ // fast exit when satisfied by buffer
+ if (lastReadChunkSize == maxSize && !(d->openMode & Text))
+ return readSoFar;
+
+ if (lastReadChunkSize > 0) {
+ data += lastReadChunkSize;
+ maxSize -= lastReadChunkSize;
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from buffer into position %d\n", this, lastReadChunkSize,
int(readSoFar) - lastReadChunkSize);
#endif
- } else if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
- // In buffered mode, we try to fill up the QIODevice buffer before
- // we do anything else.
- int bytesToBuffer = qMax(maxSize - readSoFar, QIODEVICE_BUFFERSIZE);
- char *writePointer = d->buffer.reserve(bytesToBuffer);
-
- // Make sure the device is positioned correctly.
- if (d->pos != d->devicePos && !sequential && !seek(d->pos))
- return qint64(-1);
- qint64 readFromDevice = readData(writePointer, bytesToBuffer);
- d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice)));
+ } else {
+ if (d->firstRead) {
+ // this is the first time the file has been read, check it's valid and set up pos pointers
+ // for fast pos updates.
+ CHECK_READABLE(read, qint64(-1));
+ d->firstRead = false;
+ if (d->isSequential()) {
+ d->pPos = &d->seqDumpPos;
+ d->pDevicePos = &d->seqDumpPos;
+ }
+ }
- if (readFromDevice > 0) {
- if (!sequential)
- d->devicePos += readFromDevice;
+ if ((d->openMode & Unbuffered) == 0 && maxSize < QIODEVICE_BUFFERSIZE) {
+ // In buffered mode, we try to fill up the QIODevice buffer before
+ // we do anything else.
+ // buffer is empty at this point, try to fill it
+ int bytesToBuffer = QIODEVICE_BUFFERSIZE;
+ char *writePointer = d->buffer.reserve(bytesToBuffer);
+
+ // Make sure the device is positioned correctly.
+ if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
+ return readSoFar ? readSoFar : qint64(-1);
+ qint64 readFromDevice = readData(writePointer, bytesToBuffer);
+ d->buffer.chop(bytesToBuffer - (readFromDevice < 0 ? 0 : int(readFromDevice)));
+
+ if (readFromDevice > 0) {
+ *d->pDevicePos += readFromDevice;
#if defined QIODEVICE_DEBUG
- printf("%p \treading %d from device into buffer\n", this, int(readFromDevice));
+ printf("%p \treading %d from device into buffer\n", this, int(readFromDevice));
#endif
- if (readFromDevice < bytesToBuffer)
- d->buffer.truncate(int(readFromDevice));
- if (!d->buffer.isEmpty()) {
- lastReadChunkSize = d->buffer.read(data + readSoFar, maxSize - readSoFar);
- readSoFar += lastReadChunkSize;
- if (!sequential)
- d->pos += lastReadChunkSize;
+ if (!d->buffer.isEmpty()) {
+ lastReadChunkSize = d->buffer.read(data, maxSize);
+ readSoFar += lastReadChunkSize;
+ data += lastReadChunkSize;
+ maxSize -= lastReadChunkSize;
+ *d->pPos += lastReadChunkSize;
#if defined QIODEVICE_DEBUG
- printf("%p \treading %d bytes from buffer at position %d\n", this,
- lastReadChunkSize, int(readSoFar));
+ printf("%p \treading %d bytes from buffer at position %d\n", this,
+ lastReadChunkSize, int(readSoFar));
#endif
+ }
}
}
}
// If we need more, try reading from the device.
- if (readSoFar < maxSize) {
+ if (maxSize > 0) {
// Make sure the device is positioned correctly.
- if (d->pos != d->devicePos && !sequential && !seek(d->pos))
- return qint64(-1);
- qint64 readFromDevice = readData(data + readSoFar, maxSize - readSoFar);
+ if (d->pos != d->devicePos && !d->isSequential() && !seek(d->pos))
+ return readSoFar ? readSoFar : qint64(-1);
+ qint64 readFromDevice = readData(data, maxSize);
#if defined QIODEVICE_DEBUG
printf("%p \treading %d bytes from device (total %d)\n", this, int(readFromDevice), int(readSoFar));
#endif
@@ -835,27 +857,21 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
// error and we haven't read anything: return immediately
return -1;
}
- if (readFromDevice <= 0) {
- moreToRead = false;
- } else {
- // see if we read as much data as we asked for
- if (readFromDevice < maxSize - readSoFar)
- moreToRead = false;
-
+ if (readFromDevice > 0) {
lastReadChunkSize += int(readFromDevice);
readSoFar += readFromDevice;
- if (!sequential) {
- d->pos += readFromDevice;
- d->devicePos += readFromDevice;
- }
+ data += readFromDevice;
+ maxSize -= readFromDevice;
+ *d->pPos += readFromDevice;
+ *d->pDevicePos += readFromDevice;
}
- } else {
- moreToRead = false;
}
+ // Best attempt has been made to read data, don't try again except for text mode adjustment below
+ moreToRead = false;
if (readSoFar && d->openMode & Text) {
- char *readPtr = data + readSoFar - lastReadChunkSize;
- const char *endPtr = data + readSoFar;
+ char *readPtr = data - lastReadChunkSize;
+ const char *endPtr = data;
if (readPtr < endPtr) {
// optimization to avoid initial self-assignment
@@ -870,8 +886,11 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
char ch = *readPtr++;
if (ch != '\r')
*writePtr++ = ch;
- else
+ else {
--readSoFar;
+ --data;
+ ++maxSize;
+ }
}
// Make sure we get more data if there is room for more. This
@@ -885,11 +904,15 @@ qint64 QIODevice::read(char *data, qint64 maxSize)
#if defined QIODEVICE_DEBUG
printf("%p \treturning %d, d->pos == %d, d->buffer.size() == %d\n", this,
int(readSoFar), int(d->pos), d->buffer.size());
- debugBinaryString(data, readSoFar);
+ debugBinaryString(data - readSoFar, readSoFar);
#endif
return readSoFar;
}
+#ifdef Q_CC_RVCT
+#pragma pop
+#endif
+
/*!
\overload
@@ -997,6 +1020,12 @@ QByteArray QIODevice::readAll()
return result;
}
+#ifdef Q_CC_RVCT
+// arm mode makes the 64-bit integer operations much faster in RVCT 2.2
+#pragma push
+#pragma arm
+#endif
+
/*!
This function reads a line of ASCII characters from the device, up
to a maximum of \a maxSize - 1 bytes, stores the characters in \a
@@ -1229,6 +1258,10 @@ qint64 QIODevice::readLineData(char *data, qint64 maxSize)
return readSoFar;
}
+#ifdef Q_CC_RVCT
+#pragma pop
+#endif
+
/*!
Returns true if a complete line of data can be read from the device;
otherwise returns false.
@@ -1416,9 +1449,7 @@ bool QIODevicePrivate::putCharHelper(char c)
*/
bool QIODevice::getChar(char *c)
{
- Q_D(QIODevice);
- CHECK_READABLE(getChar, false);
-
+ // readability checked in read()
char ch;
return (1 == read(c ? c : &ch, 1));
}
diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h
index cc4a237..94dadca 100644
--- a/src/corelib/io/qiodevice_p.h
+++ b/src/corelib/io/qiodevice_p.h
@@ -64,6 +64,126 @@
QT_BEGIN_NAMESPACE
+#ifndef QIODEVICE_BUFFERSIZE
+#define QIODEVICE_BUFFERSIZE Q_INT64_C(16384)
+#endif
+
+// This is QIODevice's read buffer, optimised for read(), isEmpty() and getChar()
+class QIODevicePrivateLinearBuffer
+{
+public:
+ QIODevicePrivateLinearBuffer(int) : len(0), first(0), buf(0), capacity(0) {
+ }
+ ~QIODevicePrivateLinearBuffer() {
+ delete [] buf;
+ }
+ void clear() {
+ first = buf;
+ len = 0;
+ }
+ int size() const {
+ return len;
+ }
+ bool isEmpty() const {
+ return len == 0;
+ }
+ void skip(int n) {
+ if (n >= len) {
+ clear();
+ } else {
+ len -= n;
+ first += n;
+ }
+ }
+ int getChar() {
+ if (len == 0)
+ return -1;
+ int ch = uchar(*first);
+ len--;
+ first++;
+ return ch;
+ }
+ int read(char* target, int size) {
+ int r = qMin(size, len);
+ memcpy(target, first, r);
+ len -= r;
+ first += r;
+ return r;
+ }
+ char* reserve(int size) {
+ makeSpace(size + len, freeSpaceAtEnd);
+ char* writePtr = first + len;
+ len += size;
+ return writePtr;
+ }
+ void chop(int size) {
+ if (size >= len) {
+ clear();
+ } else {
+ len -= size;
+ }
+ }
+ QByteArray readAll() {
+ char* f = first;
+ int l = len;
+ clear();
+ return QByteArray(f, l);
+ }
+ int readLine(char* target, int size) {
+ int r = qMin(size, len);
+ char* eol = static_cast<char*>(memchr(first, '\n', r));
+ if (eol)
+ r = 1+(eol-first);
+ memcpy(target, first, r);
+ len -= r;
+ first += r;
+ return int(r);
+ }
+ bool canReadLine() const {
+ return memchr(first, '\n', len);
+ }
+ void ungetChar(char c) {
+ if (first == buf) {
+ // underflow, the existing valid data needs to move to the end of the (potentially bigger) buffer
+ makeSpace(len+1, freeSpaceAtStart);
+ }
+ first--;
+ len++;
+ *first = c;
+ }
+
+private:
+ enum FreeSpacePos {freeSpaceAtStart, freeSpaceAtEnd};
+ void makeSpace(size_t required, FreeSpacePos where) {
+ size_t newCapacity = qMax(capacity, size_t(QIODEVICE_BUFFERSIZE));
+ while (newCapacity < required)
+ newCapacity *= 2;
+ int moveOffset = (where == freeSpaceAtEnd) ? 0 : newCapacity - len;
+ if (newCapacity > capacity) {
+ // allocate more space
+ char* newBuf = new char[newCapacity];
+ memmove(newBuf + moveOffset, first, len);
+ delete [] buf;
+ buf = newBuf;
+ capacity = newCapacity;
+ } else {
+ // shift any existing data to make space
+ memmove(buf + moveOffset, first, len);
+ }
+ first = buf + moveOffset;
+ }
+
+private:
+ // length of the unread data
+ int len;
+ // start of the unread data
+ char* first;
+ // the allocated buffer
+ char* buf;
+ // allocated buffer size
+ size_t capacity;
+};
+
class Q_CORE_EXPORT QIODevicePrivate
#ifndef QT_NO_QOBJECT
: public QObjectPrivate
@@ -78,10 +198,15 @@ public:
QIODevice::OpenMode openMode;
QString errorString;
- QRingBuffer buffer;
+ QIODevicePrivateLinearBuffer buffer;
qint64 pos;
qint64 devicePos;
+ // these three are for fast position updates during read, avoiding isSequential test
+ qint64 seqDumpPos;
+ qint64 *pPos;
+ qint64 *pDevicePos;
bool baseReadLineDataCalled;
+ bool firstRead;
virtual bool putCharHelper(char c);
diff --git a/src/corelib/kernel/qeventdispatcher_symbian.cpp b/src/corelib/kernel/qeventdispatcher_symbian.cpp
index 191be6c..ca44264 100644
--- a/src/corelib/kernel/qeventdispatcher_symbian.cpp
+++ b/src/corelib/kernel/qeventdispatcher_symbian.cpp
@@ -50,6 +50,13 @@
QT_BEGIN_NAMESPACE
+#ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS
+// when the system UI is Qt based, priority drop is not needed as CPU starved processes will not be killed.
+#undef QT_SYMBIAN_PRIORITY_DROP
+#else
+#define QT_SYMBIAN_PRIORITY_DROP
+#endif
+
#define WAKE_UP_PRIORITY CActive::EPriorityStandard
#define TIMER_PRIORITY CActive::EPriorityHigh
#define NULLTIMER_PRIORITY CActive::EPriorityLow
@@ -697,6 +704,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
bool handledSymbianEvent = false;
m_interrupt = false;
+#ifdef QT_SYMBIAN_PRIORITY_DROP
/*
* This QTime variable is used to measure the time it takes to finish
* the event loop. If we take too long in the loop, other processes
@@ -714,6 +722,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
} timeState = FirstRun;
TProcessPriority priority;
+#endif
while (1) {
if (block) {
@@ -727,10 +736,12 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
CActiveScheduler::Current()->WaitForAnyRequest();
}
+#ifdef QT_SYMBIAN_PRIORITY_DROP
if (timeState == SubsequentRun) {
time.start();
timeState = TimeStarted;
}
+#endif
TInt error;
handledSymbianEvent = CActiveScheduler::RunIfReady(error, KMinTInt);
@@ -747,6 +758,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
break;
}
block = false;
+#ifdef QT_SYMBIAN_PRIORITY_DROP
if (timeState == TimeStarted && time.elapsed() > 100) {
priority = m_processHandle.Priority();
m_processHandle.SetPriority(EPriorityBackground);
@@ -759,6 +771,7 @@ bool QEventDispatcherSymbian::processEvents ( QEventLoop::ProcessEventsFlags fla
}
if (timeState == FirstRun)
timeState = SubsequentRun;
+#endif
};
emit awake();
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index bd7e626..9d5c49f 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -1175,6 +1175,16 @@ void QStateMachinePrivate::removeStartState()
_startState = 0;
}
+void QStateMachinePrivate::clearHistory()
+{
+ Q_Q(QStateMachine);
+ QList<QHistoryState*> historyStates = qFindChildren<QHistoryState*>(q);
+ for (int i = 0; i < historyStates.size(); ++i) {
+ QHistoryState *h = historyStates.at(i);
+ QHistoryStatePrivate::get(h)->configuration.clear();
+ }
+}
+
void QStateMachinePrivate::_q_start()
{
Q_Q(QStateMachine);
@@ -1186,6 +1196,7 @@ void QStateMachinePrivate::_q_start()
internalEventQueue.clear();
qDeleteAll(externalEventQueue);
externalEventQueue.clear();
+ clearHistory();
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": starting";
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index 0fead5d..5e1015f 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -126,6 +126,8 @@ public:
QState *startState();
void removeStartState();
+ void clearHistory();
+
void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const;
QSet<QAbstractTransition*> selectTransitions(QEvent *event) const;
diff --git a/src/corelib/tools/qchar.cpp b/src/corelib/tools/qchar.cpp
index 2bc5347..67ea00d 100644
--- a/src/corelib/tools/qchar.cpp
+++ b/src/corelib/tools/qchar.cpp
@@ -380,8 +380,12 @@ QT_BEGIN_NAMESPACE
\value Null A QChar with this value isNull().
\value Nbsp Non-breaking space.
- \value ReplacementCharacter
- \value ObjectReplacementCharacter The character shown when a font has no glyph for a certain codepoint. The square character is normally used.
+ \value ReplacementCharacter The character shown when a font has no glyph
+ for a certain codepoint. A special question mark character is often
+ used. Codecs use this codepoint when input data cannot be
+ represented in Unicode.
+ \value ObjectReplacementCharacter Used to represent an object such as an
+ image when such objects cannot be presented.
\value ByteOrderMark
\value ByteOrderSwapped
\value ParagraphSeparator
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 54a4205..3e34d62 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -1336,7 +1336,10 @@ bool QDate::isValid(int year, int month, int day)
bool QDate::isLeapYear(int y)
{
if (y < 1582) {
- return qAbs(y) % 4 == 0;
+ if ( y < 1) { // No year 0 in Julian calendar, so -1, -5, -9 etc are leap years
+ ++y;
+ }
+ return y % 4 == 0;
} else {
return (y % 4 == 0 && y % 100 != 0) || y % 400 == 0;
}
diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h
index aecb66e..9773d4b 100644
--- a/src/corelib/tools/qvarlengtharray.h
+++ b/src/corelib/tools/qvarlengtharray.h
@@ -107,6 +107,10 @@ public:
Q_ASSERT(idx >= 0 && idx < s);
return ptr[idx];
}
+ inline const T &at(int idx) const { return operator[](idx); }
+
+ T value(int i) const;
+ T value(int i, const T &defaultValue) const;
inline void append(const T &t) {
if (s == a) // i.e. s != 0
@@ -248,6 +252,21 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray<T, Prealloc>::realloc(int asize, int a
}
}
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i) const
+{
+ if (i < 0 || i >= size()) {
+ return T();
+ }
+ return at(i);
+}
+template <class T, int Prealloc>
+Q_OUTOFLINE_TEMPLATE T QVarLengthArray<T, Prealloc>::value(int i, const T &defaultValue) const
+{
+ return (i < 0 || i >= size()) ? defaultValue : at(i);
+}
+
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc
index bb7a3de..38901e5 100644
--- a/src/corelib/tools/qvarlengtharray.qdoc
+++ b/src/corelib/tools/qvarlengtharray.qdoc
@@ -197,7 +197,7 @@
\a i must be a valid index position in the array (i.e., 0 <= \a i
< size()).
- \sa data()
+ \sa data(), at()
*/
/*! \fn const T &QVarLengthArray::operator[](int i) const
@@ -272,3 +272,33 @@
Constructs a copy of \a other.
*/
+/*! \fn const T &QVarLengthArray::at(int i) const
+
+ Returns a reference to the item at index position \a i.
+
+ \a i must be a valid index position in the array (i.e., 0 <= \a i
+ < size()).
+
+ \sa value(), operator[]()
+*/
+
+/*! \fn T QVarLengthArray::value(int i) const
+
+ Returns the value at index position \a i.
+
+ If the index \a i is out of bounds, the function returns
+ a \l{default-constructed value}. If you are certain that
+ \a i is within bounds, you can use at() instead, which is slightly
+ faster.
+
+ \sa at(), operator[]()
+*/
+
+/*! \fn T QVarLengthArray::value(int i, const T &defaultValue) const
+
+ \overload
+
+ If the index \a i is out of bounds, the function returns
+ \a defaultValue.
+*/
+
diff --git a/src/declarative/QmlChanges.txt b/src/declarative/QmlChanges.txt
index 2a35dda..c86bdc6 100644
--- a/src/declarative/QmlChanges.txt
+++ b/src/declarative/QmlChanges.txt
@@ -1,6 +1,7 @@
=============================================================================
The changes below are pre Qt 4.7.0 beta
+Removed Q-prefix from validators (IntValidator, DoubleValidator, and RegExpValidator)
PathView: offset property now uses range 0-1.0 rather than 0-100
ListView, GridView::positionViewAtIndex() gained a 'mode' parameter
Removed Qt.playSound (replaced by SoundEffect element)
@@ -13,6 +14,9 @@ AnchorAnimation must now be used to animate anchor changes (and not NumberAnimat
Removed ParentAction (use ParentAnimation instead)
ScriptAction: renamed stateChangeScriptName -> scriptName
Animation: replace repeat with loops (loops: Animation.Infinite gives the old repeat behavior)
+AnchorChanges: use natural form to specify anchors (anchors.left instead of left)
+AnchorChanges: removed reset property. (reset: "left" should now be anchors.left: undefined)
+PathView: snapPosition replaced by preferredHighlightBegin, preferredHighlightEnd
C++ API
-------
@@ -28,6 +32,39 @@ syntax has been introduced:
Item { Behavior on x {}; NumberAnimation on y {} }
Only the syntax has changed, the behavior is identical.
+
+EaseFollow changed to SmoothedAnimation
+---------------------------------------
+EaseFollow was renamed to SmoothedAnimation and now it inherits from
+NumberAnimaton and as a consequence SmoothedAnimation can be used inside
+Behaviors, as PropertySourceValues or in state transitions, like any other animation.
+
+The old EaseFollow properties changed to comply with the other declarative
+animations ('source' changed to 'to'), so now 'to' changes are not
+automatically 'followed' anymore.
+
+If you want to follow an hypothetical rect1, you should do now:
+
+     Rectangle {
+         color: "green"
+         width: 60; height: 60;
+         x: rect1.x - 5; y: rect1.y - 5;
+         Behavior on x { SmoothedAnimation { velocity: 200 } }
+         Behavior on y { SmoothedAnimation { velocity: 200 } }
+     }
+
+instead of the old automatic source changed tracking:
+
+     Rectangle {
+         color: "green"
+         width: 60; height: 60;
+         EaseFollow on x { source: rect1.x - 5; velocity: 200 }
+         EaseFollow on y { source: rect1.y - 5; velocity: 200 }
+    }
+
+This is a syntax and behavior change.
+
+
Script element removed
----------------------
Inline Script{} blocks have been deprecated, and will soon be removed entirely.
@@ -58,7 +95,7 @@ MouseArea {
becomes
-Import “foo.js” as Foo
+import “foo.js” as Foo
MouseArea {
onClicked: Foo.foo()
}
diff --git a/src/declarative/graphicsitems/graphicsitems.pri b/src/declarative/graphicsitems/graphicsitems.pri
index d30651b..af76a67 100644
--- a/src/declarative/graphicsitems/graphicsitems.pri
+++ b/src/declarative/graphicsitems/graphicsitems.pri
@@ -39,6 +39,7 @@ HEADERS += \
$$PWD/qdeclarativerepeater_p.h \
$$PWD/qdeclarativerepeater_p_p.h \
$$PWD/qdeclarativescalegrid_p_p.h \
+ $$PWD/qdeclarativetranslate_p.h \
$$PWD/qdeclarativetextinput_p.h \
$$PWD/qdeclarativetextinput_p_p.h \
$$PWD/qdeclarativetextedit_p.h \
@@ -75,6 +76,7 @@ SOURCES += \
$$PWD/qdeclarativerectangle.cpp \
$$PWD/qdeclarativerepeater.cpp \
$$PWD/qdeclarativescalegrid.cpp \
+ $$PWD/qdeclarativetranslate.cpp \
$$PWD/qdeclarativetextinput.cpp \
$$PWD/qdeclarativetext.cpp \
$$PWD/qdeclarativetextedit.cpp \
diff --git a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
index a7534b8..96f95f2 100644
--- a/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeborderimage.cpp
@@ -217,7 +217,8 @@ void QDeclarativeBorderImage::load()
thisSciRequestFinished, Qt::DirectConnection);
}
} else {
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, d->async);
+ QSize impsize;
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, &impsize, d->async);
if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url);
d->pendingPixmapCache = true;
@@ -226,8 +227,8 @@ void QDeclarativeBorderImage::load()
this, SLOT(requestProgress(qint64,qint64)));
} else {
//### should be unified with requestFinished
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
if (d->pix.isNull())
d->status = Error;
@@ -336,7 +337,8 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma
d->verticalTileMode = sci.verticalTileRule();
d->sciurl = d->url.resolved(QUrl(sci.pixmapUrl()));
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->sciurl, &d->pix, d->async);
+ QSize impsize;
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->sciurl, &d->pix, &impsize, d->async);
if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->sciurl);
d->sciPendingPixmapCache = true;
@@ -362,8 +364,8 @@ void QDeclarativeBorderImage::setGridScaledImage(const QDeclarativeGridScaledIma
thisRequestProgress, Qt::DirectConnection);
} else {
//### should be unified with requestFinished
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
if (d->pix.isNull())
d->status = Error;
@@ -381,16 +383,17 @@ void QDeclarativeBorderImage::requestFinished()
{
Q_D(QDeclarativeBorderImage);
+ QSize impsize;
if (d->url.path().endsWith(QLatin1String(".sci"))) {
d->sciPendingPixmapCache = false;
- QDeclarativePixmapCache::get(d->sciurl, &d->pix, d->async);
+ QDeclarativePixmapCache::get(d->sciurl, &d->pix, &impsize, d->async);
} else {
d->pendingPixmapCache = false;
- if (QDeclarativePixmapCache::get(d->url, &d->pix, d->async) != QDeclarativePixmapReply::Ready)
+ if (QDeclarativePixmapCache::get(d->url, &d->pix, &impsize, d->async) != QDeclarativePixmapReply::Ready)
d->status = Error;
}
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
if (d->status == Loading)
d->status = Ready;
@@ -444,7 +447,7 @@ void QDeclarativeBorderImage::paint(QPainter *p, const QStyleOptionGraphicsItem
const QDeclarativeScaleGrid *border = d->getScaleGrid();
QMargins margins(border->left(), border->top(), border->right(), border->bottom());
QTileRules rules((Qt::TileRule)d->horizontalTileMode, (Qt::TileRule)d->verticalTileMode);
- qDrawBorderPixmap(p, QRect(0, 0, (int)d->width, (int)d->height), margins, d->pix, d->pix.rect(), margins, rules);
+ qDrawBorderPixmap(p, QRect(0, 0, (int)d->width(), (int)d->height()), margins, d->pix, d->pix.rect(), margins, rules);
if (d->smooth) {
p->setRenderHint(QPainter::Antialiasing, oldAA);
p->setRenderHint(QPainter::SmoothPixmapTransform, oldSmooth);
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
index 9ccb3b6..fb22429 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
@@ -137,7 +137,8 @@ QDeclarativeFlickablePrivate::QDeclarativeFlickablePrivate()
void QDeclarativeFlickablePrivate::init()
{
Q_Q(QDeclarativeFlickable);
- viewport->setParent(q);
+ QDeclarative_setParent_noEvent(viewport, q);
+ viewport->setParentItem(q);
static int timelineUpdatedIdx = -1;
static int timelineCompletedIdx = -1;
static int flickableTickedIdx = -1;
@@ -990,10 +991,10 @@ QDeclarativeListProperty<QObject> QDeclarativeFlickable::flickableData()
return QDeclarativeListProperty<QObject>(this, (void *)d, QDeclarativeFlickablePrivate::data_append);
}
-QDeclarativeListProperty<QDeclarativeItem> QDeclarativeFlickable::flickableChildren()
+QDeclarativeListProperty<QGraphicsObject> QDeclarativeFlickable::flickableChildren()
{
Q_D(QDeclarativeFlickable);
- return d->viewport->fxChildren();
+ return QGraphicsItemPrivate::get(d->viewport)->childrenList();
}
/*!
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable_p.h b/src/declarative/graphicsitems/qdeclarativeflickable_p.h
index 7dcab98..1fa2c74 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeflickable_p.h
@@ -82,7 +82,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlickable : public QDeclarativeItem
Q_PROPERTY(QDeclarativeFlickableVisibleArea *visibleArea READ visibleArea CONSTANT)
Q_PROPERTY(QDeclarativeListProperty<QObject> flickableData READ flickableData)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> flickableChildren READ flickableChildren)
+ Q_PROPERTY(QDeclarativeListProperty<QGraphicsObject> flickableChildren READ flickableChildren)
Q_CLASSINFO("DefaultProperty", "flickableData")
Q_ENUMS(FlickDirection)
@@ -92,7 +92,7 @@ public:
~QDeclarativeFlickable();
QDeclarativeListProperty<QObject> flickableData();
- QDeclarativeListProperty<QDeclarativeItem> flickableChildren();
+ QDeclarativeListProperty<QGraphicsObject> flickableChildren();
bool overShoot() const;
void setOverShoot(bool);
diff --git a/src/declarative/graphicsitems/qdeclarativeflipable.cpp b/src/declarative/graphicsitems/qdeclarativeflipable.cpp
index 1fa08bb..e670d3e 100644
--- a/src/declarative/graphicsitems/qdeclarativeflipable.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeflipable.cpp
@@ -59,8 +59,8 @@ public:
void updateSceneTransformFromParent();
QDeclarativeFlipable::Side current;
- QDeclarativeGuard<QDeclarativeItem> front;
- QDeclarativeGuard<QDeclarativeItem> back;
+ QDeclarativeGuard<QGraphicsObject> front;
+ QDeclarativeGuard<QGraphicsObject> back;
};
/*!
@@ -112,13 +112,13 @@ QDeclarativeFlipable::~QDeclarativeFlipable()
The front and back sides of the flipable.
*/
-QDeclarativeItem *QDeclarativeFlipable::front()
+QGraphicsObject *QDeclarativeFlipable::front()
{
Q_D(const QDeclarativeFlipable);
return d->front;
}
-void QDeclarativeFlipable::setFront(QDeclarativeItem *front)
+void QDeclarativeFlipable::setFront(QGraphicsObject *front)
{
Q_D(QDeclarativeFlipable);
if (d->front) {
@@ -131,13 +131,13 @@ void QDeclarativeFlipable::setFront(QDeclarativeItem *front)
d->front->setOpacity(0.);
}
-QDeclarativeItem *QDeclarativeFlipable::back()
+QGraphicsObject *QDeclarativeFlipable::back()
{
Q_D(const QDeclarativeFlipable);
return d->back;
}
-void QDeclarativeFlipable::setBack(QDeclarativeItem *back)
+void QDeclarativeFlipable::setBack(QGraphicsObject *back)
{
Q_D(QDeclarativeFlipable);
if (d->back) {
@@ -195,12 +195,13 @@ void QDeclarativeFlipablePrivate::updateSceneTransformFromParent()
current = newSide;
if (current == QDeclarativeFlipable::Back && back) {
QTransform mat;
- mat.translate(back->width()/2,back->height()/2);
- if (back->width() && p1.x() >= p2.x())
+ QGraphicsItemPrivate *dBack = QGraphicsItemPrivate::get(back);
+ mat.translate(dBack->width()/2,dBack->height()/2);
+ if (dBack->width() && p1.x() >= p2.x())
mat.rotate(180, Qt::YAxis);
- if (back->height() && p2.y() >= p3.y())
+ if (dBack->height() && p2.y() >= p3.y())
mat.rotate(180, Qt::XAxis);
- mat.translate(-back->width()/2,-back->height()/2);
+ mat.translate(-dBack->width()/2,-dBack->height()/2);
back->setTransform(mat);
}
if (front)
diff --git a/src/declarative/graphicsitems/qdeclarativeflipable_p.h b/src/declarative/graphicsitems/qdeclarativeflipable_p.h
index 8b9c24c..302f083 100644
--- a/src/declarative/graphicsitems/qdeclarativeflipable_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeflipable_p.h
@@ -60,8 +60,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeFlipable : public QDeclarativeItem
Q_OBJECT
Q_ENUMS(Side)
- Q_PROPERTY(QDeclarativeItem *front READ front WRITE setFront)
- Q_PROPERTY(QDeclarativeItem *back READ back WRITE setBack)
+ Q_PROPERTY(QGraphicsObject *front READ front WRITE setFront)
+ Q_PROPERTY(QGraphicsObject *back READ back WRITE setBack)
Q_PROPERTY(Side side READ side NOTIFY sideChanged)
//### flipAxis
//### flipRotation
@@ -69,11 +69,11 @@ public:
QDeclarativeFlipable(QDeclarativeItem *parent=0);
~QDeclarativeFlipable();
- QDeclarativeItem *front();
- void setFront(QDeclarativeItem *);
+ QGraphicsObject *front();
+ void setFront(QGraphicsObject *);
- QDeclarativeItem *back();
- void setBack(QDeclarativeItem *);
+ QGraphicsObject *back();
+ void setBack(QGraphicsObject *);
enum Side { Front, Back };
Side side() const;
diff --git a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp b/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp
index eb5b6ce..ff85bbd 100644
--- a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer.cpp
@@ -65,12 +65,12 @@ public:
if (graphicsObject && graphicsObject->isWidget()) {
if (!on) {
graphicsObject->removeEventFilter(q);
- QObject::disconnect(q, SIGNAL(widthChanged(qreal)), q, SLOT(_q_updateSize()));
- QObject::disconnect(q, SIGNAL(heightChanged(qreal)), q, SLOT(_q_updateSize()));
+ QObject::disconnect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize()));
+ QObject::disconnect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize()));
} else {
graphicsObject->installEventFilter(q);
- QObject::connect(q, SIGNAL(widthChanged(qreal)), q, SLOT(_q_updateSize()));
- QObject::connect(q, SIGNAL(heightChanged(qreal)), q, SLOT(_q_updateSize()));
+ QObject::connect(q, SIGNAL(widthChanged()), q, SLOT(_q_updateSize()));
+ QObject::connect(q, SIGNAL(heightChanged()), q, SLOT(_q_updateSize()));
}
}
}
@@ -251,7 +251,7 @@ void QDeclarativeGraphicsObjectContainerPrivate::_q_updateSize()
return;
QGraphicsWidget *gw = static_cast<QGraphicsWidget*>(graphicsObject);
- const QSizeF newSize(width, height);
+ const QSizeF newSize(width(), height());
gw->resize(newSize);
//### will respecting the widgets min/max ever get us in trouble? (all other items always
diff --git a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h b/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h
index 95d7a4b..20c5bcf 100644
--- a/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h
+++ b/src/declarative/graphicsitems/qdeclarativegraphicsobjectcontainer_p.h
@@ -82,7 +82,6 @@ private:
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QGraphicsObject)
QML_DECLARE_TYPE(QDeclarativeGraphicsObjectContainer)
QT_END_HEADER
diff --git a/src/declarative/graphicsitems/qdeclarativegridview.cpp b/src/declarative/graphicsitems/qdeclarativegridview.cpp
index de0cb04..12ede34 100644
--- a/src/declarative/graphicsitems/qdeclarativegridview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativegridview.cpp
@@ -44,7 +44,7 @@
#include "qdeclarativevisualitemmodel_p.h"
#include "qdeclarativeflickable_p_p.h"
-#include <qdeclarativeeasefollow_p.h>
+#include "qdeclarativesmoothedanimation_p_p.h"
#include <qdeclarativeguard_p.h>
#include <qlistmodelinterface_p.h>
@@ -324,8 +324,8 @@ public:
enum MovementReason { Other, SetIndex, Mouse };
MovementReason moveReason;
int buffer;
- QDeclarativeEaseFollow *highlightXAnimator;
- QDeclarativeEaseFollow *highlightYAnimator;
+ QSmoothedAnimation *highlightXAnimator;
+ QSmoothedAnimation *highlightYAnimator;
enum BufferMode { NoBuffer = 0x00, BufferBefore = 0x01, BufferAfter = 0x02 };
BufferMode bufferMode;
QDeclarativeGridView::SnapMode snapMode;
@@ -372,7 +372,7 @@ FxGridItem *QDeclarativeGridViewPrivate::createItem(int modelIndex)
listItem->item->setZValue(1);
// complete
model->completeItem();
- listItem->item->setParent(q->viewport());
+ listItem->item->setParentItem(q->viewport());
unrequestedItems.remove(listItem->item);
}
requestedIndex = -1;
@@ -644,7 +644,7 @@ void QDeclarativeGridViewPrivate::createHighlight()
QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
QObject *nobj = highlightComponent->create(highlightContext);
if (nobj) {
- highlightContext->setParent(nobj);
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
item = qobject_cast<QDeclarativeItem *>(nobj);
if (!item)
delete nobj;
@@ -653,19 +653,21 @@ void QDeclarativeGridViewPrivate::createHighlight()
}
} else {
item = new QDeclarativeItem;
- item->setParent(q->viewport());
+ QDeclarative_setParent_noEvent(item, q->viewport());
+ item->setParentItem(q->viewport());
}
if (item) {
- item->setParent(q->viewport());
+ QDeclarative_setParent_noEvent(item, q->viewport());
+ item->setParentItem(q->viewport());
highlight = new FxGridItem(item, q);
- highlightXAnimator = new QDeclarativeEaseFollow(q);
- highlightXAnimator->setTarget(QDeclarativeProperty(highlight->item, QLatin1String("x")));
- highlightXAnimator->setDuration(150);
- highlightXAnimator->setEnabled(autoHighlight);
- highlightYAnimator = new QDeclarativeEaseFollow(q);
- highlightYAnimator->setTarget(QDeclarativeProperty(highlight->item, QLatin1String("y")));
- highlightYAnimator->setDuration(150);
- highlightYAnimator->setEnabled(autoHighlight);
+ highlightXAnimator = new QSmoothedAnimation(q);
+ highlightXAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("x"));
+ highlightXAnimator->userDuration = 150;
+ highlightYAnimator = new QSmoothedAnimation(q);
+ highlightYAnimator->target = QDeclarativeProperty(highlight->item, QLatin1String("y"));
+ highlightYAnimator->userDuration = 150;
+ highlightXAnimator->restart();
+ highlightYAnimator->restart();
changed = true;
}
}
@@ -679,10 +681,12 @@ void QDeclarativeGridViewPrivate::updateHighlight()
createHighlight();
if (currentItem && autoHighlight && highlight && !moving) {
// auto-update highlight
- highlightXAnimator->setSourceValue(currentItem->item->x());
- highlightYAnimator->setSourceValue(currentItem->item->y());
+ highlightXAnimator->to = currentItem->item->x();
+ highlightYAnimator->to = currentItem->item->y();
highlight->item->setWidth(currentItem->item->width());
highlight->item->setHeight(currentItem->item->height());
+ highlightXAnimator->restart();
+ highlightYAnimator->restart();
}
updateTrackedItem();
}
@@ -1188,10 +1192,6 @@ void QDeclarativeGridView::setHighlightFollowsCurrentItem(bool autoHighlight)
Q_D(QDeclarativeGridView);
if (d->autoHighlight != autoHighlight) {
d->autoHighlight = autoHighlight;
- if (d->highlightXAnimator) {
- d->highlightXAnimator->setEnabled(d->autoHighlight);
- d->highlightYAnimator->setEnabled(d->autoHighlight);
- }
d->updateHighlight();
}
}
@@ -1482,9 +1482,9 @@ void QDeclarativeGridView::viewportMoved()
d->updateCurrent(idx);
if (d->currentItem && d->currentItem->colPos() != d->highlight->colPos() && d->autoHighlight) {
if (d->flow == LeftToRight)
- d->highlightXAnimator->setSourceValue(d->currentItem->item->x());
+ d->highlightXAnimator->to = d->currentItem->item->x();
else
- d->highlightYAnimator->setSourceValue(d->currentItem->item->y());
+ d->highlightYAnimator->to = d->currentItem->item->y();
}
}
}
@@ -1552,9 +1552,6 @@ qreal QDeclarativeGridView::maxXExtent() const
void QDeclarativeGridView::keyPressEvent(QKeyEvent *event)
{
Q_D(QDeclarativeGridView);
- QDeclarativeFlickable::keyPressEvent(event);
- if (event->isAccepted())
- return;
if (d->model && d->model->count() && d->interactive) {
d->moveReason = QDeclarativeGridViewPrivate::SetIndex;
int oldCurrent = currentIndex();
@@ -1580,6 +1577,9 @@ void QDeclarativeGridView::keyPressEvent(QKeyEvent *event)
}
}
d->moveReason = QDeclarativeGridViewPrivate::Other;
+ QDeclarativeFlickable::keyPressEvent(event);
+ if (event->isAccepted())
+ return;
event->ignore();
}
@@ -2180,7 +2180,6 @@ void QDeclarativeGridView::modelReset()
void QDeclarativeGridView::createdItem(int index, QDeclarativeItem *item)
{
Q_D(QDeclarativeGridView);
- item->setParentItem(this);
if (d->requestedIndex != index) {
item->setParentItem(this);
d->unrequestedItems.insert(item, index);
diff --git a/src/declarative/graphicsitems/qdeclarativeimage.cpp b/src/declarative/graphicsitems/qdeclarativeimage.cpp
index 425976f..23a2350 100644
--- a/src/declarative/graphicsitems/qdeclarativeimage.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimage.cpp
@@ -266,6 +266,31 @@ qreal QDeclarativeImage::paintedHeight() const
filtering at the beginning of the animation and reenable it at the conclusion.
*/
+/*!
+ \qmlproperty QSize Image::sourceSize
+
+ This properties is the size of the loaded image, in pixels.
+
+ If you set this property explicitly, you can to control the storage
+ used by a loaded image. The image will be scaled down if its intrinsic size
+ is greater than this value.
+
+ Unlike setting the width and height properties, which merely scale the painting
+ of the image, this property affects the number of pixels stored.
+
+ \e{Changing this property dynamically will lead to the image source being reloaded,
+ potentially even from the network if it is not in the disk cache.}
+
+ If the source is an instrinsically scalable image (eg. SVG), this property
+ determines the size of the loaded image regardless of intrinsic size. You should
+ avoid changing this property dynamically - rendering an SVG is \e slow compared
+ to an image.
+
+ If the source is a non-scalable image (eg. JPEG), the loaded image will
+ be no greater than this property specifies. For some formats (currently only JPEG),
+ the whole image will never actually be loaded into memory.
+*/
+
void QDeclarativeImage::updatePaintedGeometry()
{
Q_D(QDeclarativeImage);
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
index e65c9d1..5a234b7 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase.cpp
@@ -116,6 +116,23 @@ void QDeclarativeImageBase::setSource(const QUrl &url)
load();
}
+void QDeclarativeImageBase::setSourceSize(const QSize& size)
+{
+ Q_D(QDeclarativeImageBase);
+ if (d->sourcesize == size)
+ return;
+ d->sourcesize = size;
+ emit sourceSizeChanged();
+ if (isComponentComplete())
+ load();
+}
+
+QSize QDeclarativeImageBase::sourceSize() const
+{
+ Q_D(const QDeclarativeImageBase);
+ return d->sourcesize.isValid() ? d->sourcesize : QSize(implicitWidth(),implicitHeight());
+}
+
void QDeclarativeImageBase::load()
{
Q_D(QDeclarativeImageBase);
@@ -134,9 +151,12 @@ void QDeclarativeImageBase::load()
update();
} else {
d->status = Loading;
- QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, d->async);
+ int reqwidth = d->sourcesize.width();
+ int reqheight = d->sourcesize.height();
+ QSize impsize;
+ QDeclarativePixmapReply::Status status = QDeclarativePixmapCache::get(d->url, &d->pix, &impsize, d->async, reqwidth, reqheight);
if (status != QDeclarativePixmapReply::Ready && status != QDeclarativePixmapReply::Error) {
- QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url);
+ QDeclarativePixmapReply *reply = QDeclarativePixmapCache::request(qmlEngine(this), d->url, reqwidth, reqheight);
d->pendingPixmapCache = true;
static int replyDownloadProgress = -1;
@@ -161,11 +181,14 @@ void QDeclarativeImageBase::load()
} else {
//### should be unified with requestFinished
if (status == QDeclarativePixmapReply::Ready) {
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
if (d->status == Loading)
d->status = Ready;
+
+ if (!d->sourcesize.isValid())
+ emit sourceSizeChanged();
} else {
d->status = Error;
}
@@ -186,16 +209,19 @@ void QDeclarativeImageBase::requestFinished()
d->pendingPixmapCache = false;
- if (QDeclarativePixmapCache::get(d->url, &d->pix, d->async) != QDeclarativePixmapReply::Ready)
+ QSize impsize;
+ if (QDeclarativePixmapCache::get(d->url, &d->pix, &impsize, d->async, d->sourcesize.width(), d->sourcesize.height()) != QDeclarativePixmapReply::Ready)
d->status = Error;
- setImplicitWidth(d->pix.width());
- setImplicitHeight(d->pix.height());
+ setImplicitWidth(impsize.width());
+ setImplicitHeight(impsize.height());
if (d->status == Loading)
d->status = Ready;
d->progress = 1.0;
emit statusChanged(d->status);
emit progressChanged(1.0);
+ if (!d->sourcesize.isValid())
+ emit sourceSizeChanged();
pixmapChange();
update();
}
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h
index b215193..6c84456 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p.h
@@ -59,6 +59,8 @@ class Q_DECLARATIVE_EXPORT QDeclarativeImageBase : public QDeclarativeItem
Q_PROPERTY(qreal progress READ progress NOTIFY progressChanged)
Q_PROPERTY(bool asynchronous READ asynchronous WRITE setAsynchronous NOTIFY asynchronousChanged)
+ Q_PROPERTY(QSize sourceSize READ sourceSize WRITE setSourceSize NOTIFY sourceSizeChanged)
+
public:
~QDeclarativeImageBase();
enum Status { Null, Ready, Loading, Error };
@@ -71,8 +73,12 @@ public:
bool asynchronous() const;
void setAsynchronous(bool);
+ void setSourceSize(const QSize&);
+ QSize sourceSize() const;
+
Q_SIGNALS:
void sourceChanged(const QUrl &);
+ void sourceSizeChanged();
void statusChanged(Status);
void progressChanged(qreal progress);
void asynchronousChanged();
diff --git a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
index c4a61f3..de8c93a 100644
--- a/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeimagebase_p_p.h
@@ -78,6 +78,7 @@ public:
QDeclarativeImageBase::Status status;
QUrl url;
qreal progress;
+ QSize sourcesize;
bool pendingPixmapCache : 1;
bool async : 1;
};
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.cpp b/src/declarative/graphicsitems/qdeclarativeitem.cpp
index ccad8f1..05e13a7 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitem.cpp
@@ -83,7 +83,44 @@ QT_BEGIN_NAMESPACE
You can assign any number of Transform elements to an Item. Each Transform is applied in order,
one at a time, to the Item it's assigned to.
- \sa Rotation, Scale
+ \sa Rotation, Scale, Translate
+*/
+
+/*!
+ \qmlclass Translate QGraphicsTranslate
+ \since 4.7
+ \brief The Translate object provides a way to move an Item without changing its x or y properties.
+
+ The Translate object independent control over position in addition to the Item's x and y properties.
+
+ The following example moves the Y axis of the Rectangles while still allowing the Row element
+ to lay the items out as if they had not been transformed:
+ \qml
+ Row {
+ Rectangle {
+ width: 100; height: 100
+ color: "blue"
+ transform: Translate { y: 20 }
+ }
+ Rectangle {
+ width: 100; height: 100
+ color: "red"
+ transform: Translate { y: -20 }
+ }
+ }
+ \endqml
+*/
+
+/*!
+ \qmlproperty real Translate::x
+
+ The translation along the X axis.
+*/
+
+/*!
+ \qmlproperty real Translate::yTranslate
+
+ The translation along the Y axis.
*/
/*!
@@ -312,9 +349,9 @@ void QDeclarativeContents::setItem(QDeclarativeItem *item)
QDeclarativeItem *child = qobject_cast<QDeclarativeItem *>(children.at(i));
if(!child)//### Should this be ignoring non-QDeclarativeItem graphicsobjects?
continue;
- connect(child, SIGNAL(heightChanged(qreal)), this, SLOT(calcHeight()));
+ connect(child, SIGNAL(heightChanged()), this, SLOT(calcHeight()));
connect(child, SIGNAL(yChanged()), this, SLOT(calcHeight()));
- connect(child, SIGNAL(widthChanged(qreal)), this, SLOT(calcWidth()));
+ connect(child, SIGNAL(widthChanged()), this, SLOT(calcWidth()));
connect(child, SIGNAL(xChanged()), this, SLOT(calcWidth()));
connect(this, SIGNAL(rectChanged(QRectF)), m_item, SIGNAL(childrenRectChanged(QRectF)));
}
@@ -1273,16 +1310,6 @@ QDeclarativeKeysAttached *QDeclarativeKeysAttached::qmlAttachedProperties(QObjec
*/
/*!
- \fn void QDeclarativeItem::widthChanged(qreal)
- \internal
-*/
-
-/*!
- \fn void QDeclarativeItem::heightChanged(qreal)
- \internal
-*/
-
-/*!
\fn void QDeclarativeItem::stateChanged(const QString &state)
\internal
*/
@@ -1411,22 +1438,10 @@ QDeclarativeItem::~QDeclarativeItem()
*/
void QDeclarativeItem::setParentItem(QDeclarativeItem *parent)
{
- QDeclarativeItem *oldParent = parentItem();
- if (parent == oldParent || !parent) return;
-
- QObject::setParent(parent);
QGraphicsObject::setParentItem(parent);
}
/*!
- \fn void QDeclarativeItem::setParent(QDeclarativeItem *parent)
- \overload
- Sets both the parent object and parent item to \a parent. This
- function avoids the programming error of calling setParent()
- when you mean setParentItem().
-*/
-
-/*!
Returns the QDeclarativeItem parent of this item.
*/
QDeclarativeItem *QDeclarativeItem::parentItem() const
@@ -1462,11 +1477,6 @@ QDeclarativeItem *QDeclarativeItem::parentItem() const
*/
/*!
- \property QDeclarativeItem::children
- \internal
-*/
-
-/*!
\property QDeclarativeItem::resources
\internal
*/
@@ -1500,11 +1510,20 @@ QDeclarativeAnchors *QDeclarativeItem::anchors()
void QDeclarativeItemPrivate::data_append(QDeclarativeListProperty<QObject> *prop, QObject *o)
{
- QDeclarativeItem *i = qobject_cast<QDeclarativeItem *>(o);
- if (i)
- i->setParentItem(static_cast<QDeclarativeItem *>(prop->object));
- else
- o->setParent(static_cast<QDeclarativeItem *>(prop->object));
+ if (!o)
+ return;
+
+ QDeclarativeItem *that = static_cast<QDeclarativeItem *>(prop->object);
+
+ // This test is measurably (albeit only slightly) faster than qobject_cast<>()
+ const QMetaObject *mo = o->metaObject();
+ while (mo && mo != &QGraphicsObject::staticMetaObject) mo = mo->d.superdata;
+
+ if (mo) {
+ QGraphicsItemPrivate::get(static_cast<QGraphicsObject *>(o))->setParentItemHelper(that, 0, 0);
+ } else {
+ o->setParent(that);
+ }
}
QObject *QDeclarativeItemPrivate::resources_at(QDeclarativeListProperty<QObject> *prop, int index)
@@ -1526,27 +1545,6 @@ int QDeclarativeItemPrivate::resources_count(QDeclarativeListProperty<QObject> *
return prop->object->children().count();
}
-QDeclarativeItem *QDeclarativeItemPrivate::children_at(QDeclarativeListProperty<QDeclarativeItem> *prop, int index)
-{
- QList<QGraphicsItem *> children = static_cast<QDeclarativeItem*>(prop->object)->childItems();
-
- if (index < children.count())
- return qobject_cast<QDeclarativeItem *>(children.at(index));
- else
- return 0;
-}
-
-void QDeclarativeItemPrivate::children_append(QDeclarativeListProperty<QDeclarativeItem> *prop, QDeclarativeItem *i)
-{
- if (i)
- i->setParentItem(static_cast<QDeclarativeItem*>(prop->object));
-}
-
-int QDeclarativeItemPrivate::children_count(QDeclarativeListProperty<QDeclarativeItem> *prop)
-{
- return static_cast<QDeclarativeItem*>(prop->object)->childItems().count();
-}
-
int QDeclarativeItemPrivate::transform_count(QDeclarativeListProperty<QGraphicsTransform> *list)
{
QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object);
@@ -1561,8 +1559,8 @@ int QDeclarativeItemPrivate::transform_count(QDeclarativeListProperty<QGraphicsT
void QDeclarativeItemPrivate::transform_append(QDeclarativeListProperty<QGraphicsTransform> *list, QGraphicsTransform *item)
{
QGraphicsObject *object = qobject_cast<QGraphicsObject *>(list->object);
- if (object)
- QGraphicsItemPrivate::get(object)->appendGraphicsTransform(item);
+ if (object) // QGraphicsItem applies the list in the wrong order, so we prepend.
+ QGraphicsItemPrivate::get(object)->prependGraphicsTransform(item);
}
QGraphicsTransform *QDeclarativeItemPrivate::transform_at(QDeclarativeListProperty<QGraphicsTransform> *list, int idx)
@@ -1589,6 +1587,14 @@ void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphics
}
}
+void QDeclarativeItemPrivate::parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e)
+{
+ QDeclarativeItem *item = static_cast<QDeclarativeItem*>(o);
+ if (e)
+ e->connect(&item->d_func()->parentNotifier);
+ *((QDeclarativeItem **)rv) = item->parentItem();
+}
+
/*!
\qmlproperty list<Object> Item::data
\default
@@ -1602,7 +1608,7 @@ void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphics
Item {
Text {}
Rectangle {}
- Script {}
+ Timer {}
}
\endqml
@@ -1614,7 +1620,7 @@ void QDeclarativeItemPrivate::transform_clear(QDeclarativeListProperty<QGraphics
Rectangle {}
]
resources: [
- Script {}
+ Timer {}
]
}
\endqml
@@ -1645,7 +1651,7 @@ QRectF QDeclarativeItem::childrenRect()
Q_D(QDeclarativeItem);
if (!d->_contents) {
d->_contents = new QDeclarativeContents;
- d->_contents->setParent(this);
+ QDeclarative_setParent_noEvent(d->_contents, this);
d->_contents->setItem(this);
}
return d->_contents->rectF();
@@ -1678,18 +1684,6 @@ void QDeclarativeItem::setClip(bool c)
*/
/*!
- \property QDeclarativeItem::width
-
- Defines the item's width relative to its parent.
- */
-
-/*!
- \property QDeclarativeItem::height
-
- Defines the item's height relative to its parent.
- */
-
-/*!
\qmlproperty real Item::z
Sets the stacking order of the item. By default the stacking order is 0.
@@ -1801,11 +1795,11 @@ void QDeclarativeItem::geometryChanged(const QRectF &newGeometry,
if (newGeometry.x() != oldGeometry.x())
emit xChanged();
if (newGeometry.width() != oldGeometry.width())
- emit widthChanged(newGeometry.width());
+ emit widthChanged();
if (newGeometry.y() != oldGeometry.y())
emit yChanged();
if (newGeometry.height() != oldGeometry.height())
- emit heightChanged(newGeometry.height());
+ emit heightChanged();
for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
const QDeclarativeItemPrivate::ChangeListener &change = d->changeListeners.at(ii);
@@ -2281,14 +2275,6 @@ void QDeclarativeItemPrivate::focusChanged(bool flag)
}
/*! \internal */
-QDeclarativeListProperty<QDeclarativeItem> QDeclarativeItem::fxChildren()
-{
- return QDeclarativeListProperty<QDeclarativeItem>(this, 0, QDeclarativeItemPrivate::children_append,
- QDeclarativeItemPrivate::children_count,
- QDeclarativeItemPrivate::children_at);
-}
-
-/*! \internal */
QDeclarativeListProperty<QObject> QDeclarativeItem::resources()
{
return QDeclarativeListProperty<QObject>(this, 0, QDeclarativeItemPrivate::resources_append,
@@ -2403,13 +2389,11 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeItem::transitions()
example:
\qml
- Script {
- function toggle() {
- if (button.state == 'On')
- button.state = 'Off';
- else
- button.state = 'On';
- }
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
}
\endqml
@@ -2594,14 +2578,11 @@ bool QDeclarativeItem::sceneEvent(QEvent *event)
QVariant QDeclarativeItem::itemChange(GraphicsItemChange change,
const QVariant &value)
{
- Q_D(const QDeclarativeItem);
+ Q_D(QDeclarativeItem);
switch (change) {
case ItemParentHasChanged:
emit parentChanged(parentItem());
- break;
- case ItemChildAddedChange:
- case ItemChildRemovedChange:
- emit childrenChanged();
+ d->parentNotifier.notify();
break;
case ItemVisibleHasChanged: {
for(int ii = 0; ii < d->changeListeners.count(); ++ii) {
@@ -2632,7 +2613,7 @@ QVariant QDeclarativeItem::itemChange(GraphicsItemChange change,
QRectF QDeclarativeItem::boundingRect() const
{
Q_D(const QDeclarativeItem);
- return QRectF(0, 0, d->width, d->height);
+ return QRectF(0, 0, d->mWidth, d->mHeight);
}
/*!
@@ -2717,33 +2698,50 @@ void QDeclarativeItem::setSmooth(bool smooth)
qreal QDeclarativeItem::width() const
{
Q_D(const QDeclarativeItem);
- return d->width;
+ return d->width();
}
void QDeclarativeItem::setWidth(qreal w)
{
Q_D(QDeclarativeItem);
+ d->setWidth(w);
+}
+
+void QDeclarativeItem::resetWidth()
+{
+ Q_D(QDeclarativeItem);
+ d->resetWidth();
+}
+
+qreal QDeclarativeItemPrivate::width() const
+{
+ return mWidth;
+}
+
+void QDeclarativeItemPrivate::setWidth(qreal w)
+{
+ Q_Q(QDeclarativeItem);
if (qIsNaN(w))
return;
- d->widthValid = true;
- if (d->width == w)
+ widthValid = true;
+ if (mWidth == w)
return;
- qreal oldWidth = d->width;
+ qreal oldWidth = mWidth;
- prepareGeometryChange();
- d->width = w;
+ q->prepareGeometryChange();
+ mWidth = w;
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), oldWidth, height()));
+ q->geometryChanged(QRectF(q->x(), q->y(), width(), height()),
+ QRectF(q->x(), q->y(), oldWidth, height()));
}
-void QDeclarativeItem::resetWidth()
+void QDeclarativeItemPrivate ::resetWidth()
{
- Q_D(QDeclarativeItem);
- d->widthValid = false;
- setImplicitWidth(implicitWidth());
+ Q_Q(QDeclarativeItem);
+ widthValid = false;
+ q->setImplicitWidth(q->implicitWidth());
}
/*!
@@ -2763,13 +2761,13 @@ void QDeclarativeItem::setImplicitWidth(qreal w)
{
Q_D(QDeclarativeItem);
d->implicitWidth = w;
- if (d->width == w || widthValid())
+ if (d->mWidth == w || widthValid())
return;
- qreal oldWidth = d->width;
+ qreal oldWidth = d->mWidth;
prepareGeometryChange();
- d->width = w;
+ d->mWidth = w;
geometryChanged(QRectF(x(), y(), width(), height()),
QRectF(x(), y(), oldWidth, height()));
@@ -2787,33 +2785,50 @@ bool QDeclarativeItem::widthValid() const
qreal QDeclarativeItem::height() const
{
Q_D(const QDeclarativeItem);
- return d->height;
+ return d->height();
}
void QDeclarativeItem::setHeight(qreal h)
{
Q_D(QDeclarativeItem);
+ d->setHeight(h);
+}
+
+void QDeclarativeItem::resetHeight()
+{
+ Q_D(QDeclarativeItem);
+ d->resetHeight();
+}
+
+qreal QDeclarativeItemPrivate::height() const
+{
+ return mHeight;
+}
+
+void QDeclarativeItemPrivate::setHeight(qreal h)
+{
+ Q_Q(QDeclarativeItem);
if (qIsNaN(h))
return;
- d->heightValid = true;
- if (d->height == h)
+ heightValid = true;
+ if (mHeight == h)
return;
- qreal oldHeight = d->height;
+ qreal oldHeight = mHeight;
- prepareGeometryChange();
- d->height = h;
+ q->prepareGeometryChange();
+ mHeight = h;
- geometryChanged(QRectF(x(), y(), width(), height()),
- QRectF(x(), y(), width(), oldHeight));
+ q->geometryChanged(QRectF(q->x(), q->y(), width(), height()),
+ QRectF(q->x(), q->y(), width(), oldHeight));
}
-void QDeclarativeItem::resetHeight()
+void QDeclarativeItemPrivate::resetHeight()
{
- Q_D(QDeclarativeItem);
- d->heightValid = false;
- setImplicitHeight(implicitHeight());
+ Q_Q(QDeclarativeItem);
+ heightValid = false;
+ q->setImplicitHeight(q->implicitHeight());
}
/*!
@@ -2833,13 +2848,13 @@ void QDeclarativeItem::setImplicitHeight(qreal h)
{
Q_D(QDeclarativeItem);
d->implicitHeight = h;
- if (d->height == h || heightValid())
+ if (d->mHeight == h || heightValid())
return;
- qreal oldHeight = d->height;
+ qreal oldHeight = d->mHeight;
prepareGeometryChange();
- d->height = h;
+ d->mHeight = h;
geometryChanged(QRectF(x(), y(), width(), height()),
QRectF(x(), y(), width(), oldHeight));
@@ -2861,15 +2876,15 @@ void QDeclarativeItem::setSize(const QSizeF &size)
d->heightValid = true;
d->widthValid = true;
- if (d->height == size.height() && d->width == size.width())
+ if (d->height() == size.height() && d->width() == size.width())
return;
- qreal oldHeight = d->height;
- qreal oldWidth = d->width;
+ qreal oldHeight = d->height();
+ qreal oldWidth = d->width();
prepareGeometryChange();
- d->height = size.height();
- d->width = size.width();
+ d->setHeight(size.height());
+ d->setWidth(size.width());
geometryChanged(QRectF(x(), y(), width(), height()),
QRectF(x(), y(), oldWidth, oldHeight));
diff --git a/src/declarative/graphicsitems/qdeclarativeitem.h b/src/declarative/graphicsitems/qdeclarativeitem.h
index c88b1db..917e480 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem.h
+++ b/src/declarative/graphicsitems/qdeclarativeitem.h
@@ -71,13 +71,10 @@ class Q_DECLARATIVE_EXPORT QDeclarativeItem : public QGraphicsObject, public QDe
Q_PROPERTY(QDeclarativeItem * parent READ parentItem WRITE setParentItem NOTIFY parentChanged DESIGNABLE false FINAL)
Q_PROPERTY(QDeclarativeListProperty<QObject> data READ data DESIGNABLE false)
- Q_PROPERTY(QDeclarativeListProperty<QDeclarativeItem> children READ fxChildren DESIGNABLE false NOTIFY childrenChanged)
Q_PROPERTY(QDeclarativeListProperty<QObject> resources READ resources DESIGNABLE false)
Q_PROPERTY(QDeclarativeListProperty<QDeclarativeState> states READ states DESIGNABLE false)
Q_PROPERTY(QDeclarativeListProperty<QDeclarativeTransition> transitions READ transitions DESIGNABLE false)
Q_PROPERTY(QString state READ state WRITE setState NOTIFY stateChanged)
- Q_PROPERTY(qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
- Q_PROPERTY(qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
Q_PROPERTY(QRectF childrenRect READ childrenRect NOTIFY childrenRectChanged DESIGNABLE false FINAL)
Q_PROPERTY(QDeclarativeAnchors * anchors READ anchors DESIGNABLE false CONSTANT FINAL)
Q_PROPERTY(QDeclarativeAnchorLine left READ left CONSTANT FINAL)
@@ -110,10 +107,8 @@ public:
QDeclarativeItem *parentItem() const;
void setParentItem(QDeclarativeItem *parent);
- void setParent(QDeclarativeItem *parent) { setParentItem(parent); }
QDeclarativeListProperty<QObject> data();
- QDeclarativeListProperty<QDeclarativeItem> fxChildren();
QDeclarativeListProperty<QObject> resources();
QDeclarativeAnchors *anchors();
@@ -173,8 +168,6 @@ public:
QDeclarativeAnchorLine baseline() const;
Q_SIGNALS:
- void widthChanged(qreal);
- void heightChanged(qreal);
void childrenChanged();
void childrenRectChanged(const QRectF &);
void baselineOffsetChanged(qreal);
@@ -235,9 +228,11 @@ QDebug Q_DECLARATIVE_EXPORT operator<<(QDebug debug, QDeclarativeItem *item);
QT_END_NAMESPACE
QML_DECLARE_TYPE(QDeclarativeItem)
+QML_DECLARE_TYPE(QGraphicsObject)
QML_DECLARE_TYPE(QGraphicsTransform)
QML_DECLARE_TYPE(QGraphicsScale)
QML_DECLARE_TYPE(QGraphicsRotation)
+QML_DECLARE_TYPE(QGraphicsWidget)
QML_DECLARE_TYPE(QAction)
QT_END_HEADER
diff --git a/src/declarative/graphicsitems/qdeclarativeitem_p.h b/src/declarative/graphicsitems/qdeclarativeitem_p.h
index cb068da..2607137 100644
--- a/src/declarative/graphicsitems/qdeclarativeitem_p.h
+++ b/src/declarative/graphicsitems/qdeclarativeitem_p.h
@@ -62,6 +62,9 @@
#include <private/qdeclarativestate_p.h>
#include <private/qdeclarativenullablevalue_p_p.h>
+#include <private/qdeclarativenotifier_p.h>
+#include <private/qdeclarativeglobal_p.h>
+
#include <qdeclarative.h>
#include <qdeclarativecontext.h>
@@ -114,7 +117,7 @@ public:
widthValid(false), heightValid(false),
_componentComplete(true), _keepMouse(false),
smooth(false), keyHandler(0),
- width(0), height(0), implicitWidth(0), implicitHeight(0)
+ mWidth(0), mHeight(0), implicitWidth(0), implicitHeight(0)
{
QGraphicsItemPrivate::acceptedMouseButtons = 0;
QGraphicsItemPrivate::flags = QGraphicsItem::GraphicsItemFlags(
@@ -127,15 +130,26 @@ public:
void init(QDeclarativeItem *parent)
{
Q_Q(QDeclarativeItem);
-
- if (parent)
+ if (parent) {
+ QDeclarative_setParent_noEvent(q, parent);
q->setParentItem(parent);
+ }
_baselineOffset.invalidate();
mouseSetsFocus = false;
}
QString _id;
+ // Private Properties
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+
+
// data property
static void data_append(QDeclarativeListProperty<QObject> *, QObject *);
@@ -144,17 +158,16 @@ public:
static void resources_append(QDeclarativeListProperty<QObject> *, QObject *);
static int resources_count(QDeclarativeListProperty<QObject> *);
- // children property
- static QDeclarativeItem *children_at(QDeclarativeListProperty<QDeclarativeItem> *, int);
- static void children_append(QDeclarativeListProperty<QDeclarativeItem> *, QDeclarativeItem *);
- static int children_count(QDeclarativeListProperty<QDeclarativeItem> *);
-
// transform property
static int transform_count(QDeclarativeListProperty<QGraphicsTransform> *list);
static void transform_append(QDeclarativeListProperty<QGraphicsTransform> *list, QGraphicsTransform *);
static QGraphicsTransform *transform_at(QDeclarativeListProperty<QGraphicsTransform> *list, int);
static void transform_clear(QDeclarativeListProperty<QGraphicsTransform> *list);
+ // Accelerated property accessors
+ QDeclarativeNotifier parentNotifier;
+ static void parentProperty(QObject *o, void *rv, QDeclarativeNotifierEndpoint *e);
+
QDeclarativeAnchors *anchors() {
if (!_anchors) {
Q_Q(QDeclarativeItem);
@@ -222,8 +235,8 @@ public:
QDeclarativeItemKeyFilter *keyHandler;
- qreal width;
- qreal height;
+ qreal mWidth;
+ qreal mHeight;
qreal implicitWidth;
qreal implicitHeight;
@@ -232,9 +245,9 @@ public:
virtual void setPosHelper(const QPointF &pos)
{
Q_Q(QDeclarativeItem);
- QRectF oldGeometry(this->pos.x(), this->pos.y(), width, height);
+ QRectF oldGeometry(this->pos.x(), this->pos.y(), mWidth, mHeight);
QGraphicsItemPrivate::setPosHelper(pos);
- q->geometryChanged(QRectF(this->pos.x(), this->pos.y(), width, height), oldGeometry);
+ q->geometryChanged(QRectF(this->pos.x(), this->pos.y(), mWidth, mHeight), oldGeometry);
}
// Reimplemented from QGraphicsItemPrivate
diff --git a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
index 1a48cbd..7bc74ce 100644
--- a/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeitemsmodule.cpp
@@ -69,6 +69,7 @@
#include "qdeclarativepathview_p.h"
#include "qdeclarativerectangle_p.h"
#include "qdeclarativerepeater_p.h"
+#include "qdeclarativetranslate_p.h"
#include "qdeclarativetext_p.h"
#include "qdeclarativetextedit_p.h"
#include "qdeclarativetextinput_p.h"
@@ -114,16 +115,16 @@ void QDeclarativeItemModule::defineModule()
qmlRegisterType<QDeclarativePathPercent>("Qt",4,6,"PathPercent");
qmlRegisterType<QDeclarativePathQuad>("Qt",4,6,"PathQuad");
qmlRegisterType<QDeclarativePathView>("Qt",4,6,"PathView");
- qmlRegisterType<QDeclarativePen>("Qt",4,6,"Pen");
- qmlRegisterType<QIntValidator>("Qt",4,6,"QIntValidator");
+ qmlRegisterType<QIntValidator>("Qt",4,6,"IntValidator");
#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
- qmlRegisterType<QDoubleValidator>("Qt",4,7,"QDoubleValidator");
- qmlRegisterType<QRegExpValidator>("Qt",4,7,"QRegExpValidator");
+ qmlRegisterType<QDoubleValidator>("Qt",4,7,"DoubleValidator");
+ qmlRegisterType<QRegExpValidator>("Qt",4,7,"RegExpValidator");
#endif
qmlRegisterType<QDeclarativeRectangle>("Qt",4,6,"Rectangle");
qmlRegisterType<QDeclarativeRepeater>("Qt",4,6,"Repeater");
qmlRegisterType<QGraphicsRotation>("Qt",4,6,"Rotation");
qmlRegisterType<QDeclarativeRow>("Qt",4,6,"Row");
+ qmlRegisterType<QDeclarativeTranslate>("Qt",4,6,"Translate");
qmlRegisterType<QGraphicsScale>("Qt",4,6,"Scale");
qmlRegisterType<QDeclarativeText>("Qt",4,6,"Text");
qmlRegisterType<QDeclarativeTextEdit>("Qt",4,6,"TextEdit");
@@ -146,6 +147,7 @@ void QDeclarativeItemModule::defineModule()
qmlRegisterType<QValidator>();
qmlRegisterType<QDeclarativeVisualModel>();
qmlRegisterType<QAction>();
+ qmlRegisterType<QDeclarativePen>();
#ifdef QT_WEBKIT_LIB
qmlRegisterType<QDeclarativeWebSettings>();
#endif
diff --git a/src/declarative/graphicsitems/qdeclarativelistview.cpp b/src/declarative/graphicsitems/qdeclarativelistview.cpp
index 320a2f0..cbf8eac 100644
--- a/src/declarative/graphicsitems/qdeclarativelistview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativelistview.cpp
@@ -44,7 +44,7 @@
#include "qdeclarativeflickable_p_p.h"
#include "qdeclarativevisualitemmodel_p.h"
-#include <qdeclarativeeasefollow_p.h>
+#include "qdeclarativesmoothedanimation_p_p.h"
#include <qdeclarativeexpression.h>
#include <qdeclarativeengine.h>
#include <qdeclarativeguard_p.h>
@@ -455,8 +455,8 @@ public:
enum MovementReason { Other, SetIndex, Mouse };
MovementReason moveReason;
int buffer;
- QDeclarativeEaseFollow *highlightPosAnimator;
- QDeclarativeEaseFollow *highlightSizeAnimator;
+ QSmoothedAnimation *highlightPosAnimator;
+ QSmoothedAnimation *highlightSizeAnimator;
QDeclarativeViewSection *sectionCriteria;
QString currentSection;
static const int sectionCacheSize = 3;
@@ -541,7 +541,7 @@ FxListItem *QDeclarativeListViewPrivate::createItem(int modelIndex)
listItem->item->setZValue(1);
// complete
model->completeItem();
- listItem->item->setParent(q->viewport());
+ listItem->item->setParentItem(q->viewport());
QDeclarativeItemPrivate *itemPrivate = static_cast<QDeclarativeItemPrivate*>(QGraphicsItemPrivate::get(item));
itemPrivate->addItemChangeListener(this, QDeclarativeItemPrivate::Geometry);
if (sectionCriteria && sectionCriteria->delegate()) {
@@ -562,7 +562,7 @@ void QDeclarativeListViewPrivate::releaseItem(FxListItem *item)
return;
if (trackedItem == item) {
const char *notifier1 = orient == QDeclarativeListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
- const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged(qreal)) : SIGNAL(widthChanged(qreal));
+ const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
QObject::disconnect(trackedItem->item, notifier2, q, SLOT(trackedPositionChanged()));
trackedItem = 0;
@@ -763,7 +763,7 @@ void QDeclarativeListViewPrivate::updateTrackedItem()
FxListItem *oldTracked = trackedItem;
const char *notifier1 = orient == QDeclarativeListView::Vertical ? SIGNAL(yChanged()) : SIGNAL(xChanged());
- const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged(qreal)) : SIGNAL(widthChanged(qreal));
+ const char *notifier2 = orient == QDeclarativeListView::Vertical ? SIGNAL(heightChanged()) : SIGNAL(widthChanged());
if (trackedItem && item != trackedItem) {
QObject::disconnect(trackedItem->item, notifier1, q, SLOT(trackedPositionChanged()));
@@ -803,7 +803,7 @@ void QDeclarativeListViewPrivate::createHighlight()
QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
QObject *nobj = highlightComponent->create(highlightContext);
if (nobj) {
- highlightContext->setParent(nobj);
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
item = qobject_cast<QDeclarativeItem *>(nobj);
if (!item)
delete nobj;
@@ -814,7 +814,8 @@ void QDeclarativeListViewPrivate::createHighlight()
item = new QDeclarativeItem;
}
if (item) {
- item->setParent(q->viewport());
+ QDeclarative_setParent_noEvent(item, q->viewport());
+ item->setParentItem(q->viewport());
highlight = new FxListItem(item, q);
if (currentItem && autoHighlight) {
if (orient == QDeclarativeListView::Vertical) {
@@ -824,15 +825,15 @@ void QDeclarativeListViewPrivate::createHighlight()
}
}
const QLatin1String posProp(orient == QDeclarativeListView::Vertical ? "y" : "x");
- highlightPosAnimator = new QDeclarativeEaseFollow(q);
- highlightPosAnimator->setTarget(QDeclarativeProperty(highlight->item, posProp));
- highlightPosAnimator->setVelocity(highlightMoveSpeed);
- highlightPosAnimator->setEnabled(autoHighlight);
+ highlightPosAnimator = new QSmoothedAnimation(q);
+ highlightPosAnimator->target = QDeclarativeProperty(highlight->item, posProp);
+ highlightPosAnimator->velocity = highlightMoveSpeed;
+ highlightPosAnimator->restart();
const QLatin1String sizeProp(orient == QDeclarativeListView::Vertical ? "height" : "width");
- highlightSizeAnimator = new QDeclarativeEaseFollow(q);
- highlightSizeAnimator->setVelocity(highlightResizeSpeed);
- highlightSizeAnimator->setTarget(QDeclarativeProperty(highlight->item, sizeProp));
- highlightSizeAnimator->setEnabled(autoHighlight);
+ highlightSizeAnimator = new QSmoothedAnimation(q);
+ highlightSizeAnimator->velocity = highlightResizeSpeed;
+ highlightSizeAnimator->target = QDeclarativeProperty(highlight->item, sizeProp);
+ highlightSizeAnimator->restart();
changed = true;
}
}
@@ -846,8 +847,8 @@ void QDeclarativeListViewPrivate::updateHighlight()
createHighlight();
if (currentItem && autoHighlight && highlight && !moving) {
// auto-update highlight
- highlightPosAnimator->setSourceValue(currentItem->position());
- highlightSizeAnimator->setSourceValue(currentItem->size());
+ highlightPosAnimator->to = currentItem->position();
+ highlightSizeAnimator->to = currentItem->size();
if (orient == QDeclarativeListView::Vertical) {
if (highlight->item->width() == 0)
highlight->item->setWidth(currentItem->item->width());
@@ -855,6 +856,8 @@ void QDeclarativeListViewPrivate::updateHighlight()
if (highlight->item->height() == 0)
highlight->item->setHeight(currentItem->item->height());
}
+ highlightPosAnimator->restart();
+ highlightSizeAnimator->restart();
}
updateTrackedItem();
}
@@ -880,13 +883,14 @@ void QDeclarativeListViewPrivate::createSection(FxListItem *listItem)
context->setContextProperty(QLatin1String("section"), listItem->attached->m_section);
QObject *nobj = sectionCriteria->delegate()->create(context);
if (nobj) {
- context->setParent(nobj);
+ QDeclarative_setParent_noEvent(context, nobj);
listItem->section = qobject_cast<QDeclarativeItem *>(nobj);
if (!listItem->section) {
delete nobj;
} else {
listItem->section->setZValue(1);
- listItem->section->setParent(q->viewport());
+ QDeclarative_setParent_noEvent(listItem->section, q->viewport());
+ listItem->section->setParentItem(q->viewport());
}
} else {
delete context;
@@ -1002,7 +1006,7 @@ void QDeclarativeListViewPrivate::updateFooter()
QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
QObject *nobj = footerComponent->create(context);
if (nobj) {
- context->setParent(nobj);
+ QDeclarative_setParent_noEvent(context, nobj);
item = qobject_cast<QDeclarativeItem *>(nobj);
if (!item)
delete nobj;
@@ -1010,7 +1014,8 @@ void QDeclarativeListViewPrivate::updateFooter()
delete context;
}
if (item) {
- item->setParent(q->viewport());
+ QDeclarative_setParent_noEvent(item, q->viewport());
+ item->setParentItem(q->viewport());
item->setZValue(1);
footer = new FxListItem(item, q);
}
@@ -1039,7 +1044,7 @@ void QDeclarativeListViewPrivate::updateHeader()
QDeclarativeContext *context = new QDeclarativeContext(qmlContext(q));
QObject *nobj = headerComponent->create(context);
if (nobj) {
- context->setParent(nobj);
+ QDeclarative_setParent_noEvent(context, nobj);
item = qobject_cast<QDeclarativeItem *>(nobj);
if (!item)
delete nobj;
@@ -1047,7 +1052,8 @@ void QDeclarativeListViewPrivate::updateHeader()
delete context;
}
if (item) {
- item->setParent(q->viewport());
+ QDeclarative_setParent_noEvent(item, q->viewport());
+ item->setParentItem(q->viewport());
item->setZValue(1);
header = new FxListItem(item, q);
if (visibleItems.isEmpty())
@@ -1600,10 +1606,6 @@ void QDeclarativeListView::setHighlightFollowsCurrentItem(bool autoHighlight)
Q_D(QDeclarativeListView);
if (d->autoHighlight != autoHighlight) {
d->autoHighlight = autoHighlight;
- if (d->highlightPosAnimator) {
- d->highlightPosAnimator->setEnabled(d->autoHighlight);
- d->highlightSizeAnimator->setEnabled(d->autoHighlight);
- }
d->updateHighlight();
emit highlightFollowsCurrentItemChanged();
}
@@ -1863,7 +1865,7 @@ void QDeclarativeListView::setHighlightMoveSpeed(qreal speed)
if (d->highlightMoveSpeed != speed) {
d->highlightMoveSpeed = speed;
if (d->highlightPosAnimator)
- d->highlightPosAnimator->setVelocity(d->highlightMoveSpeed);
+ d->highlightPosAnimator->velocity = d->highlightMoveSpeed;
emit highlightMoveSpeedChanged();
}
}
@@ -1880,7 +1882,7 @@ void QDeclarativeListView::setHighlightResizeSpeed(qreal speed)
if (d->highlightResizeSpeed != speed) {
d->highlightResizeSpeed = speed;
if (d->highlightSizeAnimator)
- d->highlightSizeAnimator->setVelocity(d->highlightResizeSpeed);
+ d->highlightSizeAnimator->velocity = d->highlightResizeSpeed;
emit highlightResizeSpeedChanged();
}
}
@@ -2124,9 +2126,6 @@ qreal QDeclarativeListView::maxXExtent() const
void QDeclarativeListView::keyPressEvent(QKeyEvent *event)
{
Q_D(QDeclarativeListView);
- QDeclarativeFlickable::keyPressEvent(event);
- if (event->isAccepted())
- return;
if (d->model && d->model->count() && d->interactive) {
if ((d->orient == QDeclarativeListView::Horizontal && event->key() == Qt::Key_Left)
@@ -2151,6 +2150,9 @@ void QDeclarativeListView::keyPressEvent(QKeyEvent *event)
}
}
}
+ QDeclarativeFlickable::keyPressEvent(event);
+ if (event->isAccepted())
+ return;
event->ignore();
}
diff --git a/src/declarative/graphicsitems/qdeclarativeloader.cpp b/src/declarative/graphicsitems/qdeclarativeloader.cpp
index 0d62afa..2f1511e 100644
--- a/src/declarative/graphicsitems/qdeclarativeloader.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeloader.cpp
@@ -301,12 +301,8 @@ void QDeclarativeLoaderPrivate::_q_sourceLoaded()
item = qobject_cast<QGraphicsObject *>(obj);
if (item) {
QDeclarative_setParent_noEvent(ctxt, obj);
- if (QDeclarativeItem* qmlItem = qobject_cast<QDeclarativeItem *>(item)) {
- qmlItem->setParentItem(q);
- } else {
- item->setParentItem(q);
- item->setParent(q);
- }
+ QDeclarative_setParent_noEvent(item, q);
+ item->setParentItem(q);
// item->setFocus(true);
initResize();
} else {
diff --git a/src/declarative/graphicsitems/qdeclarativemousearea.cpp b/src/declarative/graphicsitems/qdeclarativemousearea.cpp
index 26242bc..dde3366 100644
--- a/src/declarative/graphicsitems/qdeclarativemousearea.cpp
+++ b/src/declarative/graphicsitems/qdeclarativemousearea.cpp
@@ -639,7 +639,6 @@ bool QDeclarativeMouseArea::setPressed(bool p)
d->pressed = p;
QDeclarativeMouseEvent me(d->lastPos.x(), d->lastPos.y(), d->lastButton, d->lastButtons, d->lastModifiers, isclick, d->longPress);
if (d->pressed) {
- emit positionChanged(&me);
emit pressed(&me);
} else {
emit released(&me);
diff --git a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp
index 28a93d2..ab6007a 100644
--- a/src/declarative/graphicsitems/qdeclarativepainteditem.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepainteditem.cpp
@@ -211,8 +211,8 @@ QDeclarativePaintedItem::~QDeclarativePaintedItem()
*/
void QDeclarativePaintedItem::init()
{
- connect(this,SIGNAL(widthChanged(qreal)),this,SLOT(clearCache()));
- connect(this,SIGNAL(heightChanged(qreal)),this,SLOT(clearCache()));
+ connect(this,SIGNAL(widthChanged()),this,SLOT(clearCache()));
+ connect(this,SIGNAL(heightChanged()),this,SLOT(clearCache()));
connect(this,SIGNAL(visibleChanged()),this,SLOT(clearCache()));
}
diff --git a/src/declarative/graphicsitems/qdeclarativepathview.cpp b/src/declarative/graphicsitems/qdeclarativepathview.cpp
index b9c8971..71f85ae 100644
--- a/src/declarative/graphicsitems/qdeclarativepathview.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepathview.cpp
@@ -138,6 +138,167 @@ void QDeclarativePathViewPrivate::clear()
items.clear();
}
+void QDeclarativePathViewPrivate::updateMappedRange()
+{
+ if (model && pathItems != -1 && pathItems < model->count())
+ mappedRange = qreal(pathItems)/model->count();
+ else
+ mappedRange = 1.0;
+}
+
+qreal QDeclarativePathViewPrivate::positionOfIndex(qreal index) const
+{
+ qreal pos = -1.0;
+
+ if (model && index >= 0 && index < model->count()) {
+ qreal start = 0.0;
+ if (haveHighlightRange && highlightRangeMode != QDeclarativePathView::NoHighlightRange)
+ start = highlightRangeStart;
+ qreal globalPos = index + offset;
+ globalPos = qmlMod(globalPos, qreal(model->count())) / model->count();
+ if (pathItems != -1 && pathItems < model->count()) {
+ globalPos += start * mappedRange;
+ globalPos = qmlMod(globalPos, 1.0);
+ if (globalPos < mappedRange)
+ pos = globalPos / mappedRange;
+ } else {
+ pos = qmlMod(globalPos + start, 1.0);
+ }
+ }
+
+ return pos;
+}
+
+void QDeclarativePathViewPrivate::createHighlight()
+{
+ Q_Q(QDeclarativePathView);
+ if (!q->isComponentComplete())
+ return;
+
+ bool changed = false;
+ if (highlightItem) {
+ delete highlightItem;
+ highlightItem = 0;
+ changed = true;
+ }
+
+ QDeclarativeItem *item = 0;
+ if (highlightComponent) {
+ QDeclarativeContext *highlightContext = new QDeclarativeContext(qmlContext(q));
+ QObject *nobj = highlightComponent->create(highlightContext);
+ if (nobj) {
+ QDeclarative_setParent_noEvent(highlightContext, nobj);
+ item = qobject_cast<QDeclarativeItem *>(nobj);
+ if (!item)
+ delete nobj;
+ } else {
+ delete highlightContext;
+ }
+ } else {
+ item = new QDeclarativeItem;
+ }
+ if (item) {
+ QDeclarative_setParent_noEvent(item, q);
+ item->setParentItem(q);
+ highlightItem = item;
+ changed = true;
+ }
+ if (changed)
+ emit q->highlightItemChanged();
+}
+
+void QDeclarativePathViewPrivate::updateHighlight()
+{
+ Q_Q(QDeclarativePathView);
+ if (!q->isComponentComplete() || !isValid())
+ return;
+ if (highlightItem) {
+ if (haveHighlightRange && highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) {
+ updateItem(highlightItem, highlightRangeStart);
+ } else {
+ qreal target = currentIndex;
+
+ tl.reset(moveHighlight);
+ moveHighlight.setValue(highlightPosition);
+
+ const int duration = 300;
+
+ if (target - highlightPosition > model->count()/2) {
+ highlightUp = false;
+ qreal distance = model->count() - target + highlightPosition;
+ tl.move(moveHighlight, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * highlightPosition / distance));
+ tl.set(moveHighlight, model->count()-0.01);
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * (model->count()-target) / distance));
+ } else if (target - highlightPosition <= -model->count()/2) {
+ highlightUp = true;
+ qreal distance = model->count() - highlightPosition + target;
+ tl.move(moveHighlight, model->count()-0.01, QEasingCurve(QEasingCurve::InQuad), int(duration * (model->count()-highlightPosition) / distance));
+ tl.set(moveHighlight, 0.0);
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::OutQuad), int(duration * target / distance));
+ } else {
+ highlightUp = highlightPosition - target < 0;
+ tl.move(moveHighlight, target, QEasingCurve(QEasingCurve::InOutQuad), duration);
+ }
+ }
+ }
+}
+
+void QDeclarativePathViewPrivate::setHighlightPosition(qreal pos)
+{
+ if (pos != highlightPosition) {
+ qreal start = 0.0;
+ qreal end = 1.0;
+ if (haveHighlightRange && highlightRangeMode != QDeclarativePathView::NoHighlightRange) {
+ start = highlightRangeStart;
+ end = highlightRangeEnd;
+ }
+
+ qreal range = qreal(model->count());
+ // calc normalized position of highlight relative to offset
+ qreal relativeHighlight = qmlMod(pos + offset, range) / range;
+
+ if (!highlightUp && relativeHighlight > end * mappedRange) {
+ qreal diff = 1.0 - relativeHighlight;
+ setOffset(offset + diff * range);
+ } else if (highlightUp && relativeHighlight >= (end - start) * mappedRange) {
+ qreal diff = relativeHighlight - (end - start) * mappedRange;
+ setOffset(offset - diff * range - 0.00001);
+ }
+
+ highlightPosition = pos;
+ qreal pathPos = positionOfIndex(pos);
+ updateItem(highlightItem, pathPos);
+ if (QDeclarativePathViewAttached *att = attached(highlightItem))
+ att->setOnPath(pathPos != -1.0);
+ }
+}
+
+void QDeclarativePathViewPrivate::updateItem(QDeclarativeItem *item, qreal percent)
+{
+ if (QDeclarativePathViewAttached *att = attached(item)) {
+ foreach(const QString &attr, path->attributes())
+ att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
+ }
+ QPointF pf = path->pointAt(percent);
+ item->setX(pf.x() - item->width()*item->scale()/2);
+ item->setY(pf.y() - item->height()*item->scale()/2);
+}
+
+void QDeclarativePathViewPrivate::regenerate()
+{
+ Q_Q(QDeclarativePathView);
+ if (!q->isComponentComplete())
+ return;
+
+ clear();
+
+ if (!isValid())
+ return;
+
+ firstIndex = -1;
+ updateMappedRange();
+ q->refill();
+}
/*!
\qmlclass PathView QDeclarativePathView
@@ -232,6 +393,7 @@ void QDeclarativePathView::setModel(const QVariant &model)
if (d->model) {
disconnect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
disconnect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ disconnect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
disconnect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
disconnect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
for (int i=0; i<d->items.count(); i++){
@@ -261,13 +423,16 @@ void QDeclarativePathView::setModel(const QVariant &model)
if (d->model) {
connect(d->model, SIGNAL(itemsInserted(int,int)), this, SLOT(itemsInserted(int,int)));
connect(d->model, SIGNAL(itemsRemoved(int,int)), this, SLOT(itemsRemoved(int,int)));
+ connect(d->model, SIGNAL(itemsMoved(int,int,int)), this, SLOT(itemsMoved(int,int,int)));
connect(d->model, SIGNAL(modelReset()), this, SLOT(modelReset()));
connect(d->model, SIGNAL(createdItem(int, QDeclarativeItem*)), this, SLOT(createdItem(int,QDeclarativeItem*)));
}
- d->firstIndex = 0;
- d->pathOffset = 0;
+ d->offset = qmlMod(d->offset, qreal(d->model->count()));
+ if (d->offset < 0)
+ d->offset = d->model->count() + d->offset;
d->regenerate();
d->fixOffset();
+ emit countChanged();
emit modelChanged();
}
@@ -330,22 +495,27 @@ void QDeclarativePathView::setCurrentIndex(int idx)
if (d->model->count()) {
int itemIndex = (d->currentIndex - d->firstIndex + d->model->count()) % d->model->count();
if (itemIndex < d->items.count()) {
- if (QDeclarativeItem *item = d->items.at(d->currentIndex)) {
+ if (QDeclarativeItem *item = d->items.at(itemIndex)) {
if (QDeclarativePathViewAttached *att = d->attached(item))
att->setIsCurrentItem(false);
}
}
}
+ d->currentItem = 0;
+ d->moveReason = QDeclarativePathViewPrivate::SetIndex;
d->currentIndex = idx;
if (d->model->count()) {
- d->snapToCurrent();
+ if (d->haveHighlightRange && d->highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange)
+ d->snapToCurrent();
int itemIndex = (idx - d->firstIndex + d->model->count()) % d->model->count();
if (itemIndex < d->items.count()) {
- QDeclarativeItem *item = d->items.at(itemIndex);
- item->setFocus(true);
- if (QDeclarativePathViewAttached *att = d->attached(item))
+ d->currentItem = d->items.at(itemIndex);
+ d->currentItem->setFocus(true);
+ if (QDeclarativePathViewAttached *att = d->attached(d->currentItem))
att->setIsCurrentItem(true);
}
+ d->currentItemOffset = d->positionOfIndex(d->currentIndex);
+ d->updateHighlight();
}
emit currentIndexChanged();
}
@@ -354,12 +524,13 @@ void QDeclarativePathView::setCurrentIndex(int idx)
/*!
\qmlproperty real PathView::offset
- The offset specifies how far along the path (0.0-1.0) the items are from their initial positions.
+ The offset specifies how far along the path the items are from their initial positions.
+ This is a real number that ranges from 0.0 to the count of items in the model.
*/
qreal QDeclarativePathView::offset() const
{
Q_D(const QDeclarativePathView);
- return d->_offset;
+ return d->offset;
}
void QDeclarativePathView::setOffset(qreal offset)
@@ -372,34 +543,152 @@ void QDeclarativePathView::setOffset(qreal offset)
void QDeclarativePathViewPrivate::setOffset(qreal o)
{
Q_Q(QDeclarativePathView);
- if (_offset != o) {
- _offset = qmlMod(o, qreal(1.0));
- if (_offset < 0)
- _offset = 1.0 + _offset;
- q->refill();
+ if (offset != o) {
+ if (isValid() && q->isComponentComplete()) {
+ offset = qmlMod(o, qreal(model->count()));
+ if (offset < 0)
+ offset += qreal(model->count());
+ q->refill();
+ } else {
+ offset = o;
+ }
+ emit q->offsetChanged();
}
}
/*!
- \qmlproperty real PathView::snapPosition
+ \qmlproperty component PathView::highlight
+ This property holds the component to use as the highlight.
+
+ An instance of the highlight component will be created for each view.
+ The geometry of the resultant component instance will be managed by the view
+ so as to stay with the current item.
+
+ The below example demonstrates how to make a simple highlight. Note the use
+ of the PathView.onPath property to ensure that the highlight is hidden
+ when flicked off of the path.
- This property determines the position (0.0-1.0) the nearest item will snap to.
+ \code
+ Component {
+ Rectangle {
+ visible: PathView.onPath
+ ...
+ }
+ }
+ \endcode
+
+ \sa highlightItem, highlightRangeMode
*/
-qreal QDeclarativePathView::snapPosition() const
+
+QDeclarativeComponent *QDeclarativePathView::highlight() const
{
Q_D(const QDeclarativePathView);
- return d->snapPos;
+ return d->highlightComponent;
}
-void QDeclarativePathView::setSnapPosition(qreal pos)
+void QDeclarativePathView::setHighlight(QDeclarativeComponent *highlight)
{
Q_D(QDeclarativePathView);
- qreal normalizedPos = pos - int(pos);
- if (qFuzzyCompare(normalizedPos, d->snapPos))
+ if (highlight != d->highlightComponent) {
+ d->highlightComponent = highlight;
+ d->createHighlight();
+ d->updateHighlight();
+ emit highlightChanged();
+ }
+}
+
+/*!
+ \qmlproperty Item PathView::highlightItem
+
+ \c highlightItem holds the highlight item, which was created
+ from the \l highlight component.
+
+ \sa highlight
+*/
+QDeclarativeItem *QDeclarativePathView::highlightItem()
+{
+ Q_D(const QDeclarativePathView);
+ return d->highlightItem;
+}
+/*!
+ \qmlproperty real PathView::preferredHighlightBegin
+ \qmlproperty real PathView::preferredHighlightEnd
+ \qmlproperty enumeration PathView::highlightRangeMode
+
+ These properties set the preferred range of the highlight (current item)
+ within the view. The preferred values must be in the range 0.0-1.0.
+
+ If highlightRangeMode is set to \e ApplyRange the view will
+ attempt to maintain the highlight within the range, however
+ the highlight can move outside of the range at the ends of the path
+ or due to a mouse interaction.
+
+ If highlightRangeMode is set to \e StrictlyEnforceRange the highlight will never
+ move outside of the range. This means that the current item will change
+ if a keyboard or mouse action would cause the highlight to move
+ outside of the range.
+
+ Note that this is the correct way to influence where the
+ current item ends up when the view moves. For example, if you want the
+ currently selected item to be in the middle of the path, then set the
+ highlight range to be 0.5,0.5 and highlightRangeMode to StrictlyEnforceRange.
+ Then, when the path scrolls,
+ the currently selected item will be the item at that position. This also applies to
+ when the currently selected item changes - it will scroll to within the preferred
+ highlight range. Furthermore, the behaviour of the current item index will occur
+ whether or not a highlight exists.
+
+ The default value is \e StrictlyEnforceRange.
+
+ Note that a valid range requires preferredHighlightEnd to be greater
+ than or equal to preferredHighlightBegin.
+*/
+qreal QDeclarativePathView::preferredHighlightBegin() const
+{
+ Q_D(const QDeclarativePathView);
+ return d->highlightRangeStart;
+}
+
+void QDeclarativePathView::setPreferredHighlightBegin(qreal start)
+{
+ Q_D(QDeclarativePathView);
+ if (d->highlightRangeStart == start || start < 0 || start > 1.0)
return;
- d->snapPos = normalizedPos;
- d->fixOffset();
- emit snapPositionChanged();
+ d->highlightRangeStart = start;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightBeginChanged();
+}
+
+qreal QDeclarativePathView::preferredHighlightEnd() const
+{
+ Q_D(const QDeclarativePathView);
+ return d->highlightRangeEnd;
+}
+
+void QDeclarativePathView::setPreferredHighlightEnd(qreal end)
+{
+ Q_D(QDeclarativePathView);
+ if (d->highlightRangeEnd == end || end < 0 || end > 1.0)
+ return;
+ d->highlightRangeEnd = end;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit preferredHighlightEndChanged();
+}
+
+QDeclarativePathView::HighlightRangeMode QDeclarativePathView::highlightRangeMode() const
+{
+ Q_D(const QDeclarativePathView);
+ return d->highlightRangeMode;
+}
+
+void QDeclarativePathView::setHighlightRangeMode(HighlightRangeMode mode)
+{
+ Q_D(QDeclarativePathView);
+ if (d->highlightRangeMode == mode)
+ return;
+ d->highlightRangeMode = mode;
+ d->haveHighlightRange = d->highlightRangeMode != NoHighlightRange && d->highlightRangeStart <= d->highlightRangeEnd;
+ emit highlightRangeModeChanged();
}
/*!
@@ -426,6 +715,52 @@ void QDeclarativePathView::setDragMargin(qreal dragMargin)
}
/*!
+ \qmlproperty real PathView::flickDeceleration
+ This property holds the rate at which a flick will decelerate.
+
+ The default is 100.
+*/
+qreal QDeclarativePathView::flickDeceleration() const
+{
+ Q_D(const QDeclarativePathView);
+ return d->deceleration;
+}
+
+void QDeclarativePathView::setFlickDeceleration(qreal dec)
+{
+ Q_D(QDeclarativePathView);
+ if (d->deceleration == dec)
+ return;
+ d->deceleration = dec;
+ emit flickDecelerationChanged();
+}
+
+/*!
+ \qmlproperty bool PathView::interactive
+
+ A user cannot drag or flick a PathView that is not interactive.
+
+ This property is useful for temporarily disabling flicking. This allows
+ special interaction with PathView's children.
+*/
+bool QDeclarativePathView::isInteractive() const
+{
+ Q_D(const QDeclarativePathView);
+ return d->interactive;
+}
+
+void QDeclarativePathView::setInteractive(bool interactive)
+{
+ Q_D(QDeclarativePathView);
+ if (interactive != d->interactive) {
+ d->interactive = interactive;
+ if (!interactive)
+ d->tl.clear();
+ emit interactiveChanged();
+ }
+}
+
+/*!
\qmlproperty component PathView::delegate
The delegate provides a template defining each item instantiated by the view.
@@ -467,7 +802,7 @@ void QDeclarativePathView::setDelegate(QDeclarativeComponent *delegate)
/*!
\qmlproperty int PathView::pathItemCount
- This property holds the number of items visible on the path at any one time
+ This property holds the number of items visible on the path at any one time.
*/
int QDeclarativePathView::pathItemCount() const
{
@@ -480,9 +815,13 @@ void QDeclarativePathView::setPathItemCount(int i)
Q_D(QDeclarativePathView);
if (i == d->pathItems)
return;
+ if (i < 1)
+ i = 1;
d->pathItems = i;
- d->regenerate();
- pathItemCountChanged();
+ if (d->isValid() && isComponentComplete()) {
+ d->regenerate();
+ }
+ emit pathItemCountChanged();
}
QPointF QDeclarativePathViewPrivate::pointNear(const QPointF &point, qreal *nearPercent) const
@@ -512,7 +851,7 @@ QPointF QDeclarativePathViewPrivate::pointNear(const QPointF &point, qreal *near
void QDeclarativePathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarativePathView);
- if (!d->items.count())
+ if (!d->interactive || !d->items.count())
return;
QPointF scenePoint = mapToScene(event->pos());
int idx = 0;
@@ -542,7 +881,7 @@ void QDeclarativePathView::mousePressEvent(QGraphicsSceneMouseEvent *event)
void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{
Q_D(QDeclarativePathView);
- if (d->lastPosTime.isNull())
+ if (!d->interactive || d->lastPosTime.isNull())
return;
if (!d->stealMouse) {
@@ -555,14 +894,14 @@ void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
d->moveReason = QDeclarativePathViewPrivate::Mouse;
qreal newPc;
d->pointNear(event->pos(), &newPc);
- qreal diff = newPc - d->startPc;
+ qreal diff = (newPc - d->startPc)*d->model->count()*d->mappedRange;
if (diff) {
- setOffset(d->_offset + diff);
+ setOffset(d->offset + diff);
- if (diff > 0.5)
- diff -= 1.0;
- else if (diff < -0.5)
- diff += 1.0;
+ if (diff > d->model->count()/2)
+ diff -= d->model->count();
+ else if (diff < -d->model->count()/2)
+ diff += d->model->count();
d->lastElapsed = QDeclarativeItemPrivate::restart(d->lastPosTime);
d->lastDist = diff;
@@ -574,27 +913,39 @@ void QDeclarativePathView::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
void QDeclarativePathView::mouseReleaseEvent(QGraphicsSceneMouseEvent *)
{
Q_D(QDeclarativePathView);
- if (d->lastPosTime.isNull())
+ d->stealMouse = false;
+ setKeepMouseGrab(false);
+ if (!d->interactive || d->lastPosTime.isNull())
return;
qreal elapsed = qreal(d->lastElapsed + QDeclarativeItemPrivate::elapsed(d->lastPosTime)) / 1000.;
qreal velocity = elapsed > 0. ? d->lastDist / elapsed : 0;
- if (d->model && d->model->count() && qAbs(velocity) > 0.05) {
- if (velocity > 1.5)
- velocity = 1.5;
- else if (velocity < -1.5)
- velocity = -1.5;
- qreal inc = qmlMod(d->_offset - d->snapPos, qreal(1.0 / d->model->count()));
- qreal dist = qAbs(velocity/2 - qmlMod(velocity/2, qreal(1.0 / d->model->count()) - inc));
- d->moveOffset.setValue(d->_offset);
- d->tl.accel(d->moveOffset, velocity, 0.1, dist);
+ if (d->model && d->model->count() && qAbs(velocity) > 1.) {
+ qreal count = d->pathItems == -1 ? d->model->count() : d->pathItems;
+ if (qAbs(velocity) > count * 2) // limit velocity
+ velocity = (velocity > 0 ? count : -count) * 2;
+ // Calculate the distance to be travelled
+ qreal v2 = velocity*velocity;
+ qreal accel = d->deceleration/10;
+ // + 0.25 to encourage moving at least one item in the flick direction
+ qreal dist = qMin(qreal(d->model->count()-1), qreal(v2 / (accel * 2.0) + 0.25));
+ if (d->haveHighlightRange && d->highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) {
+ // round to nearest item.
+ if (velocity > 0.)
+ dist = qRound(dist + d->offset) - d->offset;
+ else
+ dist = qRound(dist - d->offset) + d->offset;
+ // Calculate accel required to stop on item boundary
+ accel = v2 / (2.0f * qAbs(dist));
+ }
+ d->moveOffset.setValue(d->offset);
+ d->tl.accel(d->moveOffset, velocity, accel, dist);
d->tl.callback(QDeclarativeTimeLineCallback(&d->moveOffset, d->fixOffsetCallback, d));
} else {
d->fixOffset();
}
d->lastPosTime = QTime();
- d->stealMouse = false;
ungrabMouse();
}
@@ -644,7 +995,8 @@ bool QDeclarativePathView::sendMouseEvent(QGraphicsSceneMouseEvent *event)
bool QDeclarativePathView::sceneEventFilter(QGraphicsItem *i, QEvent *e)
{
- if (!isVisible())
+ Q_D(QDeclarativePathView);
+ if (!isVisible() || !d->interactive)
return QDeclarativeItem::sceneEventFilter(i, e);
switch (e->type()) {
@@ -668,73 +1020,9 @@ void QDeclarativePathView::componentComplete()
{
Q_D(QDeclarativePathView);
QDeclarativeItem::componentComplete();
+ d->createHighlight();
d->regenerate();
-
- // move to correct offset
- if (d->items.count()) {
- int itemIndex = (d->currentIndex - d->firstIndex + d->model->count()) % d->model->count();
-
- itemIndex += d->pathOffset;
- itemIndex %= d->items.count();
- qreal targetOffset = qmlMod(1.0 + d->snapPos - qreal(itemIndex) / d->items.count(), qreal(1.0));
-
- if (targetOffset < 0)
- targetOffset = 1.0 + targetOffset;
- if (targetOffset != d->_offset) {
- d->moveOffset.setValue(targetOffset);
- }
- }
-}
-
-void QDeclarativePathViewPrivate::regenerate()
-{
- Q_Q(QDeclarativePathView);
- if (!q->isComponentComplete())
- return;
-
- clear();
-
- if (!isValid())
- return;
-
- if (firstIndex >= model->count())
- firstIndex = model->count()-1;
- if (pathOffset >= model->count())
- pathOffset = model->count()-1;
-
- int numItems = pathItems >= 0 ? pathItems : model->count();
- for (int i=0; i < numItems && i < model->count(); ++i){
- int index = (i + firstIndex) % model->count();
- QDeclarativeItem *item = getItem(index);
- if (!item) {
- qWarning() << "PathView: Cannot create item, index" << (i + firstIndex) % model->count();
- return;
- }
- items.append(item);
- item->setZValue(i);
- qreal percent = qreal(i) / numItems + _offset;
- percent = qAbs(qmlMod(percent, qreal(1.0)));
- updateItem(item, percent);
- model->completeItem();
- if (currentIndex == index) {
- item->setFocus(true);
- if (QDeclarativePathViewAttached *att = attached(item))
- att->setIsCurrentItem(true);
- }
- }
- if (pathItems != -1)
- q->refill();
-}
-
-void QDeclarativePathViewPrivate::updateItem(QDeclarativeItem *item, qreal percent)
-{
- if (QDeclarativePathViewAttached *att = attached(item)) {
- foreach(const QString &attr, path->attributes())
- att->setValue(attr.toUtf8(), path->attributeAt(attr, percent));
- }
- QPointF pf = path->pointAt(percent);
- item->setX(pf.x() - item->width()*item->scale()/2);
- item->setY(pf.y() - item->height()*item->scale()/2);
+ d->updateHighlight();
}
void QDeclarativePathView::refill()
@@ -743,81 +1031,110 @@ void QDeclarativePathView::refill()
if (!d->isValid() || !isComponentComplete())
return;
- QList<qreal> positions;
- for (int i=0; i<d->items.count(); i++){
- qreal percent = qreal(i) / d->items.count();
- percent = percent + d->_offset;
- percent = qmlMod(percent, qreal(1.0));
- positions << qAbs(percent);
- }
-
- if (d->pathItems==-1) {
- for (int i=0; i<positions.count(); i++)
- d->updateItem(d->items.at(i), positions[i]);
- return;
+ bool currentVisible = false;
+
+ // first move existing items and remove items off path
+ int idx = d->firstIndex;
+ QList<QDeclarativeItem*>::iterator it = d->items.begin();
+ while (it != d->items.end()) {
+ qreal pos = d->positionOfIndex(idx);
+ QDeclarativeItem *item = *it;
+ if (pos >= 0.0) {
+ d->updateItem(item, pos);
+ if (idx == d->currentIndex) {
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ }
+ ++it;
+ } else {
+// qDebug() << "release";
+ d->updateItem(item, 1.0);
+ d->releaseItem(item);
+ if (it == d->items.begin()) {
+ if (++d->firstIndex >= d->model->count())
+ d->firstIndex = 0;
+ }
+ it = d->items.erase(it);
+ }
+ ++idx;
+ if (idx >= d->model->count())
+ idx = 0;
}
- QList<qreal> rotatedPositions;
- for (int i=0; i<d->items.count(); i++)
- rotatedPositions << positions[(i + d->pathOffset + d->items.count()) % d->items.count()];
-
- int wrapIndex= -1;
- for (int i=0; i<d->items.count()-1; i++) {
- if (rotatedPositions[i] > rotatedPositions[i+1]){
- wrapIndex = i;
- break;
+ // add items to beginning and end
+ int count = d->pathItems == -1 ? d->model->count() : qMin(d->pathItems, d->model->count());
+ if (d->items.count() < count) {
+ int idx = qRound(d->model->count() - d->offset) % d->model->count();
+ qreal startPos = 0.0;
+ if (d->haveHighlightRange && d->highlightRangeMode != QDeclarativePathView::NoHighlightRange)
+ startPos = d->highlightRangeStart;
+ if (d->firstIndex >= 0) {
+ startPos = d->positionOfIndex(d->firstIndex);
+ idx = (d->firstIndex + d->items.count()) % d->model->count();
}
- }
- if (wrapIndex != -1 ){
- //A wraparound has occured
- if (wrapIndex < d->items.count()/2){
- while(wrapIndex-- >= 0){
- QDeclarativeItem* p = d->items.takeFirst();
- d->updateItem(p, 0.0);
- d->releaseItem(p);
- d->firstIndex++;
- d->firstIndex %= d->model->count();
- int index = (d->firstIndex + d->items.count())%d->model->count();
- QDeclarativeItem *item = d->getItem(index);
- item->setZValue(wrapIndex);
- d->model->completeItem();
- if (d->currentIndex == index) {
- item->setFocus(true);
- if (QDeclarativePathViewAttached *att = d->attached(item))
- att->setIsCurrentItem(true);
- }
- d->items << item;
- d->pathOffset++;
- d->pathOffset=d->pathOffset % d->items.count();
+ qreal pos = d->positionOfIndex(idx);
+ while ((pos > startPos || !d->items.count()) && d->items.count() < count) {
+// qDebug() << "append" << idx;
+ QDeclarativeItem *item = d->getItem(idx);
+ item->setZValue(idx+1);
+ d->model->completeItem();
+ if (d->currentIndex == idx) {
+ item->setFocus(true);
+ if (QDeclarativePathViewAttached *att = d->attached(item))
+ att->setIsCurrentItem(true);
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ d->currentItem = item;
}
- } else {
- while(wrapIndex++ < d->items.count()-1){
- QDeclarativeItem* p = d->items.takeLast();
- d->updateItem(p, 1.0);
- d->releaseItem(p);
- d->firstIndex--;
- if (d->firstIndex < 0)
- d->firstIndex = d->model->count() - 1;
- QDeclarativeItem *item = d->getItem(d->firstIndex);
- item->setZValue(d->firstIndex);
- d->model->completeItem();
- if (d->currentIndex == d->firstIndex) {
- item->setFocus(true);
- if (QDeclarativePathViewAttached *att = d->attached(item))
- att->setIsCurrentItem(true);
- }
- d->items.prepend(item);
- d->pathOffset--;
- if (d->pathOffset < 0)
- d->pathOffset = d->items.count() - 1;
+ if (d->items.count() == 0)
+ d->firstIndex = idx;
+ d->items.append(item);
+ d->updateItem(item, pos);
+ ++idx;
+ if (idx >= d->model->count())
+ idx = 0;
+ pos = d->positionOfIndex(idx);
+ }
+
+ idx = d->firstIndex - 1;
+ if (idx < 0)
+ idx = d->model->count() - 1;
+ pos = d->positionOfIndex(idx);
+ while (pos >= 0.0 && pos < startPos) {
+// qDebug() << "prepend" << idx;
+ QDeclarativeItem *item = d->getItem(idx);
+ item->setZValue(idx+1);
+ d->model->completeItem();
+ if (d->currentIndex == idx) {
+ item->setFocus(true);
+ if (QDeclarativePathViewAttached *att = d->attached(item))
+ att->setIsCurrentItem(true);
+ currentVisible = true;
+ d->currentItemOffset = pos;
+ d->currentItem = item;
}
+ d->items.prepend(item);
+ d->updateItem(item, pos);
+ d->firstIndex = idx;
+ idx = d->firstIndex - 1;
+ if (idx < 0)
+ idx = d->model->count() - 1;
+ pos = d->positionOfIndex(idx);
}
- for (int i=0; i<d->items.count(); i++)
- rotatedPositions[i] = positions[(i + d->pathOffset + d->items.count())
- % d->items.count()];
}
- for (int i=0; i<d->items.count(); i++)
- d->updateItem(d->items.at(i), rotatedPositions[i]);
+
+ if (!currentVisible)
+ d->currentItemOffset = 1.0;
+
+ if (d->highlightItem && d->haveHighlightRange && d->highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) {
+ d->updateItem(d->highlightItem, d->highlightRangeStart);
+ if (QDeclarativePathViewAttached *att = d->attached(d->highlightItem))
+ att->setOnPath(true);
+ } else if (d->moveReason != QDeclarativePathViewPrivate::SetIndex) {
+ d->updateItem(d->highlightItem, d->currentItemOffset);
+ if (QDeclarativePathViewAttached *att = d->attached(d->highlightItem))
+ att->setOnPath(currentVisible);
+ }
}
void QDeclarativePathView::itemsInserted(int modelIndex, int count)
@@ -826,29 +1143,18 @@ void QDeclarativePathView::itemsInserted(int modelIndex, int count)
Q_D(QDeclarativePathView);
if (!d->isValid() || !isComponentComplete())
return;
- if (d->pathItems == -1) {
- for (int i = 0; i < count; ++i) {
- QDeclarativeItem *item = d->getItem(modelIndex + i);
- item->setZValue(modelIndex + i);
- d->model->completeItem();
- d->items.insert(modelIndex + i, item);
- }
- refill();
- } else {
- //XXX This is pretty heavy handed until we reference count items.
- d->regenerate();
- }
-
- // make sure the current item is still at the snap position
- int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
- itemIndex += d->pathOffset;
- itemIndex %= d->items.count();
- qreal targetOffset = qmlMod(1.0 + d->snapPos - qreal(itemIndex) / d->items.count(), qreal(1.0));
- if (targetOffset < 0)
- targetOffset = 1.0 + targetOffset;
- if (targetOffset != d->_offset)
- d->moveOffset.setValue(targetOffset);
+ QList<QDeclarativeItem *> removedItems = d->items;
+ d->items.clear();
+ if (modelIndex <= d->currentIndex) {
+ d->currentIndex += count;
+ emit currentIndexChanged();
+ }
+ d->regenerate();
+ while (removedItems.count())
+ d->releaseItem(removedItems.takeLast());
+ d->updateCurrent();
+ emit countChanged();
}
void QDeclarativePathView::itemsRemoved(int modelIndex, int count)
@@ -857,41 +1163,63 @@ void QDeclarativePathView::itemsRemoved(int modelIndex, int count)
Q_D(QDeclarativePathView);
if (!d->isValid() || !isComponentComplete())
return;
- if (d->pathItems == -1) {
- for (int i = 0; i < count && d->items.count() > modelIndex; ++i) {
- QDeclarativeItem* p = d->items.takeAt(modelIndex);
- d->model->release(p);
+
+ // fix current
+ bool currentChanged = false;
+ if (d->currentIndex >= modelIndex + count) {
+ d->currentIndex -= count;
+ currentChanged = true;
+ } else if (d->currentIndex >= modelIndex && d->currentIndex < modelIndex + count) {
+ // current item has been removed.
+ d->currentIndex = qMin(modelIndex, d->model->count()-1);
+ if (d->currentItem) {
+ if (QDeclarativePathViewAttached *att = d->attached(d->currentItem))
+ att->setIsCurrentItem(true);
}
- d->snapToCurrent();
- refill();
- } else {
- d->regenerate();
+ currentChanged = true;
}
- if (d->model->count() == 0) {
- d->currentIndex = -1;
- d->moveOffset.setValue(0);
- return;
- }
+ QList<QDeclarativeItem *> removedItems = d->items;
+ d->items.clear();
+ if (d->offset >= d->model->count())
+ d->offset = d->model->count() - 1;
+
+ d->regenerate();
+ while (removedItems.count())
+ d->releaseItem(removedItems.takeLast());
+ d->updateCurrent();
+ if (currentChanged)
+ emit currentIndexChanged();
+ emit countChanged();
+}
- // make sure the current item is still at the snap position
- if (d->currentIndex >= d->model->count())
- d->currentIndex = d->model->count() - 1;
- int itemIndex = (d->currentIndex - d->firstIndex + d->model->count())%d->model->count();
- itemIndex += d->pathOffset;
- itemIndex %= d->items.count();
- qreal targetOffset = qmlMod(1.0 + d->snapPos - qreal(itemIndex) / d->items.count(), qreal(1.0));
+void QDeclarativePathView::itemsMoved(int /*from*/, int /*to*/, int /*count*/)
+{
+ Q_D(QDeclarativePathView);
+ if (!d->isValid() || !isComponentComplete())
+ return;
- if (targetOffset < 0)
- targetOffset = 1.0 + targetOffset;
- if (targetOffset != d->_offset)
- d->moveOffset.setValue(targetOffset);
+ QList<QDeclarativeItem *> removedItems = d->items;
+ d->items.clear();
+ d->regenerate();
+ while (removedItems.count())
+ d->releaseItem(removedItems.takeLast());
+
+ // Fix current index
+ if (d->currentIndex >= 0 && d->currentItem) {
+ int oldCurrent = d->currentIndex;
+ d->currentIndex = d->model->indexOf(d->currentItem, this);
+ if (oldCurrent != d->currentIndex)
+ emit currentIndexChanged();
+ }
+ d->updateCurrent();
}
void QDeclarativePathView::modelReset()
{
Q_D(QDeclarativePathView);
d->regenerate();
+ emit countChanged();
}
void QDeclarativePathView::createdItem(int index, QDeclarativeItem *item)
@@ -919,36 +1247,10 @@ int QDeclarativePathViewPrivate::calcCurrentIndex()
{
int current = -1;
if (model && items.count()) {
- _offset = qmlMod(_offset, qreal(1.0));
- if (_offset < 0)
- _offset += 1.0;
-
- if (pathItems == -1) {
- qreal delta = qmlMod(_offset - snapPos, qreal(1.0));
- if (delta < 0)
- delta = 1.0 + delta;
- int ii = model->count() - qRound(delta * model->count());
- if (ii < 0)
- ii = 0;
- current = ii;
- } else {
- qreal bestDiff=1e9;
- int bestI=-1;
- for (int i=0; i<items.count(); i++){
- qreal percent = qreal(i) / items.count();
- percent = percent + _offset;
- percent = qmlMod(percent, qreal(1.0));
- qreal diff = qAbs(snapPos - percent);
- if (diff < bestDiff){
- bestDiff = diff;
- bestI = i;
- }
- }
- int modelIndex = (bestI - pathOffset + items.count())%items.count();
- modelIndex += firstIndex;
- current = modelIndex;
- }
- current = qAbs(current % model->count());
+ offset = qmlMod(offset, model->count());
+ if (offset < 0)
+ offset += model->count();
+ current = qRound(qAbs(qmlMod(model->count() - offset, model->count())));
}
return current;
@@ -959,6 +1261,9 @@ void QDeclarativePathViewPrivate::updateCurrent()
Q_Q(QDeclarativePathView);
if (moveReason != Mouse)
return;
+ if (!haveHighlightRange || highlightRangeMode != QDeclarativePathView::StrictlyEnforceRange)
+ return;
+
int idx = calcCurrentIndex();
if (model && idx != currentIndex) {
int itemIndex = (currentIndex - firstIndex + model->count()) % model->count();
@@ -969,11 +1274,12 @@ void QDeclarativePathViewPrivate::updateCurrent()
}
}
currentIndex = idx;
+ currentItem = 0;
itemIndex = (idx - firstIndex + model->count()) % model->count();
if (itemIndex < items.count()) {
- QDeclarativeItem *item = items.at(itemIndex);
- item->setFocus(true);
- if (QDeclarativePathViewAttached *att = attached(item))
+ currentItem = items.at(itemIndex);
+ currentItem->setFocus(true);
+ if (QDeclarativePathViewAttached *att = attached(currentItem))
att->setIsCurrentItem(true);
}
emit q->currentIndexChanged();
@@ -989,11 +1295,13 @@ void QDeclarativePathViewPrivate::fixOffset()
{
Q_Q(QDeclarativePathView);
if (model && items.count()) {
- int curr = calcCurrentIndex();
- if (curr != currentIndex)
- q->setCurrentIndex(curr);
- else
- snapToCurrent();
+ if (haveHighlightRange && highlightRangeMode == QDeclarativePathView::StrictlyEnforceRange) {
+ int curr = calcCurrentIndex();
+ if (curr != currentIndex)
+ q->setCurrentIndex(curr);
+ else
+ snapToCurrent();
+ }
}
}
@@ -1002,57 +1310,26 @@ void QDeclarativePathViewPrivate::snapToCurrent()
if (!model || model->count() <= 0)
return;
- int itemIndex = (currentIndex - firstIndex + model->count()) % model->count();
-
- //Rounds is the number of times round to make the current item visible
- int rounds = itemIndex / items.count();
- int otherWayRounds = (model->count() - (itemIndex)) / items.count();
- if (otherWayRounds < rounds)
- rounds = -otherWayRounds;
-
- itemIndex += pathOffset;
- if(model->count() % items.count() && itemIndex - model->count() + items.count() > 0){
- //When model.count() is not a multiple of pathItemCount we need to manually
- //fix the index so that going backwards one step works correctly.
- itemIndex = itemIndex - model->count() + items.count();
- }
- itemIndex %= items.count();
- qreal targetOffset = qmlMod(1.0 + snapPos - qreal(itemIndex) / items.count(), qreal(1.0));
-
- if (targetOffset < 0)
- targetOffset = 1.0 + targetOffset;
- if (targetOffset == _offset && rounds == 0)
- return;
+ qreal targetOffset = model->count() - currentIndex;
moveReason = Other;
- tl.clear();
- moveOffset.setValue(_offset);
-
- if (rounds!=0){
- //Compensate if the targetOffset would bring the target in from off the screen
- qreal distance = targetOffset - _offset;
- if (distance <= -0.5)
- rounds--;
- if (distance > 0.5)
- rounds++;
- tl.move(moveOffset, targetOffset -rounds, QEasingCurve(QEasingCurve::InOutQuad),
- int(items.count()*qMax((qreal)(2.0/items.count()),(qreal)qAbs(rounds))));
- tl.callback(QDeclarativeTimeLineCallback(&moveOffset, fixOffsetCallback, this));
- return;
- }
-
- if (targetOffset - _offset > 0.5) {
- qreal distance = 1 - targetOffset + _offset;
- tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * _offset / distance));
- tl.set(moveOffset, 1.0);
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * (1.0-targetOffset) / distance));
- } else if (targetOffset - _offset <= -0.5) {
- qreal distance = 1 - _offset + targetOffset;
- tl.move(moveOffset, 1.0, QEasingCurve(QEasingCurve::OutQuad), int(200 * (1.0-_offset) / distance));
+ tl.reset(moveOffset);
+ moveOffset.setValue(offset);
+
+ const int duration = 300;
+
+ if (targetOffset - offset > model->count()/2) {
+ qreal distance = model->count() - targetOffset + offset;
+ tl.move(moveOffset, 0.0, QEasingCurve(QEasingCurve::InQuad), int(duration * offset / distance));
+ tl.set(moveOffset, model->count());
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::OutQuad), int(duration * (model->count()-targetOffset) / distance));
+ } else if (targetOffset - offset <= -model->count()/2) {
+ qreal distance = model->count() - offset + targetOffset;
+ tl.move(moveOffset, model->count(), QEasingCurve(QEasingCurve::InQuad), int(duration * (model->count()-offset) / distance));
tl.set(moveOffset, 0.0);
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InQuad), int(200 * targetOffset / distance));
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::OutQuad), int(duration * targetOffset / distance));
} else {
- tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), 200);
+ tl.move(moveOffset, targetOffset, QEasingCurve(QEasingCurve::InOutQuad), duration);
}
}
diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p.h
index 6dbd044..0079891 100644
--- a/src/declarative/graphicsitems/qdeclarativepathview_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepathview_p.h
@@ -61,12 +61,24 @@ class Q_DECLARATIVE_EXPORT QDeclarativePathView : public QDeclarativeItem
Q_PROPERTY(QDeclarativePath *path READ path WRITE setPath NOTIFY pathChanged)
Q_PROPERTY(int currentIndex READ currentIndex WRITE setCurrentIndex NOTIFY currentIndexChanged)
Q_PROPERTY(qreal offset READ offset WRITE setOffset NOTIFY offsetChanged)
- Q_PROPERTY(qreal snapPosition READ snapPosition WRITE setSnapPosition NOTIFY snapPositionChanged)
+
+ Q_PROPERTY(QDeclarativeComponent *highlight READ highlight WRITE setHighlight NOTIFY highlightChanged)
+ Q_PROPERTY(QDeclarativeItem *highlightItem READ highlightItem NOTIFY highlightItemChanged)
+
+ Q_PROPERTY(qreal preferredHighlightBegin READ preferredHighlightBegin WRITE setPreferredHighlightBegin NOTIFY preferredHighlightBeginChanged)
+ Q_PROPERTY(qreal preferredHighlightEnd READ preferredHighlightEnd WRITE setPreferredHighlightEnd NOTIFY preferredHighlightEndChanged)
+ Q_PROPERTY(HighlightRangeMode highlightRangeMode READ highlightRangeMode WRITE setHighlightRangeMode NOTIFY highlightRangeModeChanged)
+
Q_PROPERTY(qreal dragMargin READ dragMargin WRITE setDragMargin NOTIFY dragMarginChanged)
- Q_PROPERTY(int count READ count)
+ Q_PROPERTY(qreal flickDeceleration READ flickDeceleration WRITE setFlickDeceleration NOTIFY flickDecelerationChanged)
+ Q_PROPERTY(bool interactive READ isInteractive WRITE setInteractive NOTIFY interactiveChanged)
+
+ Q_PROPERTY(int count READ count NOTIFY countChanged)
Q_PROPERTY(QDeclarativeComponent *delegate READ delegate WRITE setDelegate NOTIFY delegateChanged)
Q_PROPERTY(int pathItemCount READ pathItemCount WRITE setPathItemCount NOTIFY pathItemCountChanged)
+ Q_ENUMS(HighlightRangeMode);
+
public:
QDeclarativePathView(QDeclarativeItem *parent=0);
virtual ~QDeclarativePathView();
@@ -83,12 +95,29 @@ public:
qreal offset() const;
void setOffset(qreal offset);
- qreal snapPosition() const;
- void setSnapPosition(qreal pos);
+ QDeclarativeComponent *highlight() const;
+ void setHighlight(QDeclarativeComponent *highlight);
+ QDeclarativeItem *highlightItem();
+
+ enum HighlightRangeMode { NoHighlightRange, ApplyRange, StrictlyEnforceRange };
+ HighlightRangeMode highlightRangeMode() const;
+ void setHighlightRangeMode(HighlightRangeMode mode);
+
+ qreal preferredHighlightBegin() const;
+ void setPreferredHighlightBegin(qreal);
+
+ qreal preferredHighlightEnd() const;
+ void setPreferredHighlightEnd(qreal);
qreal dragMargin() const;
void setDragMargin(qreal margin);
+ qreal flickDeceleration() const;
+ void setFlickDeceleration(qreal dec);
+
+ bool isInteractive() const;
+ void setInteractive(bool);
+
int count() const;
QDeclarativeComponent *delegate() const;
@@ -103,11 +132,19 @@ Q_SIGNALS:
void currentIndexChanged();
void offsetChanged();
void modelChanged();
+ void countChanged();
void pathChanged();
+ void preferredHighlightBeginChanged();
+ void preferredHighlightEndChanged();
+ void highlightRangeModeChanged();
void dragMarginChanged();
void snapPositionChanged();
void delegateChanged();
void pathItemCountChanged();
+ void flickDecelerationChanged();
+ void interactiveChanged();
+ void highlightChanged();
+ void highlightItemChanged();
protected:
void mousePressEvent(QGraphicsSceneMouseEvent *event);
@@ -122,6 +159,7 @@ private Q_SLOTS:
void ticked();
void itemsInserted(int index, int count);
void itemsRemoved(int index, int count);
+ void itemsMoved(int,int,int);
void modelReset();
void createdItem(int index, QDeclarativeItem *item);
void destroyingItem(QDeclarativeItem *item);
diff --git a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h
index 62f7d95..6470893 100644
--- a/src/declarative/graphicsitems/qdeclarativepathview_p_p.h
+++ b/src/declarative/graphicsitems/qdeclarativepathview_p_p.h
@@ -74,18 +74,25 @@ class QDeclarativePathViewPrivate : public QDeclarativeItemPrivate
public:
QDeclarativePathViewPrivate()
- : path(0), currentIndex(0), startPc(0), lastDist(0)
- , lastElapsed(0), stealMouse(false), ownModel(false), activeItem(0)
- , snapPos(0), dragMargin(0), moveOffset(this, &QDeclarativePathViewPrivate::setOffset)
- , firstIndex(0), pathItems(-1), pathOffset(0), requestedIndex(-1)
- , moveReason(Other), attType(0)
+ : path(0), currentIndex(0), currentItemOffset(0.0), startPc(0), lastDist(0)
+ , lastElapsed(0), mappedRange(1.0)
+ , stealMouse(false), ownModel(false), interactive(true), haveHighlightRange(true)
+ , autoHighlight(true), highlightUp(false), dragMargin(0), deceleration(100)
+ , moveOffset(this, &QDeclarativePathViewPrivate::setOffset)
+ , firstIndex(-1), pathItems(-1), requestedIndex(-1)
+ , moveReason(Other), attType(0), highlightComponent(0), highlightItem(0)
+ , moveHighlight(this, &QDeclarativePathViewPrivate::setHighlightPosition)
+ , highlightPosition(0)
+ , highlightRangeStart(0), highlightRangeEnd(0)
+ , highlightRangeMode(QDeclarativePathView::StrictlyEnforceRange)
+ , highlightMoveSpeed(1.0)
{
}
void init()
{
Q_Q(QDeclarativePathView);
- _offset = 0;
+ offset = 0;
q->setAcceptedMouseButtons(Qt::LeftButton);
q->setFlag(QGraphicsItem::ItemIsFocusScope);
q->setFiltersChildEvents(true);
@@ -96,7 +103,11 @@ public:
void releaseItem(QDeclarativeItem *item);
QDeclarativePathViewAttached *attached(QDeclarativeItem *item);
void clear();
-
+ void updateMappedRange();
+ qreal positionOfIndex(qreal index) const;
+ void createHighlight();
+ void updateHighlight();
+ void setHighlightPosition(qreal pos);
bool isValid() const {
return model && model->count() > 0 && model->isValid() && path;
}
@@ -113,30 +124,43 @@ public:
QDeclarativePath *path;
int currentIndex;
+ QDeclarativeGuard<QDeclarativeItem> currentItem;
+ qreal currentItemOffset;
qreal startPc;
QPointF startPoint;
qreal lastDist;
int lastElapsed;
- qreal _offset;
+ qreal offset;
+ qreal mappedRange;
bool stealMouse : 1;
bool ownModel : 1;
+ bool interactive : 1;
+ bool haveHighlightRange : 1;
+ bool autoHighlight : 1;
+ bool highlightUp : 1;
QTime lastPosTime;
QPointF lastPos;
- QDeclarativeItem *activeItem;
- qreal snapPos;
qreal dragMargin;
+ qreal deceleration;
QDeclarativeTimeLine tl;
QDeclarativeTimeLineValueProxy<QDeclarativePathViewPrivate> moveOffset;
int firstIndex;
int pathItems;
- int pathOffset;
int requestedIndex;
QList<QDeclarativeItem *> items;
QDeclarativeGuard<QDeclarativeVisualModel> model;
QVariant modelVariant;
- enum MovementReason { Other, Key, Mouse };
+ enum MovementReason { Other, SetIndex, Mouse };
MovementReason moveReason;
QDeclarativeOpenMetaObjectType *attType;
+ QDeclarativeComponent *highlightComponent;
+ QDeclarativeItem *highlightItem;
+ QDeclarativeTimeLineValueProxy<QDeclarativePathViewPrivate> moveHighlight;
+ qreal highlightPosition;
+ qreal highlightRangeStart;
+ qreal highlightRangeEnd;
+ QDeclarativePathView::HighlightRangeMode highlightRangeMode;
+ qreal highlightMoveSpeed;
};
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativepositioners.cpp b/src/declarative/graphicsitems/qdeclarativepositioners.cpp
index 7a0d33a..b23b8c9 100644
--- a/src/declarative/graphicsitems/qdeclarativepositioners.cpp
+++ b/src/declarative/graphicsitems/qdeclarativepositioners.cpp
@@ -602,7 +602,9 @@ Grid {
\qmlproperty Transition Grid::add
This property holds the transition to apply when adding an item to the positioner.
The transition is only applied to the added item(s).
- Positioner transitions will only affect the position (x,y) of items.
+ Positioner transitions will only affect the position (x,y) of items,
+ as that is all the positioners affect. To animate other property change
+ you will have to do so based on how you have changed those properties.
Added can mean that either the object has been created or
reparented, and thus is now a child or the positioner, or that the
@@ -818,6 +820,9 @@ public:
QDeclarativeFlow::QDeclarativeFlow(QDeclarativeItem *parent)
: QDeclarativeBasePositioner(*(new QDeclarativeFlowPrivate), Both, parent)
{
+ Q_D(QDeclarativeFlow);
+ // Flow layout requires relayout if its own size changes too.
+ d->addItemChangeListener(d, QDeclarativeItemPrivate::Geometry);
}
/*!
diff --git a/src/declarative/graphicsitems/qdeclarativerectangle.cpp b/src/declarative/graphicsitems/qdeclarativerectangle.cpp
index 207d05e..b82fb53 100644
--- a/src/declarative/graphicsitems/qdeclarativerectangle.cpp
+++ b/src/declarative/graphicsitems/qdeclarativerectangle.cpp
@@ -470,7 +470,7 @@ void QDeclarativeRectangle::drawRect(QPainter &p)
QRectF QDeclarativeRectangle::boundingRect() const
{
Q_D(const QDeclarativeRectangle);
- return QRectF(-d->paintmargin, -d->paintmargin, d->width+d->paintmargin*2, d->height+d->paintmargin*2);
+ return QRectF(-d->paintmargin, -d->paintmargin, d->width()+d->paintmargin*2, d->height()+d->paintmargin*2);
}
QT_END_NAMESPACE
diff --git a/src/declarative/graphicsitems/qdeclarativerepeater.cpp b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
index e8f9b24..bbee4e5 100644
--- a/src/declarative/graphicsitems/qdeclarativerepeater.cpp
+++ b/src/declarative/graphicsitems/qdeclarativerepeater.cpp
@@ -43,7 +43,7 @@
#include "qdeclarativerepeater_p_p.h"
#include "qdeclarativevisualitemmodel_p.h"
-
+#include <private/qdeclarativeglobal_p.h>
#include <qdeclarativelistaccessor_p.h>
#include <qlistmodelinterface_p.h>
@@ -283,7 +283,6 @@ void QDeclarativeRepeater::clear()
Q_D(QDeclarativeRepeater);
if (d->model) {
foreach (QDeclarativeItem *item, d->deletables) {
- item->setParentItem(this);
d->model->release(item);
}
}
@@ -307,7 +306,8 @@ void QDeclarativeRepeater::regenerate()
for (int ii = 0; ii < count(); ++ii) {
QDeclarativeItem *item = d->model->item(ii);
if (item) {
- item->setParent(parentItem());
+ QDeclarative_setParent_noEvent(item, parentItem());
+ item->setParentItem(parentItem());
item->stackBefore(this);
d->deletables << item;
}
@@ -323,7 +323,8 @@ void QDeclarativeRepeater::itemsInserted(int index, int count)
int modelIndex = index + i;
QDeclarativeItem *item = d->model->item(modelIndex);
if (item) {
- item->setParent(parentItem());
+ QDeclarative_setParent_noEvent(item, parentItem());
+ item->setParentItem(parentItem());
if (modelIndex < d->deletables.count())
item->stackBefore(d->deletables.at(modelIndex));
else
@@ -341,7 +342,6 @@ void QDeclarativeRepeater::itemsRemoved(int index, int count)
while (count--) {
QDeclarativeItem *item = d->deletables.takeAt(index);
if (item) {
- item->setParentItem(this);
d->model->release(item);
}
}
diff --git a/src/declarative/graphicsitems/qdeclarativetextedit.cpp b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
index 7dacfbb..03b2425 100644
--- a/src/declarative/graphicsitems/qdeclarativetextedit.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextedit.cpp
@@ -43,6 +43,7 @@
#include "qdeclarativetextedit_p_p.h"
#include "qdeclarativeevents_p_p.h"
+#include <private/qdeclarativeglobal_p.h>
#include <QTextLayout>
#include <QTextLine>
@@ -485,6 +486,7 @@ void QDeclarativeTextEdit::loadCursorDelegate()
this, SLOT(moveCursorDelegate()));
d->control->setCursorWidth(0);
dirtyCache(cursorRect());
+ QDeclarative_setParent_noEvent(d->cursor, this);
d->cursor->setParentItem(this);
d->cursor->setHeight(QFontMetrics(d->font).height());
moveCursorDelegate();
diff --git a/src/declarative/graphicsitems/qdeclarativetextinput.cpp b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
index b049728..88801a4 100644
--- a/src/declarative/graphicsitems/qdeclarativetextinput.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetextinput.cpp
@@ -42,6 +42,7 @@
#include "qdeclarativetextinput_p.h"
#include "qdeclarativetextinput_p_p.h"
+#include <private/qdeclarativeglobal_p.h>
#include <qdeclarativeinfo.h>
#include <QValidator>
@@ -428,20 +429,21 @@ void QDeclarativeTextInput::setFocusOnPress(bool b)
}
/*!
- \qmlproperty QValidator* TextInput::validator
+ \qmlproperty Validator TextInput::validator
- Allows you to set a QValidator on the TextInput. When a validator is set
+ Allows you to set a validator on the TextInput. When a validator is set
the TextInput will only accept input which leaves the text property in
an acceptable or intermediate state. The accepted signal will only be sent
if the text is in an acceptable state when enter is pressed.
- Currently supported validators are QIntValidator, QDoubleValidator and
- QRegExpValidator. For details, refer to their C++ documentation and remember
+ Currently supported validators are IntValidator, DoubleValidator and
+ RegExpValidator. For details, refer to their C++ documentation (QIntValidator,
+ QDoubleValidator, and QRegExpValidator) and remember
that all Q_PROPERTIES are accessible from Qml. A brief usage guide follows:
- QIntValidator and QDoubleValidator both are controllable through two properties,
- top and bottom. The difference is that for QIntValidator the top and bottom properties
- should be integers, and for QDoubleValidator they should be doubles. QRegExpValidator
+ IntValidator and DoubleValidator both are controllable through two properties,
+ top and bottom. The difference is that for IntValidator the top and bottom properties
+ should be integers, and for DoubleValidator they should be doubles. RegExpValidator
has a single string property, regExp, which should be set to the regular expression to
be used for validation. An example of using validators is shown below, which allows
input of integers between 11 and 31 into the text input:
@@ -449,7 +451,7 @@ void QDeclarativeTextInput::setFocusOnPress(bool b)
\code
import Qt 4.6
TextInput{
- validator: QIntValidator{bottom: 11; top: 31;}
+ validator: IntValidator{bottom: 11; top: 31;}
focus: true
}
\endcode
@@ -618,6 +620,7 @@ void QDeclarativeTextInput::createCursor()
return;
}
+ QDeclarative_setParent_noEvent(d->cursorItem, this);
d->cursorItem->setParentItem(this);
d->cursorItem->setX(d->control->cursorToX());
d->cursorItem->setHeight(d->control->height());
diff --git a/src/declarative/graphicsitems/qdeclarativetranslate.cpp b/src/declarative/graphicsitems/qdeclarativetranslate.cpp
new file mode 100644
index 0000000..1c96fa4
--- /dev/null
+++ b/src/declarative/graphicsitems/qdeclarativetranslate.cpp
@@ -0,0 +1,136 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativetranslate_p.h"
+#include <private/qgraphicstransform_p.h>
+#include <QDebug>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeTranslatePrivate : public QGraphicsTransformPrivate
+{
+public:
+ QDeclarativeTranslatePrivate()
+ : x(0), y(0) {}
+ qreal x;
+ qreal y;
+};
+
+/*!
+ Constructs an empty QDeclarativeTranslate object with the given \a parent.
+*/
+QDeclarativeTranslate::QDeclarativeTranslate(QObject *parent)
+ : QGraphicsTransform(*new QDeclarativeTranslatePrivate, parent)
+{
+}
+
+/*!
+ Destroys the graphics scale.
+*/
+QDeclarativeTranslate::~QDeclarativeTranslate()
+{
+}
+
+/*!
+ \property QDeclarativeTranslate::x
+ \brief the horizontal translation.
+
+ The translation can be any real number; the default value is 0.0.
+
+ \sa y
+*/
+qreal QDeclarativeTranslate::x() const
+{
+ Q_D(const QDeclarativeTranslate);
+ return d->x;
+}
+void QDeclarativeTranslate::setX(qreal x)
+{
+ Q_D(QDeclarativeTranslate);
+ if (d->x == x)
+ return;
+ d->x = x;
+ update();
+ emit positionChanged();
+}
+
+/*!
+ \property QDeclarativeTranslate::y
+ \brief the vertical translation.
+
+ The translation can be any real number; the default value is 0.0.
+
+ \sa x
+*/
+qreal QDeclarativeTranslate::y() const
+{
+ Q_D(const QDeclarativeTranslate);
+ return d->y;
+}
+void QDeclarativeTranslate::setY(qreal y)
+{
+ Q_D(QDeclarativeTranslate);
+ if (d->y == y)
+ return;
+ d->y = y;
+ update();
+ emit positionChanged();
+}
+
+/*!
+ \reimp
+*/
+void QDeclarativeTranslate::applyTo(QMatrix4x4 *matrix) const
+{
+ Q_D(const QDeclarativeTranslate);
+ matrix->translate(d->x, d->y, 0);
+}
+
+/*!
+ \fn QDeclarativeTranslate::positionChanged()
+
+ QDeclarativeTranslate emits this signal when its position changes.
+
+ \sa QDeclarativeTranslate::x, QDeclarativeTranslate::y
+*/
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativescript.cpp b/src/declarative/graphicsitems/qdeclarativetranslate_p.h
index ac4b2c1..939692b 100644
--- a/src/declarative/qml/qdeclarativescript.cpp
+++ b/src/declarative/graphicsitems/qdeclarativetranslate_p.h
@@ -39,50 +39,50 @@
**
****************************************************************************/
-// This is just a dummy file to include the documentation
-
-/*!
- \qmlclass Script QDeclarativeScript
- \since 4.7
- \brief The Script element provides a way to add JavaScript code snippets in QML.
- \ingroup group_utility
-
- The Script element is used to add convenient JavaScript "glue" methods to
- your Qt Declarative application or component.
-
- An example:
-
- \qml
- Script {
- function debugMyComponent() {
- console.log(text.text);
- console.log(otherinterestingitem.property);
- }
- }
- MouseArea { onClicked: debugMyComponent() }
- \endqml
-
- \note While it is possible to use any JavaScript code within a Script element,
- it is recommended that the code be limited to defining functions. The Script
- element executes JavaScript as soon as it is specified, so
- when defining a component, this may be done before the execution context is
- fully specified. As a result, some properties or items may not be
- accessible. You can avoid this problem by limiting your JavaScript to
- defining functions that are only executed later once the context is fully
- defined.
-
- \sa {JavaScript Blocks}
-*/
-
-/*!
- \qmlproperty string Script::script
- \default
- The JavaScript code to be executed.
-*/
-
-/*!
- \qmlproperty url Script::source
-
- Specifies a source file containing JavaScript code. This can be used instead
- of providing inline JavaScript code in the Script element.
-*/
+#ifndef QDECLARATIVETRANSLATE_H
+#define QDECLARATIVETRANSLATE_H
+
+#include "qdeclarativeitem.h"
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Declarative)
+
+class QDeclarativeTranslatePrivate;
+
+class Q_DECLARATIVE_EXPORT QDeclarativeTranslate : public QGraphicsTransform
+{
+ Q_OBJECT
+
+ Q_PROPERTY(qreal x READ x WRITE setX NOTIFY positionChanged)
+ Q_PROPERTY(qreal y READ y WRITE setY NOTIFY positionChanged)
+
+public:
+ QDeclarativeTranslate(QObject *parent = 0);
+ ~QDeclarativeTranslate();
+
+ qreal x() const;
+ void setX(qreal);
+
+ qreal y() const;
+ void setY(qreal);
+
+ void applyTo(QMatrix4x4 *matrix) const;
+
+Q_SIGNALS:
+ void positionChanged();
+
+private:
+ Q_DECLARE_PRIVATE(QDeclarativeTranslate)
+ Q_DISABLE_COPY(QDeclarativeTranslate)
+};
+
+QT_END_NAMESPACE
+
+QML_DECLARE_TYPE(QDeclarativeTranslate)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g
index 0256c52..6434d10 100644
--- a/src/declarative/qml/parser/qdeclarativejs.g
+++ b/src/declarative/qml/parser/qdeclarativejs.g
@@ -654,11 +654,6 @@ case $rule_number: {
node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
node->fileNameToken = loc(2);
} else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
- QString text;
- for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
- text += q->name->asString();
- if (q->next) text += QLatin1String(".");
- }
node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
node->fileNameToken = loc(2);
}
@@ -1109,6 +1104,9 @@ case $rule_number: {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
return false; // ### remove me
}
+
+ loc(1).length = lexer->tokenLength();
+
AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
node->literalToken = loc(1);
sym(1).Node = node;
@@ -1126,6 +1124,9 @@ case $rule_number: {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
return false;
}
+
+ loc(1).length = lexer->tokenLength();
+
AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
node->literalToken = loc(1);
sym(1).Node = node;
diff --git a/src/declarative/qml/parser/qdeclarativejsparser.cpp b/src/declarative/qml/parser/qdeclarativejsparser.cpp
index 9205ef4..3cf73b1 100644
--- a/src/declarative/qml/parser/qdeclarativejsparser.cpp
+++ b/src/declarative/qml/parser/qdeclarativejsparser.cpp
@@ -273,11 +273,6 @@ case 20: {
node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value);
node->fileNameToken = loc(2);
} else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) {
- QString text;
- for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) {
- text += q->name->asString();
- if (q->next) text += QLatin1String(".");
- }
node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId);
node->fileNameToken = loc(2);
}
@@ -571,6 +566,9 @@ case 76: {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
return false; // ### remove me
}
+
+ loc(1).length = lexer->tokenLength();
+
AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
node->literalToken = loc(1);
sym(1).Node = node;
@@ -582,6 +580,9 @@ case 77: {
diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage()));
return false;
}
+
+ loc(1).length = lexer->tokenLength();
+
AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags);
node->literalToken = loc(1);
sym(1).Node = node;
diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp
index 1acca2f..67750a4 100644
--- a/src/declarative/qml/qdeclarativecompiledbindings.cpp
+++ b/src/declarative/qml/qdeclarativecompiledbindings.cpp
@@ -53,11 +53,15 @@
#include <QtCore/qnumeric.h>
#include <private/qdeclarativeanchors_p_p.h>
#include <private/qdeclarativeglobal_p.h>
+#include <private/qdeclarativefastproperties_p.h>
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER);
+DEFINE_BOOL_CONFIG_OPTION(qmlDisableFastProperties, QML_DISABLE_FAST_PROPERTIES);
+
+Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties);
using namespace QDeclarativeJS;
@@ -334,6 +338,8 @@ struct Instr {
Subscribe, // subscribe
SubscribeId, // subscribe
+ FetchAndSubscribe, // fetchAndSubscribe
+
LoadId, // load
LoadScope, // load
LoadRoot, // load
@@ -433,6 +439,14 @@ struct Instr {
qint8 output;
qint8 objectReg;
quint8 exceptionId;
+ quint16 subscription;
+ quint16 function;
+ } fetchAndSubscribe;
+ struct {
+ quint8 type;
+ qint8 output;
+ qint8 objectReg;
+ quint8 exceptionId;
quint32 index;
} fetch;
struct {
@@ -937,6 +951,9 @@ static void dumpInstruction(const Instr *instr)
case Instr::SubscribeId:
qWarning().nospace() << "SubscribeId" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index;
break;
+ case Instr::FetchAndSubscribe:
+ qWarning().nospace() << "FetchAndSubscribe" << "\t" << instr->fetchAndSubscribe.output << "\t" << instr->fetchAndSubscribe.objectReg << "\t" << instr->fetchAndSubscribe.subscription;
+ break;
case Instr::LoadId:
qWarning().nospace() << "LoadId" << "\t\t\t" << instr->load.index << "\t" << instr->load.reg;
break;
@@ -1070,6 +1087,8 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex,
QDeclarativeContextData *context, QDeclarativeDelayedError *error,
QObject *scope, QObject *output)
{
+ Q_Q(QDeclarativeCompiledBindings);
+
error->removeError();
Register registers[32];
@@ -1081,6 +1100,7 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex,
instr += instrIndex;
const char *data = program->data();
+ // return;
#ifdef COMPILEDBINDINGS_DEBUG
qWarning().nospace() << "Begin binding run";
#endif
@@ -1107,6 +1127,32 @@ void QDeclarativeCompiledBindingsPrivate::run(int instrIndex,
}
break;
+ case Instr::FetchAndSubscribe:
+ {
+ const Register &input = registers[instr->fetchAndSubscribe.objectReg];
+ Register &output = registers[instr->fetchAndSubscribe.output];
+
+ if (input.isUndefined()) {
+ throwException(instr->fetchAndSubscribe.exceptionId, error, program, context);
+ return;
+ }
+
+ QObject *object = input.getQObject();
+ if (!object) {
+ output.setUndefined();
+ } else {
+ int subIdx = instr->fetchAndSubscribe.subscription;
+ QDeclarativeCompiledBindingsPrivate::Subscription *sub = 0;
+ if (subIdx != -1) {
+ sub = (subscriptions + subIdx);
+ sub->target = q;
+ sub->targetMethod = methodCount + subIdx;
+ }
+ fastProperties()->accessor(instr->fetchAndSubscribe.function)(object, output.typeDataPtr(), sub);
+ }
+ }
+ break;
+
case Instr::LoadId:
registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
break;
@@ -2376,29 +2422,41 @@ bool QDeclarativeBindingCompilerPrivate::buildName(QStringList &name,
return true;
}
-
bool QDeclarativeBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg,
- int idx, const QStringList &subName, QDeclarativeJS::AST::ExpressionNode *node)
+ int idx, const QStringList &subName,
+ QDeclarativeJS::AST::ExpressionNode *node)
{
QMetaProperty prop = mo->property(idx);
rv.metaObject = 0;
rv.type = 0;
- if (subscription(subName, &rv) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) {
- Instr sub;
- sub.common.type = Instr::Subscribe;
- sub.subscribe.offset = subscriptionIndex(subName);
- sub.subscribe.reg = reg;
- sub.subscribe.index = prop.notifySignalIndex();
- bytecode << sub;
- }
+ int fastFetchIndex = fastProperties()->accessorIndexForProperty(mo, idx);
Instr fetch;
- fetch.common.type = Instr::Fetch;
- fetch.fetch.objectReg = reg;
- fetch.fetch.index = idx;
- fetch.fetch.output = reg;
- fetch.fetch.exceptionId = exceptionId(node);
+
+ if (!qmlDisableFastProperties() && fastFetchIndex != -1) {
+ fetch.common.type = Instr::FetchAndSubscribe;
+ fetch.fetchAndSubscribe.objectReg = reg;
+ fetch.fetchAndSubscribe.output = reg;
+ fetch.fetchAndSubscribe.function = fastFetchIndex;
+ fetch.fetchAndSubscribe.subscription = subscriptionIndex(subName);
+ fetch.fetchAndSubscribe.exceptionId = exceptionId(node);
+ } else {
+ if (subscription(subName, &rv) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) {
+ Instr sub;
+ sub.common.type = Instr::Subscribe;
+ sub.subscribe.offset = subscriptionIndex(subName);
+ sub.subscribe.reg = reg;
+ sub.subscribe.index = prop.notifySignalIndex();
+ bytecode << sub;
+ }
+
+ fetch.common.type = Instr::Fetch;
+ fetch.fetch.objectReg = reg;
+ fetch.fetch.index = idx;
+ fetch.fetch.output = reg;
+ fetch.fetch.exceptionId = exceptionId(node);
+ }
rv.type = prop.userType();
rv.metaObject = engine->metaObjectForType(rv.type);
diff --git a/src/declarative/qml/qdeclarativecompiler.cpp b/src/declarative/qml/qdeclarativecompiler.cpp
index a9d90f3..56af5f5 100644
--- a/src/declarative/qml/qdeclarativecompiler.cpp
+++ b/src/declarative/qml/qdeclarativecompiler.cpp
@@ -80,7 +80,7 @@
QT_BEGIN_NAMESPACE
DEFINE_BOOL_CONFIG_OPTION(compilerDump, QML_COMPILER_DUMP);
-DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATISTICS_DUMP);
+DEFINE_BOOL_CONFIG_OPTION(compilerStatDump, QML_COMPILER_STATS);
DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP);
using namespace QDeclarativeParser;
@@ -617,6 +617,7 @@ bool QDeclarativeCompiler::compile(QDeclarativeEngine *engine,
void QDeclarativeCompiler::compileTree(Object *tree)
{
compileState.root = tree;
+ componentStat.lineNumber = tree->location.start.line;
if (!buildObject(tree, BindingContext()) || !completeComponentBuild())
return;
@@ -2428,10 +2429,18 @@ bool QDeclarativeCompiler::buildDynamicMeta(QDeclarativeParser::Object *obj, Dyn
propertyType = QVariant::Color;
type = "QColor";
break;
+ case Object::DynamicProperty::Time:
+ propertyType = QVariant::Time;
+ type = "QTime";
+ break;
case Object::DynamicProperty::Date:
propertyType = QVariant::Date;
type = "QDate";
break;
+ case Object::DynamicProperty::DateTime:
+ propertyType = QVariant::DateTime;
+ type = "QDateTime";
+ break;
}
((QDeclarativeVMEMetaData *)dynamicData.data())->propertyCount++;
@@ -2776,7 +2785,7 @@ bool QDeclarativeCompiler::completeComponentBuild()
if (index != -1) {
binding.dataType = BindingReference::Experimental;
binding.compiledIndex = index;
- componentStat.optimizedBindings++;
+ componentStat.optimizedBindings.append(iter.key()->location);
continue;
}
@@ -2810,7 +2819,7 @@ bool QDeclarativeCompiler::completeComponentBuild()
QByteArray((const char *)expression.constData(),
expression.length() * sizeof(QChar));
- componentStat.scriptBindings++;
+ componentStat.scriptBindings.append(iter.key()->location);
}
if (bindingCompiler.isValid()) {
@@ -2832,8 +2841,44 @@ void QDeclarativeCompiler::dumpStats()
qWarning().nospace() << " Component Line " << stat.lineNumber;
qWarning().nospace() << " Total Objects: " << stat.objects;
qWarning().nospace() << " IDs Used: " << stat.ids;
- qWarning().nospace() << " Optimized Bindings: " << stat.optimizedBindings;
- qWarning().nospace() << " QScript Bindings: " << stat.scriptBindings;
+ qWarning().nospace() << " Optimized Bindings: " << stat.optimizedBindings.count();
+
+ {
+ QByteArray output;
+ for (int ii = 0; ii < stat.optimizedBindings.count(); ++ii) {
+ if (0 == (ii % 10)) {
+ if (ii) output.append("\n");
+ output.append(" ");
+ }
+
+ output.append("(");
+ output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.line));
+ output.append(":");
+ output.append(QByteArray::number(stat.optimizedBindings.at(ii).start.column));
+ output.append(") ");
+ }
+ if (!output.isEmpty())
+ qWarning().nospace() << output.constData();
+ }
+
+ qWarning().nospace() << " QScript Bindings: " << stat.scriptBindings.count();
+ {
+ QByteArray output;
+ for (int ii = 0; ii < stat.scriptBindings.count(); ++ii) {
+ if (0 == (ii % 10)) {
+ if (ii) output.append("\n");
+ output.append(" ");
+ }
+
+ output.append("(");
+ output.append(QByteArray::number(stat.scriptBindings.at(ii).start.line));
+ output.append(":");
+ output.append(QByteArray::number(stat.scriptBindings.at(ii).start.column));
+ output.append(") ");
+ }
+ if (!output.isEmpty())
+ qWarning().nospace() << output.constData();
+ }
}
}
diff --git a/src/declarative/qml/qdeclarativecompiler_p.h b/src/declarative/qml/qdeclarativecompiler_p.h
index a81259b..e5836d1 100644
--- a/src/declarative/qml/qdeclarativecompiler_p.h
+++ b/src/declarative/qml/qdeclarativecompiler_p.h
@@ -318,14 +318,13 @@ private:
struct ComponentStat
{
- ComponentStat()
- : ids(0), scriptBindings(0), optimizedBindings(0), objects(0) {}
+ ComponentStat() : ids(0), objects(0) {}
int lineNumber;
int ids;
- int scriptBindings;
- int optimizedBindings;
+ QList<QDeclarativeParser::LocationSpan> scriptBindings;
+ QList<QDeclarativeParser::LocationSpan> optimizedBindings;
int objects;
};
ComponentStat componentStat;
diff --git a/src/declarative/qml/qdeclarativecontext.cpp b/src/declarative/qml/qdeclarativecontext.cpp
index 2b8cf70..a9224ad 100644
--- a/src/declarative/qml/qdeclarativecontext.cpp
+++ b/src/declarative/qml/qdeclarativecontext.cpp
@@ -71,31 +71,30 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate()
Contexts allow data to be exposed to the QML components instantiated by the
QML engine.
- Each QDeclarativeContext contains a set of properties, distinct from
- its QObject properties, that allow data to be
- explicitly bound to a context by name. The context properties are defined or
- updated by calling QDeclarativeContext::setContextProperty(). The following example shows
- a Qt model being bound to a context and then accessed from a QML file.
+ Each QDeclarativeContext contains a set of properties, distinct from its QObject
+ properties, that allow data to be explicitly bound to a context by name. The
+ context properties are defined and updated by calling
+ QDeclarativeContext::setContextProperty(). The following example shows a Qt model
+ being bound to a context and then accessed from a QML file.
\code
QDeclarativeEngine engine;
- QDeclarativeContext context(engine.rootContext());
- context.setContextProperty("myModel", modelData);
+ QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
+ context->setContextProperty("myModel", modelData);
QDeclarativeComponent component(&engine, "ListView { model=myModel }");
- component.create(&context);
+ component.create(context);
\endcode
- To simplify binding and maintaining larger data sets, QObject's can be
- added to a QDeclarativeContext. These objects are known as the context's default
- objects. In this case all the properties of the QObject are
- made available by name in the context, as though they were all individually
- added by calling QDeclarativeContext::setContextProperty(). Changes to the property's
- values are detected through the property's notify signal. This method is
- also slightly more faster than manually adding property values.
+ To simplify binding and maintaining larger data sets, a context object can be set
+ on a QDeclarativeContext. All the properties of the context object are available
+ by name in the context, as though they were all individually added through calls
+ to QDeclarativeContext::setContextProperty(). Changes to the property's values are
+ detected through the property's notify signal. Setting a context object is both
+ faster and easier than manually adding and maintaing context property values.
- The following example has the same effect as the one above, but it is
- achieved using a default object.
+ The following example has the same effect as the previous one, but it uses a context
+ object.
\code
class MyDataSet : ... {
@@ -104,46 +103,42 @@ QDeclarativeContextPrivate::QDeclarativeContextPrivate()
...
};
- MyDataSet myDataSet;
+ MyDataSet *myDataSet = new MyDataSet;
QDeclarativeEngine engine;
- QDeclarativeContext context(engine.rootContext());
- context.setContextObject(&myDataSet);
+ QDeclarativeContext *context = new QDeclarativeContext(engine.rootContext());
+ context->setContextObject(myDataSet);
QDeclarativeComponent component(&engine, "ListView { model=myModel }");
- component.create(&context);
+ component.create(context);
\endcode
- Default objects added first take precedence over those added later. All properties
- added explicitly by QDeclarativeContext::setContextProperty() take precedence over default
- object properties.
+ All properties added explicitly by QDeclarativeContext::setContextProperty() take
+ precedence over context object's properties.
- Contexts are hierarchal, with the \l {QDeclarativeEngine::rootContext()}{root context}
- being created by the QDeclarativeEngine. A component instantiated in a given context
- has access to that context's data, as well as the data defined by its
- ancestor contexts. Data values (including those added implicitly by the
- default objects) in a context override those in ancestor contexts. Data
- that should be available to all components instantiated by the QDeclarativeEngine
- should be added to the \l {QDeclarativeEngine::rootContext()}{root context}.
+ Contexts form a hierarchy. The root of this heirarchy is the QDeclarativeEngine's
+ \l {QDeclarativeEngine::rootContext()}{root context}. A component instance can
+ access the data in its own context, as well as all its ancestor contexts. Data
+ can be made available to all instances by modifying the
+ \l {QDeclarativeEngine::rootContext()}{root context}.
- In the following example,
+ The following example defines two contexts - \c context1 and \c context2. The
+ second context overrides the "b" context property inherited from the first with a
+ new value.
\code
QDeclarativeEngine engine;
- QDeclarativeContext context1(engine.rootContext());
- QDeclarativeContext context2(&context1);
- QDeclarativeContext context3(&context2);
-
- context1.setContextProperty("a", 12);
- context2.setContextProperty("b", 13);
- context3.setContextProperty("a", 14);
- context3.setContextProperty("c", 14);
+ QDeclarativeContext *context1 = new QDeclarativeContext(engine.rootContext());
+ QDeclarativeContext *context2 = new QDeclarativeContext(context1);
+
+ context1->setContextProperty("a", 12);
+ context1->setContextProperty("b", 12);
+
+ context2->setContextProperty("b", 15);
\endcode
- a QML component instantiated in context1 would have access to the "a" data,
- a QML component instantiated in context2 would have access to the "a" and
- "b" data, and a QML component instantiated in context3 would have access to
- the "a", "b" and "c" data - although its "a" data would return 14, unlike
- that in context1 or context2.
+ While QML objects instantiated in a context are not strictly owned by that
+ context, their bindings are. If a context is destroyed, the property bindings of
+ outstanding QML objects will stop evaluating.
*/
/*! \internal */
diff --git a/src/declarative/qml/qdeclarativedom.cpp b/src/declarative/qml/qdeclarativedom.cpp
index 366750e..dec30a1 100644
--- a/src/declarative/qml/qdeclarativedom.cpp
+++ b/src/declarative/qml/qdeclarativedom.cpp
@@ -480,9 +480,15 @@ int QDeclarativeDomDynamicProperty::propertyType() const
case QDeclarativeParser::Object::DynamicProperty::Color:
return QMetaType::type("QColor");
+ case QDeclarativeParser::Object::DynamicProperty::Time:
+ return QMetaType::type("QTime");
+
case QDeclarativeParser::Object::DynamicProperty::Date:
return QMetaType::type("QDate");
+ case QDeclarativeParser::Object::DynamicProperty::DateTime:
+ return QMetaType::type("QDateTime");
+
case QDeclarativeParser::Object::DynamicProperty::Int:
return QMetaType::type("int");
diff --git a/src/declarative/qml/qdeclarativeengine.cpp b/src/declarative/qml/qdeclarativeengine.cpp
index 2f0ec24..bb742ee 100644
--- a/src/declarative/qml/qdeclarativeengine.cpp
+++ b/src/declarative/qml/qdeclarativeengine.cpp
@@ -178,10 +178,16 @@ QDeclarativeEnginePrivate::QDeclarativeEnginePrivate(QDeclarativeEngine *e)
#endif
foreach (const QString &path, QString::fromLatin1(envImportPath).split(pathSep, QString::SkipEmptyParts)) {
QString canonicalPath = QDir(path).canonicalPath();
- if (!canonicalPath.isEmpty() && !environmentImportPath.contains(canonicalPath))
- environmentImportPath.append(canonicalPath);
+ if (!canonicalPath.isEmpty() && !fileImportPath.contains(canonicalPath))
+ fileImportPath.append(canonicalPath);
}
}
+#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
+ QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
+ if (!builtinPath.isEmpty())
+ fileImportPath += builtinPath;
+#endif
+
}
QUrl QDeclarativeScriptEngine::resolvedUrl(QScriptContext *context, const QUrl& url)
@@ -580,13 +586,13 @@ void QDeclarativeEngine::removeImageProvider(const QString &providerId)
delete d->imageProviders.take(providerId);
}
-QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url)
+QImage QDeclarativeEnginePrivate::getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size)
{
QMutexLocker locker(&mutex);
QImage image;
QDeclarativeImageProvider *provider = imageProviders.value(url.host());
if (provider)
- image = provider->request(url.path().mid(1));
+ image = provider->request(url.path().mid(1), size, req_size);
return image;
}
@@ -1306,13 +1312,14 @@ QScriptValue QDeclarativeEnginePrivate::tint(QScriptContext *ctxt, QScriptEngine
QScriptValue QDeclarativeEnginePrivate::scriptValueFromVariant(const QVariant &val)
{
if (val.userType() == qMetaTypeId<QDeclarativeListReference>()) {
- QDeclarativeListReferencePrivate *p = QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
+ QDeclarativeListReferencePrivate *p =
+ QDeclarativeListReferencePrivate::get((QDeclarativeListReference*)val.constData());
if (p->object) {
return listClass->newList(p->property, p->propertyType);
} else {
return scriptEngine.nullValue();
}
- }
+ }
bool objOk;
QObject *obj = QDeclarativeMetaType::toQObject(val, &objOk);
@@ -1405,7 +1412,9 @@ struct QDeclarativeEnginePrivate::ImportedNamespace {
foreach (const QDeclarativeDirParser::Component &c, qmldircomponents) {
if (c.typeName == typeName) {
typeWasDeclaredInQmldir = true;
- if (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion)) {
+
+ // importing version -1 means import ALL versions
+ if ((vmaj == -1) || (c.majorVersion < vmaj || (c.majorVersion == vmaj && vmin >= c.minorVersion))) {
QUrl candidate = url.resolved(QUrl(c.fileName));
if (c.internal && base) {
if (base->resolved(QUrl(c.fileName)) != candidate)
@@ -1454,13 +1463,14 @@ public:
QDeclarativeDirComponents importExtension(const QString &absoluteFilePath, const QString &uri, QDeclarativeEngine *engine) {
QFile file(absoluteFilePath);
- QString dir = QFileInfo(file).path();
QString filecontent;
if (file.open(QFile::ReadOnly)) {
filecontent = QString::fromUtf8(file.readAll());
if (qmlImportTrace())
qDebug() << "QDeclarativeEngine::add: loaded" << absoluteFilePath;
}
+ QDir dir = QFileInfo(file).dir();
+
QDeclarativeDirParser qmldirParser;
qmldirParser.setSource(filecontent);
qmldirParser.parse();
@@ -1470,9 +1480,13 @@ public:
foreach (const QDeclarativeDirParser::Plugin &plugin, qmldirParser.plugins()) {
- QDir pluginDir(dir + QDir::separator() + plugin.path);
- if (dir.startsWith(QLatin1Char(':')))
+
+ QDir pluginDir = dir.absoluteFilePath(plugin.path);
+
+ // hack for resources, should probably go away
+ if (absoluteFilePath.startsWith(QLatin1Char(':')))
pluginDir = QDir(QCoreApplication::applicationDirPath());
+
QString resolvedFilePath =
QDeclarativeEnginePrivate::get(engine)
->resolvePlugin(pluginDir,
@@ -1492,29 +1506,7 @@ public:
if (dir.endsWith(QLatin1Char('/')) || dir.endsWith(QLatin1Char('\\')))
dir.chop(1);
- QStringList paths;
-
- if (!base.isEmpty()) {
- QString baseDir = QFileInfo(toLocalFileOrQrc(base)).path();
- paths += baseDir;
- }
-
- QString applicationDirPath = QCoreApplication::applicationDirPath();
- if (!applicationDirPath.isEmpty())
- paths += applicationDirPath;
-
- paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath;
-#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
- QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
-#else
- QString builtinPath;
-#endif
- if (!builtinPath.isEmpty())
- paths += builtinPath;
-
- // add fileImportPath last, this is *not* search order.
- paths += QDeclarativeEnginePrivate::get(engine)->fileImportPath;
-
+ QStringList paths = QDeclarativeEnginePrivate::get(engine)->fileImportPath;
qSort(paths.begin(), paths.end(), greaterThan); // Ensure subdirs preceed their parents.
QString stableRelativePath = dir;
@@ -1554,28 +1546,8 @@ public:
QString dir;
- // user import paths
- QStringList paths;
- // base..
- QString localFileOrQrc = toLocalFileOrQrc(base);
- QString localFileOrQrcPath = QFileInfo(localFileOrQrc).path();
- paths += localFileOrQrcPath;
- paths += QDeclarativeEnginePrivate::get(engine)->fileImportPath;
-
- QString applicationDirPath = QCoreApplication::applicationDirPath();
- if (!applicationDirPath.isEmpty())
- paths += applicationDirPath;
-
- paths += QDeclarativeEnginePrivate::get(engine)->environmentImportPath;
-#if (QT_VERSION >= QT_VERSION_CHECK(4,7,0))
- QString builtinPath = QLibraryInfo::location(QLibraryInfo::ImportsPath);
-#else
- QString builtinPath;
-#endif
- if (!builtinPath.isEmpty())
- paths += builtinPath;
-
- foreach (const QString &p, paths) {
+ foreach (const QString &p,
+ QDeclarativeEnginePrivate::get(engine)->fileImportPath) {
dir = p+QLatin1Char('/')+url;
QFileInfo fi(dir+QLatin1String("/qmldir"));
@@ -1807,18 +1779,9 @@ QUrl QDeclarativeEnginePrivate::Imports::baseUrl() const
Adds \a path as a directory where installed QML components are
defined in a URL-based directory structure.
- For example, if you add \c /opt/MyApp/lib/imports and then load QML
- that imports \c com.mycompany.Feature, then QDeclarativeEngine will look
- in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
- provided by that module. A \c qmldir file is required for definiting the
- type version mapping and possibly declarative extensions plugins.
-
- The engine searches in the base directory of the qml file, then
- the paths added via addImportPath(), then in the directory containing the
- application executable (QCoreApplication::applicationDirPath()),
- then the paths specified in the \c QML_IMPORT_PATH environment variable, then the
- builtin \c ImportsPath from QLibraryInfo.
+ The newly added \a path will be first in the importPathList().
+ \sa setImportPathList()
*/
void QDeclarativeEngine::addImportPath(const QString& path)
{
@@ -1828,6 +1791,43 @@ void QDeclarativeEngine::addImportPath(const QString& path)
d->fileImportPath.prepend(path);
}
+
+/*!
+ Returns the list of directories where the engine searches for
+ installed modules.
+
+ For example, if \c /opt/MyApp/lib/imports is in the path, then QML that
+ imports \c com.mycompany.Feature will cause the QDeclarativeEngine to look
+ in \c /opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
+ provided by that module. A \c qmldir file is required for defining the
+ type version mapping and possibly declarative extensions plugins.
+
+ By default, the list contains the paths specified in the \c QML_IMPORT_PATH environment
+ variable, then the builtin \c ImportsPath from QLibraryInfo.
+
+ \sa addImportPath() setImportPathList()
+*/
+QStringList QDeclarativeEngine::importPathList() const
+{
+ Q_D(const QDeclarativeEngine);
+ return d->fileImportPath;
+}
+
+/*!
+ Sets the list of directories where the engine searches for
+ installed modules.
+
+ By default, the list contains the paths specified in the \c QML_IMPORT_PATH environment
+ variable, then the builtin \c ImportsPath from QLibraryInfo.
+
+ \sa importPathList() addImportPath()
+ */
+void QDeclarativeEngine::setImportPathList(const QStringList &paths)
+{
+ Q_D(QDeclarativeEngine);
+ d->fileImportPath = paths;
+}
+
/*!
Imports the extension named \a fileName from the \a uri provided.
Returns true if the extension was successfully imported.
diff --git a/src/declarative/qml/qdeclarativeengine.h b/src/declarative/qml/qdeclarativeengine.h
index 19e81b6..b861c1b 100644
--- a/src/declarative/qml/qdeclarativeengine.h
+++ b/src/declarative/qml/qdeclarativeengine.h
@@ -77,7 +77,10 @@ public:
void clearComponentCache();
+ QStringList importPathList() const;
+ void setImportPathList(const QStringList &paths);
void addImportPath(const QString& dir);
+
bool importExtension(const QString &fileName, const QString &uri);
void setNetworkAccessManagerFactory(QDeclarativeNetworkAccessManagerFactory *);
diff --git a/src/declarative/qml/qdeclarativeengine_p.h b/src/declarative/qml/qdeclarativeengine_p.h
index 06b5027..5aff30d 100644
--- a/src/declarative/qml/qdeclarativeengine_p.h
+++ b/src/declarative/qml/qdeclarativeengine_p.h
@@ -225,7 +225,7 @@ public:
mutable QDeclarativeNetworkAccessManagerFactory *networkAccessManagerFactory;
QHash<QString,QDeclarativeImageProvider*> imageProviders;
- QImage getImageFromProvider(const QUrl &url);
+ QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
mutable QMutex mutex;
@@ -272,7 +272,6 @@ public:
};
- QStringList environmentImportPath;
QSet<QString> initializedPlugins;
QString resolvePlugin(const QDir &dir, const QString &baseName,
diff --git a/src/declarative/qml/qdeclarativefastproperties.cpp b/src/declarative/qml/qdeclarativefastproperties.cpp
new file mode 100644
index 0000000..088d329
--- /dev/null
+++ b/src/declarative/qml/qdeclarativefastproperties.cpp
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativefastproperties_p.h"
+
+#include <private/qdeclarativeitem_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// Adding entries to the QDeclarativeFastProperties class allows the QML
+// binding optimizer to bypass Qt's meta system and read and, more
+// importantly, subscribe to properties directly. Any property that is
+// primarily read from bindings is a candidate for inclusion as a fast
+// property.
+
+QDeclarativeFastProperties::QDeclarativeFastProperties()
+{
+ add(&QDeclarativeItem::staticMetaObject, QDeclarativeItem::staticMetaObject.indexOfProperty("parent"),
+ QDeclarativeItemPrivate::parentProperty);
+}
+
+int QDeclarativeFastProperties::accessorIndexForProperty(const QMetaObject *metaObject, int propertyIndex)
+{
+ Q_ASSERT(metaObject);
+ Q_ASSERT(propertyIndex >= 0);
+
+ // Find the "real" metaObject
+ while (metaObject->propertyOffset() > propertyIndex)
+ metaObject = metaObject->superClass();
+
+ QHash<QPair<const QMetaObject *, int>, int>::Iterator iter =
+ m_index.find(qMakePair(metaObject, propertyIndex));
+ if (iter != m_index.end())
+ return *iter;
+ else
+ return -1;
+}
+
+void QDeclarativeFastProperties::add(const QMetaObject *metaObject, int propertyIndex, Accessor accessor)
+{
+ Q_ASSERT(metaObject);
+ Q_ASSERT(propertyIndex >= 0);
+
+ // Find the "real" metaObject
+ while (metaObject->propertyOffset() > propertyIndex)
+ metaObject = metaObject->superClass();
+
+ QPair<const QMetaObject *, int> data = qMakePair(metaObject, propertyIndex);
+ int accessorIndex = m_accessors.count();
+ m_accessors.append(accessor);
+ m_index.insert(data, accessorIndex);
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativefastproperties_p.h b/src/declarative/qml/qdeclarativefastproperties_p.h
new file mode 100644
index 0000000..60df947
--- /dev/null
+++ b/src/declarative/qml/qdeclarativefastproperties_p.h
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEFASTPROPERTIES_P_H
+#define QDECLARATIVEFASTPROPERTIES_P_H
+
+#include <QtCore/qvector.h>
+#include <QtCore/qhash.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QObject;
+class QDeclarativeNotifierEndpoint;
+class QDeclarativeFastProperties
+{
+public:
+ typedef void (*Accessor)(QObject *object, void *output, QDeclarativeNotifierEndpoint *endpoint);
+
+ QDeclarativeFastProperties();
+
+ Accessor accessor(int index) const { return m_accessors.at(index); }
+ int accessorIndexForProperty(const QMetaObject *, int);
+
+private:
+ void add(const QMetaObject *, int, Accessor);
+
+ QHash<QPair<const QMetaObject *, int>, int> m_index;
+ QVector<Accessor> m_accessors;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECLARATIVEFASTPROPERTIES_P_H
diff --git a/src/declarative/qml/qdeclarativeimageprovider.cpp b/src/declarative/qml/qdeclarativeimageprovider.cpp
index 9ef8545..b992b9f 100644
--- a/src/declarative/qml/qdeclarativeimageprovider.cpp
+++ b/src/declarative/qml/qdeclarativeimageprovider.cpp
@@ -61,10 +61,14 @@ QDeclarativeImageProvider::~QDeclarativeImageProvider()
}
/*!
- \fn QImage QDeclarativeImageProvider::request(const QString &id)
+ \fn QImage QDeclarativeImageProvider::request(const QString &id, QSize *size, const QSize& requested_size)
Implement this method to return the image with \a id.
+ If \a requested_size is a valid size, resize the image to that size before returning.
+
+ In any case, \a size must be set to the (original) size of the image.
+
Note: this method may be called by multiple threads, so ensure the
implementation of this method is reentrant.
*/
diff --git a/src/declarative/qml/qdeclarativeimageprovider.h b/src/declarative/qml/qdeclarativeimageprovider.h
index 6ee7bcf..50b73fe 100644
--- a/src/declarative/qml/qdeclarativeimageprovider.h
+++ b/src/declarative/qml/qdeclarativeimageprovider.h
@@ -54,7 +54,7 @@ class Q_DECLARATIVE_EXPORT QDeclarativeImageProvider
{
public:
virtual ~QDeclarativeImageProvider();
- virtual QImage request(const QString &id) = 0;
+ virtual QImage request(const QString &id, QSize *size, const QSize& requested_size) = 0;
};
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativelist.h b/src/declarative/qml/qdeclarativelist.h
index ed402a8..219aa4b 100644
--- a/src/declarative/qml/qdeclarativelist.h
+++ b/src/declarative/qml/qdeclarativelist.h
@@ -54,8 +54,12 @@ QT_MODULE(Declarative)
class QObject;
struct QMetaObject;
+
+#ifndef QDECLARATIVELISTPROPERTY
+#define QDECLARATIVELISTPROPERTY
template<typename T>
-struct QDeclarativeListProperty {
+class QDeclarativeListProperty {
+public:
typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
@@ -106,6 +110,7 @@ private:
return ((QList<T *> *)p->data)->clear();
}
};
+#endif
class QDeclarativeEngine;
class QDeclarativeListReferencePrivate;
diff --git a/src/declarative/qml/qdeclarativeparser_p.h b/src/declarative/qml/qdeclarativeparser_p.h
index 476b027..f432024 100644
--- a/src/declarative/qml/qdeclarativeparser_p.h
+++ b/src/declarative/qml/qdeclarativeparser_p.h
@@ -203,7 +203,7 @@ namespace QDeclarativeParser
DynamicProperty();
DynamicProperty(const DynamicProperty &);
- enum Type { Variant, Int, Bool, Real, String, Url, Color, Date, Alias, Custom, CustomList };
+ enum Type { Variant, Int, Bool, Real, String, Url, Color, Time, Date, DateTime, Alias, Custom, CustomList };
bool isDefaultProperty;
Type type;
diff --git a/src/declarative/qml/qdeclarativeproperty.h b/src/declarative/qml/qdeclarativeproperty.h
index 73bccf3..8f6ea48 100644
--- a/src/declarative/qml/qdeclarativeproperty.h
+++ b/src/declarative/qml/qdeclarativeproperty.h
@@ -131,6 +131,11 @@ private:
};
typedef QList<QDeclarativeProperty> QDeclarativeProperties;
+inline uint qHash (const QDeclarativeProperty &key)
+{
+ return qHash(key.object()) + qHash(key.name());
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/declarative/qml/qdeclarativescriptparser.cpp b/src/declarative/qml/qdeclarativescriptparser.cpp
index 49bd3b7..9fff294 100644
--- a/src/declarative/qml/qdeclarativescriptparser.cpp
+++ b/src/declarative/qml/qdeclarativescriptparser.cpp
@@ -528,9 +528,14 @@ bool ProcessAST::visit(AST::UiPublicMember *node)
{ "string", Object::DynamicProperty::String, "QString" },
{ "url", Object::DynamicProperty::Url, "QUrl" },
{ "color", Object::DynamicProperty::Color, "QColor" },
- { "date", Object::DynamicProperty::Date, "QDate" },
- { "var", Object::DynamicProperty::Variant, "QVariant" },
- { "variant", Object::DynamicProperty::Variant, "QVariant" }
+ // Internally QTime, QDate and QDateTime are all supported.
+ // To be more consistent with JavaScript we expose only
+ // QDateTime as it matches closely with the Date JS type.
+ // We also call it "date" to match.
+ // { "time", Object::DynamicProperty::Time, "QTime" },
+ // { "date", Object::DynamicProperty::Date, "QDate" },
+ { "date", Object::DynamicProperty::DateTime, "QDateTime" },
+ { "var", Object::DynamicProperty::Variant, "QVariant" }
};
const int propTypeNameToTypesCount = sizeof(propTypeNameToTypes) /
sizeof(propTypeNameToTypes[0]);
diff --git a/src/declarative/qml/qdeclarativesqldatabase.cpp b/src/declarative/qml/qdeclarativesqldatabase.cpp
index 2d5f096..37d2d5b 100644
--- a/src/declarative/qml/qdeclarativesqldatabase.cpp
+++ b/src/declarative/qml/qdeclarativesqldatabase.cpp
@@ -279,7 +279,7 @@ static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScri
QString foundvers = context->thisObject().property(QLatin1String("version")).toString();
if (from_version!=foundvers) {
- THROW_SQL(2,QDeclarativeEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(foundvers));
+ THROW_SQL(VERSION_ERR,QDeclarativeEngine::tr("Version mismatch: expected %1, found %2").arg(from_version).arg(foundvers));
return engine->undefinedValue();
}
@@ -293,7 +293,7 @@ static QScriptValue qmlsqldatabase_change_version(QScriptContext *context, QScri
} else {
if (!db.commit()) {
db.rollback();
- THROW_SQL(0,QDeclarativeEngine::tr("SQL transaction failed"));
+ THROW_SQL(UNKNOWN_ERR,QDeclarativeEngine::tr("SQL transaction failed"));
} else {
ok = true;
}
diff --git a/src/declarative/qml/qdeclarativevmemetaobject.cpp b/src/declarative/qml/qdeclarativevmemetaobject.cpp
index f9c99ee..9a7bdd6 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject.cpp
+++ b/src/declarative/qml/qdeclarativevmemetaobject.cpp
@@ -47,19 +47,340 @@
#include "qdeclarativeexpression_p.h"
#include "qdeclarativecontext_p.h"
-#include <QColor>
-#include <QDate>
-#include <QtCore/qlist.h>
-#include <QtCore/qdebug.h>
+Q_DECLARE_METATYPE(QScriptValue);
QT_BEGIN_NAMESPACE
+class QDeclarativeVMEVariant
+{
+public:
+ inline QDeclarativeVMEVariant();
+ inline ~QDeclarativeVMEVariant();
+
+ inline const void *dataPtr() const;
+ inline void *dataPtr();
+ inline int dataType() const;
+
+ inline QObject *asQObject();
+ inline const QVariant &asQVariant();
+ inline int asInt();
+ inline bool asBool();
+ inline double asDouble();
+ inline const QString &asQString();
+ inline const QUrl &asQUrl();
+ inline const QColor &asQColor();
+ inline const QTime &asQTime();
+ inline const QDate &asQDate();
+ inline const QDateTime &asQDateTime();
+ inline const QScriptValue &asQScriptValue();
+
+ inline void setValue(QObject *);
+ inline void setValue(const QVariant &);
+ inline void setValue(int);
+ inline void setValue(bool);
+ inline void setValue(double);
+ inline void setValue(const QString &);
+ inline void setValue(const QUrl &);
+ inline void setValue(const QColor &);
+ inline void setValue(const QTime &);
+ inline void setValue(const QDate &);
+ inline void setValue(const QDateTime &);
+ inline void setValue(const QScriptValue &);
+
+private:
+ int type;
+ void *data[4]; // Large enough to hold all types
+
+ inline void cleanup();
+};
+
+QDeclarativeVMEVariant::QDeclarativeVMEVariant()
+: type(QVariant::Invalid)
+{
+}
+
+QDeclarativeVMEVariant::~QDeclarativeVMEVariant()
+{
+ cleanup();
+}
+
+void QDeclarativeVMEVariant::cleanup()
+{
+ if (type == QVariant::Invalid) {
+ } else if (type == QMetaType::QObjectStar ||
+ type == QMetaType::Int ||
+ type == QMetaType::Bool ||
+ type == QMetaType::Double) {
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QString) {
+ ((QString *)dataPtr())->~QString();
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QUrl) {
+ ((QUrl *)dataPtr())->~QUrl();
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QColor) {
+ ((QColor *)dataPtr())->~QColor();
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QTime) {
+ ((QTime *)dataPtr())->~QTime();
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QDate) {
+ ((QDate *)dataPtr())->~QDate();
+ type = QVariant::Invalid;
+ } else if (type == QMetaType::QDateTime) {
+ ((QDateTime *)dataPtr())->~QDateTime();
+ type = QVariant::Invalid;
+ } else if (type == qMetaTypeId<QVariant>()) {
+ ((QVariant *)dataPtr())->~QVariant();
+ type = QVariant::Invalid;
+ } else if (type == qMetaTypeId<QScriptValue>()) {
+ ((QScriptValue *)dataPtr())->~QScriptValue();
+ type = QVariant::Invalid;
+ }
+
+}
+
+int QDeclarativeVMEVariant::dataType() const
+{
+ return type;
+}
+
+const void *QDeclarativeVMEVariant::dataPtr() const
+{
+ return &data;
+}
+
+void *QDeclarativeVMEVariant::dataPtr()
+{
+ return &data;
+}
+
+QObject *QDeclarativeVMEVariant::asQObject()
+{
+ if (type != QMetaType::QObjectStar)
+ setValue((QObject *)0);
+
+ return *(QObject **)(dataPtr());
+}
+
+const QVariant &QDeclarativeVMEVariant::asQVariant()
+{
+ if (type != QMetaType::QVariant)
+ setValue(QVariant());
+
+ return *(QVariant *)(dataPtr());
+}
+
+int QDeclarativeVMEVariant::asInt()
+{
+ if (type != QMetaType::Int)
+ setValue(int(0));
+
+ return *(int *)(dataPtr());
+}
+
+bool QDeclarativeVMEVariant::asBool()
+{
+ if (type != QMetaType::Bool)
+ setValue(bool(false));
+
+ return *(bool *)(dataPtr());
+}
+
+double QDeclarativeVMEVariant::asDouble()
+{
+ if (type != QMetaType::Double)
+ setValue(double(0));
+
+ return *(double *)(dataPtr());
+}
+
+const QString &QDeclarativeVMEVariant::asQString()
+{
+ if (type != QMetaType::QString)
+ setValue(QString());
+
+ return *(QString *)(dataPtr());
+}
+
+const QUrl &QDeclarativeVMEVariant::asQUrl()
+{
+ if (type != QMetaType::QUrl)
+ setValue(QUrl());
+
+ return *(QUrl *)(dataPtr());
+}
+
+const QColor &QDeclarativeVMEVariant::asQColor()
+{
+ if (type != QMetaType::QColor)
+ setValue(QColor());
+
+ return *(QColor *)(dataPtr());
+}
+
+const QTime &QDeclarativeVMEVariant::asQTime()
+{
+ if (type != QMetaType::QTime)
+ setValue(QTime());
+
+ return *(QTime *)(dataPtr());
+}
+
+const QDate &QDeclarativeVMEVariant::asQDate()
+{
+ if (type != QMetaType::QDate)
+ setValue(QDate());
+
+ return *(QDate *)(dataPtr());
+}
+
+const QDateTime &QDeclarativeVMEVariant::asQDateTime()
+{
+ if (type != QMetaType::QDateTime)
+ setValue(QDateTime());
+
+ return *(QDateTime *)(dataPtr());
+}
+
+const QScriptValue &QDeclarativeVMEVariant::asQScriptValue()
+{
+ if (type != qMetaTypeId<QScriptValue>())
+ setValue(QScriptValue());
+
+ return *(QScriptValue *)(dataPtr());
+}
+
+void QDeclarativeVMEVariant::setValue(QObject *v)
+{
+ if (type != QMetaType::QObjectStar) {
+ cleanup();
+ type = QMetaType::QObjectStar;
+ }
+ *(QObject **)(dataPtr()) = v;
+}
+
+void QDeclarativeVMEVariant::setValue(const QVariant &v)
+{
+ if (type != qMetaTypeId<QVariant>()) {
+ cleanup();
+ type = qMetaTypeId<QVariant>();
+ new (dataPtr()) QVariant(v);
+ } else {
+ *(QVariant *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(int v)
+{
+ if (type != QMetaType::Int) {
+ cleanup();
+ type = QMetaType::Int;
+ }
+ *(int *)(dataPtr()) = v;
+}
+
+void QDeclarativeVMEVariant::setValue(bool v)
+{
+ if (type != QMetaType::Bool) {
+ cleanup();
+ type = QMetaType::Bool;
+ }
+ *(bool *)(dataPtr()) = v;
+}
+
+void QDeclarativeVMEVariant::setValue(double v)
+{
+ if (type != QMetaType::Double) {
+ cleanup();
+ type = QMetaType::Double;
+ }
+ *(double *)(dataPtr()) = v;
+}
+
+void QDeclarativeVMEVariant::setValue(const QString &v)
+{
+ if (type != QMetaType::QString) {
+ cleanup();
+ type = QMetaType::QString;
+ new (dataPtr()) QString(v);
+ } else {
+ *(QString *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(const QUrl &v)
+{
+ if (type != QMetaType::QUrl) {
+ cleanup();
+ type = QMetaType::QUrl;
+ new (dataPtr()) QUrl(v);
+ } else {
+ *(QUrl *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(const QColor &v)
+{
+ if (type != QMetaType::QColor) {
+ cleanup();
+ type = QMetaType::QColor;
+ new (dataPtr()) QColor(v);
+ } else {
+ *(QColor *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(const QTime &v)
+{
+ if (type != QMetaType::QTime) {
+ cleanup();
+ type = QMetaType::QTime;
+ new (dataPtr()) QTime(v);
+ } else {
+ *(QTime *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(const QDate &v)
+{
+ if (type != QMetaType::QDate) {
+ cleanup();
+ type = QMetaType::QDate;
+ new (dataPtr()) QDate(v);
+ } else {
+ *(QDate *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(const QDateTime &v)
+{
+ if (type != QMetaType::QDateTime) {
+ cleanup();
+ type = QMetaType::QDateTime;
+ new (dataPtr()) QDateTime(v);
+ } else {
+ *(QDateTime *)(dataPtr()) = v;
+ }
+}
+
+void QDeclarativeVMEVariant::setValue(const QScriptValue &v)
+{
+ if (type != qMetaTypeId<QScriptValue>()) {
+ cleanup();
+ type = qMetaTypeId<QScriptValue>();
+ new (dataPtr()) QScriptValue(v);
+ } else {
+ *(QScriptValue *)(dataPtr()) = v;
+ }
+}
+
QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
const QMetaObject *other,
const QDeclarativeVMEMetaData *meta,
QDeclarativeCompiledData *cdata)
: object(obj), compiledData(cdata), ctxt(QDeclarativeDeclarativeData::get(obj)->outerContext),
- metaData(meta), methods(0), parent(0)
+ metaData(meta), data(0), methods(0), parent(0)
{
compiledData->addref();
@@ -74,20 +395,18 @@ QDeclarativeVMEMetaObject::QDeclarativeVMEMetaObject(QObject *obj,
propOffset = QAbstractDynamicMetaObject::propertyOffset();
methodOffset = QAbstractDynamicMetaObject::methodOffset();
- data = new QVariant[metaData->propertyCount];
- aConnected.resize(metaData->aliasCount);
+ data = new QDeclarativeVMEVariant[metaData->propertyCount];
+ aConnected.resize(metaData->aliasCount);
int list_type = qMetaTypeId<QDeclarativeListProperty<QObject> >();
+
// ### Optimize
for (int ii = 0; ii < metaData->propertyCount; ++ii) {
int t = (metaData->propertyData() + ii)->propertyType;
if (t == list_type) {
- listProperties.append(new List(methodOffset + ii));
- data[ii] = QVariant::fromValue(QDeclarativeListProperty<QObject>(obj, listProperties.last(), list_append,
- list_count, list_at, list_clear));
- } else if (t != -1) {
- data[ii] = QVariant((QVariant::Type)t);
- }
+ listProperties.append(List(methodOffset + ii));
+ data[ii].setValue(listProperties.count() - 1);
+ }
}
}
@@ -95,7 +414,6 @@ QDeclarativeVMEMetaObject::~QDeclarativeVMEMetaObject()
{
compiledData->release();
delete parent;
- qDeleteAll(listProperties);
delete [] data;
delete [] methods;
}
@@ -145,11 +463,10 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (t == -1) {
if (c == QMetaObject::ReadProperty) {
- *reinterpret_cast<QVariant *>(a[0]) = data[id];
+ *reinterpret_cast<QVariant *>(a[0]) = readVarPropertyAsVariant(id);
} else if (c == QMetaObject::WriteProperty) {
- needActivate =
- (data[id] != *reinterpret_cast<QVariant *>(a[0]));
- data[id] = *reinterpret_cast<QVariant *>(a[0]);
+ needActivate = (data[id].asQVariant() != *reinterpret_cast<QVariant *>(a[0]));
+ data[id].setValue(*reinterpret_cast<QVariant *>(a[0]));
}
} else {
@@ -157,42 +474,86 @@ int QDeclarativeVMEMetaObject::metaCall(QMetaObject::Call c, int _id, void **a)
if (c == QMetaObject::ReadProperty) {
switch(t) {
case QVariant::Int:
- *reinterpret_cast<int *>(a[0]) = data[id].toInt();
+ *reinterpret_cast<int *>(a[0]) = data[id].asInt();
break;
case QVariant::Bool:
- *reinterpret_cast<bool *>(a[0]) = data[id].toBool();
+ *reinterpret_cast<bool *>(a[0]) = data[id].asBool();
break;
case QVariant::Double:
- *reinterpret_cast<double *>(a[0]) = data[id].toDouble();
+ *reinterpret_cast<double *>(a[0]) = data[id].asDouble();
break;
case QVariant::String:
- *reinterpret_cast<QString *>(a[0]) = data[id].toString();
+ *reinterpret_cast<QString *>(a[0]) = data[id].asQString();
break;
case QVariant::Url:
- *reinterpret_cast<QUrl *>(a[0]) = data[id].toUrl();
+ *reinterpret_cast<QUrl *>(a[0]) = data[id].asQUrl();
break;
case QVariant::Color:
- *reinterpret_cast<QColor *>(a[0]) = data[id].value<QColor>();
+ *reinterpret_cast<QColor *>(a[0]) = data[id].asQColor();
break;
case QVariant::Date:
- *reinterpret_cast<QDate *>(a[0]) = data[id].toDate();
+ *reinterpret_cast<QDate *>(a[0]) = data[id].asQDate();
+ break;
+ case QVariant::DateTime:
+ *reinterpret_cast<QDateTime *>(a[0]) = data[id].asQDateTime();
break;
case QMetaType::QObjectStar:
- *reinterpret_cast<QObject **>(a[0]) = data[id].value<QObject*>();
+ *reinterpret_cast<QObject **>(a[0]) = data[id].asQObject();
break;
default:
break;
}
if (t == qMetaTypeId<QDeclarativeListProperty<QObject> >()) {
+ int listIndex = data[id].asInt();
+ const List *list = &listProperties.at(listIndex);
*reinterpret_cast<QDeclarativeListProperty<QObject> *>(a[0]) =
- data[id].value<QDeclarativeListProperty<QObject> >();
+ QDeclarativeListProperty<QObject>(object, (void *)list,
+ list_append, list_count, list_at,
+ list_clear);
}
} else if (c == QMetaObject::WriteProperty) {
- QVariant value = QVariant((QVariant::Type)data[id].type(), a[0]);
- needActivate = (data[id] != value);
- data[id] = value;
+ switch(t) {
+ case QVariant::Int:
+ needActivate = *reinterpret_cast<int *>(a[0]) != data[id].asInt();
+ data[id].setValue(*reinterpret_cast<int *>(a[0]));
+ break;
+ case QVariant::Bool:
+ needActivate = *reinterpret_cast<bool *>(a[0]) != data[id].asBool();
+ data[id].setValue(*reinterpret_cast<bool *>(a[0]));
+ break;
+ case QVariant::Double:
+ needActivate = *reinterpret_cast<double *>(a[0]) != data[id].asDouble();
+ data[id].setValue(*reinterpret_cast<double *>(a[0]));
+ break;
+ case QVariant::String:
+ needActivate = *reinterpret_cast<QString *>(a[0]) != data[id].asQString();
+ data[id].setValue(*reinterpret_cast<QString *>(a[0]));
+ break;
+ case QVariant::Url:
+ needActivate = *reinterpret_cast<QUrl *>(a[0]) != data[id].asQUrl();
+ data[id].setValue(*reinterpret_cast<QUrl *>(a[0]));
+ break;
+ case QVariant::Color:
+ needActivate = *reinterpret_cast<QColor *>(a[0]) != data[id].asQColor();
+ data[id].setValue(*reinterpret_cast<QColor *>(a[0]));
+ break;
+ case QVariant::Date:
+ needActivate = *reinterpret_cast<QDate *>(a[0]) != data[id].asQDate();
+ data[id].setValue(*reinterpret_cast<QDate *>(a[0]));
+ break;
+ case QVariant::DateTime:
+ needActivate = *reinterpret_cast<QDateTime *>(a[0]) != data[id].asQDateTime();
+ data[id].setValue(*reinterpret_cast<QDateTime *>(a[0]));
+ break;
+ case QMetaType::QObjectStar:
+ needActivate = *reinterpret_cast<QObject **>(a[0]) != data[id].asQObject();
+ data[id].setValue(*reinterpret_cast<QObject **>(a[0]));
+ break;
+ default:
+ break;
+ }
}
}
@@ -316,6 +677,28 @@ QScriptValue QDeclarativeVMEMetaObject::method(int index)
return methods[index];
}
+QScriptValue QDeclarativeVMEMetaObject::readVarProperty(int id)
+{
+ if (data[id].dataType() == qMetaTypeId<QScriptValue>())
+ return data[id].asQScriptValue();
+ else
+ return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueFromVariant(data[id].asQVariant());
+}
+
+QVariant QDeclarativeVMEMetaObject::readVarPropertyAsVariant(int id)
+{
+ if (data[id].dataType() == qMetaTypeId<QScriptValue>())
+ return QDeclarativeEnginePrivate::get(ctxt->engine)->scriptValueToVariant(data[id].asQScriptValue());
+ else
+ return data[id].asQVariant();
+}
+
+void QDeclarativeVMEMetaObject::writeVarProperty(int id, const QScriptValue &value)
+{
+ data[id].setValue(value);
+ activate(object, methodOffset + id, 0);
+}
+
void QDeclarativeVMEMetaObject::listChanged(int id)
{
activate(object, methodOffset + id, 0);
@@ -364,4 +747,22 @@ QScriptValue QDeclarativeVMEMetaObject::vmeMethod(int index)
return method(index - methodOffset - plainSignals);
}
+QScriptValue QDeclarativeVMEMetaObject::vmeProperty(int index)
+{
+ if (index < propOffset) {
+ Q_ASSERT(parent);
+ return static_cast<QDeclarativeVMEMetaObject *>(parent)->vmeProperty(index);
+ }
+ return readVarProperty(index - propOffset);
+}
+
+void QDeclarativeVMEMetaObject::setVMEProperty(int index, const QScriptValue &v)
+{
+ if (index < propOffset) {
+ Q_ASSERT(parent);
+ static_cast<QDeclarativeVMEMetaObject *>(parent)->setVMEProperty(index, v);
+ }
+ return writeVarProperty(index - propOffset, v);
+}
+
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qdeclarativevmemetaobject_p.h b/src/declarative/qml/qdeclarativevmemetaobject_p.h
index e11f6fa..839f0cd 100644
--- a/src/declarative/qml/qdeclarativevmemetaobject_p.h
+++ b/src/declarative/qml/qdeclarativevmemetaobject_p.h
@@ -58,6 +58,10 @@
#include <QtCore/QMetaObject>
#include <QtCore/QBitArray>
#include <QtCore/QPair>
+#include <QtGui/QColor>
+#include <QtCore/QDate>
+#include <QtCore/qlist.h>
+#include <QtCore/qdebug.h>
#include <private/qobject_p.h>
@@ -106,6 +110,7 @@ struct QDeclarativeVMEMetaData
}
};
+class QDeclarativeVMEVariant;
class QDeclarativeRefCount;
class QDeclarativeVMEMetaObject : public QAbstractDynamicMetaObject
{
@@ -116,6 +121,9 @@ public:
void registerInterceptor(int index, int valueIndex, QDeclarativePropertyValueInterceptor *interceptor);
QScriptValue vmeMethod(int index);
+ QScriptValue vmeProperty(int index);
+ void setVMEProperty(int index, const QScriptValue &);
+
protected:
virtual int metaCall(QMetaObject::Call _c, int _id, void **_a);
@@ -128,7 +136,8 @@ private:
int propOffset;
int methodOffset;
- QVariant *data;
+ QDeclarativeVMEVariant *data;
+
QBitArray aConnected;
QBitArray aInterceptors;
QHash<int, QPair<int, QDeclarativePropertyValueInterceptor*> > interceptors;
@@ -136,6 +145,10 @@ private:
QScriptValue *methods;
QScriptValue method(int);
+ QScriptValue readVarProperty(int);
+ QVariant readVarPropertyAsVariant(int);
+ void writeVarProperty(int, const QScriptValue &);
+
QAbstractDynamicMetaObject *parent;
void listChanged(int);
@@ -145,7 +158,7 @@ private:
List(int lpi) : notifyIndex(lpi) {}
int notifyIndex;
};
- QList<List *> listProperties;
+ QList<List> listProperties;
static void list_append(QDeclarativeListProperty<QObject> *, QObject *);
static int list_count(QDeclarativeListProperty<QObject> *);
diff --git a/src/declarative/qml/qdeclarativeworkerscript.cpp b/src/declarative/qml/qdeclarativeworkerscript.cpp
index a7ed358..628681f 100644
--- a/src/declarative/qml/qdeclarativeworkerscript.cpp
+++ b/src/declarative/qml/qdeclarativeworkerscript.cpp
@@ -437,8 +437,12 @@ QDeclarativeWorkerScriptEngine::QDeclarativeWorkerScriptEngine(QDeclarativeEngin
QDeclarativeWorkerScriptEngine::~QDeclarativeWorkerScriptEngine()
{
+ d->m_lock.lock();
qDeleteAll(d->workers);
- delete d; d = 0;
+ d->workers.clear();
+ d->m_lock.unlock();
+
+ d->deleteLater();
}
QDeclarativeWorkerScriptEnginePrivate::WorkerScript::WorkerScript()
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index 49888c3..e2f0c67 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -31,11 +31,11 @@ SOURCES += \
$$PWD/qdeclarativerewrite.cpp \
$$PWD/qdeclarativevaluetype.cpp \
$$PWD/qdeclarativecompiledbindings.cpp \
+ $$PWD/qdeclarativefastproperties.cpp \
$$PWD/qdeclarativexmlhttprequest.cpp \
$$PWD/qdeclarativesqldatabase.cpp \
$$PWD/qmetaobjectbuilder.cpp \
$$PWD/qdeclarativewatcher.cpp \
- $$PWD/qdeclarativescript.cpp \
$$PWD/qdeclarativecleanup.cpp \
$$PWD/qdeclarativepropertycache.cpp \
$$PWD/qdeclarativenotifier.cpp \
@@ -103,6 +103,7 @@ HEADERS += \
$$PWD/qbitfield_p.h \
$$PWD/qdeclarativevaluetype_p.h \
$$PWD/qdeclarativecompiledbindings_p.h \
+ $$PWD/qdeclarativefastproperties_p.h \
$$PWD/qdeclarativexmlhttprequest_p.h \
$$PWD/qdeclarativesqldatabase_p.h \
$$PWD/qmetaobjectbuilder_p.h \
diff --git a/src/declarative/util/qdeclarativeanimation.cpp b/src/declarative/util/qdeclarativeanimation.cpp
index bad142c..ba1444e 100644
--- a/src/declarative/util/qdeclarativeanimation.cpp
+++ b/src/declarative/util/qdeclarativeanimation.cpp
@@ -1078,15 +1078,26 @@ void QDeclarativePropertyAction::transition(QDeclarativeStateActions &actions,
QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QObject *parent)
: QDeclarativePropertyAnimation(parent)
{
- Q_D(QDeclarativePropertyAnimation);
- d->interpolatorType = QMetaType::QReal;
- d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+ init();
+}
+
+QDeclarativeNumberAnimation::QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent)
+: QDeclarativePropertyAnimation(dd, parent)
+{
+ init();
}
QDeclarativeNumberAnimation::~QDeclarativeNumberAnimation()
{
}
+void QDeclarativeNumberAnimation::init()
+{
+ Q_D(QDeclarativePropertyAnimation);
+ d->interpolatorType = QMetaType::QReal;
+ d->interpolator = QVariantAnimationPrivate::getInterpolator(d->interpolatorType);
+}
+
/*!
\qmlproperty real NumberAnimation::from
This property holds the starting value.
@@ -2237,8 +2248,10 @@ void QDeclarativePropertyAnimation::transition(QDeclarativeStateActions &actions
}
d->va->setAnimValue(data, QAbstractAnimation::DeleteWhenStopped);
d->va->setFromSourcedValue(&data->fromSourced);
+ d->actions = &data->actions;
} else {
delete data;
+ d->actions = 0;
}
}
diff --git a/src/declarative/util/qdeclarativeanimation_p.h b/src/declarative/util/qdeclarativeanimation_p.h
index 816520e..f620786 100644
--- a/src/declarative/util/qdeclarativeanimation_p.h
+++ b/src/declarative/util/qdeclarativeanimation_p.h
@@ -251,8 +251,8 @@ public:
QDeclarativePropertyAnimation(QObject *parent=0);
virtual ~QDeclarativePropertyAnimation();
- int duration() const;
- void setDuration(int);
+ virtual int duration() const;
+ virtual void setDuration(int);
QVariant from() const;
void setFrom(const QVariant &);
@@ -326,6 +326,12 @@ public:
qreal to() const;
void setTo(qreal);
+
+protected:
+ QDeclarativeNumberAnimation(QDeclarativePropertyAnimationPrivate &dd, QObject *parent);
+
+private:
+ void init();
};
class Q_AUTOTEST_EXPORT QDeclarativeVector3dAnimation : public QDeclarativePropertyAnimation
diff --git a/src/declarative/util/qdeclarativeanimation_p_p.h b/src/declarative/util/qdeclarativeanimation_p_p.h
index 3908e50..8bcbeff 100644
--- a/src/declarative/util/qdeclarativeanimation_p_p.h
+++ b/src/declarative/util/qdeclarativeanimation_p_p.h
@@ -100,17 +100,11 @@ class QActionAnimation : public QAbstractAnimation
{
Q_OBJECT
public:
- QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped), running(false) {}
+ QActionAnimation(QObject *parent = 0) : QAbstractAnimation(parent), animAction(0), policy(KeepWhenStopped) {}
QActionAnimation(QAbstractAnimationAction *action, QObject *parent = 0)
- : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped), running(false) {}
+ : QAbstractAnimation(parent), animAction(action), policy(KeepWhenStopped) {}
~QActionAnimation() { if (policy == DeleteWhenStopped) { delete animAction; animAction = 0; } }
virtual int duration() const { return 0; }
- void clearAnimAction()
- {
- if (policy == DeleteWhenStopped)
- delete animAction;
- animAction = 0;
- }
void setAnimAction(QAbstractAnimationAction *action, DeletionPolicy p)
{
if (state() == Running)
@@ -127,26 +121,18 @@ protected:
{
if (newState == Running) {
if (animAction) {
- running = true;
animAction->doAction();
- running = false;
if (state() == Stopped && policy == DeleteWhenStopped) {
delete animAction;
animAction = 0;
}
}
- } /*else if (newState == Stopped && policy == DeleteWhenStopped) {
- if (!running) {
- delete animAction;
- animAction = 0;
- }
- }*/
+ }
}
private:
QAbstractAnimationAction *animAction;
DeletionPolicy policy;
- bool running;
};
class QDeclarativeBulkValueUpdater
@@ -192,11 +178,7 @@ protected:
//check for new from every loop
if (fromSourced)
*fromSourced = false;
- } /*else if (newState == Stopped && policy == DeleteWhenStopped) {
- delete animValue;
- animValue = 0;
- }*/ //### we get a stop each loop if we are in a group
- //### top-level animation is the only reliable one for this
+ }
}
private:
@@ -322,7 +304,7 @@ class QDeclarativePropertyAnimationPrivate : public QDeclarativeAbstractAnimatio
public:
QDeclarativePropertyAnimationPrivate()
: QDeclarativeAbstractAnimationPrivate(), target(0), fromSourced(false), fromIsDefined(false), toIsDefined(false),
- rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0) {}
+ rangeIsSet(false), defaultToInterpolatorType(0), interpolatorType(0), interpolator(0), va(0), actions(0) {}
void init();
@@ -348,6 +330,9 @@ public:
QDeclarativeBulkValueAnimator *va;
+ // for animations that dont use the QDeclarativeBulkValueAnimator
+ QDeclarativeStateActions *actions;
+
static QVariant interpolateVariant(const QVariant &from, const QVariant &to, qreal progress);
static void convertVariant(QVariant &variant, int type);
};
diff --git a/src/declarative/util/qdeclarativebehavior.cpp b/src/declarative/util/qdeclarativebehavior.cpp
index 1e000df..87d6836 100644
--- a/src/declarative/util/qdeclarativebehavior.cpp
+++ b/src/declarative/util/qdeclarativebehavior.cpp
@@ -47,15 +47,12 @@
#include <qdeclarativecontext.h>
#include <qdeclarativeinfo.h>
#include <qdeclarativeproperty_p.h>
-
-#include <QtCore/qparallelanimationgroup.h>
+#include <qdeclarativeguard_p.h>
#include <private/qobject_p.h>
QT_BEGIN_NAMESPACE
-
-
class QDeclarativeBehaviorPrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QDeclarativeBehavior)
@@ -64,7 +61,7 @@ public:
QDeclarativeProperty property;
QVariant currentValue;
- QDeclarativeAbstractAnimation *animation;
+ QDeclarativeGuard<QDeclarativeAbstractAnimation> animation;
bool enabled;
};
@@ -166,7 +163,8 @@ void QDeclarativeBehavior::write(const QVariant &value)
d->currentValue = d->property.read();
- d->animation->qtAnimation()->stop();
+ if (d->animation->qtAnimation()->duration() != -1)
+ d->animation->qtAnimation()->stop();
QDeclarativeStateOperation::ActionList actions;
QDeclarativeAction action;
@@ -176,11 +174,10 @@ void QDeclarativeBehavior::write(const QVariant &value)
actions << action;
QList<QDeclarativeProperty> after;
- if (d->animation)
- d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward);
+ d->animation->transition(actions, after, QDeclarativeAbstractAnimation::Forward);
d->animation->qtAnimation()->start();
if (!after.contains(d->property))
- QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
+ QDeclarativePropertyPrivate::write(d->property, value, QDeclarativePropertyPrivate::BypassInterceptor | QDeclarativePropertyPrivate::DontRemoveBinding);
}
void QDeclarativeBehavior::setTarget(const QDeclarativeProperty &property)
diff --git a/src/declarative/util/qdeclarativeeasefollow.cpp b/src/declarative/util/qdeclarativeeasefollow.cpp
deleted file mode 100644
index ee181dd..0000000
--- a/src/declarative/util/qdeclarativeeasefollow.cpp
+++ /dev/null
@@ -1,537 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qdeclarativeeasefollow_p.h"
-
-#include "qdeclarativeanimation_p_p.h"
-
-#include <qdeclarativeproperty.h>
-
-#include <QtCore/qdebug.h>
-
-#include <math.h>
-
-QT_BEGIN_NAMESPACE
-
-
-
-class QDeclarativeEaseFollowPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QDeclarativeEaseFollow)
-public:
- QDeclarativeEaseFollowPrivate()
- : source(0), velocity(200), duration(-1), maximumEasingTime(-1),
- reversingMode(QDeclarativeEaseFollow::Eased), initialVelocity(0),
- initialValue(0), invert(false), enabled(true), trackVelocity(0), clockOffset(0),
- lastTick(0), clock(this)
- {}
-
- qreal source;
- qreal velocity;
- qreal duration;
- qreal maximumEasingTime;
- QDeclarativeEaseFollow::ReversingMode reversingMode;
-
- qreal initialVelocity;
- qreal initialValue;
- bool invert;
- bool enabled;
-
- qreal trackVelocity;
-
- QDeclarativeProperty target;
-
- int clockOffset;
- int lastTick;
- void tick(int);
- void clockStart();
- void clockStop();
- QTickAnimationProxy<QDeclarativeEaseFollowPrivate, &QDeclarativeEaseFollowPrivate::tick> clock;
-
- void restart();
-
- // Parameters for use in tick()
- qreal a; // Acceleration
- qreal d; // Deceleration
- qreal tf; // Total time
- qreal tp; // Time at which peak velocity occurs
- qreal td; // Time at which decelleration begins
- qreal vp; // Velocity at tp
- qreal sp; // Displacement at tp
- qreal sd; // Displacement at td
- qreal vi; // "Normalized" initialvelocity
- bool recalc();
-};
-
-bool QDeclarativeEaseFollowPrivate::recalc()
-{
- qreal s = source - initialValue;
- vi = initialVelocity;
-
- s = (invert?-1.0:1.0) * s;
- vi = (invert?-1.0:1.0) * vi;
-
- if (duration > 0 && velocity > 0) {
- tf = s / velocity;
- if (tf > (duration / 1000.)) tf = (duration / 1000.);
- } else if (duration > 0) {
- tf = duration / 1000.;
- } else if (velocity > 0) {
- tf = s / velocity;
- } else {
- return false;
- }
-
- if (maximumEasingTime == 0) {
- a = 0;
- d = 0;
- tp = 0;
- td = tf;
- vp = velocity;
- sp = 0;
- sd = s;
- } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
-
- qreal met = maximumEasingTime / 1000.;
- td = tf - met;
-
- qreal c1 = td;
- qreal c2 = (tf - td) * vi - tf * velocity;
- qreal c3 = -0.5 * (tf - td) * vi * vi;
-
- qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
- // qreal vp2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
-
- vp = vp1;
- a = vp / met;
- d = a;
- tp = (vp - vi) / a;
- sp = vi * tp + 0.5 * a * tp * tp;
- sd = sp + (td - tp) * vp;
- } else {
-
- qreal c1 = 0.25 * tf * tf;
- qreal c2 = 0.5 * vi * tf - s;
- qreal c3 = -0.25 * vi * vi;
-
- qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
- //qreal a2 = (-c2 - sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
-
- qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
- //qreal tp2 = 0.5 * tf - 0.5 * vi / a2;
- qreal vp1 = a1 * tp1 + vi;
- //qreal vp2 = a2 * tp2 + vi;
-
- qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
- //qreal sp2 = 0.5 * a2 * tp2 * tp2 + vi * tp2;
-
- a = a1;
- d = a1;
- tp = tp1;
- td = tp1;
- vp = vp1;
- sp = sp1;
- sd = sp1;
- }
-
- /*
- qWarning() << "a:" << a << "tf:" << tf << "tp:" << tp << "vp:"
- << vp << "sp:" << sp << "vi:" << vi << "invert:" << invert;
- */
- return true;
-}
-
-void QDeclarativeEaseFollowPrivate::clockStart()
-{
- if (clock.state() == QAbstractAnimation::Running) {
- clockOffset = lastTick;
- return;
- } else {
- clockOffset = 0;
- lastTick = 0;
- clock.start();
- }
-}
-
-void QDeclarativeEaseFollowPrivate::clockStop()
-{
- clockOffset = 0;
- lastTick = 0;
- clock.stop();
-}
-
-void QDeclarativeEaseFollowPrivate::tick(int t)
-{
- lastTick = t;
- t -= clockOffset;
-
- qreal time_seconds = qreal(t) / 1000.;
-
- qreal out = 0;
- if (time_seconds < tp) {
-
- trackVelocity = vi + time_seconds * a;
- trackVelocity = (invert?-1.0:1.0) * trackVelocity;
-
- qreal value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
- value = (invert?-1.0:1.0) * value;
- target.write(initialValue + value);
- out = initialValue + value;
- } else if (time_seconds < td) {
-
- time_seconds -= tp;
- trackVelocity = (invert?-1.0:1.0) * vp;
- qreal value = sp + time_seconds * vp;
- value = (invert?-1.0:1.0) * value;
-
- target.write(initialValue + value);
-
- out = initialValue + value;
- } else if (time_seconds < tf) {
-
- time_seconds -= td;
-
- trackVelocity = vp - time_seconds * a;
- trackVelocity = (invert?-1.0:1.0) * trackVelocity;
-
- qreal value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
- value = (invert?-1.0:1.0) * value;
-
- target.write(initialValue + value);
-
- out = initialValue + value;
- } else {
-
- clock.stop();
-
- trackVelocity = 0;
- target.write(source);
- }
-
- //qWarning() << out << trackVelocity << t << a;
-}
-
-/*!
- \qmlclass EaseFollow QDeclarativeEaseFollow
- \since 4.7
- \brief The EaseFollow element allows a property to smoothly track a value.
-
- The EaseFollow smoothly animates a property's value to a set target value
- using an ease in/out quad easing curve. If the target value changes while
- the animation is in progress, the easing curves used to animate to the old
- and the new target values are spliced together to avoid any obvious visual
- glitches.
-
- The property animation is configured by setting the velocity at which the
- animation should occur, or the duration that the animation should take.
- If both a velocity and a duration are specified, the one that results in
- the quickest animation is chosen for each change in the target value.
-
- For example, animating from 0 to 800 will take 4 seconds if a velocity
- of 200 is set, will take 8 seconds with a duration of 8000 set, and will
- take 4 seconds with both a velocity of 200 and a duration of 8000 set.
- Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set,
- will take 8 seconds with a duration of 8000 set, and will take 8 seconds
- with both a velocity of 200 and a duration of 8000 set.
-
- The follow example shows one rectangle tracking the position of another.
-\code
-import Qt 4.6
-
-Rectangle {
- width: 800; height: 600; color: "blue"
-
- Rectangle {
- color: "green"
- width: 60; height: 60;
- x: -5; y: -5;
- EaseFollow on x { source: rect1.x - 5; velocity: 200 }
- EaseFollow on y { source: rect1.y - 5; velocity: 200 }
- }
-
- Rectangle {
- id: rect1
- color: "red"
- width: 50; height: 50;
- }
-
- focus: true
- Keys.onRightPressed: rect1.x = rect1.x + 100
- Keys.onLeftPressed: rect1.x = rect1.x - 100
- Keys.onUpPressed: rect1.y = rect1.y - 100
- Keys.onDownPressed: rect1.y = rect1.y + 100
-}
-\endcode
-
- The default velocity of EaseFollow is 200 units/second. Note that if the range of the
- value being animated is small, then the velocity will need to be adjusted
- appropriately. For example, the opacity of an item ranges from 0 - 1.0.
- To enable a smooth animation in this range the velocity will need to be
- set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity
- of 0.5 will take 2000 ms to complete.
-
- \sa SpringFollow
-*/
-
-QDeclarativeEaseFollow::QDeclarativeEaseFollow(QObject *parent)
-: QObject(*(new QDeclarativeEaseFollowPrivate), parent)
-{
-}
-
-QDeclarativeEaseFollow::~QDeclarativeEaseFollow()
-{
-}
-
-/*!
- \qmlproperty qreal EaseFollow::source
- This property holds the source value which will be tracked.
-
- Bind to a property in order to track its changes.
-*/
-qreal QDeclarativeEaseFollow::sourceValue() const
-{
- Q_D(const QDeclarativeEaseFollow);
- return d->source;
-}
-
-/*!
- \qmlproperty enumeration EaseFollow::reversingMode
-
- Sets how the EaseFollow behaves if an animation direction is reversed.
-
- If reversing mode is \c Eased, the animation will smoothly decelerate, and
- then reverse direction. If the reversing mode is \c Immediate, the
- animation will immediately begin accelerating in the reverse direction,
- begining with a velocity of 0. If the reversing mode is \c Sync, the
- property is immediately set to the target value.
-*/
-QDeclarativeEaseFollow::ReversingMode QDeclarativeEaseFollow::reversingMode() const
-{
- Q_D(const QDeclarativeEaseFollow);
- return d->reversingMode;
-}
-
-void QDeclarativeEaseFollow::setReversingMode(ReversingMode m)
-{
- Q_D(QDeclarativeEaseFollow);
- if (d->reversingMode == m)
- return;
-
- d->reversingMode = m;
- emit reversingModeChanged();
-}
-
-void QDeclarativeEaseFollowPrivate::restart()
-{
- if (!enabled || velocity == 0) {
- clockStop();
- return;
- }
-
- initialValue = target.read().toReal();
-
- if (source == initialValue) {
- clockStop();
- return;
- }
-
- bool hasReversed = trackVelocity != 0. &&
- ((trackVelocity > 0) == ((initialValue - source) > 0));
-
- if (hasReversed) {
- switch (reversingMode) {
- default:
- case QDeclarativeEaseFollow::Eased:
- break;
- case QDeclarativeEaseFollow::Sync:
- target.write(source);
- return;
- case QDeclarativeEaseFollow::Immediate:
- initialVelocity = 0;
- clockStop();
- break;
- }
- }
-
- trackVelocity = initialVelocity;
-
- invert = (source < initialValue);
-
- if (!recalc()) {
- target.write(source);
- clockStop();
- return;
- }
-
- clockStart();
-}
-
-void QDeclarativeEaseFollow::setSourceValue(qreal s)
-{
- Q_D(QDeclarativeEaseFollow);
-
- if (d->clock.state() == QAbstractAnimation::Running && d->source == s)
- return;
-
- d->source = s;
- d->initialVelocity = d->trackVelocity;
- d->restart();
-
- emit sourceChanged();
-}
-
-/*!
- \qmlproperty qreal EaseFollow::duration
-
- This property holds the animation duration used when tracking the source.
-
- Setting this to -1 (the default) disables the duration value.
-*/
-qreal QDeclarativeEaseFollow::duration() const
-{
- Q_D(const QDeclarativeEaseFollow);
- return d->duration;
-}
-
-void QDeclarativeEaseFollow::setDuration(qreal v)
-{
- Q_D(QDeclarativeEaseFollow);
- if (d->duration == v)
- return;
-
- d->duration = v;
- d->trackVelocity = 0;
-
- if (d->clock.state() == QAbstractAnimation::Running)
- d->restart();
-
- emit durationChanged();
-}
-
-qreal QDeclarativeEaseFollow::velocity() const
-{
- Q_D(const QDeclarativeEaseFollow);
- return d->velocity;
-}
-
-/*!
- \qmlproperty qreal EaseFollow::velocity
-
- This property holds the average velocity allowed when tracking the source.
-
- The default velocity of EaseFollow is 200 units/second.
-
- Setting this to -1 disables the velocity value.
-*/
-void QDeclarativeEaseFollow::setVelocity(qreal v)
-{
- Q_D(QDeclarativeEaseFollow);
- if (d->velocity == v)
- return;
-
- d->velocity = v;
- d->trackVelocity = 0;
-
- if (d->clock.state() == QAbstractAnimation::Running)
- d->restart();
-
- emit velocityChanged();
-}
-
-/*!
- \qmlproperty bool EaseFollow::enabled
- This property holds whether the target will track the source.
-*/
-bool QDeclarativeEaseFollow::enabled() const
-{
- Q_D(const QDeclarativeEaseFollow);
- return d->enabled;
-}
-
-void QDeclarativeEaseFollow::setEnabled(bool enabled)
-{
- Q_D(QDeclarativeEaseFollow);
- if (d->enabled == enabled)
- return;
-
- d->enabled = enabled;
- if (enabled)
- d->restart();
- else
- d->clockStop();
-
- emit enabledChanged();
-}
-
-void QDeclarativeEaseFollow::setTarget(const QDeclarativeProperty &t)
-{
- Q_D(QDeclarativeEaseFollow);
- d->target = t;
-}
-
-/*!
-\qmlproperty qreal EaseFollow::maximumEasingTime
-
-This property specifies the maximum time an "eases" during the follow should take.
-Setting this property causes the velocity to "level out" after at a time. Setting
-a negative value reverts to the normal mode of easing over the entire animation
-duration.
-
-The default value is -1.
-*/
-qreal QDeclarativeEaseFollow::maximumEasingTime() const
-{
- Q_D(const QDeclarativeEaseFollow);
- return d->maximumEasingTime;
-}
-
-void QDeclarativeEaseFollow::setMaximumEasingTime(qreal v)
-{
- Q_D(QDeclarativeEaseFollow);
- d->maximumEasingTime = v;
-
- if (d->clock.state() == QAbstractAnimation::Running)
- d->restart();
-
- emit maximumEasingTimeChanged();
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativelistmodel.cpp b/src/declarative/util/qdeclarativelistmodel.cpp
index 3e25234..1a28176 100644
--- a/src/declarative/util/qdeclarativelistmodel.cpp
+++ b/src/declarative/util/qdeclarativelistmodel.cpp
@@ -365,7 +365,7 @@ void QDeclarativeListModel::clear()
if (!m_isWorkerCopy) {
emit itemsRemoved(0, cleared);
- emit countChanged(0);
+ emit countChanged();
}
}
@@ -390,7 +390,7 @@ void QDeclarativeListModel::remove(int index)
if (!m_isWorkerCopy) {
emit itemsRemoved(index, 1);
- emit countChanged(this->count());
+ emit countChanged();
}
}
@@ -424,7 +424,7 @@ void QDeclarativeListModel::insert(int index, const QScriptValue& valuemap)
bool ok = m_flat ? m_flat->insert(index, valuemap) : m_nested->insert(index, valuemap);
if (ok && !m_isWorkerCopy) {
emit itemsInserted(index, 1);
- emit countChanged(this->count());
+ emit countChanged();
}
}
@@ -1250,14 +1250,9 @@ ModelNode::ModelNode()
ModelNode::~ModelNode()
{
- ModelNode *node;
-
- QList<ModelNode *> nodeValues = properties.values();
- for (int ii = 0; ii < nodeValues.count(); ++ii) {
- node = nodeValues[ii];
- if (node) { delete node; node = 0; }
- }
+ qDeleteAll(properties.values());
+ ModelNode *node;
for (int ii = 0; ii < values.count(); ++ii) {
node = qvariant_cast<ModelNode *>(values.at(ii));
if (node) { delete node; node = 0; }
@@ -1279,7 +1274,9 @@ void ModelNode::setObjectValue(const QScriptValue& valuemap) {
} else {
value->values << v.toVariant();
}
- properties.insert(it.name(),value);
+ if (properties.contains(it.name()))
+ delete properties[it.name()];
+ properties.insert(it.name(), value);
}
}
diff --git a/src/declarative/util/qdeclarativelistmodel_p.h b/src/declarative/util/qdeclarativelistmodel_p.h
index 6a0426b..d09062e 100644
--- a/src/declarative/util/qdeclarativelistmodel_p.h
+++ b/src/declarative/util/qdeclarativelistmodel_p.h
@@ -91,7 +91,7 @@ public:
QDeclarativeListModelWorkerAgent *agent();
Q_SIGNALS:
- void countChanged(int);
+ void countChanged();
private:
friend class QDeclarativeListModelParser;
diff --git a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp
index 2951262..0e38632 100644
--- a/src/declarative/util/qdeclarativelistmodelworkeragent.cpp
+++ b/src/declarative/util/qdeclarativelistmodelworkeragent.cpp
@@ -229,7 +229,7 @@ bool QDeclarativeListModelWorkerAgent::event(QEvent *e)
}
if (cc)
- emit m_orig->countChanged(m_copy->count());
+ emit m_orig->countChanged();
}
}
diff --git a/src/declarative/util/qdeclarativeopenmetaobject.cpp b/src/declarative/util/qdeclarativeopenmetaobject.cpp
index 8c23354..6611885 100644
--- a/src/declarative/util/qdeclarativeopenmetaobject.cpp
+++ b/src/declarative/util/qdeclarativeopenmetaobject.cpp
@@ -222,9 +222,10 @@ int QDeclarativeOpenMetaObject::metaCall(QMetaObject::Call c, int id, void **a)
propertyRead(propId);
*reinterpret_cast<QVariant *>(a[0]) = d->getData(propId);
} else if (c == QMetaObject::WriteProperty) {
- if (d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
+ if (propId <= d->data.count() || d->data[propId].first != *reinterpret_cast<QVariant *>(a[0])) {
propertyWrite(propId);
d->writeData(propId, *reinterpret_cast<QVariant *>(a[0]));
+ propertyWritten(propId);
activate(d->object, d->type->d->signalOffset + propId, 0);
}
}
@@ -270,6 +271,11 @@ QVariant &QDeclarativeOpenMetaObject::operator[](const QByteArray &name)
return d->getData(*iter);
}
+QVariant &QDeclarativeOpenMetaObject::operator[](int id)
+{
+ return d->getData(id);
+}
+
void QDeclarativeOpenMetaObject::setValue(const QByteArray &name, const QVariant &val)
{
QHash<QByteArray, int>::ConstIterator iter = d->type->d->names.find(name);
@@ -326,6 +332,10 @@ void QDeclarativeOpenMetaObject::propertyWrite(int)
{
}
+void QDeclarativeOpenMetaObject::propertyWritten(int)
+{
+}
+
void QDeclarativeOpenMetaObject::propertyCreated(int, QMetaPropertyBuilder &)
{
}
diff --git a/src/declarative/util/qdeclarativeopenmetaobject_p.h b/src/declarative/util/qdeclarativeopenmetaobject_p.h
index ec5ac17..9bb4c34 100644
--- a/src/declarative/util/qdeclarativeopenmetaobject_p.h
+++ b/src/declarative/util/qdeclarativeopenmetaobject_p.h
@@ -90,6 +90,7 @@ public:
QVariant value(int) const;
void setValue(int, const QVariant &);
QVariant &operator[](const QByteArray &);
+ QVariant &operator[](int);
int count() const;
QByteArray name(int) const;
@@ -109,6 +110,7 @@ protected:
virtual void propertyRead(int);
virtual void propertyWrite(int);
+ virtual void propertyWritten(int);
virtual void propertyCreated(int, QMetaPropertyBuilder &);
QAbstractDynamicMetaObject *parent() const;
diff --git a/src/declarative/util/qdeclarativepixmapcache.cpp b/src/declarative/util/qdeclarativepixmapcache.cpp
index e78fdf1..1da929e 100644
--- a/src/declarative/util/qdeclarativepixmapcache.cpp
+++ b/src/declarative/util/qdeclarativepixmapcache.cpp
@@ -60,11 +60,6 @@
#include <private/qobject_p.h>
#include <QSslError>
-#ifdef Q_OS_LINUX
-#include <pthread.h>
-#include <linux/sched.h>
-#endif
-
// Maximum number of simultaneous image requests to send.
static const int maxImageRequestCount = 8;
@@ -106,7 +101,7 @@ public:
QDeclarativeImageReader(QDeclarativeEngine *eng);
~QDeclarativeImageReader();
- QDeclarativePixmapReply *getImage(const QUrl &url);
+ QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height);
void cancel(QDeclarativePixmapReply *rep);
static QDeclarativeImageReader *instance(QDeclarativeEngine *engine);
@@ -119,6 +114,7 @@ private:
QList<QDeclarativePixmapReply*> cancelled;
QDeclarativeEngine *engine;
QDeclarativeImageRequestHandler *handler;
+ QObject *eventLoopQuitHack;
QMutex mutex;
static QHash<QDeclarativeEngine *,QDeclarativeImageReader*> readers;
@@ -140,7 +136,7 @@ public:
QCoreApplication::postEvent(this, new QEvent(QEvent::User));
}
- QDeclarativePixmapReply *getImage(const QUrl &url);
+ QDeclarativePixmapReply *getImage(const QUrl &url, int req_width, int req_height);
void cancel(QDeclarativePixmapReply *reply);
protected:
@@ -170,11 +166,58 @@ private:
//===========================================================================
+static bool readImage(const QUrl& url, QIODevice *dev, QImage *image, QString *errorString, QSize *impsize, int req_width, int req_height)
+{
+ QImageReader imgio(dev);
+
+ bool force_scale = false;
+ if (url.path().endsWith(QLatin1String(".svg"),Qt::CaseInsensitive)) {
+ imgio.setFormat("svg"); // QSvgPlugin::capabilities bug QTBUG-9053
+ force_scale = true;
+ }
+
+ bool scaled = false;
+ if (req_width > 0 || req_height > 0) {
+ QSize s = imgio.size();
+ if (req_width && (force_scale || req_width < s.width())) {
+ if (req_height <= 0)
+ s.setHeight(s.height()*req_width/s.width());
+ s.setWidth(req_width); scaled = true;
+ }
+ if (req_height && (force_scale || req_height < s.height())) {
+ if (req_width <= 0)
+ s.setWidth(s.width()*req_height/s.height());
+ s.setHeight(req_height); scaled = true;
+ }
+ if (scaled) { imgio.setScaledSize(s); }
+ }
+
+ if (impsize)
+ *impsize = imgio.size();
+
+ if (imgio.read(image)) {
+ if (impsize && impsize->width() < 0)
+ *impsize = image->size();
+ return true;
+ } else {
+ if (errorString)
+ *errorString = QLatin1String("Error decoding: ") + url.toString()
+ + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\"");
+ return false;
+ }
+}
+
+
+//===========================================================================
+
int QDeclarativeImageRequestHandler::replyDownloadProgress = -1;
int QDeclarativeImageRequestHandler::replyFinished = -1;
int QDeclarativeImageRequestHandler::downloadProgress = -1;
int QDeclarativeImageRequestHandler::thisNetworkRequestDone = -1;
+typedef QHash<QUrl, QSize> QDeclarativePixmapSizeHash;
+Q_GLOBAL_STATIC(QDeclarativePixmapSizeHash, qmlOriginalSizes);
+
bool QDeclarativeImageRequestHandler::event(QEvent *event)
{
if (event->type() == QEvent::User) {
@@ -221,7 +264,9 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event)
// fetch
if (url.scheme() == QLatin1String("image")) {
// Use QmlImageProvider
- QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url);
+ QSize read_impsize;
+ QImage image = QDeclarativeEnginePrivate::get(engine)->getImageFromProvider(url, &read_impsize, QSize(runningJob->forcedWidth(),runningJob->forcedHeight()));
+ qmlOriginalSizes()->insert(url, read_impsize);
QDeclarativeImageReaderEvent::ReadError errorCode = QDeclarativeImageReaderEvent::NoError;
QString errorStr;
if (image.isNull()) {
@@ -238,10 +283,10 @@ bool QDeclarativeImageRequestHandler::event(QEvent *event)
QString errorStr;
QFile f(lf);
if (f.open(QIODevice::ReadOnly)) {
- QImageReader imgio(&f);
- if (!imgio.read(&image)) {
- errorStr = QLatin1String("Error decoding: ") + url.toString()
- + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\"");
+ QSize read_impsize;
+ if (readImage(url, &f, &image, &errorStr, &read_impsize, runningJob->forcedWidth(),runningJob->forcedHeight())) {
+ qmlOriginalSizes()->insert(url, read_impsize);
+ } else {
errorCode = QDeclarativeImageReaderEvent::Loading;
}
} else {
@@ -303,12 +348,11 @@ void QDeclarativeImageRequestHandler::networkRequestDone()
error = QDeclarativeImageReaderEvent::Loading;
errorString = reply->errorString();
} else {
- QImageReader imgio(reply);
- if (imgio.read(&image)) {
+ QSize read_impsize;
+ if (readImage(reply->url(), reply, &image, &errorString, &read_impsize, job->forcedWidth(), job->forcedHeight())) {
+ qmlOriginalSizes()->insert(reply->url(), read_impsize);
error = QDeclarativeImageReaderEvent::NoError;
} else {
- errorString = QLatin1String("Error decoding: ") + reply->url().toString()
- + QLatin1String(" \"") + imgio.errorString() + QLatin1String("\"");
error = QDeclarativeImageReaderEvent::Decoding;
}
}
@@ -326,7 +370,10 @@ void QDeclarativeImageRequestHandler::networkRequestDone()
QDeclarativeImageReader::QDeclarativeImageReader(QDeclarativeEngine *eng)
: QThread(eng), engine(eng), handler(0)
{
- start(QThread::LowPriority);
+ eventLoopQuitHack = new QObject;
+ eventLoopQuitHack->moveToThread(this);
+ connect(eventLoopQuitHack, SIGNAL(destroyed(QObject*)), SLOT(quit()), Qt::DirectConnection);
+ start(QThread::IdlePriority);
}
QDeclarativeImageReader::~QDeclarativeImageReader()
@@ -335,7 +382,7 @@ QDeclarativeImageReader::~QDeclarativeImageReader()
readers.remove(engine);
readerMutex.unlock();
- quit();
+ eventLoopQuitHack->deleteLater();
wait();
}
@@ -352,10 +399,10 @@ QDeclarativeImageReader *QDeclarativeImageReader::instance(QDeclarativeEngine *e
return reader;
}
-QDeclarativePixmapReply *QDeclarativeImageReader::getImage(const QUrl &url)
+QDeclarativePixmapReply *QDeclarativeImageReader::getImage(const QUrl &url, int req_width, int req_height)
{
mutex.lock();
- QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(this, url);
+ QDeclarativePixmapReply *reply = new QDeclarativePixmapReply(this, url, req_width, req_height);
reply->addRef();
reply->setLoading();
jobs.append(reply);
@@ -379,15 +426,9 @@ void QDeclarativeImageReader::cancel(QDeclarativePixmapReply *reply)
void QDeclarativeImageReader::run()
{
-#if defined(Q_OS_LINUX) && defined(SCHED_IDLE)
- struct sched_param param;
- int policy;
-
- pthread_getschedparam(pthread_self(), &policy, &param);
- pthread_setschedparam(pthread_self(), SCHED_IDLE, &param);
-#endif
-
+ readerMutex.lock();
handler = new QDeclarativeImageRequestHandler(this, engine);
+ readerMutex.unlock();
exec();
@@ -397,40 +438,6 @@ void QDeclarativeImageReader::run()
//===========================================================================
-static bool readImage(QIODevice *dev, QPixmap *pixmap, QString &errorString)
-{
- QImageReader imgio(dev);
-
-//#define QT_TEST_SCALED_SIZE
-#ifdef QT_TEST_SCALED_SIZE
- /*
- Some mechanism is needed for loading images at a limited size, especially
- for remote images. Loading only thumbnails of remote progressive JPEG
- images can be efficient. (Qt jpeg handler does not do so currently)
- */
-
- QSize limit(60,60);
- QSize sz = imgio.size();
- if (sz.width() > limit.width() || sz.height() > limit.height()) {
- sz.scale(limit,Qt::KeepAspectRatio);
- imgio.setScaledSize(sz);
- }
-#endif
-
- QImage img;
- if (imgio.read(&img)) {
-#ifdef QT_TEST_SCALED_SIZE
- if (!sz.isValid())
- img = img.scaled(limit,Qt::KeepAspectRatio);
-#endif
- *pixmap = QPixmap::fromImage(img);
- return true;
- } else {
- errorString = imgio.errorString();
- return false;
- }
-}
-
/*!
\internal
\class QDeclarativePixmapCache
@@ -447,8 +454,10 @@ class QDeclarativePixmapReplyPrivate : public QObjectPrivate
Q_DECLARE_PUBLIC(QDeclarativePixmapReply)
public:
- QDeclarativePixmapReplyPrivate(QDeclarativeImageReader *r, const QUrl &u)
- : QObjectPrivate(), refCount(1), url(u), status(QDeclarativePixmapReply::Loading), loading(false), reader(r) {
+ QDeclarativePixmapReplyPrivate(QDeclarativeImageReader *r, const QUrl &u, int req_width, int req_height)
+ : QObjectPrivate(), refCount(1), url(u), status(QDeclarativePixmapReply::Loading), loading(false), reader(r),
+ forced_width(req_width), forced_height(req_height)
+ {
}
int refCount;
@@ -457,11 +466,12 @@ public:
QDeclarativePixmapReply::Status status;
bool loading;
QDeclarativeImageReader *reader;
+ int forced_width, forced_height;
};
-QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url)
- : QObject(*new QDeclarativePixmapReplyPrivate(reader, url), 0)
+QDeclarativePixmapReply::QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height)
+ : QObject(*new QDeclarativePixmapReplyPrivate(reader, url, req_width, req_height), 0)
{
}
@@ -475,6 +485,28 @@ const QUrl &QDeclarativePixmapReply::url() const
return d->url;
}
+int QDeclarativePixmapReply::forcedWidth() const
+{
+ Q_D(const QDeclarativePixmapReply);
+ return d->forced_width;
+}
+
+int QDeclarativePixmapReply::forcedHeight() const
+{
+ Q_D(const QDeclarativePixmapReply);
+ return d->forced_height;
+}
+
+QSize QDeclarativePixmapReply::implicitSize() const
+{
+ Q_D(const QDeclarativePixmapReply);
+ QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(d->url);
+ if (iter != qmlOriginalSizes()->end())
+ return *iter;
+ else
+ return QSize();
+}
+
bool QDeclarativePixmapReply::event(QEvent *event)
{
Q_D(QDeclarativePixmapReply);
@@ -554,13 +586,25 @@ bool QDeclarativePixmapReply::release(bool defer)
If \a async is false the image will be loaded and decoded immediately;
otherwise the image will be loaded and decoded in a separate thread.
+ If \a req_width and \a req_height are non-zero, they are used for
+ the size of the rendered pixmap rather than the intrinsic size of the image.
+ Different request sizes add different cache items.
+
Note that images sourced from the network will always be loaded and
decoded asynchonously.
*/
-QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, bool async)
+QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QPixmap *pixmap, QSize *impsize, bool async, int req_width, int req_height)
{
QDeclarativePixmapReply::Status status = QDeclarativePixmapReply::Unrequested;
QByteArray key = url.toEncoded(QUrl::FormattingOption(0x100));
+
+ if (req_width > 0 || req_height > 0) {
+ key += ':';
+ key += QByteArray::number(req_width);
+ key += 'x';
+ key += QByteArray::number(req_height);
+ }
+
QString strKey = QString::fromLatin1(key.constData(), key.count());
#ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
@@ -570,11 +614,13 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP
status = QDeclarativePixmapReply::Ready;
if (!QPixmapCache::find(strKey,pixmap)) {
QFile f(lf);
+ QSize read_impsize;
if (f.open(QIODevice::ReadOnly)) {
QString errorString;
- if (!readImage(&f, pixmap, errorString)) {
- errorString = QLatin1String("Error decoding: ") + url.toString()
- + QLatin1String(" \"") + errorString + QLatin1String("\"");
+ QImage image;
+ if (readImage(url, &f, &image, &errorString, &read_impsize, req_width, req_height)) {
+ *pixmap = QPixmap::fromImage(image);
+ } else {
qWarning() << errorString;
*pixmap = QPixmap();
status = QDeclarativePixmapReply::Error;
@@ -584,8 +630,18 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP
*pixmap = QPixmap();
status = QDeclarativePixmapReply::Error;
}
- if (status == QDeclarativePixmapReply::Ready)
+ if (status == QDeclarativePixmapReply::Ready) {
QPixmapCache::insert(strKey, *pixmap);
+ qmlOriginalSizes()->insert(url, read_impsize);
+ }
+ if (impsize)
+ *impsize = read_impsize;
+ } else {
+ if (impsize) {
+ QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url);
+ if (iter != qmlOriginalSizes()->end())
+ *impsize = *iter;
+ }
}
return status;
}
@@ -608,6 +664,11 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP
} else if (iter != qmlActivePixmapReplies()->end()) {
status = QDeclarativePixmapReply::Loading;
}
+ if (impsize) {
+ QDeclarativePixmapSizeHash::Iterator iter = qmlOriginalSizes()->find(url);
+ if (iter != qmlOriginalSizes()->end())
+ *impsize = *iter;
+ }
return status;
}
@@ -621,12 +682,12 @@ QDeclarativePixmapReply::Status QDeclarativePixmapCache::get(const QUrl& url, QP
The returned QDeclarativePixmapReply will be deleted when all request() calls are
matched by a corresponding get() call.
*/
-QDeclarativePixmapReply *QDeclarativePixmapCache::request(QDeclarativeEngine *engine, const QUrl &url)
+QDeclarativePixmapReply *QDeclarativePixmapCache::request(QDeclarativeEngine *engine, const QUrl &url, int req_width, int req_height)
{
QDeclarativePixmapReplyHash::Iterator iter = qmlActivePixmapReplies()->find(url);
if (iter == qmlActivePixmapReplies()->end()) {
QDeclarativeImageReader *reader = QDeclarativeImageReader::instance(engine);
- QDeclarativePixmapReply *item = reader->getImage(url);
+ QDeclarativePixmapReply *item = reader->getImage(url, req_width, req_height);
iter = qmlActivePixmapReplies()->insert(url, item);
} else {
(*iter)->addRef();
diff --git a/src/declarative/util/qdeclarativepixmapcache_p.h b/src/declarative/util/qdeclarativepixmapcache_p.h
index b8949db..df71d65 100644
--- a/src/declarative/util/qdeclarativepixmapcache_p.h
+++ b/src/declarative/util/qdeclarativepixmapcache_p.h
@@ -66,6 +66,9 @@ public:
Status status() const;
const QUrl &url() const;
+ int forcedWidth() const;
+ int forcedHeight() const;
+ QSize implicitSize() const;
Q_SIGNALS:
void finished();
@@ -81,7 +84,7 @@ private:
void setLoading();
private:
- QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url);
+ QDeclarativePixmapReply(QDeclarativeImageReader *reader, const QUrl &url, int req_width, int req_height);
Q_DISABLE_COPY(QDeclarativePixmapReply)
Q_DECLARE_PRIVATE(QDeclarativePixmapReply)
friend class QDeclarativeImageRequestHandler;
@@ -92,8 +95,8 @@ private:
class Q_DECLARATIVE_EXPORT QDeclarativePixmapCache
{
public:
- static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, bool async=false);
- static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url);
+ static QDeclarativePixmapReply::Status get(const QUrl& url, QPixmap *pixmap, QSize *impsize=0, bool async=false, int req_width=0, int req_height=0);
+ static QDeclarativePixmapReply *request(QDeclarativeEngine *, const QUrl& url, int req_width=0, int req_height=0);
static void cancel(const QUrl& url, QObject *obj);
static int pendingRequests();
};
diff --git a/src/declarative/util/qdeclarativepropertymap.cpp b/src/declarative/util/qdeclarativepropertymap.cpp
index fcea515..0bdd91b 100644
--- a/src/declarative/util/qdeclarativepropertymap.cpp
+++ b/src/declarative/util/qdeclarativepropertymap.cpp
@@ -41,6 +41,7 @@
#include "qdeclarativepropertymap.h"
+#include <private/qmetaobjectbuilder_p.h>
#include "qdeclarativeopenmetaobject_p.h"
#include <QDebug>
@@ -55,7 +56,8 @@ public:
QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv);
protected:
- virtual void propertyWrite(int index);
+ virtual void propertyWritten(int index);
+ virtual void propertyCreated(int, QMetaPropertyBuilder &);
private:
QDeclarativePropertyMap *map;
@@ -68,13 +70,13 @@ class QDeclarativePropertyMapPrivate : public QObjectPrivate
public:
QDeclarativePropertyMapMetaObject *mo;
QStringList keys;
- void emitChanged(const QString &key);
+ void emitChanged(const QString &key, const QVariant &value);
};
-void QDeclarativePropertyMapPrivate::emitChanged(const QString &key)
+void QDeclarativePropertyMapPrivate::emitChanged(const QString &key, const QVariant &value)
{
Q_Q(QDeclarativePropertyMap);
- emit q->valueChanged(key);
+ emit q->valueChanged(key, value);
}
QDeclarativePropertyMapMetaObject::QDeclarativePropertyMapMetaObject(QDeclarativePropertyMap *obj, QDeclarativePropertyMapPrivate *objPriv) : QDeclarativeOpenMetaObject(obj)
@@ -83,14 +85,19 @@ QDeclarativePropertyMapMetaObject::QDeclarativePropertyMapMetaObject(QDeclarativ
priv = objPriv;
}
-void QDeclarativePropertyMapMetaObject::propertyWrite(int index)
+void QDeclarativePropertyMapMetaObject::propertyWritten(int index)
{
- priv->emitChanged(QString::fromUtf8(name(index)));
+ priv->emitChanged(QString::fromUtf8(name(index)), operator[](index));
+}
+
+void QDeclarativePropertyMapMetaObject::propertyCreated(int, QMetaPropertyBuilder &b)
+{
+ priv->keys.append(QString::fromUtf8(b.name()));
}
/*!
\class QDeclarativePropertyMap
- \since 4.7
+ \since 4.7
\brief The QDeclarativePropertyMap class allows you to set key-value pairs that can be used in bindings.
QDeclarativePropertyMap provides a convenient way to expose domain data to the UI layer.
@@ -172,8 +179,6 @@ QVariant QDeclarativePropertyMap::value(const QString &key) const
void QDeclarativePropertyMap::insert(const QString &key, const QVariant &value)
{
Q_D(QDeclarativePropertyMap);
- if (!d->keys.contains(key))
- d->keys.append(key);
d->mo->setValue(key.toUtf8(), value);
}
@@ -249,10 +254,8 @@ QVariant &QDeclarativePropertyMap::operator[](const QString &key)
//### optimize
Q_D(QDeclarativePropertyMap);
QByteArray utf8key = key.toUtf8();
- if (!d->keys.contains(key)) {
- d->keys.append(key);
+ if (!d->keys.contains(key))
d->mo->setValue(utf8key, QVariant()); //force creation -- needed below
- }
return (*(d->mo))[utf8key];
}
@@ -268,9 +271,9 @@ const QVariant QDeclarativePropertyMap::operator[](const QString &key) const
}
/*!
- \fn void QDeclarativePropertyMap::valueChanged(const QString &key)
+ \fn void QDeclarativePropertyMap::valueChanged(const QString &key, const QVariant &value)
This signal is emitted whenever one of the values in the map is changed. \a key
- is the key corresponding to the value that was changed.
+ is the key corresponding to the \a value that was changed.
\note valueChanged() is \bold NOT emitted when changes are made by calling insert()
or clear() - it is only emitted when a value is updated from QML.
diff --git a/src/declarative/util/qdeclarativepropertymap.h b/src/declarative/util/qdeclarativepropertymap.h
index 513089f..e0b7ce3 100644
--- a/src/declarative/util/qdeclarativepropertymap.h
+++ b/src/declarative/util/qdeclarativepropertymap.h
@@ -76,7 +76,7 @@ public:
const QVariant operator[](const QString &key) const;
Q_SIGNALS:
- void valueChanged(const QString &key);
+ void valueChanged(const QString &key, const QVariant &value);
private:
Q_DECLARE_PRIVATE(QDeclarativePropertyMap)
diff --git a/src/declarative/util/qdeclarativesmoothedanimation.cpp b/src/declarative/util/qdeclarativesmoothedanimation.cpp
new file mode 100644
index 0000000..b3a9b9a
--- /dev/null
+++ b/src/declarative/util/qdeclarativesmoothedanimation.cpp
@@ -0,0 +1,483 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativesmoothedanimation_p.h"
+#include "qdeclarativesmoothedanimation_p_p.h"
+
+#include "qdeclarativeanimation_p_p.h"
+
+#include <qdeclarativeproperty.h>
+#include "qdeclarativeproperty_p.h"
+
+#include "qdeclarativeglobal_p.h"
+
+#include <QtCore/qdebug.h>
+
+#include <math.h>
+
+#define DELAY_STOP_TIMER_INTERVAL 32
+
+QT_BEGIN_NAMESPACE
+
+QSmoothedAnimation::QSmoothedAnimation(QObject *parent)
+ : QAbstractAnimation(parent), to(0), velocity(200), userDuration(-1), maximumEasingTime(-1),
+ reversingMode(QDeclarativeSmoothedAnimation::Eased), initialVelocity(0),
+ trackVelocity(0), initialValue(0), invert(false), finalDuration(-1), lastTime(0)
+{
+ delayedStopTimer.setInterval(DELAY_STOP_TIMER_INTERVAL);
+ delayedStopTimer.setSingleShot(true);
+ connect(&delayedStopTimer, SIGNAL(timeout()), this, SLOT(stop()));
+}
+
+void QSmoothedAnimation::restart()
+{
+ if (state() != QAbstractAnimation::Running)
+ start();
+ else
+ init();
+}
+
+void QSmoothedAnimation::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State /*oldState*/)
+{
+ if (newState == QAbstractAnimation::Running)
+ init();
+}
+
+void QSmoothedAnimation::delayedStop()
+{
+ if (!delayedStopTimer.isActive())
+ delayedStopTimer.start();
+}
+
+int QSmoothedAnimation::duration() const
+{
+ return -1;
+}
+
+bool QSmoothedAnimation::recalc()
+{
+ s = to - initialValue;
+ vi = initialVelocity;
+
+ s = (invert? -1.0: 1.0) * s;
+
+ if (userDuration > 0 && velocity > 0) {
+ tf = s / velocity;
+ if (tf > (userDuration / 1000.)) tf = (userDuration / 1000.);
+ } else if (userDuration > 0) {
+ tf = userDuration / 1000.;
+ } else if (velocity > 0) {
+ tf = s / velocity;
+ } else {
+ return false;
+ }
+
+ finalDuration = ceil(tf * 1000.0);
+
+ if (maximumEasingTime == 0) {
+ a = 0;
+ d = 0;
+ tp = 0;
+ td = tf;
+ vp = velocity;
+ sp = 0;
+ sd = s;
+ } else if (maximumEasingTime != -1 && tf > (maximumEasingTime / 1000.)) {
+ qreal met = maximumEasingTime / 1000.;
+ td = tf - met;
+
+ qreal c1 = td;
+ qreal c2 = (tf - td) * vi - tf * velocity;
+ qreal c3 = -0.5 * (tf - td) * vi * vi;
+
+ qreal vp1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+
+ vp = vp1;
+ a = vp / met;
+ d = a;
+ tp = (vp - vi) / a;
+ sp = vi * tp + 0.5 * a * tp * tp;
+ sd = sp + (td - tp) * vp;
+ } else {
+ qreal c1 = 0.25 * tf * tf;
+ qreal c2 = 0.5 * vi * tf - s;
+ qreal c3 = -0.25 * vi * vi;
+
+ qreal a1 = (-c2 + sqrt(c2 * c2 - 4 * c1 * c3)) / (2. * c1);
+
+ qreal tp1 = 0.5 * tf - 0.5 * vi / a1;
+ qreal vp1 = a1 * tp1 + vi;
+
+ qreal sp1 = 0.5 * a1 * tp1 * tp1 + vi * tp1;
+
+ a = a1;
+ d = a1;
+ tp = tp1;
+ td = tp1;
+ vp = vp1;
+ sp = sp1;
+ sd = sp1;
+ }
+ return true;
+}
+
+qreal QSmoothedAnimation::easeFollow(qreal time_seconds)
+{
+ qreal value;
+ if (time_seconds < tp) {
+ trackVelocity = vi + time_seconds * a;
+ value = 0.5 * a * time_seconds * time_seconds + vi * time_seconds;
+ } else if (time_seconds < td) {
+ time_seconds -= tp;
+ trackVelocity = vp;
+ value = sp + time_seconds * vp;
+ } else if (time_seconds < tf) {
+ time_seconds -= td;
+ trackVelocity = vp - time_seconds * a;
+ value = sd - 0.5 * d * time_seconds * time_seconds + vp * time_seconds;
+ } else {
+ trackVelocity = 0;
+ value = s;
+ delayedStop();
+ }
+
+ // to normalize 's' between [0..1], divide 'value' by 's'
+ return value;
+}
+
+void QSmoothedAnimation::updateCurrentTime(int t)
+{
+ qreal time_seconds = qreal(t - lastTime) / 1000.;
+
+ qreal value = easeFollow(time_seconds);
+ value *= (invert? -1.0: 1.0);
+ QDeclarativePropertyPrivate::write(target, initialValue + value,
+ QDeclarativePropertyPrivate::BypassInterceptor
+ | QDeclarativePropertyPrivate::DontRemoveBinding);
+}
+
+void QSmoothedAnimation::init()
+{
+ if (velocity == 0) {
+ stop();
+ return;
+ }
+
+ if (delayedStopTimer.isActive())
+ delayedStopTimer.stop();
+
+ initialValue = target.read().toReal();
+ lastTime = this->currentTime();
+
+ if (to == initialValue) {
+ stop();
+ return;
+ }
+
+ bool hasReversed = trackVelocity != 0. &&
+ ((trackVelocity > 0) == ((initialValue - to) > 0));
+
+ if (hasReversed) {
+ switch (reversingMode) {
+ default:
+ case QDeclarativeSmoothedAnimation::Eased:
+ break;
+ case QDeclarativeSmoothedAnimation::Sync:
+ QDeclarativePropertyPrivate::write(target, to,
+ QDeclarativePropertyPrivate::BypassInterceptor
+ | QDeclarativePropertyPrivate::DontRemoveBinding);
+ return;
+ case QDeclarativeSmoothedAnimation::Immediate:
+ initialVelocity = 0;
+ delayedStop();
+ break;
+ }
+ }
+
+ trackVelocity = initialVelocity;
+
+ invert = (to < initialValue);
+
+ if (!recalc()) {
+ QDeclarativePropertyPrivate::write(target, to,
+ QDeclarativePropertyPrivate::BypassInterceptor
+ | QDeclarativePropertyPrivate::DontRemoveBinding);
+ stop();
+ return;
+ }
+}
+
+/*!
+ \qmlclass SmoothedAnimation QDeclarativeSmoothedAnimation
+ \since 4.7
+ \brief The SmoothedAnimation element allows a property to smoothly track a value.
+
+ The SmoothedAnimation smoothly animates a property's value to a set target value
+ using an ease in/out quad easing curve. If the animation is restarted
+ with a different target value, the easing curves used to animate to the old
+ and the new target values are spliced together to avoid any obvious visual
+ glitches.
+
+ The property animation is configured by setting the velocity at which the
+ animation should occur, or the duration that the animation should take.
+ If both a velocity and a duration are specified, the one that results in
+ the quickest animation is chosen for each change in the target value.
+
+ For example, animating from 0 to 800 will take 4 seconds if a velocity
+ of 200 is set, will take 8 seconds with a duration of 8000 set, and will
+ take 4 seconds with both a velocity of 200 and a duration of 8000 set.
+ Animating from 0 to 20000 will take 10 seconds if a velocity of 200 is set,
+ will take 8 seconds with a duration of 8000 set, and will take 8 seconds
+ with both a velocity of 200 and a duration of 8000 set.
+
+ The follow example shows one rectangle tracking the position of another.
+\code
+import Qt 4.6
+
+Rectangle {
+ width: 800; height: 600; color: "blue"
+
+ Rectangle {
+ color: "green"
+ width: 60; height: 60;
+ x: rect1.x - 5; y: rect1.y - 5;
+ Behavior on x { SmoothedAnimation { velocity: 200 } }
+ Behavior on y { SmoothedAnimation { velocity: 200 } }
+ }
+
+ Rectangle {
+ id: rect1
+ color: "red"
+ width: 50; height: 50;
+ }
+
+ focus: true
+ Keys.onRightPressed: rect1.x = rect1.x + 100
+ Keys.onLeftPressed: rect1.x = rect1.x - 100
+ Keys.onUpPressed: rect1.y = rect1.y - 100
+ Keys.onDownPressed: rect1.y = rect1.y + 100
+}
+\endcode
+
+ The default velocity of SmoothedAnimation is 200 units/second. Note that if the range of the
+ value being animated is small, then the velocity will need to be adjusted
+ appropriately. For example, the opacity of an item ranges from 0 - 1.0.
+ To enable a smooth animation in this range the velocity will need to be
+ set to a value such as 0.5 units/second. Animating from 0 to 1.0 with a velocity
+ of 0.5 will take 2000 ms to complete.
+
+ \sa SpringFollow
+*/
+
+QDeclarativeSmoothedAnimation::QDeclarativeSmoothedAnimation(QObject *parent)
+: QDeclarativeNumberAnimation(*(new QDeclarativeSmoothedAnimationPrivate), parent)
+{
+}
+
+QDeclarativeSmoothedAnimation::~QDeclarativeSmoothedAnimation()
+{
+}
+
+QDeclarativeSmoothedAnimationPrivate::QDeclarativeSmoothedAnimationPrivate()
+ : wrapperGroup(new QParallelAnimationGroup), anim(new QSmoothedAnimation)
+{
+ Q_Q(QDeclarativeSmoothedAnimation);
+ QDeclarative_setParent_noEvent(wrapperGroup, q);
+ QDeclarative_setParent_noEvent(anim, q);
+}
+
+QAbstractAnimation* QDeclarativeSmoothedAnimation::qtAnimation()
+{
+ Q_D(QDeclarativeSmoothedAnimation);
+ return d->wrapperGroup;
+}
+
+void QDeclarativeSmoothedAnimation::transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction)
+{
+ Q_D(QDeclarativeSmoothedAnimation);
+ QDeclarativeNumberAnimation::transition(actions, modified, direction);
+
+ if (!d->actions)
+ return;
+
+ QSet<QAbstractAnimation*> anims;
+ for (int i = 0; i < d->actions->size(); i++) {
+ QSmoothedAnimation *ease;
+ qreal trackVelocity;
+ bool needsRestart;
+ if (!d->activeAnimations.contains((*d->actions)[i].property)) {
+ ease = new QSmoothedAnimation();
+ d->wrapperGroup->addAnimation(ease);
+ d->activeAnimations.insert((*d->actions)[i].property, ease);
+ trackVelocity = 0.0;
+ needsRestart = false;
+ } else {
+ ease = d->activeAnimations.value((*d->actions)[i].property);
+ trackVelocity = ease->trackVelocity;
+ needsRestart = true;
+ }
+
+ ease->target = (*d->actions)[i].property;
+ ease->to = (*d->actions)[i].toValue.toReal();
+
+ // copying public members from main value holder animation
+ ease->maximumEasingTime = d->anim->maximumEasingTime;
+ ease->reversingMode = d->anim->reversingMode;
+ ease->velocity = d->anim->velocity;
+ ease->userDuration = d->anim->userDuration;
+
+ ease->trackVelocity = trackVelocity;
+ ease->initialVelocity = trackVelocity;
+
+ if (needsRestart)
+ ease->init();
+ anims.insert(ease);
+ }
+
+ for (int i = d->wrapperGroup->animationCount() - 1; i >= 0 ; --i) {
+ if (!anims.contains(d->wrapperGroup->animationAt(i))) {
+ QSmoothedAnimation *ease = static_cast<QSmoothedAnimation*>(d->wrapperGroup->animationAt(i));
+ d->activeAnimations.remove(ease->target);
+ d->wrapperGroup->takeAnimation(i);
+ delete ease;
+ }
+ }
+}
+
+/*!
+ \qmlproperty enumeration SmoothedAnimation::reversingMode
+
+ Sets how the SmoothedAnimation behaves if an animation direction is reversed.
+
+ If reversing mode is \c Eased, the animation will smoothly decelerate, and
+ then reverse direction. If the reversing mode is \c Immediate, the
+ animation will immediately begin accelerating in the reverse direction,
+ begining with a velocity of 0. If the reversing mode is \c Sync, the
+ property is immediately set to the target value.
+*/
+QDeclarativeSmoothedAnimation::ReversingMode QDeclarativeSmoothedAnimation::reversingMode() const
+{
+ Q_D(const QDeclarativeSmoothedAnimation);
+ return (QDeclarativeSmoothedAnimation::ReversingMode) d->anim->reversingMode;
+}
+
+void QDeclarativeSmoothedAnimation::setReversingMode(ReversingMode m)
+{
+ Q_D(QDeclarativeSmoothedAnimation);
+ if (d->anim->reversingMode == m)
+ return;
+
+ d->anim->reversingMode = m;
+ emit reversingModeChanged();
+}
+
+/*!
+ \qmlproperty int SmoothedAnimation::duration
+
+ This property holds the animation duration, in msecs, used when tracking the source.
+
+ Setting this to -1 (the default) disables the duration value.
+*/
+int QDeclarativeSmoothedAnimation::duration() const
+{
+ Q_D(const QDeclarativeSmoothedAnimation);
+ return d->anim->userDuration;
+}
+
+void QDeclarativeSmoothedAnimation::setDuration(int duration)
+{
+ Q_D(QDeclarativeSmoothedAnimation);
+ if (duration != -1)
+ QDeclarativeNumberAnimation::setDuration(duration);
+ d->anim->userDuration = duration;
+}
+
+qreal QDeclarativeSmoothedAnimation::velocity() const
+{
+ Q_D(const QDeclarativeSmoothedAnimation);
+ return d->anim->velocity;
+}
+
+/*!
+ \qmlproperty qreal SmoothedAnimation::velocity
+
+ This property holds the average velocity allowed when tracking the 'to' value.
+
+ The default velocity of SmoothedAnimation is 200 units/second.
+
+ Setting this to -1 disables the velocity value.
+*/
+void QDeclarativeSmoothedAnimation::setVelocity(qreal v)
+{
+ Q_D(QDeclarativeSmoothedAnimation);
+ if (d->anim->velocity == v)
+ return;
+
+ d->anim->velocity = v;
+ emit velocityChanged();
+}
+
+/*!
+\qmlproperty qreal SmoothedAnimation::maximumEasingTime
+
+This property specifies the maximum time, in msecs, an "eases" during the follow should take.
+Setting this property causes the velocity to "level out" after at a time. Setting
+a negative value reverts to the normal mode of easing over the entire animation
+duration.
+
+The default value is -1.
+*/
+int QDeclarativeSmoothedAnimation::maximumEasingTime() const
+{
+ Q_D(const QDeclarativeSmoothedAnimation);
+ return d->anim->maximumEasingTime;
+}
+
+void QDeclarativeSmoothedAnimation::setMaximumEasingTime(int v)
+{
+ Q_D(QDeclarativeSmoothedAnimation);
+ d->anim->maximumEasingTime = v;
+ emit maximumEasingTimeChanged();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativeeasefollow_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p.h
index 83d1eff..50ed00c 100644
--- a/src/declarative/util/qdeclarativeeasefollow_p.h
+++ b/src/declarative/util/qdeclarativesmoothedanimation_p.h
@@ -39,11 +39,11 @@
**
****************************************************************************/
-#ifndef QDECLARATIVEEASEFOLLOW_H
-#define QDECLARATIVEEASEFOLLOW_H
+#ifndef QDECLARATIVESMOOTHEDANIMATION_H
+#define QDECLARATIVESMOOTHEDANIMATION_H
#include <qdeclarative.h>
-#include <qdeclarativepropertyvaluesource.h>
+#include "qdeclarativeanimation_p.h"
#include <QtCore/qobject.h>
@@ -54,61 +54,51 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
class QDeclarativeProperty;
-class QDeclarativeEaseFollowPrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativeEaseFollow : public QObject,
- public QDeclarativePropertyValueSource
+class QDeclarativeSmoothedAnimationPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarativeSmoothedAnimation : public QDeclarativeNumberAnimation
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeEaseFollow)
- Q_INTERFACES(QDeclarativePropertyValueSource)
+ Q_DECLARE_PRIVATE(QDeclarativeSmoothedAnimation)
Q_ENUMS(ReversingMode)
- Q_PROPERTY(qreal source READ sourceValue WRITE setSourceValue NOTIFY sourceChanged)
Q_PROPERTY(qreal velocity READ velocity WRITE setVelocity NOTIFY velocityChanged)
- Q_PROPERTY(qreal duration READ duration WRITE setDuration NOTIFY durationChanged)
Q_PROPERTY(ReversingMode reversingMode READ reversingMode WRITE setReversingMode NOTIFY reversingModeChanged)
- Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged)
Q_PROPERTY(qreal maximumEasingTime READ maximumEasingTime WRITE setMaximumEasingTime NOTIFY maximumEasingTimeChanged)
public:
enum ReversingMode { Eased, Immediate, Sync };
- QDeclarativeEaseFollow(QObject *parent = 0);
- ~QDeclarativeEaseFollow();
+ QDeclarativeSmoothedAnimation(QObject *parent = 0);
+ ~QDeclarativeSmoothedAnimation();
ReversingMode reversingMode() const;
void setReversingMode(ReversingMode);
- qreal sourceValue() const;
- void setSourceValue(qreal);
+ virtual int duration() const;
+ virtual void setDuration(int);
qreal velocity() const;
void setVelocity(qreal);
- qreal duration() const;
- void setDuration(qreal);
+ int maximumEasingTime() const;
+ void setMaximumEasingTime(int);
- bool enabled() const;
- void setEnabled(bool enabled);
-
- qreal maximumEasingTime() const;
- void setMaximumEasingTime(qreal);
-
- virtual void setTarget(const QDeclarativeProperty &);
+public:
+ virtual void transition(QDeclarativeStateActions &actions,
+ QDeclarativeProperties &modified,
+ TransitionDirection direction);
+ QAbstractAnimation* qtAnimation();
Q_SIGNALS:
- void sourceChanged();
void velocityChanged();
- void durationChanged();
void reversingModeChanged();
- void enabledChanged();
void maximumEasingTimeChanged();
};
QT_END_NAMESPACE
-QML_DECLARE_TYPE(QDeclarativeEaseFollow);
+QML_DECLARE_TYPE(QDeclarativeSmoothedAnimation);
QT_END_HEADER
-#endif // QDECLARATIVEEASEFOLLOW_H
+#endif // QDECLARATIVESMOOTHEDANIMATION_H
diff --git a/src/declarative/util/qdeclarativesmoothedanimation_p_p.h b/src/declarative/util/qdeclarativesmoothedanimation_p_p.h
new file mode 100644
index 0000000..bdceeb3
--- /dev/null
+++ b/src/declarative/util/qdeclarativesmoothedanimation_p_p.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVESMOOTHEDANIMATION_P_H
+#define QDECLARATIVESMOOTHEDANIMATION_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 "qdeclarativesmoothedanimation_p.h"
+#include "qdeclarativeanimation_p.h"
+
+#include "qdeclarativeanimation_p_p.h"
+
+#include <qparallelanimationgroup.h>
+
+#include <private/qobject_p.h>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QSmoothedAnimation : public QAbstractAnimation
+{
+public:
+ QSmoothedAnimation(QObject *parent=0);
+
+ qreal to;
+ qreal velocity;
+ int userDuration;
+
+ int maximumEasingTime;
+ QDeclarativeSmoothedAnimation::ReversingMode reversingMode;
+
+ qreal initialVelocity;
+ qreal trackVelocity;
+
+ QDeclarativeProperty target;
+
+ int duration() const;
+ void restart();
+ void init();
+
+protected:
+ virtual void updateCurrentTime(int);
+ virtual void updateState(QAbstractAnimation::State, QAbstractAnimation::State);
+
+private:
+ qreal easeFollow(qreal);
+ qreal initialValue;
+
+ bool invert;
+
+ int finalDuration;
+
+ // Parameters for use in updateCurrentTime()
+ qreal a; // Acceleration
+ qreal d; // Deceleration
+ qreal tf; // Total time
+ qreal tp; // Time at which peak velocity occurs
+ qreal td; // Time at which decelleration begins
+ qreal vp; // Velocity at tp
+ qreal sp; // Displacement at tp
+ qreal sd; // Displacement at td
+ qreal vi; // "Normalized" initialvelocity
+ qreal s; // Total s
+
+ int lastTime;
+
+ bool recalc();
+ void delayedStop();
+
+ QTimer delayedStopTimer;
+};
+
+class QDeclarativeSmoothedAnimationPrivate : public QDeclarativePropertyAnimationPrivate
+{
+ Q_DECLARE_PUBLIC(QDeclarativeSmoothedAnimation)
+public:
+ QDeclarativeSmoothedAnimationPrivate();
+
+ QParallelAnimationGroup *wrapperGroup;
+ QSmoothedAnimation *anim;
+ QHash<QDeclarativeProperty, QSmoothedAnimation*> activeAnimations;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVESMOOTHEDANIMATION_P_H
diff --git a/src/declarative/util/qdeclarativespringfollow.cpp b/src/declarative/util/qdeclarativespringfollow.cpp
index 76d7c98..063c3df 100644
--- a/src/declarative/util/qdeclarativespringfollow.cpp
+++ b/src/declarative/util/qdeclarativespringfollow.cpp
@@ -242,8 +242,6 @@ void QDeclarativeSpringFollowPrivate::stop()
SpringFollow on y { source: rect1.y; velocity: 200 }
}
\endcode
-
- \sa EaseFollow
*/
QDeclarativeSpringFollow::QDeclarativeSpringFollow(QObject *parent)
diff --git a/src/declarative/util/qdeclarativestategroup.cpp b/src/declarative/util/qdeclarativestategroup.cpp
index 083e87d..258a9e9 100644
--- a/src/declarative/util/qdeclarativestategroup.cpp
+++ b/src/declarative/util/qdeclarativestategroup.cpp
@@ -69,6 +69,7 @@ public:
static void append_state(QDeclarativeListProperty<QDeclarativeState> *list, QDeclarativeState *state);
static int count_state(QDeclarativeListProperty<QDeclarativeState> *list);
static QDeclarativeState *at_state(QDeclarativeListProperty<QDeclarativeState> *list, int index);
+ static void clear_states(QDeclarativeListProperty<QDeclarativeState> *list);
QList<QDeclarativeState *> states;
QList<QDeclarativeTransition *> transitions;
@@ -150,7 +151,8 @@ QDeclarativeListProperty<QDeclarativeState> QDeclarativeStateGroup::statesProper
Q_D(QDeclarativeStateGroup);
return QDeclarativeListProperty<QDeclarativeState>(this, &d->states, &QDeclarativeStateGroupPrivate::append_state,
&QDeclarativeStateGroupPrivate::count_state,
- &QDeclarativeStateGroupPrivate::at_state);
+ &QDeclarativeStateGroupPrivate::at_state,
+ &QDeclarativeStateGroupPrivate::clear_states);
}
void QDeclarativeStateGroupPrivate::append_state(QDeclarativeListProperty<QDeclarativeState> *list, QDeclarativeState *state)
@@ -175,6 +177,16 @@ QDeclarativeState *QDeclarativeStateGroupPrivate::at_state(QDeclarativeListPrope
return _this->d_func()->states.at(index);
}
+void QDeclarativeStateGroupPrivate::clear_states(QDeclarativeListProperty<QDeclarativeState> *list)
+{
+ QDeclarativeStateGroup *_this = static_cast<QDeclarativeStateGroup *>(list->object);
+ _this->d_func()->setCurrentStateInternal(QString(), true);
+ for (int i = 0; i < _this->d_func()->states.count(); ++i) {
+ _this->d_func()->states.at(i)->setStateGroup(0);
+ }
+ _this->d_func()->states.clear();
+}
+
/*!
\qmlproperty list<Transition> StateGroup::transitions
This property holds a list of transitions defined by the state group.
@@ -206,13 +218,11 @@ QDeclarativeListProperty<QDeclarativeTransition> QDeclarativeStateGroup::transit
example:
\qml
- Script {
- function toggle() {
- if (button.state == 'On')
- button.state = 'Off';
- else
- button.state = 'On';
- }
+ function toggle() {
+ if (button.state == 'On')
+ button.state = 'Off';
+ else
+ button.state = 'On';
}
\endqml
diff --git a/src/declarative/util/qdeclarativestateoperations.cpp b/src/declarative/util/qdeclarativestateoperations.cpp
index 0bc81ee..3469136 100644
--- a/src/declarative/util/qdeclarativestateoperations.cpp
+++ b/src/declarative/util/qdeclarativestateoperations.cpp
@@ -609,209 +609,343 @@ QString QDeclarativeStateChangeScript::typeName() const
For more information on anchors see \l {anchor-layout}{Anchor Layouts}.
*/
-
-
-class QDeclarativeAnchorChangesPrivate : public QObjectPrivate
+class QDeclarativeAnchorSetPrivate : public QObjectPrivate
{
+ Q_DECLARE_PUBLIC(QDeclarativeAnchorSet)
public:
- QDeclarativeAnchorChangesPrivate() : target(0) {}
+ QDeclarativeAnchorSetPrivate()
+ : usedAnchors(0), fill(0),
+ centerIn(0)/*, leftMargin(0), rightMargin(0), topMargin(0), bottomMargin(0),
+ margins(0), vCenterOffset(0), hCenterOffset(0), baselineOffset(0)*/
+ {
+ }
- QDeclarativeItem *target;
- QString resetString;
+ QDeclarativeAnchors::UsedAnchors usedAnchors;
+ //### change to QDeclarativeAnchors::UsedAnchors resetAnchors
QStringList resetList;
+ QDeclarativeItem *fill;
+ QDeclarativeItem *centerIn;
+
QDeclarativeAnchorLine left;
QDeclarativeAnchorLine right;
- QDeclarativeAnchorLine horizontalCenter;
QDeclarativeAnchorLine top;
QDeclarativeAnchorLine bottom;
- QDeclarativeAnchorLine verticalCenter;
+ QDeclarativeAnchorLine vCenter;
+ QDeclarativeAnchorLine hCenter;
QDeclarativeAnchorLine baseline;
- QDeclarativeAnchorLine origLeft;
- QDeclarativeAnchorLine origRight;
- QDeclarativeAnchorLine origHCenter;
- QDeclarativeAnchorLine origTop;
- QDeclarativeAnchorLine origBottom;
- QDeclarativeAnchorLine origVCenter;
- QDeclarativeAnchorLine origBaseline;
-
- QDeclarativeAnchorLine rewindLeft;
- QDeclarativeAnchorLine rewindRight;
- QDeclarativeAnchorLine rewindHCenter;
- QDeclarativeAnchorLine rewindTop;
- QDeclarativeAnchorLine rewindBottom;
- QDeclarativeAnchorLine rewindVCenter;
- QDeclarativeAnchorLine rewindBaseline;
+ /*qreal leftMargin;
+ qreal rightMargin;
+ qreal topMargin;
+ qreal bottomMargin;
+ qreal margins;
+ qreal vCenterOffset;
+ qreal hCenterOffset;
+ qreal baselineOffset;*/
+};
- qreal fromX;
- qreal fromY;
- qreal fromWidth;
- qreal fromHeight;
+QDeclarativeAnchorSet::QDeclarativeAnchorSet(QObject *parent)
+ : QObject(*new QDeclarativeAnchorSetPrivate, parent)
+{
+}
- qreal toX;
- qreal toY;
- qreal toWidth;
- qreal toHeight;
+QDeclarativeAnchorSet::~QDeclarativeAnchorSet()
+{
+}
- qreal rewindX;
- qreal rewindY;
- qreal rewindWidth;
- qreal rewindHeight;
+QDeclarativeAnchorLine QDeclarativeAnchorSet::top() const
+{
+ Q_D(const QDeclarativeAnchorSet);
+ return d->top;
+}
- bool applyOrigLeft;
- bool applyOrigRight;
- bool applyOrigHCenter;
- bool applyOrigTop;
- bool applyOrigBottom;
- bool applyOrigVCenter;
- bool applyOrigBaseline;
-};
+void QDeclarativeAnchorSet::setTop(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasTopAnchor;
+ d->top = edge;
+}
-/*!
- \qmlproperty Item AnchorChanges::target
- This property holds the Item whose anchors will change
-*/
+void QDeclarativeAnchorSet::resetTop()
+{
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasTopAnchor;
+ d->top = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("top");
+}
-QDeclarativeAnchorChanges::QDeclarativeAnchorChanges(QObject *parent)
- : QDeclarativeStateOperation(*(new QDeclarativeAnchorChangesPrivate), parent)
+QDeclarativeAnchorLine QDeclarativeAnchorSet::bottom() const
{
+ Q_D(const QDeclarativeAnchorSet);
+ return d->bottom;
}
-QDeclarativeAnchorChanges::~QDeclarativeAnchorChanges()
+void QDeclarativeAnchorSet::setBottom(const QDeclarativeAnchorLine &edge)
{
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasBottomAnchor;
+ d->bottom = edge;
}
-QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions()
+void QDeclarativeAnchorSet::resetBottom()
{
- QDeclarativeAction a;
- a.event = this;
- return ActionList() << a;
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasBottomAnchor;
+ d->bottom = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("bottom");
}
-QDeclarativeItem *QDeclarativeAnchorChanges::object() const
+QDeclarativeAnchorLine QDeclarativeAnchorSet::verticalCenter() const
{
- Q_D(const QDeclarativeAnchorChanges);
- return d->target;
+ Q_D(const QDeclarativeAnchorSet);
+ return d->vCenter;
}
-void QDeclarativeAnchorChanges::setObject(QDeclarativeItem *target)
+void QDeclarativeAnchorSet::setVerticalCenter(const QDeclarativeAnchorLine &edge)
{
- Q_D(QDeclarativeAnchorChanges);
- d->target = target;
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasVCenterAnchor;
+ d->vCenter = edge;
}
-QString QDeclarativeAnchorChanges::reset() const
+void QDeclarativeAnchorSet::resetVerticalCenter()
{
- Q_D(const QDeclarativeAnchorChanges);
- return d->resetString;
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasVCenterAnchor;
+ d->vCenter = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("verticalCenter");
}
-void QDeclarativeAnchorChanges::setReset(const QString &reset)
+QDeclarativeAnchorLine QDeclarativeAnchorSet::baseline() const
{
- Q_D(QDeclarativeAnchorChanges);
- d->resetString = reset;
- d->resetList = d->resetString.split(QLatin1Char(','));
- for (int i = 0; i < d->resetList.count(); ++i)
- d->resetList[i] = d->resetList.at(i).trimmed();
+ Q_D(const QDeclarativeAnchorSet);
+ return d->baseline;
}
-/*!
- \qmlproperty AnchorLine AnchorChanges::left
- \qmlproperty AnchorLine AnchorChanges::right
- \qmlproperty AnchorLine AnchorChanges::horizontalCenter
- \qmlproperty AnchorLine AnchorChanges::top
- \qmlproperty AnchorLine AnchorChanges::bottom
- \qmlproperty AnchorLine AnchorChanges::verticalCenter
- \qmlproperty AnchorLine AnchorChanges::baseline
+void QDeclarativeAnchorSet::setBaseline(const QDeclarativeAnchorLine &edge)
+{
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasBaselineAnchor;
+ d->baseline = edge;
+}
- These properties change the respective anchors of the item.
-*/
+void QDeclarativeAnchorSet::resetBaseline()
+{
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasBaselineAnchor;
+ d->baseline = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("baseline");
+}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::left() const
+QDeclarativeAnchorLine QDeclarativeAnchorSet::left() const
{
- Q_D(const QDeclarativeAnchorChanges);
+ Q_D(const QDeclarativeAnchorSet);
return d->left;
}
-void QDeclarativeAnchorChanges::setLeft(const QDeclarativeAnchorLine &edge)
+void QDeclarativeAnchorSet::setLeft(const QDeclarativeAnchorLine &edge)
{
- Q_D(QDeclarativeAnchorChanges);
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasLeftAnchor;
d->left = edge;
}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::right() const
+void QDeclarativeAnchorSet::resetLeft()
{
- Q_D(const QDeclarativeAnchorChanges);
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasLeftAnchor;
+ d->left = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("left");
+}
+
+QDeclarativeAnchorLine QDeclarativeAnchorSet::right() const
+{
+ Q_D(const QDeclarativeAnchorSet);
return d->right;
}
-void QDeclarativeAnchorChanges::setRight(const QDeclarativeAnchorLine &edge)
+void QDeclarativeAnchorSet::setRight(const QDeclarativeAnchorLine &edge)
{
- Q_D(QDeclarativeAnchorChanges);
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasRightAnchor;
d->right = edge;
}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::horizontalCenter() const
+void QDeclarativeAnchorSet::resetRight()
{
- Q_D(const QDeclarativeAnchorChanges);
- return d->horizontalCenter;
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasRightAnchor;
+ d->right = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("right");
}
-void QDeclarativeAnchorChanges::setHorizontalCenter(const QDeclarativeAnchorLine &edge)
+QDeclarativeAnchorLine QDeclarativeAnchorSet::horizontalCenter() const
{
- Q_D(QDeclarativeAnchorChanges);
- d->horizontalCenter = edge;
+ Q_D(const QDeclarativeAnchorSet);
+ return d->hCenter;
}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::top() const
+void QDeclarativeAnchorSet::setHorizontalCenter(const QDeclarativeAnchorLine &edge)
{
- Q_D(const QDeclarativeAnchorChanges);
- return d->top;
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors |= QDeclarativeAnchors::HasHCenterAnchor;
+ d->hCenter = edge;
}
-void QDeclarativeAnchorChanges::setTop(const QDeclarativeAnchorLine &edge)
+void QDeclarativeAnchorSet::resetHorizontalCenter()
{
- Q_D(QDeclarativeAnchorChanges);
- d->top = edge;
+ Q_D(QDeclarativeAnchorSet);
+ d->usedAnchors &= ~QDeclarativeAnchors::HasHCenterAnchor;
+ d->hCenter = QDeclarativeAnchorLine();
+ d->resetList << QLatin1String("horizontalCenter");
}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::bottom() const
+QDeclarativeItem *QDeclarativeAnchorSet::fill() const
{
- Q_D(const QDeclarativeAnchorChanges);
- return d->bottom;
+ Q_D(const QDeclarativeAnchorSet);
+ return d->fill;
}
-void QDeclarativeAnchorChanges::setBottom(const QDeclarativeAnchorLine &edge)
+void QDeclarativeAnchorSet::setFill(QDeclarativeItem *f)
{
- Q_D(QDeclarativeAnchorChanges);
- d->bottom = edge;
+ Q_D(QDeclarativeAnchorSet);
+ d->fill = f;
}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::verticalCenter() const
+void QDeclarativeAnchorSet::resetFill()
{
- Q_D(const QDeclarativeAnchorChanges);
- return d->verticalCenter;
+ setFill(0);
+}
+
+QDeclarativeItem *QDeclarativeAnchorSet::centerIn() const
+{
+ Q_D(const QDeclarativeAnchorSet);
+ return d->centerIn;
}
-void QDeclarativeAnchorChanges::setVerticalCenter(const QDeclarativeAnchorLine &edge)
+void QDeclarativeAnchorSet::setCenterIn(QDeclarativeItem* c)
+{
+ Q_D(QDeclarativeAnchorSet);
+ d->centerIn = c;
+}
+
+void QDeclarativeAnchorSet::resetCenterIn()
+{
+ setCenterIn(0);
+}
+
+
+class QDeclarativeAnchorChangesPrivate : public QObjectPrivate
+{
+public:
+ QDeclarativeAnchorChangesPrivate()
+ : target(0), anchorSet(new QDeclarativeAnchorSet) {}
+ ~QDeclarativeAnchorChangesPrivate() { delete anchorSet; }
+
+ QDeclarativeItem *target;
+ QDeclarativeAnchorSet *anchorSet;
+
+ QDeclarativeAnchorLine origLeft;
+ QDeclarativeAnchorLine origRight;
+ QDeclarativeAnchorLine origHCenter;
+ QDeclarativeAnchorLine origTop;
+ QDeclarativeAnchorLine origBottom;
+ QDeclarativeAnchorLine origVCenter;
+ QDeclarativeAnchorLine origBaseline;
+
+ QDeclarativeAnchorLine rewindLeft;
+ QDeclarativeAnchorLine rewindRight;
+ QDeclarativeAnchorLine rewindHCenter;
+ QDeclarativeAnchorLine rewindTop;
+ QDeclarativeAnchorLine rewindBottom;
+ QDeclarativeAnchorLine rewindVCenter;
+ QDeclarativeAnchorLine rewindBaseline;
+
+ qreal fromX;
+ qreal fromY;
+ qreal fromWidth;
+ qreal fromHeight;
+
+ qreal toX;
+ qreal toY;
+ qreal toWidth;
+ qreal toHeight;
+
+ qreal rewindX;
+ qreal rewindY;
+ qreal rewindWidth;
+ qreal rewindHeight;
+
+ bool applyOrigLeft;
+ bool applyOrigRight;
+ bool applyOrigHCenter;
+ bool applyOrigTop;
+ bool applyOrigBottom;
+ bool applyOrigVCenter;
+ bool applyOrigBaseline;
+};
+
+/*!
+ \qmlproperty Item AnchorChanges::target
+ This property holds the Item whose anchors will change
+*/
+
+QDeclarativeAnchorChanges::QDeclarativeAnchorChanges(QObject *parent)
+ : QDeclarativeStateOperation(*(new QDeclarativeAnchorChangesPrivate), parent)
+{
+}
+
+QDeclarativeAnchorChanges::~QDeclarativeAnchorChanges()
+{
+}
+
+QDeclarativeAnchorChanges::ActionList QDeclarativeAnchorChanges::actions()
+{
+ QDeclarativeAction a;
+ a.event = this;
+ return ActionList() << a;
+}
+
+QDeclarativeAnchorSet *QDeclarativeAnchorChanges::anchors()
{
Q_D(QDeclarativeAnchorChanges);
- d->verticalCenter = edge;
+ return d->anchorSet;
}
-QDeclarativeAnchorLine QDeclarativeAnchorChanges::baseline() const
+QDeclarativeItem *QDeclarativeAnchorChanges::object() const
{
Q_D(const QDeclarativeAnchorChanges);
- return d->baseline;
+ return d->target;
}
-void QDeclarativeAnchorChanges::setBaseline(const QDeclarativeAnchorLine &edge)
+void QDeclarativeAnchorChanges::setObject(QDeclarativeItem *target)
{
Q_D(QDeclarativeAnchorChanges);
- d->baseline = edge;
+ d->target = target;
}
+/*!
+ \qmlproperty AnchorLine AnchorChanges::anchors.left
+ \qmlproperty AnchorLine AnchorChanges::anchors.right
+ \qmlproperty AnchorLine AnchorChanges::anchors.horizontalCenter
+ \qmlproperty AnchorLine AnchorChanges::anchors.top
+ \qmlproperty AnchorLine AnchorChanges::anchors.bottom
+ \qmlproperty AnchorLine AnchorChanges::anchors.verticalCenter
+ \qmlproperty AnchorLine AnchorChanges::anchors.baseline
+
+ These properties change the respective anchors of the item.
+
+ To reset an anchor you can assign \c undefined:
+ \qml
+ AnchorChanges {
+ target: myItem
+ left: undefined //remove myItem's left anchor
+ right: otherItem.right
+ }
+ \endqml
+*/
+
void QDeclarativeAnchorChanges::execute()
{
Q_D(QDeclarativeAnchorChanges);
@@ -835,36 +969,36 @@ void QDeclarativeAnchorChanges::execute()
d->target->anchors()->setBaseline(d->origBaseline);
//reset any anchors that have been specified
- if (d->resetList.contains(QLatin1String("left")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("left")))
d->target->anchors()->resetLeft();
- if (d->resetList.contains(QLatin1String("right")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("right")))
d->target->anchors()->resetRight();
- if (d->resetList.contains(QLatin1String("horizontalCenter")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("horizontalCenter")))
d->target->anchors()->resetHorizontalCenter();
- if (d->resetList.contains(QLatin1String("top")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("top")))
d->target->anchors()->resetTop();
- if (d->resetList.contains(QLatin1String("bottom")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("bottom")))
d->target->anchors()->resetBottom();
- if (d->resetList.contains(QLatin1String("verticalCenter")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("verticalCenter")))
d->target->anchors()->resetVerticalCenter();
- if (d->resetList.contains(QLatin1String("baseline")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("baseline")))
d->target->anchors()->resetBaseline();
//set any anchors that have been specified
- if (d->left.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setLeft(d->left);
- if (d->right.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setRight(d->right);
- if (d->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setHorizontalCenter(d->horizontalCenter);
- if (d->top.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setTop(d->top);
- if (d->bottom.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setBottom(d->bottom);
- if (d->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setVerticalCenter(d->verticalCenter);
- if (d->baseline.anchorLine != QDeclarativeAnchorLine::Invalid)
- d->target->anchors()->setBaseline(d->baseline);
+ if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setLeft(d->anchorSet->d_func()->left);
+ if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setRight(d->anchorSet->d_func()->right);
+ if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setHorizontalCenter(d->anchorSet->d_func()->hCenter);
+ if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setTop(d->anchorSet->d_func()->top);
+ if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setBottom(d->anchorSet->d_func()->bottom);
+ if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setVerticalCenter(d->anchorSet->d_func()->vCenter);
+ if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid)
+ d->target->anchors()->setBaseline(d->anchorSet->d_func()->baseline);
}
bool QDeclarativeAnchorChanges::isReversable()
@@ -879,19 +1013,19 @@ void QDeclarativeAnchorChanges::reverse()
return;
//reset any anchors set by the state
- if (d->left.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetLeft();
- if (d->right.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetRight();
- if (d->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetHorizontalCenter();
- if (d->top.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetTop();
- if (d->bottom.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetBottom();
- if (d->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetVerticalCenter();
- if (d->baseline.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetBaseline();
//restore previous anchors
@@ -977,26 +1111,26 @@ void QDeclarativeAnchorChanges::copyOriginals(QDeclarativeActionEvent *other)
QDeclarativeAnchorChangesPrivate *acp = ac->d_func();
//probably also need to revert some things
- d->applyOrigLeft = (acp->left.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("left")));
+ d->applyOrigLeft = (acp->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("left")));
- d->applyOrigRight = (acp->right.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("right")));
+ d->applyOrigRight = (acp->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("right")));
- d->applyOrigHCenter = (acp->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("horizontalCenter")));
+ d->applyOrigHCenter = (acp->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("horizontalCenter")));
- d->applyOrigTop = (acp->top.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("top")));
+ d->applyOrigTop = (acp->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("top")));
- d->applyOrigBottom = (acp->bottom.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("bottom")));
+ d->applyOrigBottom = (acp->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("bottom")));
- d->applyOrigVCenter = (acp->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("verticalCenter")));
+ d->applyOrigVCenter = (acp->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("verticalCenter")));
- d->applyOrigBaseline = (acp->baseline.anchorLine != QDeclarativeAnchorLine::Invalid ||
- acp->resetList.contains(QLatin1String("baseline")));
+ d->applyOrigBaseline = (acp->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid ||
+ acp->anchorSet->d_func()->resetList.contains(QLatin1String("baseline")));
d->origLeft = ac->d_func()->origLeft;
d->origRight = ac->d_func()->origRight;
@@ -1034,35 +1168,35 @@ void QDeclarativeAnchorChanges::clearBindings()
d->target->anchors()->resetBaseline();
//reset any anchors that have been specified
- if (d->resetList.contains(QLatin1String("left")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("left")))
d->target->anchors()->resetLeft();
- if (d->resetList.contains(QLatin1String("right")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("right")))
d->target->anchors()->resetRight();
- if (d->resetList.contains(QLatin1String("horizontalCenter")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("horizontalCenter")))
d->target->anchors()->resetHorizontalCenter();
- if (d->resetList.contains(QLatin1String("top")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("top")))
d->target->anchors()->resetTop();
- if (d->resetList.contains(QLatin1String("bottom")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("bottom")))
d->target->anchors()->resetBottom();
- if (d->resetList.contains(QLatin1String("verticalCenter")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("verticalCenter")))
d->target->anchors()->resetVerticalCenter();
- if (d->resetList.contains(QLatin1String("baseline")))
+ if (d->anchorSet->d_func()->resetList .contains(QLatin1String("baseline")))
d->target->anchors()->resetBaseline();
//reset any anchors that we'll be setting in the state
- if (d->left.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->left.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetLeft();
- if (d->right.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->right.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetRight();
- if (d->horizontalCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->hCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetHorizontalCenter();
- if (d->top.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->top.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetTop();
- if (d->bottom.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->bottom.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetBottom();
- if (d->verticalCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->vCenter.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetVerticalCenter();
- if (d->baseline.anchorLine != QDeclarativeAnchorLine::Invalid)
+ if (d->anchorSet->d_func()->baseline.anchorLine != QDeclarativeAnchorLine::Invalid)
d->target->anchors()->resetBaseline();
}
diff --git a/src/declarative/util/qdeclarativestateoperations_p.h b/src/declarative/util/qdeclarativestateoperations_p.h
index 66a8717..c97b2da 100644
--- a/src/declarative/util/qdeclarativestateoperations_p.h
+++ b/src/declarative/util/qdeclarativestateoperations_p.h
@@ -143,54 +143,132 @@ public:
virtual void execute();
};
-class QDeclarativeAnchorChangesPrivate;
-class Q_DECLARATIVE_EXPORT QDeclarativeAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent
+class QDeclarativeAnchorChanges;
+class QDeclarativeAnchorSetPrivate;
+class Q_AUTOTEST_EXPORT QDeclarativeAnchorSet : public QObject
{
Q_OBJECT
- Q_DECLARE_PRIVATE(QDeclarativeAnchorChanges)
- Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject)
- Q_PROPERTY(QString reset READ reset WRITE setReset)
- Q_PROPERTY(QDeclarativeAnchorLine left READ left WRITE setLeft)
- Q_PROPERTY(QDeclarativeAnchorLine right READ right WRITE setRight)
- Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter)
- Q_PROPERTY(QDeclarativeAnchorLine top READ top WRITE setTop)
- Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom WRITE setBottom)
- Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter)
- Q_PROPERTY(QDeclarativeAnchorLine baseline READ baseline WRITE setBaseline)
+ Q_PROPERTY(QDeclarativeAnchorLine left READ left WRITE setLeft RESET resetLeft)
+ Q_PROPERTY(QDeclarativeAnchorLine right READ right WRITE setRight RESET resetRight)
+ Q_PROPERTY(QDeclarativeAnchorLine horizontalCenter READ horizontalCenter WRITE setHorizontalCenter RESET resetHorizontalCenter)
+ Q_PROPERTY(QDeclarativeAnchorLine top READ top WRITE setTop RESET resetTop)
+ Q_PROPERTY(QDeclarativeAnchorLine bottom READ bottom WRITE setBottom RESET resetBottom)
+ Q_PROPERTY(QDeclarativeAnchorLine verticalCenter READ verticalCenter WRITE setVerticalCenter RESET resetVerticalCenter)
+ Q_PROPERTY(QDeclarativeAnchorLine baseline READ baseline WRITE setBaseline RESET resetBaseline)
+ //Q_PROPERTY(QDeclarativeItem *fill READ fill WRITE setFill RESET resetFill)
+ //Q_PROPERTY(QDeclarativeItem *centerIn READ centerIn WRITE setCenterIn RESET resetCenterIn)
+
+ /*Q_PROPERTY(qreal margins READ margins WRITE setMargins NOTIFY marginsChanged)
+ Q_PROPERTY(qreal leftMargin READ leftMargin WRITE setLeftMargin NOTIFY leftMarginChanged)
+ Q_PROPERTY(qreal rightMargin READ rightMargin WRITE setRightMargin NOTIFY rightMarginChanged)
+ Q_PROPERTY(qreal horizontalCenterOffset READ horizontalCenterOffset WRITE setHorizontalCenterOffset NOTIFY horizontalCenterOffsetChanged())
+ Q_PROPERTY(qreal topMargin READ topMargin WRITE setTopMargin NOTIFY topMarginChanged)
+ Q_PROPERTY(qreal bottomMargin READ bottomMargin WRITE setBottomMargin NOTIFY bottomMarginChanged)
+ Q_PROPERTY(qreal verticalCenterOffset READ verticalCenterOffset WRITE setVerticalCenterOffset NOTIFY verticalCenterOffsetChanged())
+ Q_PROPERTY(qreal baselineOffset READ baselineOffset WRITE setBaselineOffset NOTIFY baselineOffsetChanged())*/
public:
- QDeclarativeAnchorChanges(QObject *parent=0);
- ~QDeclarativeAnchorChanges();
-
- virtual ActionList actions();
-
- QDeclarativeItem *object() const;
- void setObject(QDeclarativeItem *);
-
- QString reset() const;
- void setReset(const QString &);
+ QDeclarativeAnchorSet(QObject *parent=0);
+ virtual ~QDeclarativeAnchorSet();
QDeclarativeAnchorLine left() const;
void setLeft(const QDeclarativeAnchorLine &edge);
+ void resetLeft();
QDeclarativeAnchorLine right() const;
void setRight(const QDeclarativeAnchorLine &edge);
+ void resetRight();
QDeclarativeAnchorLine horizontalCenter() const;
void setHorizontalCenter(const QDeclarativeAnchorLine &edge);
+ void resetHorizontalCenter();
QDeclarativeAnchorLine top() const;
void setTop(const QDeclarativeAnchorLine &edge);
+ void resetTop();
QDeclarativeAnchorLine bottom() const;
void setBottom(const QDeclarativeAnchorLine &edge);
+ void resetBottom();
QDeclarativeAnchorLine verticalCenter() const;
void setVerticalCenter(const QDeclarativeAnchorLine &edge);
+ void resetVerticalCenter();
QDeclarativeAnchorLine baseline() const;
void setBaseline(const QDeclarativeAnchorLine &edge);
+ void resetBaseline();
+
+ QDeclarativeItem *fill() const;
+ void setFill(QDeclarativeItem *);
+ void resetFill();
+
+ QDeclarativeItem *centerIn() const;
+ void setCenterIn(QDeclarativeItem *);
+ void resetCenterIn();
+
+ /*qreal leftMargin() const;
+ void setLeftMargin(qreal);
+
+ qreal rightMargin() const;
+ void setRightMargin(qreal);
+
+ qreal horizontalCenterOffset() const;
+ void setHorizontalCenterOffset(qreal);
+
+ qreal topMargin() const;
+ void setTopMargin(qreal);
+
+ qreal bottomMargin() const;
+ void setBottomMargin(qreal);
+
+ qreal margins() const;
+ void setMargins(qreal);
+
+ qreal verticalCenterOffset() const;
+ void setVerticalCenterOffset(qreal);
+
+ qreal baselineOffset() const;
+ void setBaselineOffset(qreal);*/
+
+ QDeclarativeAnchors::UsedAnchors usedAnchors() const;
+
+/*Q_SIGNALS:
+ void leftMarginChanged();
+ void rightMarginChanged();
+ void topMarginChanged();
+ void bottomMarginChanged();
+ void marginsChanged();
+ void verticalCenterOffsetChanged();
+ void horizontalCenterOffsetChanged();
+ void baselineOffsetChanged();*/
+
+private:
+ friend class QDeclarativeAnchorChanges;
+ Q_DISABLE_COPY(QDeclarativeAnchorSet)
+ Q_DECLARE_PRIVATE(QDeclarativeAnchorSet)
+};
+
+class QDeclarativeAnchorChangesPrivate;
+class Q_DECLARATIVE_EXPORT QDeclarativeAnchorChanges : public QDeclarativeStateOperation, public QDeclarativeActionEvent
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDeclarativeAnchorChanges)
+
+ Q_PROPERTY(QDeclarativeItem *target READ object WRITE setObject)
+ Q_PROPERTY(QDeclarativeAnchorSet *anchors READ anchors CONSTANT)
+
+public:
+ QDeclarativeAnchorChanges(QObject *parent=0);
+ ~QDeclarativeAnchorChanges();
+
+ virtual ActionList actions();
+
+ QDeclarativeAnchorSet *anchors();
+
+ QDeclarativeItem *object() const;
+ void setObject(QDeclarativeItem *);
virtual void execute();
virtual bool isReversable();
@@ -212,6 +290,7 @@ QT_END_NAMESPACE
QML_DECLARE_TYPE(QDeclarativeParentChange)
QML_DECLARE_TYPE(QDeclarativeStateChangeScript)
+QML_DECLARE_TYPE(QDeclarativeAnchorSet)
QML_DECLARE_TYPE(QDeclarativeAnchorChanges)
QT_END_HEADER
diff --git a/src/declarative/util/qdeclarativetransition.cpp b/src/declarative/util/qdeclarativetransition.cpp
index 4326a55..1e8be7f 100644
--- a/src/declarative/util/qdeclarativetransition.cpp
+++ b/src/declarative/util/qdeclarativetransition.cpp
@@ -116,9 +116,9 @@ void QDeclarativeTransitionPrivate::append_animation(QDeclarativeListProperty<QD
void ParallelAnimationWrapper::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState)
{
QParallelAnimationGroup::updateState(newState, oldState);
- if (newState == Stopped &&
- ((direction() == QAbstractAnimation::Forward && currentLoopTime() == duration()) ||
- (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0)))
+ if (newState == Stopped && (duration() == -1
+ || (direction() == QAbstractAnimation::Forward && currentLoopTime() == duration())
+ || (direction() == QAbstractAnimation::Backward && currentLoopTime() == 0)))
{
trans->complete();
}
diff --git a/src/declarative/util/qdeclarativeutilmodule.cpp b/src/declarative/util/qdeclarativeutilmodule.cpp
index d79c6ba..7f2f64a 100644
--- a/src/declarative/util/qdeclarativeutilmodule.cpp
+++ b/src/declarative/util/qdeclarativeutilmodule.cpp
@@ -45,7 +45,7 @@
#include "qdeclarativebehavior_p.h"
#include "qdeclarativebind_p.h"
#include "qdeclarativeconnections_p.h"
-#include "qdeclarativeeasefollow_p.h"
+#include "qdeclarativesmoothedanimation_p.h"
#include "qdeclarativefontloader_p.h"
#include "qdeclarativelistaccessor_p.h"
#include "qdeclarativelistmodel_p.h"
@@ -111,7 +111,7 @@ void QDeclarativeUtilModule::defineModule()
qmlRegisterType<QDeclarativeBind>("Qt",4,6,"Binding");
qmlRegisterType<QDeclarativeColorAnimation>("Qt",4,6,"ColorAnimation");
qmlRegisterType<QDeclarativeConnections>("Qt",4,6,"Connections");
- qmlRegisterType<QDeclarativeEaseFollow>("Qt",4,6,"EaseFollow");
+ qmlRegisterType<QDeclarativeSmoothedAnimation>("Qt",4,6,"SmoothedAnimation");
qmlRegisterType<QDeclarativeFontLoader>("Qt",4,6,"FontLoader");
qmlRegisterType<QDeclarativeListElement>("Qt",4,6,"ListElement");
qmlRegisterType<QDeclarativeNumberAnimation>("Qt",4,6,"NumberAnimation");
@@ -140,6 +140,7 @@ void QDeclarativeUtilModule::defineModule()
qmlRegisterType<QDeclarativeAnchors>();
qmlRegisterType<QDeclarativeStateOperation>();
+ qmlRegisterType<QDeclarativeAnchorSet>();
qmlRegisterTypeEnums<QDeclarativeAbstractAnimation>("Animation");
diff --git a/src/declarative/util/qdeclarativeview.cpp b/src/declarative/util/qdeclarativeview.cpp
index d97fb5f..22a7873 100644
--- a/src/declarative/util/qdeclarativeview.cpp
+++ b/src/declarative/util/qdeclarativeview.cpp
@@ -157,6 +157,7 @@ void QDeclarativeViewPrivate::execute()
{
delete root;
delete component;
+ initialSize = QSize();
component = new QDeclarativeComponent(&engine, source, q);
if (!component->isLoading()) {
@@ -289,7 +290,6 @@ QDeclarativeView::~QDeclarativeView()
void QDeclarativeView::setSource(const QUrl& url)
{
d->source = url;
- d->engine.setBaseUrl(url);
d->execute();
}
@@ -448,8 +448,8 @@ void QDeclarativeView::setRootObject(QObject *obj)
d->root = item;
d->qmlRoot = item;
- connect(item, SIGNAL(widthChanged(qreal)), this, SLOT(sizeChanged()));
- connect(item, SIGNAL(heightChanged(qreal)), this, SLOT(sizeChanged()));
+ connect(item, SIGNAL(widthChanged()), this, SLOT(sizeChanged()));
+ connect(item, SIGNAL(heightChanged()), this, SLOT(sizeChanged()));
if (d->initialSize.height() <= 0 && d->qmlRoot->width() > 0)
d->initialSize.setWidth(d->qmlRoot->width());
if (d->initialSize.height() <= 0 && d->qmlRoot->height() > 0)
diff --git a/src/declarative/util/qdeclarativexmllistmodel.cpp b/src/declarative/util/qdeclarativexmllistmodel.cpp
index f7beeaa..efc614b 100644
--- a/src/declarative/util/qdeclarativexmllistmodel.cpp
+++ b/src/declarative/util/qdeclarativexmllistmodel.cpp
@@ -57,6 +57,7 @@
#include <QBuffer>
#include <QNetworkRequest>
#include <QNetworkReply>
+#include <QTimer>
#include <private/qobject_p.h>
@@ -67,6 +68,8 @@ QT_BEGIN_NAMESPACE
typedef QPair<int, int> QDeclarativeXmlListRange;
+#define XMLLISTMODEL_CLEAR_ID 0
+
/*!
\qmlclass XmlRole QDeclarativeXmlListModelRole
\since 4.7
@@ -127,9 +130,10 @@ class QDeclarativeXmlQuery : public QThread
Q_OBJECT
public:
QDeclarativeXmlQuery(QObject *parent=0)
- : QThread(parent), m_quit(false), m_abortQueryId(-1), m_queryIds(0) {
+ : QThread(parent), m_quit(false), m_abortQueryId(-1), m_queryIds(XMLLISTMODEL_CLEAR_ID + 1) {
qRegisterMetaType<QDeclarativeXmlQueryResult>("QDeclarativeXmlQueryResult");
}
+
~QDeclarativeXmlQuery() {
m_mutex.lock();
m_quit = true;
@@ -173,22 +177,6 @@ public:
return job.queryId;
}
- QList<QList<QVariant> > modelData() {
- QMutexLocker locker(&m_mutex);
- return m_modelData;
- }
-
- QList<QDeclarativeXmlListRange> insertedItemRanges() {
- QMutexLocker locker(&m_mutex);
- return m_insertedItemRanges;
- }
-
- QList<QDeclarativeXmlListRange> removedItemRanges() {
- QMutexLocker locker(&m_mutex);
- return m_removedItemRanges;
- }
-
-
Q_SIGNALS:
void queryCompleted(const QDeclarativeXmlQueryResult &);
@@ -254,13 +242,10 @@ void QDeclarativeXmlQuery::doQueryJob()
query.setQuery(job.namespaces + job.query);
query.evaluateTo(&r);
- //qDebug() << r;
-
//always need a single root element
QByteArray xml = "<dummy:items xmlns:dummy=\"http://qtsotware.com/dummy\">\n" + r.toUtf8() + "</dummy:items>";
QBuffer b(&xml);
b.open(QIODevice::ReadOnly);
- //qDebug() << xml;
QString namespaces = QLatin1String("declare namespace dummy=\"http://qtsotware.com/dummy\";\n") + job.namespaces;
QString prefix = QLatin1String("doc($inputDocument)/dummy:items") +
@@ -278,7 +263,6 @@ void QDeclarativeXmlQuery::doQueryJob()
if (item.isAtomicValue())
count = item.toAtomicValue().toInt();
}
- //qDebug() << count;
job.data = xml;
m_prefix = namespaces + prefix + QLatin1Char('/');
@@ -552,7 +536,7 @@ QHash<int,QVariant> QDeclarativeXmlListModel::data(int index, const QList<int> &
for (int i = 0; i < roles.size(); ++i) {
int role = roles.at(i);
int roleIndex = d->roles.indexOf(role);
- rv.insert(role, roleIndex == -1 ? QVariant() : d->data.at(roleIndex).at(index));
+ rv.insert(role, roleIndex == -1 ? QVariant() : d->data.value(roleIndex).value(index));
}
return rv;
}
@@ -561,7 +545,7 @@ QVariant QDeclarativeXmlListModel::data(int index, int role) const
{
Q_D(const QDeclarativeXmlListModel);
int roleIndex = d->roles.indexOf(role);
- return (roleIndex == -1) ? QVariant() : d->data.at(roleIndex).at(index);
+ return (roleIndex == -1) ? QVariant() : d->data.value(roleIndex).value(index);
}
/*!
@@ -606,7 +590,8 @@ void QDeclarativeXmlListModel::setSource(const QUrl &src)
Q_D(QDeclarativeXmlListModel);
if (d->src != src) {
d->src = src;
- reload();
+ if (d->xml.isEmpty()) // src is only used if d->xml is not set
+ reload();
emit sourceChanged();
}
}
@@ -683,23 +668,13 @@ void QDeclarativeXmlListModel::setNamespaceDeclarations(const QString &declarati
/*!
\qmlproperty enum XmlListModel::status
+ Specifies the model loading status, which can be one of the following:
- This property holds the status of data source loading. It can be one of:
- \list
- \o Null - no data source has been set
- \o Ready - the data source has been loaded
- \o Loading - the data source is currently being loaded
- \o Error - an error occurred while loading the data source
- \endlist
-
- Note that a change in the status property does not cause anything to happen
- (although it reflects what has happened to the XmlListModel internally). If you wish
- to react to the change in status you need to do it yourself, for example in one
- of the following ways:
\list
- \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: xmlListModel.status = XmlListModel.Ready;}
- \o Do something inside the onStatusChanged signal handler, e.g. XmlListModel{id: xmlListModel; onStatusChanged: if(xmlListModel.status == XmlListModel.Ready) console.log('Loaded');}
- \o Bind to the status variable somewhere, e.g. Text{text: if(xmlListModel.status!=XmlListModel.Ready){'Not Loaded';}else{'Loaded';}}
+ \o Null - No XML data has been set for this model.
+ \o Ready - The XML data has been loaded into the model.
+ \o Loading - The model is in the process of reading and loading XML data.
+ \o Error - An error occurred while the model was loading.
\endlist
\sa progress
@@ -714,10 +689,17 @@ QDeclarativeXmlListModel::Status QDeclarativeXmlListModel::status() const
/*!
\qmlproperty real XmlListModel::progress
- This property holds the progress of data source loading, from 0.0 (nothing loaded)
- to 1.0 (finished).
+ This indicates the current progress of the downloading of the XML data
+ source. This value ranges from 0.0 (no data downloaded) to
+ 1.0 (all data downloaded). If the XML data is not from a remote source,
+ the progress becomes 1.0 as soon as the data is read.
+
+ Note that when the progress is 1.0, the XML data has been downloaded, but
+ it is yet to be loaded into the model at this point. Use the status
+ property to find out when the XML data has been read and loaded into
+ the model.
- \sa status
+ \sa status, source
*/
qreal QDeclarativeXmlListModel::progress() const
{
@@ -748,6 +730,8 @@ void QDeclarativeXmlListModel::componentComplete()
Otherwise, items are only added if the model does not already
contain items with matching key role values.
+
+ \sa XmlRole::isKey
*/
void QDeclarativeXmlListModel::reload()
{
@@ -759,27 +743,8 @@ void QDeclarativeXmlListModel::reload()
globalXmlQuery()->abort(d->queryId);
d->queryId = -1;
- int count = d->size;
- if (count < 0)
+ if (d->size < 0)
d->size = 0;
- bool hasKeys = false;
- for (int i=0; i<d->roleObjects.count(); i++) {
- if (d->roleObjects[i]->isKey()) {
- hasKeys = true;
- break;
- }
- }
- if (!hasKeys) {
- d->data.clear();
- d->size = 0;
- if (count > 0) {
- emit itemsRemoved(0, count);
- emit countChanged();
- }
- }
-
- if (d->src.isEmpty() && d->xml.isEmpty())
- return;
if (d->reply) {
d->reply->abort();
@@ -790,9 +755,19 @@ void QDeclarativeXmlListModel::reload()
if (!d->xml.isEmpty()) {
d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, d->xml.toUtf8(), &d->roleObjects, d->keyRoleResultsCache);
d->progress = 1.0;
- d->status = Ready;
+ d->status = Loading;
+ emit progressChanged(d->progress);
+ emit statusChanged(d->status);
+ return;
+ }
+
+ if (d->src.isEmpty()) {
+ d->queryId = XMLLISTMODEL_CLEAR_ID;
+ d->progress = 1.0;
+ d->status = Loading;
emit progressChanged(d->progress);
emit statusChanged(d->status);
+ QTimer::singleShot(0, this, SLOT(dataCleared()));
return;
}
@@ -831,18 +806,33 @@ void QDeclarativeXmlListModel::requestFinished()
disconnect(d->reply, 0, this, 0);
d->reply->deleteLater();
d->reply = 0;
+
+ int count = this->count();
+ d->data.clear();
+ d->size = 0;
+ if (count > 0) {
+ emit itemsRemoved(0, count);
+ emit countChanged();
+ }
+
d->status = Error;
+ d->queryId = -1;
+ emit statusChanged(d->status);
} else {
- d->status = Ready;
QByteArray data = d->reply->readAll();
- d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
+ if (data.isEmpty()) {
+ d->queryId = XMLLISTMODEL_CLEAR_ID;
+ QTimer::singleShot(0, this, SLOT(dataCleared()));
+ } else {
+ d->queryId = globalXmlQuery()->doQuery(d->query, d->namespaces, data, &d->roleObjects, d->keyRoleResultsCache);
+ }
disconnect(d->reply, 0, this, 0);
d->reply->deleteLater();
d->reply = 0;
+
+ d->progress = 1.0;
+ emit progressChanged(d->progress);
}
- d->progress = 1.0;
- emit progressChanged(d->progress);
- emit statusChanged(d->status);
}
void QDeclarativeXmlListModel::requestProgress(qint64 received, qint64 total)
@@ -854,23 +844,58 @@ void QDeclarativeXmlListModel::requestProgress(qint64 received, qint64 total)
}
}
+void QDeclarativeXmlListModel::dataCleared()
+{
+ Q_D(QDeclarativeXmlListModel);
+ QDeclarativeXmlQueryResult r;
+ r.queryId = XMLLISTMODEL_CLEAR_ID;
+ r.size = 0;
+ r.removed << qMakePair(0, count());
+ r.keyRoleResultsCache = d->keyRoleResultsCache;
+ queryCompleted(r);
+}
+
void QDeclarativeXmlListModel::queryCompleted(const QDeclarativeXmlQueryResult &result)
{
Q_D(QDeclarativeXmlListModel);
if (result.queryId != d->queryId)
return;
+
+ int origCount = d->size;
bool sizeChanged = result.size != d->size;
+
d->size = result.size;
d->data = result.data;
d->keyRoleResultsCache = result.keyRoleResultsCache;
+ d->status = Ready;
+ d->queryId = -1;
+
+ bool hasKeys = false;
+ for (int i=0; i<d->roleObjects.count(); i++) {
+ if (d->roleObjects[i]->isKey()) {
+ hasKeys = true;
+ break;
+ }
+ }
+ if (!hasKeys) {
+ if (!(origCount == 0 && d->size == 0)) {
+ emit itemsRemoved(0, origCount);
+ emit itemsInserted(0, d->size);
+ emit countChanged();
+ }
+
+ } else {
- for (int i=0; i<result.removed.count(); i++)
- emit itemsRemoved(result.removed[i].first, result.removed[i].second);
- for (int i=0; i<result.inserted.count(); i++)
- emit itemsInserted(result.inserted[i].first, result.inserted[i].second);
+ for (int i=0; i<result.removed.count(); i++)
+ emit itemsRemoved(result.removed[i].first, result.removed[i].second);
+ for (int i=0; i<result.inserted.count(); i++)
+ emit itemsInserted(result.inserted[i].first, result.inserted[i].second);
- if (sizeChanged)
- emit countChanged();
+ if (sizeChanged)
+ emit countChanged();
+ }
+
+ emit statusChanged(d->status);
}
QT_END_NAMESPACE
diff --git a/src/declarative/util/qdeclarativexmllistmodel_p.h b/src/declarative/util/qdeclarativexmllistmodel_p.h
index 7bb0f0e..7b85476 100644
--- a/src/declarative/util/qdeclarativexmllistmodel_p.h
+++ b/src/declarative/util/qdeclarativexmllistmodel_p.h
@@ -117,7 +117,7 @@ public:
virtual void componentComplete();
Q_SIGNALS:
- void statusChanged(Status);
+ void statusChanged(QDeclarativeXmlListModel::Status);
void progressChanged(qreal progress);
void countChanged();
void sourceChanged();
@@ -135,6 +135,7 @@ public Q_SLOTS:
private Q_SLOTS:
void requestFinished();
void requestProgress(qint64,qint64);
+ void dataCleared();
void queryCompleted(const QDeclarativeXmlQueryResult &);
private:
diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri
index f537806..4163596 100644
--- a/src/declarative/util/util.pri
+++ b/src/declarative/util/util.pri
@@ -8,7 +8,7 @@ SOURCES += \
$$PWD/qdeclarativeanimation.cpp \
$$PWD/qdeclarativesystempalette.cpp \
$$PWD/qdeclarativespringfollow.cpp \
- $$PWD/qdeclarativeeasefollow.cpp \
+ $$PWD/qdeclarativesmoothedanimation.cpp \
$$PWD/qdeclarativestate.cpp\
$$PWD/qdeclarativetransitionmanager.cpp \
$$PWD/qdeclarativestateoperations.cpp \
@@ -37,7 +37,8 @@ HEADERS += \
$$PWD/qdeclarativeanimation_p_p.h \
$$PWD/qdeclarativesystempalette_p.h \
$$PWD/qdeclarativespringfollow_p.h \
- $$PWD/qdeclarativeeasefollow_p.h \
+ $$PWD/qdeclarativesmoothedanimation_p.h \
+ $$PWD/qdeclarativesmoothedanimation_p_p.h \
$$PWD/qdeclarativestate_p.h\
$$PWD/qdeclarativestateoperations_p.h \
$$PWD/qdeclarativepropertychanges_p.h \
diff --git a/src/gui/dialogs/qdialog.cpp b/src/gui/dialogs/qdialog.cpp
index 4faa193..3f8cc72 100644
--- a/src/gui/dialogs/qdialog.cpp
+++ b/src/gui/dialogs/qdialog.cpp
@@ -69,7 +69,6 @@ extern bool qt_wince_is_smartphone(); //is defined in qguifunctions_wce.cpp
# include "qfontdialog.h"
# include "qcolordialog.h"
# include "qwizard.h"
-# include "qmenubar.h"
#endif
#if defined(Q_WS_S60)
@@ -529,12 +528,6 @@ int QDialog::exec()
#endif //Q_WS_WINCE_WM
#ifdef Q_OS_SYMBIAN
-#ifndef QT_NO_MENUBAR
- QMenuBar *menuBar = 0;
- if (!findChild<QMenuBar *>())
- menuBar = new QMenuBar(this);
-#endif
-
if (qobject_cast<QFileDialog *>(this) || qobject_cast<QFontDialog *>(this) ||
qobject_cast<QColorDialog *>(this) || qobject_cast<QWizard *>(this))
showMaximized();
@@ -566,13 +559,6 @@ int QDialog::exec()
delete menuBar;
#endif //QT_NO_MENUBAR
#endif //Q_WS_WINCE_WM
-#ifdef Q_OS_SYMBIAN
-#ifndef QT_NO_MENUBAR
- else if (menuBar)
- delete menuBar;
-#endif //QT_NO_MENUBAR
-#endif //Q_OS_SYMBIAN
-
return res;
}
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index ef2b223..3b5fb9f 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -723,9 +723,15 @@ void QFileDialog::setVisible(bool visible)
// Set WA_DontShowOnScreen so that QDialog::setVisible(visible) below
// updates the state correctly, but skips showing the non-native version:
setAttribute(Qt::WA_DontShowOnScreen);
+ //So the completer don't try to complete and therefore to show a popup
+ d->completer->setModel(0);
} else {
d->nativeDialogInUse = false;
setAttribute(Qt::WA_DontShowOnScreen, false);
+ if (d->proxyModel != 0)
+ d->completer->setModel(d->proxyModel);
+ else
+ d->completer->setModel(d->model);
}
}
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 2f1933c..aba69b7 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -1373,6 +1373,16 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
if (!showDrives && !newPathDir.exists())
return d->index(rootPath());
+ //We remove the watcher on the previous path
+ if (!rootPath().isEmpty()) {
+ //This remove the watcher for the old rootPath
+ d->fileInfoGatherer.removePath(rootPath());
+ //This line "marks" the node as dirty, so the next fetchMore
+ //call on the path will ask the gatherer to install a watcher again
+ //But it doesn't re-fetch everything
+ d->node(rootPath())->populatedChildren = false;
+ }
+
// We have a new valid root path
d->rootDir = newPathDir;
QModelIndex newRootIndex;
diff --git a/src/gui/dialogs/qmessagebox.cpp b/src/gui/dialogs/qmessagebox.cpp
index df8b525..fe25b0f 100644
--- a/src/gui/dialogs/qmessagebox.cpp
+++ b/src/gui/dialogs/qmessagebox.cpp
@@ -65,6 +65,10 @@
#include <QtGui/qfontmetrics.h>
#include <QtGui/qclipboard.h>
+#ifndef QT_NO_STYLE_S60
+#include <qs60style.h>
+#endif
+
#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
@@ -383,6 +387,16 @@ void QMessageBoxPrivate::updateSize()
int height = (layout->hasHeightForWidth())
? layout->totalHeightForWidth(width)
: layout->totalMinimumSize().height();
+
+#ifndef QT_NO_STYLE_S60
+ QS60Style *s60Style = 0;
+ s60Style = qobject_cast<QS60Style *>(QApplication::style());
+
+ //use custom pixel metric to deduce the minimum height of the messagebox
+ if (s60Style)
+ height = qMax(height, s60Style->pixelMetric((QStyle::PixelMetric)PM_MessageBoxHeight));
+#endif
+
q->setFixedSize(width, height);
QCoreApplication::removePostedEvents(q, QEvent::LayoutRequest);
}
diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp
index 9a552cf..498245c 100644
--- a/src/gui/egl/qegl.cpp
+++ b/src/gui/egl/qegl.cpp
@@ -528,7 +528,7 @@ QEglProperties QEglContext::configProperties() const
return QEglProperties(config());
}
-#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
+#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
_eglCreateImageKHR eglCreateImageKHR = 0;
_eglDestroyImageKHR eglDestroyImageKHR = 0;
#endif
@@ -556,10 +556,12 @@ EGLDisplay QEgl::display()
}
// Resolve the egl extension function pointers:
+#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) {
eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR");
eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR");
}
+#endif
}
return dpy;
diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h
index c659796..540cd3d 100644
--- a/src/gui/egl/qegl_p.h
+++ b/src/gui/egl/qegl_p.h
@@ -110,20 +110,49 @@ QT_BEGIN_NAMESPACE
#define EGLAPIENTRY
#endif
-#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
+// Try to get some info to debug the symbian build failues:
+#ifdef Q_OS_SYMBIAN
+
+#ifdef EGL_KHR_image
+#warning "EGL_KHR_image is defined"
+#else
+#warning "EGL_KHR_image is NOT defined"
+#endif
+
+#ifdef EGL_KHR_image_base
+#warning "EGL_KHR_image_base is defined"
+#else
+#warning "EGL_KHR_image_base is NOT defined"
+#endif
+
+#ifdef EGL_EGLEXT_PROTOTYPES
+#warning "EGL_EGLEXT_PROTOTYPES is defined"
+#else
+#warning "EGL_EGLEXT_PROTOTYPES NOT not defined"
+#endif
+
+#endif
+
+// Declare/define the bits of EGL_KHR_image_base we need:
+#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
typedef void *EGLImageKHR;
#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0)
#define EGL_IMAGE_PRESERVED_KHR 0x30D2
+#endif
+// It is possible that something has included eglext.h (like Symbian 10.1's broken egl.h), in
+// which case, EGL_KHR_image/EGL_KHR_image_base will be defined. They may have also defined
+// the actual function prototypes, but generally EGL_EGLEXT_PROTOTYPES will be defined in that
+// case and we shouldn't re-define them here.
+#if (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*);
typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR);
// Defined in qegl.cpp:
extern Q_GUI_EXPORT _eglCreateImageKHR eglCreateImageKHR;
extern Q_GUI_EXPORT _eglDestroyImageKHR eglDestroyImageKHR;
-
-#endif // !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base)
+#endif // (defined(EGL_KHR_image) || defined(EGL_KHR_image_base)) && !defined(EGL_EGLEXT_PROTOTYPES)
#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap)
#define EGL_NATIVE_PIXMAP_KHR 0x30B0
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 66b262c..71f248d 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -731,6 +731,9 @@
#include <QtGui/qevent.h>
#include <QtGui/qinputcontext.h>
#include <QtGui/qgraphicseffect.h>
+#ifndef QT_NO_ACCESSIBILITY
+# include "qaccessible.h"
+#endif
#include <private/qgraphicsitem_p.h>
#include <private/qgraphicswidget_p.h>
@@ -738,6 +741,7 @@
#include <private/qtextdocumentlayout_p.h>
#include <private/qtextengine_p.h>
#include <private/qwidget_p.h>
+#include <private/qapplication_p.h>
#ifdef Q_WS_X11
#include <private/qt_x11_p.h>
@@ -1179,6 +1183,9 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
}
+ // Resolve depth.
+ invalidateDepthRecursively();
+
if ((parent = newParent)) {
if (parent->d_func()->scene && parent->d_func()->scene != scene) {
// Move this item to its new parent's scene
@@ -1229,8 +1236,6 @@ void QGraphicsItemPrivate::setParentItemHelper(QGraphicsItem *newParent, const Q
}
}
- // Resolve depth.
- invalidateDepthRecursively();
dirtySceneTransform = 1;
// Restore the sub focus chain.
@@ -1931,7 +1936,8 @@ void QGraphicsItem::setCacheMode(CacheMode mode, const QSize &logicalCacheSize)
d_ptr->cacheMode = mode;
bool noVisualChange = (mode == NoCache && lastMode == NoCache)
|| (mode == NoCache && lastMode == DeviceCoordinateCache)
- || (mode == DeviceCoordinateCache && lastMode == NoCache);
+ || (mode == DeviceCoordinateCache && lastMode == NoCache)
+ || (mode == DeviceCoordinateCache && lastMode == DeviceCoordinateCache);
if (mode == NoCache) {
d_ptr->removeExtraItemCache();
} else {
@@ -2225,8 +2231,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly, bo
QGraphicsItemCache *c = (QGraphicsItemCache *)qVariantValue<void *>(extra(ExtraCacheData));
if (c)
c->purge();
- if (scene)
+ if (scene) {
+#ifndef QT_NO_GRAPHICSEFFECT
+ invalidateParentGraphicsEffectsRecursively();
+#endif //QT_NO_GRAPHICSEFFECT
scene->d_func()->markDirty(q_ptr, QRectF(), /*invalidateChildren=*/false, /*force=*/true);
+ }
}
// Certain properties are dropped as an item becomes invisible.
@@ -3625,7 +3635,7 @@ void QGraphicsItem::setPos(const QPointF &pos)
return;
// Update and repositition.
- if (!(d_ptr->flags & ItemSendsGeometryChanges) && !(d_ptr->flags & ItemSendsScenePositionChanges)) {
+ if (!(d_ptr->flags & (ItemSendsGeometryChanges | ItemSendsScenePositionChanges))) {
d_ptr->setPosHelper(pos);
return;
}
@@ -3918,6 +3928,22 @@ void QGraphicsItem::setTransformations(const QList<QGraphicsTransform *> &transf
/*!
\internal
*/
+void QGraphicsItemPrivate::prependGraphicsTransform(QGraphicsTransform *t)
+{
+ if (!transformData)
+ transformData = new QGraphicsItemPrivate::TransformData;
+ if (!transformData->graphicsTransforms.contains(t))
+ transformData->graphicsTransforms.prepend(t);
+
+ Q_Q(QGraphicsItem);
+ t->d_func()->setItem(q);
+ transformData->onlyTransform = false;
+ dirtySceneTransform = 1;
+}
+
+/*!
+ \internal
+*/
void QGraphicsItemPrivate::appendGraphicsTransform(QGraphicsTransform *t)
{
if (!transformData)
@@ -5325,6 +5351,8 @@ void QGraphicsItemPrivate::addChild(QGraphicsItem *child)
needSortChildren = 1; // ### maybe 0
child->d_ptr->siblingIndex = children.size();
children.append(child);
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -5347,6 +5375,8 @@ void QGraphicsItemPrivate::removeChild(QGraphicsItem *child)
// the child is not guaranteed to be at the index after the list is sorted.
// (see ensureSortedChildren()).
child->d_ptr->siblingIndex = -1;
+ if (isObject)
+ emit static_cast<QGraphicsObject *>(q_ptr)->childrenChanged();
}
/*!
@@ -7279,6 +7309,31 @@ void QGraphicsItem::setInputMethodHints(Qt::InputMethodHints hints)
}
/*!
+ Updates the item's micro focus.
+
+ \since 4.7
+
+ \sa QInputContext
+*/
+void QGraphicsItem::updateMicroFocus()
+{
+#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN))
+ if (QWidget *fw = qApp->focusWidget()) {
+ if (qt_widget_private(fw)->ic || qApp->d_func()->inputContext) {
+ if (QInputContext *ic = fw->inputContext()) {
+ if (ic)
+ ic->update();
+ }
+ }
+#ifndef QT_NO_ACCESSIBILITY
+ // ##### is this correct
+ QAccessible::updateAccessibility(fw, 0, QAccessible::StateChanged);
+#endif
+ }
+#endif
+}
+
+/*!
This virtual function is called by QGraphicsItem to notify custom items
that some part of the item's state changes. By reimplementing this
function, your can react to a change, and in some cases, (depending on \a
@@ -7554,6 +7609,93 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
}
}
+void QGraphicsObject::updateMicroFocus()
+{
+ QGraphicsItem::updateMicroFocus();
+}
+
+void QGraphicsItemPrivate::append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item)
+{
+ QGraphicsItemPrivate::get(item)->setParentItemHelper(static_cast<QGraphicsObject *>(list->object), /*newParentVariant=*/0, /*thisPointerVariant=*/0);
+}
+
+/*!
+ Returns a list of this item's children.
+
+ The items are sorted by stacking order. This takes into account both the
+ items' insertion order and their Z-values.
+
+*/
+QDeclarativeListProperty<QGraphicsObject> QGraphicsItemPrivate::childrenList()
+{
+ Q_Q(QGraphicsItem);
+ if (isObject) {
+ QGraphicsObject *that = static_cast<QGraphicsObject *>(q);
+ return QDeclarativeListProperty<QGraphicsObject>(that, &children, QGraphicsItemPrivate::append);
+ } else {
+ //QGraphicsItem is not supported for this property
+ return QDeclarativeListProperty<QGraphicsObject>();
+ }
+}
+
+/*!
+ \internal
+ Returns the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::width() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setWidth(qreal w)
+{
+ Q_UNUSED(w);
+}
+
+/*!
+ \internal
+ Reset the width of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetWidth()
+{
+}
+
+/*!
+ \internal
+ Returns the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+qreal QGraphicsItemPrivate::height() const
+{
+ return 0;
+}
+
+/*!
+ \internal
+ Set the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::setHeight(qreal h)
+{
+ Q_UNUSED(h);
+}
+
+/*!
+ \internal
+ Reset the height of the item
+ Reimplemented by QGraphicsWidget
+*/
+void QGraphicsItemPrivate::resetHeight()
+{
+}
+
/*!
\property QGraphicsObject::parent
\brief the parent of the item
@@ -7740,6 +7882,23 @@ void QGraphicsObject::ungrabGesture(Qt::GestureType gesture)
\sa scale, rotation, QGraphicsItem::transformOriginPoint()
*/
+/*!
+ \fn void QGraphicsObject::widthChanged()
+ \internal
+*/
+
+/*!
+ \fn void QGraphicsObject::heightChanged()
+ \internal
+*/
+
+/*!
+
+ \fn QGraphicsObject::childrenChanged()
+
+ This signal gets emitted whenever the children list changes
+ \internal
+*/
/*!
\class QAbstractGraphicsShapeItem
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index 117113f..9cc75af 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -424,6 +424,7 @@ public:
void removeSceneEventFilter(QGraphicsItem *filterItem);
protected:
+ void updateMicroFocus();
virtual bool sceneEventFilter(QGraphicsItem *watched, QEvent *event);
virtual bool sceneEvent(QEvent *event);
virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent *event);
@@ -553,6 +554,10 @@ class Q_GUI_EXPORT QGraphicsObject : public QObject, public QGraphicsItem
Q_PROPERTY(qreal rotation READ rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(qreal scale READ scale WRITE setScale NOTIFY scaleChanged)
Q_PROPERTY(QPointF transformOriginPoint READ transformOriginPoint WRITE setTransformOriginPoint)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), QDeclarativeListProperty<QGraphicsObject> children READ childrenList DESIGNABLE false NOTIFY childrenChanged)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal width READ width WRITE setWidth NOTIFY widthChanged RESET resetWidth FINAL)
+ Q_PRIVATE_PROPERTY(QGraphicsItem::d_func(), qreal height READ height WRITE setHeight NOTIFY heightChanged RESET resetHeight FINAL)
+ Q_CLASSINFO("DefaultProperty", "children")
Q_INTERFACES(QGraphicsItem)
public:
QGraphicsObject(QGraphicsItem *parent = 0);
@@ -567,6 +572,9 @@ public:
void grabGesture(Qt::GestureType type, Qt::GestureFlags flags = Qt::GestureFlags());
void ungrabGesture(Qt::GestureType type);
+protected Q_SLOTS:
+ void updateMicroFocus();
+
Q_SIGNALS:
void parentChanged();
void opacityChanged();
@@ -577,6 +585,9 @@ Q_SIGNALS:
void zChanged();
void rotationChanged();
void scaleChanged();
+ void childrenChanged();
+ void widthChanged();
+ void heightChanged();
protected:
QGraphicsObject(QGraphicsItemPrivate &dd, QGraphicsItem *parent, QGraphicsScene *scene);
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index de8cf56..73b8f04 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -71,6 +71,63 @@ QT_BEGIN_NAMESPACE
class QGraphicsItemPrivate;
+#ifndef QDECLARATIVELISTPROPERTY
+#define QDECLARATIVELISTPROPERTY
+template<typename T>
+class QDeclarativeListProperty {
+public:
+ typedef void (*AppendFunction)(QDeclarativeListProperty<T> *, T*);
+ typedef int (*CountFunction)(QDeclarativeListProperty<T> *);
+ typedef T *(*AtFunction)(QDeclarativeListProperty<T> *, int);
+ typedef void (*ClearFunction)(QDeclarativeListProperty<T> *);
+
+ QDeclarativeListProperty()
+ : object(0), data(0), append(0), count(0), at(0), clear(0), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, QList<T *> &list)
+ : object(o), data(&list), append(qlist_append), count(qlist_count), at(qlist_at),
+ clear(qlist_clear), dummy1(0), dummy2(0) {}
+ QDeclarativeListProperty(QObject *o, void *d, AppendFunction a, CountFunction c = 0, AtFunction t = 0,
+ ClearFunction r = 0)
+ : object(o), data(d), append(a), count(c), at(t), clear(r), dummy1(0), dummy2(0) {}
+
+ bool operator==(const QDeclarativeListProperty &o) const {
+ return object == o.object &&
+ data == o.data &&
+ append == o.append &&
+ count == o.count &&
+ at == o.at &&
+ clear == o.clear;
+ }
+
+ QObject *object;
+ void *data;
+
+ AppendFunction append;
+
+ CountFunction count;
+ AtFunction at;
+
+ ClearFunction clear;
+
+ void *dummy1;
+ void *dummy2;
+
+private:
+ static void qlist_append(QDeclarativeListProperty *p, T *v) {
+ ((QList<T *> *)p->data)->append(v);
+ }
+ static int qlist_count(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->count();
+ }
+ static T *qlist_at(QDeclarativeListProperty *p, int idx) {
+ return ((QList<T *> *)p->data)->at(idx);
+ }
+ static void qlist_clear(QDeclarativeListProperty *p) {
+ return ((QList<T *> *)p->data)->clear();
+ }
+};
+#endif
+
class QGraphicsItemCache
{
public:
@@ -220,6 +277,7 @@ public:
virtual void setPosHelper(const QPointF &pos);
void setTransformHelper(const QTransform &transform);
+ void prependGraphicsTransform(QGraphicsTransform *t);
void appendGraphicsTransform(QGraphicsTransform *t);
void setVisibleHelper(bool newVisible, bool explicitly, bool update = true);
void setEnabledHelper(bool newEnabled, bool explicitly, bool update = true);
@@ -237,6 +295,7 @@ public:
void resolveDepth();
void addChild(QGraphicsItem *child);
void removeChild(QGraphicsItem *child);
+ QDeclarativeListProperty<QGraphicsObject> childrenList();
void setParentItemHelper(QGraphicsItem *parent, const QVariant *newParentVariant,
const QVariant *thisPointerVariant);
void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
@@ -423,11 +482,21 @@ public:
inline QTransform transformToParent() const;
inline void ensureSortedChildren();
+ static void append(QDeclarativeListProperty<QGraphicsObject> *list, QGraphicsObject *item);
static inline bool insertionOrder(QGraphicsItem *a, QGraphicsItem *b);
void ensureSequentialSiblingIndex();
inline void sendScenePosChange();
virtual void siblingOrderChange();
+ // Private Properties
+ virtual qreal width() const;
+ virtual void setWidth(qreal);
+ virtual void resetWidth();
+
+ virtual qreal height() const;
+ virtual void setHeight(qreal);
+ virtual void resetHeight();
+
QRectF childrenBoundingRect;
QRectF needsRepaint;
QMap<QWidget *, QRect> paintedViewBoundingRects;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 29a4be8..4b612f4 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -4301,12 +4301,7 @@ static void _q_paintIntoCache(QPixmap *pix, QGraphicsItem *item, const QRegion &
if (!subPix.isNull()) {
// Blit the subpixmap into the main pixmap.
pixmapPainter.begin(pix);
- if (item->cacheMode() == QGraphicsItem::DeviceCoordinateCache
- && itemToPixmap.type() > QTransform::TxTranslate) {
- pixmapPainter.setCompositionMode(QPainter::CompositionMode_SourceAtop);
- } else {
- pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
- }
+ pixmapPainter.setCompositionMode(QPainter::CompositionMode_Source);
pixmapPainter.setClipRegion(pixmapExposed);
pixmapPainter.drawPixmap(br.topLeft(), subPix);
pixmapPainter.end();
@@ -4472,6 +4467,8 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
// Create or reuse offscreen pixmap, possibly scroll/blit from the old one.
+ // If the world transform is rotated we always recreate the cache to avoid
+ // wrong blending.
bool pixModified = false;
QGraphicsItemCache::DeviceData *deviceData = &itemCache->deviceData[widget];
bool invertable = true;
@@ -4479,7 +4476,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
if (invertable)
diff *= painter->worldTransform();
deviceData->lastTransform = painter->worldTransform();
- if (!invertable || diff.type() > QTransform::TxTranslate) {
+ if (!invertable
+ || diff.type() > QTransform::TxTranslate
+ || painter->worldTransform().type() > QTransform::TxScale) {
pixModified = true;
itemCache->allExposed = true;
itemCache->exposed.clear();
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index a257e0d..8e439be 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -324,6 +324,14 @@ void QGraphicsWidget::resize(const QSizeF &size)
*/
/*!
+
+ \fn QGraphicsWidget::geometryChanged()
+
+ This signal gets emitted whenever the geometry of the item changes
+ \internal
+*/
+
+/*!
\property QGraphicsWidget::geometry
\brief the geometry of the widget
@@ -334,7 +342,7 @@ void QGraphicsWidget::resize(const QSizeF &size)
A side effect of calling this function is that the widget will receive
a move event and a resize event. Also, if the widget has a layout
assigned, the layout will activate.
-
+
\sa geometry(), resize()
*/
void QGraphicsWidget::setGeometry(const QRectF &rect)
@@ -391,6 +399,10 @@ void QGraphicsWidget::setGeometry(const QRectF &rect)
QGraphicsSceneResizeEvent re;
re.setOldSize(oldSize);
re.setNewSize(newGeom.size());
+ if (oldSize.width() != newGeom.size().width())
+ emit widthChanged();
+ if (oldSize.height() != newGeom.size().height())
+ emit heightChanged();
QApplication::sendEvent(this, &re);
}
}
@@ -568,7 +580,7 @@ void QGraphicsWidget::getWindowFrameMargins(qreal *left, qreal *top, qreal *righ
void QGraphicsWidget::unsetWindowFrameMargins()
{
Q_D(QGraphicsWidget);
- if ((d->windowFlags & Qt::Window) && (d->windowFlags & Qt::WindowType_Mask) != Qt::Popup &&
+ if ((d->windowFlags & Qt::Window) && (d->windowFlags & Qt::WindowType_Mask) != Qt::Popup &&
(d->windowFlags & Qt::WindowType_Mask) != Qt::ToolTip && !(d->windowFlags & Qt::FramelessWindowHint)) {
QStyleOptionTitleBar bar;
d->initStyleOptionTitleBar(&bar);
@@ -795,6 +807,7 @@ void QGraphicsWidget::setLayout(QGraphicsLayout *l)
l->setParentLayoutItem(this);
l->d_func()->reparentChildItems(this);
l->invalidate();
+ emit layoutChanged();
}
/*!
@@ -1175,7 +1188,7 @@ bool QGraphicsWidget::sceneEvent(QEvent *event)
Returns true if \a event has been recognized and processed; otherwise,
returns false.
-
+
\sa event()
*/
bool QGraphicsWidget::windowFrameEvent(QEvent *event)
@@ -1232,7 +1245,7 @@ Qt::WindowFrameSection QGraphicsWidget::windowFrameSectionAt(const QPointF &pos)
const QRectF r = windowFrameRect();
if (!r.contains(pos))
return Qt::NoSection;
-
+
const qreal left = r.left();
const qreal top = r.top();
const qreal right = r.right();
@@ -2358,5 +2371,5 @@ void QGraphicsWidget::dumpFocusChain()
#endif
QT_END_NAMESPACE
-
+
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h
index 87c669b..894b84e 100644
--- a/src/gui/graphicsview/qgraphicswidget.h
+++ b/src/gui/graphicsview/qgraphicswidget.h
@@ -82,6 +82,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay
Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags)
Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle)
Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged)
+ Q_PROPERTY(QGraphicsLayout* layout READ layout WRITE setLayout NOTIFY layoutChanged)
Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground)
public:
QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0);
@@ -180,6 +181,7 @@ public:
Q_SIGNALS:
void geometryChanged();
+ void layoutChanged();
public Q_SLOTS:
bool close();
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 1835c74..6e397b6 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -44,6 +44,7 @@
#ifndef QT_NO_GRAPHICSVIEW
#include <QtCore/qdebug.h>
+#include <QtCore/qnumeric.h>
#include "qgraphicswidget_p.h"
#include "qgraphicslayout.h"
#include "qgraphicsscene_p.h"
@@ -825,6 +826,56 @@ void QGraphicsWidgetPrivate::setLayout_helper(QGraphicsLayout *l)
}
}
+qreal QGraphicsWidgetPrivate::width() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().width();
+}
+
+void QGraphicsWidgetPrivate::setWidth(qreal w)
+{
+ if (qIsNaN(w))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().width() == w)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), w, height()));
+}
+
+void QGraphicsWidgetPrivate::resetWidth()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), 0, height()));
+}
+
+qreal QGraphicsWidgetPrivate::height() const
+{
+ Q_Q(const QGraphicsWidget);
+ return q->geometry().height();
+}
+
+void QGraphicsWidgetPrivate::setHeight(qreal h)
+{
+ if (qIsNaN(h))
+ return;
+ Q_Q(QGraphicsWidget);
+ if (q->geometry().height() == h)
+ return;
+
+ QRectF oldGeom = q->geometry();
+
+ q->setGeometry(QRectF(q->x(), q->y(), width(), h));
+}
+
+void QGraphicsWidgetPrivate::resetHeight()
+{
+ Q_Q(QGraphicsWidget);
+ q->setGeometry(QRectF(q->x(), q->y(), width(), 0));
+}
+
QT_END_NAMESPACE
#endif //QT_NO_GRAPHICSVIEW
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index 3ab8737..7116a23 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -131,6 +131,15 @@ public:
void windowFrameHoverLeaveEvent(QGraphicsSceneHoverEvent *event);
bool hasDecoration() const;
+ // Private Properties
+ qreal width() const;
+ void setWidth(qreal);
+ void resetWidth();
+
+ qreal height() const;
+ void setHeight(qreal);
+ void resetHeight();
+
// State
inline int attributeToBitIndex(Qt::WidgetAttribute att) const
{
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index 52531a3..b22f732 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -41,6 +41,7 @@ include(math3d/math3d.pri)
include(effects/effects.pri)
contains(QT_CONFIG, egl): include(egl/egl.pri)
+win32:!wince*: DEFINES += QT_NO_EGL
embedded: QT += network
@@ -62,7 +63,6 @@ symbian {
# Partial upgrade SIS file
vendorinfo = \
- "&EN" \
"; Localised Vendor name" \
"%{\"Nokia, Qt\"}" \
" " \
diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri
index 6d9f748..02e3e57 100644
--- a/src/gui/inputmethod/inputmethod.pri
+++ b/src/gui/inputmethod/inputmethod.pri
@@ -26,6 +26,6 @@ mac:!embedded {
symbian:contains(QT_CONFIG, s60) {
HEADERS += inputmethod/qcoefepinputcontext_p.h
SOURCES += inputmethod/qcoefepinputcontext_s60.cpp
- LIBS += -lfepbase
+ LIBS += -lfepbase -lakninputlanguage
}
diff --git a/src/gui/inputmethod/qinputcontextfactory.cpp b/src/gui/inputmethod/qinputcontextfactory.cpp
index 501a36e..d47e343 100644
--- a/src/gui/inputmethod/qinputcontextfactory.cpp
+++ b/src/gui/inputmethod/qinputcontextfactory.cpp
@@ -73,6 +73,7 @@
#endif
#ifdef Q_WS_S60
#include "qcoefepinputcontext_p.h"
+#include "akninputlanguageinfo.h"
#endif
#include "private/qfactoryloader_p.h"
@@ -198,6 +199,42 @@ QStringList QInputContextFactory::keys()
return result;
}
+#if defined(Q_WS_S60)
+/*!
+ \internal
+
+ This function contains pure Symbian exception handling code for
+ getting S60 language list.
+ Returned object ownership is transfered to caller.
+*/
+static CAknInputLanguageList* s60LangListL()
+{
+ CAknInputLanguageInfo *langInfo = AknInputLanguageInfoFactory::CreateInputLanguageInfoL();
+ CleanupStack::PushL(langInfo);
+ // In rare phone there is more than 7 languages installed -> use 7 as an array granularity
+ CAknInputLanguageList *langList = new (ELeave) CAknInputLanguageList(7);
+ CleanupStack::PushL(langList);
+ langInfo->AppendAvailableLanguagesL(langList);
+ CleanupStack::Pop(langList);
+ CleanupStack::PopAndDestroy(langInfo);
+ return langList;
+}
+
+/*!
+ \internal
+
+ This function utility function return S60 language list.
+ Returned object ownership is transfered to caller.
+*/
+static CAknInputLanguageList* s60LangList()
+{
+ CAknInputLanguageList *langList = NULL;
+ TRAP_IGNORE(langList = s60LangListL());
+ q_check_ptr(langList);
+ return langList;
+}
+#endif
+
/*!
Returns the languages supported by the QInputContext object
specified by \a key.
@@ -229,7 +266,15 @@ QStringList QInputContextFactory::languages( const QString &key )
#endif
#if defined(Q_WS_S60)
if (key == QLatin1String("coefep"))
- return QStringList(QString());
+ {
+ CAknInputLanguageList *langList = s60LangList();
+ int count = langList->Count();
+ for (int i = 0; i < count; ++i)
+ {
+ result.append(QString(qt_symbianLocaleName(langList->At(i)->LanguageCode())));
+ }
+ delete langList;
+ }
#endif
#if defined(QT_NO_LIBRARY) || defined(QT_NO_SETTINGS)
Q_UNUSED(key);
diff --git a/src/gui/kernel/qapplication.h b/src/gui/kernel/qapplication.h
index ee74350..c21b982 100644
--- a/src/gui/kernel/qapplication.h
+++ b/src/gui/kernel/qapplication.h
@@ -376,6 +376,7 @@ private:
Q_DECLARE_PRIVATE(QApplication)
friend class QGraphicsWidget;
+ friend class QGraphicsItem;
friend class QGraphicsScene;
friend class QGraphicsScenePrivate;
friend class QWidget;
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 27b490b..25a7bbe 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1004,16 +1004,32 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
// else { We don't touch the active window unless we were explicitly activated or deactivated }
}
+void QSymbianControl::handleClientAreaChange()
+{
+ const bool cbaVisibilityHint = qwidget->windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ if (qwidget->isFullScreen() && !cbaVisibilityHint) {
+ SetExtentToWholeScreen();
+ } else if (qwidget->isMaximized() || (qwidget->isFullScreen() && cbaVisibilityHint)) {
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ SetExtent(r.iTl, r.Size());
+ } else if (!qwidget->isMinimized()) { // Normal geometry
+ if (!qwidget->testAttribute(Qt::WA_Resized)) {
+ qwidget->adjustSize();
+ qwidget->setAttribute(Qt::WA_Resized, false); //not a user resize
+ }
+ if (!qwidget->testAttribute(Qt::WA_Moved) && qwidget->windowType() != Qt::Dialog) {
+ TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
+ SetPosition(r.iTl);
+ qwidget->setAttribute(Qt::WA_Moved, false); // not really an explicit position
+ }
+ }
+}
+
void QSymbianControl::HandleResourceChange(int resourceType)
{
switch (resourceType) {
case KInternalStatusPaneChange:
- if (qwidget->isFullScreen()) {
- SetExtentToWholeScreen();
- } else if (qwidget->isMaximized()) {
- TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
- SetExtent(r.iTl, r.Size());
- }
+ handleClientAreaChange();
if (IsFocused() && IsVisible()) {
qwidget->d_func()->setWindowIcon_sys(true);
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
@@ -1025,22 +1041,7 @@ void QSymbianControl::HandleResourceChange(int resourceType)
#ifdef Q_WS_S60
case KEikDynamicLayoutVariantSwitch:
{
- if (qwidget->isFullScreen()) {
- SetExtentToWholeScreen();
- } else if (qwidget->isMaximized()) {
- TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
- SetExtent(r.iTl, r.Size());
- } else if (!qwidget->isMinimized()){ // Normal geometry
- if (!qwidget->testAttribute(Qt::WA_Resized)) {
- qwidget->adjustSize();
- qwidget->setAttribute(Qt::WA_Resized, false); //not a user resize
- }
- if (!qwidget->testAttribute(Qt::WA_Moved) && qwidget->windowType() != Qt::Dialog) {
- TRect r = static_cast<CEikAppUi*>(S60->appUi())->ClientRect();
- SetPosition(r.iTl);
- qwidget->setAttribute(Qt::WA_Moved, false); // not really an explicit position
- }
- }
+ handleClientAreaChange();
break;
}
#endif
diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp
index c9a94ee..923144a 100644
--- a/src/gui/kernel/qsoftkeymanager.cpp
+++ b/src/gui/kernel/qsoftkeymanager.cpp
@@ -115,6 +115,8 @@ QAction *QSoftKeyManager::createAction(StandardSoftKey standardKey, QWidget *act
break;
}
action->setSoftKeyRole(softKeyRole);
+ action->setVisible(false);
+ setForceEnabledInSoftkeys(action);
return action;
}
@@ -168,25 +170,55 @@ bool QSoftKeyManager::appendSoftkeys(const QWidget &source, int level)
{
Q_D(QSoftKeyManager);
bool ret = false;
- QList<QAction*> actions = source.actions();
- for (int i = 0; i < actions.count(); ++i) {
- if (actions.at(i)->softKeyRole() != QAction::NoSoftKey) {
- d->requestedSoftKeyActions.insert(level, actions.at(i));
+ foreach(QAction *action, source.actions()) {
+ if (action->softKeyRole() != QAction::NoSoftKey
+ && (action->isVisible() || isForceEnabledInSofkeys(action))) {
+ d->requestedSoftKeyActions.insert(level, action);
ret = true;
}
}
return ret;
}
+
+static bool isChildOf(const QWidget *c, const QWidget *p)
+{
+ while (c) {
+ if (c == p)
+ return true;
+ c = c->parentWidget();
+ }
+ return false;
+}
+
QWidget *QSoftKeyManager::softkeySource(QWidget *previousSource, bool& recursiveMerging)
{
Q_D(QSoftKeyManager);
QWidget *source = NULL;
if (!previousSource) {
// Initial source is primarily focuswidget and secondarily activeWindow
- source = QApplication::focusWidget();
- if (!source)
- source = QApplication::activeWindow();
+ QWidget *focus = QApplication::focusWidget();
+ QWidget *popup = QApplication::activePopupWidget();
+ if (popup) {
+ if (isChildOf(focus, popup))
+ source = focus;
+ else
+ source = popup;
+ }
+ if (!source) {
+ QWidget *modal = QApplication::activeModalWidget();
+ if (modal) {
+ if (isChildOf(focus, modal))
+ source = focus;
+ else
+ source = modal;
+ }
+ }
+ if (!source) {
+ source = focus;
+ if (!source)
+ source = QApplication::activeWindow();
+ }
} else {
// Softkey merging is based on four criterias
// 1. Implicit merging is used whenever focus widget does not specify any softkeys
@@ -220,6 +252,20 @@ bool QSoftKeyManager::handleUpdateSoftKeys()
return true;
}
+void QSoftKeyManager::setForceEnabledInSoftkeys(QAction *action)
+{
+ action->setProperty(FORCE_ENABLED_PROPERTY, QVariant(true));
+}
+
+bool QSoftKeyManager::isForceEnabledInSofkeys(QAction *action)
+{
+ bool ret = false;
+ QVariant property = action->property(FORCE_ENABLED_PROPERTY);
+ if (property.isValid() && property.toBool())
+ ret = true;
+ return ret;
+}
+
bool QSoftKeyManager::event(QEvent *e)
{
#ifndef QT_NO_ACTION
diff --git a/src/gui/kernel/qsoftkeymanager_p.h b/src/gui/kernel/qsoftkeymanager_p.h
index a6fe17e..a5b258b 100644
--- a/src/gui/kernel/qsoftkeymanager_p.h
+++ b/src/gui/kernel/qsoftkeymanager_p.h
@@ -63,7 +63,8 @@ QT_BEGIN_NAMESPACE
class QSoftKeyManagerPrivate;
-const char MENU_ACTION_PROPERTY[] = "_q_menuaction";
+const char MENU_ACTION_PROPERTY[] = "_q_menuAction";
+const char FORCE_ENABLED_PROPERTY[] = "_q_forceEnabledInSoftkeys";
class Q_AUTOTEST_EXPORT QSoftKeyManager : public QObject
{
@@ -88,6 +89,8 @@ public:
static QAction *createAction(StandardSoftKey standardKey, QWidget *actionWidget);
static QAction *createKeyedAction(StandardSoftKey standardKey, Qt::Key key, QWidget *actionWidget);
static QString standardSoftKeyText(StandardSoftKey standardKey);
+ static void setForceEnabledInSoftkeys(QAction *action);
+ static bool isForceEnabledInSofkeys(QAction *action);
protected:
bool event(QEvent *e);
diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp
index 3a0304c..9812d72 100644
--- a/src/gui/kernel/qsoftkeymanager_s60.cpp
+++ b/src/gui/kernel/qsoftkeymanager_s60.cpp
@@ -288,11 +288,7 @@ bool QSoftKeyManagerPrivateS60::setSoftkey(CEikButtonGroupContainer &cba,
TPtrC nativeText = qt_QString2TPtrC(text);
int command = S60_COMMAND_START + position;
setNativeSoftkey(cba, position, command, nativeText);
- // QMainWindow "Options" action is set to invisible in order it does not appear in context menu
- // and all invisible actions are by default disabled.
- // However we never want to dim options softkey, even it is set to invisible
- QVariant property = action->property(MENU_ACTION_PROPERTY);
- const bool dimmed = (property.isValid() && property.toBool()) ? false : !action->isEnabled();
+ const bool dimmed = !action->isEnabled() && !QSoftKeyManager::isForceEnabledInSofkeys(action);
cba.DimCommand(command, dimmed);
realSoftKeyActions.insert(command, action);
return true;
@@ -335,6 +331,7 @@ bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba)
cbaHasImage[RSK_POSITION] = false;
}
setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText);
+ cba.DimCommand(EAknSoftkeyExit, false);
return true;
}
}
diff --git a/src/gui/kernel/qsound.cpp b/src/gui/kernel/qsound.cpp
index 165e6ce..9d8ffa5 100644
--- a/src/gui/kernel/qsound.cpp
+++ b/src/gui/kernel/qsound.cpp
@@ -147,12 +147,13 @@ public:
supports WAVE and AU files.
\row
\o Mac OS X
- \o NSSound is used. All formats that NSSound supports, including QuickTime formats,
+ \o NSSound is used. All formats that NSSound supports, including QuickTime formats,
are supported by Qt for Mac OS X.
\row
\o Qt for Embedded Linux
\o A built-in mixing sound server is used, accessing \c /dev/dsp
directly. Only the WAVE format is supported.
+ \row
\o Symbian
\o CMdaAudioPlayerUtility is used. All formats that Symbian OS or devices support
are supported also by Qt.
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index cedede1..7c6b754 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -212,6 +212,7 @@ private:
#ifdef QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER
void translateAdvancedPointerEvent(const TAdvancedPointerEvent *event);
#endif
+ void handleClientAreaChange();
private:
static QSymbianControl *lastFocusedControl;
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index ef7ac1f..89ea256 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -234,6 +234,15 @@ struct QWExtra {
uint activated : 1; // RWindowBase::Activated has been called
/**
+ * If this bit is set, each native widget receives the signals from the
+ * Symbian control immediately before and immediately after draw ops are
+ * sent to the window server for this control:
+ * void beginNativePaintEvent(const QRect &paintRect);
+ * void endNativePaintEvent(const QRect &paintRect);
+ */
+ uint receiveNativePaintEvents : 1;
+
+ /**
* Defines the behaviour of QSymbianControl::Draw.
*/
enum NativePaintMode {
@@ -258,16 +267,7 @@ struct QWExtra {
Default = Blit
};
- NativePaintMode nativePaintMode : 2;
-
- /**
- * If this bit is set, each native widget receives the signals from the
- * Symbian control immediately before and immediately after draw ops are
- * sent to the window server for this control:
- * void beginNativePaintEvent(const QRect &paintRect);
- * void endNativePaintEvent(const QRect &paintRect);
- */
- uint receiveNativePaintEvents : 1;
+ NativePaintMode nativePaintMode;
#endif
};
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 79702af..bfa7050 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -1109,9 +1109,11 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
QTLWExtra *top = d->topData();
const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
- if (newstate & Qt::WindowFullScreen)
- setGeometry(qApp->desktop()->availableGeometry(this));
- else if (newstate & Qt::WindowMaximized)
+
+ const bool cbaVisibilityHint = windowFlags() & Qt::WindowSoftkeysVisibleHint;
+ if (newstate & Qt::WindowFullScreen && !cbaVisibilityHint)
+ setGeometry(qApp->desktop()->screenGeometry(this));
+ else if (newstate & Qt::WindowMaximized || ((newstate & Qt::WindowFullScreen) && cbaVisibilityHint))
setGeometry(qApp->desktop()->availableGeometry(this));
else
setGeometry(normalGeometry);
diff --git a/src/gui/painting/qpaintbuffer.cpp b/src/gui/painting/qpaintbuffer.cpp
index ca2077f..e1156dc 100644
--- a/src/gui/painting/qpaintbuffer.cpp
+++ b/src/gui/painting/qpaintbuffer.cpp
@@ -557,11 +557,7 @@ QString QPaintBuffer::commandDescription(int command) const
debug << "Cmd_Translate:" << delta;
break; }
case QPaintBufferPrivate::Cmd_DrawStaticText: {
- QPointF delta(d_ptr->floats.at(cmd.extra), d_ptr->floats.at(cmd.extra+1));
- QVariantList variants(d_ptr->variants.at(cmd.offset).value<QVariantList>());
-
- QStaticText text(variants.at(0).value<QStaticText>());
- debug << "Cmd_DrawStaticText:" << text.text();
+ debug << "Cmd_DrawStaticText";
break; }
}
@@ -1272,13 +1268,14 @@ void QPaintBufferEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pm, con
void QPaintBufferEngine::drawStaticTextItem(QStaticTextItem *staticTextItem)
{
- QString text = QString(staticTextItem->chars, staticTextItem->numChars);
+ QVariantList variants;
- QStaticText staticText(text);
- staticText.prepare(state()->matrix, staticTextItem->font);
+ variants << QVariant(staticTextItem->font);
+ for (int i=0; i<staticTextItem->numGlyphs; ++i) {
+ variants.append(staticTextItem->glyphs[i]);
+ variants.append(staticTextItem->glyphPositions[i].toPointF());
+ }
- QVariantList variants;
- variants << QVariant(staticTextItem->font) << QVariant::fromValue(staticText);
buffer->addCommand(QPaintBufferPrivate::Cmd_DrawStaticText, QVariant(variants));
}
@@ -1761,11 +1758,19 @@ void QPainterReplayer::process(const QPaintBufferCommand &cmd)
QVariantList variants(d->variants.at(cmd.offset).value<QVariantList>());
- QFont font(variants.at(0).value<QFont>());
- QStaticText text(variants.at(0).value<QStaticText>());
-
+ QFont font = variants.at(0).value<QFont>();
+
+ QVector<quint32> glyphs;
+ QVector<QPointF> positions;
+
+ for (int i=0; i<(variants.size() - 1) / 2; ++i) {
+ glyphs.append(variants.at(i*2 + 1).toUInt());
+ positions.append(variants.at(i*2 + 2).toPointF());
+ }
+
painter->setFont(font);
- painter->drawStaticText(QPointF(0, 0), text);
+
+ qt_draw_glyphs(painter, glyphs.constData(), positions.constData(), glyphs.size());
break;
}
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 1c528fe..898a996 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -5720,6 +5720,16 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
QFontEngine *fontEngine = state->font.d->engineForScript(QUnicodeTables::Common);
+ while (fontEngine->type() == QFontEngine::Multi) {
+ // Pick engine based on first glyph in array if we are using a multi engine.
+ // (all glyphs must be for same font)
+ int engineIdx = 0;
+ if (glyphCount > 0)
+ engineIdx = glyphArray[0] >> 24;
+
+ fontEngine = static_cast<QFontEngineMulti *>(fontEngine)->engine(engineIdx);
+ }
+
QVarLengthArray<QFixedPoint, 128> positions;
for (int i=0; i<glyphCount; ++i) {
QFixedPoint fp = QFixedPoint::fromPointF(positionArray[i]);
@@ -5762,19 +5772,24 @@ void QPainterPrivate::drawGlyphs(const quint32 *glyphArray, const QPointF *posit
/*!
- \fn void QPainter::drawStaticText(const QPoint &position, const QStaticText &staticText)
+ \fn void QPainter::drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText)
\since 4.7
\overload
- Draws the \a staticText at the \a position.
+ Draws the \a staticText at the \a topLeftPosition.
+
+ \note The y-position is used as the top of the font.
+
*/
/*!
- \fn void QPainter::drawStaticText(int x, int y, const QStaticText &staticText)
+ \fn void QPainter::drawStaticText(int left, int top, const QStaticText &staticText)
\since 4.7
\overload
- Draws the \a staticText at coordinates \a x and \a y.
+ Draws the \a staticText at coordinates \a left and \a top.
+
+ \note The y-position is used as the top of the font.
*/
/*!
@@ -5802,7 +5817,7 @@ void QPainter::drawText(const QPointF &p, const QString &str)
/*!
\since 4.7
- Draws the given \a staticText at the given \a position.
+ Draws the given \a staticText at the given \a topLeftPosition.
The text will be drawn using the font and the transformation set on the painter. If the
font and/or transformation set on the painter are different from the ones used to initialize
@@ -5810,15 +5825,17 @@ void QPainter::drawText(const QPointF &p, const QString &str)
QStaticText::prepare() to initialize \a staticText with the font and transformation with which
it will later be drawn.
- If \a position is not the same as when \a staticText was initialized, or when it was last drawn,
- then there will be a slight overhead when translating the text to its new position.
+ If \a topLeftPosition is not the same as when \a staticText was initialized, or when it was
+ last drawn, then there will be a slight overhead when translating the text to its new position.
- \note If the painter's transformation is not affine, then \a staticText will be drawn using regular
- calls to drawText(), losing any potential performance improvement.
+ \note If the painter's transformation is not affine, then \a staticText will be drawn using
+ regular calls to drawText(), losing any potential for performance improvement.
+
+ \note The y-position is used as the top of the font.
\sa QStaticText
*/
-void QPainter::drawStaticText(const QPointF &position, const QStaticText &staticText)
+void QPainter::drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText)
{
Q_D(QPainter);
if (!d->engine || staticText.text().isEmpty() || pen().style() == Qt::NoPen)
@@ -5827,16 +5844,21 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
QStaticTextPrivate *staticText_d =
const_cast<QStaticTextPrivate *>(QStaticTextPrivate::get(&staticText));
+ if (font() != staticText_d->font) {
+ staticText_d->font = font();
+ staticText_d->needsRelayout = true;
+ }
+
// If we don't have an extended paint engine, or if the painter is projected,
// we go through standard code path
if (d->extended == 0 || !d->state->matrix.isAffine()) {
- staticText_d->paintText(position, this);
+ staticText_d->paintText(topLeftPosition, this);
return;
}
// Don't recalculate entire layout because of translation, rather add the dx and dy
// into the position to move each text item the correct distance.
- QPointF transformedPosition = position * d->state->matrix;
+ QPointF transformedPosition = topLeftPosition * d->state->matrix;
QTransform matrix = d->state->matrix;
// The translation has been applied to transformedPosition. Remove translation
@@ -5857,25 +5879,12 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
// If the transform is not identical to the text transform,
// we have to relayout the text (for other transformations than plain translation)
- bool staticTextNeedsReinit = false;
+ bool staticTextNeedsReinit = staticText_d->needsRelayout;
if (staticText_d->matrix != d->state->matrix) {
staticText_d->matrix = d->state->matrix;
staticTextNeedsReinit = true;
}
- bool restoreWhenFinished = false;
- if (staticText_d->needsClipRect) {
- save();
- setClipRect(QRectF(position, staticText_d->maximumSize));
-
- restoreWhenFinished = true;
- }
-
- if (font() != staticText_d->font) {
- staticText_d->font = font();
- staticTextNeedsReinit = true;
- }
-
// Recreate the layout of the static text because the matrix or font has changed
if (staticTextNeedsReinit)
staticText_d->init();
@@ -5901,7 +5910,7 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
QColor currentColor = oldPen.color();
for (int i=0; i<staticText_d->itemCount; ++i) {
QStaticTextItem *item = staticText_d->items + i;
- if (currentColor != item->color) {
+ if (item->color.isValid() && currentColor != item->color) {
setPen(item->color);
currentColor = item->color;
}
@@ -5910,9 +5919,6 @@ void QPainter::drawStaticText(const QPointF &position, const QStaticText &static
if (currentColor != oldPen.color())
setPen(oldPen);
- if (restoreWhenFinished)
- restore();
-
if (matrix.isTranslating())
d->state->matrix = matrix;
}
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 443925b..edfb67e 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -396,9 +396,9 @@ public:
void setLayoutDirection(Qt::LayoutDirection direction);
Qt::LayoutDirection layoutDirection() const;
- void drawStaticText(const QPointF &p, const QStaticText &staticText);
- inline void drawStaticText(const QPoint &p, const QStaticText &staticText);
- inline void drawStaticText(int x, int y, const QStaticText &staticText);
+ void drawStaticText(const QPointF &topLeftPosition, const QStaticText &staticText);
+ inline void drawStaticText(const QPoint &topLeftPosition, const QStaticText &staticText);
+ inline void drawStaticText(int left, int top, const QStaticText &staticText);
void drawText(const QPointF &p, const QString &s);
inline void drawText(const QPoint &p, const QString &s);
diff --git a/src/gui/styles/qgtkstyle.cpp b/src/gui/styles/qgtkstyle.cpp
index bd87ca4..9c61023 100644
--- a/src/gui/styles/qgtkstyle.cpp
+++ b/src/gui/styles/qgtkstyle.cpp
@@ -3423,6 +3423,9 @@ QRect QGtkStyle::subElementRect(SubElement element, const QStyleOption *option,
Q_D(const QGtkStyle);
QRect r = QCleanlooksStyle::subElementRect(element, option, widget);
+ if (!d->isThemeAvailable())
+ return r;
+
switch (element) {
case SE_ProgressBarLabel:
case SE_ProgressBarContents:
diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp
index 750e19f..000696c 100644
--- a/src/gui/styles/qs60style.cpp
+++ b/src/gui/styles/qs60style.cpp
@@ -50,6 +50,7 @@
#include "qcalendarwidget.h"
#include "qdial.h"
#include "qdialog.h"
+#include "qmessagebox.h"
#include "qgroupbox.h"
#include "qheaderview.h"
#include "qlist.h"
@@ -61,7 +62,6 @@
#include "qscrollarea.h"
#include "qscrollbar.h"
#include "qtabbar.h"
-#include "qtablewidget.h"
#include "qtableview.h"
#include "qtextedit.h"
#include "qtoolbar.h"
@@ -92,10 +92,10 @@ static const qreal goldenRatio = 1.618;
const layoutHeader QS60StylePrivate::m_layoutHeaders[] = {
// *** generated layout data ***
-{240,320,1,16,"QVGA Landscape"},
-{320,240,1,16,"QVGA Portrait"},
-{360,640,1,16,"NHD Landscape"},
-{640,360,1,16,"NHD Portrait"},
+{240,320,1,17,"QVGA Landscape"},
+{320,240,1,17,"QVGA Portrait"},
+{360,640,1,17,"NHD Landscape"},
+{640,360,1,17,"NHD Portrait"},
{352,800,1,12,"E90 Landscape"}
// *** End of generated data ***
};
@@ -104,11 +104,11 @@ const int QS60StylePrivate::m_numberOfLayouts =
const short QS60StylePrivate::data[][MAX_PIXELMETRICS] = {
// *** generated pixel metrics ***
-{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,0,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1},
-{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,0,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1},
-{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,0,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1},
-{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,0,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1},
-{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,0,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1}
+{5,0,-909,0,0,2,0,0,-1,7,12,19,13,13,6,200,-909,-909,-909,20,13,2,0,0,21,7,18,0,3,3,1,-909,-909,0,1,0,0,12,20,15,15,18,18,1,115,18,0,-909,-909,-909,-909,0,0,16,2,-909,0,0,-909,16,-909,-909,-909,-909,32,18,55,24,55,4,4,4,9,13,-909,5,51,11,5,0,3,3,6,8,3,3,-909,2,-909,-909,-909,-909,5,5,3,1, 106},
+{5,0,-909,0,0,1,0,0,-1,8,14,22,15,15,7,164,-909,-909,-909,19,15,2,0,0,21,8,27,0,4,4,1,-909,-909,0,7,6,0,13,23,17,17,21,21,7,115,21,0,-909,-909,-909,-909,0,0,15,1,-909,0,0,-909,15,-909,-909,-909,-909,32,21,65,27,65,3,3,5,10,15,-909,5,58,13,5,0,4,4,7,9,4,4,-909,2,-909,-909,-909,-909,6,6,3,1, 106},
+{7,0,-909,0,0,2,0,0,-1,25,69,28,19,19,9,258,-909,-909,-909,23,19,26,0,0,32,25,72,0,5,5,2,-909,-909,0,7,21,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,25,2,-909,0,0,-909,25,-909,-909,-909,-909,87,27,77,35,77,13,13,6,8,19,-909,7,74,19,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135},
+{7,0,-909,0,0,2,0,0,-1,25,68,28,19,19,9,258,-909,-909,-909,31,19,6,0,0,32,25,60,0,5,5,2,-909,-909,0,7,32,0,17,29,22,22,27,27,7,173,29,0,-909,-909,-909,-909,0,0,26,2,-909,0,0,-909,26,-909,-909,-909,-909,87,27,96,35,96,12,12,6,8,19,-909,7,74,22,7,0,5,5,8,12,5,5,-909,3,-909,-909,-909,-909,7,7,3,1, 135},
+{7,0,-909,0,0,2,0,0,-1,10,20,27,18,18,9,301,-909,-909,-909,29,18,5,0,0,35,7,32,0,5,5,2,-909,-909,0,2,8,0,16,28,21,21,26,26,2,170,26,0,-909,-909,-909,-909,0,0,21,6,-909,0,0,-909,-909,-909,-909,-909,-909,54,26,265,34,265,5,5,6,3,18,-909,7,72,19,7,0,5,6,8,11,6,5,-909,2,-909,-909,-909,-909,5,5,3,1, 106}
// *** End of generated data ***
};
@@ -127,7 +127,7 @@ const struct QS60StylePrivate::frameElementCenter QS60StylePrivate::m_frameEleme
{SE_ButtonPressed, QS60StyleEnums::SP_QsnFrButtonTbCenterPressed},
{SE_FrameLineEdit, QS60StyleEnums::SP_QsnFrInputCenter},
{SE_ListHighlight, QS60StyleEnums::SP_QsnFrListCenter},
- {SE_OptionsMenu, QS60StyleEnums::SP_QsnFrPopupCenter},
+ {SE_PopupBackground, QS60StyleEnums::SP_QsnFrPopupCenter},
{SE_SettingsList, QS60StyleEnums::SP_QsnFrSetOptCenter},
{SE_TableItem, QS60StyleEnums::SP_QsnFrCaleCenter},
{SE_TableHeaderItem, QS60StyleEnums::SP_QsnFrCaleHeadingCenter},
@@ -250,8 +250,8 @@ void QS60StylePrivate::drawSkinElement(SkinElements element, QPainter *painter,
case SE_ListHighlight:
drawFrame(SF_ListHighlight, painter, rect, flags | SF_PointNorth);
break;
- case SE_OptionsMenu:
- drawFrame(SF_OptionsMenu, painter, rect, flags | SF_PointNorth);
+ case SE_PopupBackground:
+ drawFrame(SF_PopupBackground, painter, rect, flags | SF_PointNorth);
break;
case SE_SettingsList:
drawFrame(SF_SettingsList, painter, rect, flags | SF_PointNorth);
@@ -307,6 +307,13 @@ void QS60StylePrivate::drawSkinPart(QS60StyleEnums::SkinParts part,
short QS60StylePrivate::pixelMetric(int metric)
{
+ //If it is a custom value, need to strip away the base to map to internal
+ //pixel metric value table
+ if (metric & QStyle::PM_CustomBase) {
+ metric -= QStyle::PM_CustomBase;
+ metric += MAX_NON_CUSTOM_PIXELMETRICS - 1;
+ }
+
Q_ASSERT(metric < MAX_PIXELMETRICS);
const short returnValue = m_pmPointer[metric];
return returnValue;
@@ -407,8 +414,8 @@ QColor QS60StylePrivate::colorFromFrameGraphics(SkinFrameElements frame) const
{
const bool cachedColorExists = m_colorCache.contains(frame);
if (!cachedColorExists) {
- const int frameCornerWidth = pixelMetric(PM_Custom_FrameCornerWidth);
- const int frameCornerHeight = pixelMetric(PM_Custom_FrameCornerHeight);
+ const int frameCornerWidth = pixelMetric(PM_FrameCornerWidth);
+ const int frameCornerHeight = pixelMetric(PM_FrameCornerHeight);
Q_ASSERT(2 * frameCornerWidth < 32);
Q_ASSERT(2 * frameCornerHeight < 32);
@@ -630,6 +637,8 @@ void QS60StylePrivate::setFont(QWidget *widget) const
fontCategory = QS60StyleEnums::FC_Secondary;
} else if (qobject_cast<QGroupBox *>(widget)){
fontCategory = QS60StyleEnums::FC_Title;
+ } else if (qobject_cast<QMessageBox *>(widget)){
+ fontCategory = QS60StyleEnums::FC_Primary;
}
if (fontCategory != QS60StyleEnums::FC_Undefined) {
const bool resolveFontSize = widget->testAttribute(Qt::WA_SetFont)
@@ -868,7 +877,7 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag
case QS60StyleEnums::SP_QgnGrafBarFrameSideL:
case QS60StyleEnums::SP_QgnGrafBarFrameSideR:
- result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ result.setWidth(pixelMetric(PM_FrameCornerWidth));
break;
case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed:
@@ -895,15 +904,15 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag
case 7: /* CornerTr */
case 6: /* CornerBl */
case 5: /* CornerBr */
- result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ result.setWidth(pixelMetric(PM_FrameCornerWidth));
// Falltrough intended...
case 4: /* SideT */
case 3: /* SideB */
- result.setHeight(pixelMetric(PM_Custom_FrameCornerHeight));
+ result.setHeight(pixelMetric(PM_FrameCornerHeight));
break;
case 2: /* SideL */
case 1: /* SideR */
- result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth));
+ result.setWidth(pixelMetric(PM_FrameCornerWidth));
break;
case 0: /* center */
default:
@@ -1002,7 +1011,6 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom
QS60StylePrivate::SE_SliderGrooveVertical;
QS60StylePrivate::drawSkinElement(grooveElement, painter, sliderGroove, flags);
} else {
- const QRect sliderGroove = subControlRect(control, optionSlider, SC_SliderGroove, widget);
const QPoint sliderGrooveCenter = sliderGroove.center();
const bool horizontal = optionSlider->orientation == Qt::Horizontal;
painter->save();
@@ -1129,7 +1137,7 @@ void QS60Style::drawComplexControl(ComplexControl control, const QStyleOptionCom
drawPrimitive(pe, &toolButton, painter, widget);
}
- if (toolBtn->text.length()>0 ||
+ if (toolBtn->text.length() > 0 ||
!toolBtn->icon.isNull()) {
const int frameWidth = pixelMetric(PM_DefaultFrameWidth, option, widget);
toolButton.rect = button.adjusted(frameWidth, frameWidth, -frameWidth, -frameWidth);
@@ -1371,7 +1379,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
}
if (!comboBox->currentText.isEmpty() && !comboBox->editable) {
QCommonStyle::drawItemText(painter,
- editRect.adjusted(QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth), 0, -1, 0),
+ editRect.adjusted(QS60StylePrivate::pixelMetric(PM_FrameCornerWidth), 0, -1, 0),
visualAlignment(comboBox->direction, Qt::AlignLeft | Qt::AlignVCenter),
comboBox->palette, comboBox->state & State_Enabled, comboBox->currentText);
}
@@ -1836,8 +1844,8 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
painter->save();
QPen linePen = QPen(QS60StylePrivate::s60Color(QS60StyleEnums::CL_QsnLineColors, 1, header));
const int penWidth = (header->orientation == Qt::Horizontal) ?
- linePen.width() + QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth)
- : linePen.width() + QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth);
+ linePen.width() + QS60StylePrivate::pixelMetric(PM_BoldLineWidth)
+ : linePen.width() + QS60StylePrivate::pixelMetric(PM_ThinLineWidth);
linePen.setWidth(penWidth);
painter->setPen(linePen);
if (header->orientation == Qt::Horizontal){
@@ -1856,7 +1864,7 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
//Make cornerButton slightly smaller so that it is not on top of table border graphic.
QStyleOptionHeader subopt = *header;
const int borderTweak =
- QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1;
+ QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
if (subopt.direction == Qt::LeftToRight)
subopt.rect.adjust(borderTweak, borderTweak, 0, -borderTweak);
else
@@ -1964,40 +1972,37 @@ void QS60Style::drawControl(ControlElement element, const QStyleOption *option,
case CE_MenuScroller:
break;
case CE_FocusFrame: {
- // The pen width should nearly fill the layoutspacings around the widget
- const int penWidth =
- qMin(pixelMetric(QS60Style::PM_LayoutVerticalSpacing), pixelMetric(QS60Style::PM_LayoutHorizontalSpacing))
- - 2; // But keep 1 pixel distance to the focus widget and 1 pixel to the adjacent widgets
-
#ifdef QT_KEYPAD_NAVIGATION
bool editFocus = false;
if (const QFocusFrame *focusFrame = qobject_cast<const QFocusFrame*>(widget)) {
if (focusFrame->widget() && focusFrame->widget()->hasEditFocus())
editFocus = true;
}
- const qreal opacity = editFocus ? 0.65 : 0.45; // Trial and error factors. Feel free to improve.
+ const qreal opacity = editFocus ? 1 : 0.75; // Trial and error factors. Feel free to improve.
#else
- const qreal opacity = 0.5;
+ const qreal opacity = 0.85;
#endif
- // Because of Qts coordinate system, we need to tweak the rect by .5 pixels, otherwise it gets blurred.
- const qreal rectAdjustment = (penWidth % 2) ? -.5 : 0;
-
- // Make sure that the pen stroke is inside the rect
- const QRectF adjustedRect =
- QRectF(option->rect).adjusted(
- rectAdjustment + penWidth,
- rectAdjustment + penWidth,
- -rectAdjustment - penWidth,
- -rectAdjustment - penWidth
- );
-
- const qreal roundRectRadius = penWidth * goldenRatio;
+ // We need to reduce the focus frame size if LayoutSpacing is smaller than FocusFrameMargin
+ // Otherwise, we would overlay adjacent widgets.
+ const int frameHeightReduction =
+ qMin(0, pixelMetric(QStyle::PM_LayoutVerticalSpacing)
+ - pixelMetric(QStyle::PM_FocusFrameVMargin));
+ const int frameWidthReduction =
+ qMin(0, pixelMetric(QStyle::PM_LayoutHorizontalSpacing)
+ - pixelMetric(QStyle::PM_FocusFrameHMargin));
+ const int rounding =
+ qMin(pixelMetric(QStyle::PM_FocusFrameVMargin),
+ pixelMetric(QStyle::PM_LayoutVerticalSpacing));
+ const QRect frameRect =
+ option->rect.adjusted(-frameWidthReduction, -frameHeightReduction,
+ frameWidthReduction, frameHeightReduction);
+ QPainterPath framePath;
+ framePath.addRoundedRect(frameRect, rounding, rounding);
painter->save();
painter->setRenderHint(QPainter::Antialiasing);
painter->setOpacity(opacity);
- painter->setPen(QPen(option->palette.color(QPalette::Text), penWidth));
- painter->drawRoundedRect(adjustedRect, roundRectRadius, roundRectRadius);
+ painter->fillPath(framePath, option->palette.color(QPalette::Text));
painter->restore();
}
break;
@@ -2080,7 +2085,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
// ... or normal "tick" selection at the end.
} else if (option->state & State_Selected) {
QRect tickRect = option->rect;
- const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
+ const int frameBorderWidth = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth);
// adjust tickmark rect to exclude frame border
tickRect.adjust(0, -frameBorderWidth, 0, -frameBorderWidth);
QS60StyleEnums::SkinParts skinPart = QS60StyleEnums::SP_QgnIndiMarkedAdd;
@@ -2161,7 +2166,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
const QS60StyleEnums::SkinParts part = (element == PE_IndicatorSpinUp) ?
QS60StyleEnums::SP_QgnGrafScrollArrowUp :
QS60StyleEnums::SP_QgnGrafScrollArrowDown;
- const int iconMargin = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1;
+ const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
optionSpinBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin );
QS60StylePrivate::drawSkinPart(part, painter, optionSpinBox.rect, flags);
} else {
@@ -2175,7 +2180,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
// We want to draw down arrow here for comboboxes as well.
QStyleOptionFrame optionsComboBox = *cmb;
const QS60StyleEnums::SkinParts part = QS60StyleEnums::SP_QgnGrafScrollArrowDown;
- const int iconMargin = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth) >> 1;
+ const int iconMargin = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth) >> 1;
optionsComboBox.rect.translate(0, (element == PE_IndicatorSpinDown) ? iconMargin : -iconMargin );
QS60StylePrivate::drawSkinPart(part, painter, optionsComboBox.rect, flags);
} else {
@@ -2213,7 +2218,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
if (QS60StylePrivate::canDrawThemeBackground(option->palette.base(), widget) &&
option->palette.window().texture().cacheKey() ==
QS60StylePrivate::m_themePalette->window().texture().cacheKey())
- QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_OptionsMenu, painter, option->rect, flags);
+ QS60StylePrivate::drawSkinElement(QS60StylePrivate::SE_PopupBackground, painter, option->rect, flags);
else
commonStyleDraws = true;
}
@@ -2309,7 +2314,7 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti
(option->state & State_Open) ? QS60StyleEnums::SP_QgnIndiHlColSuper : QS60StyleEnums::SP_QgnIndiHlExpSuper;
int minDimension = qMin(option->rect.width(), option->rect.height());
QRect iconRect(option->rect.topLeft(), QSize(minDimension, minDimension));
- const int magicTweak = 3;
+ const int magicTweak = 3;
int resizeValue = minDimension >> 1;
if (!QS60StylePrivate::isTouchSupported()) {
minDimension += resizeValue; // Adjust the icon bigger because of empty space in svg icon.
@@ -2384,13 +2389,6 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const
if (metricValue == KNotFound)
metricValue = QCommonStyle::pixelMetric(metric, option, widget);
- if (metric == PM_SubMenuOverlap && widget) {
- const QMenu *menu = qobject_cast<const QMenu *>(widget);
- if (menu && menu->activeAction() && menu->activeAction()->menu()) {
- const int menuWidth = menu->activeAction()->menu()->sizeHint().width();
- metricValue = -menuWidth;
- }
- }
//if layout direction is mirrored, switch left and right border margins
if (option && option->direction == Qt::RightToLeft) {
if (metric == PM_LayoutLeftMargin)
@@ -2398,6 +2396,12 @@ int QS60Style::pixelMetric(PixelMetric metric, const QStyleOption *option, const
else if (metric == PM_LayoutRightMargin)
metricValue = QS60StylePrivate::pixelMetric(PM_LayoutLeftMargin);
}
+
+ if (widget && (metric == PM_LayoutTopMargin))
+ if (widget->windowType() == Qt::Dialog)
+ //double the top layout margin for dialogs, it is very close to real value
+ //without having to define custom pixel metric
+ metricValue *= 2;
return metricValue;
}
@@ -2454,9 +2458,9 @@ QSize QS60Style::sizeFromContents(ContentsType ct, const QStyleOption *opt,
#ifndef QT_NO_COMBOBOX
case CT_ComboBox: {
// Fixing Ui design issues with too wide QComboBoxes and greedy SizeHints
- // Make sure, that the combobox says within the screen.
+ // Make sure, that the combobox stays within the screen.
const QSize desktopContentSize = QApplication::desktop()->availableGeometry().size()
- -QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0);
+ - QSize(pixelMetric(PM_LayoutLeftMargin) + pixelMetric(PM_LayoutRightMargin), 0);
sz = QCommonStyle::sizeFromContents(ct, opt, csz, widget).
boundedTo(desktopContentSize);
}
@@ -2622,14 +2626,22 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
const int frameThickness = spinbox->frame ? pixelMetric(PM_SpinBoxFrameWidth, spinbox, widget) : 0;
const int buttonMargin = spinbox->frame ? 2 : 0;
const int buttonContentWidth = QS60StylePrivate::pixelMetric(PM_ButtonIconSize) + 2 * buttonMargin;
+ // Spinbox buttons should be no larger than one fourth of total width.
+ // Thus, side-by-side buttons would take half of the total width.
+ const int maxSize = qMax(spinbox->rect.width() / 4, buttonContentWidth);
QSize buttonSize;
- buttonSize.setHeight(qMax(8, spinbox->rect.height() - frameThickness));
+ buttonSize.setHeight(qMin(maxSize, qMax(8, spinbox->rect.height() - frameThickness)));
//width should at least be equal to height
buttonSize.setWidth(qMax(buttonSize.height(), buttonContentWidth));
buttonSize = buttonSize.expandedTo(QApplication::globalStrut());
- const int y = frameThickness + spinbox->rect.y();
- const int x = spinbox->rect.x() + spinbox->rect.width() - frameThickness - 2 * buttonSize.width();
+ // Normally spinbuttons should be side-by-side, but if spinbox grows very big
+ // and spinbuttons reach their maximum size, they can be deployed one top of the other.
+ const bool sideBySide = (buttonSize.height() * 2 < spinbox->rect.height()) ? false : true;
+ const int y = frameThickness + spinbox->rect.y() +
+ (spinbox->rect.height() - (sideBySide ? 1 : 2) * buttonSize.height()) / 2;
+ const int x = spinbox->rect.x() +
+ spinbox->rect.width() - frameThickness - (sideBySide ? 2 : 1) * buttonSize.width();
switch (scontrol) {
case SC_SpinBoxUp:
@@ -2640,7 +2652,9 @@ QRect QS60Style::subControlRect(ComplexControl control, const QStyleOptionComple
case SC_SpinBoxDown:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
return QRect();
- ret = QRect(x + buttonSize.width(), y, buttonSize.width(), buttonSize.height());
+ ret = QRect(x + (sideBySide ? buttonSize.width() : 0),
+ y + (sideBySide ? 0 : buttonSize.height()),
+ buttonSize.width(), buttonSize.height());
break;
case SC_SpinBoxEditField:
if (spinbox->buttonSymbols == QAbstractSpinBox::NoButtons)
@@ -2783,11 +2797,10 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
break;
case SE_LineEditContents: {
// in S60 the input text box doesn't start from line Edit's TL, but
- // a bit indented.
- QRect lineEditRect = opt->rect;
- const int adjustment = opt->rect.height() >> 2;
- lineEditRect.adjust(adjustment, 0, 0, 0);
- ret = lineEditRect;
+ // a bit indented (8 pixels).
+ const int KLineEditDefaultIndention = 8;
+ ret = visualRect(
+ opt->direction, opt->rect, opt->rect.adjusted(KLineEditDefaultIndention, 0, 0, 0));
}
break;
case SE_TabBarTearIndicator:
@@ -2929,9 +2942,9 @@ QRect QS60Style::subElementRect(SubElement element, const QStyleOption *opt, con
if (qstyleoption_cast<const QStyleOptionHeader *>(opt)) {
// Subtract area needed for line
if (opt->state & State_Horizontal)
- ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_Custom_BoldLineWidth));
+ ret.setHeight(ret.height() - QS60StylePrivate::pixelMetric(PM_BoldLineWidth));
else
- ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_Custom_ThinLineWidth));
+ ret.setWidth(ret.width() - QS60StylePrivate::pixelMetric(PM_ThinLineWidth));
}
ret = visualRect(opt->direction, opt->rect, ret);
break;
@@ -3242,7 +3255,7 @@ bool QS60Style::eventFilter(QObject *object, QEvent *event)
/*!
\internal
- Handle the timer \a event.
+ Handle the timer \a event.
*/
void QS60Style::timerEvent(QTimerEvent *event)
{
diff --git a/src/gui/styles/qs60style.h b/src/gui/styles/qs60style.h
index 82cc21c..c878538 100644
--- a/src/gui/styles/qs60style.h
+++ b/src/gui/styles/qs60style.h
@@ -52,6 +52,16 @@ QT_MODULE(Gui)
#if !defined(QT_NO_STYLE_S60)
+//Public custom pixel metrics values.
+//These can be used to fetch custom pixel metric value from outside QS60Style.
+enum {
+ PM_FrameCornerWidth = QStyle::PM_CustomBase + 1,
+ PM_FrameCornerHeight,
+ PM_BoldLineWidth,
+ PM_ThinLineWidth,
+ PM_MessageBoxHeight
+ };
+
class QS60StylePrivate;
class Q_GUI_EXPORT QS60Style : public QCommonStyle
diff --git a/src/gui/styles/qs60style_p.h b/src/gui/styles/qs60style_p.h
index 16d82e7..6ce4960 100644
--- a/src/gui/styles/qs60style_p.h
+++ b/src/gui/styles/qs60style_p.h
@@ -60,13 +60,8 @@
QT_BEGIN_NAMESPACE
const int MAX_NON_CUSTOM_PIXELMETRICS = 92;
-const int CUSTOMVALUESCOUNT = 4;
-enum {
- PM_Custom_FrameCornerWidth = MAX_NON_CUSTOM_PIXELMETRICS,
- PM_Custom_FrameCornerHeight,
- PM_Custom_BoldLineWidth,
- PM_Custom_ThinLineWidth
- };
+const int CUSTOMVALUESCOUNT = 5;
+
const int MAX_PIXELMETRICS = MAX_NON_CUSTOM_PIXELMETRICS + CUSTOMVALUESCOUNT;
typedef struct {
@@ -416,7 +411,7 @@ public:
SE_TabBarTabWestActive,
SE_TabBarTabWestInactive,
SE_ListHighlight,
- SE_OptionsMenu,
+ SE_PopupBackground,
SE_SettingsList,
SE_TableItem,
SE_TableHeaderItem,
@@ -425,7 +420,7 @@ public:
SE_ToolBarButton,
SE_ToolBarButtonPressed,
SE_PanelBackground,
- SE_ScrollBarHandlePressedHorizontal, //only for 5.0+
+ SE_ScrollBarHandlePressedHorizontal,
SE_ScrollBarHandlePressedVertical,
SE_ButtonInactive,
SE_Editor,
@@ -437,7 +432,7 @@ public:
SF_ButtonPressed,
SF_FrameLineEdit,
SF_ListHighlight,
- SF_OptionsMenu,
+ SF_PopupBackground,
SF_SettingsList,
SF_TableItem,
SF_TableHeaderItem,
diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp
index 4a279a7..6a552e0 100644
--- a/src/gui/styles/qs60style_s60.cpp
+++ b/src/gui/styles/qs60style_s60.cpp
@@ -755,7 +755,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(
if (drawn)
result = fromFbsBitmap(background, NULL, flags, targetSize);
- // if drawing fails in skin server, just ignore the background (probably OOM occured)
+ // if drawing fails in skin server, just ignore the background (probably OOM case)
CleanupStack::PopAndDestroy(4, background); //background, dev, gc, bgContext
// QS60WindowSurface::lockBitmapHeap();
@@ -787,7 +787,7 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(
const int currentFrame = QS60StylePrivate::currentAnimationFrame(part);
if (constructedFromTheme && aknAnimation && aknAnimation->BitmapAnimData()->FrameArray().Count() > 0) {
- //Animation was created succesfully and contains frames, just fetch current frame
+ //Animation was created successfully and contains frames, just fetch current frame
if(currentFrame >= aknAnimation->BitmapAnimData()->FrameArray().Count())
User::Leave(KErrOverflow);
const CBitmapFrameData* frameData = aknAnimation->BitmapAnimData()->FrameArray().At(currentFrame);
@@ -859,11 +859,9 @@ QPixmap QS60StyleModeSpecifics::createSkinnedGraphicsLX(QS60StylePrivate::SkinFr
User::LeaveIfError(bitmapDev->CreateContext(bitmapGc));
CleanupStack::PushL(bitmapGc);
-#ifndef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE
frame->LockHeap();
memset(frame->DataAddress(), 0, frame->SizeInPixels().iWidth * frame->SizeInPixels().iHeight * 4); // 4: argb bytes
frame->UnlockHeap();
-#endif
const TRect outerRect(TPoint(0, 0), targetSize);
const TRect innerRect = innerRectFromElement(frameElement, outerRect);
@@ -978,21 +976,25 @@ void QS60StyleModeSpecifics::frameIdAndCenterId(QS60StylePrivate::SkinFrameEleme
TRect QS60StyleModeSpecifics::innerRectFromElement(QS60StylePrivate::SkinFrameElements frameElement, const TRect &outerRect)
{
- TInt widthShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerWidth);
- TInt heightShrink = QS60StylePrivate::pixelMetric(PM_Custom_FrameCornerHeight);
+ TInt widthShrink = QS60StylePrivate::pixelMetric(PM_FrameCornerWidth);
+ TInt heightShrink = QS60StylePrivate::pixelMetric(PM_FrameCornerHeight);
switch(frameElement) {
case QS60StylePrivate::SF_PanelBackground:
// panel should have slightly slimmer border to enable thin line of background graphics between closest component
- widthShrink = widthShrink-2;
- heightShrink = heightShrink-2;
+ widthShrink = widthShrink - 2;
+ heightShrink = heightShrink - 2;
break;
case QS60StylePrivate::SF_ToolTip:
- widthShrink = widthShrink>>1;
- heightShrink = heightShrink>>1;
+ widthShrink = widthShrink >> 1;
+ heightShrink = heightShrink >> 1;
break;
case QS60StylePrivate::SF_ListHighlight:
- widthShrink = widthShrink-2;
- heightShrink = heightShrink-2;
+ widthShrink = widthShrink - 2;
+ heightShrink = heightShrink - 2;
+ break;
+ case QS60StylePrivate::SF_PopupBackground:
+ widthShrink = widthShrink + 5;
+ heightShrink = heightShrink + 5;
break;
default:
break;
@@ -1096,7 +1098,7 @@ void QS60StylePrivate::setActiveLayout()
activeLayoutIndex += (!landscape) ? 1 : 0;
}
- m_pmPointer = data[activeLayoutIndex];
+ setCurrentLayout(activeLayoutIndex);
}
Q_GLOBAL_STATIC(QList<QS60StyleAnimation *>, m_animations)
diff --git a/src/gui/text/qfontdatabase_s60.cpp b/src/gui/text/qfontdatabase_s60.cpp
index 621f666..ef5e0c4 100644
--- a/src/gui/text/qfontdatabase_s60.cpp
+++ b/src/gui/text/qfontdatabase_s60.cpp
@@ -332,6 +332,11 @@ bool QFontDatabase::removeApplicationFont(int handle)
return false;
}
+bool QFontDatabase::removeAllApplicationFonts()
+{
+ return false;
+}
+
bool QFontDatabase::supportsThreadedFontRendering()
{
return false;
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index e5975d2..194c5f3 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -379,6 +379,15 @@ void QFontEngine::getGlyphPositions(const QGlyphLayout &glyphs, const QTransform
Q_ASSERT(positions.size() == glyphs_out.size());
}
+void QFontEngine::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ glyph_metrics_t gi = boundingBox(glyph);
+ bool isValid = gi.isValid();
+ if (leftBearing != 0)
+ *leftBearing = isValid ? gi.x.toReal() : 0.0;
+ if (rightBearing != 0)
+ *rightBearing = isValid ? (gi.xoff - gi.x - gi.width).toReal() : 0.0;
+}
glyph_metrics_t QFontEngine::tightBoundingBox(const QGlyphLayout &glyphs)
{
@@ -1389,6 +1398,12 @@ glyph_metrics_t QFontEngineMulti::boundingBox(const QGlyphLayout &glyphs)
return overall;
}
+void QFontEngineMulti::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ int which = highByte(glyph);
+ engine(which)->getGlyphBearings(stripped(glyph), leftBearing, rightBearing);
+}
+
void QFontEngineMulti::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags)
{
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index 71ab5a5..e645caf 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -206,6 +206,8 @@ public:
virtual qreal minLeftBearing() const { return qreal(); }
virtual qreal minRightBearing() const { return qreal(); }
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+
virtual const char *name() const = 0;
virtual bool canRender(const QChar *string, int len) = 0;
@@ -374,6 +376,7 @@ public:
virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const;
virtual void addOutlineToPath(qreal, qreal, const QGlyphLayout &, QPainterPath *, QTextItem::RenderFlags flags);
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
virtual QFixed ascent() const;
virtual QFixed descent() const;
diff --git a/src/gui/text/qfontengine_win.cpp b/src/gui/text/qfontengine_win.cpp
index 55e93bd..a805612 100644
--- a/src/gui/text/qfontengine_win.cpp
+++ b/src/gui/text/qfontengine_win.cpp
@@ -39,6 +39,11 @@
**
****************************************************************************/
+#if _WIN32_WINNT < 0x0500
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0500
+#endif
+
#include "qfontengine_p.h"
#include "qtextengine_p.h"
#include <qglobal.h>
@@ -649,6 +654,32 @@ static const ushort char_table[] = {
static const int char_table_entries = sizeof(char_table)/sizeof(ushort);
+#ifndef Q_CC_MINGW
+void QFontEngineWin::getGlyphBearings(glyph_t glyph, qreal *leftBearing, qreal *rightBearing)
+{
+ HDC hdc = shared_dc();
+ SelectObject(hdc, hfont);
+
+#ifndef Q_WS_WINCE
+ if (ttf)
+#endif
+
+ {
+ ABC abcWidths;
+ GetCharABCWidthsI(hdc, glyph, 1, 0, &abcWidths);
+ if (leftBearing)
+ *leftBearing = abcWidths.abcA;
+ if (rightBearing)
+ *rightBearing = abcWidths.abcC;
+ }
+
+#ifndef Q_WS_WINCE
+ else {
+ QFontEngine::getGlyphBearings(glyph, leftBearing, rightBearing);
+ }
+#endif
+}
+#endif // Q_CC_MINGW
qreal QFontEngineWin::minLeftBearing() const
{
diff --git a/src/gui/text/qfontengine_win_p.h b/src/gui/text/qfontengine_win_p.h
index f9d8f8b..68b53b5 100644
--- a/src/gui/text/qfontengine_win_p.h
+++ b/src/gui/text/qfontengine_win_p.h
@@ -106,6 +106,10 @@ public:
virtual QImage alphaMapForGlyph(glyph_t, const QTransform &xform);
virtual QImage alphaRGBMapForGlyph(glyph_t t, int margin, const QTransform &xform);
+#ifndef Q_CC_MINGW
+ virtual void getGlyphBearings(glyph_t glyph, qreal *leftBearing = 0, qreal *rightBearing = 0);
+#endif
+
int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, bool mirrored) const;
void getCMap();
diff --git a/src/gui/text/qfontmetrics.cpp b/src/gui/text/qfontmetrics.cpp
index 7f9ae8b..3a52e8e 100644
--- a/src/gui/text/qfontmetrics.cpp
+++ b/src/gui/text/qfontmetrics.cpp
@@ -472,8 +472,9 @@ int QFontMetrics::leftBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return qRound(gi.x);
+ qreal lb;
+ engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ return qRound(lb);
}
/*!
@@ -506,8 +507,9 @@ int QFontMetrics::rightBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return qRound(gi.xoff - gi.x - gi.width);
+ qreal rb;
+ engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ return qRound(rb);
}
/*!
@@ -1317,8 +1319,9 @@ qreal QFontMetricsF::leftBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return gi.x.toReal();
+ qreal lb;
+ engine->getGlyphBearings(glyphs.glyphs[0], &lb);
+ return lb;
}
/*!
@@ -1351,8 +1354,10 @@ qreal QFontMetricsF::rightBearing(QChar ch) const
int nglyphs = 9;
engine->stringToCMap(&ch, 1, &glyphs, &nglyphs, 0);
// ### can nglyphs != 1 happen at all? Not currently I think
- glyph_metrics_t gi = engine->boundingBox(glyphs.glyphs[0]);
- return (gi.xoff - gi.x - gi.width).toReal();
+ qreal rb;
+ engine->getGlyphBearings(glyphs.glyphs[0], 0, &rb);
+ return rb;
+
}
/*!
diff --git a/src/gui/text/qstatictext.cpp b/src/gui/text/qstatictext.cpp
index d685cd9..5f31ef0 100644
--- a/src/gui/text/qstatictext.cpp
+++ b/src/gui/text/qstatictext.cpp
@@ -99,20 +99,27 @@ QT_BEGIN_NAMESPACE
point with no boundaries, and also when QPainter::drawText() is called with a bounding
rectangle.
- If a bounding rectangle is not required, create a QStaticText object without setting a maximum
- size. The text will then occupy a single line.
+ If a bounding rectangle is not required, create a QStaticText object without setting a preferred
+ text width. The text will then occupy a single line.
- If you set a maximum size on the QStaticText object, this will bound the text. The text will
- be formatted so that no line exceeds the given width. When the object is painted, it will
- be clipped at the given size. The position of the text is decided by the argument
- passed to QPainter::drawStaticText() and can change from call to call with a minimal impact
- on performance.
+ If you set a text width on the QStaticText object, this will bound the text. The text will
+ be formatted so that no line exceeds the given width. The text width set for QStaticText will
+ not automatically be used for clipping. To achieve clipping in addition to line breaks, use
+ QPainter::setClipRect(). The position of the text is decided by the argument passed to
+ QPainter::drawStaticText() and can change from call to call with a minimal impact on
+ performance.
QStaticText will attempt to guess the format of the input text using Qt::mightBeRichText().
To force QStaticText to display its contents as either plain text or rich text, use the
function QStaticText::setTextFormat() and pass in, respectively, Qt::PlainText and
Qt::RichText.
+ If it's the first time the static text is drawn, or if the static text, or the painter's font
+ or matrix have been altered since the last time it was drawn, the text's layout has to be
+ recalculated. This will impose an overhead on the QPainter::drawStaticText() call where the
+ relayout occurs. To avoid this overhead in the paint event, you can call prepare() ahead of
+ time to ensure that the layout is calculated.
+
\sa QPainter::drawText(), QPainter::drawStaticText(), QTextLayout, QTextDocument
*/
@@ -143,12 +150,11 @@ QStaticText::QStaticText()
If an invalid size is passed for \a size the text will be unbounded.
*/
-QStaticText::QStaticText(const QString &text, const QSizeF &size)
+QStaticText::QStaticText(const QString &text)
: data(new QStaticTextPrivate)
{
data->text = text;
- data->maximumSize = size;
- data->init();
+ data->invalidate();
}
/*!
@@ -177,17 +183,17 @@ void QStaticText::detach()
}
/*!
- Prepares the QStaticText object for being painted with the given \a matrix and the given
- \a font to avoid overhead when the actual drawStaticText() call is made.
+ Prepares the QStaticText object for being painted with the given \a matrix and the given \a font
+ to avoid overhead when the actual drawStaticText() call is made.
- When drawStaticText() is called, the layout of the QStaticText will be recalculated if the
- painter's font or matrix is different from the one used for the currently cached layout. By
- default, QStaticText will use a default constructed QFont and an identity matrix to create
- its layout.
+ When drawStaticText() is called, the layout of the QStaticText will be recalculated if any part
+ of the QStaticText object has changed since the last time it was drawn. It will also be
+ recalculated if the painter's font or matrix are not the same as when the QStaticText was last
+ drawn.
- To avoid the overhead of creating the layout the first time you draw the QStaticText with
- a painter whose matrix or font are different from the defaults, you can use the prepare()
- function and pass in the matrix and font you expect to use when drawing the text.
+ To avoid the overhead of creating the layout the first time you draw the QStaticText after
+ making changes, you can use the prepare() function and pass in the \a matrix and \a font you
+ expect to use when drawing the text.
\sa QPainter::setFont(), QPainter::setMatrix()
*/
@@ -209,7 +215,7 @@ QStaticText &QStaticText::operator=(const QStaticText &other)
}
/*!
- Compares \a other to this QStaticText. Returns true if the texts, fonts and maximum sizes
+ Compares \a other to this QStaticText. Returns true if the texts, fonts and text widths
are equal.
*/
bool QStaticText::operator==(const QStaticText &other) const
@@ -217,7 +223,7 @@ bool QStaticText::operator==(const QStaticText &other) const
return (data == other.data
|| (data->text == other.data->text
&& data->font == other.data->font
- && data->maximumSize == other.data->maximumSize));
+ && data->textWidth == other.data->textWidth));
}
/*!
@@ -232,7 +238,7 @@ bool QStaticText::operator!=(const QStaticText &other) const
/*!
Sets the text of the QStaticText to \a text.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa text()
*/
@@ -240,7 +246,7 @@ void QStaticText::setText(const QString &text)
{
detach();
data->text = text;
- data->init();
+ data->invalidate();
}
/*!
@@ -250,7 +256,7 @@ void QStaticText::setText(const QString &text)
displayed as is, whereas it will be interpreted as HTML if the format is Qt::RichText. HTML tags
that alter the font of the text, its color, or its layout are supported by QStaticText.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa textFormat(), setText(), text()
*/
@@ -258,7 +264,7 @@ void QStaticText::setTextFormat(Qt::TextFormat textFormat)
{
detach();
data->textFormat = textFormat;
- data->init();
+ data->invalidate();
}
/*!
@@ -289,7 +295,7 @@ QString QStaticText::text() const
The default is QStaticText::ModerateCaching.
- \note This function will cause the layout of the text to be recalculated.
+ \note This function will cause the layout of the text to require recalculation.
\sa performanceHint()
*/
@@ -301,7 +307,7 @@ void QStaticText::setPerformanceHint(PerformanceHint performanceHint)
}
detach();
data->useBackendOptimizations = (performanceHint == AggressiveCaching);
- data->init();
+ data->invalidate();
}
/*!
@@ -315,48 +321,56 @@ QStaticText::PerformanceHint QStaticText::performanceHint() const
}
/*!
- Sets the maximum size of the QStaticText to \a size.
+ Sets the preferred width for this QStaticText. If the text is wider than the specified width,
+ it will be broken into multiple lines and grow vertically. If the text cannot be split into
+ multiple lines, it will be larger than the specified \a textWidth.
- \note This function will cause the layout of the text to be recalculated.
+ Setting the preferred text width to a negative number will cause the text to be unbounded.
- \sa maximumSize(), size()
+ Use size() to get the actual size of the text.
+
+ \note This function will cause the layout of the text to require recalculation.
+
+ \sa textWidth(), size()
*/
-void QStaticText::setMaximumSize(const QSizeF &size)
+void QStaticText::setTextWidth(qreal textWidth)
{
detach();
- data->maximumSize = size;
- data->init();
+ data->textWidth = textWidth;
+ data->invalidate();
}
/*!
- Returns the maximum size of the QStaticText.
+ Returns the preferred width for this QStaticText.
- \sa setMaximumSize()
+ \sa setTextWidth()
*/
-QSizeF QStaticText::maximumSize() const
+qreal QStaticText::textWidth() const
{
- return data->maximumSize;
+ return data->textWidth;
}
/*!
Returns the size of the bounding rect for this QStaticText.
- \sa maximumSize()
+ \sa textWidth()
*/
QSizeF QStaticText::size() const
{
+ if (data->needsRelayout)
+ data->init();
return data->actualSize;
}
QStaticTextPrivate::QStaticTextPrivate()
- : items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false),
- useBackendOptimizations(false), textFormat(Qt::AutoText)
+ : items(0), itemCount(0), glyphPool(0), positionPool(0), textWidth(-1.0),
+ needsRelayout(true), useBackendOptimizations(false), textFormat(Qt::AutoText)
{
}
QStaticTextPrivate::QStaticTextPrivate(const QStaticTextPrivate &other)
- : text(other.text), font(other.font), maximumSize(other.maximumSize), matrix(other.matrix),
- items(0), itemCount(0), glyphPool(0), positionPool(0), needsClipRect(false),
+ : text(other.text), font(other.font), textWidth(other.textWidth), matrix(other.matrix),
+ items(0), itemCount(0), glyphPool(0), positionPool(0), needsRelayout(true),
useBackendOptimizations(other.useBackendOptimizations), textFormat(other.textFormat)
{
}
@@ -388,8 +402,15 @@ namespace {
m_expectedItemCount(expectedItemCount),
m_expectedGlyphCount(expectedGlyphCount),
m_glyphPool(glyphPool),
- m_positionPool(positionPool)
+ m_positionPool(positionPool),
+ m_dirtyPen(false)
+ {
+ }
+
+ virtual void updateState(const QPaintEngineState &newState)
{
+ if (newState.state() & QPaintEngine::DirtyPen)
+ m_dirtyPen = true;
}
virtual void drawTextItem(const QPointF &position, const QTextItem &textItem)
@@ -412,7 +433,8 @@ namespace {
currentItem->numGlyphs = ti.glyphs.numGlyphs;
currentItem->glyphs = m_glyphPool;
currentItem->glyphPositions = m_positionPool;
- currentItem->color = state->pen().color();
+ if (m_dirtyPen)
+ currentItem->color = state->pen().color();
QTransform matrix = state->transform();
matrix.translate(position.x(), position.y());
@@ -435,7 +457,6 @@ namespace {
virtual bool begin(QPaintDevice *) { return true; }
virtual bool end() { return true; }
- virtual void updateState(const QPaintEngineState &) {}
virtual void drawPixmap(const QRectF &, const QPixmap &, const QRectF &) {}
virtual Type type() const
{
@@ -461,6 +482,8 @@ namespace {
glyph_t *m_glyphPool;
QFixedPoint *m_positionPool;
+
+ bool m_dirtyPen;
};
class DrawTextItemDevice: public QPaintDevice
@@ -530,43 +553,55 @@ namespace {
};
}
-void QStaticTextPrivate::paintText(const QPointF &pos, QPainter *p)
+void QStaticTextPrivate::paintText(const QPointF &topLeftPosition, QPainter *p)
{
bool preferRichText = textFormat == Qt::RichText
|| (textFormat == Qt::AutoText && Qt::mightBeRichText(text));
if (!preferRichText) {
- if (maximumSize.isValid()) {
- QRectF boundingRect;
- p->drawText(QRectF(pos, maximumSize), Qt::TextWordWrap, text, &boundingRect);
-
- actualSize = boundingRect.size();
- needsClipRect = boundingRect.width() > maximumSize.width()
- || boundingRect.height() > maximumSize.height();
- } else {
- p->drawText(pos, text);
- needsClipRect = false;
-
- QFontMetrics fm(font);
- actualSize = fm.boundingRect(text).size();
+ QTextLayout textLayout;
+ textLayout.setText(text);
+ textLayout.setFont(font);
+
+ qreal leading = QFontMetricsF(font).leading();
+ qreal height = -leading;
+
+ textLayout.beginLayout();
+ while (1) {
+ QTextLine line = textLayout.createLine();
+ if (!line.isValid())
+ break;
+
+ if (textWidth >= 0.0)
+ line.setLineWidth(textWidth);
+ height += leading;
+ line.setPosition(QPointF(0.0, height));
+ height += line.height();
}
+ textLayout.endLayout();
+
+ actualSize = textLayout.boundingRect().size();
+ textLayout.draw(p, topLeftPosition);
} else {
QTextDocument document;
+ QColor color = p->pen().color();
+ document.setDefaultStyleSheet(QString::fromLatin1("body { color: #%1%2%3 }")
+ .arg(QString::number(color.red(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.green(), 16), 2, QLatin1Char('0'))
+ .arg(QString::number(color.blue(), 16), 2, QLatin1Char('0')));
document.setDefaultFont(font);
document.setDocumentMargin(0.0);
+ if (textWidth >= 0.0)
+ document.setTextWidth(textWidth);
document.setHtml(text);
- QPointF adjustedPos = pos - QPointF(0, QFontMetricsF(font).ascent());
- QRectF rect = maximumSize.isValid() ? QRectF(adjustedPos, maximumSize) : QRectF();
document.adjustSize();
p->save();
- p->translate(adjustedPos);
- document.drawContents(p, rect);
+ p->translate(topLeftPosition);
+ document.drawContents(p);
p->restore();
+
actualSize = document.size();
- needsClipRect = maximumSize.isValid()
- && (actualSize.width() > maximumSize.width()
- || actualSize.height() > maximumSize.height());
}
}
@@ -613,6 +648,7 @@ void QStaticTextPrivate::init()
paintText(QPointF(0, 0), &painter);
}
+ needsRelayout = false;
}
QT_END_NAMESPACE
diff --git a/src/gui/text/qstatictext.h b/src/gui/text/qstatictext.h
index 00d42e0..f3bef93 100644
--- a/src/gui/text/qstatictext.h
+++ b/src/gui/text/qstatictext.h
@@ -66,7 +66,7 @@ public:
};
QStaticText();
- QStaticText(const QString &text, const QSizeF &maximumSize = QSizeF());
+ QStaticText(const QString &text);
QStaticText(const QStaticText &other);
~QStaticText();
@@ -76,12 +76,12 @@ public:
void setTextFormat(Qt::TextFormat textFormat);
Qt::TextFormat textFormat() const;
- void setMaximumSize(const QSizeF &maximumSize);
- QSizeF maximumSize() const;
+ void setTextWidth(qreal textWidth);
+ qreal textWidth() const;
QSizeF size() const;
- void prepare(const QTransform &matrix, const QFont &font);
+ void prepare(const QTransform &matrix = QTransform(), const QFont &font = QFont());
void setPerformanceHint(PerformanceHint performanceHint);
PerformanceHint performanceHint() const;
diff --git a/src/gui/text/qstatictext_p.h b/src/gui/text/qstatictext_p.h
index e758244..f017ed1 100644
--- a/src/gui/text/qstatictext_p.h
+++ b/src/gui/text/qstatictext_p.h
@@ -118,11 +118,16 @@ public:
void init();
void paintText(const QPointF &pos, QPainter *p);
+ void invalidate()
+ {
+ needsRelayout = true;
+ }
+
QAtomicInt ref; // 4 bytes per text
QString text; // 4 bytes per text
QFont font; // 8 bytes per text
- QSizeF maximumSize; // 16 bytes per text
+ qreal textWidth; // 8 bytes per text
QSizeF actualSize; // 16 bytes per text
QPointF position; // 16 bytes per text
@@ -132,11 +137,11 @@ public:
glyph_t *glyphPool; // 4 bytes per text
QFixedPoint *positionPool; // 4 bytes per text
- unsigned char needsClipRect : 1; // 1 byte per text
- unsigned char useBackendOptimizations : 1;
+ unsigned char needsRelayout : 1;
+ unsigned char useBackendOptimizations : 1; // 1 byte per text
unsigned char textFormat : 2;
// ================
- // 171 bytes per text
+ // 163 bytes per text
static QStaticTextPrivate *get(const QStaticText *q);
};
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index 2fc5d1a..312d135 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -1702,9 +1702,9 @@ namespace {
if (currentPosition <= 0)
return;
- glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph());
- if (gi.isValid())
- rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width);
+ qreal rb;
+ fontEngine->getGlyphBearings(currentGlyph(), 0, &rb);
+ rightBearing = qMin(QFixed(), QFixed::fromReal(rb));
}
inline void resetRightBearing()
diff --git a/src/gui/widgets/qmenu.cpp b/src/gui/widgets/qmenu.cpp
index ebc05d9..404d46e 100644
--- a/src/gui/widgets/qmenu.cpp
+++ b/src/gui/widgets/qmenu.cpp
@@ -167,8 +167,8 @@ void QMenuPrivate::init()
#ifdef QT_SOFTKEYS_ENABLED
selectAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::SelectSoftKey, Qt::Key_Select, q);
cancelAction = QSoftKeyManager::createKeyedAction(QSoftKeyManager::CancelSoftKey, Qt::Key_Back, q);
- selectAction->setVisible(false); // Don't show these in the menu
- cancelAction->setVisible(false);
+ selectAction->setPriority(QAction::HighPriority);
+ cancelAction->setPriority(QAction::HighPriority);
q->addAction(selectAction);
q->addAction(cancelAction);
#endif
diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp
index 13aa02b..e368d3d 100644
--- a/src/gui/widgets/qmenubar.cpp
+++ b/src/gui/widgets/qmenubar.cpp
@@ -1404,7 +1404,6 @@ void QMenuBarPrivate::handleReparent()
if (!menuBarAction) {
if (newParent) {
menuBarAction = QSoftKeyManager::createAction(QSoftKeyManager::MenuSoftKey, newParent);
- menuBarAction->setVisible(false);
newParent->addAction(menuBarAction);
}
} else {
diff --git a/src/gui/widgets/qspinbox.cpp b/src/gui/widgets/qspinbox.cpp
index 726426d..2d871d0 100644
--- a/src/gui/widgets/qspinbox.cpp
+++ b/src/gui/widgets/qspinbox.cpp
@@ -448,11 +448,12 @@ void QSpinBox::setRange(int minimum, int maximum)
}
/*!
- This virtual function is used by the spin box whenever it needs
- to display the given \a value. The default implementation returns
- a string containing \a value printed in the standard way using
- QWidget::locale().toString(). Reimplementations may return anything. (See
- the example in the detailed description.)
+ This virtual function is used by the spin box whenever it needs to
+ display the given \a value. The default implementation returns a
+ string containing \a value printed in the standard way using
+ QWidget::locale().toString(), but with the thousand separator
+ removed. Reimplementations may return anything. (See the example
+ in the detailed description.)
Note: QSpinBox does not call this function for specialValueText()
and that neither prefix() nor suffix() should be included in the
@@ -461,7 +462,7 @@ void QSpinBox::setRange(int minimum, int maximum)
If you reimplement this, you may also need to reimplement
valueFromText() and validate()
- \sa valueFromText(), validate()
+ \sa valueFromText(), validate(), QLocale::groupSeparator()
*/
QString QSpinBox::textFromValue(int value) const
@@ -869,7 +870,7 @@ void QDoubleSpinBox::setDecimals(int decimals)
If you reimplement this, you may also need to reimplement
valueFromText().
- \sa valueFromText()
+ \sa valueFromText(), QLocale::groupSeparator()
*/
diff --git a/src/imports/multimedia/multimedia.pro b/src/imports/multimedia/multimedia.pro
index 16b3ace..78618fc 100644
--- a/src/imports/multimedia/multimedia.pro
+++ b/src/imports/multimedia/multimedia.pro
@@ -20,7 +20,18 @@ SOURCES += \
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
-qmldir.files += $$QT_BUILD_TREE/imports/$$TARGETPATH/qmldir
+qmldir.files += $$PWD/qmldir
qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+symbian:{
+ load(data_caging_paths)
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+
+ importFiles.sources = multimedia.dll \
+ qmldir
+ importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH
+
+ DEPLOYMENT = importFiles
+}
+
INSTALLS += target qmldir
diff --git a/src/imports/particles/particles.pro b/src/imports/particles/particles.pro
index 02d9ea6..a46db8c 100644
--- a/src/imports/particles/particles.pro
+++ b/src/imports/particles/particles.pro
@@ -14,7 +14,18 @@ HEADERS += \
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
-qmldir.files += $$QT_BUILD_TREE/imports/$$TARGETPATH/qmldir
+qmldir.files += $$PWD/qmldir
qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+symbian:{
+ load(data_caging_paths)
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+
+ importFiles.sources = particles.dll \
+ qmldir
+ importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH
+
+ DEPLOYMENT = importFiles
+}
+
INSTALLS += target qmldir
diff --git a/src/imports/particles/qdeclarativeparticles.cpp b/src/imports/particles/qdeclarativeparticles.cpp
index 83be59b..e69c235 100644
--- a/src/imports/particles/qdeclarativeparticles.cpp
+++ b/src/imports/particles/qdeclarativeparticles.cpp
@@ -623,6 +623,8 @@ void QDeclarativeParticlesPrivate::updateOpacity(QDeclarativeParticle &p, int ag
\brief The Particles object generates and moves particles.
\inherits Item
+ Particles are available in the Qt.labs.particles 1.0 module.
+
This element provides preliminary support for particles in QML,
and may be heavily changed or removed in later versions.
@@ -640,6 +642,9 @@ void QDeclarativeParticlesPrivate::updateOpacity(QDeclarativeParticle &p, int ag
snow, the lower one has particles expelled up like a fountain.
\qml
+import Qt 4.6
+import Qt.labs.particles 1.0
+
Rectangle {
width: 240
height: 320
diff --git a/src/imports/webkit/qdeclarativewebview.cpp b/src/imports/webkit/qdeclarativewebview.cpp
index 0b85ae4..be3fca2 100644
--- a/src/imports/webkit/qdeclarativewebview.cpp
+++ b/src/imports/webkit/qdeclarativewebview.cpp
@@ -121,6 +121,10 @@ public:
A WebView renders web content based on a URL.
+ This type is made available by importing the \c org.webkit module:
+
+ \b{import org.webkit 1.0}
+
If the width and height of the item is not set, they will
dynamically adjust to a size appropriate for the content.
This width may be large for typical online web pages.
diff --git a/src/imports/webkit/webkit.pro b/src/imports/webkit/webkit.pro
index ef08efe..7463a7f 100644
--- a/src/imports/webkit/webkit.pro
+++ b/src/imports/webkit/webkit.pro
@@ -11,7 +11,18 @@ HEADERS += qdeclarativewebview_p.h \
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
-qmldir.files += $$QT_BUILD_TREE/imports/$$TARGETPATH/qmldir
+qmldir.files += $$PWD/qmldir
qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+symbian:{
+ load(data_caging_paths)
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+
+ importFiles.sources = webkitqmlplugin.dll \
+ qmldir
+ importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH
+
+ DEPLOYMENT = importFiles
+}
+
INSTALLS += target qmldir
diff --git a/src/imports/widgets/widgets.pro b/src/imports/widgets/widgets.pro
index aa09b3c..cccd8b4 100644
--- a/src/imports/widgets/widgets.pro
+++ b/src/imports/widgets/widgets.pro
@@ -15,7 +15,18 @@ HEADERS += \
QTDIR_build:DESTDIR = $$QT_BUILD_TREE/imports/$$TARGETPATH
target.path = $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
-qmldir.files += $$QT_BUILD_TREE/imports/$$TARGETPATH/qmldir
+qmldir.files += $$PWD/qmldir
qmldir.path += $$[QT_INSTALL_IMPORTS]/$$TARGETPATH
+symbian:{
+ load(data_caging_paths)
+ include($$QT_SOURCE_TREE/demos/symbianpkgrules.pri)
+
+ importFiles.sources = widgets.dll \
+ qmldir
+ importFiles.path = $$QT_IMPORTS_BASE_DIR/$$TARGETPATH
+
+ DEPLOYMENT = importFiles
+}
+
INSTALLS += target qmldir
diff --git a/src/multimedia/audio/qaudioinput_mac_p.cpp b/src/multimedia/audio/qaudioinput_mac_p.cpp
index 4b37b18..cb65f6e 100644
--- a/src/multimedia/audio/qaudioinput_mac_p.cpp
+++ b/src/multimedia/audio/qaudioinput_mac_p.cpp
@@ -670,8 +670,8 @@ bool QAudioInputPrivate::open()
}
// Allocate buffer
- periodSizeBytes = (numberOfFrames * streamFormat.mSampleRate / deviceFormat.mSampleRate) *
- streamFormat.mBytesPerFrame;
+ periodSizeBytes = numberOfFrames * streamFormat.mBytesPerFrame;
+
if (internalBufferSize < periodSizeBytes * 2)
internalBufferSize = periodSizeBytes * 2;
else
diff --git a/src/multimedia/audio/qaudiooutput_symbian_p.cpp b/src/multimedia/audio/qaudiooutput_symbian_p.cpp
index 945a08d..3f8e933 100644
--- a/src/multimedia/audio/qaudiooutput_symbian_p.cpp
+++ b/src/multimedia/audio/qaudiooutput_symbian_p.cpp
@@ -185,10 +185,11 @@ void QAudioOutputPrivate::suspend()
const qint64 samplesWritten = SymbianAudio::Utils::bytesToSamples(
m_format, m_bytesWritten);
- m_bytesWritten = 0;
const qint64 samplesPlayed = getSamplesPlayed();
+ m_bytesWritten = 0;
+
// CMMFDevSound::Pause() is not guaranteed to work correctly in all
// implementations, for play-mode DevSound sessions. We therefore
// have to implement suspend() by calling CMMFDevSound::Stop().
diff --git a/src/multimedia/base/base.pri b/src/multimedia/base/base.pri
index 5aebbf0..49eca49 100644
--- a/src/multimedia/base/base.pri
+++ b/src/multimedia/base/base.pri
@@ -60,4 +60,10 @@ SOURCES += \
$$PWD/qpaintervideosurface.cpp \
$$PWD/qmediatimerange.cpp
-
+mac {
+ HEADERS += $$PWD/qpaintervideosurface_mac_p.h
+ OBJECTIVE_SOURCES += $$PWD/qpaintervideosurface_mac.mm
+
+ LIBS += -framework AppKit -framework QuartzCore -framework QTKit
+
+}
diff --git a/src/multimedia/base/qpaintervideosurface.cpp b/src/multimedia/base/qpaintervideosurface.cpp
index 695dc73..b8028d8f 100644
--- a/src/multimedia/base/qpaintervideosurface.cpp
+++ b/src/multimedia/base/qpaintervideosurface.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qpaintervideosurface_p.h"
+#include "qpaintervideosurface_mac_p.h"
#include <qmath.h>
@@ -56,28 +57,6 @@
QT_BEGIN_NAMESPACE
-class QVideoSurfacePainter
-{
-public:
- virtual ~QVideoSurfacePainter();
-
- virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(
- QAbstractVideoBuffer::HandleType handleType) const = 0;
-
- virtual bool isFormatSupported(
- const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const = 0;
-
- virtual QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) = 0;
- virtual void stop() = 0;
-
- virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0;
-
- virtual QAbstractVideoSurface::Error paint(
- const QRectF &target, QPainter *painter, const QRectF &source) = 0;
-
- virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0;
-};
-
QVideoSurfacePainter::~QVideoSurfacePainter()
{
}
@@ -1544,6 +1523,14 @@ void QPainterVideoSurface::createPainter()
{
Q_ASSERT(!m_painter);
+#ifdef Q_WS_MAC
+ if (m_glContext)
+ m_glContext->makeCurrent();
+
+ m_painter = new QVideoSurfaceCoreGraphicsPainter(m_glContext != 0);
+ return;
+#endif
+
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
switch (m_shaderType) {
#ifndef QT_OPENGL_ES
diff --git a/src/multimedia/base/qpaintervideosurface_mac.mm b/src/multimedia/base/qpaintervideosurface_mac.mm
new file mode 100644
index 0000000..ee03990
--- /dev/null
+++ b/src/multimedia/base/qpaintervideosurface_mac.mm
@@ -0,0 +1,274 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qpaintervideosurface_mac_p.h"
+
+#include <QtCore/qdatetime.h>
+
+#include <qmath.h>
+
+#include <qpainter.h>
+#include <qvariant.h>
+#include <QtMultimedia/qvideosurfaceformat.h>
+
+#include <QtDebug>
+
+#include <QuartzCore/CIContext.h>
+#include <CGLCurrent.h>
+
+QT_BEGIN_NAMESPACE
+
+extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev); //qpaintdevice_mac.cpp
+
+QVideoSurfaceCoreGraphicsPainter::QVideoSurfaceCoreGraphicsPainter(bool glSupported)
+ : ciContext(0)
+ , m_imageFormat(QImage::Format_Invalid)
+ , m_scanLineDirection(QVideoSurfaceFormat::TopToBottom)
+{
+ //qDebug() << "QVideoSurfaceCoreGraphicsPainter, GL supported:" << glSupported;
+ ciContext = 0;
+ m_imagePixelFormats
+ << QVideoFrame::Format_RGB32;
+
+ m_supportedHandles
+ << QAbstractVideoBuffer::NoHandle
+ << QAbstractVideoBuffer::CoreImageHandle;
+
+ if (glSupported)
+ m_supportedHandles << QAbstractVideoBuffer::GLTextureHandle;
+}
+
+QVideoSurfaceCoreGraphicsPainter::~QVideoSurfaceCoreGraphicsPainter()
+{
+ [(CIContext*)ciContext release];
+}
+
+QList<QVideoFrame::PixelFormat> QVideoSurfaceCoreGraphicsPainter::supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const
+{
+ return m_supportedHandles.contains(handleType)
+ ? m_imagePixelFormats
+ : QList<QVideoFrame::PixelFormat>();
+}
+
+bool QVideoSurfaceCoreGraphicsPainter::isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *) const
+{
+ return m_supportedHandles.contains(format.handleType())
+ && m_imagePixelFormats.contains(format.pixelFormat())
+ && !format.frameSize().isEmpty();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::start(const QVideoSurfaceFormat &format)
+{
+ m_frame = QVideoFrame();
+ m_imageFormat = QVideoFrame::imageFormatFromPixelFormat(format.pixelFormat());
+ m_imageSize = format.frameSize();
+ m_scanLineDirection = format.scanLineDirection();
+
+ return m_supportedHandles.contains(format.handleType())
+ && m_imageFormat != QImage::Format_Invalid
+ && !m_imageSize.isEmpty()
+ ? QAbstractVideoSurface::NoError
+ : QAbstractVideoSurface::UnsupportedFormatError;
+}
+
+void QVideoSurfaceCoreGraphicsPainter::stop()
+{
+ m_frame = QVideoFrame();
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::setCurrentFrame(const QVideoFrame &frame)
+{
+ m_frame = frame;
+
+ return QAbstractVideoSurface::NoError;
+}
+
+QAbstractVideoSurface::Error QVideoSurfaceCoreGraphicsPainter::paint(
+ const QRectF &target, QPainter *painter, const QRectF &source)
+{
+ if (m_frame.handleType() == QAbstractVideoBuffer::CoreImageHandle) {
+ if (painter->paintEngine()->type() == QPaintEngine::CoreGraphics ) {
+
+ CIImage *img = (CIImage*)(m_frame.handle().value<void*>());
+
+ if (img) {
+ CGContextRef cgContext = qt_mac_cg_context(painter->device());
+
+ if (cgContext) {
+ painter->beginNativePainting();
+
+ CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height());
+ CGRect dRect = CGRectMake(target.x(), target.y(), target.width(), target.height());
+
+ NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::TopToBottom) {
+ CGContextSaveGState( cgContext );
+ CGContextTranslateCTM(cgContext, 0, dRect.origin.y + CGRectGetMaxY(dRect));
+ CGContextScaleCTM(cgContext, 1, -1);
+
+ CGContextDrawImage(cgContext, dRect, [bitmap CGImage]);
+
+ CGContextRestoreGState(cgContext);
+ } else {
+ CGContextDrawImage(cgContext, dRect, [bitmap CGImage]);
+ }
+
+ [bitmap release];
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+ }
+ } else if (painter->paintEngine()->type() == QPaintEngine::OpenGL2 ||
+ painter->paintEngine()->type() == QPaintEngine::OpenGL) {
+ CIImage *img = (CIImage*)(m_frame.handle().value<void*>());
+
+ if (img) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+
+ if (cglContext) {
+
+ if (!ciContext) {
+ CGLContextObj cglContext = CGLGetCurrentContext();
+ NSOpenGLPixelFormat *nsglPixelFormat = [NSOpenGLView defaultPixelFormat];
+ CGLPixelFormatObj cglPixelFormat = static_cast<CGLPixelFormatObj>([nsglPixelFormat CGLPixelFormatObj]);
+
+ ciContext = [CIContext contextWithCGLContext:cglContext
+ pixelFormat:cglPixelFormat
+ options:nil];
+
+ [(CIContext*)ciContext retain];
+ }
+
+ CGRect sRect = CGRectMake(source.x(), source.y(), source.width(), source.height());
+ CGRect dRect = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom ?
+ CGRectMake(target.x(), target.y()+target.height(), target.width(), -target.height()) :
+ CGRectMake(target.x(), target.y(), target.width(), target.height());
+
+
+ painter->beginNativePainting();
+
+ [(CIContext*)ciContext drawImage:img inRect:dRect fromRect:sRect];
+
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+ }
+ }
+ }
+
+ if (m_frame.handleType() == QAbstractVideoBuffer::GLTextureHandle &&
+ (painter->paintEngine()->type() == QPaintEngine::OpenGL2 ||
+ painter->paintEngine()->type() == QPaintEngine::OpenGL)) {
+
+ painter->beginNativePainting();
+ GLuint texture = m_frame.handle().toUInt();
+
+ glDisable(GL_CULL_FACE);
+ glEnable(GL_TEXTURE_2D);
+
+ glBindTexture(GL_TEXTURE_2D, texture);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+ const float txLeft = source.left() / m_frame.width();
+ const float txRight = source.right() / m_frame.width();
+ const float txTop = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.top() / m_frame.height()
+ : source.bottom() / m_frame.height();
+ const float txBottom = m_scanLineDirection == QVideoSurfaceFormat::TopToBottom
+ ? source.bottom() / m_frame.height()
+ : source.top() / m_frame.height();
+
+ glBegin(GL_QUADS);
+ QRectF rect = target;
+ glTexCoord2f(txLeft, txBottom);
+ glVertex2f(rect.topLeft().x(), rect.topLeft().y());
+ glTexCoord2f(txRight, txBottom);
+ glVertex2f(rect.topRight().x() + 1, rect.topRight().y());
+ glTexCoord2f(txRight, txTop);
+ glVertex2f(rect.bottomRight().x() + 1, rect.bottomRight().y() + 1);
+ glTexCoord2f(txLeft, txTop);
+ glVertex2f(rect.bottomLeft().x(), rect.bottomLeft().y() + 1);
+ glEnd();
+ painter->endNativePainting();
+
+ return QAbstractVideoSurface::NoError;
+ }
+
+ //fallback case, software rendering
+ if (m_frame.map(QAbstractVideoBuffer::ReadOnly)) {
+ QImage image(
+ m_frame.bits(),
+ m_imageSize.width(),
+ m_imageSize.height(),
+ m_frame.bytesPerLine(),
+ m_imageFormat);
+
+ if (m_scanLineDirection == QVideoSurfaceFormat::BottomToTop) {
+ const QTransform oldTransform = painter->transform();
+
+ painter->scale(1, -1);
+ painter->translate(0, -target.bottom());
+ painter->drawImage(
+ QRectF(target.x(), 0, target.width(), target.height()), image, source);
+ painter->setTransform(oldTransform);
+ } else {
+ painter->drawImage(target, image, source);
+ }
+
+ m_frame.unmap();
+ } else {
+ painter->fillRect(target, Qt::black);
+ }
+ return QAbstractVideoSurface::NoError;
+}
+
+void QVideoSurfaceCoreGraphicsPainter::updateColors(int, int, int, int)
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/multimedia/base/qpaintervideosurface_mac_p.h b/src/multimedia/base/qpaintervideosurface_mac_p.h
new file mode 100644
index 0000000..64442ed
--- /dev/null
+++ b/src/multimedia/base/qpaintervideosurface_mac_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtMultimedia module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPAINTERVIDEOSURFACE_MAC_P_H
+#define QPAINTERVIDEOSURFACE_MAC_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 "qpaintervideosurface_p.h"
+#include <QtMultimedia/qvideosurfaceformat.h>
+#include <QtMultimedia/qvideoframe.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QVideoSurfaceCoreGraphicsPainter : public QVideoSurfacePainter
+{
+public:
+ QVideoSurfaceCoreGraphicsPainter(bool glSupported);
+ ~QVideoSurfaceCoreGraphicsPainter();
+
+ QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const;
+
+ bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
+
+ QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format);
+ void stop();
+
+ QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame);
+
+ QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source);
+
+ void updateColors(int brightness, int contrast, int hue, int saturation);
+
+private:
+ void* ciContext;
+ QList<QVideoFrame::PixelFormat> m_imagePixelFormats;
+ QVideoFrame m_frame;
+ QSize m_imageSize;
+ QImage::Format m_imageFormat;
+ QVector<QAbstractVideoBuffer::HandleType> m_supportedHandles;
+ QVideoSurfaceFormat::Direction m_scanLineDirection;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/multimedia/base/qpaintervideosurface_p.h b/src/multimedia/base/qpaintervideosurface_p.h
index d4b6740..caba3ba 100644
--- a/src/multimedia/base/qpaintervideosurface_p.h
+++ b/src/multimedia/base/qpaintervideosurface_p.h
@@ -67,8 +67,28 @@ QT_BEGIN_NAMESPACE
class QGLContext;
+class QVideoSurfacePainter
+{
+public:
+ virtual ~QVideoSurfacePainter();
+
+ virtual QList<QVideoFrame::PixelFormat> supportedPixelFormats(
+ QAbstractVideoBuffer::HandleType handleType) const = 0;
+
+ virtual bool isFormatSupported(
+ const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const = 0;
+
+ virtual QAbstractVideoSurface::Error start(const QVideoSurfaceFormat &format) = 0;
+ virtual void stop() = 0;
+
+ virtual QAbstractVideoSurface::Error setCurrentFrame(const QVideoFrame &frame) = 0;
+
+ virtual QAbstractVideoSurface::Error paint(
+ const QRectF &target, QPainter *painter, const QRectF &source) = 0;
+
+ virtual void updateColors(int brightness, int contrast, int hue, int saturation) = 0;
+};
-class QVideoSurfacePainter;
class Q_MULTIMEDIA_EXPORT QPainterVideoSurface : public QAbstractVideoSurface
{
Q_OBJECT
diff --git a/src/multimedia/base/qvideowidget.cpp b/src/multimedia/base/qvideowidget.cpp
index 3820af9..b791abd 100644
--- a/src/multimedia/base/qvideowidget.cpp
+++ b/src/multimedia/base/qvideowidget.cpp
@@ -218,13 +218,23 @@ void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event)
{
QPainter painter(m_widget);
+ if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QRegion borderRegion = event->region();
+ borderRegion = borderRegion.subtracted(m_boundingRect);
+
+ QBrush brush = m_widget->palette().window();
+
+ QVector<QRect> rects = borderRegion.rects();
+ for (QVector<QRect>::iterator it = rects.begin(), end = rects.end(); it != end; ++it) {
+ painter.fillRect(*it, brush);
+ }
+ }
+
if (m_surface->isActive() && m_boundingRect.intersects(event->rect())) {
m_surface->paint(&painter, m_boundingRect, m_sourceRect);
m_surface->setReady(true);
} else {
- painter.fillRect(event->rect(), m_widget->palette().background());
-
#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_1_CL) && !defined(QT_OPENGL_ES_1)
if (m_updatePaintDevice && (painter.paintEngine()->type() == QPaintEngine::OpenGL
|| painter.paintEngine()->type() == QPaintEngine::OpenGL2)) {
@@ -239,6 +249,7 @@ void QRendererVideoWidgetBackend::paintEvent(QPaintEvent *event)
}
#endif
}
+
}
void QRendererVideoWidgetBackend::formatChanged(const QVideoSurfaceFormat &format)
@@ -248,6 +259,7 @@ void QRendererVideoWidgetBackend::formatChanged(const QVideoSurfaceFormat &forma
updateRects();
m_widget->updateGeometry();
+ m_widget->update();
}
void QRendererVideoWidgetBackend::frameChanged()
@@ -364,6 +376,12 @@ void QWindowVideoWidgetBackend::resizeEvent(QResizeEvent *)
void QWindowVideoWidgetBackend::paintEvent(QPaintEvent *event)
{
+ if (m_widget->testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QPainter painter(m_widget);
+
+ painter.fillRect(event->rect(), m_widget->palette().window());
+ }
+
m_windowControl->repaint();
event->accept();
@@ -504,6 +522,7 @@ void QVideoWidgetPrivate::_q_fullScreenChanged(bool fullScreen)
void QVideoWidgetPrivate::_q_dimensionsChanged()
{
q_func()->updateGeometry();
+ q_func()->update();
}
/*!
@@ -545,10 +564,6 @@ QVideoWidget::QVideoWidget(QWidget *parent)
, d_ptr(new QVideoWidgetPrivate)
{
d_ptr->q_ptr = this;
-
- QPalette palette = QWidget::palette();
- palette.setColor(QPalette::Background, Qt::black);
- setPalette(palette);
}
/*!
@@ -913,8 +928,13 @@ void QVideoWidget::paintEvent(QPaintEvent *event)
{
Q_D(QVideoWidget);
- if (d->currentBackend)
+ if (d->currentBackend) {
d->currentBackend->paintEvent(event);
+ } else if (testAttribute(Qt::WA_OpaquePaintEvent)) {
+ QPainter painter(this);
+
+ painter.fillRect(event->rect(), palette().window());
+ }
}
#include "moc_qvideowidget.cpp"
diff --git a/src/multimedia/effects/effects.pri b/src/multimedia/effects/effects.pri
index be2b696..6307255 100644
--- a/src/multimedia/effects/effects.pri
+++ b/src/multimedia/effects/effects.pri
@@ -5,7 +5,8 @@ unix:!mac {
DEFINES += QT_MULTIMEDIA_PULSEAUDIO
HEADERS += $$PWD/qsoundeffect_pulse_p.h
SOURCES += $$PWD/qsoundeffect_pulse_p.cpp
- LIBS += -lpulse
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_PULSEAUDIO
+ LIBS += $$QT_LIBS_PULSEAUDIO
} else {
DEFINES += QT_MULTIMEDIA_QMEDIAPLAYER
HEADERS += $$PWD/qsoundeffect_qmedia_p.h
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 1d8224c..bc7684a 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -58,6 +58,28 @@ QT_BEGIN_NAMESPACE
// TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp
+QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
+ : socket(0)
+ , state(IdleState)
+ , reply(0)
+ , written(0)
+ , bytesTotal(0)
+ , resendCurrent(false)
+ , lastStatus(0)
+ , pendingEncrypt(false)
+ , reconnectAttempts(2)
+ , authMehtod(QAuthenticatorPrivate::None)
+ , proxyAuthMehtod(QAuthenticatorPrivate::None)
+#ifndef QT_NO_OPENSSL
+ , ignoreAllSslErrors(false)
+#endif
+ , pipeliningSupported(PipeliningSupportUnknown)
+ , connection(0)
+{
+ // Inlining this function in the header leads to compiler error on
+ // release-armv5, on at least timebox 9.2 and 10.1.
+}
+
void QHttpNetworkConnectionChannel::init()
{
#ifndef QT_NO_OPENSSL
@@ -865,7 +887,14 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
void QHttpNetworkConnectionChannel::_q_connected()
{
// improve performance since we get the request sent by the kernel ASAP
- socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
+ //socket->setSocketOption(QAbstractSocket::LowDelayOption, 1);
+ // We have this commented out now. It did not have the effect we wanted. If we want to
+ // do this properly, Qt has to combine multiple HTTP requests into one buffer
+ // and send this to the kernel in one syscall and then the kernel immediately sends
+ // it as one TCP packet because of TCP_NODELAY.
+ // However, this code is currently not in Qt, so we rely on the kernel combining
+ // the requests into one TCP packet.
+
// not sure yet if it helps, but it makes sense
socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
@@ -932,7 +961,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
errorCode = QNetworkReply::UnknownNetworkError;
break;
}
- QPointer<QObject> that = connection;
+ QPointer<QHttpNetworkConnection> that = connection;
QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString());
if (send2Reply) {
if (reply) {
@@ -987,8 +1016,16 @@ void QHttpNetworkConnectionChannel::_q_encryptedBytesWritten(qint64 bytes)
sendRequest();
// otherwise we do nothing
}
+
#endif
+void QHttpNetworkConnectionChannel::setConnection(QHttpNetworkConnection *c)
+{
+ // Inlining this function in the header leads to compiler error on
+ // release-armv5, on at least timebox 9.2 and 10.1.
+ connection = c;
+}
+
QT_END_NAMESPACE
#include "moc_qhttpnetworkconnectionchannel_p.cpp"
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 5032d2b..51cb5e8 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -65,6 +65,7 @@
#include <private/qhttpnetworkrequest_p.h>
#include <private/qhttpnetworkreply_p.h>
+#include "qhttpnetworkconnection_p.h"
#ifndef QT_NO_HTTP
@@ -80,7 +81,6 @@ QT_BEGIN_NAMESPACE
class QHttpNetworkRequest;
class QHttpNetworkReply;
class QByteArray;
-class QHttpNetworkConnection;
#ifndef HttpMessagePair
typedef QPair<QHttpNetworkRequest, QHttpNetworkReply*> HttpMessagePair;
@@ -127,18 +127,10 @@ public:
QList<HttpMessagePair> alreadyPipelinedRequests;
- QHttpNetworkConnectionChannel() : socket(0), state(IdleState), reply(0), written(0), bytesTotal(0), resendCurrent(false),
- lastStatus(0), pendingEncrypt(false), reconnectAttempts(2),
- authMehtod(QAuthenticatorPrivate::None), proxyAuthMehtod(QAuthenticatorPrivate::None)
-#ifndef QT_NO_OPENSSL
- , ignoreAllSslErrors(false)
-#endif
- , pipeliningSupported(PipeliningSupportUnknown)
- , connection(0)
- {}
-
- void setConnection(QHttpNetworkConnection *c) {connection = c;}
- QHttpNetworkConnection *connection;
+ QHttpNetworkConnectionChannel();
+
+ void setConnection(QHttpNetworkConnection *c);
+ QPointer<QHttpNetworkConnection> connection;
void init();
void close();
@@ -187,8 +179,6 @@ public:
#endif
};
-
-
QT_END_NAMESPACE
#endif // QT_NO_HTTP
diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp
index 3d0c32d..baf69e7 100644
--- a/src/network/kernel/qhostinfo.cpp
+++ b/src/network/kernel/qhostinfo.cpp
@@ -479,6 +479,7 @@ void QHostInfoRunnable::run()
QHostInfoLookupManager::QHostInfoLookupManager() : mutex(QMutex::Recursive), wasDeleted(false)
{
moveToThread(QCoreApplicationPrivate::mainThread());
+ connect(QCoreApplication::instance(), SIGNAL(destroyed()), SLOT(waitForThreadPoolDone()), Qt::DirectConnection);
threadPool.setMaxThreadCount(5); // do 5 DNS lookups in parallel
}
diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h
index 2b26b07..4fc74e9 100644
--- a/src/network/kernel/qhostinfo_p.h
+++ b/src/network/kernel/qhostinfo_p.h
@@ -184,6 +184,9 @@ protected:
QMutex mutex;
bool wasDeleted;
+
+private slots:
+ void waitForThreadPoolDone() { threadPool.waitForDone(); }
};
#endif
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 1169533..1f28b08 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -593,7 +593,7 @@ inline GLenum qt_gl_preferredTextureTarget()
}
// One resource per group of shared contexts.
-class Q_AUTOTEST_EXPORT QGLContextResource
+class Q_OPENGL_EXPORT QGLContextResource
{
public:
typedef void (*FreeFunc)(void *);
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index 4902cbd..b3b923d 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -537,7 +537,7 @@ void QVGPaintEnginePrivate::updateTransform(QPaintDevice *pdev)
// adds 0.5 to each co-ordinate.
QTransform viewport2(1.0f, 0.0f, 0.0f,
0.0f, -1.0f, 0.0f,
- 0.0f, devh, 1.0f);
+ 0.0f, devh + 1, 1.0f);
imageTransform = transform * viewport2;
// Calculate the scaling factor to use for turning cosmetic pens
diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp
index 7550446..5c4f41b 100644
--- a/src/openvg/qpixmapdata_vg.cpp
+++ b/src/openvg/qpixmapdata_vg.cpp
@@ -46,8 +46,10 @@
#include "qvg_p.h"
#include "qvgimagepool_p.h"
+#if defined(Q_OS_SYMBIAN)
#include <private/qt_s60_p.h>
#include <fbs.h>
+#endif
#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
#include <sgresource/sgimage.h>
typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR);
@@ -455,8 +457,8 @@ void QVGPixmapData::cleanup()
void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
{
-#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
if (type == QPixmapData::SgImage && pixmap) {
+#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap);
destroyImages();
@@ -487,7 +489,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
- if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
+ if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) {
cleanup();
driver.Close();
return;
@@ -525,6 +527,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
// release stuff
eglDestroyImageKHR(QEgl::display(), eglImage);
driver.Close();
+#endif
} else if (type == QPixmapData::FbsBitmap) {
CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap);
@@ -570,16 +573,12 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type)
if(deleteSourceBitmap)
delete bitmap;
}
-#else
- Q_UNUSED(pixmap);
- Q_UNUSED(type);
-#endif
}
void* QVGPixmapData::toNativeType(NativeType type)
{
-#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
if (type == QPixmapData::SgImage) {
+#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL)
toVGImage();
if (!isValid() || vgImage == VG_INVALID_HANDLE)
@@ -606,7 +605,7 @@ void* QVGPixmapData::toNativeType(NativeType type)
pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR");
- if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) {
+ if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) {
driver.Close();
return 0;
}
@@ -644,6 +643,7 @@ void* QVGPixmapData::toNativeType(NativeType type)
eglDestroyImageKHR(QEgl::display(), eglImage);
driver.Close();
return reinterpret_cast<void*>(sgImage);
+#endif
} else if (type == QPixmapData::FbsBitmap) {
CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap);
@@ -665,10 +665,7 @@ void* QVGPixmapData::toNativeType(NativeType type)
return reinterpret_cast<void*>(bitmap);
}
-#else
- Q_UNUSED(type);
return 0;
-#endif
}
#endif //Q_OS_SYMBIAN
diff --git a/src/phonon/phonon.pro b/src/phonon/phonon.pro
index 0469839..7f79d0b 100644
--- a/src/phonon/phonon.pro
+++ b/src/phonon/phonon.pro
@@ -2,8 +2,8 @@ TARGET = phonon
include(../qbase.pri)
PHONON_MAJOR_VERSION = $${QT_MAJOR_VERSION}
-PHONON_MINOR_VERSION = 3
-PHONON_PATCH_VERSION = 1
+PHONON_MINOR_VERSION = 4
+PHONON_PATCH_VERSION = 0
VERSION = $${PHONON_MAJOR_VERSION}.$${PHONON_MINOR_VERSION}.$${PHONON_PATCH_VERSION}
DEPENDPATH += .
@@ -21,6 +21,9 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \
$$PHONON_DIR/abstractvideooutput.h \
$$PHONON_DIR/abstractvideooutput_p.h \
$$PHONON_DIR/addoninterface.h \
+ $$PHONON_DIR/audiodataoutput_p.h \
+ $$PHONON_DIR/audiodataoutput.h \
+ $$PHONON_DIR/audiodataoutputinterface.h \
$$PHONON_DIR/audiooutput.h \
$$PHONON_DIR/audiooutput_p.h \
$$PHONON_DIR/audiooutputinterface.h \
@@ -36,6 +39,7 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \
$$PHONON_DIR/effectwidget_p.h \
$$PHONON_DIR/factory_p.h \
$$PHONON_DIR/frontendinterface_p.h \
+ $$PHONON_DIR/globalconfig.h \
$$PHONON_DIR/globalconfig_p.h \
$$PHONON_DIR/iodevicestream_p.h \
$$PHONON_DIR/mediacontroller.h \
@@ -53,6 +57,7 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \
$$PHONON_DIR/objectdescriptionmodel_p.h \
$$PHONON_DIR/path.h \
$$PHONON_DIR/path_p.h \
+ $$PHONON_DIR/pulsesupport.h \
$$PHONON_DIR/phonondefs.h \
$$PHONON_DIR/phonondefs_p.h \
$$PHONON_DIR/phononnamespace.h \
@@ -64,6 +69,7 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \
$$PHONON_DIR/seekslider_p.h \
$$PHONON_DIR/streaminterface.h \
$$PHONON_DIR/streaminterface_p.h \
+ $$PHONON_DIR/swiftslider_p.h \
$$PHONON_DIR/videoplayer.h \
$$PHONON_DIR/videowidget.h \
$$PHONON_DIR/videowidget_p.h \
@@ -73,35 +79,39 @@ HEADERS += $$PHONON_DIR/abstractaudiooutput.h \
$$PHONON_DIR/volumefaderinterface.h \
$$PHONON_DIR/volumeslider.h \
$$PHONON_DIR/volumeslider_p.h
-SOURCES += $$PHONON_DIR/objectdescription.cpp \
- $$PHONON_DIR/objectdescriptionmodel.cpp \
- $$PHONON_DIR/phononnamespace.cpp \
- $$PHONON_DIR/mediasource.cpp \
- $$PHONON_DIR/abstractmediastream.cpp \
- $$PHONON_DIR/streaminterface.cpp \
- $$PHONON_DIR/mediaobject.cpp \
- $$PHONON_DIR/medianode.cpp \
- $$PHONON_DIR/path.cpp \
- $$PHONON_DIR/effectparameter.cpp \
- $$PHONON_DIR/effect.cpp \
- $$PHONON_DIR/volumefadereffect.cpp \
- $$PHONON_DIR/abstractaudiooutput.cpp \
+
+SOURCES += $$PHONON_DIR/abstractaudiooutput.cpp \
$$PHONON_DIR/abstractaudiooutput_p.cpp \
- $$PHONON_DIR/audiooutput.cpp \
- $$PHONON_DIR/audiooutputinterface.cpp \
+ $$PHONON_DIR/abstractmediastream.cpp \
$$PHONON_DIR/abstractvideooutput.cpp \
$$PHONON_DIR/abstractvideooutput_p.cpp \
+ $$PHONON_DIR/audiodataoutput.cpp \
+ $$PHONON_DIR/audiooutput.cpp \
+ $$PHONON_DIR/audiooutputinterface.cpp \
$$PHONON_DIR/backendcapabilities.cpp \
- $$PHONON_DIR/globalconfig.cpp \
+ $$PHONON_DIR/effect.cpp \
+ $$PHONON_DIR/effectparameter.cpp \
+ $$PHONON_DIR/effectwidget.cpp \
$$PHONON_DIR/factory.cpp \
- $$PHONON_DIR/platform.cpp \
+ $$PHONON_DIR/globalconfig.cpp \
+ $$PHONON_DIR/iodevicestream.cpp \
$$PHONON_DIR/mediacontroller.cpp \
- $$PHONON_DIR/videowidget.cpp \
- $$PHONON_DIR/videoplayer.cpp \
+ $$PHONON_DIR/medianode.cpp \
+ $$PHONON_DIR/mediaobject.cpp \
+ $$PHONON_DIR/mediasource.cpp \
+ $$PHONON_DIR/objectdescription.cpp \
+ $$PHONON_DIR/objectdescriptionmodel.cpp \
+ $$PHONON_DIR/path.cpp \
+ $$PHONON_DIR/phononnamespace.cpp \
+ $$PHONON_DIR/platform.cpp \
+ $$PHONON_DIR/pulsesupport.cpp \
$$PHONON_DIR/seekslider.cpp \
- $$PHONON_DIR/volumeslider.cpp \
- $$PHONON_DIR/effectwidget.cpp \
- $$PHONON_DIR/iodevicestream.cpp
+ $$PHONON_DIR/streaminterface.cpp \
+ $$PHONON_DIR/swiftslider.cpp \
+ $$PHONON_DIR/videoplayer.cpp \
+ $$PHONON_DIR/videowidget.cpp \
+ $$PHONON_DIR/volumefadereffect.cpp \
+ $$PHONON_DIR/volumeslider.cpp
contains(QT_CONFIG, dbus) {
QT += dbus
@@ -114,6 +124,12 @@ contains(QT_CONFIG, dbus) {
contains(QT_CONFIG, reduce_exports): CONFIG += hide_symbols
+unix:!isEmpty(QT_CFLAGS_PULSEAUDIO) {
+ DEFINES += HAVE_PULSEAUDIO
+ QMAKE_CXXFLAGS += $$QT_CFLAGS_PULSEAUDIO
+ LIBS += $$QT_LIBS_PULSEAUDIO
+}
+
symbian: {
# Phonon depends on numeric_limits. Enabling STL support in Qt
# would bring in link dependencies, and we don't need that for
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index 4219f6f..80366d1 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -290,27 +290,22 @@ bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescripti
void QDirectFBPixmapData::fromImage(const QImage &img,
Qt::ImageConversionFlags flags)
{
- if (img.depth() == 1 || img.format() == QImage::Format_RGB32) {
- fromImage(img.convertToFormat(screen->alphaPixmapFormat()), flags);
- return;
- }
-
- if (img.hasAlphaChannel()
+ if (img.depth() == 1) {
+ alpha = true;
#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION
- && (flags & Qt::NoOpaqueDetection || QDirectFBPixmapData::hasAlphaChannel(img))
-#endif
- ) {
+ } else if (flags & Qt::NoOpaqueDetection || QDirectFBPixmapData::hasAlphaChannel(img)) {
alpha = true;
- imageFormat = screen->alphaPixmapFormat();
- } else {
- alpha = false;
- imageFormat = screen->pixelFormat();
+#else
+ } else if (img.hasAlphaChannel()) {
+ alpha = true;
+#endif
}
+ imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat();
QImage image;
- if (flags != Qt::AutoColor) {
+ if ((flags & ~Qt::NoOpaqueDetection) != Qt::AutoColor) {
image = img.convertToFormat(imageFormat, flags);
flags = Qt::AutoColor;
- } else if (img.format() == QImage::Format_RGB32) {
+ } else if (img.format() == QImage::Format_RGB32 || img.depth() == 1) {
image = img.convertToFormat(imageFormat, flags);
} else {
image = img;
diff --git a/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp b/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp
index e25dd99..1c6df2c 100644
--- a/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp
+++ b/src/plugins/mediaservices/directshow/mediaplayer/vmr9videowindowcontrol.cpp
@@ -61,6 +61,7 @@ Vmr9VideoWindowControl::Vmr9VideoWindowControl(QObject *parent)
if (IVMRFilterConfig9 *config = com_cast<IVMRFilterConfig9>(m_filter, IID_IVMRFilterConfig9)) {
config->SetRenderingMode(VMR9Mode_Windowless);
config->SetNumberOfStreams(1);
+ config->SetRenderingPrefs(RenderPrefs9_DoNotRenderBorder);
config->Release();
}
}
diff --git a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp
index 589d2b5..98068ac 100644
--- a/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp
+++ b/src/plugins/mediaservices/gstreamer/qgstreamerserviceplugin.cpp
@@ -52,9 +52,9 @@
#ifdef QMEDIA_GSTREAMER_CAPTURE
#include "qgstreamercaptureservice.h"
#endif
-
#include <QtMultimedia/qmediaserviceprovider.h>
+#ifdef QMEDIA_GSTREAMER_CAPTURE
#include <linux/types.h>
#include <sys/time.h>
#include <sys/ioctl.h>
@@ -66,6 +66,7 @@
#include <stdlib.h>
#include <sys/mman.h>
#include <linux/videodev2.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -109,18 +110,21 @@ void QGstreamerServicePlugin::release(QMediaService *service)
QList<QByteArray> QGstreamerServicePlugin::devices(const QByteArray &service) const
{
+#ifdef QMEDIA_GSTREAMER_CAPTURE
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
return m_cameraDevices;
}
+#endif
return QList<QByteArray>();
}
QString QGstreamerServicePlugin::deviceDescription(const QByteArray &service, const QByteArray &device)
{
+#ifdef QMEDIA_GSTREAMER_CAPTURE
if (service == Q_MEDIASERVICE_CAMERA) {
if (m_cameraDevices.isEmpty())
updateDevices();
@@ -129,12 +133,14 @@ QString QGstreamerServicePlugin::deviceDescription(const QByteArray &service, co
if (m_cameraDevices[i] == device)
return m_cameraDescriptions[i];
}
+#endif
return QString();
}
void QGstreamerServicePlugin::updateDevices() const
{
+#ifdef QMEDIA_GSTREAMER_CAPTURE
m_cameraDevices.clear();
m_cameraDescriptions.clear();
@@ -178,6 +184,7 @@ void QGstreamerServicePlugin::updateDevices() const
}
::close(fd);
}
+#endif
}
Q_EXPORT_PLUGIN2(gstengine, QGstreamerServicePlugin);
diff --git a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp
index 406cefe11..4ecf10b 100644
--- a/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp
+++ b/src/plugins/mediaservices/gstreamer/qgstreamervideoinputdevicecontrol.cpp
@@ -117,6 +117,7 @@ void QGstreamerVideoInputDeviceControl::update()
m_names.clear();
m_descriptions.clear();
+#ifdef QMEDIA_GSTREAMER_CAPTURE
QDir devDir("/dev");
devDir.setFilter(QDir::System);
@@ -157,6 +158,7 @@ void QGstreamerVideoInputDeviceControl::update()
}
::close(fd);
}
+#endif
}
QT_END_NAMESPACE
diff --git a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm
index d83c0e3..65c9f7d 100644
--- a/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm
+++ b/src/plugins/mediaservices/qt7/mediaplayer/qt7playersession.mm
@@ -128,25 +128,25 @@
- (void) processEOS:(NSNotification *)notification
{
Q_UNUSED(notification);
- m_session->processEOS();
+ QMetaObject::invokeMethod(m_session, "processEOS", Qt::AutoConnection);
}
- (void) processLoadStateChange:(NSNotification *)notification
{
Q_UNUSED(notification);
- m_session->processLoadStateChange();
+ QMetaObject::invokeMethod(m_session, "processLoadStateChange", Qt::AutoConnection);
}
- (void) processVolumeChange:(NSNotification *)notification
{
Q_UNUSED(notification);
- m_session->processVolumeChange();
+ QMetaObject::invokeMethod(m_session, "processVolumeChange", Qt::AutoConnection);
}
- (void) processNaturalSizeChange :(NSNotification *)notification
{
Q_UNUSED(notification);
- m_session->processNaturalSizeChange();
+ QMetaObject::invokeMethod(m_session, "processNaturalSizeChange", Qt::AutoConnection);
}
@end
@@ -193,17 +193,13 @@ void QT7PlayerSession::setVideoOutput(QT7VideoOutput *output)
if (m_videoOutput == output)
return;
- if (m_videoOutput) {
- m_videoOutput->setEnabled(false);
+ if (m_videoOutput)
m_videoOutput->setMovie(0);
- }
m_videoOutput = output;
- if (m_videoOutput) {
- m_videoOutput->setEnabled(m_QTMovie != 0);
+ if (m_videoOutput && m_state != QMediaPlayer::StoppedState)
m_videoOutput->setMovie(m_QTMovie);
- }
}
@@ -297,6 +293,9 @@ void QT7PlayerSession::setPosition(qint64 pos)
void QT7PlayerSession::play()
{
+ if (m_videoOutput)
+ m_videoOutput->setMovie(m_QTMovie);
+
float preferredRate = [[(QTMovie*)m_QTMovie attributeForKey:@"QTMoviePreferredRateAttribute"] floatValue];
[(QTMovie*)m_QTMovie setRate:preferredRate*m_rate];
@@ -306,6 +305,9 @@ void QT7PlayerSession::play()
void QT7PlayerSession::pause()
{
+ if (m_videoOutput)
+ m_videoOutput->setMovie(m_QTMovie);
+
m_state = QMediaPlayer::PausedState;
[(QTMovie*)m_QTMovie setRate:0];
@@ -320,6 +322,9 @@ void QT7PlayerSession::stop()
[(QTMovie*)m_QTMovie setRate:0];
setPosition(0);
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
if (m_state == QMediaPlayer::StoppedState)
emit stateChanged(m_state);
}
@@ -361,10 +366,8 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream)
if (m_QTMovie) {
[(QTMovieObserver*)m_movieObserver setMovie:nil];
- if (m_videoOutput) {
- m_videoOutput->setEnabled(false);
+ if (m_videoOutput)
m_videoOutput->setMovie(0);
- }
[(QTMovie*)m_QTMovie release];
m_QTMovie = 0;
@@ -425,10 +428,9 @@ void QT7PlayerSession::setMedia(const QMediaContent &content, QIODevice *stream)
} else {
[(QTMovieObserver*)m_movieObserver setMovie:(QTMovie*)m_QTMovie];
- if (m_videoOutput) {
+ if (m_videoOutput && m_state != QMediaPlayer::StoppedState)
m_videoOutput->setMovie(m_QTMovie);
- m_videoOutput->setEnabled(true);
- }
+
processLoadStateChange();
[(QTMovie*)m_QTMovie setMuted:m_muted];
@@ -457,6 +459,8 @@ bool QT7PlayerSession::isVideoAvailable() const
void QT7PlayerSession::processEOS()
{
m_mediaStatus = QMediaPlayer::EndOfMedia;
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
emit stateChanged(m_state = QMediaPlayer::StoppedState);
emit mediaStatusChanged(m_mediaStatus);
}
@@ -493,6 +497,9 @@ void QT7PlayerSession::processLoadStateChange()
if (state == kMovieLoadStateError) {
newStatus = QMediaPlayer::InvalidMedia;
+ if (m_videoOutput)
+ m_videoOutput->setMovie(0);
+
emit error(QMediaPlayer::FormatError, tr("Failed to load media"));
emit stateChanged(m_state = QMediaPlayer::StoppedState);
}
diff --git a/src/plugins/mediaservices/qt7/qt7.pro b/src/plugins/mediaservices/qt7/qt7.pro
index 6624d13..8791d73 100644
--- a/src/plugins/mediaservices/qt7/qt7.pro
+++ b/src/plugins/mediaservices/qt7/qt7.pro
@@ -25,6 +25,7 @@ HEADERS += \
qt7movieviewrenderer.h \
qt7serviceplugin.h \
qt7movierenderer.h \
+ qt7ciimagevideobuffer.h \
qcvdisplaylink.h
OBJECTIVE_SOURCES += \
@@ -35,6 +36,7 @@ OBJECTIVE_SOURCES += \
qt7movieviewrenderer.mm \
qt7movierenderer.mm \
qt7videooutputcontrol.mm \
+ qt7ciimagevideobuffer.mm \
qcvdisplaylink.mm
include(mediaplayer/mediaplayer.pri)
diff --git a/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.h b/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.h
new file mode 100644
index 0000000..669724f
--- /dev/null
+++ b/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT7CIIMAGEVIDEOBUFFER_H
+#define QT7CIIMAGEVIDEOBUFFER_H
+
+#include "qt7backend.h"
+#import <QTKit/QTKit.h>
+
+#include <QtCore/qvariant.h>
+#include <QtMultimedia/qabstractvideobuffer.h>
+
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+class QT7CIImageVideoBuffer : public QAbstractVideoBuffer
+{
+public:
+ QT7CIImageVideoBuffer(CIImage *image);
+
+ virtual ~QT7CIImageVideoBuffer();
+
+ MapMode mapMode() const;
+ uchar *map(MapMode mode, int *numBytes, int *bytesPerLine);
+ void unmap();
+ QVariant handle() const;
+
+private:
+ CIImage *m_image;
+ NSBitmapImageRep *m_buffer;
+ MapMode m_mode;
+};
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm b/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm
new file mode 100644
index 0000000..3778b58
--- /dev/null
+++ b/src/plugins/mediaservices/qt7/qt7ciimagevideobuffer.mm
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qt7ciimagevideobuffer.h"
+
+QT7CIImageVideoBuffer::QT7CIImageVideoBuffer(CIImage *image)
+ : QAbstractVideoBuffer(CoreImageHandle)
+ , m_image(image)
+ , m_buffer(0)
+ , m_mode(NotMapped)
+{
+ [m_image retain];
+}
+
+QT7CIImageVideoBuffer::~QT7CIImageVideoBuffer()
+{
+ [m_image release];
+ [m_buffer release];
+}
+
+QAbstractVideoBuffer::MapMode QT7CIImageVideoBuffer::mapMode() const
+{
+ return m_mode;
+}
+
+uchar *QT7CIImageVideoBuffer::map(QAbstractVideoBuffer::MapMode mode, int *numBytes, int *bytesPerLine)
+{
+ if (mode == NotMapped || m_mode != NotMapped || !m_image)
+ return 0;
+
+ if (!m_buffer) {
+ //swap R and B channels
+ CIFilter *colorSwapFilter = [CIFilter filterWithName: @"CIColorMatrix" keysAndValues:
+ @"inputImage", m_image,
+ @"inputRVector", [CIVector vectorWithX: 0 Y: 0 Z: 1 W: 0],
+ @"inputGVector", [CIVector vectorWithX: 0 Y: 1 Z: 0 W: 0],
+ @"inputBVector", [CIVector vectorWithX: 1 Y: 0 Z: 0 W: 0],
+ @"inputAVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 1],
+ @"inputBiasVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 0],
+ nil];
+ CIImage *img = [colorSwapFilter valueForKey: @"outputImage"];
+
+ m_buffer = [[NSBitmapImageRep alloc] initWithCIImage:img];
+ }
+
+ if (numBytes)
+ *numBytes = [m_buffer bytesPerPlane];
+
+ if (bytesPerLine)
+ *bytesPerLine = [m_buffer bytesPerRow];
+
+ m_mode = mode;
+
+ return [m_buffer bitmapData];
+}
+
+void QT7CIImageVideoBuffer::unmap()
+{
+ m_mode = NotMapped;
+}
+
+QVariant QT7CIImageVideoBuffer::handle() const
+{
+ return QVariant::fromValue<void*>(m_image);
+}
+
diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.h b/src/plugins/mediaservices/qt7/qt7movierenderer.h
index a547329..c2dd177 100644
--- a/src/plugins/mediaservices/qt7/qt7movierenderer.h
+++ b/src/plugins/mediaservices/qt7/qt7movierenderer.h
@@ -74,7 +74,6 @@ public:
QT7MovieRenderer(QObject *parent = 0);
virtual ~QT7MovieRenderer();
- void setEnabled(bool);
void setMovie(void *movie);
void updateNaturalSize(const QSize &newSize);
diff --git a/src/plugins/mediaservices/qt7/qt7movierenderer.mm b/src/plugins/mediaservices/qt7/qt7movierenderer.mm
index 1c1f5e4..95f5d4c 100644
--- a/src/plugins/mediaservices/qt7/qt7movierenderer.mm
+++ b/src/plugins/mediaservices/qt7/qt7movierenderer.mm
@@ -46,6 +46,7 @@
#include "qt7playercontrol.h"
#include "qt7movierenderer.h"
#include "qt7playersession.h"
+#include "qt7ciimagevideobuffer.h"
#include "qcvdisplaylink.h"
#include <QtCore/qdebug.h>
#include <QtCore/qcoreapplication.h>
@@ -64,7 +65,7 @@ class CVGLTextureVideoBuffer : public QAbstractVideoBuffer
{
public:
CVGLTextureVideoBuffer(CVOpenGLTextureRef buffer)
- : QAbstractVideoBuffer(NoHandle)
+ : QAbstractVideoBuffer(GLTextureHandle)
, m_buffer(buffer)
, m_mode(NotMapped)
{
@@ -82,11 +83,6 @@ public:
return QVariant(int(id));
}
- HandleType handleType() const
- {
- return GLTextureHandle;
- }
-
MapMode mapMode() const { return m_mode; }
uchar *map(MapMode mode, int *numBytes, int *bytesPerLine)
@@ -372,10 +368,6 @@ void QT7MovieRenderer::setupVideoOutput()
}
-void QT7MovieRenderer::setEnabled(bool)
-{
-}
-
void QT7MovieRenderer::setMovie(void *movie)
{
// qDebug() << "QT7MovieRenderer::setMovie" << movie;
@@ -447,15 +439,14 @@ void QT7MovieRenderer::updateVideoFrame(const CVTimeStamp &ts)
OSStatus status = QTVisualContextCopyImageForTime(m_visualContext, NULL, &ts, &imageBuffer);
if (status == noErr && imageBuffer) {
- //qDebug() << "render video frame";
QAbstractVideoBuffer *buffer = 0;
if (m_usingGLContext) {
- buffer = new CVGLTextureVideoBuffer((CVOpenGLTextureRef)imageBuffer);
+ buffer = new QT7CIImageVideoBuffer([CIImage imageWithCVImageBuffer:imageBuffer]);
CVOpenGLTextureRelease((CVOpenGLTextureRef)imageBuffer);
- //qDebug() << "render GL video frame" << buffer->handle();
} else {
buffer = new CVPixelBufferVideoBuffer((CVPixelBufferRef)imageBuffer);
+ //buffer = new QT7CIImageVideoBuffer( [CIImage imageWithCVImageBuffer:imageBuffer] );
CVPixelBufferRelease((CVPixelBufferRef)imageBuffer);
}
diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.h b/src/plugins/mediaservices/qt7/qt7movievideowidget.h
index 7908efd..831a18d 100644
--- a/src/plugins/mediaservices/qt7/qt7movievideowidget.h
+++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.h
@@ -72,7 +72,6 @@ public:
QT7MovieVideoWidget(QObject *parent = 0);
virtual ~QT7MovieVideoWidget();
- void setEnabled(bool);
void setMovie(void *movie);
void updateNaturalSize(const QSize &newSize);
diff --git a/src/plugins/mediaservices/qt7/qt7movievideowidget.mm b/src/plugins/mediaservices/qt7/qt7movievideowidget.mm
index 197c26e..648d6b4 100644
--- a/src/plugins/mediaservices/qt7/qt7movievideowidget.mm
+++ b/src/plugins/mediaservices/qt7/qt7movievideowidget.mm
@@ -73,7 +73,8 @@ public:
void initializeGL()
{
- glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ QColor bgColor = palette().color(QPalette::Background);
+ glClearColor(bgColor.redF(), bgColor.greenF(), bgColor.blueF(), bgColor.alphaF());
}
void resizeGL(int w, int h)
@@ -279,10 +280,6 @@ void QT7MovieVideoWidget::setupVideoOutput()
m_displayLink->start();
}
-void QT7MovieVideoWidget::setEnabled(bool)
-{
-}
-
void QT7MovieVideoWidget::setMovie(void *movie)
{
if (m_movie == movie)
diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.h b/src/plugins/mediaservices/qt7/qt7movieviewoutput.h
index 49049ad..0fee41c 100644
--- a/src/plugins/mediaservices/qt7/qt7movieviewoutput.h
+++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.h
@@ -63,7 +63,6 @@ public:
QT7MovieViewOutput(QObject *parent = 0);
~QT7MovieViewOutput();
- void setEnabled(bool);
void setMovie(void *movie);
void updateNaturalSize(const QSize &newSize);
diff --git a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm
index 8e4dd9b..20f1a02 100644
--- a/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm
+++ b/src/plugins/mediaservices/qt7/qt7movieviewoutput.mm
@@ -194,10 +194,6 @@ void QT7MovieViewOutput::setupVideoOutput()
setDisplayRect(m_displayRect);
}
-void QT7MovieViewOutput::setEnabled(bool)
-{
-}
-
void QT7MovieViewOutput::setMovie(void *movie)
{
if (m_movie != movie) {
diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h
index 336006c..0b515ae 100644
--- a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h
+++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.h
@@ -67,7 +67,6 @@ public:
QT7MovieViewRenderer(QObject *parent = 0);
~QT7MovieViewRenderer();
- void setEnabled(bool);
void setMovie(void *movie);
void updateNaturalSize(const QSize &newSize);
@@ -87,6 +86,7 @@ private:
QSize m_nativeSize;
QAbstractVideoSurface *m_surface;
QVideoFrame m_currentFrame;
+ bool m_pendingRenderEvent;
QMutex m_mutex;
};
diff --git a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm
index 5047853..33a6970 100644
--- a/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm
+++ b/src/plugins/mediaservices/qt7/qt7movieviewrenderer.mm
@@ -46,6 +46,7 @@
#include "qt7playercontrol.h"
#include "qt7movieviewrenderer.h"
#include "qt7playersession.h"
+#include "qt7ciimagevideobuffer.h"
#include <QtCore/qdebug.h>
#include <QtCore/qcoreevent.h>
#include <QtCore/qcoreapplication.h>
@@ -113,6 +114,7 @@ QT_END_NAMESPACE
- (HiddenQTMovieView *) initWithRenderer:(QT7MovieViewRenderer *)renderer;
- (void) setRenderer:(QT7MovieViewRenderer *)renderer;
- (void) setDrawRect:(const QRect &)rect;
+- (CIImage *) view:(QTMovieView *)view willDisplayImage:(CIImage *)img;
@end
@implementation HiddenQTMovieView
@@ -163,33 +165,37 @@ QT_END_NAMESPACE
// before the image will be drawn.
Q_UNUSED(view);
if (m_renderer) {
- NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCIImage:img];
CGRect bounds = [img extent];
int w = bounds.size.width;
int h = bounds.size.height;
- // Swap red and blue (same as QImage::rgbSwapped, but without copy)
- uchar *data = [bitmap bitmapData];
- //qDebug() << data << w << h;
- int bytesPerLine = [bitmap bytesPerRow];
- for (int i=0; i<h; ++i) {
- quint32 *p = (quint32*)data;
- data += bytesPerLine;
- quint32 *end = p + w;
- while (p < end) {
- *p = ((*p << 16) & 0xff0000) | ((*p >> 16) & 0xff) | (*p & 0xff00ff00);
- p++;
- }
- }
+ QVideoFrame frame;
- QVideoFrame frame( new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 );
+ QAbstractVideoSurface *surface = m_renderer->surface();
+ if (!surface || !surface->isActive())
+ return img;
- //static int i=0;
- //i++;
- //QImage img([bitmap bitmapData], w, h, QImage::Format_RGB32);
- //img.save(QString("img%1.jpg").arg(i));
-
- [bitmap release];
+ if (surface->surfaceFormat().handleType() == QAbstractVideoBuffer::CoreImageHandle) {
+ //surface supports rendering of opengl based CIImage
+ frame = QVideoFrame(new QT7CIImageVideoBuffer(img), QSize(w,h), QVideoFrame::Format_RGB32 );
+ } else {
+ //Swap R and B colors
+ CIFilter *colorSwapFilter = [CIFilter filterWithName: @"CIColorMatrix" keysAndValues:
+ @"inputImage", img,
+ @"inputRVector", [CIVector vectorWithX: 0 Y: 0 Z: 1 W: 0],
+ @"inputGVector", [CIVector vectorWithX: 0 Y: 1 Z: 0 W: 0],
+ @"inputBVector", [CIVector vectorWithX: 1 Y: 0 Z: 0 W: 0],
+ @"inputAVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 1],
+ @"inputBiasVector", [CIVector vectorWithX: 0 Y: 0 Z: 0 W: 0],
+ nil];
+ CIImage *img = [colorSwapFilter valueForKey: @"outputImage"];
+ NSBitmapImageRep *bitmap =[[NSBitmapImageRep alloc] initWithCIImage:img];
+ //requesting the bitmap data is slow,
+ //but it's better to do it here to avoid blocking the main thread for a long.
+ [bitmap bitmapData];
+ frame = QVideoFrame(new NSBitmapVideoBuffer(bitmap), QSize(w,h), QVideoFrame::Format_RGB32 );
+ [bitmap release];
+ }
if (m_renderer)
m_renderer->renderFrame(frame);
@@ -230,7 +236,8 @@ QT7MovieViewRenderer::QT7MovieViewRenderer(QObject *parent)
:QT7VideoRendererControl(parent),
m_movie(0),
m_movieView(0),
- m_surface(0)
+ m_surface(0),
+ m_pendingRenderEvent(false)
{
}
@@ -267,11 +274,15 @@ void QT7MovieViewRenderer::setupVideoOutput()
}
[movieView setMovie:(QTMovie*)m_movie];
- //[movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)];
+ [movieView setDrawRect:QRect(QPoint(0,0), m_nativeSize)];
}
if (m_surface && !m_nativeSize.isEmpty()) {
- QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32);
+ bool coreImageFrameSupported = !m_surface->supportedPixelFormats(QAbstractVideoBuffer::CoreImageHandle).isEmpty() &&
+ !m_surface->supportedPixelFormats(QAbstractVideoBuffer::GLTextureHandle).isEmpty();
+
+ QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32,
+ coreImageFrameSupported ? QAbstractVideoBuffer::CoreImageHandle : QAbstractVideoBuffer::NoHandle);
if (m_surface->isActive() && m_surface->surfaceFormat() != format) {
// qDebug() << "Surface format was changed, stop the surface.";
@@ -279,18 +290,15 @@ void QT7MovieViewRenderer::setupVideoOutput()
}
if (!m_surface->isActive()) {
-// qDebug() << "Starting the surface with format" << format;
- m_surface->start(format);
-// if (!m_surface->start(format))
-// qDebug() << "failed to start video surface" << m_surface->error();
+ //qDebug() << "Starting the surface with format" << format;
+ if (!m_surface->start(format)) {
+ qWarning() << "Failed to start video surface" << m_surface->error();
+ qWarning() << "Surface format:" << format;
+ }
}
}
}
-void QT7MovieViewRenderer::setEnabled(bool)
-{
-}
-
void QT7MovieViewRenderer::setMovie(void *movie)
{
if (movie == m_movie)
@@ -330,18 +338,21 @@ void QT7MovieViewRenderer::setSurface(QAbstractVideoSurface *surface)
void QT7MovieViewRenderer::renderFrame(const QVideoFrame &frame)
{
- {
- QMutexLocker locker(&m_mutex);
- m_currentFrame = frame;
- }
- qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+ QMutexLocker locker(&m_mutex);
+ m_currentFrame = frame;
+
+ if (!m_pendingRenderEvent)
+ qApp->postEvent(this, new QEvent(QEvent::User), Qt::HighEventPriority);
+
+ m_pendingRenderEvent = true;
}
bool QT7MovieViewRenderer::event(QEvent *event)
{
if (event->type() == QEvent::User) {
QMutexLocker locker(&m_mutex);
+ m_pendingRenderEvent = false;
if (m_surface->isActive())
m_surface->present(m_currentFrame);
}
diff --git a/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h
index 2c60919..3c74cb8 100644
--- a/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h
+++ b/src/plugins/mediaservices/qt7/qt7videooutputcontrol.h
@@ -67,7 +67,6 @@ class QT7PlayerService;
class QT7VideoOutput {
public:
virtual ~QT7VideoOutput() {}
- virtual void setEnabled(bool enabled) = 0;
virtual void setMovie(void *movie) = 0;
virtual void updateNaturalSize(const QSize &newSize) = 0;
};
diff --git a/src/plugins/phonon/ds9/ds9.pro b/src/plugins/phonon/ds9/ds9.pro
index 301808e..f40c561 100644
--- a/src/plugins/phonon/ds9/ds9.pro
+++ b/src/plugins/phonon/ds9/ds9.pro
@@ -22,6 +22,7 @@ HEADERS += \
$$PHONON_DS9_DIR/mediaobject.h \
$$PHONON_DS9_DIR/videowidget.h \
$$PHONON_DS9_DIR/videorenderer_soft.h \
+ $$PHONON_DS9_DIR/videorenderer_vmr9.h \
$$PHONON_DS9_DIR/volumeeffect.h \
$$PHONON_DS9_DIR/qbasefilter.h \
$$PHONON_DS9_DIR/qpin.h \
@@ -44,6 +45,7 @@ SOURCES += \
$$PHONON_DS9_DIR/mediaobject.cpp \
$$PHONON_DS9_DIR/videowidget.cpp \
$$PHONON_DS9_DIR/videorenderer_soft.cpp \
+ $$PHONON_DS9_DIR/videorenderer_vmr9.cpp \
$$PHONON_DS9_DIR/volumeeffect.cpp \
$$PHONON_DS9_DIR/qbasefilter.cpp \
$$PHONON_DS9_DIR/qpin.cpp \
@@ -51,15 +53,6 @@ SOURCES += \
$$PHONON_DS9_DIR/qaudiocdreader.cpp \
$$PHONON_DS9_DIR/qmeminputpin.cpp
-#the EVR renderer (only available on desktop)
-!wince*:SOURCES += $$PHONON_DS9_DIR/videorenderer_evr.cpp \
- $$PHONON_DS9_DIR/videorenderer_vmr9.cpp
-!wince*:HEADERS += $$PHONON_DS9_DIR/qevr9.h \
- $$PHONON_DS9_DIR/videorenderer_evr.h \
- $$PHONON_DS9_DIR/videorenderer_vmr9.h
-wince*:SOURCES += $$PHONON_DS9_DIR/videorenderer_default.cpp
-wince*:HEADERS += $$PHONON_DS9_DIR/videorenderer_default.h
-
target.path = $$[QT_INSTALL_PLUGINS]/phonon_backend
INSTALLS += target
diff --git a/src/plugins/phonon/gstreamer/gstreamer.pro b/src/plugins/phonon/gstreamer/gstreamer.pro
index ae597fa..1013205 100644
--- a/src/plugins/phonon/gstreamer/gstreamer.pro
+++ b/src/plugins/phonon/gstreamer/gstreamer.pro
@@ -15,6 +15,7 @@ PHONON_GSTREAMER_DIR = $$QT_SOURCE_TREE/src/3rdparty/phonon/gstreamer
HEADERS += $$PHONON_GSTREAMER_DIR/common.h \
$$PHONON_GSTREAMER_DIR/audiooutput.h \
+ $$PHONON_GSTREAMER_DIR/audiodataoutput.h \
$$PHONON_GSTREAMER_DIR/artssink.h \
$$PHONON_GSTREAMER_DIR/abstractrenderer.h \
$$PHONON_GSTREAMER_DIR/backend.h \
@@ -35,26 +36,27 @@ HEADERS += $$PHONON_GSTREAMER_DIR/common.h \
$$PHONON_GSTREAMER_DIR/audioeffect.h \
$$PHONON_GSTREAMER_DIR/volumefadereffect.h
-SOURCES += $$PHONON_GSTREAMER_DIR/audiooutput.cpp \
- $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \
+SOURCES += $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \
$$PHONON_GSTREAMER_DIR/artssink.cpp \
+ $$PHONON_GSTREAMER_DIR/audioeffect.cpp \
+ $$PHONON_GSTREAMER_DIR/audiooutput.cpp \
+ $$PHONON_GSTREAMER_DIR/audiodataoutput.cpp \
$$PHONON_GSTREAMER_DIR/backend.cpp \
$$PHONON_GSTREAMER_DIR/devicemanager.cpp \
$$PHONON_GSTREAMER_DIR/effect.cpp \
$$PHONON_GSTREAMER_DIR/effectmanager.cpp \
+ $$PHONON_GSTREAMER_DIR/glrenderer.cpp \
$$PHONON_GSTREAMER_DIR/gsthelper.cpp \
- $$PHONON_GSTREAMER_DIR/mediaobject.cpp \
$$PHONON_GSTREAMER_DIR/medianode.cpp \
$$PHONON_GSTREAMER_DIR/medianodeevent.cpp \
- $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp \
- $$PHONON_GSTREAMER_DIR/videowidget.cpp \
- $$PHONON_GSTREAMER_DIR/glrenderer.cpp \
- $$PHONON_GSTREAMER_DIR/qwidgetvideosink.cpp \
+ $$PHONON_GSTREAMER_DIR/mediaobject.cpp \
+ $$PHONON_GSTREAMER_DIR/message.cpp \
$$PHONON_GSTREAMER_DIR/phononsrc.cpp \
+ $$PHONON_GSTREAMER_DIR/qwidgetvideosink.cpp \
$$PHONON_GSTREAMER_DIR/streamreader.cpp \
- $$PHONON_GSTREAMER_DIR/message.cpp \
- $$PHONON_GSTREAMER_DIR/audioeffect.cpp \
- $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp
+ $$PHONON_GSTREAMER_DIR/videowidget.cpp \
+ $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp \
+ $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp
!embedded {
HEADERS += $$PHONON_GSTREAMER_DIR/x11renderer.h
diff --git a/src/s60installs/bwins/QtGuiu.def b/src/s60installs/bwins/QtGuiu.def
index 2feaffd..6a4f07b 100644
--- a/src/s60installs/bwins/QtGuiu.def
+++ b/src/s60installs/bwins/QtGuiu.def
@@ -3961,7 +3961,7 @@ EXPORTS
?drawPixmap@QPainter@@QAEXHHABVQPixmap@@HHHH@Z @ 3960 NONAME ; void QPainter::drawPixmap(int, int, class QPixmap const &, int, int, int, int)
?drawPixmap@QPainter@@QAEXHHHHABVQPixmap@@@Z @ 3961 NONAME ; void QPainter::drawPixmap(int, int, int, int, class QPixmap const &)
?drawPixmap@QPainter@@QAEXHHHHABVQPixmap@@HHHH@Z @ 3962 NONAME ; void QPainter::drawPixmap(int, int, int, int, class QPixmap const &, int, int, int, int)
- ?drawPixmaps@QPaintEngineEx@@UAEXPBUData@QDrawPixmaps@@HABVQPixmap@@V?$QFlags@W4DrawingHint@QDrawPixmaps@@@@@Z @ 3963 NONAME ABSENT ; void QPaintEngineEx::drawPixmaps(struct QDrawPixmaps::Data const *, int, class QPixmap const &, class QFlags<enum QDrawPixmaps::DrawingHint>)
+ ?drawPixmaps@QPaintEngineEx@@UAEXPBUData@QDrawPixmaps@@HABVQPixmap@@V?$QFlags@W4DrawingHint@QDrawPixmaps@@@@@Z @ 3963 NONAME ; void QPaintEngineEx::drawPixmaps(struct QDrawPixmaps::Data const *, int, class QPixmap const &, class QFlags<enum QDrawPixmaps::DrawingHint>)
?drawPoint@QPainter@@QAEXABVQPoint@@@Z @ 3964 NONAME ; void QPainter::drawPoint(class QPoint const &)
?drawPoint@QPainter@@QAEXABVQPointF@@@Z @ 3965 NONAME ; void QPainter::drawPoint(class QPointF const &)
?drawPoint@QPainter@@QAEXHH@Z @ 3966 NONAME ; void QPainter::drawPoint(int, int)
@@ -7291,7 +7291,7 @@ EXPORTS
?polishEvent@QGraphicsWidget@@MAEXXZ @ 7290 NONAME ; void QGraphicsWidget::polishEvent(void)
?polygon@QGraphicsPolygonItem@@QBE?AVQPolygonF@@XZ @ 7291 NONAME ; class QPolygonF QGraphicsPolygonItem::polygon(void) const
?polygonFlags@QVectorPath@@SAIW4PolygonDrawMode@QPaintEngine@@@Z @ 7292 NONAME ; unsigned int QVectorPath::polygonFlags(enum QPaintEngine::PolygonDrawMode)
- ?populate@QTextureGlyphCache@@QAEXABVQTextItemInt@@ABV?$QVarLengthArray@I$0BAA@@@ABV?$QVarLengthArray@UQFixedPoint@@$0BAA@@@@Z @ 7293 NONAME ABSENT ; void QTextureGlyphCache::populate(class QTextItemInt const &, class QVarLengthArray<unsigned int, 256> const &, class QVarLengthArray<struct QFixedPoint, 256> const &)
+ ?populate@QTextureGlyphCache@@QAEXABVQTextItemInt@@ABV?$QVarLengthArray@I$0BAA@@@ABV?$QVarLengthArray@UQFixedPoint@@$0BAA@@@@Z @ 7293 NONAME ; void QTextureGlyphCache::populate(class QTextItemInt const &, class QVarLengthArray<unsigned int, 256> const &, class QVarLengthArray<struct QFixedPoint, 256> const &)
?popup@QCompleter@@QBEPAVQAbstractItemView@@XZ @ 7294 NONAME ; class QAbstractItemView * QCompleter::popup(void) const
?popup@QMenu@@QAEXABVQPoint@@PAVQAction@@@Z @ 7295 NONAME ; void QMenu::popup(class QPoint const &, class QAction *)
?popupMode@QToolButton@@QBE?AW4ToolButtonPopupMode@1@XZ @ 7296 NONAME ; enum QToolButton::ToolButtonPopupMode QToolButton::popupMode(void) const
@@ -7389,7 +7389,7 @@ EXPORTS
?qAlpha@@YAHI@Z @ 7388 NONAME ; int qAlpha(unsigned int)
?qBlue@@YAHI@Z @ 7389 NONAME ; int qBlue(unsigned int)
?qDrawBorderPixmap@@YAXPAVQPainter@@ABVQRect@@ABVQMargins@@ABVQPixmap@@12ABUQTileRules@@V?$QFlags@W4DrawingHint@QDrawBorderPixmap@@@@@Z @ 7390 NONAME ; void qDrawBorderPixmap(class QPainter *, class QRect const &, class QMargins const &, class QPixmap const &, class QRect const &, class QMargins const &, struct QTileRules const &, class QFlags<enum QDrawBorderPixmap::DrawingHint>)
- ?qDrawPixmaps@@YAXPAVQPainter@@PBUData@QDrawPixmaps@@HABVQPixmap@@V?$QFlags@W4DrawingHint@QDrawPixmaps@@@@@Z @ 7391 NONAME ABSENT ; void qDrawPixmaps(class QPainter *, struct QDrawPixmaps::Data const *, int, class QPixmap const &, class QFlags<enum QDrawPixmaps::DrawingHint>)
+ ?qDrawPixmaps@@YAXPAVQPainter@@PBUData@QDrawPixmaps@@HABVQPixmap@@V?$QFlags@W4DrawingHint@QDrawPixmaps@@@@@Z @ 7391 NONAME ; void qDrawPixmaps(class QPainter *, struct QDrawPixmaps::Data const *, int, class QPixmap const &, class QFlags<enum QDrawPixmaps::DrawingHint>)
?qDrawPlainRect@@YAXPAVQPainter@@ABVQRect@@ABVQColor@@HPBVQBrush@@@Z @ 7392 NONAME ; void qDrawPlainRect(class QPainter *, class QRect const &, class QColor const &, int, class QBrush const *)
?qDrawPlainRect@@YAXPAVQPainter@@HHHHABVQColor@@HPBVQBrush@@@Z @ 7393 NONAME ; void qDrawPlainRect(class QPainter *, int, int, int, int, class QColor const &, int, class QBrush const *)
?qDrawShadeLine@@YAXPAVQPainter@@ABVQPoint@@1ABVQPalette@@_NHH@Z @ 7394 NONAME ; void qDrawShadeLine(class QPainter *, class QPoint const &, class QPoint const &, class QPalette const &, bool, int, int)
@@ -12601,125 +12601,5 @@ EXPORTS
?setPixelFormat@QEglProperties@@QAEXW4Format@QImage@@@Z @ 12600 NONAME ABSENT ; void QEglProperties::setPixelFormat(enum QImage::Format)
?currentContext@QEglContext@@CAPAV1@W4API@QEgl@@@Z @ 12601 NONAME ABSENT ; class QEglContext * QEglContext::currentContext(enum QEgl::API)
?errorString@QEglContext@@SA?AVQString@@H@Z @ 12602 NONAME ABSENT ; class QString QEglContext::errorString(int)
- ??0FileInfo@QZipReader@@QAE@ABU01@@Z @ 12603 NONAME ; QZipReader::FileInfo::FileInfo(struct QZipReader::FileInfo const &)
- ??0FileInfo@QZipReader@@QAE@XZ @ 12604 NONAME ; QZipReader::FileInfo::FileInfo(void)
- ??0QAbstractScrollAreaPrivate@@QAE@XZ @ 12605 NONAME ; QAbstractScrollAreaPrivate::QAbstractScrollAreaPrivate(void)
- ??0QGraphicsViewPrivate@@QAE@XZ @ 12606 NONAME ; QGraphicsViewPrivate::QGraphicsViewPrivate(void)
- ??0QKeySequence@@QAE@ABVQString@@W4SequenceFormat@0@@Z @ 12607 NONAME ; QKeySequence::QKeySequence(class QString const &, enum QKeySequence::SequenceFormat)
- ??0QStaticText@@QAE@ABV0@@Z @ 12608 NONAME ; QStaticText::QStaticText(class QStaticText const &)
- ??0QStaticText@@QAE@ABVQString@@ABVQSizeF@@@Z @ 12609 NONAME ; QStaticText::QStaticText(class QString const &, class QSizeF const &)
- ??0QStaticText@@QAE@XZ @ 12610 NONAME ; QStaticText::QStaticText(void)
- ??0QStaticTextItem@@QAE@XZ @ 12611 NONAME ; QStaticTextItem::QStaticTextItem(void)
- ??0QZipReader@@QAE@ABVQString@@V?$QFlags@W4OpenModeFlag@QIODevice@@@@@Z @ 12612 NONAME ; QZipReader::QZipReader(class QString const &, class QFlags<enum QIODevice::OpenModeFlag>)
- ??0QZipReader@@QAE@PAVQIODevice@@@Z @ 12613 NONAME ; QZipReader::QZipReader(class QIODevice *)
- ??1FileInfo@QZipReader@@QAE@XZ @ 12614 NONAME ; QZipReader::FileInfo::~FileInfo(void)
- ??1QAbstractScrollAreaPrivate@@UAE@XZ @ 12615 NONAME ; QAbstractScrollAreaPrivate::~QAbstractScrollAreaPrivate(void)
- ??1QGraphicsViewPrivate@@UAE@XZ @ 12616 NONAME ; QGraphicsViewPrivate::~QGraphicsViewPrivate(void)
- ??1QStaticText@@QAE@XZ @ 12617 NONAME ; QStaticText::~QStaticText(void)
- ??1QStaticTextItem@@QAE@XZ @ 12618 NONAME ; QStaticTextItem::~QStaticTextItem(void)
- ??1QZipReader@@QAE@XZ @ 12619 NONAME ; QZipReader::~QZipReader(void)
- ??4FileInfo@QZipReader@@QAEAAU01@ABU01@@Z @ 12620 NONAME ; struct QZipReader::FileInfo & QZipReader::FileInfo::operator=(struct QZipReader::FileInfo const &)
- ??4QStaticText@@QAEAAV0@ABV0@@Z @ 12621 NONAME ; class QStaticText & QStaticText::operator=(class QStaticText const &)
- ??8QStaticText@@QBE_NABV0@@Z @ 12622 NONAME ; bool QStaticText::operator==(class QStaticText const &) const
- ??9QStaticText@@QBE_NABV0@@Z @ 12623 NONAME ; bool QStaticText::operator!=(class QStaticText const &) const
- ??_EQAbstractScrollAreaPrivate@@UAE@I@Z @ 12624 NONAME ; QAbstractScrollAreaPrivate::~QAbstractScrollAreaPrivate(unsigned int)
- ??_EQGraphicsViewPrivate@@UAE@I@Z @ 12625 NONAME ; QGraphicsViewPrivate::~QGraphicsViewPrivate(unsigned int)
- ?_q_hslide@QAbstractScrollAreaPrivate@@QAEXH@Z @ 12626 NONAME ; void QAbstractScrollAreaPrivate::_q_hslide(int)
- ?_q_setViewportCursor@QGraphicsViewPrivate@@QAEXABVQCursor@@@Z @ 12627 NONAME ; void QGraphicsViewPrivate::_q_setViewportCursor(class QCursor const &)
- ?_q_showOrHideScrollBars@QAbstractScrollAreaPrivate@@QAEXXZ @ 12628 NONAME ; void QAbstractScrollAreaPrivate::_q_showOrHideScrollBars(void)
- ?_q_unsetViewportCursor@QGraphicsViewPrivate@@QAEXXZ @ 12629 NONAME ; void QGraphicsViewPrivate::_q_unsetViewportCursor(void)
- ?_q_vslide@QAbstractScrollAreaPrivate@@QAEXH@Z @ 12630 NONAME ; void QAbstractScrollAreaPrivate::_q_vslide(int)
- ?allocStyleOptionsArray@QGraphicsViewPrivate@@QAEPAVQStyleOptionGraphicsItem@@H@Z @ 12631 NONAME ; class QStyleOptionGraphicsItem * QGraphicsViewPrivate::allocStyleOptionsArray(int)
- ?anchorAt@QPlainTextEdit@@QBE?AVQString@@ABVQPoint@@@Z @ 12632 NONAME ; class QString QPlainTextEdit::anchorAt(class QPoint const &) const
- ?assign@QKeySequence@@AAEHABVQString@@W4SequenceFormat@1@@Z @ 12633 NONAME ; int QKeySequence::assign(class QString const &, enum QKeySequence::SequenceFormat)
- ?autoFillBackground@QGraphicsWidget@@QBE_NXZ @ 12634 NONAME ; bool QGraphicsWidget::autoFillBackground(void) const
- ?canKeypadNavigate@QWidgetPrivate@@SA_NW4Orientation@Qt@@@Z @ 12635 NONAME ; bool QWidgetPrivate::canKeypadNavigate(enum Qt::Orientation)
- ?centerView@QGraphicsViewPrivate@@QAEXW4ViewportAnchor@QGraphicsView@@@Z @ 12636 NONAME ; void QGraphicsViewPrivate::centerView(enum QGraphicsView::ViewportAnchor)
- ?clearUndoRedoStacks@QTextDocument@@QAEXW4Stacks@1@@Z @ 12637 NONAME ; void QTextDocument::clearUndoRedoStacks(enum QTextDocument::Stacks)
- ?close@QZipReader@@QAEXXZ @ 12638 NONAME ; void QZipReader::close(void)
- ?constBits@QImage@@QBEPBEXZ @ 12639 NONAME ; unsigned char const * QImage::constBits(void) const
- ?constScanLine@QImage@@QBEPBEH@Z @ 12640 NONAME ; unsigned char const * QImage::constScanLine(int) const
- ?contentsOffset@QAbstractScrollAreaPrivate@@UBE?AVQPoint@@XZ @ 12641 NONAME ; class QPoint QAbstractScrollAreaPrivate::contentsOffset(void) const
- ?convertFromImage@QPixmap@@QAE_NABVQImage@@V?$QFlags@W4ImageConversionFlag@Qt@@@@@Z @ 12642 NONAME ; bool QPixmap::convertFromImage(class QImage const &, class QFlags<enum Qt::ImageConversionFlag>)
- ?count@QZipReader@@QBEHXZ @ 12643 NONAME ; int QZipReader::count(void) const
- ?create@Fragment@QPainter@@SA?AV12@ABVQPointF@@ABVQRectF@@MMMM@Z @ 12644 NONAME ; class QPainter::Fragment QPainter::Fragment::create(class QPointF const &, class QRectF const &, float, float, float, float)
- ?detach@QStaticText@@AAEXXZ @ 12645 NONAME ; void QStaticText::detach(void)
- ?directoryLoaded@QFileSystemModel@@IAEXABVQString@@@Z @ 12646 NONAME ; void QFileSystemModel::directoryLoaded(class QString const &)
- ?dispatchPendingUpdateRequests@QGraphicsViewPrivate@@QAEXXZ @ 12647 NONAME ; void QGraphicsViewPrivate::dispatchPendingUpdateRequests(void)
- ?drawPixmapFragments@QPaintEngineEx@@UAEXPBVFragment@QPainter@@HABVQPixmap@@V?$QFlags@W4FragmentHint@QPainter@@@@@Z @ 12648 NONAME ; void QPaintEngineEx::drawPixmapFragments(class QPainter::Fragment const *, int, class QPixmap const &, class QFlags<enum QPainter::FragmentHint>)
- ?drawPixmapFragments@QPainter@@QAEXPBVFragment@1@HABVQPixmap@@V?$QFlags@W4FragmentHint@QPainter@@@@@Z @ 12649 NONAME ; void QPainter::drawPixmapFragments(class QPainter::Fragment const *, int, class QPixmap const &, class QFlags<enum QPainter::FragmentHint>)
- ?drawStaticText@QPainter@@QAEXABVQPoint@@ABVQStaticText@@@Z @ 12650 NONAME ; void QPainter::drawStaticText(class QPoint const &, class QStaticText const &)
- ?drawStaticText@QPainter@@QAEXABVQPointF@@ABVQStaticText@@@Z @ 12651 NONAME ; void QPainter::drawStaticText(class QPointF const &, class QStaticText const &)
- ?drawStaticText@QPainter@@QAEXHHABVQStaticText@@@Z @ 12652 NONAME ; void QPainter::drawStaticText(int, int, class QStaticText const &)
- ?entryInfoAt@QZipReader@@QBE?AUFileInfo@1@H@Z @ 12653 NONAME ; struct QZipReader::FileInfo QZipReader::entryInfoAt(int) const
- ?exists@QZipReader@@QBE_NXZ @ 12654 NONAME ; bool QZipReader::exists(void) const
- ?extractAll@QZipReader@@QBE_NABVQString@@@Z @ 12655 NONAME ; bool QZipReader::extractAll(class QString const &) const
- ?fileData@QZipReader@@QBE?AVQByteArray@@ABVQString@@@Z @ 12656 NONAME ; class QByteArray QZipReader::fileData(class QString const &) const
- ?fileInfoList@QZipReader@@QBE?AV?$QList@UFileInfo@QZipReader@@@@XZ @ 12657 NONAME ; class QList<struct QZipReader::FileInfo> QZipReader::fileInfoList(void) const
- ?findItems@QGraphicsViewPrivate@@QBE?AV?$QList@PAVQGraphicsItem@@@@ABVQRegion@@PA_NABVQTransform@@@Z @ 12658 NONAME ; class QList<class QGraphicsItem *> QGraphicsViewPrivate::findItems(class QRegion const &, bool *, class QTransform const &) const
- ?fixup@QIntValidator@@UBEXAAVQString@@@Z @ 12659 NONAME ; void QIntValidator::fixup(class QString &) const
- ?freeStyleOptionsArray@QGraphicsViewPrivate@@QAEXPAVQStyleOptionGraphicsItem@@@Z @ 12660 NONAME ; void QGraphicsViewPrivate::freeStyleOptionsArray(class QStyleOptionGraphicsItem *)
- ?getPixmapCursor@QApplicationPrivate@@QAE?AVQPixmap@@W4CursorShape@Qt@@@Z @ 12661 NONAME ; class QPixmap QApplicationPrivate::getPixmapCursor(enum Qt::CursorShape)
- ?getSubRange@QBezier@@QBE?AV1@MM@Z @ 12662 NONAME ; class QBezier QBezier::getSubRange(float, float) const
- ?hasSelectedText@QLabel@@QBE_NXZ @ 12663 NONAME ; bool QLabel::hasSelectedText(void) const
- ?horizontalScroll@QGraphicsViewPrivate@@QBE_JXZ @ 12664 NONAME ; long long QGraphicsViewPrivate::horizontalScroll(void) const
- ?inTabWidget@QWidgetPrivate@@SA_NPAVQWidget@@@Z @ 12665 NONAME ; bool QWidgetPrivate::inTabWidget(class QWidget *)
- ?init@QAbstractScrollAreaPrivate@@QAEXXZ @ 12666 NONAME ; void QAbstractScrollAreaPrivate::init(void)
- ?isImageCached@QImagePixmapCleanupHooks@@SA_NABVQImage@@@Z @ 12667 NONAME ; bool QImagePixmapCleanupHooks::isImageCached(class QImage const &)
- ?isPixmapCached@QImagePixmapCleanupHooks@@SA_NABVQPixmap@@@Z @ 12668 NONAME ; bool QImagePixmapCleanupHooks::isPixmapCached(class QPixmap const &)
- ?isReadable@QZipReader@@QBE_NXZ @ 12669 NONAME ; bool QZipReader::isReadable(void) const
- ?isValidColor@QColor@@SA_NABVQString@@@Z @ 12670 NONAME ; bool QColor::isValidColor(class QString const &)
- ?layoutChildren@QAbstractScrollAreaPrivate@@QAEXXZ @ 12671 NONAME ; void QAbstractScrollAreaPrivate::layoutChildren(void)
- ?mapBy@QBezier@@QBE?AV1@ABVQTransform@@@Z @ 12672 NONAME ; class QBezier QBezier::mapBy(class QTransform const &) const
- ?mapRectFromScene@QGraphicsViewPrivate@@QBE?AVQRectF@@ABV2@@Z @ 12673 NONAME ; class QRectF QGraphicsViewPrivate::mapRectFromScene(class QRectF const &) const
- ?mapRectToScene@QGraphicsViewPrivate@@QBE?AVQRectF@@ABVQRect@@@Z @ 12674 NONAME ; class QRectF QGraphicsViewPrivate::mapRectToScene(class QRect const &) const
- ?mapToScene@QGraphicsViewPrivate@@QBE?AVQPointF@@ABV2@@Z @ 12675 NONAME ; class QPointF QGraphicsViewPrivate::mapToScene(class QPointF const &) const
- ?mapToScene@QGraphicsViewPrivate@@QBE?AVQRectF@@ABV2@@Z @ 12676 NONAME ; class QRectF QGraphicsViewPrivate::mapToScene(class QRectF const &) const
- ?mapToViewRect@QGraphicsViewPrivate@@QBE?AVQRect@@PBVQGraphicsItem@@ABVQRectF@@@Z @ 12677 NONAME ; class QRect QGraphicsViewPrivate::mapToViewRect(class QGraphicsItem const *, class QRectF const &) const
- ?mapToViewRegion@QGraphicsViewPrivate@@QBE?AVQRegion@@PBVQGraphicsItem@@ABVQRectF@@@Z @ 12678 NONAME ; class QRegion QGraphicsViewPrivate::mapToViewRegion(class QGraphicsItem const *, class QRectF const &) const
- ?maximumSize@QStaticText@@QBE?AVQSizeF@@XZ @ 12679 NONAME ; class QSizeF QStaticText::maximumSize(void) const
- ?mouseMoveEventHandler@QGraphicsViewPrivate@@QAEXPAVQMouseEvent@@@Z @ 12680 NONAME ; void QGraphicsViewPrivate::mouseMoveEventHandler(class QMouseEvent *)
- ?performanceHint@QStaticText@@QBE?AW4PerformanceHint@1@XZ @ 12681 NONAME ; enum QStaticText::PerformanceHint QStaticText::performanceHint(void) const
- ?populate@QTextureGlyphCache@@QAEXPAVQFontEngine@@HPBIPBUQFixedPoint@@@Z @ 12682 NONAME ; void QTextureGlyphCache::populate(class QFontEngine *, int, unsigned int const *, struct QFixedPoint const *)
- ?populateSceneDragDropEvent@QGraphicsViewPrivate@@QAEXPAVQGraphicsSceneDragDropEvent@@PAVQDropEvent@@@Z @ 12683 NONAME ; void QGraphicsViewPrivate::populateSceneDragDropEvent(class QGraphicsSceneDragDropEvent *, class QDropEvent *)
- ?positionInBlock@QTextCursor@@QBEHXZ @ 12684 NONAME ; int QTextCursor::positionInBlock(void) const
- ?prepare@QStaticText@@QAEXABVQTransform@@ABVQFont@@@Z @ 12685 NONAME ; void QStaticText::prepare(class QTransform const &, class QFont const &)
- ?processPendingUpdates@QGraphicsViewPrivate@@QAEXXZ @ 12686 NONAME ; void QGraphicsViewPrivate::processPendingUpdates(void)
- ?q_func@QAbstractScrollAreaPrivate@@AAEPAVQAbstractScrollArea@@XZ @ 12687 NONAME ; class QAbstractScrollArea * QAbstractScrollAreaPrivate::q_func(void)
- ?q_func@QAbstractScrollAreaPrivate@@ABEPBVQAbstractScrollArea@@XZ @ 12688 NONAME ; class QAbstractScrollArea const * QAbstractScrollAreaPrivate::q_func(void) const
- ?q_func@QGraphicsViewPrivate@@AAEPAVQGraphicsView@@XZ @ 12689 NONAME ; class QGraphicsView * QGraphicsViewPrivate::q_func(void)
- ?q_func@QGraphicsViewPrivate@@ABEPBVQGraphicsView@@XZ @ 12690 NONAME ; class QGraphicsView const * QGraphicsViewPrivate::q_func(void) const
- ?qt_draw_glyphs@@YAXPAVQPainter@@PBIPBVQPointF@@H@Z @ 12691 NONAME ; void qt_draw_glyphs(class QPainter *, unsigned int const *, class QPointF const *, int)
- ?recalculateContentSize@QGraphicsViewPrivate@@QAEXXZ @ 12692 NONAME ; void QGraphicsViewPrivate::recalculateContentSize(void)
- ?render@QWidgetPrivate@@QAEXPAVQPaintDevice@@ABVQPoint@@ABVQRegion@@V?$QFlags@W4RenderFlag@QWidget@@@@_N@Z @ 12693 NONAME ; void QWidgetPrivate::render(class QPaintDevice *, class QPoint const &, class QRegion const &, class QFlags<enum QWidget::RenderFlag>, bool)
- ?replaceScrollBar@QAbstractScrollAreaPrivate@@QAEXPAVQScrollBar@@W4Orientation@Qt@@@Z @ 12694 NONAME ; void QAbstractScrollAreaPrivate::replaceScrollBar(class QScrollBar *, enum Qt::Orientation)
- ?replayLastMouseEvent@QGraphicsViewPrivate@@QAEXXZ @ 12695 NONAME ; void QGraphicsViewPrivate::replayLastMouseEvent(void)
- ?rubberBandRegion@QGraphicsViewPrivate@@QBE?AVQRegion@@PBVQWidget@@ABVQRect@@@Z @ 12696 NONAME ; class QRegion QGraphicsViewPrivate::rubberBandRegion(class QWidget const *, class QRect const &) const
- ?scrollBarPolicyChanged@QAbstractScrollAreaPrivate@@UAEXW4Orientation@Qt@@W4ScrollBarPolicy@3@@Z @ 12697 NONAME ; void QAbstractScrollAreaPrivate::scrollBarPolicyChanged(enum Qt::Orientation, enum Qt::ScrollBarPolicy)
- ?selectedText@QLabel@@QBE?AVQString@@XZ @ 12698 NONAME ; class QString QLabel::selectedText(void) const
- ?selectionStart@QLabel@@QBEHXZ @ 12699 NONAME ; int QLabel::selectionStart(void) const
- ?setAutoFillBackground@QGraphicsWidget@@QAEX_N@Z @ 12700 NONAME ; void QGraphicsWidget::setAutoFillBackground(bool)
- ?setColorFromString@QColor@@AAE_NABVQString@@@Z @ 12701 NONAME ; bool QColor::setColorFromString(class QString const &)
- ?setMaximumSize@QStaticText@@QAEXABVQSizeF@@@Z @ 12702 NONAME ; void QStaticText::setMaximumSize(class QSizeF const &)
- ?setPerformanceHint@QStaticText@@QAEXW4PerformanceHint@1@@Z @ 12703 NONAME ; void QStaticText::setPerformanceHint(enum QStaticText::PerformanceHint)
- ?setSelection@QLabel@@QAEXHH@Z @ 12704 NONAME ; void QLabel::setSelection(int, int)
- ?setText@QStaticText@@QAEXABVQString@@@Z @ 12705 NONAME ; void QStaticText::setText(class QString const &)
- ?setTextFormat@QStaticText@@QAEXW4TextFormat@Qt@@@Z @ 12706 NONAME ; void QStaticText::setTextFormat(enum Qt::TextFormat)
- ?setUserData@QStaticTextItem@@QAEXPAVQStaticTextUserData@@@Z @ 12707 NONAME ; void QStaticTextItem::setUserData(class QStaticTextUserData *)
- ?size@QStaticText@@QBE?AVQSizeF@@XZ @ 12708 NONAME ; class QSizeF QStaticText::size(void) const
- ?status@QZipReader@@QBE?AW4Status@1@XZ @ 12709 NONAME ; enum QZipReader::Status QZipReader::status(void) const
- ?storeDragDropEvent@QGraphicsViewPrivate@@QAEXPBVQGraphicsSceneDragDropEvent@@@Z @ 12710 NONAME ; void QGraphicsViewPrivate::storeDragDropEvent(class QGraphicsSceneDragDropEvent const *)
- ?storeMouseEvent@QGraphicsViewPrivate@@QAEXPAVQMouseEvent@@@Z @ 12711 NONAME ; void QGraphicsViewPrivate::storeMouseEvent(class QMouseEvent *)
- ?text@QStaticText@@QBE?AVQString@@XZ @ 12712 NONAME ; class QString QStaticText::text(void) const
- ?textFormat@QStaticText@@QBE?AW4TextFormat@Qt@@XZ @ 12713 NONAME ; enum Qt::TextFormat QStaticText::textFormat(void) const
- ?translateTouchEvent@QGraphicsViewPrivate@@SAXPAV1@PAVQTouchEvent@@@Z @ 12714 NONAME ; void QGraphicsViewPrivate::translateTouchEvent(class QGraphicsViewPrivate *, class QTouchEvent *)
- ?updateAll@QGraphicsViewPrivate@@QAEXXZ @ 12715 NONAME ; void QGraphicsViewPrivate::updateAll(void)
- ?updateInputMethodSensitivity@QGraphicsViewPrivate@@QAEXXZ @ 12716 NONAME ; void QGraphicsViewPrivate::updateInputMethodSensitivity(void)
- ?updateLastCenterPoint@QGraphicsViewPrivate@@QAEXXZ @ 12717 NONAME ; void QGraphicsViewPrivate::updateLastCenterPoint(void)
- ?updateRect@QGraphicsViewPrivate@@QAE_NABVQRect@@@Z @ 12718 NONAME ; bool QGraphicsViewPrivate::updateRect(class QRect const &)
- ?updateRegion@QGraphicsViewPrivate@@QAE_NABVQRegion@@@Z @ 12719 NONAME ; bool QGraphicsViewPrivate::updateRegion(class QRegion const &)
- ?updateScroll@QGraphicsViewPrivate@@QAEXXZ @ 12720 NONAME ; void QGraphicsViewPrivate::updateScroll(void)
- ?verticalScroll@QGraphicsViewPrivate@@QBE_JXZ @ 12721 NONAME ; long long QGraphicsViewPrivate::verticalScroll(void) const
- ?viewportEvent@QAbstractScrollAreaPrivate@@QAE_NPAVQEvent@@@Z @ 12722 NONAME ; bool QAbstractScrollAreaPrivate::viewportEvent(class QEvent *)
- ?visibilityChanged@QToolBar@@IAEX_N@Z @ 12723 NONAME ; void QToolBar::visibilityChanged(bool)
+ ?removeAllApplicationFonts@QFontDatabase@@SA_NXZ @12603 ; NONAME ; bool QFontDatabase::removeAllApplicationFonts()
diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def
index 7c91264..a3fc452 100644
--- a/src/s60installs/eabi/QtGuiu.def
+++ b/src/s60installs/eabi/QtGuiu.def
@@ -1,7 +1,7 @@
EXPORTS
_Z11qFadeEffectP7QWidgeti @ 1 NONAME
_Z11qt_image_idRK6QImage @ 2 NONAME
- _Z12qDrawPixmapsP8QPainterPKN12QDrawPixmaps4DataEiRK7QPixmap6QFlagsINS1_11DrawingHintEE @ 3 NONAME ABSENT
+ _Z12qDrawPixmapsP8QPainterPKN12QDrawPixmaps4DataEiRK7QPixmap6QFlagsINS1_11DrawingHintEE @ 3 NONAME
_Z12qt_pixmap_idRK7QPixmap @ 4 NONAME
_Z13qDrawWinPanelP8QPainterRK5QRectRK8QPalettebPK6QBrush @ 5 NONAME
_Z13qDrawWinPanelP8QPainteriiiiRK8QPalettebPK6QBrush @ 6 NONAME
@@ -2906,7 +2906,7 @@ EXPORTS
_ZN14QPaintEngineEx10drawPointsEPK7QPointFi @ 2905 NONAME
_ZN14QPaintEngineEx11drawEllipseERK5QRect @ 2906 NONAME
_ZN14QPaintEngineEx11drawEllipseERK6QRectF @ 2907 NONAME
- _ZN14QPaintEngineEx11drawPixmapsEPKN12QDrawPixmaps4DataEiRK7QPixmap6QFlagsINS0_11DrawingHintEE @ 2908 NONAME ABSENT
+ _ZN14QPaintEngineEx11drawPixmapsEPKN12QDrawPixmaps4DataEiRK7QPixmap6QFlagsINS0_11DrawingHintEE @ 2908 NONAME
_ZN14QPaintEngineEx11drawPolygonEPK6QPointiN12QPaintEngine15PolygonDrawModeE @ 2909 NONAME
_ZN14QPaintEngineEx11drawPolygonEPK7QPointFiN12QPaintEngine15PolygonDrawModeE @ 2910 NONAME
_ZN14QPaintEngineEx11updateStateERK17QPaintEngineState @ 2911 NONAME
@@ -4223,7 +4223,7 @@ EXPORTS
_ZN18QTextBlockUserDataD0Ev @ 4222 NONAME
_ZN18QTextBlockUserDataD1Ev @ 4223 NONAME
_ZN18QTextBlockUserDataD2Ev @ 4224 NONAME
- _ZN18QTextureGlyphCache8populateERK12QTextItemIntRK15QVarLengthArrayIjLi256EERKS3_I11QFixedPointLi256EE @ 4225 NONAME ABSENT
+ _ZN18QTextureGlyphCache8populateERK12QTextItemIntRK15QVarLengthArrayIjLi256EERKS3_I11QFixedPointLi256EE @ 4225 NONAME
_ZN19QAbstractProxyModel11qt_metacallEN11QMetaObject4CallEiPPv @ 4226 NONAME
_ZN19QAbstractProxyModel11qt_metacastEPKc @ 4227 NONAME
_ZN19QAbstractProxyModel13setHeaderDataEiN2Qt11OrientationERK8QVarianti @ 4228 NONAME
@@ -11805,125 +11805,5 @@ EXPORTS
_ZN24QImagePixmapCleanupHooks34executePixmapDataModificationHooksEP11QPixmapData @ 11804 NONAME
_ZN9QS60Style10timerEventEP11QTimerEvent @ 11805 NONAME
_ZN9QS60Style11eventFilterEP7QObjectP6QEvent @ 11806 NONAME
- _Z14qt_draw_glyphsP8QPainterPKjPK7QPointFi @ 11807 NONAME
- _ZN10QZipReader5closeEv @ 11808 NONAME
- _ZN10QZipReader8FileInfoC1ERKS0_ @ 11809 NONAME
- _ZN10QZipReader8FileInfoC1Ev @ 11810 NONAME
- _ZN10QZipReader8FileInfoC2ERKS0_ @ 11811 NONAME
- _ZN10QZipReader8FileInfoC2Ev @ 11812 NONAME
- _ZN10QZipReader8FileInfoD1Ev @ 11813 NONAME
- _ZN10QZipReader8FileInfoD2Ev @ 11814 NONAME
- _ZN10QZipReader8FileInfoaSERKS0_ @ 11815 NONAME
- _ZN10QZipReaderC1EP9QIODevice @ 11816 NONAME
- _ZN10QZipReaderC1ERK7QString6QFlagsIN9QIODevice12OpenModeFlagEE @ 11817 NONAME
- _ZN10QZipReaderC2EP9QIODevice @ 11818 NONAME
- _ZN10QZipReaderC2ERK7QString6QFlagsIN9QIODevice12OpenModeFlagEE @ 11819 NONAME
- _ZN10QZipReaderD1Ev @ 11820 NONAME
- _ZN10QZipReaderD2Ev @ 11821 NONAME
- _ZN11QStaticText13setTextFormatEN2Qt10TextFormatE @ 11822 NONAME
- _ZN11QStaticText14setMaximumSizeERK6QSizeF @ 11823 NONAME
- _ZN11QStaticText18setPerformanceHintENS_15PerformanceHintE @ 11824 NONAME
- _ZN11QStaticText6detachEv @ 11825 NONAME
- _ZN11QStaticText7prepareERK10QTransformRK5QFont @ 11826 NONAME
- _ZN11QStaticText7setTextERK7QString @ 11827 NONAME
- _ZN11QStaticTextC1ERK7QStringRK6QSizeF @ 11828 NONAME
- _ZN11QStaticTextC1ERKS_ @ 11829 NONAME
- _ZN11QStaticTextC1Ev @ 11830 NONAME
- _ZN11QStaticTextC2ERK7QStringRK6QSizeF @ 11831 NONAME
- _ZN11QStaticTextC2ERKS_ @ 11832 NONAME
- _ZN11QStaticTextC2Ev @ 11833 NONAME
- _ZN11QStaticTextD1Ev @ 11834 NONAME
- _ZN11QStaticTextD2Ev @ 11835 NONAME
- _ZN11QStaticTextaSERKS_ @ 11836 NONAME
- _ZN12QKeySequence6assignERK7QStringNS_14SequenceFormatE @ 11837 NONAME
- _ZN12QKeySequenceC1ERK7QStringNS_14SequenceFormatE @ 11838 NONAME
- _ZN12QKeySequenceC2ERK7QStringNS_14SequenceFormatE @ 11839 NONAME
- _ZN13QTextDocument19clearUndoRedoStacksENS_6StacksE @ 11840 NONAME
- _ZN14QPaintEngineEx19drawPixmapFragmentsEPKN8QPainter8FragmentEiRK7QPixmap6QFlagsINS0_12FragmentHintEE @ 11841 NONAME
- _ZN14QWidgetPrivate11inTabWidgetEP7QWidget @ 11842 NONAME
- _ZN14QWidgetPrivate17canKeypadNavigateEN2Qt11OrientationE @ 11843 NONAME
- _ZN14QWidgetPrivate6renderEP12QPaintDeviceRK6QPointRK7QRegion6QFlagsIN7QWidget10RenderFlagEEb @ 11844 NONAME
- _ZN15QGraphicsWidget21setAutoFillBackgroundEb @ 11845 NONAME
- _ZN16QFileSystemModel15directoryLoadedERK7QString @ 11846 NONAME
- _ZN18QTextureGlyphCache8populateEP11QFontEngineiPKjPK11QFixedPoint @ 11847 NONAME
- _ZN19QApplicationPrivate15getPixmapCursorEN2Qt11CursorShapeE @ 11848 NONAME
- _ZN20QGraphicsViewPrivate10centerViewEN13QGraphicsView14ViewportAnchorE @ 11849 NONAME
- _ZN20QGraphicsViewPrivate10updateRectERK5QRect @ 11850 NONAME
- _ZN20QGraphicsViewPrivate12updateRegionERK7QRegion @ 11851 NONAME
- _ZN20QGraphicsViewPrivate12updateScrollEv @ 11852 NONAME
- _ZN20QGraphicsViewPrivate15storeMouseEventEP11QMouseEvent @ 11853 NONAME
- _ZN20QGraphicsViewPrivate18storeDragDropEventEPK27QGraphicsSceneDragDropEvent @ 11854 NONAME
- _ZN20QGraphicsViewPrivate19translateTouchEventEPS_P11QTouchEvent @ 11855 NONAME
- _ZN20QGraphicsViewPrivate20_q_setViewportCursorERK7QCursor @ 11856 NONAME
- _ZN20QGraphicsViewPrivate20replayLastMouseEventEv @ 11857 NONAME
- _ZN20QGraphicsViewPrivate21freeStyleOptionsArrayEP24QStyleOptionGraphicsItem @ 11858 NONAME
- _ZN20QGraphicsViewPrivate21mouseMoveEventHandlerEP11QMouseEvent @ 11859 NONAME
- _ZN20QGraphicsViewPrivate21processPendingUpdatesEv @ 11860 NONAME
- _ZN20QGraphicsViewPrivate21updateLastCenterPointEv @ 11861 NONAME
- _ZN20QGraphicsViewPrivate22_q_unsetViewportCursorEv @ 11862 NONAME
- _ZN20QGraphicsViewPrivate22allocStyleOptionsArrayEi @ 11863 NONAME
- _ZN20QGraphicsViewPrivate22recalculateContentSizeEv @ 11864 NONAME
- _ZN20QGraphicsViewPrivate26populateSceneDragDropEventEP27QGraphicsSceneDragDropEventP10QDropEvent @ 11865 NONAME
- _ZN20QGraphicsViewPrivate28updateInputMethodSensitivityEv @ 11866 NONAME
- _ZN20QGraphicsViewPrivateC1Ev @ 11867 NONAME
- _ZN20QGraphicsViewPrivateC2Ev @ 11868 NONAME
- _ZN24QImagePixmapCleanupHooks13isImageCachedERK6QImage @ 11869 NONAME
- _ZN24QImagePixmapCleanupHooks14isPixmapCachedERK7QPixmap @ 11870 NONAME
- _ZN26QAbstractScrollAreaPrivate14layoutChildrenEv @ 11871 NONAME
- _ZN26QAbstractScrollAreaPrivate16replaceScrollBarEP10QScrollBarN2Qt11OrientationE @ 11872 NONAME
- _ZN26QAbstractScrollAreaPrivate23_q_showOrHideScrollBarsEv @ 11873 NONAME
- _ZN26QAbstractScrollAreaPrivate4initEv @ 11874 NONAME
- _ZN26QAbstractScrollAreaPrivate9_q_hslideEi @ 11875 NONAME
- _ZN26QAbstractScrollAreaPrivate9_q_vslideEi @ 11876 NONAME
- _ZN26QAbstractScrollAreaPrivateC1Ev @ 11877 NONAME
- _ZN26QAbstractScrollAreaPrivateC2Ev @ 11878 NONAME
- _ZN6QColor12isValidColorERK7QString @ 11879 NONAME
- _ZN6QColor18setColorFromStringERK7QString @ 11880 NONAME
- _ZN6QLabel12setSelectionEii @ 11881 NONAME
- _ZN7QPixmap16convertFromImageERK6QImage6QFlagsIN2Qt19ImageConversionFlagEE @ 11882 NONAME
- _ZN8QPainter14drawStaticTextERK7QPointFRK11QStaticText @ 11883 NONAME
- _ZN8QPainter19drawPixmapFragmentsEPKNS_8FragmentEiRK7QPixmap6QFlagsINS_12FragmentHintEE @ 11884 NONAME
- _ZN8QPainter8Fragment6createERK7QPointFRK6QRectFffff @ 11885 NONAME
- _ZN8QToolBar17visibilityChangedEb @ 11886 NONAME
- _ZNK10QZipReader10extractAllERK7QString @ 11887 NONAME
- _ZNK10QZipReader10isReadableEv @ 11888 NONAME
- _ZNK10QZipReader11entryInfoAtEi @ 11889 NONAME
- _ZNK10QZipReader12fileInfoListEv @ 11890 NONAME
- _ZNK10QZipReader5countEv @ 11891 NONAME
- _ZNK10QZipReader6existsEv @ 11892 NONAME
- _ZNK10QZipReader6statusEv @ 11893 NONAME
- _ZNK10QZipReader8fileDataERK7QString @ 11894 NONAME
- _ZNK11QStaticText10textFormatEv @ 11895 NONAME
- _ZNK11QStaticText11maximumSizeEv @ 11896 NONAME
- _ZNK11QStaticText15performanceHintEv @ 11897 NONAME
- _ZNK11QStaticText4sizeEv @ 11898 NONAME
- _ZNK11QStaticText4textEv @ 11899 NONAME
- _ZNK11QStaticTexteqERKS_ @ 11900 NONAME
- _ZNK11QStaticTextneERKS_ @ 11901 NONAME
- _ZNK11QTextCursor15positionInBlockEv @ 11902 NONAME
- _ZNK13QIntValidator5fixupER7QString @ 11903 NONAME
- _ZNK14QPlainTextEdit8anchorAtERK6QPoint @ 11904 NONAME
- _ZNK15QGraphicsWidget18autoFillBackgroundEv @ 11905 NONAME
- _ZNK20QGraphicsViewPrivate10mapToSceneERK6QRectF @ 11906 NONAME
- _ZNK20QGraphicsViewPrivate10mapToSceneERK7QPointF @ 11907 NONAME
- _ZNK20QGraphicsViewPrivate13mapToViewRectEPK13QGraphicsItemRK6QRectF @ 11908 NONAME
- _ZNK20QGraphicsViewPrivate14mapRectToSceneERK5QRect @ 11909 NONAME
- _ZNK20QGraphicsViewPrivate14verticalScrollEv @ 11910 NONAME
- _ZNK20QGraphicsViewPrivate15mapToViewRegionEPK13QGraphicsItemRK6QRectF @ 11911 NONAME
- _ZNK20QGraphicsViewPrivate16horizontalScrollEv @ 11912 NONAME
- _ZNK20QGraphicsViewPrivate16mapRectFromSceneERK6QRectF @ 11913 NONAME
- _ZNK20QGraphicsViewPrivate16rubberBandRegionEPK7QWidgetRK5QRect @ 11914 NONAME
- _ZNK20QGraphicsViewPrivate9findItemsERK7QRegionPbRK10QTransform @ 11915 NONAME
- _ZNK26QAbstractScrollAreaPrivate14contentsOffsetEv @ 11916 NONAME
- _ZNK6QImage13constScanLineEi @ 11917 NONAME
- _ZNK6QImage9constBitsEv @ 11918 NONAME
- _ZNK6QLabel12selectedTextEv @ 11919 NONAME
- _ZNK6QLabel14selectionStartEv @ 11920 NONAME
- _ZNK6QLabel15hasSelectedTextEv @ 11921 NONAME
- _ZNK7QBezier11getSubRangeEff @ 11922 NONAME
- _ZNK7QBezier5mapByERK10QTransform @ 11923 NONAME
- _ZTI20QGraphicsViewPrivate @ 11924 NONAME
- _ZTI26QAbstractScrollAreaPrivate @ 11925 NONAME
- _ZTV20QGraphicsViewPrivate @ 11926 NONAME
- _ZTV26QAbstractScrollAreaPrivate @ 11927 NONAME
+ _ZN13QFontDatabase25removeAllApplicationFontsEv @ 11807 NONAME
diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro
index db1ee4d..ffd15e6 100644
--- a/src/s60installs/s60installs.pro
+++ b/src/s60installs/s60installs.pro
@@ -13,9 +13,12 @@ symbian: {
TARGET.UID3 = 0x2001E61C
# sqlite3 is expected to be already found on phone if infixed configuration is built.
+ BLD_INF_RULES.prj_exports += \
+ "sqlite3.sis $${EPOCROOT}epoc32/data/qt/sis/sqlite3.sis" \
+ "sqlite3_selfsigned.sis $${EPOCROOT}epoc32/data/qt/sis/sqlite3_selfsigned.sis"
sqlitedeployment = \
"; Deploy sqlite onto phone that does not have it already" \
- "@\"$$PWD/sqlite3.sis\", (0x2002af5f)"
+ "@\"$${EPOCROOT}epoc32/data/qt/sis/sqlite3.sis\", (0x2002af5f)"
qtlibraries.pkg_postrules += sqlitedeployment
} else {
# Always use experimental UID for infixed configuration to avoid UID clash
diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp
index b322523..70f798e 100644
--- a/src/script/api/qscriptengine.cpp
+++ b/src/script/api/qscriptengine.cpp
@@ -875,7 +875,7 @@ QScriptEnginePrivate::QScriptEnginePrivate()
return;
}
JSC::initializeThreading();
-
+ JSC::IdentifierTable *oldTable = JSC::currentIdentifierTable();
globalData = JSC::JSGlobalData::create().releaseRef();
globalData->clientData = new QScript::GlobalClientData(this);
JSC::JSGlobalObject *globalObject = new (globalData)QScript::GlobalObject();
@@ -911,11 +911,12 @@ QScriptEnginePrivate::QScriptEnginePrivate()
activeAgent = 0;
agentLineNumber = -1;
processEventsInterval = -1;
+ JSC::setCurrentIdentifierTable(oldTable);
}
QScriptEnginePrivate::~QScriptEnginePrivate()
{
- JSC::setCurrentIdentifierTable(globalData->identifierTable);
+ QScript::APIShim shim(this);
//disconnect all loadedScripts and generate all jsc::debugger::scriptUnload events
QHash<intptr_t,QScript::UStringSourceProviderWithFeedback*>::const_iterator it;
@@ -3277,6 +3278,7 @@ bool QScriptEnginePrivate::hasDemarshalFunction(int type) const
bool QScriptEngine::convert(const QScriptValue &value, int type, void *ptr)
{
Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
return QScriptEnginePrivate::convertValue(d->currentFrame, d->scriptValueToJSCValue(value), type, ptr);
}
@@ -3289,8 +3291,12 @@ bool QScriptEngine::convertV2(const QScriptValue &value, int type, void *ptr)
if (vp) {
switch (vp->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = vp->engine ? vp->engine->currentFrame : 0;
- return QScriptEnginePrivate::convertValue(exec, vp->jscValue, type, ptr);
+ if (vp->engine) {
+ QScript::APIShim shim(vp->engine);
+ return QScriptEnginePrivate::convertValue(vp->engine->currentFrame, vp->jscValue, type, ptr);
+ } else {
+ return QScriptEnginePrivate::convertValue(0, vp->jscValue, type, ptr);
+ }
}
case QScriptValuePrivate::Number:
return QScriptEnginePrivate::convertNumber(vp->numberValue, type, ptr);
@@ -3341,6 +3347,7 @@ void QScriptEngine::registerCustomType(int type, MarshalFunction mf,
void QScriptEngine::installTranslatorFunctions(const QScriptValue &object)
{
Q_D(QScriptEngine);
+ QScript::APIShim shim(d);
JSC::ExecState* exec = d->currentFrame;
JSC::JSValue jscObject = d->scriptValueToJSCValue(object);
JSC::JSGlobalObject *glob = d->originalGlobalObject();
diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp
index 4cd84a4..3aab268 100644
--- a/src/script/api/qscriptvalue.cpp
+++ b/src/script/api/qscriptvalue.cpp
@@ -561,6 +561,7 @@ QScriptValue QScriptValue::scope() const
Q_D(const QScriptValue);
if (!d || !d->isObject())
return QScriptValue();
+ QScript::APIShim shim(d->engine);
// ### make hidden property
JSC::JSValue result = d->property("__qt_scope__", QScriptValue::ResolveLocal);
return d->engine->scriptValueFromJSCValue(result);
@@ -650,11 +651,12 @@ static Type type(const QScriptValue &v)
return Object;
}
-QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference)
+static QScriptValue ToPrimitive(const QScriptValue &object, JSC::PreferredPrimitiveType hint = JSC::NoPreference)
{
Q_ASSERT(object.isObject());
QScriptValuePrivate *pp = QScriptValuePrivate::get(object);
Q_ASSERT(pp->engine != 0);
+ QScript::APIShim shim(pp->engine);
JSC::ExecState *exec = pp->engine->currentFrame;
JSC::JSValue savedException;
QScriptEnginePrivate::saveException(exec, &savedException);
@@ -848,6 +850,7 @@ bool QScriptValue::equals(const QScriptValue &other) const
if (!eng_p)
eng_p = other.d_ptr->engine;
if (eng_p) {
+ QScript::APIShim shim(eng_p);
JSC::ExecState *exec = eng_p->currentFrame;
JSC::JSValue savedException;
QScriptEnginePrivate::saveException(exec, &savedException);
@@ -940,9 +943,12 @@ QString QScriptValue::toString() const
return QString();
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toString(exec, d->jscValue);
- }
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toString(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toString(0, d->jscValue);
+ } }
case QScriptValuePrivate::Number:
return QScript::ToString(d->numberValue);
case QScriptValuePrivate::String:
@@ -970,8 +976,12 @@ qsreal QScriptValue::toNumber() const
return 0;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toNumber(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toNumber(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toNumber(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return d->numberValue;
@@ -993,8 +1003,12 @@ bool QScriptValue::toBoolean() const
return false;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toBool(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toBool(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QScript::ToBool(d->numberValue);
@@ -1025,8 +1039,12 @@ bool QScriptValue::toBool() const
return false;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toBool(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toBool(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toBool(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QScript::ToBool(d->numberValue);
@@ -1055,8 +1073,12 @@ qint32 QScriptValue::toInt32() const
return 0;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toInt32(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toInt32(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toInt32(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QScript::ToInt32(d->numberValue);
@@ -1085,8 +1107,12 @@ quint32 QScriptValue::toUInt32() const
return 0;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toUInt32(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toUInt32(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toUInt32(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QScript::ToUInt32(d->numberValue);
@@ -1115,8 +1141,12 @@ quint16 QScriptValue::toUInt16() const
return 0;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toUInt16(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toUInt16(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toUInt16(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QScript::ToUInt16(d->numberValue);
@@ -1145,8 +1175,12 @@ qsreal QScriptValue::toInteger() const
return 0;
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toInteger(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toInteger(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toInteger(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QScript::ToInteger(d->numberValue);
@@ -1185,8 +1219,12 @@ QVariant QScriptValue::toVariant() const
return QVariant();
switch (d->type) {
case QScriptValuePrivate::JavaScriptCore: {
- JSC::ExecState *exec = d->engine ? d->engine->currentFrame : 0;
- return QScriptEnginePrivate::toVariant(exec, d->jscValue);
+ if (d->engine) {
+ QScript::APIShim shim(d->engine);
+ return QScriptEnginePrivate::toVariant(d->engine->currentFrame, d->jscValue);
+ } else {
+ return QScriptEnginePrivate::toVariant(0, d->jscValue);
+ }
}
case QScriptValuePrivate::Number:
return QVariant(d->numberValue);
diff --git a/src/script/api/qscriptvalueiterator.cpp b/src/script/api/qscriptvalueiterator.cpp
index 7fd7093..ecda5fc 100644
--- a/src/script/api/qscriptvalueiterator.cpp
+++ b/src/script/api/qscriptvalueiterator.cpp
@@ -85,6 +85,17 @@ public:
: initialized(false)
{}
+ ~QScriptValueIteratorPrivate()
+ {
+ if (!initialized)
+ return;
+ QScriptEnginePrivate *eng_p = engine();
+ if (!eng_p)
+ return;
+ QScript::APIShim shim(eng_p);
+ propertyNames.clear(); //destroying the identifiers need to be done under the APIShim guard
+ }
+
QScriptValuePrivate *object() const
{
return QScriptValuePrivate::get(objectValue);
@@ -281,6 +292,7 @@ QScriptValue QScriptValueIterator::value() const
Q_D(const QScriptValueIterator);
if (!d || !d->initialized || !d->engine())
return QScriptValue();
+ QScript::APIShim shim(d->engine());
JSC::JSValue jsValue = d->object()->property(*d->current);
return d->engine()->scriptValueFromJSCValue(jsValue);
}
@@ -296,6 +308,7 @@ void QScriptValueIterator::setValue(const QScriptValue &value)
Q_D(QScriptValueIterator);
if (!d || !d->initialized || !d->engine())
return;
+ QScript::APIShim shim(d->engine());
JSC::JSValue jsValue = d->engine()->scriptValueToJSCValue(value);
d->object()->setProperty(*d->current, jsValue);
}
@@ -311,6 +324,7 @@ QScriptValue::PropertyFlags QScriptValueIterator::flags() const
Q_D(const QScriptValueIterator);
if (!d || !d->initialized || !d->engine())
return 0;
+ QScript::APIShim shim(d->engine());
return d->object()->propertyFlags(*d->current);
}
@@ -325,6 +339,7 @@ void QScriptValueIterator::remove()
Q_D(QScriptValueIterator);
if (!d || !d->initialized || !d->engine())
return;
+ QScript::APIShim shim(d->engine());
d->object()->setProperty(*d->current, JSC::JSValue());
d->propertyNames.erase(d->current);
}
diff --git a/src/script/bridge/qscriptdeclarativeclass.cpp b/src/script/bridge/qscriptdeclarativeclass.cpp
index acfb2a4..0f450ca 100644
--- a/src/script/bridge/qscriptdeclarativeclass.cpp
+++ b/src/script/bridge/qscriptdeclarativeclass.cpp
@@ -70,9 +70,12 @@ QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, uint value)
new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
}
-QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, bool value)
+QScriptDeclarativeClass::Value::Value(QScriptContext *, bool value)
{
- new (this) JSC::JSValue(QScriptEnginePrivate::frameForContext(ctxt), value);
+ if (value)
+ new (this) JSC::JSValue(JSC::JSValue::JSTrue);
+ else
+ new (this) JSC::JSValue(JSC::JSValue::JSFalse);
}
QScriptDeclarativeClass::Value::Value(QScriptContext *ctxt, double value)
@@ -107,7 +110,10 @@ QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, uint value)
QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, bool value)
{
- new (this) JSC::JSValue(QScriptEnginePrivate::get(eng)->currentFrame, value);
+ if (value)
+ new (this) JSC::JSValue(JSC::JSValue::JSTrue);
+ else
+ new (this) JSC::JSValue(JSC::JSValue::JSFalse);
}
QScriptDeclarativeClass::Value::Value(QScriptEngine *eng, double value)
diff --git a/src/sql/drivers/odbc/qsql_odbc.cpp b/src/sql/drivers/odbc/qsql_odbc.cpp
index ee22bc3..6fd1725 100644
--- a/src/sql/drivers/odbc/qsql_odbc.cpp
+++ b/src/sql/drivers/odbc/qsql_odbc.cpp
@@ -124,11 +124,10 @@ class QODBCDriverPrivate
public:
enum DefaultCase{Lower, Mixed, Upper, Sensitive};
QODBCDriverPrivate()
- : hEnv(0), hDbc(0), useSchema(false), disconnectCount(0), isMySqlServer(false),
- isMSSqlServer(false), hasSQLFetchScroll(true), hasMultiResultSets(false),
- isQuoteInitialized(false), quote(QLatin1Char('"'))
+ : hEnv(0), hDbc(0), unicode(false), useSchema(false), disconnectCount(0), isMySqlServer(false),
+ isMSSqlServer(false), isFreeTDSDriver(false), hasSQLFetchScroll(true),
+ hasMultiResultSets(false), isQuoteInitialized(false), quote(QLatin1Char('"'))
{
- unicode = false;
}
SQLHANDLE hEnv;
@@ -139,6 +138,7 @@ public:
int disconnectCount;
bool isMySqlServer;
bool isMSSqlServer;
+ bool isFreeTDSDriver;
bool hasSQLFetchScroll;
bool hasMultiResultSets;
@@ -165,7 +165,10 @@ public:
QODBCPrivate(QODBCDriverPrivate *dpp)
: hStmt(0), useSchema(false), hasSQLFetchScroll(true), driverPrivate(dpp), userForwardOnly(false)
{
- unicode = false;
+ unicode = dpp->unicode;
+ useSchema = dpp->useSchema;
+ disconnectCount = dpp->disconnectCount;
+ hasSQLFetchScroll = dpp->hasSQLFetchScroll;
}
inline void clearValues()
@@ -340,7 +343,9 @@ static QVariant::Type qDecodeODBCType(SQLSMALLINT sqltype, const T* p, bool isSi
break;
case SQL_CHAR:
case SQL_VARCHAR:
+#if (ODBCVER >= 0x0350)
case SQL_GUID:
+#endif
case SQL_LONGVARCHAR:
type = QVariant::String;
break;
@@ -365,44 +370,88 @@ static QString qGetStringData(SQLHANDLE hStmt, int column, int colSize, bool uni
} else {
colSize++; // make sure there is room for more than the 0 termination
}
- r = SQLGetData(hStmt,
- column+1,
- SQL_C_TCHAR,
- NULL,
- 0,
- &lengthIndicator);
- if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
- colSize = lengthIndicator/sizeof(SQLTCHAR) + 1;
- QVarLengthArray<SQLTCHAR> buf(colSize);
- while (true) {
+ if(unicode) {
r = SQLGetData(hStmt,
column+1,
SQL_C_TCHAR,
- (SQLPOINTER)buf.data(),
- colSize*sizeof(SQLTCHAR),
+ NULL,
+ 0,
&lengthIndicator);
- if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
- if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator/sizeof(SQLTCHAR) + 1;
+ QVarLengthArray<SQLTCHAR> buf(colSize);
+ memset(buf.data(), 0, colSize*sizeof(SQLTCHAR));
+ while (true) {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_TCHAR,
+ (SQLPOINTER)buf.data(),
+ colSize*sizeof(SQLTCHAR),
+ &lengthIndicator);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ fieldVal.clear();
+ break;
+ }
+ // if SQL_SUCCESS_WITH_INFO is returned, indicating that
+ // more data can be fetched, the length indicator does NOT
+ // contain the number of bytes returned - it contains the
+ // total number of bytes that CAN be fetched
+ // colSize-1: remove 0 termination when there is more data to fetch
+ int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR);
+ fieldVal += fromSQLTCHAR(buf, rSize);
+ if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) {
+ // workaround for Drivermanagers that don't return SQL_NO_DATA
+ break;
+ }
+ } else if (r == SQL_NO_DATA) {
+ break;
+ } else {
+ qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
fieldVal.clear();
break;
}
- // if SQL_SUCCESS_WITH_INFO is returned, indicating that
- // more data can be fetched, the length indicator does NOT
- // contain the number of bytes returned - it contains the
- // total number of bytes that CAN be fetched
- // colSize-1: remove 0 termination when there is more data to fetch
- int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator/sizeof(SQLTCHAR);
- fieldVal += fromSQLTCHAR(buf, rSize);
- if (lengthIndicator < (unsigned int)colSize*sizeof(SQLTCHAR)) {
- // workaround for Drivermanagers that don't return SQL_NO_DATA
+ }
+ } else {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_CHAR,
+ NULL,
+ 0,
+ &lengthIndicator);
+ if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && lengthIndicator > 0)
+ colSize = lengthIndicator + 1;
+ QVarLengthArray<SQLCHAR> buf(colSize);
+ while (true) {
+ r = SQLGetData(hStmt,
+ column+1,
+ SQL_C_CHAR,
+ (SQLPOINTER)buf.data(),
+ colSize,
+ &lengthIndicator);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ if (lengthIndicator == SQL_NULL_DATA || lengthIndicator == SQL_NO_TOTAL) {
+ fieldVal.clear();
+ break;
+ }
+ // if SQL_SUCCESS_WITH_INFO is returned, indicating that
+ // more data can be fetched, the length indicator does NOT
+ // contain the number of bytes returned - it contains the
+ // total number of bytes that CAN be fetched
+ // colSize-1: remove 0 termination when there is more data to fetch
+ int rSize = (r == SQL_SUCCESS_WITH_INFO) ? colSize : lengthIndicator;
+ fieldVal += QString::fromUtf8((const char *)buf.constData(), rSize);
+ if (lengthIndicator < (unsigned int)colSize) {
+ // workaround for Drivermanagers that don't return SQL_NO_DATA
+ break;
+ }
+ } else if (r == SQL_NO_DATA) {
+ break;
+ } else {
+ qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
+ fieldVal.clear();
break;
}
- } else if (r == SQL_NO_DATA) {
- break;
- } else {
- qWarning() << "qGetStringData: Error while fetching data (" << qWarnODBCHandle(SQL_HANDLE_STMT, hStmt) << ')';
- fieldVal.clear();
- break;
}
}
return fieldVal;
@@ -847,10 +896,6 @@ QODBCResult::QODBCResult(const QODBCDriver * db, QODBCDriverPrivate* p)
: QSqlResult(db)
{
d = new QODBCPrivate(p);
- d->unicode = p->unicode;
- d->useSchema = p->useSchema;
- d->disconnectCount = p->disconnectCount;
- d->hasSQLFetchScroll = p->hasSQLFetchScroll;
}
QODBCResult::~QODBCResult()
@@ -1825,6 +1870,7 @@ bool QODBCDriver::open(const QString & db,
SQLSMALLINT cb;
QVarLengthArray<SQLTCHAR> connOut(1024);
+ memset(connOut.data(), 0, connOut.size() * sizeof(SQLTCHAR));
r = SQLDriverConnect(d->hDbc,
NULL,
#ifdef UNICODE
@@ -1917,6 +1963,7 @@ void QODBCDriverPrivate::checkUnicode()
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WCHAR)) {
unicode = true;
+ return;
}
r = SQLGetInfo(hDbc,
@@ -1926,6 +1973,7 @@ void QODBCDriverPrivate::checkUnicode()
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WVARCHAR)) {
unicode = true;
+ return;
}
r = SQLGetInfo(hDbc,
@@ -1935,7 +1983,25 @@ void QODBCDriverPrivate::checkUnicode()
NULL);
if ((r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) && (fFunc & SQL_CVT_WLONGVARCHAR)) {
unicode = true;
+ return;
+ }
+ SQLHANDLE hStmt;
+ r = SQLAllocHandle(SQL_HANDLE_STMT,
+ hDbc,
+ &hStmt);
+
+ r = SQLExecDirect(hStmt, toSQLTCHAR(QLatin1String("select 'test'")).data(), SQL_NTS);
+ if(r == SQL_SUCCESS) {
+ r = SQLFetch(hStmt);
+ if(r == SQL_SUCCESS) {
+ QVarLengthArray<SQLWCHAR> buffer(10);
+ r = SQLGetData(hStmt, 1, SQL_C_WCHAR, buffer.data(), buffer.size() * sizeof(SQLWCHAR), NULL);
+ if(r == SQL_SUCCESS && fromSQLTCHAR(buffer) == QLatin1String("test")) {
+ unicode = true;
+ }
+ }
}
+ r = SQLFreeHandle(SQL_HANDLE_STMT, hStmt);
}
bool QODBCDriverPrivate::checkDriver() const
@@ -2027,6 +2093,21 @@ void QODBCDriverPrivate::checkSqlServer()
isMySqlServer = serverType.contains(QLatin1String("mysql"), Qt::CaseInsensitive);
isMSSqlServer = serverType.contains(QLatin1String("Microsoft SQL Server"), Qt::CaseInsensitive);
}
+ r = SQLGetInfo(hDbc,
+ SQL_DRIVER_NAME,
+ serverString.data(),
+ serverString.size() * sizeof(SQLTCHAR),
+ &t);
+ if (r == SQL_SUCCESS || r == SQL_SUCCESS_WITH_INFO) {
+ QString serverType;
+#ifdef UNICODE
+ serverType = fromSQLTCHAR(serverString, t/sizeof(SQLTCHAR));
+#else
+ serverType = QString::fromUtf8((const char *)serverString.constData(), t);
+#endif
+ isFreeTDSDriver = serverType.contains(QLatin1String("tdsodbc"), Qt::CaseInsensitive);
+ unicode = isFreeTDSDriver == false;
+ }
}
void QODBCDriverPrivate::checkHasSQLFetchScroll()
diff --git a/src/xmlpatterns/api/qxmlresultitems.cpp b/src/xmlpatterns/api/qxmlresultitems.cpp
index c474082..98c5bdc 100644
--- a/src/xmlpatterns/api/qxmlresultitems.cpp
+++ b/src/xmlpatterns/api/qxmlresultitems.cpp
@@ -70,6 +70,10 @@ QT_BEGIN_NAMESPACE
sequence and returns it, and current() always returns the QXmlItem
that next() returned the last time it was called.
+ \note When using the QXmlResultItems overload of QXmlQuery::evaluateTo()
+ to execute a query, it is advisable to create a new instance of this
+ class for each new set of results rather than reusing an old instance.
+
\sa QXmlItem::isNode(), QXmlItem::isAtomicValue(), QXmlNodeModelIndex
*/