diff options
120 files changed, 3687 insertions, 1794 deletions
@@ -725,6 +725,7 @@ CFG_DBUS=auto CFG_GLIB=auto CFG_GSTREAMER=auto CFG_QGTKSTYLE=auto +CFG_QS60STYLE=auto CFG_LARGEFILE=yes CFG_OPENSSL=auto CFG_PTMALLOC=no @@ -1798,6 +1799,13 @@ while [ "$#" -gt 0 ]; do UNKNOWN_OPT=yes fi ;; + style-s60) + if [ "$VAL" = "qt" ] || [ "$VAL" = "no" ]; then + CFG_QS60STYLE="$VAL" + else + UNKNOWN_OPT=yes + fi + ;; qdbus|dbus) if [ "$VAL" = "yes" ] || [ "$VAL" = "no" ] || [ "$VAL" = "linked" ]; then CFG_DBUS="$VAL" @@ -3353,7 +3361,6 @@ Usage: $relconf [-h] [-prefix <dir>] [-prefix-install] [-bindir <dir>] [-libdir [-no-openssl] [-openssl] [-openssl-linked] [-no-gtkstyle] [-gtkstyle] [-no-svg] [-svg] [-no-webkit] [-webkit] [-no-javascript-jit] [-javascript-jit] [-no-script] [-script] [-no-scripttools] [-scripttools] [-no-declarative] [-declarative] - [-no-s60] [-s60] [-no-usedeffiles] [-usedeffiles] [additional platform specific options (see below)] @@ -3537,11 +3544,6 @@ EOF fi cat << EOF - -no-s60 ............ Do not compile in S60 support. - + -s60 ............... Compile with support for the S60 UI Framework. - -no-usedeffiles .... Disable the usage of DEF files. - * -usedeffiles ....... Enable the usage of DEF files. - -no-mmx ............ Do not compile with use of MMX instructions. -no-3dnow .......... Do not compile with use of 3DNOW instructions. -no-sse ............ Do not compile with use of SSE instructions. @@ -3992,6 +3994,20 @@ if [ "$PLATFORM_QWS" = "yes" -o "$PLATFORM_X11" = "yes" ]; then EOF fi +if echo "$XPLATFORM" | grep symbian > /dev/null ; then + cat << EOF + +Qt for Symbian only: + -no-s60 ............ Do not compile in S60 support. + + -s60 ............... Compile with support for the S60 UI Framework. + -no-style-s60....... Disable s60 style + + -qt-style-s60....... Enable s60 style in the Qt Library + + -no-usedeffiles .... Disable the usage of DEF files. + * -usedeffiles ....... Enable the usage of DEF files. +EOF +fi + [ "x$ERROR" = "xyes" ] && exit 1 exit 0 fi # Help @@ -4005,6 +4021,8 @@ if [ "$PLATFORM_QWS" = "yes" ]; then Platform="Qt for Embedded Linux" elif [ "$PLATFORM_MAC" = "yes" ]; then Platform="Qt for Mac OS X" +elif echo "$XPLATFORM" | grep "symbian" > /dev/null ; then + Platform="Qt for Symbian" elif [ '!' -z "`getQMakeConf \"$XQMAKESPEC\" | grep QMAKE_LIBS_X11 | awk '{print $3;}'`" ]; then PLATFORM_X11=yes Platform="Qt for Linux/X11" @@ -4630,15 +4648,23 @@ if [ "$CFG_ZLIB" = "auto" ]; then fi if [ "$CFG_S60" = "auto" ]; then - if echo "$XQMAKESPEC" | grep symbian > /dev/null; then + if echo "$XPLATFORM" | grep symbian > /dev/null; then CFG_S60=yes else CFG_S60=no fi fi +if [ "$CFG_QS60STYLE" = "auto" ]; then + if echo "$XPLATFORM" | grep symbian > /dev/null; then + CFG_QS60STYLE=qt + else + CFG_QS60STYLE=no + fi +fi + if [ "$CFG_SYMBIAN_DEFFILES" = "auto" ]; then - if echo "$XQMAKESPEC" | grep symbian > /dev/null && [ "$CFG_DEV" = "no" ]; then + if echo "$XPLATFORM" | grep symbian > /dev/null && [ "$CFG_DEV" = "no" ]; then CFG_SYMBIAN_DEFFILES=yes else CFG_SYMBIAN_DEFFILES=no @@ -5671,6 +5697,8 @@ fi if [ "$CFG_ENDIAN" = "auto" ]; then if [ "$PLATFORM_MAC" = "yes" ]; then true #leave as auto + elif [ "$XPLATFORM" = "symbian-sbsv2" ]; then + CFG_ENDIAN="Q_LITTLE_ENDIAN" else "$unixtests/endian.test" "$XQMAKESPEC" $OPT_VERBOSE "$relpath" "$outpath" F="$?" @@ -5756,7 +5784,7 @@ if [ "$CFG_DOUBLEFORMAT" = "auto" ]; then fi HAVE_STL=no -if echo "$XQMAKESPEC" | grep symbian > /dev/null || "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stl "STL" $L_FLAGS $I_FLAGS $l_FLAGS; then +if echo "$XPLATFORM" | grep symbian > /dev/null || "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/unix/stl "STL" $L_FLAGS $I_FLAGS $l_FLAGS; then HAVE_STL=yes fi @@ -5910,7 +5938,7 @@ if [ "$CFG_OPENSSL" != "no" ]; then fi # detect OpenVG support -if [ "$CFG_OPENVG" != "no" ]; then +if [ "$CFG_OPENVG" != "no" ] && [ "$XPLATFORM" != "symbian-sbsv2" ]; then if "$unixtests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" "config.tests/unix/openvg" "OpenVG" $L_FLAGS $I_FLAGS $l_FLAGS $CONFIG_ARG; then if [ "$CFG_OPENVG" = "auto" ]; then CFG_OPENVG=yes @@ -5994,7 +6022,7 @@ elif [ "$CFG_JAVASCRIPTCORE_JIT" = "no" ]; then fi if [ "$CFG_AUDIO_BACKEND" = "auto" ]; then - if echo "$XQMAKESPEC" | grep symbian > /dev/null 2>&1; then + if echo "$XPLATFORM" | grep symbian > /dev/null 2>&1; then "$symbiantests/compile.test" "$XQMAKESPEC" "$QMAKE_CONFIG" $OPT_VERBOSE "$relpath" "$outpath" config.tests/symbian/audio "audio" $L_FLAGS $I_FLAGS $l_FLAGS else CFG_AUDIO_BACKEND=yes @@ -6172,6 +6200,12 @@ else fi fi +if [ "$CFG_QS60STYLE" = "no" ]; then + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_NO_STYLE_S60" +else + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_STYLE_S60" +fi + # Disable OpenGL on Symbian. case "$XPLATFORM" in symbian*) diff --git a/demos/embedded/fluidlauncher/fluidlauncher.pro b/demos/embedded/fluidlauncher/fluidlauncher.pro index b2916d7..13274c3 100644 --- a/demos/embedded/fluidlauncher/fluidlauncher.pro +++ b/demos/embedded/fluidlauncher/fluidlauncher.pro @@ -180,10 +180,12 @@ symbian { mifs.sources += \ $$appResourceDir(demos/embedded/anomaly/anomaly.mif) - # Since Fluidlauncher itself doesn't link webkit, we won't get dependency automatically - executables.pkg_prerules += \ - "; Dependency to Qt Webkit" \ - "(0x200267C2), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"QtWebKit\"}" + isEmpty(QT_LIBINFIX) { + # Since Fluidlauncher itself doesn't link webkit, we won't get dependency automatically + executables.pkg_prerules += \ + "; Dependency to Qt Webkit" \ + "(0x200267C2), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"QtWebKit\"}" + } } contains(QT_CONFIG, phonon) { diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index 4dd81b0..090f3b6 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -71,12 +71,16 @@ QMAKE_LIBS_GUI = $$QMAKE_LIBS_CORE -lfbscli -lbitgdi -lhal -lgdi -lws32 QMAKE_LIBS_NETWORK = QMAKE_LIBS_EGL = -llibEGL QMAKE_LIBS_OPENGL = -QMAKE_LIBS_OPENVG = -llibOpenVG -lgraphicsresource -lfbscli -lbitgdi -lgdi +QMAKE_LIBS_OPENVG = -llibOpenVG -lfbscli -lbitgdi -lgdi QMAKE_LIBS_THREAD = -llibpthread QMAKE_LIBS_COMPAT = QMAKE_LIBS_QT_ENTRY = -llibcrt0.lib QMAKE_LIBS_S60 = -lavkon +exists($${EPOCROOT}epoc32/include/platform/sgresource/sgimage.h) { + QMAKE_LIBS_OPENVG += -lsgresource +} + contains(QMAKE_HOST.os,Windows) { QMAKE_COPY = copy /y QMAKE_COPY_DIR = xcopy /s /q /y /i diff --git a/mkspecs/features/symbian/application_icon.prf b/mkspecs/features/symbian/application_icon.prf index 1109060..9979f40 100644 --- a/mkspecs/features/symbian/application_icon.prf +++ b/mkspecs/features/symbian/application_icon.prf @@ -31,9 +31,9 @@ contains( CONFIG, no_icon ) { # Note: symbian-sbsv2 builds can't utilize extra compiler for mifconv, so ICON handling is done in code !symbian-sbsv2 { + !contains(ICON, "^(/|\\\\|.:).*"):ICON = $$_PRO_FILE_PWD_/$$ICON #absolute path #Makefile: requires paths with backslash ICON_backslashed = $$ICON - contains(QMAKE_HOST.os, "Windows"):ICON_backslashed = $$replace( ICON_backslashed, /, \\) symbian-abld { mifIconZDir = ${ZDIR}$$APP_RESOURCE_DIR @@ -47,9 +47,14 @@ contains( CONFIG, no_icon ) { # Extra compiler rules for mifconv mifconv.target = $$mifIconZDir/$${baseTarget}.mif + contains(QMAKE_HOST.os, "Windows") { + ICON_backslashed = $$replace(ICON_backslashed, /, \\) + mifconv.target = $$replace(mifconv.target, /, \\) + } # Based on: http://www.forum.nokia.com/document/Cpp_Developers_Library # svg-t icons should always use /c32 depth mifconv.commands = mifconv $$mifconv.target /c32 $$ICON_backslashed + mifconv.depends = $$ICON PRE_TARGETDEPS += $$mifconv.target QMAKE_EXTRA_TARGETS += mifconv diff --git a/mkspecs/features/symbian/data_caging_paths.prf b/mkspecs/features/symbian/data_caging_paths.prf index 3ed5661..6f40bb5 100644 --- a/mkspecs/features/symbian/data_caging_paths.prf +++ b/mkspecs/features/symbian/data_caging_paths.prf @@ -74,7 +74,7 @@ exists($${EPOCROOT}epoc32/include/data_caging_paths.prf) { BOOTDATA_DIR = /resource/bootdata } -isEmpty(QT_PLUGINS_BASE_DIR): QT_PLUGINS_BASE_DIR = /$$RESOURCE_FILES_DIR/qt/plugins +isEmpty(QT_PLUGINS_BASE_DIR): QT_PLUGINS_BASE_DIR = /$$RESOURCE_FILES_DIR/qt$${QT_LIBINFIX}/plugins isEmpty(HW_ZDIR): HW_ZDIR = epoc32/data/z isEmpty(REG_RESOURCE_DIR): REG_RESOURCE_DIR = /private/10003a3f/apps isEmpty(REG_RESOURCE_IMPORT_DIR): REG_RESOURCE_IMPORT_DIR = /private/10003a3f/import/apps
\ No newline at end of file diff --git a/mkspecs/features/symbian/default_post.prf b/mkspecs/features/symbian/default_post.prf index d29e460..0564e9b 100644 --- a/mkspecs/features/symbian/default_post.prf +++ b/mkspecs/features/symbian/default_post.prf @@ -5,7 +5,7 @@ contains(TEMPLATE, ".*app") { QMAKE_LIBS += } else:contains(QT, gui):contains(CONFIG,qt) { S60MAIN_LIBS = -leuser - QMAKE_LIBS += -lqtmain.lib $$S60MAIN_LIBS + QMAKE_LIBS += -lqtmain$${QT_LIBINFIX}.lib $$S60MAIN_LIBS } else { QMAKE_LIBS += $$QMAKE_LIBS_QT_ENTRY } diff --git a/mkspecs/features/symbian/qt.prf b/mkspecs/features/symbian/qt.prf index 294a68c..0d2e6eb 100644 --- a/mkspecs/features/symbian/qt.prf +++ b/mkspecs/features/symbian/qt.prf @@ -24,7 +24,7 @@ INCLUDEPATH = $$PREPEND_INCLUDEPATH $$INCLUDEPATH # Add dependency to Qt package to all other projects besides Qt libs. # Note: Qt libs with full capabilities has UID3 of 0x2001E61C, # while self-signed version typically has temporary UID3 of 0xE001E61C. -contains(CONFIG, qt):!contains(TARGET.UID3, 0x2001E61C):!contains(TARGET.UID3, 0xE001E61C) { +contains(CONFIG, qt):!contains(TARGET.UID3, 0x2001E61C):!contains(TARGET.UID3, 0xE001E61C):isEmpty(QT_LIBINFIX) { default_deployment.pkg_prerules += \ "; Default dependency to Qt libraries" \ "(0x2001E61C), $${QT_MAJOR_VERSION}, $${QT_MINOR_VERSION}, $${QT_PATCH_VERSION}, {\"Qt\"}" @@ -43,5 +43,5 @@ isEmpty(TARGET.EPOCHEAPSIZE):TARGET.EPOCHEAPSIZE = 0x020000 0x800000 # Workaround for the fact that Gnupoc and Symbian chose different approaches to # the letter casing of headers. contains(CONFIG, is_using_gnupoc) { - INCLUDEPATH += $$QT_SOURCE_TREE/mkspecs/common/symbian/header-wrappers + INCLUDEPATH += $$QMAKESPEC/../../common/symbian/header-wrappers } diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h index 5fb7fe3..5b655e8 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Threading.h @@ -75,7 +75,7 @@ #include <libkern/OSAtomic.h> #elif OS(ANDROID) #include <cutils/atomic.h> -#elif COMPILER(GCC) && !PLATFORM(SYMBIAN) +#elif COMPILER(GCC) && !defined(__SYMBIAN32__) #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) #include <ext/atomicity.h> #else @@ -239,7 +239,7 @@ inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Bar inline int atomicIncrement(int volatile* addend) { return android_atomic_inc(addend); } inline int atomicDecrement(int volatile* addend) { return android_atomic_dec(addend); } -#elif COMPILER(GCC) && !PLATFORM(SPARC64) && !PLATFORM(SYMBIAN) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc +#elif COMPILER(GCC) && !PLATFORM(SPARC64) && !defined(__SYMBIAN32__) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp index 132eb79..6cfeb76 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp @@ -20,7 +20,6 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "abstractaudioeffect.h" #include "audioplayer.h" -#include "mmf_videoplayer.h" QT_BEGIN_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.h b/src/3rdparty/phonon/mmf/abstractaudioeffect.h index 436e8e4..d71993b 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.h +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.h @@ -28,7 +28,6 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "audioplayer.h" #include "effectparameter.h" #include "mmf_medianode.h" -#include "mmf_videoplayer.h" class CMdaAudioOutputStream; diff --git a/src/3rdparty/phonon/mmf/abstractplayer.cpp b/src/3rdparty/phonon/mmf/abstractplayer.cpp index 53973eb..421155b 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.cpp +++ b/src/3rdparty/phonon/mmf/abstractplayer.cpp @@ -96,7 +96,7 @@ void MMF::AbstractPlayer::volumeChanged(qreal volume) // Video output //----------------------------------------------------------------------------- -void MMF::AbstractPlayer::setVideoOutput(VideoOutput* videoOutput) +void MMF::AbstractPlayer::setVideoOutput(AbstractVideoOutput* videoOutput) { m_videoOutput = videoOutput; videoOutputChanged(); diff --git a/src/3rdparty/phonon/mmf/abstractplayer.h b/src/3rdparty/phonon/mmf/abstractplayer.h index cec5568..92bd87e 100644 --- a/src/3rdparty/phonon/mmf/abstractplayer.h +++ b/src/3rdparty/phonon/mmf/abstractplayer.h @@ -24,7 +24,7 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <QObject> -#include "videooutput.h" +#include "abstractvideooutput.h" class RFile; @@ -34,7 +34,6 @@ namespace Phonon { namespace MMF { -class VideoOutput; /** * @short Interface which abstracts from MediaObject the current @@ -79,7 +78,7 @@ public: virtual void volumeChanged(qreal volume); - void setVideoOutput(VideoOutput* videoOutput); + void setVideoOutput(AbstractVideoOutput *videoOutput); /** * Records error message and changes state to ErrorState @@ -156,7 +155,7 @@ private: protected: // Not owned - VideoOutput* m_videoOutput; + AbstractVideoOutput* m_videoOutput; qreal m_volume; diff --git a/src/3rdparty/phonon/mmf/abstractvideooutput.cpp b/src/3rdparty/phonon/mmf/abstractvideooutput.cpp new file mode 100644 index 0000000..3fe66fc --- /dev/null +++ b/src/3rdparty/phonon/mmf/abstractvideooutput.cpp @@ -0,0 +1,177 @@ +/* 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 "abstractvideooutput.h" +#include "utils.h" + +#ifndef QT_NO_DEBUG +#include "objectdump.h" +#endif + +#include <QtCore/private/qcore_symbian_p.h> // for qt_TSize2QSize + +#include <QMoveEvent> +#include <QResizeEvent> + +#include <coecntrl.h> + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +/*! \class MMF::AbstractVideoOutput + \internal +*/ + +//----------------------------------------------------------------------------- +// Constants +//----------------------------------------------------------------------------- + +static const Phonon::VideoWidget::AspectRatio DefaultAspectRatio = + Phonon::VideoWidget::AspectRatioAuto; +static const Phonon::VideoWidget::ScaleMode DefaultScaleMode = + Phonon::VideoWidget::FitInView; + + +//----------------------------------------------------------------------------- +// Constructor / destructor +//----------------------------------------------------------------------------- + +MMF::AbstractVideoOutput::AbstractVideoOutput(QWidget *parent) + : QWidget(parent) + , m_aspectRatio(DefaultAspectRatio) + , m_scaleMode(DefaultScaleMode) +{ + +} + +MMF::AbstractVideoOutput::~AbstractVideoOutput() +{ + +} + +void MMF::AbstractVideoOutput::setVideoSize(const QSize &frameSize) +{ + TRACE_CONTEXT(AbstractVideoOutput::setVideoSize, EVideoInternal); + TRACE("oldSize %d %d newSize %d %d", + m_videoFrameSize.width(), m_videoFrameSize.height(), + frameSize.width(), frameSize.height()); + + if (frameSize != m_videoFrameSize) { + m_videoFrameSize = frameSize; + updateGeometry(); + } +} + + +//----------------------------------------------------------------------------- +// QWidget +//----------------------------------------------------------------------------- + +QSize MMF::AbstractVideoOutput::sizeHint() const +{ + // TODO: replace this with a more sensible default + QSize result(320, 240); + + if (!m_videoFrameSize.isNull()) + result = m_videoFrameSize; + + return result; +} + + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + +RWindowBase* MMF::AbstractVideoOutput::videoWindow() const +{ + CCoeControl *control = internalWinId(); + if (!control) + control = effectiveWinId(); + + RWindowBase *window = 0; + if (control) + window = control->DrawableWindow(); + + return window; +} + +QSize MMF::AbstractVideoOutput::videoWindowSize() const +{ + QSize result; + if (RWindowBase *const window = videoWindow()) + result = qt_TSize2QSize(window->Size()); + return result; +} + +Phonon::VideoWidget::AspectRatio MMF::AbstractVideoOutput::aspectRatio() const +{ + return m_aspectRatio; +} + +void MMF::AbstractVideoOutput::setAspectRatio + (Phonon::VideoWidget::AspectRatio aspectRatio) +{ + if (m_aspectRatio != aspectRatio) { + m_aspectRatio = aspectRatio; + emit aspectRatioChanged(); + } +} + +Phonon::VideoWidget::ScaleMode MMF::AbstractVideoOutput::scaleMode() const +{ + return m_scaleMode; +} + +void MMF::AbstractVideoOutput::setScaleMode + (Phonon::VideoWidget::ScaleMode scaleMode) +{ + if (m_scaleMode != scaleMode) { + m_scaleMode = scaleMode; + emit scaleModeChanged(); + } +} + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +void MMF::AbstractVideoOutput::dump() const +{ +#ifndef QT_NO_DEBUG + TRACE_CONTEXT(AbstractVideoOutput::dump, EVideoInternal); + + QScopedPointer<ObjectDump::QVisitor> visitor(new ObjectDump::QVisitor); + visitor->setPrefix("Phonon::MMF"); // to aid searchability of logs + ObjectDump::addDefaultAnnotators(*visitor); + TRACE("Dumping tree from leaf 0x%08x:", this); + ObjectDump::dumpTreeFromLeaf(*this, *visitor); + + QScopedPointer<ObjectDump::QDumper> dumper(new ObjectDump::QDumper); + dumper->setPrefix("Phonon::MMF"); // to aid searchability of logs + ObjectDump::addDefaultAnnotators(*dumper); + TRACE_0("Dumping AbstractVideoOutput:"); + dumper->dumpObject(*this); +#endif +} + +QT_END_NAMESPACE + diff --git a/src/3rdparty/phonon/mmf/videooutput.h b/src/3rdparty/phonon/mmf/abstractvideooutput.h index 3e9c036..61bcd0f 100644 --- a/src/3rdparty/phonon/mmf/videooutput.h +++ b/src/3rdparty/phonon/mmf/abstractvideooutput.h @@ -16,14 +16,15 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. */ -#ifndef PHONON_MMF_VIDEOOUTPUT_H -#define PHONON_MMF_VIDEOOUTPUT_H +#ifndef PHONON_MMF_ABSTRACTVIDEOOUTPUT_H +#define PHONON_MMF_ABSTRACTVIDEOOUTPUT_H #include <QtGui/QWidget> #include <QVector> #include <QRect> #include "defs.h" +#include <phonon/abstractvideooutput.h> #include <phonon/videowidget.h> #include <e32std.h> @@ -35,21 +36,25 @@ namespace Phonon { namespace MMF { -class AncestorMoveMonitor; -class VideoOutput : public QWidget +/** + * @short ABC for widget on which video is displayed + * + * @see DsaVideoOutput, SurfaceVideoOutput + */ +class AbstractVideoOutput + : public QWidget { Q_OBJECT public: - VideoOutput(AncestorMoveMonitor* ancestorMoveMonitor, QWidget* parent); - ~VideoOutput(); + ~AbstractVideoOutput(); // Set size of video frame. Called by VideoPlayer. - void setVideoSize(const QSize& size); + void setVideoSize(const QSize &size); - RWindowBase* videoWindow(); - const QRect& videoWindowRect() const; + RWindowBase* videoWindow() const; + QSize videoWindowSize() const; Phonon::VideoWidget::AspectRatio aspectRatio() const; void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio); @@ -57,41 +62,24 @@ public: Phonon::VideoWidget::ScaleMode scaleMode() const; void setScaleMode(Phonon::VideoWidget::ScaleMode scaleMode); - // Called by AncestorMoveMonitor - void ancestorMoved(); - // Debugging output void dump() const; -public Q_SLOTS: - void beginNativePaintEvent(const QRect& /*controlRect*/); - void endNativePaintEvent(const QRect& /*controlRect*/); - Q_SIGNALS: void videoWindowChanged(); void aspectRatioChanged(); void scaleModeChanged(); - void beginVideoWindowNativePaint(); - void endVideoWindowNativePaint(); protected: - // Override QWidget functions - QSize sizeHint() const; - void paintEvent(QPaintEvent* event); - void resizeEvent(QResizeEvent* event); - void moveEvent(QMoveEvent* event); - bool event(QEvent* event); + AbstractVideoOutput(QWidget *parent); private: - void getVideoWindowRect(); - void registerForAncestorMoved(); + // QWidget + QSize sizeHint() const; private: - // Not owned - AncestorMoveMonitor* m_ancestorMoveMonitor; - + // Dimensions of the video clip QSize m_videoFrameSize; - QRect m_videoWindowRect; Phonon::VideoWidget::AspectRatio m_aspectRatio; Phonon::VideoWidget::ScaleMode m_scaleMode; diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp new file mode 100644 index 0000000..8cb9db5 --- /dev/null +++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.cpp @@ -0,0 +1,490 @@ +/* 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 <QUrl> +#include <QTimer> +#include <QWidget> + +#include <coemain.h> // for CCoeEnv + +#include "abstractvideoplayer.h" +#include "utils.h" + +#ifndef QT_NO_DEBUG +#include "objectdump.h" +#endif + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +/*! \class MMF::AbstractVideoPlayer + \internal +*/ + +//----------------------------------------------------------------------------- +// Constructor / destructor +//----------------------------------------------------------------------------- + +MMF::AbstractVideoPlayer::AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player) + : AbstractMediaPlayer(parent, player) + , m_wsSession(CCoeEnv::Static()->WsSession()) + , m_screenDevice(*CCoeEnv::Static()->ScreenDevice()) + , m_window(0) + , m_scaleWidth(1.0) + , m_scaleHeight(1.0) + , m_totalTime(0) +{ + +} + +void MMF::AbstractVideoPlayer::construct() +{ + TRACE_CONTEXT(AbstractVideoPlayer::AbstractVideoPlayer, EVideoApi); + TRACE_ENTRY_0(); + + if (m_videoOutput) { + initVideoOutput(); + m_window = m_videoOutput->videoWindow(); + } + + createPlayer(); + + TRACE_EXIT_0(); +} + +MMF::AbstractVideoPlayer::~AbstractVideoPlayer() +{ + TRACE_CONTEXT(AbstractVideoPlayer::~AbstractVideoPlayer, EVideoApi); + TRACE_ENTRY_0(); + + // QObject destructor removes all signal-slot connections involving this + // object, so we do not need to disconnect from m_videoOutput here. + + TRACE_EXIT_0(); +} + +CVideoPlayerUtility* MMF::AbstractVideoPlayer::nativePlayer() const +{ + return m_player.data(); +} + +//----------------------------------------------------------------------------- +// Public API +//----------------------------------------------------------------------------- + +void MMF::AbstractVideoPlayer::doPlay() +{ + TRACE_CONTEXT(AbstractVideoPlayer::doPlay, EVideoApi); + + handlePendingParametersChanged(); + + m_player->Play(); +} + +void MMF::AbstractVideoPlayer::doPause() +{ + TRACE_CONTEXT(AbstractVideoPlayer::doPause, EVideoApi); + + TRAPD(err, m_player->PauseL()); + if (KErrNone != err && state() != ErrorState) { + TRACE("PauseL error %d", err); + setError(tr("Pause failed"), err); + } +} + +void MMF::AbstractVideoPlayer::doStop() +{ + m_player->Stop(); +} + +void MMF::AbstractVideoPlayer::doSeek(qint64 ms) +{ + TRACE_CONTEXT(AbstractVideoPlayer::doSeek, EVideoApi); + + TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000))); + + if (KErrNone != err) + setError(tr("Seek failed"), err); +} + +int MMF::AbstractVideoPlayer::setDeviceVolume(int mmfVolume) +{ + TRAPD(err, m_player->SetVolumeL(mmfVolume)); + return err; +} + +int MMF::AbstractVideoPlayer::openFile(RFile &file) +{ + TRAPD(err, m_player->OpenFileL(file)); + return err; +} + +int MMF::AbstractVideoPlayer::openUrl(const QString &url) +{ + TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url))); + return err; +} + +int MMF::AbstractVideoPlayer::bufferStatus() const +{ + int result = 0; + TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result)); + return result; +} + +void MMF::AbstractVideoPlayer::close() +{ + m_player->Close(); +} + +bool MMF::AbstractVideoPlayer::hasVideo() const +{ + return true; +} + +qint64 MMF::AbstractVideoPlayer::currentTime() const +{ + TRACE_CONTEXT(AbstractVideoPlayer::currentTime, EVideoApi); + + TTimeIntervalMicroSeconds us; + TRAPD(err, us = m_player->PositionL()) + + qint64 result = 0; + + if (KErrNone == err) { + result = toMilliSeconds(us); + } else { + TRACE("PositionL error %d", err); + + // If we don't cast away constness here, we simply have to ignore + // the error. + const_cast<AbstractVideoPlayer*>(this)->setError(tr("Getting position failed"), err); + } + + return result; +} + +qint64 MMF::AbstractVideoPlayer::totalTime() const +{ + return m_totalTime; +} + + +//----------------------------------------------------------------------------- +// Public slots +//----------------------------------------------------------------------------- + +void MMF::AbstractVideoPlayer::videoWindowChanged() +{ + TRACE_CONTEXT(AbstractVideoPlayer::videoOutputRegionChanged, EVideoInternal); + TRACE_ENTRY("state %d", state()); + + m_window = m_videoOutput ? m_videoOutput->videoWindow() : 0; + + handleVideoWindowChanged(); + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::aspectRatioChanged() +{ + TRACE_CONTEXT(AbstractVideoPlayer::aspectRatioChanged, EVideoInternal); + TRACE_ENTRY("state %d aspectRatio %d", state()); + + updateScaleFactors(m_videoOutput->videoWindowSize()); + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::scaleModeChanged() +{ + TRACE_CONTEXT(AbstractVideoPlayer::scaleModeChanged, EVideoInternal); + TRACE_ENTRY("state %d", state()); + + updateScaleFactors(m_videoOutput->videoWindowSize()); + + TRACE_EXIT_0(); +} + + +//----------------------------------------------------------------------------- +// MVideoPlayerUtilityObserver callbacks +//----------------------------------------------------------------------------- + +void MMF::AbstractVideoPlayer::MvpuoOpenComplete(TInt aError) +{ + TRACE_CONTEXT(AbstractVideoPlayer::MvpuoOpenComplete, EVideoApi); + TRACE_ENTRY("state %d error %d", state(), aError); + + __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic)); + + if (KErrNone == aError) + m_player->Prepare(); + else + setError(tr("Opening clip failed"), aError); + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::MvpuoPrepareComplete(TInt aError) +{ + TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPrepareComplete, EVideoApi); + TRACE_ENTRY("state %d error %d", state(), aError); + + __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic)); + + TRAPD(err, getVideoClipParametersL(aError)); + + if (KErrNone == err) { + maxVolumeChanged(m_player->MaxVolume()); + + if (m_videoOutput) + m_videoOutput->setVideoSize(m_videoFrameSize); + + prepareCompleted(); + handlePendingParametersChanged(); + + emit totalTimeChanged(totalTime()); + changeState(StoppedState); + } else { + setError(tr("Buffering clip failed"), err); + } + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::getVideoClipParametersL(TInt aError) +{ + User::LeaveIfError(aError); + + // Get frame size + TSize size; + m_player->VideoFrameSizeL(size); + m_videoFrameSize = QSize(size.iWidth, size.iHeight); + + // Get duration + m_totalTime = toMilliSeconds(m_player->DurationL()); +} + + +void MMF::AbstractVideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError) +{ + TRACE_CONTEXT(AbstractVideoPlayer::MvpuoFrameReady, EVideoApi); + TRACE_ENTRY("state %d error %d", state(), aError); + + Q_UNUSED(aFrame); + Q_UNUSED(aError); // suppress warnings in release builds + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::MvpuoPlayComplete(TInt aError) +{ + TRACE_CONTEXT(AbstractVideoPlayer::MvpuoPlayComplete, EVideoApi) + TRACE_ENTRY("state %d error %d", state(), aError); + + // Call base class function which handles end of playback for both + // audio and video clips. + playbackComplete(aError); + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::MvpuoEvent(const TMMFEvent &aEvent) +{ + TRACE_CONTEXT(AbstractVideoPlayer::MvpuoEvent, EVideoApi); + TRACE_ENTRY("state %d", state()); + + Q_UNUSED(aEvent); + + TRACE_EXIT_0(); +} + + +//----------------------------------------------------------------------------- +// MVideoLoadingObserver callbacks +//----------------------------------------------------------------------------- + +void MMF::AbstractVideoPlayer::MvloLoadingStarted() +{ + bufferingStarted(); +} + +void MMF::AbstractVideoPlayer::MvloLoadingComplete() +{ + bufferingComplete(); +} + + +//----------------------------------------------------------------------------- +// Video window updates +//----------------------------------------------------------------------------- + +void MMF::AbstractVideoPlayer::videoOutputChanged() +{ + TRACE_CONTEXT(AbstractVideoPlayer::videoOutputChanged, EVideoInternal); + TRACE_ENTRY_0(); + + if (m_videoOutput) + initVideoOutput(); + + videoWindowChanged(); + + TRACE_EXIT_0(); +} + +void MMF::AbstractVideoPlayer::initVideoOutput() +{ + bool connected = connect( + m_videoOutput, SIGNAL(videoWindowChanged()), + this, SLOT(videoWindowChanged()) + ); + Q_ASSERT(connected); + + connected = connect( + m_videoOutput, SIGNAL(aspectRatioChanged()), + this, SLOT(aspectRatioChanged()) + ); + Q_ASSERT(connected); + + connected = connect( + m_videoOutput, SIGNAL(scaleModeChanged()), + this, SLOT(scaleModeChanged()) + ); + Q_ASSERT(connected); + + // Suppress warnings in release builds + Q_UNUSED(connected); + + // Do these after all connections are complete, to ensure + // that any signals generated get to their destinations. + m_videoOutput->winId(); + m_videoOutput->setVideoSize(m_videoFrameSize); +} + +// Helper function for aspect ratio / scale mode handling +QSize scaleToAspect(const QSize &srcRect, int aspectWidth, int aspectHeight) +{ + const qreal aspectRatio = qreal(aspectWidth) / aspectHeight; + + int width = srcRect.width(); + int height = srcRect.width() / aspectRatio; + if (height > srcRect.height()){ + height = srcRect.height(); + width = srcRect.height() * aspectRatio; + } + return QSize(width, height); +} + +void MMF::AbstractVideoPlayer::updateScaleFactors(const QSize &windowSize, bool apply) +{ + if (m_videoFrameSize.isValid()) { + QRect videoRect; + + // Calculate size of smallest rect which contains video frame size + // and conforms to aspect ratio + switch (m_videoOutput->aspectRatio()) { + case Phonon::VideoWidget::AspectRatioAuto: + videoRect.setSize(m_videoFrameSize); + break; + + case Phonon::VideoWidget::AspectRatioWidget: + videoRect.setSize(windowSize); + break; + + case Phonon::VideoWidget::AspectRatio4_3: + videoRect.setSize(scaleToAspect(m_videoFrameSize, 4, 3)); + break; + + case Phonon::VideoWidget::AspectRatio16_9: + videoRect.setSize(scaleToAspect(m_videoFrameSize, 16, 9)); + break; + } + + // Scale to fill the window width + const int windowWidth = windowSize.width(); + const int windowHeight = windowSize.height(); + const qreal windowScaleFactor = qreal(windowWidth) / videoRect.width(); + int videoWidth = windowWidth; + int videoHeight = videoRect.height() * windowScaleFactor; + + const qreal windowToVideoHeightRatio = qreal(windowHeight) / videoHeight; + + switch (m_videoOutput->scaleMode()) { + case Phonon::VideoWidget::ScaleAndCrop: + if (videoHeight < windowHeight) { + videoWidth *= windowToVideoHeightRatio; + videoHeight = windowHeight; + } + break; + case Phonon::VideoWidget::FitInView: + default: + if (videoHeight > windowHeight) { + videoWidth *= windowToVideoHeightRatio; + videoHeight = windowHeight; + } + break; + } + + // Calculate scale factors + m_scaleWidth = 100.0f * videoWidth / m_videoFrameSize.width(); + m_scaleHeight = 100.0f * videoHeight / m_videoFrameSize.height(); + + if (apply) + parametersChanged(ScaleFactors); + } +} + +void MMF::AbstractVideoPlayer::parametersChanged(VideoParameters parameters) +{ + if (state() == LoadingState) + m_pendingChanges |= parameters; + else + handleParametersChanged(parameters); +} + +void MMF::AbstractVideoPlayer::handlePendingParametersChanged() +{ + if (m_pendingChanges) + handleParametersChanged(m_pendingChanges); + m_pendingChanges = 0; +} + + +//----------------------------------------------------------------------------- +// Metadata +//----------------------------------------------------------------------------- + +int MMF::AbstractVideoPlayer::numberOfMetaDataEntries() const +{ + int numberOfEntries = 0; + TRAP_IGNORE(numberOfEntries = m_player->NumberOfMetaDataEntriesL()); + return numberOfEntries; +} + +QPair<QString, QString> MMF::AbstractVideoPlayer::metaDataEntry(int index) const +{ + CMMFMetaDataEntry *entry = 0; + QT_TRAP_THROWING(entry = m_player->MetaDataEntryL(index)); + return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value())); +} + +QT_END_NAMESPACE + diff --git a/src/3rdparty/phonon/mmf/abstractvideoplayer.h b/src/3rdparty/phonon/mmf/abstractvideoplayer.h new file mode 100644 index 0000000..d854793 --- /dev/null +++ b/src/3rdparty/phonon/mmf/abstractvideoplayer.h @@ -0,0 +1,171 @@ +/* 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_MMF_ABSTRACTVIDEOPLAYER_H +#define PHONON_MMF_ABSTRACTVIDEOPLAYER_H + +#include <videoplayer.h> // from epoc32/include + +#include <QSize> + +#include "abstractmediaplayer.h" +#include "abstractvideooutput.h" +#include "defs.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace MMF +{ +/** + * @short ABC for classes which wrap the MMF video player utility + * + * On devices which use the legacy graphics subsystem which does not + * support surfaces, video rendering is done via Direct Screen Access using + * the CVideoPlayerUtility API. On devices with a graphics subsystem which + * does support surfaces, video rendering is done using the + * CVideoPlayerUtility2 API. Because CVideoPlayerUtility2 inherits from + * CVideoPlayerUtility, AbstractVideoPlayer holds a pointer to the latter. + * + * @see DsaVideoPlayer, SurfaceVideoPlayer + */ +class AbstractVideoPlayer + : public AbstractMediaPlayer + , public MVideoPlayerUtilityObserver + , public MVideoLoadingObserver +{ + Q_OBJECT + +public: + ~AbstractVideoPlayer(); + + typedef CVideoPlayerUtility NativePlayer; + NativePlayer *nativePlayer() const; + + // AbstractPlayer + virtual void doPlay(); + virtual void doPause(); + virtual void doStop(); + virtual void doSeek(qint64 milliseconds); + virtual int setDeviceVolume(int mmfVolume); + virtual int openFile(RFile &file); + virtual int openUrl(const QString &url); + virtual int bufferStatus() const; + virtual void close(); + + // MediaObjectInterface + virtual bool hasVideo() const; + virtual qint64 currentTime() const; + virtual qint64 totalTime() const; + + // AbstractPlayer + virtual void videoOutputChanged(); + + // AbstractMediaPlayer + virtual int numberOfMetaDataEntries() const; + virtual QPair<QString, QString> metaDataEntry(int index) const; + +public Q_SLOTS: + void videoWindowChanged(); + void aspectRatioChanged(); + void scaleModeChanged(); + +protected: + AbstractVideoPlayer(MediaObject *parent, const AbstractPlayer *player); + void construct(); + virtual void initVideoOutput(); + void updateScaleFactors(const QSize &windowSize, bool apply = true); + + // Called when a video parameter changes. If the underlying native API is + // ready to handle the change, it is propagated immediately, otherwise the + // change is recorded in m_pendingChanged and handled later by + // handlePendingParametersChanged(). + void parametersChanged(VideoParameters parameter); + + // Implementation must initialize the m_player pointer. + virtual void createPlayer() = 0; + + // Called from the MvpuoPrepareComplete callback. Allows derived class to + // calculate clipping rectangles and scale factors prior to starting + // playback. + virtual void prepareCompleted() = 0; + + // Called when native video window handle changes. Derived class may defer + // propagation of this change to the MMF video player utility by calling + // parametersChanged(). + virtual void handleVideoWindowChanged() = 0; + + // Called when the derived class must handle changes which have been made + // to video parameters such as window handle, screen rectangle and scale + // factors. Guaranteed to be called only when the underlying MMF video + // player object is ready to handle changes to these parameters. + virtual void handleParametersChanged(VideoParameters parameters) = 0; + +private: + void getVideoClipParametersL(TInt aError); + + // Called when native player API enters a state in which it is able to + // handle pending changes such as new video window handle, updated scale + // factors etc. + void handlePendingParametersChanged(); + +private: + // MVideoPlayerUtilityObserver + virtual void MvpuoOpenComplete(TInt aError); + virtual void MvpuoPrepareComplete(TInt aError); + virtual void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError); + virtual void MvpuoPlayComplete(TInt aError); + virtual void MvpuoEvent(const TMMFEvent &aEvent); + + // MVideoLoadingObserver + virtual void MvloLoadingStarted(); + virtual void MvloLoadingComplete(); + +protected: + QScopedPointer<NativePlayer> m_player; + + // Not owned + RWsSession& m_wsSession; + CWsScreenDevice& m_screenDevice; + RWindowBase* m_window; + + // Scaling factors for video display, expressed as percentages + TReal32 m_scaleWidth; + TReal32 m_scaleHeight; + + // Dimensions of the video clip + QSize m_videoFrameSize; + +private: + // Bitmask of parameters which have changed while the MMF video player + // object is not yet ready to receive these changes. + // See handlePendingParametersChanged(). + VideoParameters m_pendingChanges; + + // Duration of the video clip + qint64 m_totalTime; + +}; + +} +} + +QT_END_NAMESPACE + +#endif diff --git a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp index 18ced94..f0d1be2 100644 --- a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp +++ b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp @@ -18,7 +18,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "ancestormovemonitor.h" #include "utils.h" -#include "videooutput.h" + +#include "videooutput_dsa.h" #include <QCoreApplication> @@ -59,7 +60,7 @@ AncestorMoveMonitor::~AncestorMoveMonitor() // Public functions //----------------------------------------------------------------------------- -void AncestorMoveMonitor::registerTarget(VideoOutput *target) +void AncestorMoveMonitor::registerTarget(DsaVideoOutput *target) { TRACE_CONTEXT(AncestorMoveMonitor::registerTarget, EVideoInternal); TRACE_ENTRY("target 0x%08x", target); @@ -93,7 +94,7 @@ void AncestorMoveMonitor::registerTarget(VideoOutput *target) TRACE_EXIT_0(); } -void AncestorMoveMonitor::unRegisterTarget(VideoOutput *target) +void AncestorMoveMonitor::unRegisterTarget(DsaVideoOutput *target) { TRACE_CONTEXT(AncestorMoveMonitor::unRegisterTarget, EVideoInternal); TRACE_ENTRY("target 0x%08x", target); @@ -126,7 +127,7 @@ bool AncestorMoveMonitor::eventFilter(QObject *watched, QEvent *event) const Hash::const_iterator it = m_hash.find(watched); if(it != m_hash.end()) { const TargetList& targetList = it.value(); - VideoOutput* target = 0; + DsaVideoOutput* target = 0; foreach(target, targetList) { switch (event->type()) { @@ -166,7 +167,7 @@ void AncestorMoveMonitor::dump() const QObject *ancestor = it.key(); TRACE("ancestor 0x%08x", ancestor); const TargetList& targetList = it.value(); - VideoOutput* target = 0; + DsaVideoOutput* target = 0; foreach(target, targetList) { TRACE(" target 0x%08x", target); } @@ -174,7 +175,5 @@ void AncestorMoveMonitor::dump() #endif } - - QT_END_NAMESPACE diff --git a/src/3rdparty/phonon/mmf/ancestormovemonitor.h b/src/3rdparty/phonon/mmf/ancestormovemonitor.h index 0e681aa..f3a022d 100644 --- a/src/3rdparty/phonon/mmf/ancestormovemonitor.h +++ b/src/3rdparty/phonon/mmf/ancestormovemonitor.h @@ -29,7 +29,7 @@ namespace Phonon { namespace MMF { -class VideoOutput; +class DsaVideoOutput; class AncestorMoveMonitor : public QObject { @@ -49,7 +49,7 @@ public: * ancestor list to be updated - therefore it should be called when * the target receives a ParentChange event. */ - void registerTarget(VideoOutput *target); + void registerTarget(DsaVideoOutput *target); /** * Remove target from the monitor. @@ -57,7 +57,7 @@ public: * The target will no longer receive notification when move events are * delivered to its ancestors. */ - void unRegisterTarget(VideoOutput *target); + void unRegisterTarget(DsaVideoOutput *target); protected: /** @@ -77,7 +77,7 @@ private: * therefore a set, however we use QList rather than QSet for * efficiency of iteration. */ - typedef QList<VideoOutput *> TargetList; + typedef QList<DsaVideoOutput *> TargetList; /** * Map from widget on which the move event occurs, to widgets which @@ -92,4 +92,4 @@ private: QT_END_NAMESPACE -#endif +#endif // !PHONON_MMF_ANCESTORMOVEMONITOR_H diff --git a/src/3rdparty/phonon/mmf/backend.cpp b/src/3rdparty/phonon/mmf/backend.cpp index 3568a49..2cec43b 100644 --- a/src/3rdparty/phonon/mmf/backend.cpp +++ b/src/3rdparty/phonon/mmf/backend.cpp @@ -24,7 +24,6 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include <apmstd.h> // for TDataType #include "abstractaudioeffect.h" -#include "ancestormovemonitor.h" #include "audiooutput.h" #include "audioplayer.h" #include "backend.h" @@ -44,7 +43,9 @@ using namespace Phonon::MMF; Backend::Backend(QObject *parent) : QObject(parent) +#ifndef PHONON_MMF_VIDEO_SURFACES , m_ancestorMoveMonitor(new AncestorMoveMonitor(this)) +#endif , m_effectFactory(new EffectFactory(this)) { TRACE_CONTEXT(Backend::Backend, EBackend); @@ -86,8 +87,15 @@ QObject *Backend::createObject(BackendInterface::Class c, QObject *parent, const static_cast<EffectFactory::Type>(args.first().toInt()); return m_effectFactory->createAudioEffect(type, parent); } + case VideoWidgetClass: - result = new VideoWidget(m_ancestorMoveMonitor.data(), qobject_cast<QWidget *>(parent)); + { + VideoWidget *widget = new VideoWidget(qobject_cast<QWidget *>(parent)); +#ifndef PHONON_MMF_VIDEO_SURFACES + widget->setAncestorMoveMonitor(m_ancestorMoveMonitor.data()); +#endif + result = widget; + } break; default: diff --git a/src/3rdparty/phonon/mmf/backend.h b/src/3rdparty/phonon/mmf/backend.h index 9361544..a45c92a 100644 --- a/src/3rdparty/phonon/mmf/backend.h +++ b/src/3rdparty/phonon/mmf/backend.h @@ -19,7 +19,10 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef PHONON_MMF_BACKEND_H #define PHONON_MMF_BACKEND_H +#ifndef PHONON_MMF_VIDEO_SURFACES #include "ancestormovemonitor.h" +#endif + #include "effectfactory.h" #include <phonon/mediasource.h> @@ -53,7 +56,9 @@ Q_SIGNALS: void objectDescriptionChanged(ObjectDescriptionType); private: +#ifndef PHONON_MMF_VIDEO_SURFACES QScopedPointer<AncestorMoveMonitor> m_ancestorMoveMonitor; +#endif QScopedPointer<EffectFactory> m_effectFactory; }; diff --git a/src/3rdparty/phonon/mmf/defs.h b/src/3rdparty/phonon/mmf/defs.h index 1a93aa9..1ed8250 100644 --- a/src/3rdparty/phonon/mmf/defs.h +++ b/src/3rdparty/phonon/mmf/defs.h @@ -35,6 +35,15 @@ enum MediaType { MediaTypeAudio, MediaTypeVideo }; + +enum VideoParameter { + WindowHandle = 0x1, + WindowScreenRect = 0x2, + ScaleFactors = 0x4 +}; +Q_DECLARE_FLAGS(VideoParameters, VideoParameter) +Q_DECLARE_OPERATORS_FOR_FLAGS(VideoParameters) + } } diff --git a/src/3rdparty/phonon/mmf/mediaobject.cpp b/src/3rdparty/phonon/mmf/mediaobject.cpp index 9744774..ee459e6 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.cpp +++ b/src/3rdparty/phonon/mmf/mediaobject.cpp @@ -22,7 +22,13 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "dummyplayer.h" #include "utils.h" #include "utils.h" -#include "mmf_videoplayer.h" + +#ifdef PHONON_MMF_VIDEO_SURFACES +#include "videoplayer_surface.h" +#else +#include "videoplayer_dsa.h" +#endif + #include "videowidget.h" #include "mediaobject.h" @@ -293,7 +299,11 @@ void MMF::MediaObject::createPlayer(const MediaSource &source) break; case MediaTypeVideo: - newPlayer = new VideoPlayer(this, oldPlayer); +#ifdef PHONON_MMF_VIDEO_SURFACES + newPlayer = SurfaceVideoPlayer::create(this, oldPlayer); +#else + newPlayer = DsaVideoPlayer::create(this, oldPlayer); +#endif break; } @@ -383,7 +393,7 @@ void MMF::MediaObject::disconnectMediaObject(MediaObject * /*mediaObject*/) // Video output //----------------------------------------------------------------------------- -void MMF::MediaObject::setVideoOutput(VideoOutput* videoOutput) +void MMF::MediaObject::setVideoOutput(AbstractVideoOutput* videoOutput) { m_player->setVideoOutput(videoOutput); } diff --git a/src/3rdparty/phonon/mmf/mediaobject.h b/src/3rdparty/phonon/mmf/mediaobject.h index d6248e2..62e0a0e 100644 --- a/src/3rdparty/phonon/mmf/mediaobject.h +++ b/src/3rdparty/phonon/mmf/mediaobject.h @@ -38,7 +38,7 @@ namespace Phonon namespace MMF { class AbstractPlayer; -class VideoOutput; +class AbstractVideoOutput; /** * @short Facade class which wraps MMF client utility instance @@ -85,7 +85,7 @@ public: */ AbstractPlayer *abstractPlayer() const; - void setVideoOutput(VideoOutput* videoOutput); + void setVideoOutput(AbstractVideoOutput* videoOutput); public Q_SLOTS: void volumeChanged(qreal volume); diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp b/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp deleted file mode 100644 index 127edb4..0000000 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.cpp +++ /dev/null @@ -1,658 +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 <QApplication> // for QApplication::activeWindow -#include <QUrl> -#include <QTimer> -#include <QWidget> - -#include <coemain.h> // for CCoeEnv -#include <coecntrl.h> - -#include "mmf_videoplayer.h" -#include "utils.h" - -#ifndef QT_NO_DEBUG -#include "objectdump.h" -#endif - -QT_BEGIN_NAMESPACE - -using namespace Phonon; -using namespace Phonon::MMF; - -/*! \class MMF::VideoPlayer - \internal -*/ - -//----------------------------------------------------------------------------- -// Constructor / destructor -//----------------------------------------------------------------------------- - -MMF::VideoPlayer::VideoPlayer(MediaObject *parent, const AbstractPlayer *player) - : AbstractMediaPlayer(parent, player) - , m_wsSession(CCoeEnv::Static()->WsSession()) - , m_screenDevice(*CCoeEnv::Static()->ScreenDevice()) - , m_window(0) - , m_totalTime(0) - , m_pendingChanges(false) - , m_dsaActive(false) -{ - construct(); -} - -void MMF::VideoPlayer::construct() -{ - TRACE_CONTEXT(VideoPlayer::VideoPlayer, EVideoApi); - TRACE_ENTRY_0(); - - getVideoWindow(); - - const TInt priority = 0; - const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone; - - CVideoPlayerUtility *player = 0; - QT_TRAP_THROWING(player = CVideoPlayerUtility::NewL - ( - *this, - priority, preference, - m_wsSession, m_screenDevice, - *m_window, - m_videoRect, m_videoRect - ) - ); - m_player.reset(player); - - // CVideoPlayerUtility::NewL starts DSA - m_dsaActive = true; - - m_player->RegisterForVideoLoadingNotification(*this); - - TRACE_EXIT_0(); -} - -MMF::VideoPlayer::~VideoPlayer() -{ - TRACE_CONTEXT(VideoPlayer::~VideoPlayer, EVideoApi); - TRACE_ENTRY_0(); - - // QObject destructor removes all signal-slot connections involving this - // object, so we do not need to disconnect from m_videoOutput here. - - TRACE_EXIT_0(); -} - -CVideoPlayerUtility* MMF::VideoPlayer::nativePlayer() const -{ - return m_player.data(); -} - -//----------------------------------------------------------------------------- -// Public API -//----------------------------------------------------------------------------- - -void MMF::VideoPlayer::doPlay() -{ - TRACE_CONTEXT(VideoPlayer::doPlay, EVideoApi); - - applyPendingChanges(); - - m_player->Play(); -} - -void MMF::VideoPlayer::doPause() -{ - TRACE_CONTEXT(VideoPlayer::doPause, EVideoApi); - - TRAPD(err, m_player->PauseL()); - if (KErrNone != err && state() != ErrorState) { - TRACE("PauseL error %d", err); - setError(tr("Pause failed"), err); - } -} - -void MMF::VideoPlayer::doStop() -{ - m_player->Stop(); -} - -void MMF::VideoPlayer::doSeek(qint64 ms) -{ - TRACE_CONTEXT(VideoPlayer::doSeek, EVideoApi); - - TRAPD(err, m_player->SetPositionL(TTimeIntervalMicroSeconds(ms * 1000))); - - if(KErrNone != err) - setError(tr("Seek failed"), err); -} - -int MMF::VideoPlayer::setDeviceVolume(int mmfVolume) -{ - TRAPD(err, m_player->SetVolumeL(mmfVolume)); - return err; -} - -int MMF::VideoPlayer::openFile(RFile& file) -{ - TRAPD(err, m_player->OpenFileL(file)); - return err; -} - -int MMF::VideoPlayer::openUrl(const QString& url) -{ - TRAPD(err, m_player->OpenUrlL(qt_QString2TPtrC(url))); - return err; -} - -int MMF::VideoPlayer::bufferStatus() const -{ - int result = 0; - TRAP_IGNORE(m_player->GetVideoLoadingProgressL(result)); - return result; -} - -void MMF::VideoPlayer::close() -{ - m_player->Close(); -} - -bool MMF::VideoPlayer::hasVideo() const -{ - return true; -} - -qint64 MMF::VideoPlayer::currentTime() const -{ - TRACE_CONTEXT(VideoPlayer::currentTime, EVideoApi); - - TTimeIntervalMicroSeconds us; - TRAPD(err, us = m_player->PositionL()) - - qint64 result = 0; - - if (KErrNone == err) { - result = toMilliSeconds(us); - } else { - TRACE("PositionL error %d", err); - - // If we don't cast away constness here, we simply have to ignore - // the error. - const_cast<VideoPlayer*>(this)->setError(tr("Getting position failed"), err); - } - - return result; -} - -qint64 MMF::VideoPlayer::totalTime() const -{ - return m_totalTime; -} - - -//----------------------------------------------------------------------------- -// MVideoPlayerUtilityObserver callbacks -//----------------------------------------------------------------------------- - -void MMF::VideoPlayer::MvpuoOpenComplete(TInt aError) -{ - TRACE_CONTEXT(VideoPlayer::MvpuoOpenComplete, EVideoApi); - TRACE_ENTRY("state %d error %d", state(), aError); - - __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic)); - - if (KErrNone == aError) - m_player->Prepare(); - else - setError(tr("Opening clip failed"), aError); - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::MvpuoPrepareComplete(TInt aError) -{ - TRACE_CONTEXT(VideoPlayer::MvpuoPrepareComplete, EVideoApi); - TRACE_ENTRY("state %d error %d", state(), aError); - - __ASSERT_ALWAYS(LoadingState == state(), Utils::panic(InvalidStatePanic)); - - TRAPD(err, doPrepareCompleteL(aError)); - - if (KErrNone == err) { - maxVolumeChanged(m_player->MaxVolume()); - - if (m_videoOutput) - m_videoOutput->setVideoSize(m_videoFrameSize); - - updateVideoRect(); - applyPendingChanges(); - - emit totalTimeChanged(totalTime()); - changeState(StoppedState); - } else { - setError(tr("Buffering clip failed"), err); - } - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::doPrepareCompleteL(TInt aError) -{ - User::LeaveIfError(aError); - - // Get frame size - TSize size; - m_player->VideoFrameSizeL(size); - m_videoFrameSize = QSize(size.iWidth, size.iHeight); - - // Get duration - m_totalTime = toMilliSeconds(m_player->DurationL()); -} - - -void MMF::VideoPlayer::MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError) -{ - TRACE_CONTEXT(VideoPlayer::MvpuoFrameReady, EVideoApi); - TRACE_ENTRY("state %d error %d", state(), aError); - - Q_UNUSED(aFrame); - Q_UNUSED(aError); // suppress warnings in release builds - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::MvpuoPlayComplete(TInt aError) -{ - TRACE_CONTEXT(VideoPlayer::MvpuoPlayComplete, EVideoApi) - TRACE_ENTRY("state %d error %d", state(), aError); - - // Call base class function which handles end of playback for both - // audio and video clips. - playbackComplete(aError); - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::MvpuoEvent(const TMMFEvent &aEvent) -{ - TRACE_CONTEXT(VideoPlayer::MvpuoEvent, EVideoApi); - TRACE_ENTRY("state %d", state()); - - Q_UNUSED(aEvent); - - TRACE_EXIT_0(); -} - - -//----------------------------------------------------------------------------- -// MVideoLoadingObserver callbacks -//----------------------------------------------------------------------------- - -void MMF::VideoPlayer::MvloLoadingStarted() -{ - bufferingStarted(); -} - -void MMF::VideoPlayer::MvloLoadingComplete() -{ - bufferingComplete(); -} - - -//----------------------------------------------------------------------------- -// Video window updates -//----------------------------------------------------------------------------- - -void MMF::VideoPlayer::getVideoWindow() -{ - TRACE_CONTEXT(VideoPlayer::getVideoWindow, EVideoInternal); - TRACE_ENTRY_0(); - - if(m_videoOutput) { - // Dump information to log, only in debug builds - m_videoOutput->dump(); - - initVideoOutput(); - videoWindowChanged(); - } else - // Top-level window - m_window = QApplication::activeWindow()->effectiveWinId()->DrawableWindow(); - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::videoOutputChanged() -{ - TRACE_CONTEXT(VideoPlayer::videoOutputChanged, EVideoInternal); - TRACE_ENTRY_0(); - - if (m_videoOutput) { - initVideoOutput(); - videoWindowChanged(); - } - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::initVideoOutput() -{ - m_videoOutput->winId(); - m_videoOutput->setVideoSize(m_videoFrameSize); - - bool connected = connect( - m_videoOutput, SIGNAL(videoWindowChanged()), - this, SLOT(videoWindowChanged()) - ); - Q_ASSERT(connected); - - connected = connect( - m_videoOutput, SIGNAL(beginVideoWindowNativePaint()), - this, SLOT(suspendDirectScreenAccess()) - ); - Q_ASSERT(connected); - - connected = connect( - m_videoOutput, SIGNAL(endVideoWindowNativePaint()), - this, SLOT(resumeDirectScreenAccess()) - ); - Q_ASSERT(connected); - - connected = connect( - m_videoOutput, SIGNAL(aspectRatioChanged()), - this, SLOT(aspectRatioChanged()) - ); - Q_ASSERT(connected); - - connected = connect( - m_videoOutput, SIGNAL(scaleModeChanged()), - this, SLOT(scaleModeChanged()) - ); - Q_ASSERT(connected); - - // Suppress warnings in release builds - Q_UNUSED(connected); -} - -void MMF::VideoPlayer::videoWindowChanged() -{ - TRACE_CONTEXT(VideoPlayer::videoOutputRegionChanged, EVideoInternal); - TRACE_ENTRY("state %d", state()); - - m_window = m_videoOutput->videoWindow(); - updateVideoRect(); - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::suspendDirectScreenAccess() -{ - m_dsaWasActive = stopDirectScreenAccess(); -} - -void MMF::VideoPlayer::resumeDirectScreenAccess() -{ - if(m_dsaWasActive) { - startDirectScreenAccess(); - m_dsaWasActive = false; - } -} - -void MMF::VideoPlayer::startDirectScreenAccess() -{ - if(!m_dsaActive) { - TRAPD(err, m_player->StartDirectScreenAccessL()); - if(KErrNone == err) - m_dsaActive = true; - else - setError(tr("Video display error"), err); - } -} - -bool MMF::VideoPlayer::stopDirectScreenAccess() -{ - const bool dsaWasActive = m_dsaActive; - if(m_dsaActive) { - TRAPD(err, m_player->StopDirectScreenAccessL()); - if(KErrNone == err) - m_dsaActive = false; - else - setError(tr("Video display error"), err); - } - return dsaWasActive; -} - -// Helper function for aspect ratio / scale mode handling -QSize scaleToAspect(const QSize& srcRect, int aspectWidth, int aspectHeight) -{ - const qreal aspectRatio = qreal(aspectWidth) / aspectHeight; - - int width = srcRect.width(); - int height = srcRect.width() / aspectRatio; - if (height > srcRect.height()){ - height = srcRect.height(); - width = srcRect.height() * aspectRatio; - } - return QSize(width, height); -} - -void MMF::VideoPlayer::updateVideoRect() -{ - QRect videoRect; - QRect windowRect = m_videoOutput->videoWindowRect(); - - // Clip to physical window size - // This is due to a defect in the layout when running on S60 3.2, which - // results in the rectangle of the video widget extending outside the - // screen in certain circumstances. These include the initial startup - // of the mediaplayer demo in portrait mode. When this rectangle is - // passed to the CVideoPlayerUtility, no video is rendered. - const TSize screenSize = m_screenDevice.SizeInPixels(); - const QRect screenRect(0, 0, screenSize.iWidth, screenSize.iHeight); - windowRect = windowRect.intersected(screenRect); - - const QSize windowSize = windowRect.size(); - - // Calculate size of smallest rect which contains video frame size - // and conforms to aspect ratio - switch (m_videoOutput->aspectRatio()) { - case Phonon::VideoWidget::AspectRatioAuto: - videoRect.setSize(m_videoFrameSize); - break; - - case Phonon::VideoWidget::AspectRatioWidget: - videoRect.setSize(windowSize); - break; - - case Phonon::VideoWidget::AspectRatio4_3: - videoRect.setSize(scaleToAspect(m_videoFrameSize, 4, 3)); - break; - - case Phonon::VideoWidget::AspectRatio16_9: - videoRect.setSize(scaleToAspect(m_videoFrameSize, 16, 9)); - break; - } - - // Scale to fill the window width - const int windowWidth = windowSize.width(); - const int windowHeight = windowSize.height(); - const qreal windowScaleFactor = qreal(windowWidth) / videoRect.width(); - int videoWidth = windowWidth; - int videoHeight = videoRect.height() * windowScaleFactor; - - const qreal windowToVideoHeightRatio = qreal(windowHeight) / videoHeight; - - switch(m_videoOutput->scaleMode()) { - case Phonon::VideoWidget::ScaleAndCrop: - if(videoHeight < windowHeight) { - videoWidth *= windowToVideoHeightRatio; - videoHeight = windowHeight; - } - break; - case Phonon::VideoWidget::FitInView: - default: - if(videoHeight > windowHeight) { - videoWidth *= windowToVideoHeightRatio; - videoHeight = windowHeight; - } - break; - } - - // Calculate scale factors - m_scaleWidth = 100.0f * videoWidth / m_videoFrameSize.width(); - m_scaleHeight = 100.0f * videoHeight / m_videoFrameSize.height(); - - m_videoRect = qt_QRect2TRect(windowRect); - - if (state() == LoadingState) - m_pendingChanges = true; - else { - applyVideoWindowChange(); - m_pendingChanges = false; - } -} - -void MMF::VideoPlayer::aspectRatioChanged() -{ - TRACE_CONTEXT(VideoPlayer::aspectRatioChanged, EVideoInternal); - TRACE_ENTRY("state %d aspectRatio %d", state()); - - updateVideoRect(); - - TRACE_EXIT_0(); -} - -void MMF::VideoPlayer::scaleModeChanged() -{ - TRACE_CONTEXT(VideoPlayer::scaleModeChanged, EVideoInternal); - TRACE_ENTRY("state %d", state()); - - updateVideoRect(); - - TRACE_EXIT_0(); -} - -#ifndef QT_NO_DEBUG - -// The following code is for debugging problems related to video visibility. It allows -// the VideoPlayer instance to query the window server in order to determine the -// DSA drawing region for the video window. - -class CDummyAO : public CActive -{ -public: - CDummyAO() : CActive(CActive::EPriorityStandard) { CActiveScheduler::Add(this); } - void RunL() { } - void DoCancel() { } - TRequestStatus& Status() { return iStatus; } - void SetActive() { CActive::SetActive(); } -}; - -void getDsaRegion(RWsSession &session, const RWindowBase &window) -{ - RDirectScreenAccess dsa(session); - TInt err = dsa.Construct(); - CDummyAO ao; - RRegion* region; - err = dsa.Request(region, ao.Status(), window); - ao.SetActive(); - dsa.Close(); - ao.Cancel(); - if (region) { - qDebug() << "Phonon::MMF::getDsaRegion count" << region->Count(); - for (int i=0; i<region->Count(); ++i) { - const TRect& rect = region->RectangleList()[i]; - qDebug() << "Phonon::MMF::getDsaRegion rect" - << rect.iTl.iX << rect.iTl.iY << rect.iBr.iX << rect.iBr.iY; - } - region->Close(); - } -} - -#endif // _DEBUG - -void MMF::VideoPlayer::applyPendingChanges() -{ - if(m_pendingChanges) - applyVideoWindowChange(); - - m_pendingChanges = false; -} - -void MMF::VideoPlayer::applyVideoWindowChange() -{ - TRACE_CONTEXT(VideoPlayer::applyVideoWindowChange, EVideoInternal); - TRACE_ENTRY_0(); - -#ifndef QT_NO_DEBUG - getDsaRegion(m_wsSession, *m_window); -#endif - - static const TBool antialias = ETrue; - - TRAPD(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, antialias)); - if(KErrNone != err) { - TRACE("SetScaleFactorL (1) err %d", err); - setError(tr("Video display error"), err); - } - - if(KErrNone == err) { - TRAP(err, - m_player->SetDisplayWindowL - ( - m_wsSession, m_screenDevice, - *m_window, - m_videoRect, m_videoRect - ) - ); - - if (KErrNone != err) { - TRACE("SetDisplayWindowL err %d", err); - setError(tr("Video display error"), err); - } else { - m_dsaActive = true; - TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, antialias)); - if(KErrNone != err) { - TRACE("SetScaleFactorL (2) err %d", err); - setError(tr("Video display error"), err); - } - } - } - - TRACE_EXIT_0(); -} - - -//----------------------------------------------------------------------------- -// Metadata -//----------------------------------------------------------------------------- - -int MMF::VideoPlayer::numberOfMetaDataEntries() const -{ - int numberOfEntries = 0; - TRAP_IGNORE(numberOfEntries = m_player->NumberOfMetaDataEntriesL()); - return numberOfEntries; -} - -QPair<QString, QString> MMF::VideoPlayer::metaDataEntry(int index) const -{ - CMMFMetaDataEntry *entry = 0; - QT_TRAP_THROWING(entry = m_player->MetaDataEntryL(index)); - return QPair<QString, QString>(qt_TDesC2QString(entry->Name()), qt_TDesC2QString(entry->Value())); -} - -QT_END_NAMESPACE - diff --git a/src/3rdparty/phonon/mmf/mmf_videoplayer.h b/src/3rdparty/phonon/mmf/mmf_videoplayer.h deleted file mode 100644 index 0253ab9..0000000 --- a/src/3rdparty/phonon/mmf/mmf_videoplayer.h +++ /dev/null @@ -1,138 +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_MMF_VIDEOPLAYER_H -#define PHONON_MMF_VIDEOPLAYER_H - -#include <videoplayer.h> // from epoc32/include - -#include "abstractmediaplayer.h" -#include "videooutput.h" - -QT_BEGIN_NAMESPACE - -namespace Phonon -{ -namespace MMF -{ -/** - * @short Wrapper over MMF video client utility - * - * See - * <a href="http://wiki.forum.nokia.com/index.php/How_to_play_a_video_file_using_CVideoPlayerUtility">How to - * play a video file using CVideoPlayerUtility</a> - */ -class VideoPlayer : public AbstractMediaPlayer - , public MVideoPlayerUtilityObserver - , public MVideoLoadingObserver -{ - Q_OBJECT - -public: - VideoPlayer(MediaObject *parent = 0, const AbstractPlayer *player = 0); - virtual ~VideoPlayer(); - - typedef CVideoPlayerUtility NativePlayer; - NativePlayer *nativePlayer() const; - - // AbstractPlayer - virtual void doPlay(); - virtual void doPause(); - virtual void doStop(); - virtual void doSeek(qint64 milliseconds); - virtual int setDeviceVolume(int mmfVolume); - virtual int openFile(RFile& file); - virtual int openUrl(const QString& url); - virtual int bufferStatus() const; - virtual void close(); - - // MediaObjectInterface - virtual bool hasVideo() const; - virtual qint64 currentTime() const; - virtual qint64 totalTime() const; - - // AbstractPlayer - virtual void videoOutputChanged(); - - // AbstractMediaPlayer - virtual int numberOfMetaDataEntries() const; - virtual QPair<QString, QString> metaDataEntry(int index) const; - -public Q_SLOTS: - void videoWindowChanged(); - void aspectRatioChanged(); - void scaleModeChanged(); - void suspendDirectScreenAccess(); - void resumeDirectScreenAccess(); - -private: - void construct(); - - void doPrepareCompleteL(TInt aError); - - void getVideoWindow(); - void initVideoOutput(); - void updateVideoRect(); - - void applyPendingChanges(); - void applyVideoWindowChange(); - - void startDirectScreenAccess(); - bool stopDirectScreenAccess(); - -private: - // MVideoPlayerUtilityObserver - virtual void MvpuoOpenComplete(TInt aError); - virtual void MvpuoPrepareComplete(TInt aError); - virtual void MvpuoFrameReady(CFbsBitmap &aFrame, TInt aError); - virtual void MvpuoPlayComplete(TInt aError); - virtual void MvpuoEvent(const TMMFEvent &aEvent); - - // MVideoLoadingObserver - virtual void MvloLoadingStarted(); - virtual void MvloLoadingComplete(); - -private: - QScopedPointer<NativePlayer> m_player; - - // Not owned - RWsSession& m_wsSession; - CWsScreenDevice& m_screenDevice; - RWindowBase* m_window; - - /* Extent of the video display - will be clipped to m_windowRect */ - TRect m_videoRect; - - TReal32 m_scaleWidth; - TReal32 m_scaleHeight; - - QSize m_videoFrameSize; - qint64 m_totalTime; - - bool m_pendingChanges; - bool m_dsaActive; - bool m_dsaWasActive; - -}; - -} -} - -QT_END_NAMESPACE - -#endif diff --git a/src/3rdparty/phonon/mmf/videooutput.cpp b/src/3rdparty/phonon/mmf/videooutput.cpp deleted file mode 100644 index 119dcb1..0000000 --- a/src/3rdparty/phonon/mmf/videooutput.cpp +++ /dev/null @@ -1,303 +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 "ancestormovemonitor.h" -#include "utils.h" -#include "videooutput.h" - -#ifndef QT_NO_DEBUG -#include "objectdump.h" -#endif - -#include <QPaintEvent> -#include <QPainter> -#include <QMoveEvent> -#include <QResizeEvent> - -#include <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect -#include <QtGui/private/qwidget_p.h> // to access QWExtra - -#include <coecntrl.h> - -#include <coemain.h> // for CCoeEnv - -QT_BEGIN_NAMESPACE - -using namespace Phonon; -using namespace Phonon::MMF; - -/*! \class MMF::VideoOutput - \internal -*/ - -//----------------------------------------------------------------------------- -// Constants -//----------------------------------------------------------------------------- - -static const Phonon::VideoWidget::AspectRatio DefaultAspectRatio = - Phonon::VideoWidget::AspectRatioAuto; -static const Phonon::VideoWidget::ScaleMode DefaultScaleMode = - Phonon::VideoWidget::FitInView; - - -//----------------------------------------------------------------------------- -// Constructor / destructor -//----------------------------------------------------------------------------- - -MMF::VideoOutput::VideoOutput - (AncestorMoveMonitor* ancestorMoveMonitor, QWidget* parent) - : QWidget(parent) - , m_ancestorMoveMonitor(ancestorMoveMonitor) - , m_aspectRatio(DefaultAspectRatio) - , m_scaleMode(DefaultScaleMode) -{ - TRACE_CONTEXT(VideoOutput::VideoOutput, EVideoInternal); - TRACE_ENTRY("parent 0x%08x", parent); - - setPalette(QPalette(Qt::black)); - setAttribute(Qt::WA_OpaquePaintEvent, true); - setAttribute(Qt::WA_NoSystemBackground, true); - setAutoFillBackground(false); - - qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::ZeroFill; - qt_widget_private(this)->extraData()->receiveNativePaintEvents = true; - - getVideoWindowRect(); - registerForAncestorMoved(); - - dump(); - - TRACE_EXIT_0(); -} - -MMF::VideoOutput::~VideoOutput() -{ - TRACE_CONTEXT(VideoOutput::~VideoOutput, EVideoInternal); - TRACE_ENTRY_0(); - - m_ancestorMoveMonitor->unRegisterTarget(this); - - TRACE_EXIT_0(); -} - -void MMF::VideoOutput::setVideoSize(const QSize& frameSize) -{ - TRACE_CONTEXT(VideoOutput::setVideoSize, EVideoInternal); - TRACE("oldSize %d %d newSize %d %d", - m_videoFrameSize.width(), m_videoFrameSize.height(), - frameSize.width(), frameSize.height()); - - if (frameSize != m_videoFrameSize) { - m_videoFrameSize = frameSize; - updateGeometry(); - } -} - -void MMF::VideoOutput::ancestorMoved() -{ - TRACE_CONTEXT(VideoOutput::ancestorMoved, EVideoInternal); - TRACE_ENTRY_0(); - - RWindowBase *const window = videoWindow(); - - if(window) { - const TPoint newWindowPosSymbian = window->AbsPosition(); - const QPoint newWindowPos(newWindowPosSymbian.iX, newWindowPosSymbian.iY); - - if(newWindowPos != m_videoWindowRect.topLeft()) { - m_videoWindowRect.moveTo(newWindowPos); - emit videoWindowChanged(); - } - } - - TRACE_EXIT_0(); -} - -//----------------------------------------------------------------------------- -// QWidget -//----------------------------------------------------------------------------- - -QSize MMF::VideoOutput::sizeHint() const -{ - // TODO: replace this with a more sensible default - QSize result(320, 240); - - if (!m_videoFrameSize.isNull()) - result = m_videoFrameSize; - - return result; -} - -void MMF::VideoOutput::paintEvent(QPaintEvent* event) -{ - TRACE_CONTEXT(VideoOutput::paintEvent, EVideoInternal); - TRACE("rect %d %d - %d %d", - event->rect().left(), event->rect().top(), - event->rect().right(), event->rect().bottom()); - TRACE("regions %d", event->region().rectCount()); - TRACE("type %d", event->type()); - - // Do nothing -} - -void MMF::VideoOutput::resizeEvent(QResizeEvent* event) -{ - TRACE_CONTEXT(VideoOutput::resizeEvent, EVideoInternal); - TRACE("%d %d -> %d %d", - event->oldSize().width(), event->oldSize().height(), - event->size().width(), event->size().height()); - - if(event->size() != event->oldSize()) { - m_videoWindowRect.setSize(event->size()); - emit videoWindowChanged(); - } -} - -void MMF::VideoOutput::moveEvent(QMoveEvent* event) -{ - TRACE_CONTEXT(VideoOutput::moveEvent, EVideoInternal); - TRACE("%d %d -> %d %d", - event->oldPos().x(), event->oldPos().y(), - event->pos().x(), event->pos().y()); - - if(event->pos() != event->oldPos()) { - m_videoWindowRect.moveTo(event->pos()); - emit videoWindowChanged(); - } -} - -bool MMF::VideoOutput::event(QEvent* event) -{ - TRACE_CONTEXT(VideoOutput::event, EVideoInternal); - - if (event->type() == QEvent::WinIdChange) { - TRACE_0("WinIdChange"); - getVideoWindowRect(); - emit videoWindowChanged(); - return true; - } else if (event->type() == QEvent::ParentChange) { - // Tell ancestor move monitor to update ancestor list for this widget - registerForAncestorMoved(); - return true; - } else - return QWidget::event(event); -} - - -//----------------------------------------------------------------------------- -// Public functions -//----------------------------------------------------------------------------- - -RWindowBase* MMF::VideoOutput::videoWindow() -{ - CCoeControl *control = internalWinId(); - if(!control) - control = effectiveWinId(); - - RWindowBase *window = 0; - if(control) - window = control->DrawableWindow(); - - return window; -} - -const QRect& MMF::VideoOutput::videoWindowRect() const -{ - return m_videoWindowRect; -} - -Phonon::VideoWidget::AspectRatio MMF::VideoOutput::aspectRatio() const -{ - return m_aspectRatio; -} - -void MMF::VideoOutput::setAspectRatio - (Phonon::VideoWidget::AspectRatio aspectRatio) -{ - if(m_aspectRatio != aspectRatio) { - m_aspectRatio = aspectRatio; - emit aspectRatioChanged(); - } -} - -Phonon::VideoWidget::ScaleMode MMF::VideoOutput::scaleMode() const -{ - return m_scaleMode; -} - -void MMF::VideoOutput::setScaleMode - (Phonon::VideoWidget::ScaleMode scaleMode) -{ - if(m_scaleMode != scaleMode) { - m_scaleMode = scaleMode; - emit scaleModeChanged(); - } -} - - -//----------------------------------------------------------------------------- -// Private functions -//----------------------------------------------------------------------------- - -void MMF::VideoOutput::getVideoWindowRect() -{ - RWindowBase *const window = videoWindow(); - if(window) - m_videoWindowRect = - qt_TRect2QRect(TRect(window->AbsPosition(), window->Size())); -} - -void MMF::VideoOutput::registerForAncestorMoved() -{ - m_ancestorMoveMonitor->registerTarget(this); -} - -void MMF::VideoOutput::dump() const -{ -#ifndef QT_NO_DEBUG - TRACE_CONTEXT(VideoOutput::dump, EVideoInternal); - - QScopedPointer<ObjectDump::QVisitor> visitor(new ObjectDump::QVisitor); - visitor->setPrefix("Phonon::MMF"); // to aid searchability of logs - ObjectDump::addDefaultAnnotators(*visitor); - TRACE("Dumping tree from leaf 0x%08x:", this); - ObjectDump::dumpTreeFromLeaf(*this, *visitor); - - QScopedPointer<ObjectDump::QDumper> dumper(new ObjectDump::QDumper); - dumper->setPrefix("Phonon::MMF"); // to aid searchability of logs - ObjectDump::addDefaultAnnotators(*dumper); - TRACE_0("Dumping VideoOutput:"); - dumper->dumpObject(*this); -#endif -} - -void MMF::VideoOutput::beginNativePaintEvent(const QRect& /*controlRect*/) -{ - emit beginVideoWindowNativePaint(); -} - -void MMF::VideoOutput::endNativePaintEvent(const QRect& /*controlRect*/) -{ - // Ensure that draw ops are executed into the WSERV output framebuffer - CCoeEnv::Static()->WsSession().Flush(); - - emit endVideoWindowNativePaint(); -} - -QT_END_NAMESPACE - diff --git a/src/3rdparty/phonon/mmf/videooutput_dsa.cpp b/src/3rdparty/phonon/mmf/videooutput_dsa.cpp new file mode 100644 index 0000000..a5e2ac8 --- /dev/null +++ b/src/3rdparty/phonon/mmf/videooutput_dsa.cpp @@ -0,0 +1,177 @@ +/* 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 <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect +#include <QtGui/private/qwidget_p.h> // to access QWExtra +#include <QResizeEvent> +#include <QMoveEvent> + +#include <coemain.h> // for CCoeEnv + +#include "ancestormovemonitor.h" +#include "utils.h" +#include "videooutput_dsa.h" + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +DsaVideoOutput::DsaVideoOutput(QWidget *parent) + : AbstractVideoOutput(parent) + , m_ancestorMoveMonitor(0) +{ + TRACE_CONTEXT(DsaVideoOutput::DsaVideoOutput, EVideoInternal); + TRACE_ENTRY("parent 0x%08x", parent); + + setPalette(QPalette(Qt::black)); + setAttribute(Qt::WA_OpaquePaintEvent, true); + setAttribute(Qt::WA_NoSystemBackground, true); + setAutoFillBackground(false); + + qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::ZeroFill; + qt_widget_private(this)->extraData()->receiveNativePaintEvents = true; + + getVideoWindowScreenRect(); + + dump(); + + TRACE_EXIT_0(); +} + +DsaVideoOutput::~DsaVideoOutput() +{ + TRACE_CONTEXT(DsaVideoOutput::~DsaVideoOutput, EVideoInternal); + TRACE_ENTRY_0(); + + m_ancestorMoveMonitor->unRegisterTarget(this); + + TRACE_EXIT_0(); +} + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + +void MMF::DsaVideoOutput::setAncestorMoveMonitor(AncestorMoveMonitor *monitor) +{ + m_ancestorMoveMonitor = monitor; + registerForAncestorMoved(); +} + +const QRect& MMF::DsaVideoOutput::videoWindowScreenRect() const +{ + return m_videoWindowScreenRect; +} + +void MMF::DsaVideoOutput::ancestorMoved() +{ + TRACE_CONTEXT(DsaVideoOutput::ancestorMoved, EVideoInternal); + TRACE_ENTRY_0(); + + RWindowBase *const window = videoWindow(); + + if (window) { + const TPoint newWindowPosSymbian = window->AbsPosition(); + const QPoint newWindowPos(newWindowPosSymbian.iX, newWindowPosSymbian.iY); + + if (newWindowPos != m_videoWindowScreenRect.topLeft()) { + m_videoWindowScreenRect.moveTo(newWindowPos); + emit videoWindowScreenRectChanged(); + } + } + + TRACE_EXIT_0(); +} + +void MMF::DsaVideoOutput::beginNativePaintEvent(const QRect & /*controlRect*/) +{ + emit beginVideoWindowNativePaint(); +} + +void MMF::DsaVideoOutput::endNativePaintEvent(const QRect & /*controlRect*/) +{ + // Ensure that draw ops are executed into the WSERV output framebuffer + CCoeEnv::Static()->WsSession().Flush(); + + emit endVideoWindowNativePaint(); +} + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +void MMF::DsaVideoOutput::getVideoWindowScreenRect() +{ + RWindowBase *const window = videoWindow(); + if (window) + m_videoWindowScreenRect = + qt_TRect2QRect(TRect(window->AbsPosition(), window->Size())); +} + +void MMF::DsaVideoOutput::registerForAncestorMoved() +{ + m_ancestorMoveMonitor->registerTarget(this); +} + +void MMF::DsaVideoOutput::resizeEvent(QResizeEvent *event) +{ + TRACE_CONTEXT(DsaVideoOutput::resizeEvent, EVideoInternal); + TRACE("%d %d -> %d %d", + event->oldSize().width(), event->oldSize().height(), + event->size().width(), event->size().height()); + + if (event->size() != event->oldSize()) { + m_videoWindowScreenRect.setSize(event->size()); + emit videoWindowScreenRectChanged(); + } +} + +void MMF::DsaVideoOutput::moveEvent(QMoveEvent *event) +{ + TRACE_CONTEXT(DsaVideoOutput::moveEvent, EVideoInternal); + TRACE("%d %d -> %d %d", + event->oldPos().x(), event->oldPos().y(), + event->pos().x(), event->pos().y()); + + if (event->pos() != event->oldPos()) { + m_videoWindowScreenRect.moveTo(event->pos()); + emit videoWindowScreenRectChanged(); + } +} + +bool MMF::DsaVideoOutput::event(QEvent *event) +{ + TRACE_CONTEXT(DsaVideoOutput::event, EVideoInternal); + + if (event->type() == QEvent::WinIdChange) { + TRACE_0("WinIdChange"); + getVideoWindowScreenRect(); + emit videoWindowChanged(); + return true; + } else if (event->type() == QEvent::ParentChange) { + // Tell ancestor move monitor to update ancestor list for this widget + registerForAncestorMoved(); + return true; + } else { + return QWidget::event(event); + } +} + +QT_END_NAMESPACE + diff --git a/src/3rdparty/phonon/mmf/videooutput_dsa.h b/src/3rdparty/phonon/mmf/videooutput_dsa.h new file mode 100644 index 0000000..c37dad8 --- /dev/null +++ b/src/3rdparty/phonon/mmf/videooutput_dsa.h @@ -0,0 +1,109 @@ +/* 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_MMF_VIDEOOUTPUT_DSA_H +#define PHONON_MMF_VIDEOOUTPUT_DSA_H + +#include <QRect> + +#include "phonon/mmf/abstractvideooutput.h" + +QT_BEGIN_NAMESPACE + +class QResizeEvent; +class QMoveEvent; + +namespace Phonon +{ +namespace MMF +{ +class AncestorMoveMonitor; + +/** + * @short Widget on which video is displayed by DSA rendering + * + * This implementation is used on devices with the legacy graphics + * subsystem, which does not support surfaces. On such devices, + * video rendering is done via Direct Screen Access (DSA), whereby + * the video decoder writes directly to the framebuffer. To ensure + * that the window server and video decoder do not try to draw to + * the same screen region at the same time, the video subsystem + * first requests permission to perform DSA. If the window server + * needs to draw to this screen region (for example to display a + * message dialog), it first notifies the video subsystem that it + * must stop rendering to this region. + * + * @see SurfaceVideoOutput + */ +class DsaVideoOutput + : public AbstractVideoOutput +{ + Q_OBJECT + +public: + DsaVideoOutput(QWidget *parent); + ~DsaVideoOutput(); + + void setAncestorMoveMonitor(AncestorMoveMonitor *monitor); + + // Get absolute screen rectangle for video window + const QRect& videoWindowScreenRect() const; + + // Called by AncestorMoveMonitor + void ancestorMoved(); + +public Q_SLOTS: + // Callbacks received from Symbian QtGui implementation, when it + // begins / ends blitting the video widget's backing store to the + // window server. + void beginNativePaintEvent(const QRect & /*controlRect*/); + void endNativePaintEvent(const QRect & /*controlRect*/); + +Q_SIGNALS: + void videoWindowScreenRectChanged(); + + // Emitted when the Symbian QtGui implementation begins / ends + // blitting the video widget's backing store to the window server. + void beginVideoWindowNativePaint(); + void endVideoWindowNativePaint(); + +private: + void getVideoWindowScreenRect(); + void registerForAncestorMoved(); + + // QWidget + void resizeEvent(QResizeEvent *event); + void moveEvent(QMoveEvent *event); + bool event(QEvent *event); + +private: + // Not owned + AncestorMoveMonitor* m_ancestorMoveMonitor; + + // Absolute screen rectangle on which video is displayed + QRect m_videoWindowScreenRect; + +}; + +} +} + +QT_END_NAMESPACE + +#endif // !PHONON_MMF_VIDEOOUTPUT_DSA_H + diff --git a/src/3rdparty/phonon/mmf/videooutput_surface.cpp b/src/3rdparty/phonon/mmf/videooutput_surface.cpp new file mode 100644 index 0000000..e9b2d3f --- /dev/null +++ b/src/3rdparty/phonon/mmf/videooutput_surface.cpp @@ -0,0 +1,87 @@ +/* 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 <QResizeEvent> + +#include <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect +#include <QtGui/private/qwidget_p.h> // to access QWExtra + +#include "utils.h" +#include "videooutput_surface.h" + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +SurfaceVideoOutput::SurfaceVideoOutput(QWidget *parent) + : AbstractVideoOutput(parent) +{ + TRACE_CONTEXT(SurfaceVideoOutput::SurfaceVideoOutput, EVideoInternal); + TRACE_ENTRY("parent 0x%08x", parent); + + qt_widget_private(this)->createExtra(); + qt_widget_private(this)->extraData()->nativePaintMode = QWExtra::Disable; + + TRACE_EXIT_0(); +} + +SurfaceVideoOutput::~SurfaceVideoOutput() +{ + TRACE_CONTEXT(SurfaceVideoOutput::~SurfaceVideoOutput, EVideoInternal); + TRACE_ENTRY_0(); + + TRACE_EXIT_0(); +} + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +void MMF::SurfaceVideoOutput::resizeEvent(QResizeEvent *event) +{ + TRACE_CONTEXT(SurfaceVideoOutput::resizeEvent, EVideoInternal); + TRACE("%d %d -> %d %d", + event->oldSize().width(), event->oldSize().height(), + event->size().width(), event->size().height()); + + if (event->size() != event->oldSize()) + emit videoWindowSizeChanged(); +} + +bool MMF::SurfaceVideoOutput::event(QEvent *event) +{ + TRACE_CONTEXT(SurfaceVideoOutput::event, EVideoInternal); + + if (event->type() == QEvent::WinIdChange) { + TRACE_0("WinIdChange"); + emit videoWindowChanged(); + return true; + } else { + return QWidget::event(event); + } +} + + +QT_END_NAMESPACE + diff --git a/src/3rdparty/phonon/mmf/videooutput_surface.h b/src/3rdparty/phonon/mmf/videooutput_surface.h new file mode 100644 index 0000000..0b22a710 --- /dev/null +++ b/src/3rdparty/phonon/mmf/videooutput_surface.h @@ -0,0 +1,66 @@ +/* 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_MMF_VIDEOOUTPUT_SURFACE_H +#define PHONON_MMF_VIDEOOUTPUT_SURFACE_H + +#include "phonon/mmf/abstractvideooutput.h" + +QT_BEGIN_NAMESPACE + +class QResizeEvent; + +namespace Phonon +{ +namespace MMF +{ + +/** + * @short Widget on which video is displayed by rendering to a surface + * + * This implementation is used on devices with a graphics subsystem which + * supports surfaces. + * + * @see DsaVideoOutput + */ +class SurfaceVideoOutput + : public AbstractVideoOutput +{ + Q_OBJECT + +public: + SurfaceVideoOutput(QWidget *parent); + ~SurfaceVideoOutput(); + +Q_SIGNALS: + void videoWindowSizeChanged(); + +private: + // QWidget + void resizeEvent(QResizeEvent *event); + bool event(QEvent *event); + +}; + +} +} + +QT_END_NAMESPACE + +#endif // !PHONON_MMF_VIDEOOUTPUT_SURFACE_H + diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp new file mode 100644 index 0000000..21cdb16 --- /dev/null +++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.cpp @@ -0,0 +1,285 @@ +/* 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 <coecntrl.h> // for CCoeControl + +#include <QApplication> // for QApplication::activeWindow +#include <QtCore/private/qcore_symbian_p.h> // for qt_TRect2QRect + +#include "utils.h" +#include "videooutput_dsa.h" +#include "videoplayer_dsa.h" + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +// Two-phase constructor idiom is used because construct() calls virtual +// functions and therefore cannot be called from the AbstractVideoPlayer +// C++ constructor. +DsaVideoPlayer* DsaVideoPlayer::create(MediaObject *parent, + const AbstractPlayer *player) +{ + QScopedPointer<DsaVideoPlayer> self(new DsaVideoPlayer(parent, player)); + self->construct(); + return self.take(); +} + +DsaVideoPlayer::DsaVideoPlayer(MediaObject *parent, const AbstractPlayer *player) + : AbstractVideoPlayer(parent, player) + , m_dsaActive(false) + , m_dsaWasActive(false) +{ + +} + +DsaVideoPlayer::~DsaVideoPlayer() +{ + +} + + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + +void MMF::DsaVideoPlayer::videoWindowScreenRectChanged() +{ + QRect windowRect = static_cast<DsaVideoOutput *>(m_videoOutput)->videoWindowScreenRect(); + + // Clip to physical window size + // This is due to a defect in the layout when running on S60 3.2, which + // results in the rectangle of the video widget extending outside the + // screen in certain circumstances. These include the initial startup + // of the mediaplayer demo in portrait mode. When this rectangle is + // passed to the CVideoPlayerUtility, no video is rendered. + const TSize screenSize = m_screenDevice.SizeInPixels(); + const QRect screenRect(0, 0, screenSize.iWidth, screenSize.iHeight); + windowRect = windowRect.intersected(screenRect); + + // Recalculate scale factors. Pass 'false' as second parameter in order to + // suppress application of the change to the player - this is done at the end + // of the function. + updateScaleFactors(windowRect.size(), false); + + m_videoScreenRect = qt_QRect2TRect(windowRect); + + parametersChanged(WindowScreenRect | ScaleFactors); +} + +void MMF::DsaVideoPlayer::suspendDirectScreenAccess() +{ + m_dsaWasActive = stopDirectScreenAccess(); +} + +void MMF::DsaVideoPlayer::resumeDirectScreenAccess() +{ + if (m_dsaWasActive) { + startDirectScreenAccess(); + m_dsaWasActive = false; + } +} + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +void MMF::DsaVideoPlayer::createPlayer() +{ + // A window handle must be provided in order to construct + // CVideoPlayerUtility. If no VideoOutput has yet been connected to this + // player, we temporarily use the top-level application window handle. + // No video ever gets rendered into this window; SetDisplayWindowL is + // always called before rendering actually begins. + if (!m_window) + m_window = QApplication::activeWindow()->effectiveWinId()->DrawableWindow(); + + const TInt priority = 0; + const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone; + + CVideoPlayerUtility *player = 0; + QT_TRAP_THROWING(player = CVideoPlayerUtility::NewL(*this, + priority, preference, + m_wsSession, m_screenDevice, + *m_window, + m_videoScreenRect, m_videoScreenRect)); + m_player.reset(player); + + // CVideoPlayerUtility::NewL starts DSA + m_dsaActive = true; + + m_player->RegisterForVideoLoadingNotification(*this); +} + +void MMF::DsaVideoPlayer::initVideoOutput() +{ + bool connected = connect( + m_videoOutput, SIGNAL(videoWindowScreenRectChanged()), + this, SLOT(videoWindowScreenRectChanged()) + ); + Q_ASSERT(connected); + + connected = connect( + m_videoOutput, SIGNAL(beginVideoWindowNativePaint()), + this, SLOT(suspendDirectScreenAccess()) + ); + Q_ASSERT(connected); + + connected = connect( + m_videoOutput, SIGNAL(endVideoWindowNativePaint()), + this, SLOT(resumeDirectScreenAccess()) + ); + Q_ASSERT(connected); + + // Suppress warnings in release builds + Q_UNUSED(connected); + + AbstractVideoPlayer::initVideoOutput(); +} + +void MMF::DsaVideoPlayer::prepareCompleted() +{ + videoWindowScreenRectChanged(); +} + +void MMF::DsaVideoPlayer::handleVideoWindowChanged() +{ + if (!m_window) { + m_window = QApplication::activeWindow()->effectiveWinId()->DrawableWindow(); + m_videoScreenRect = TRect(); + } + + parametersChanged(WindowHandle | WindowScreenRect); +} + +#ifndef QT_NO_DEBUG + +// The following code is for debugging problems related to video visibility. It allows +// the VideoPlayer instance to query the window server in order to determine the +// DSA drawing region for the video window. + +class CDummyAO : public CActive +{ +public: + CDummyAO() : CActive(CActive::EPriorityStandard) { CActiveScheduler::Add(this); } + void RunL() { } + void DoCancel() { } + TRequestStatus& Status() { return iStatus; } + void SetActive() { CActive::SetActive(); } +}; + +void getDsaRegion(RWsSession &session, const RWindowBase &window) +{ + RDirectScreenAccess dsa(session); + TInt err = dsa.Construct(); + CDummyAO ao; + RRegion* region; + err = dsa.Request(region, ao.Status(), window); + ao.SetActive(); + dsa.Close(); + ao.Cancel(); + if (region) { + qDebug() << "Phonon::MMF::getDsaRegion count" << region->Count(); + for (int i=0; i<region->Count(); ++i) { + const TRect& rect = region->RectangleList()[i]; + qDebug() << "Phonon::MMF::getDsaRegion rect" + << rect.iTl.iX << rect.iTl.iY << rect.iBr.iX << rect.iBr.iY; + } + region->Close(); + } +} + +#endif // QT_NO_DEBUG + +void MMF::DsaVideoPlayer::handleParametersChanged(VideoParameters parameters) +{ + TRACE_CONTEXT(DsaVideoPlayer::handleParametersChanged, EVideoInternal); + TRACE_ENTRY_0(); + +#ifndef QT_NO_DEBUG + getDsaRegion(m_wsSession, *m_window); +#endif + + static const TBool antialias = ETrue; + int err = KErrNone; + + if (parameters & ScaleFactors) { + TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, + antialias)); + if(KErrNone != err) { + TRACE("SetScaleFactorL (1) err %d", err); + setError(tr("Video display error"), err); + } + } + + if (KErrNone == err) { + if (parameters & WindowHandle || parameters & WindowScreenRect) { + TRAP(err, + m_player->SetDisplayWindowL(m_wsSession, m_screenDevice, + *m_window, + m_videoScreenRect, + m_videoScreenRect)); + } + + if (KErrNone != err) { + TRACE("SetDisplayWindowL err %d", err); + setError(tr("Video display error"), err); + } else { + m_dsaActive = true; + if (parameters & ScaleFactors) { + TRAP(err, m_player->SetScaleFactorL(m_scaleWidth, m_scaleHeight, + antialias)); + if (KErrNone != err) { + TRACE("SetScaleFactorL (2) err %d", err); + setError(tr("Video display error"), err); + } + } + } + } + + TRACE_EXIT_0(); +} + +void MMF::DsaVideoPlayer::startDirectScreenAccess() +{ + if (!m_dsaActive) { + TRAPD(err, m_player->StartDirectScreenAccessL()); + if (KErrNone == err) + m_dsaActive = true; + else + setError(tr("Video display error"), err); + } +} + +bool MMF::DsaVideoPlayer::stopDirectScreenAccess() +{ + const bool dsaWasActive = m_dsaActive; + if (m_dsaActive) { + TRAPD(err, m_player->StopDirectScreenAccessL()); + if (KErrNone == err) + m_dsaActive = false; + else + setError(tr("Video display error"), err); + } + return dsaWasActive; +} + +QT_END_NAMESPACE + diff --git a/src/3rdparty/phonon/mmf/videoplayer_dsa.h b/src/3rdparty/phonon/mmf/videoplayer_dsa.h new file mode 100644 index 0000000..45cc47d --- /dev/null +++ b/src/3rdparty/phonon/mmf/videoplayer_dsa.h @@ -0,0 +1,92 @@ +/* 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_MMF_VIDEOPLAYER_DSA_H +#define PHONON_MMF_VIDEOPLAYER_DSA_H + +#include "abstractvideoplayer.h" + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace MMF +{ + +/** + * @short Wrapper over the MMF video player utility (DSA version) + * + * This implementation is used on devices with the legacy graphics + * subsystem, which does not support surfaces. On such devices, + * video rendering is done via Direct Screen Access (DSA), whereby + * the video decoder writes directly to the framebuffer. To ensure + * that the window server and video decoder do not try to draw to + * the same screen region at the same time, the video subsystem + * first requests permission to perform DSA. If the window server + * needs to draw to this screen region (for example to display a + * message dialog), it first notifies the video subsystem that it + * must stop rendering to this region. + * + * @see SurfaceVideoPlayer + */ +class DsaVideoPlayer + : public AbstractVideoPlayer +{ + Q_OBJECT + +public: + // Factory function + static DsaVideoPlayer* create(MediaObject *parent = 0, + const AbstractPlayer *player = 0); + ~DsaVideoPlayer(); + +public Q_SLOTS: + void videoWindowScreenRectChanged(); + void suspendDirectScreenAccess(); + void resumeDirectScreenAccess(); + +private: + DsaVideoPlayer(MediaObject *parent, const AbstractPlayer *player); + + // AbstractVideoPlayer + void createPlayer(); + void initVideoOutput(); + void prepareCompleted(); + void handleVideoWindowChanged(); + void handleParametersChanged(VideoParameters parameters); + + void startDirectScreenAccess(); + bool stopDirectScreenAccess(); + +private: + bool m_dsaActive; + bool m_dsaWasActive; + + // Absolute screen rectangle on which video is displayed + TRect m_videoScreenRect; + +}; + +} +} + +QT_END_NAMESPACE + +#endif // !PHONON_MMF_VIDEOPLAYER_DSA_H + + diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.cpp b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp new file mode 100644 index 0000000..5f234e5 --- /dev/null +++ b/src/3rdparty/phonon/mmf/videoplayer_surface.cpp @@ -0,0 +1,150 @@ +/* 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 <videoplayer2.h> + +#include <QtCore/private/qcore_symbian_p.h> // for qt_QRect2TRect + +#include "utils.h" +#include "videooutput_surface.h" +#include "videoplayer_surface.h" + +QT_BEGIN_NAMESPACE + +using namespace Phonon; +using namespace Phonon::MMF; + +// Two-phase constructor idiom is used because construct() calls virtual +// functions and therefore cannot be called from the AbstractVideoPlayer +// C++ constructor. +SurfaceVideoPlayer* SurfaceVideoPlayer::create(MediaObject *parent, + const AbstractPlayer *player) +{ + QScopedPointer<SurfaceVideoPlayer> self(new SurfaceVideoPlayer(parent, player)); + self->construct(); + return self.take(); +} + +SurfaceVideoPlayer::SurfaceVideoPlayer(MediaObject *parent, const AbstractPlayer *player) + : AbstractVideoPlayer(parent, player) + , m_displayWindow(0) +{ + +} + +SurfaceVideoPlayer::~SurfaceVideoPlayer() +{ + +} + + +//----------------------------------------------------------------------------- +// Public functions +//----------------------------------------------------------------------------- + +void MMF::SurfaceVideoPlayer::videoWindowSizeChanged() +{ + updateScaleFactors(m_videoOutput->videoWindowSize()); +} + + +//----------------------------------------------------------------------------- +// Private functions +//----------------------------------------------------------------------------- + +void MMF::SurfaceVideoPlayer::createPlayer() +{ + const TInt priority = 0; + const TMdaPriorityPreference preference = EMdaPriorityPreferenceNone; + + CVideoPlayerUtility2 *player = 0; + QT_TRAP_THROWING(player = CVideoPlayerUtility2::NewL(*this, + priority, preference)); + m_player.reset(player); +} + +void MMF::SurfaceVideoPlayer::initVideoOutput() +{ + bool connected = connect( + m_videoOutput, SIGNAL(videoWindowSizeChanged()), + this, SLOT(videoWindowSizeChanged()) + ); + Q_ASSERT(connected); + + // Suppress warnings in release builds + Q_UNUSED(connected); + + AbstractVideoPlayer::initVideoOutput(); +} + +void MMF::SurfaceVideoPlayer::prepareCompleted() +{ + videoWindowSizeChanged(); +} + +void MMF::SurfaceVideoPlayer::handleVideoWindowChanged() +{ + parametersChanged(WindowHandle); +} + +void MMF::SurfaceVideoPlayer::handleParametersChanged(VideoParameters parameters) +{ + CVideoPlayerUtility2 *player = static_cast<CVideoPlayerUtility2 *>(m_player.data()); + + int err = KErrNone; + + TRect rect; + + if (m_videoOutput) { + m_videoOutput->dump(); + const QSize size = m_videoOutput->videoWindowSize(); + rect.SetSize(TSize(size.width(), size.height())); + } + + if (parameters & WindowHandle) { + if (m_displayWindow) + player->RemoveDisplayWindow(*m_displayWindow); + + RWindow *window = static_cast<RWindow *>(m_window); + if (window) { + window->SetBackgroundColor(TRgb(0, 0, 0, 255)); + TRAP(err, player->AddDisplayWindowL(m_wsSession, m_screenDevice, *window, rect, rect)); + if (KErrNone != err) { + setError(tr("Video display error"), err); + window = 0; + } + } + m_displayWindow = window; + } + + if (KErrNone == err) { + if (parameters & ScaleFactors) { + Q_ASSERT(m_displayWindow); + TRAP(err, player->SetVideoExtentL(*m_displayWindow, rect)); + if (KErrNone == err) + TRAP(err, player->SetWindowClipRectL(*m_displayWindow, rect)); + if (KErrNone == err) + TRAP(err, player->SetScaleFactorL(*m_displayWindow, m_scaleWidth, m_scaleHeight)); + if (KErrNone != err) + setError(tr("Video display error"), err); + } + } +} + +QT_END_NAMESPACE + diff --git a/src/3rdparty/phonon/mmf/videoplayer_surface.h b/src/3rdparty/phonon/mmf/videoplayer_surface.h new file mode 100644 index 0000000..c05da9c --- /dev/null +++ b/src/3rdparty/phonon/mmf/videoplayer_surface.h @@ -0,0 +1,78 @@ +/* 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_MMF_VIDEOPLAYER_SURFACE_H +#define PHONON_MMF_VIDEOPLAYER_SURFACE_H + +#include "abstractvideoplayer.h" + +class RWindow; + +QT_BEGIN_NAMESPACE + +namespace Phonon +{ +namespace MMF +{ + +/** + * @short Wrapper over the MMF video player utility (surface version) + * + * This implementation is used on devices with a graphics subsystem which + * supports surfaces. + * + * @see DsaVideoPlayer + */ +class SurfaceVideoPlayer + : public AbstractVideoPlayer +{ + Q_OBJECT + +public: + // Factory function + static SurfaceVideoPlayer* create(MediaObject *parent = 0, + const AbstractPlayer *player = 0); + ~SurfaceVideoPlayer(); + +public Q_SLOTS: + void videoWindowSizeChanged(); + +private: + SurfaceVideoPlayer(MediaObject *parent, const AbstractPlayer *player); + + // AbstractVideoPlayer + void createPlayer(); + void initVideoOutput(); + void prepareCompleted(); + void handleVideoWindowChanged(); + void handleParametersChanged(VideoParameters parameters); + +private: + // Window handle which has been passed to the MMF via + // CVideoPlayerUtility2::SetDisplayWindowL + RWindow* m_displayWindow; + +}; + +} +} + +QT_END_NAMESPACE + +#endif // !PHONON_MMF_VIDEOPLAYER_SURFACE_H + diff --git a/src/3rdparty/phonon/mmf/videowidget.cpp b/src/3rdparty/phonon/mmf/videowidget.cpp index bc9acfd..4ed9979 100644 --- a/src/3rdparty/phonon/mmf/videowidget.cpp +++ b/src/3rdparty/phonon/mmf/videowidget.cpp @@ -18,10 +18,15 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #include "mediaobject.h" #include "utils.h" -#include "videooutput.h" #include "videowidget.h" +#ifdef PHONON_MMF_VIDEO_SURFACES +#include "videooutput_surface.h" +#else +#include "videooutput_dsa.h" +#endif + QT_BEGIN_NAMESPACE using namespace Phonon; @@ -45,10 +50,13 @@ static const qreal DefaultSaturation = 1.0; // Constructor / destructor //----------------------------------------------------------------------------- -MMF::VideoWidget::VideoWidget - (AncestorMoveMonitor* ancestorMoveMonitor, QWidget* parent) +MMF::VideoWidget::VideoWidget(QWidget *parent) : MediaNode(parent) - , m_videoOutput(new VideoOutput(ancestorMoveMonitor, parent)) +#ifdef PHONON_MMF_VIDEO_SURFACES + , m_videoOutput(new SurfaceVideoOutput(parent)) +#else + , m_videoOutput(new DsaVideoOutput(parent)) +#endif , m_brightness(DefaultBrightness) , m_contrast(DefaultContrast) , m_hue(DefaultHue) @@ -68,6 +76,13 @@ MMF::VideoWidget::~VideoWidget() TRACE_EXIT_0(); } +#ifndef PHONON_MMF_VIDEO_SURFACES +void MMF::VideoWidget::setAncestorMoveMonitor(AncestorMoveMonitor *monitor) +{ + static_cast<DsaVideoOutput *>(m_videoOutput.data())->setAncestorMoveMonitor(monitor); +} +#endif + //----------------------------------------------------------------------------- // VideoWidgetInterface diff --git a/src/3rdparty/phonon/mmf/videowidget.h b/src/3rdparty/phonon/mmf/videowidget.h index 899dca6..3b6283e 100644 --- a/src/3rdparty/phonon/mmf/videowidget.h +++ b/src/3rdparty/phonon/mmf/videowidget.h @@ -19,8 +19,8 @@ along with this library. If not, see <http://www.gnu.org/licenses/>. #ifndef PHONON_MMF_VIDEOWIDGET_H #define PHONON_MMF_VIDEOWIDGET_H +#include "abstractvideooutput.h" #include "mmf_medianode.h" -#include "videooutput.h" #include <QtGui/QWidget> #include <phonon/videowidget.h> @@ -32,8 +32,9 @@ namespace Phonon { namespace MMF { +#ifndef PHONON_MMF_VIDEO_SURFACES class AncestorMoveMonitor; -class VideoOutput; +#endif class VideoWidget : public MediaNode , public Phonon::VideoWidgetInterface @@ -42,9 +43,13 @@ class VideoWidget : public MediaNode Q_INTERFACES(Phonon::VideoWidgetInterface) public: - VideoWidget(AncestorMoveMonitor* ancestorMoveMonitor, QWidget* parent); + VideoWidget(QWidget* parent); ~VideoWidget(); +#ifndef PHONON_MMF_VIDEO_SURFACES + void setAncestorMoveMonitor(AncestorMoveMonitor *ancestorMoveMonitor); +#endif + // VideoWidgetInterface virtual Phonon::VideoWidget::AspectRatio aspectRatio() const; virtual void setAspectRatio(Phonon::VideoWidget::AspectRatio aspectRatio); @@ -66,7 +71,7 @@ protected: void disconnectMediaObject(MediaObject *mediaObject); private: - QScopedPointer<VideoOutput> m_videoOutput; + QScopedPointer<AbstractVideoOutput> m_videoOutput; qreal m_brightness; qreal m_contrast; diff --git a/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h b/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h index 52a24f6..3e25c95 100644 --- a/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h +++ b/src/3rdparty/webkit/JavaScriptCore/wtf/Threading.h @@ -73,7 +73,7 @@ #include <windows.h> #elif PLATFORM(DARWIN) #include <libkern/OSAtomic.h> -#elif COMPILER(GCC) && !PLATFORM(SYMBIAN) +#elif COMPILER(GCC) && !defined(__SYMBIAN32__) #if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 2)) #include <ext/atomicity.h> #else @@ -232,7 +232,7 @@ inline int atomicDecrement(int volatile* addend) { return InterlockedDecrement(r inline int atomicIncrement(int volatile* addend) { return OSAtomicIncrement32Barrier(const_cast<int*>(addend)); } inline int atomicDecrement(int volatile* addend) { return OSAtomicDecrement32Barrier(const_cast<int*>(addend)); } -#elif COMPILER(GCC) && !PLATFORM(SPARC64) && !PLATFORM(SYMBIAN) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc +#elif COMPILER(GCC) && !PLATFORM(SPARC64) && !defined(__SYMBIAN32__) // sizeof(_Atomic_word) != sizeof(int) on sparc64 gcc #define WTF_USE_LOCKFREE_THREADSAFESHARED 1 inline int atomicIncrement(int volatile* addend) { return __gnu_cxx::__exchange_and_add(addend, 1) + 1; } diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp index ceb5ee1..a80c5d3 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp +++ b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.cpp @@ -30,6 +30,7 @@ #include <QtGui/qapplication.h> #include <QtGui/qgraphicssceneevent.h> #include <QtGui/qstyleoption.h> +#include <QtGui/qinputcontext.h> #if defined(Q_WS_X11) #include <QX11Info> #endif @@ -63,6 +64,8 @@ public: void _q_doLoadFinished(bool success); + void _q_updateMicroFocus(); + QGraphicsWebView* q; QWebPage* page; }; @@ -80,6 +83,20 @@ void QGraphicsWebViewPrivate::_q_doLoadFinished(bool success) emit q->loadFinished(success); } +void QGraphicsWebViewPrivate::_q_updateMicroFocus() +{ +#if !defined(QT_NO_IM) && (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) + // Ideally, this should be handled by a common call to an updateMicroFocus function + // in QGraphicsItem. See http://bugreports.qt.nokia.com/browse/QTBUG-7578. + QList<QGraphicsView*> views = q->scene()->views(); + for (int c = 0; c < views.size(); ++c) { + QInputContext* ic = views.at(c)->inputContext(); + if (ic) + ic->update(); + } +#endif +} + void QGraphicsWebViewPrivate::scroll(int dx, int dy, const QRect& rectToScroll) { q->scroll(qreal(dx), qreal(dy), QRectF(rectToScroll)); @@ -435,6 +452,8 @@ void QGraphicsWebView::setPage(QWebPage* page) this, SIGNAL(statusBarMessage(QString))); connect(d->page, SIGNAL(linkClicked(QUrl)), this, SIGNAL(linkClicked(QUrl))); + connect(d->page, SIGNAL(microFocusChanged()), + this, SLOT(_q_updateMicroFocus())); } /*! diff --git a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h index f3afb4c..68379a2 100644 --- a/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h +++ b/src/3rdparty/webkit/WebKit/qt/Api/qgraphicswebview.h @@ -140,3 +140,4 @@ private: }; #endif // QGraphicsWebView_h + Q_PRIVATE_SLOT(d, void _q_updateMicroFocus()) diff --git a/src/3rdparty/webkit/WebKit/qt/ChangeLog b/src/3rdparty/webkit/WebKit/qt/ChangeLog index e54c176..a5441cd 100644 --- a/src/3rdparty/webkit/WebKit/qt/ChangeLog +++ b/src/3rdparty/webkit/WebKit/qt/ChangeLog @@ -1,3 +1,15 @@ +2010-03-21 Kristian Amlie <kristian.amlie@nokia.com> + + Reviewed by Simon Hausmann. + + Fixed updating the VKB display when inputting into QGraphicsWebView. + https://bugs.webkit.org/show_bug.cgi?id=36292 + + * Api/qgraphicswebview.cpp: + (QGraphicsWebViewPrivate::_q_updateMicroFocus): + (QGraphicsWebView::setPage): + * Api/qgraphicswebview.h: + 2010-03-04 Simon Hausmann <simon.hausmann@nokia.com> Reviewed by Kenneth Rohde Christiansen. diff --git a/src/corelib/animation/qanimationgroup.cpp b/src/corelib/animation/qanimationgroup.cpp index a89f949..2decda3 100644 --- a/src/corelib/animation/qanimationgroup.cpp +++ b/src/corelib/animation/qanimationgroup.cpp @@ -244,7 +244,7 @@ QAbstractAnimation *QAnimationGroup::takeAnimation(int index) // in ChildRemoved event d->animations.removeAt(index); animation->setParent(0); - d->animationRemovedAt(index); + d->animationRemoved(index, animation); return animation; } @@ -285,7 +285,7 @@ bool QAnimationGroup::event(QEvent *event) } -void QAnimationGroupPrivate::animationRemovedAt(int index) +void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *) { Q_Q(QAnimationGroup); Q_UNUSED(index); diff --git a/src/corelib/animation/qanimationgroup_p.h b/src/corelib/animation/qanimationgroup_p.h index 394773b..45603b3 100644 --- a/src/corelib/animation/qanimationgroup_p.h +++ b/src/corelib/animation/qanimationgroup_p.h @@ -72,8 +72,19 @@ public: isGroup = true; } - virtual void animationInsertedAt(int index) { Q_UNUSED(index) }; - virtual void animationRemovedAt(int index); + virtual void animationInsertedAt(int) { } + virtual void animationRemoved(int, QAbstractAnimation *); + + void disconnectUncontrolledAnimation(QAbstractAnimation *anim) + { + //0 for the signal here because we might be called from the animation destructor + QObject::disconnect(anim, 0, q_func(), SLOT(_q_uncontrolledAnimationFinished())); + } + + void connectUncontrolledAnimation(QAbstractAnimation *anim) + { + QObject::connect(anim, SIGNAL(finished()), q_func(), SLOT(_q_uncontrolledAnimationFinished())); + } QList<QAbstractAnimation *> animations; }; diff --git a/src/corelib/animation/qparallelanimationgroup.cpp b/src/corelib/animation/qparallelanimationgroup.cpp index eaa0364..280afed 100644 --- a/src/corelib/animation/qparallelanimationgroup.cpp +++ b/src/corelib/animation/qparallelanimationgroup.cpp @@ -246,11 +246,9 @@ void QParallelAnimationGroupPrivate::_q_uncontrolledAnimationFinished() void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations() { - Q_Q(QParallelAnimationGroup); - QHash<QAbstractAnimation *, int>::iterator it = uncontrolledFinishTime.begin(); while (it != uncontrolledFinishTime.end()) { - QObject::disconnect(it.key(), SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + disconnectUncontrolledAnimation(it.key()); ++it; } @@ -259,13 +257,11 @@ void QParallelAnimationGroupPrivate::disconnectUncontrolledAnimations() void QParallelAnimationGroupPrivate::connectUncontrolledAnimations() { - Q_Q(QParallelAnimationGroup); - for (int i = 0; i < animations.size(); ++i) { QAbstractAnimation *animation = animations.at(i); if (animation->duration() == -1 || animation->loopCount() < 0) { uncontrolledFinishTime[animation] = -1; - QObject::connect(animation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + connectUncontrolledAnimation(animation); } } } @@ -305,6 +301,13 @@ bool QParallelAnimationGroupPrivate::isUncontrolledAnimationFinished(QAbstractAn return uncontrolledFinishTime.value(anim, -1) >= 0; } +void QParallelAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim) +{ + QAnimationGroupPrivate::animationRemoved(index, anim); + disconnectUncontrolledAnimation(anim); + uncontrolledFinishTime.remove(anim); +} + /*! \reimp */ diff --git a/src/corelib/animation/qparallelanimationgroup_p.h b/src/corelib/animation/qparallelanimationgroup_p.h index a74d496..cab4fa9 100644 --- a/src/corelib/animation/qparallelanimationgroup_p.h +++ b/src/corelib/animation/qparallelanimationgroup_p.h @@ -80,6 +80,8 @@ public: void connectUncontrolledAnimations(); void disconnectUncontrolledAnimations(); + void animationRemoved(int index, QAbstractAnimation *); + // private slot void _q_uncontrolledAnimationFinished(); }; diff --git a/src/corelib/animation/qsequentialanimationgroup.cpp b/src/corelib/animation/qsequentialanimationgroup.cpp index 8ab084a..5ca30e6 100644 --- a/src/corelib/animation/qsequentialanimationgroup.cpp +++ b/src/corelib/animation/qsequentialanimationgroup.cpp @@ -464,12 +464,7 @@ void QSequentialAnimationGroupPrivate::setCurrentAnimation(int index, bool inter void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediate) { - Q_Q(QSequentialAnimationGroup); - - if (!currentAnimation) - return; - - if (state == QSequentialAnimationGroup::Stopped) + if (!currentAnimation || state == QSequentialAnimationGroup::Stopped) return; currentAnimation->stop(); @@ -479,7 +474,7 @@ void QSequentialAnimationGroupPrivate::activateCurrentAnimation(bool intermediat // connects to the finish signal of uncontrolled animations if (currentAnimation->totalDuration() == -1) - QObject::connect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + connectUncontrolledAnimation(currentAnimation); currentAnimation->start(); if (!intermediate && state == QSequentialAnimationGroup::Paused) @@ -496,7 +491,7 @@ void QSequentialAnimationGroupPrivate::_q_uncontrolledAnimationFinished() actualDuration.append(-1); actualDuration[currentAnimationIndex] = currentAnimation->currentTime(); - QObject::disconnect(currentAnimation, SIGNAL(finished()), q, SLOT(_q_uncontrolledAnimationFinished())); + disconnectUncontrolledAnimation(currentAnimation); if ((direction == QAbstractAnimation::Forward && currentAnimation == animations.last()) || (direction == QAbstractAnimation::Backward && currentAnimationIndex == 0)) { @@ -543,10 +538,10 @@ void QSequentialAnimationGroupPrivate::animationInsertedAt(int index) the group at index \a index. The animation is no more listed when this method is called. */ -void QSequentialAnimationGroupPrivate::animationRemovedAt(int index) +void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *anim) { Q_Q(QSequentialAnimationGroup); - QAnimationGroupPrivate::animationRemovedAt(index); + QAnimationGroupPrivate::animationRemoved(index, anim); Q_ASSERT(currentAnimation); // currentAnimation should always be set @@ -555,7 +550,10 @@ void QSequentialAnimationGroupPrivate::animationRemovedAt(int index) const int currentIndex = animations.indexOf(currentAnimation); if (currentIndex == -1) { - //we're removing the current animation, let's update it to another one + //we're removing the current animation + + disconnectUncontrolledAnimation(currentAnimation); + if (index < animations.count()) setCurrentAnimation(index); //let's try to take the next one else if (index > 0) diff --git a/src/corelib/animation/qsequentialanimationgroup_p.h b/src/corelib/animation/qsequentialanimationgroup_p.h index a55e136..de69916 100644 --- a/src/corelib/animation/qsequentialanimationgroup_p.h +++ b/src/corelib/animation/qsequentialanimationgroup_p.h @@ -85,7 +85,7 @@ public: void activateCurrentAnimation(bool intermediate = false); void animationInsertedAt(int index); - void animationRemovedAt(int index); + void animationRemoved(int index, QAbstractAnimation *anim); bool atEnd() const; diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 6437fb7..3118f8f 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -2429,12 +2429,15 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); #define Q_SYMBIAN_FIXED_POINTER_CURSORS #define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE #define Q_SYMBIAN_WINDOW_SIZE_CACHE -//enabling new graphics resources -#define QT_SYMBIAN_SUPPORTS_SGIMAGE #define QT_SYMBIAN_SUPPORTS_ADVANCED_POINTER +//enabling new graphics resources +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE +# define QT_SYMBIAN_SUPPORTS_SGIMAGE +#endif + #ifdef SYMBIAN_GRAPHICS_WSERV_QT_EFFECTS -#define Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE +# define Q_SYMBIAN_SEMITRANSPARENT_BG_SURFACE #endif #endif diff --git a/src/corelib/io/qprocess_symbian.cpp b/src/corelib/io/qprocess_symbian.cpp index 8902f7d..92212fe 100644 --- a/src/corelib/io/qprocess_symbian.cpp +++ b/src/corelib/io/qprocess_symbian.cpp @@ -237,11 +237,15 @@ static void qt_create_symbian_commandline(const QStringList &arguments, QString --i; endQuote += QLatin1String("\\"); } - commandLine += QLatin1String(" \"") + tmp.left(i) + endQuote; + commandLine += QLatin1String("\"") + tmp.left(i) + endQuote + QLatin1Char(' '); } else { - commandLine += QLatin1Char(' ') + tmp; + commandLine += tmp + QLatin1Char(' '); } } + + // Chop the extra trailing space if any arguments were appended + if (arguments.size()) + commandLine.chop(1); } static TInt qt_create_symbian_process(RProcess **proc, const QString &programName, const QStringList &arguments) diff --git a/src/corelib/kernel/qcore_symbian_p.cpp b/src/corelib/kernel/qcore_symbian_p.cpp index 0257ac4..402eccf 100644 --- a/src/corelib/kernel/qcore_symbian_p.cpp +++ b/src/corelib/kernel/qcore_symbian_p.cpp @@ -132,9 +132,10 @@ private: void init() { #ifdef Q_WS_S60 - _LIT(KLibName_3_1, "qts60plugin_3_1.dll"); - _LIT(KLibName_3_2, "qts60plugin_3_2.dll"); - _LIT(KLibName_5_0, "qts60plugin_5_0.dll"); + _LIT(KLibName_3_1, "qts60plugin_3_1" QT_LIBINFIX_UNICODE L".dll"); + _LIT(KLibName_3_2, "qts60plugin_3_2" QT_LIBINFIX_UNICODE L".dll"); + _LIT(KLibName_5_0, "qts60plugin_5_0" QT_LIBINFIX_UNICODE L".dll"); + TPtrC libName; TInt uidValue; switch (QSysInfo::s60Version()) { diff --git a/src/corelib/kernel/qcore_symbian_p.h b/src/corelib/kernel/qcore_symbian_p.h index 9f282d5..4a515ce 100644 --- a/src/corelib/kernel/qcore_symbian_p.h +++ b/src/corelib/kernel/qcore_symbian_p.h @@ -60,6 +60,15 @@ #include <qhash.h> #include <f32file.h> +#define QT_LSTRING2(x) L##x +#define QT_LSTRING(x) QT_LSTRING2(x) + +#if defined(QT_LIBINFIX) +# define QT_LIBINFIX_UNICODE QT_LSTRING(QT_LIBINFIX) +#else +# define QT_LIBINFIX_UNICODE L"" +#endif + QT_BEGIN_HEADER QT_BEGIN_NAMESPACE diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 312c4b2..4ad78fd 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -483,38 +483,37 @@ int QMetaObject::classInfoCount() const } /** \internal -* helper class for indexOf{Method,Slot,Signal}, returns the relative index of the method within +* helper function for indexOf{Method,Slot,Signal}, returns the relative index of the method within * the baseObject * \a MethodType might be MethodSignal or MethodSlot, or 0 to match everything. +* \a normalizeStringData set to true if we should do a second pass for old moc generated files normalizing all the symbols. */ template<int MethodType> static inline int indexOfMethodRelative(const QMetaObject **baseObject, const char *method, bool normalizeStringData) { - const QMetaObject *m; - for (m = *baseObject; m; m = *baseObject = m->d.superdata) { - const QMetaObject *const m = *baseObject; + for (const QMetaObject *m = *baseObject; m; m = m->d.superdata) { int i = (MethodType == MethodSignal && priv(m->d.data)->revision >= 4) ? (priv(m->d.data)->signalCount - 1) : (priv(m->d.data)->methodCount - 1); - if (i < 0) - continue; - const int end = (MethodType == MethodSlot && priv(m->d.data)->revision >= 4) ? (priv(m->d.data)->signalCount) : 0; if (!normalizeStringData) { for (; i >= end; --i) { - if ((MethodType == 0 || (m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodType) - && strcmp(method, m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i]) == 0) + const char *stringdata = m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5*i]; + if (method[0] == stringdata[0] && strcmp(method + 1, stringdata + 1) == 0) { + *baseObject = m; return i; + } } } else if (priv(m->d.data)->revision < 5) { - const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]); - const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata); for (; i >= end; --i) { - if ((MethodType == 0|| (m->d.data[priv(m->d.data)->methodData + 5*i + 4] & MethodTypeMask) == MethodType) - && normalizedSignature == method) + const char *stringdata = (m->d.stringdata + m->d.data[priv(m->d.data)->methodData + 5 * i]); + const QByteArray normalizedSignature = QMetaObject::normalizedSignature(stringdata); + if (normalizedSignature == method) { + *baseObject = m; return i; + } } } } @@ -537,8 +536,8 @@ int QMetaObject::indexOfConstructor(const char *constructor) const if (priv(d.data)->revision < 2) return -1; for (int i = priv(d.data)->constructorCount-1; i >= 0; --i) { - if (strcmp(constructor, d.stringdata - + d.data[priv(d.data)->constructorData + 5*i]) == 0) { + const char *data = d.stringdata + d.data[priv(d.data)->constructorData + 5*i]; + if (data[0] == constructor[0] && strcmp(constructor + 1, data + 1) == 0) { return i; } } @@ -682,18 +681,19 @@ static const QMetaObject *QMetaObject_findMetaObject(const QMetaObject *self, co */ int QMetaObject::indexOfEnumerator(const char *name) const { - int i = -1; const QMetaObject *m = this; - while (m && i < 0) { - for (i = priv(m->d.data)->enumeratorCount-1; i >= 0; --i) - if (strcmp(name, m->d.stringdata - + m->d.data[priv(m->d.data)->enumeratorData + 4*i]) == 0) { + while (m) { + const QMetaObjectPrivate *d = priv(m->d.data); + for (int i = d->enumeratorCount - 1; i >= 0; --i) { + const char *prop = m->d.stringdata + m->d.data[d->enumeratorData + 4*i]; + if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) { i += m->enumeratorOffset(); - break; + return i; } + } m = m->d.superdata; } - return i; + return -1; } /*! @@ -704,26 +704,27 @@ int QMetaObject::indexOfEnumerator(const char *name) const */ int QMetaObject::indexOfProperty(const char *name) const { - int i = -1; const QMetaObject *m = this; - while (m && i < 0) { - for (i = priv(m->d.data)->propertyCount-1; i >= 0; --i) - if (strcmp(name, m->d.stringdata - + m->d.data[priv(m->d.data)->propertyData + 3*i]) == 0) { + while (m) { + const QMetaObjectPrivate *d = priv(m->d.data); + for (int i = d->propertyCount-1; i >= 0; --i) { + const char *prop = m->d.stringdata + m->d.data[d->propertyData + 3*i]; + if (name[0] == prop[0] && strcmp(name + 1, prop + 1) == 0) { i += m->propertyOffset(); - break; + return i; } + } m = m->d.superdata; } - if (i == -1 && priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)){ + if (priv(this->d.data)->revision >= 3 && (priv(this->d.data)->flags & DynamicMetaObject)) { QAbstractDynamicMetaObject *me = const_cast<QAbstractDynamicMetaObject *>(static_cast<const QAbstractDynamicMetaObject *>(this)); - i = me->createProperty(name, 0); + return me->createProperty(name, 0); } - return i; + return -1; } /*! diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h index b045c42..555a1f5 100644 --- a/src/corelib/kernel/qobjectdefs.h +++ b/src/corelib/kernel/qobjectdefs.h @@ -78,6 +78,7 @@ class QString; #define Q_CLASSINFO(name, value) #define Q_INTERFACES(x) #define Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) #define Q_OVERRIDE(text) #define Q_ENUMS(x) #define Q_FLAGS(x) @@ -178,6 +179,7 @@ private: #define Q_CLASSINFO(name, value) Q_CLASSINFO(name, value) #define Q_INTERFACES(x) Q_INTERFACES(x) #define Q_PROPERTY(text) Q_PROPERTY(text) +#define Q_PRIVATE_PROPERTY(d, text) Q_PRIVATE_PROPERTY(d, text) #define Q_OVERRIDE(text) Q_OVERRIDE(text) #define Q_ENUMS(x) Q_ENUMS(x) #define Q_FLAGS(x) Q_FLAGS(x) diff --git a/src/declarative/util/util.pri b/src/declarative/util/util.pri index ddf00ea..f455870 100644 --- a/src/declarative/util/util.pri +++ b/src/declarative/util/util.pri @@ -62,8 +62,7 @@ HEADERS += \ $$PWD/qdeclarativebehavior_p.h \ $$PWD/qdeclarativefontloader_p.h \ $$PWD/qdeclarativestyledtext_p.h \ - $$PWD/qdeclarativelistmodelworkeragent_p.h \ - $$PWD/qdeclarativelistmodelworkeragent_p_p.h + $$PWD/qdeclarativelistmodelworkeragent_p.h contains(QT_CONFIG, xmlpatterns) { QT+=xmlpatterns diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 3c255ef..948ff28 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -3482,7 +3482,7 @@ void QGraphicsItem::setX(qreal x) if (qIsNaN(x)) return; - d_ptr->setPosHelper(QPointF(x, d_ptr->pos.y())); + setPos(QPointF(x, d_ptr->pos.y())); } /*! @@ -3509,7 +3509,7 @@ void QGraphicsItem::setY(qreal y) if (qIsNaN(y)) return; - d_ptr->setPosHelper(QPointF(d_ptr->pos.x(), y)); + setPos(QPointF(d_ptr->pos.x(), y)); } /*! @@ -3577,7 +3577,7 @@ void QGraphicsItem::setPos(const QPointF &pos) return; // Update and repositition. - if (!(d_ptr->flags & ItemSendsGeometryChanges)) { + if (!(d_ptr->flags & ItemSendsGeometryChanges) && !(d_ptr->flags & ItemSendsScenePositionChanges)) { d_ptr->setPosHelper(pos); return; } @@ -10936,7 +10936,7 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP // Item coordinates with info. QTransform newEffectTransform = info->transformPtr->inverted(); newEffectTransform *= effectTransform; - scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, info->exposedRegion, + scened->draw(item, &pixmapPainter, info->viewTransform, info->transformPtr, 0, info->widget, info->opacity, &newEffectTransform, info->wasDirtySceneTransform, info->drawItem); } diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 159c997..29a4be8 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4301,6 +4301,12 @@ 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.setClipRegion(pixmapExposed); pixmapPainter.drawPixmap(br.topLeft(), subPix); pixmapPainter.end(); @@ -4715,7 +4721,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter * if (item->d_ptr->graphicsEffect && item->d_ptr->graphicsEffect->isEnabled()) { ENSURE_TRANSFORM_PTR; QGraphicsItemPaintInfo info(viewTransform, transformPtr, effectTransform, exposedRegion, widget, &styleOptionTmp, - painter, opacity, wasDirtyParentSceneTransform, drawItem); + painter, opacity, wasDirtyParentSceneTransform, itemHasContents && !itemIsFullyTransparent); QGraphicsEffectSource *source = item->d_ptr->graphicsEffect->d_func()->source; QGraphicsItemEffectSourcePrivate *sourced = static_cast<QGraphicsItemEffectSourcePrivate *> (source->d_func()); diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp index 87416b4..669dd61 100644 --- a/src/gui/graphicsview/qgraphicswidget.cpp +++ b/src/gui/graphicsview/qgraphicswidget.cpp @@ -384,7 +384,7 @@ void QGraphicsWidget::setGeometry(const QRectF &rect) } QSizeF oldSize = size(); QGraphicsLayoutItem::setGeometry(newGeom); - + emit geometryChanged(); // Send resize event bool resized = newGeom.size() != oldSize; if (resized) { diff --git a/src/gui/graphicsview/qgraphicswidget.h b/src/gui/graphicsview/qgraphicswidget.h index 4bea5be..87c669b 100644 --- a/src/gui/graphicsview/qgraphicswidget.h +++ b/src/gui/graphicsview/qgraphicswidget.h @@ -73,7 +73,7 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(QPalette palette READ palette WRITE setPalette) Q_PROPERTY(QFont font READ font WRITE setFont) Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection RESET unsetLayoutDirection) - Q_PROPERTY(QSizeF size READ size WRITE resize) + Q_PROPERTY(QSizeF size READ size WRITE resize NOTIFY geometryChanged) Q_PROPERTY(QSizeF minimumSize READ minimumSize WRITE setMinimumSize) Q_PROPERTY(QSizeF preferredSize READ preferredSize WRITE setPreferredSize) Q_PROPERTY(QSizeF maximumSize READ maximumSize WRITE setMaximumSize) @@ -81,12 +81,11 @@ class Q_GUI_EXPORT QGraphicsWidget : public QGraphicsObject, public QGraphicsLay Q_PROPERTY(Qt::FocusPolicy focusPolicy READ focusPolicy WRITE setFocusPolicy) Q_PROPERTY(Qt::WindowFlags windowFlags READ windowFlags WRITE setWindowFlags) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle) - Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry) + Q_PROPERTY(QRectF geometry READ geometry WRITE setGeometry NOTIFY geometryChanged) Q_PROPERTY(bool autoFillBackground READ autoFillBackground WRITE setAutoFillBackground) public: QGraphicsWidget(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0); ~QGraphicsWidget(); - QGraphicsLayout *layout() const; void setLayout(QGraphicsLayout *layout); void adjustSize(); @@ -179,6 +178,9 @@ public: using QObject::children; #endif +Q_SIGNALS: + void geometryChanged(); + public Q_SLOTS: bool close(); diff --git a/src/gui/itemviews/qabstractitemview.cpp b/src/gui/itemviews/qabstractitemview.cpp index 0f99949..a4722f7 100644 --- a/src/gui/itemviews/qabstractitemview.cpp +++ b/src/gui/itemviews/qabstractitemview.cpp @@ -104,7 +104,7 @@ QAbstractItemViewPrivate::QAbstractItemViewPrivate() horizontalScrollMode(QAbstractItemView::ScrollPerItem), currentIndexSet(false), wrapItemText(false), - delayedPendingLayout(false) + delayedPendingLayout(true) { } @@ -131,8 +131,6 @@ void QAbstractItemViewPrivate::init() viewport->setBackgroundRole(QPalette::Base); - doDelayedItemsLayout(); - q->setAttribute(Qt::WA_InputMethodEnabled); #ifdef QT_SOFTKEYS_ENABLED diff --git a/src/gui/itemviews/qheaderview.cpp b/src/gui/itemviews/qheaderview.cpp index 586e5d4..cd9ee15 100644 --- a/src/gui/itemviews/qheaderview.cpp +++ b/src/gui/itemviews/qheaderview.cpp @@ -2220,16 +2220,24 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e) case QHeaderViewPrivate::MoveSection: { if (qAbs(pos - d->firstPos) >= QApplication::startDragDistance() || !d->sectionIndicator->isHidden()) { - int indicatorCenter = (d->orientation == Qt::Horizontal - ? d->sectionIndicator->width() - : d->sectionIndicator->height()) / 2; - int centerOffset = indicatorCenter - d->sectionIndicatorOffset; - // This will drop the moved section to the position under the center of the indicator. - // If centerOffset is 0, the section will be moved to the position of the mouse cursor. - int visual = visualIndexAt(pos + centerOffset); + int visual = visualIndexAt(pos); if (visual == -1) return; - d->target = d->logicalIndex(visual); + int posThreshold = d->headerSectionPosition(visual) + d->headerSectionSize(visual) / 2; + int moving = visualIndex(d->section); + if (visual < moving) { + if (pos < posThreshold) + d->target = d->logicalIndex(visual); + else + d->target = d->logicalIndex(visual + 1); + } else if (visual > moving) { + if (pos > posThreshold) + d->target = d->logicalIndex(visual); + else + d->target = d->logicalIndex(visual - 1); + } else { + d->target = d->section; + } d->updateSectionIndicator(d->section, pos); } return; diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index cab002e..d6e68f6 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -527,6 +527,27 @@ void QItemSelection::split(const QItemSelectionRange &range, } } + +void QItemSelectionModelPrivate::initModel(QAbstractItemModel *model) +{ + this->model = model; + if (model) { + Q_Q(QItemSelectionModel); + QObject::connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), + q, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); + QObject::connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), + q, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); + QObject::connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), + q, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); + QObject::connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), + q, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int))); + QObject::connect(model, SIGNAL(layoutAboutToBeChanged()), + q, SLOT(_q_layoutAboutToBeChanged())); + QObject::connect(model, SIGNAL(layoutChanged()), + q, SLOT(_q_layoutChanged())); + } +} + /*! \internal @@ -793,6 +814,10 @@ static QItemSelection mergeIndexes(const QList<QPersistentModelIndex> &indexes) while (++i < colSpans.count()) { QModelIndex nextTl = colSpans.at(i).topLeft(); QModelIndex nextBr = colSpans.at(i).bottomRight(); + + if (nextTl.parent() != tl.parent()) + break; // we can't merge selection ranges from different parents + if ((nextTl.column() == prevTl.column()) && (nextBr.column() == br.column()) && (nextTl.row() == prevTl.row() + 1) && (nextBr.row() == br.row() + 1)) { br = nextBr; @@ -890,21 +915,7 @@ void QItemSelectionModelPrivate::_q_layoutChanged() QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model) : QObject(*new QItemSelectionModelPrivate, model) { - d_func()->model = model; - if (model) { - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); - connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int))); - connect(model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_layoutAboutToBeChanged())); - connect(model, SIGNAL(layoutChanged()), - this, SLOT(_q_layoutChanged())); - } + d_func()->initModel(model); } /*! @@ -913,21 +924,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model) QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *parent) : QObject(*new QItemSelectionModelPrivate, parent) { - d_func()->model = model; - if (model) { - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); - connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int))); - connect(model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_layoutAboutToBeChanged())); - connect(model, SIGNAL(layoutChanged()), - this, SLOT(_q_layoutChanged())); - } + d_func()->initModel(model); } /*! @@ -936,21 +933,7 @@ QItemSelectionModel::QItemSelectionModel(QAbstractItemModel *model, QObject *par QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstractItemModel *model) : QObject(dd, model) { - d_func()->model = model; - if (model) { - connect(model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - connect(model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); - connect(model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int))); - connect(model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_layoutAboutToBeChanged())); - connect(model, SIGNAL(layoutChanged()), - this, SLOT(_q_layoutChanged())); - } + dd.initModel(model); } /*! @@ -958,21 +941,6 @@ QItemSelectionModel::QItemSelectionModel(QItemSelectionModelPrivate &dd, QAbstra */ QItemSelectionModel::~QItemSelectionModel() { - Q_D(QItemSelectionModel); - if (d->model) { - disconnect(d->model, SIGNAL(rowsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsAboutToBeRemoved(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeRemoved(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(rowsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_rowsAboutToBeInserted(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(columnsAboutToBeInserted(QModelIndex,int,int)), - this, SLOT(_q_columnsAboutToBeInserted(QModelIndex,int,int))); - disconnect(d->model, SIGNAL(layoutAboutToBeChanged()), - this, SLOT(_q_layoutAboutToBeChanged())); - disconnect(d->model, SIGNAL(layoutChanged()), - this, SLOT(_q_layoutChanged())); - } } /*! diff --git a/src/gui/itemviews/qitemselectionmodel_p.h b/src/gui/itemviews/qitemselectionmodel_p.h index 30583b2..5afa90d 100644 --- a/src/gui/itemviews/qitemselectionmodel_p.h +++ b/src/gui/itemviews/qitemselectionmodel_p.h @@ -70,6 +70,8 @@ public: QItemSelection expandSelection(const QItemSelection &selection, QItemSelectionModel::SelectionFlags command) const; + void initModel(QAbstractItemModel *model); + void _q_rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); void _q_columnsAboutToBeRemoved(const QModelIndex &parent, int start, int end); void _q_rowsAboutToBeInserted(const QModelIndex &parent, int start, int end); diff --git a/src/gui/itemviews/qtreeview.cpp b/src/gui/itemviews/qtreeview.cpp index 61ad79d..4636c50 100644 --- a/src/gui/itemviews/qtreeview.cpp +++ b/src/gui/itemviews/qtreeview.cpp @@ -674,15 +674,19 @@ void QTreeView::dataChanged(const QModelIndex &topLeft, const QModelIndex &botto // refresh the height cache here; we don't really lose anything by getting the size hint, // since QAbstractItemView::dataChanged() will get the visualRect for the items anyway - int topViewIndex = d->viewIndex(topLeft); - if (topViewIndex == 0) - d->defaultItemHeight = indexRowSizeHint(topLeft); bool sizeChanged = false; + int topViewIndex = d->viewIndex(topLeft); + if (topViewIndex == 0) { + int newDefaultItemHeight = indexRowSizeHint(topLeft); + sizeChanged = d->defaultItemHeight != newDefaultItemHeight; + d->defaultItemHeight = newDefaultItemHeight; + } + if (topViewIndex != -1) { if (topLeft.row() == bottomRight.row()) { int oldHeight = d->itemHeight(topViewIndex); d->invalidateHeightCache(topViewIndex); - sizeChanged = (oldHeight != d->itemHeight(topViewIndex)); + sizeChanged |= (oldHeight != d->itemHeight(topViewIndex)); if (topLeft.column() == 0) d->viewItems[topViewIndex].hasChildren = d->hasVisibleChildren(topLeft); } else { diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index fea8c37..9fe6c87 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -903,6 +903,14 @@ void QApplicationPrivate::initialize() { QWidgetPrivate::mapper = new QWidgetMapper; QWidgetPrivate::allWidgets = new QWidgetSet; + +#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) + // initialize the graphics system - on X11 this is initialized inside + // qt_init() in qapplication_x11.cpp because of several reasons. + // On QWS, the graphics system is set by the QScreen plugin. + graphics_system = QGraphicsSystemFactory::create(graphics_system_name); +#endif + if (qt_appType != QApplication::Tty) (void) QApplication::style(); // trigger creation of application style // trigger registering of QVariant's GUI types @@ -936,13 +944,7 @@ void QApplicationPrivate::initialize() // Set up which span functions should be used in raster engine... qInitDrawhelperAsm(); - -#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) - // initialize the graphics system - on X11 this is initialized inside - // qt_init() in qapplication_x11.cpp because of several reasons. - // On QWS, the graphics system is set by the QScreen plugin. - graphics_system = QGraphicsSystemFactory::create(graphics_system_name); -#endif + #ifndef QT_NO_WHEELEVENT QApplicationPrivate::wheel_scroll_lines = 3; #endif diff --git a/src/gui/kernel/qtooltip.cpp b/src/gui/kernel/qtooltip.cpp index c912129..1343959 100644 --- a/src/gui/kernel/qtooltip.cpp +++ b/src/gui/kernel/qtooltip.cpp @@ -368,7 +368,16 @@ void QTipLabel::placeTip(const QPoint &pos, QWidget *w) #ifdef Q_WS_MAC - QRect screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w)); + // When in full screen mode, there is no Dock nor Menu so we can use + // the whole screen for displaying the tooltip. However when not in + // full screen mode we need to save space for the dock, so we use + // availableGeometry instead. + extern bool qt_mac_app_fullscreen; //qapplication_mac.mm + QRect screen; + if(qt_mac_app_fullscreen) + screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w)); + else + screen = QApplication::desktop()->availableGeometry(getTipScreen(pos, w)); #else QRect screen = QApplication::desktop()->screenGeometry(getTipScreen(pos, w)); #endif diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp index 10fb009..9660de5 100644 --- a/src/gui/kernel/qwidget_x11.cpp +++ b/src/gui/kernel/qwidget_x11.cpp @@ -369,7 +369,7 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w) // ConfigureNotify ... MapNotify ... Expose enum State { - Initial, Reparented, Mapped + Initial, Mapped } state = Initial; do { @@ -377,33 +377,15 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w) XNextEvent(X11->display, &ev); qApp->x11ProcessEvent(&ev); - if (w->windowFlags() & Qt::X11BypassWindowManagerHint) { - switch (state) { - case Initial: - case Reparented: - if (ev.type == MapNotify && ev.xany.window == winid) - state = Mapped; - break; - case Mapped: - if (ev.type == Expose && ev.xany.window == winid) - return; - break; - } - } else { - switch (state) { - case Initial: - if (ev.type == ReparentNotify && ev.xany.window == winid) - state = Reparented; - break; - case Reparented: - if (ev.type == MapNotify && ev.xany.window == winid) - state = Mapped; - break; - case Mapped: - if (ev.type == Expose && ev.xany.window == winid) - return; - break; - } + switch (state) { + case Initial: + if (ev.type == MapNotify && ev.xany.window == winid) + state = Mapped; + break; + case Mapped: + if (ev.type == Expose && ev.xany.window == winid) + return; + break; } } else { if (!XEventsQueued(X11->display, QueuedAfterFlush)) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a1ed8f5..1c528fe 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -5414,10 +5414,15 @@ void QPainter::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) scale(w / sw, h / sh); setBackgroundMode(Qt::TransparentMode); setRenderHint(Antialiasing, renderHints() & SmoothPixmapTransform); - QBrush brush(d->state->pen.color(), pm); + QBrush brush; + + if (sw == pm.width() && sh == pm.height()) + brush = QBrush(d->state->pen.color(), pm); + else + brush = QBrush(d->state->pen.color(), pm.copy(sx, sy, sw, sh)); + setBrush(brush); setPen(Qt::NoPen); - setBrushOrigin(QPointF(-sx, -sy)); drawRect(QRectF(0, 0, sw, sh)); restore(); @@ -7994,7 +7999,7 @@ start_lengthVariant: for (int i = 0; i < textLayout.lineCount(); i++) { QTextLine line = textLayout.lineAt(i); - qreal advance = textLayout.engine()->lines[i].textAdvance.toReal(); + qreal advance = line.horizontalAdvance(); if (tf & Qt::AlignRight) xoff = r.width() - advance; else if (tf & Qt::AlignHCenter) diff --git a/src/gui/painting/qpainterpath.h b/src/gui/painting/qpainterpath.h index 296ce33..15d83b8 100644 --- a/src/gui/painting/qpainterpath.h +++ b/src/gui/painting/qpainterpath.h @@ -288,6 +288,8 @@ public: QPainterPath createStroke(const QPainterPath &path) const; private: + Q_DISABLE_COPY(QPainterPathStroker) + friend class QX11PaintEngine; QScopedPointer<QPainterPathStrokerPrivate> d_ptr; diff --git a/src/gui/s60framework/qs60mainapplication.cpp b/src/gui/s60framework/qs60mainapplication.cpp index 2a7c4aa..41ac1a8 100644 --- a/src/gui/s60framework/qs60mainapplication.cpp +++ b/src/gui/s60framework/qs60mainapplication.cpp @@ -41,6 +41,7 @@ // INCLUDE FILES #include <exception> +#include <private/qcore_symbian_p.h> #include "qs60maindocument.h" #include "qs60mainapplication_p.h" #include "qs60mainapplication.h" @@ -57,17 +58,17 @@ CApaApplication *newS60Application() return new QS60MainApplication; } -_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main.rsc"); +_LIT(KQtWrapperResourceFile, "\\resource\\apps\\s60main" QT_LIBINFIX_UNICODE L".rsc"); /*! \class QS60MainApplication \since 4.6 \brief The QS60MainApplication class provides support for migration from S60. - + \warning This class is provided only to get access to S60 specific functionality in the application framework classes. It is not portable. We strongly recommend against using it in new applications. - + The QS60MainApplication provides a helper class for use in migrating from existing S60 based applications to Qt based applications. It is used in the exact same way as the \c CAknApplication class from diff --git a/src/gui/s60framework/qs60mainappui.cpp b/src/gui/s60framework/qs60mainappui.cpp index 012985b..3b5b9d3 100644 --- a/src/gui/s60framework/qs60mainappui.cpp +++ b/src/gui/s60framework/qs60mainappui.cpp @@ -45,7 +45,15 @@ #include <eikmenub.h> #include <eikmenup.h> #include <barsread.h> -#include <s60main.rsg> +#include <qconfig.h> +#if defined(QT_LIBINFIX_UNQUOTED) +// Two level macro needed for proper expansion of libinfix +# define QT_S60MAIN_RSG_2(x) <s60main##x##.rsg> +# define QT_S60MAIN_RSG(x) QT_S60MAIN_RSG_2(x) +# include QT_S60MAIN_RSG(QT_LIBINFIX_UNQUOTED) +#else +# include <s60main.rsg> +#endif #include <avkon.rsg> #include "qs60mainappui.h" diff --git a/src/gui/s60framework/s60framework.pri b/src/gui/s60framework/s60framework.pri index e177a33..f9d89dc 100644 --- a/src/gui/s60framework/s60framework.pri +++ b/src/gui/s60framework/s60framework.pri @@ -4,6 +4,7 @@ minimalAppResource31 = \ "SOURCEPATH s60framework" \ "START RESOURCE s60main.rss" \ + "TARGET s60main$${QT_LIBINFIX}" \ "HEADER" \ "TARGETPATH /resource/apps" \ "END" @@ -19,3 +20,5 @@ HEADERS += s60framework/qs60mainapplication_p.h \ s60framework/qs60mainapplication.h \ s60framework/qs60mainappui.h \ s60framework/qs60maindocument.h + +!isEmpty(QT_LIBINFIX): DEFINES += QT_LIBINFIX_UNQUOTED=$$QT_LIBINFIX
\ No newline at end of file diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index a2ebebb..750e19f 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -2069,11 +2069,11 @@ void QS60Style::drawPrimitive(PrimitiveElement element, const QStyleOption *opti break; case PE_IndicatorViewItemCheck: #ifndef QT_NO_ITEMVIEWS - if (const QListView *listItem = (qobject_cast<const QListView *>(widget))) { + if (const QAbstractItemView *itemView = (qobject_cast<const QAbstractItemView *>(widget))) { if (const QStyleOptionViewItemV4 *vopt = qstyleoption_cast<const QStyleOptionViewItemV4 *>(option)) { const bool checkBoxVisible = vopt->features & QStyleOptionViewItemV2::HasCheckIndicator; - const bool singleSelection = listItem->selectionMode() == - QAbstractItemView::SingleSelection || listItem->selectionMode() == QAbstractItemView::NoSelection; + const bool singleSelection = itemView->selectionMode() == + QAbstractItemView::SingleSelection || itemView->selectionMode() == QAbstractItemView::NoSelection; // draw either checkbox at the beginning if (checkBoxVisible && singleSelection) { drawPrimitive(PE_IndicatorCheckBox, option, painter, widget); @@ -2475,6 +2475,12 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w { int retValue = -1; switch (sh) { + case SH_RequestSoftwareInputPanel: + if (QS60StylePrivate::isSingleClickUi()) + retValue = RSIP_OnMouseClick; + else + retValue = RSIP_OnMouseClickAndAlreadyFocused; + break; case SH_ComboBox_Popup: retValue = true; break; @@ -2531,9 +2537,6 @@ int QS60Style::styleHint(StyleHint sh, const QStyleOption *opt, const QWidget *w case SH_UnderlineShortcut: retValue = 0; break; - case SH_RequestSoftwareInputPanel: - retValue = RSIP_OnMouseClickAndAlreadyFocused; - break; case SH_FormLayoutWrapPolicy: retValue = QFormLayout::WrapLongRows; break; diff --git a/src/gui/styles/qs60style_s60.cpp b/src/gui/styles/qs60style_s60.cpp index ecac3d6..4a279a7 100644 --- a/src/gui/styles/qs60style_s60.cpp +++ b/src/gui/styles/qs60style_s60.cpp @@ -63,7 +63,7 @@ #include <AknUtils.h> #include <aknnavi.h> #include <gulicon.h> -#include <AknBitmapAnimation.h> +#include <aknbitmapanimation.h> #if !defined(QT_NO_STYLE_S60) || defined(QT_PLUGIN) @@ -1121,7 +1121,7 @@ QColor QS60StylePrivate::s60Color(QS60StyleEnums::ColorLists list, &KAknsIIDQsnParentColors, &KAknsIIDQsnTextColors }; - Q_ASSERT((int)list <= (int)sizeof(idMap)/sizeof(idMap[0])); + Q_ASSERT((int)list < (int)sizeof(idMap)/sizeof(idMap[0])); const QColor color = QS60StyleModeSpecifics::colorValue(*idMap[(int) list], index - 1); return option ? QS60StylePrivate::stateColor(color, option) : color; } diff --git a/src/gui/styles/qwindowsmobilestyle.cpp b/src/gui/styles/qwindowsmobilestyle.cpp index 6e77409..5f939d0 100644 --- a/src/gui/styles/qwindowsmobilestyle.cpp +++ b/src/gui/styles/qwindowsmobilestyle.cpp @@ -5076,6 +5076,10 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp color = option->palette.buttonText().color(); QImage image; int xoffset, yoffset; + bool isTabBarArrow = widget && widget->parent() + && widget->inherits("QToolButton") + && widget->parent()->inherits("QTabBar"); + switch (element) { case PE_IndicatorArrowUp: image = d->imageArrowUp; @@ -5090,12 +5094,12 @@ void QWindowsMobileStyle::drawPrimitive(PrimitiveElement element, const QStyleOp case PE_IndicatorArrowLeft: image = d->imageArrowLeft; xoffset = 8; - yoffset = 2; + yoffset = isTabBarArrow ? 12 : 2; break; case PE_IndicatorArrowRight: image = d->imageArrowRight; xoffset = 8; - yoffset = 2; + yoffset = isTabBarArrow ? 12 : 2; break; case PE_IndicatorArrowUpBig: image = d->imageArrowUpBig; @@ -6949,10 +6953,11 @@ int QWindowsMobileStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, co case PM_SliderThickness: ret = d->doubleControls ? windowsMobileSliderThickness * 2: windowsMobileSliderThickness; break; - case PM_TabBarScrollButtonWidth: - ret = d->doubleControls ? 14 * 2 : 18; - case PM_CheckBoxLabelSpacing: - case PM_RadioButtonLabelSpacing: + case PM_TabBarScrollButtonWidth: + ret = d->doubleControls ? 14 * 2 : 18; + break; + case PM_CheckBoxLabelSpacing: + case PM_RadioButtonLabelSpacing: ret = d->doubleControls ? 6 * 2 : 6; break; // Returns the number of pixels to use for the business part of the diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index cc6793d..2fc5d1a 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1570,6 +1570,20 @@ qreal QTextLine::naturalTextWidth() const return eng->lines[i].textWidth.toReal(); } +/*! \since 4.7 + Returns the horizontal advance of the text. The advance of the text + is the distance from its position to the next position at which + text would naturally be drawn. + + By adding the advance to the position of the text line and using this + as the position of a second text line, you will be able to position + the two lines side-by-side without gaps in-between. +*/ +qreal QTextLine::horizontalAdvance() const +{ + return eng->lines[i].textAdvance.toReal(); +} + /*! Lays out the line with the given \a width. The line is filled from its starting position with as many characters as will fit into @@ -1644,28 +1658,67 @@ namespace { struct LineBreakHelper { - LineBreakHelper() : glyphCount(0), maxGlyphs(0), manualWrap(false) {} + LineBreakHelper() + : glyphCount(0), maxGlyphs(0), currentPosition(0), fontEngine(0), logClusters(0), + manualWrap(false) + { + } + QScriptLine tmpData; QScriptLine spaceData; + QGlyphLayout glyphs; + int glyphCount; int maxGlyphs; + int currentPosition; QFixed minw; QFixed softHyphenWidth; QFixed rightBearing; + QFixed minimumRightBearing; + + QFontEngine *fontEngine; + const unsigned short *logClusters; bool manualWrap; bool checkFullOtherwiseExtend(QScriptLine &line); + + QFixed calculateNewWidth(const QScriptLine &line) const { + return line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + - qMin(rightBearing, QFixed()); + } + + inline glyph_t currentGlyph() const + { + Q_ASSERT(currentPosition > 0); + return glyphs.glyphs[logClusters[currentPosition - 1]]; + } + + inline void adjustRightBearing() + { + if (currentPosition <= 0) + return; + + glyph_metrics_t gi = fontEngine->boundingBox(currentGlyph()); + if (gi.isValid()) + rightBearing = qMin(QFixed(), gi.xoff - gi.x - gi.width); + } + + inline void resetRightBearing() + { + rightBearing = QFixed(1); // Any positive number is defined as invalid since only + // negative right bearings are interesting to us. + } }; inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line) { LB_DEBUG("possible break width %f, spacew=%f", tmpData.textWidth.toReal(), spaceData.textWidth.toReal()); - QFixed newWidth = line.textWidth + tmpData.textWidth + spaceData.textWidth + softHyphenWidth + rightBearing; + QFixed newWidth = calculateNewWidth(line); if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs)) return true; @@ -1741,13 +1794,12 @@ void QTextLine::layout_helper(int maxGlyphs) Qt::Alignment alignment = eng->option.alignment(); const HB_CharAttributes *attributes = eng->attributes(); - int pos = line.from; + lbh.currentPosition = line.from; int end = 0; - QGlyphLayout glyphs; - const unsigned short *logClusters = eng->layoutData->logClustersPtr; + lbh.logClusters = eng->layoutData->logClustersPtr; while (newItem < eng->layoutData->items.size()) { - lbh.rightBearing = 0; + lbh.resetRightBearing(); lbh.softHyphenWidth = 0; if (newItem != item) { item = newItem; @@ -1755,13 +1807,19 @@ void QTextLine::layout_helper(int maxGlyphs) if (!current.num_glyphs) { eng->shape(item); attributes = eng->attributes(); - logClusters = eng->layoutData->logClustersPtr; + lbh.logClusters = eng->layoutData->logClustersPtr; } - pos = qMax(line.from, current.position); + lbh.currentPosition = qMax(line.from, current.position); end = current.position + eng->length(item); - glyphs = eng->shapedGlyphs(¤t); + lbh.glyphs = eng->shapedGlyphs(¤t); } const QScriptItem ¤t = eng->layoutData->items[item]; + QFontEngine *fontEngine = eng->fontEngine(current); + if (lbh.fontEngine != fontEngine) { + lbh.fontEngine = fontEngine; + lbh.minimumRightBearing = qMin(QFixed(), + QFixed::fromReal(fontEngine->minRightBearing())); + } lbh.tmpData.leading = qMax(lbh.tmpData.leading + lbh.tmpData.ascent, current.leading + current.ascent) - qMax(lbh.tmpData.ascent, @@ -1791,8 +1849,8 @@ void QTextLine::layout_helper(int maxGlyphs) if (!line.length && !lbh.tmpData.length) line.setDefaultHeight(eng); if (eng->option.flags() & QTextOption::ShowLineAndParagraphSeparators) { - addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount, - current, logClusters, glyphs); + addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, + current, lbh.logClusters, lbh.glyphs); } else { lbh.tmpData.length++; } @@ -1811,10 +1869,10 @@ void QTextLine::layout_helper(int maxGlyphs) ++lbh.glyphCount; if (lbh.checkFullOtherwiseExtend(line)) goto found; - } else if (attributes[pos].whiteSpace) { - while (pos < end && attributes[pos].whiteSpace) - addNextCluster(pos, end, lbh.spaceData, lbh.glyphCount, - current, logClusters, glyphs); + } else if (attributes[lbh.currentPosition].whiteSpace) { + while (lbh.currentPosition < end && attributes[lbh.currentPosition].whiteSpace) + addNextCluster(lbh.currentPosition, end, lbh.spaceData, lbh.glyphCount, + current, lbh.logClusters, lbh.glyphs); if (!lbh.manualWrap && lbh.spaceData.textWidth > line.width) { lbh.spaceData.textWidth = line.width; // ignore spaces that fall out of the line. @@ -1823,19 +1881,19 @@ void QTextLine::layout_helper(int maxGlyphs) } else { bool sb_or_ws = false; do { - addNextCluster(pos, end, lbh.tmpData, lbh.glyphCount, - current, logClusters, glyphs); + addNextCluster(lbh.currentPosition, end, lbh.tmpData, lbh.glyphCount, + current, lbh.logClusters, lbh.glyphs); - if (attributes[pos].whiteSpace || attributes[pos-1].lineBreakType != HB_NoBreak) { + if (attributes[lbh.currentPosition].whiteSpace || attributes[lbh.currentPosition-1].lineBreakType != HB_NoBreak) { sb_or_ws = true; break; - } else if (breakany && attributes[pos].charStop) { + } else if (breakany && attributes[lbh.currentPosition].charStop) { break; } - } while (pos < end); + } while (lbh.currentPosition < end); lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw); - if (pos && attributes[pos - 1].lineBreakType == HB_SoftHyphen) { + if (lbh.currentPosition && attributes[lbh.currentPosition - 1].lineBreakType == HB_SoftHyphen) { // if we are splitting up a word because of // a soft hyphen then we ... // @@ -1853,43 +1911,40 @@ void QTextLine::layout_helper(int maxGlyphs) // and thus become invisible again. // if (line.length) - lbh.softHyphenWidth = glyphs.advances_x[logClusters[pos - 1]]; + lbh.softHyphenWidth = lbh.glyphs.advances_x[lbh.logClusters[lbh.currentPosition - 1]]; else if (breakany) - lbh.tmpData.textWidth += glyphs.advances_x[logClusters[pos - 1]]; + lbh.tmpData.textWidth += lbh.glyphs.advances_x[lbh.logClusters[lbh.currentPosition - 1]]; } // The actual width of the text needs to take the right bearing into account. The // right bearing is left-ward, which means that if the rightmost pixel is to the right // of the advance of the glyph, the bearing will be negative. We flip the sign // for the code to be more readable. Logic borrowed from qfontmetrics.cpp. - if (pos) { - QFontEngine *fontEngine = eng->fontEngine(current); - glyph_t glyph = glyphs.glyphs[logClusters[pos - 1]]; - glyph_metrics_t gi = fontEngine->boundingBox(glyph); - if (gi.isValid()) - lbh.rightBearing = qMax(QFixed(), -(gi.xoff - gi.x - gi.width)); - } + // We ignore the right bearing if the minimum negative bearing is too little to + // expand the text beyond the edge. + if (sb_or_ws|breakany) { + if (lbh.calculateNewWidth(line) + lbh.minimumRightBearing > line.width) + lbh.adjustRightBearing(); + if (lbh.checkFullOtherwiseExtend(line)) { + if (!breakany) { + line.textWidth += lbh.softHyphenWidth; + } - if ((sb_or_ws|breakany) && lbh.checkFullOtherwiseExtend(line)) { - if (!breakany) { - line.textWidth += lbh.softHyphenWidth; + goto found; } - - line.textAdvance = line.textWidth; - line.textWidth += lbh.rightBearing; - - goto found; } } - if (pos == end) + if (lbh.currentPosition == end) newItem = item + 1; } LB_DEBUG("reached end of line"); lbh.checkFullOtherwiseExtend(line); +found: + if (lbh.rightBearing > 0) // If right bearing has not yet been adjusted + lbh.adjustRightBearing(); line.textAdvance = line.textWidth; - line.textWidth += lbh.rightBearing; + line.textWidth -= qMin(QFixed(), lbh.rightBearing); -found: if (line.length == 0) { LB_DEBUG("no break available in line, adding temp: length %d, width %f, space: length %d, width %f", lbh.tmpData.length, lbh.tmpData.textWidth.toReal(), diff --git a/src/gui/text/qtextlayout.h b/src/gui/text/qtextlayout.h index edae7de..8c93ed6 100644 --- a/src/gui/text/qtextlayout.h +++ b/src/gui/text/qtextlayout.h @@ -202,6 +202,7 @@ public: bool leadingIncluded() const; qreal naturalTextWidth() const; + qreal horizontalAdvance() const; QRectF naturalTextRect() const; enum Edge { diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 806452c..1d8224c 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -353,6 +353,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() replyPrivate->autoDecompress = false; } if (replyPrivate->statusCode == 100) { + replyPrivate->clearHttpLayerInformation(); replyPrivate->state = QHttpNetworkReplyPrivate::ReadingStatusState; break; // ignore } diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp index 984f557..338236e 100644 --- a/src/network/access/qhttpnetworkreply.cpp +++ b/src/network/access/qhttpnetworkreply.cpp @@ -219,7 +219,7 @@ QHttpNetworkReplyPrivate::~QHttpNetworkReplyPrivate() { } -void QHttpNetworkReplyPrivate::clear() +void QHttpNetworkReplyPrivate::clearHttpLayerInformation() { state = NothingDoneState; statusCode = 100; @@ -229,18 +229,24 @@ void QHttpNetworkReplyPrivate::clear() currentChunkSize = 0; currentChunkRead = 0; connectionCloseEnabled = true; - connection = 0; - connectionChannel = 0; #ifndef QT_NO_COMPRESS if (initInflate) inflateEnd(&inflateStrm); #endif initInflate = false; streamEnd = false; - autoDecompress = false; fields.clear(); } +// TODO: Isn't everything HTTP layer related? We don't need to set connection and connectionChannel to 0 at all +void QHttpNetworkReplyPrivate::clear() +{ + connection = 0; + connectionChannel = 0; + autoDecompress = false; + clearHttpLayerInformation(); +} + // QHttpNetworkReplyPrivate qint64 QHttpNetworkReplyPrivate::bytesAvailable() const { @@ -539,6 +545,11 @@ qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket) || fragment.endsWith("\r\n\n") || fragment.endsWith("\n\n")) allHeaders = true; + + // there is another case: We have no headers. Then the fragment equals just the line ending + if ((fragment.length() == 2 && fragment.endsWith("\r\n")) + || (fragment.length() == 1 && fragment.endsWith("\n"))) + allHeaders = true; } } } while (!allHeaders && haveRead > 0); diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index fa240ec..4011c78 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -172,6 +172,7 @@ public: bool findChallenge(bool forProxy, QByteArray &challenge) const; QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const; void clear(); + void clearHttpLayerInformation(); qint64 readReplyBodyRaw(QIODevice *in, QByteDataBuffer *out, qint64 size); qint64 readReplyBodyChunked(QIODevice *in, QByteDataBuffer *out); diff --git a/src/opengl/qglbuffer.cpp b/src/opengl/qglbuffer.cpp index 2ab7c32..223243c 100644 --- a/src/opengl/qglbuffer.cpp +++ b/src/opengl/qglbuffer.cpp @@ -289,6 +289,10 @@ bool QGLBuffer::read(int offset, void *data, int count) */ void QGLBuffer::write(int offset, const void *data, int count) { +#ifndef QT_NO_DEBUG + if (!isCreated()) + qWarning("QGLBuffer::allocate(): buffer not created"); +#endif Q_D(QGLBuffer); if (d->guard.id()) glBufferSubData(d->type, offset, count, data); @@ -305,6 +309,10 @@ void QGLBuffer::write(int offset, const void *data, int count) */ void QGLBuffer::allocate(const void *data, int count) { +#ifndef QT_NO_DEBUG + if (!isCreated()) + qWarning("QGLBuffer::allocate(): buffer not created"); +#endif Q_D(QGLBuffer); if (d->guard.id()) glBufferData(d->type, count, data, d->actualUsagePattern); @@ -336,6 +344,10 @@ void QGLBuffer::allocate(const void *data, int count) */ bool QGLBuffer::bind() const { +#ifndef QT_NO_DEBUG + if (!isCreated()) + qWarning("QGLBuffer::bind(): buffer not created"); +#endif Q_D(const QGLBuffer); GLuint bufferId = d->guard.id(); if (bufferId) { @@ -364,6 +376,10 @@ bool QGLBuffer::bind() const */ void QGLBuffer::release() const { +#ifndef QT_NO_DEBUG + if (!isCreated()) + qWarning("QGLBuffer::release(): buffer not created"); +#endif Q_D(const QGLBuffer); if (d->guard.id()) glBindBuffer(d->type, 0); @@ -372,31 +388,23 @@ void QGLBuffer::release() const #undef ctx /*! - Binds a raw \a bufferId to the specified buffer \a type - in the current QGLContext. Returns false if there is - no context current or the GL buffer extension could - not be resolved. + Releases the buffer associated with \a type in the current + QGLContext. - This function is a direct call to \c{glBindBuffer()} for - use when the caller does not have a QGLBuffer but does - have a raw \a bufferId. It can also be used to release - the current buffer when the caller does not know which - QGLBuffer object is currently bound: + This function is a direct call to \c{glBindBuffer(type, 0)} + for use when the caller does not know which QGLBuffer has + been bound to the context but wants to make sure that it + is released. \code - QGLBuffer::bind(QGLBuffer::VertexBuffer, 0); + QGLBuffer::release(QGLBuffer::VertexBuffer); \endcode */ -bool QGLBuffer::bind(QGLBuffer::Type type, uint bufferId) +void QGLBuffer::release(QGLBuffer::Type type) { const QGLContext *ctx = QGLContext::currentContext(); - if (ctx) { - if (qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx))) { - glBindBuffer(GLenum(type), GLuint(bufferId)); - return true; - } - } - return false; + if (ctx && qt_resolve_buffer_extensions(const_cast<QGLContext *>(ctx))) + glBindBuffer(GLenum(type), 0); } #define ctx d->guard.context() @@ -407,7 +415,7 @@ bool QGLBuffer::bind(QGLBuffer::Type type, uint bufferId) \sa isCreated() */ -uint QGLBuffer::bufferId() const +GLuint QGLBuffer::bufferId() const { Q_D(const QGLBuffer); return d->guard.id(); @@ -453,6 +461,10 @@ int QGLBuffer::size() const void *QGLBuffer::map(QGLBuffer::Access access) { Q_D(QGLBuffer); +#ifndef QT_NO_DEBUG + if (!isCreated()) + qWarning("QGLBuffer::map(): buffer not created"); +#endif if (!d->guard.id()) return 0; if (!glMapBufferARB) @@ -476,6 +488,10 @@ void *QGLBuffer::map(QGLBuffer::Access access) bool QGLBuffer::unmap() { Q_D(QGLBuffer); +#ifndef QT_NO_DEBUG + if (!isCreated()) + qWarning("QGLBuffer::unmap(): buffer not created"); +#endif if (!d->guard.id()) return false; if (!glUnmapBufferARB) diff --git a/src/opengl/qglbuffer.h b/src/opengl/qglbuffer.h index a060733..2fe1f1f 100644 --- a/src/opengl/qglbuffer.h +++ b/src/opengl/qglbuffer.h @@ -43,6 +43,7 @@ #define QGLBUFFER_H #include <QtCore/qscopedpointer.h> +#include <QtOpenGL/qgl.h> QT_BEGIN_HEADER @@ -97,9 +98,9 @@ public: bool bind() const; void release() const; - static bool bind(QGLBuffer::Type type, uint bufferId); + static void release(QGLBuffer::Type type); - uint bufferId() const; + GLuint bufferId() const; int size() const; diff --git a/src/openvg/openvg.pro b/src/openvg/openvg.pro index c8c9917..3790492 100644 --- a/src/openvg/openvg.pro +++ b/src/openvg/openvg.pro @@ -33,6 +33,8 @@ contains(QT_CONFIG, egl) { qwindowsurface_vgegl.cpp } +symbian: DEFINES += QVG_RECREATE_ON_SIZE_CHANGE + include(../qbase.pri) unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index 53f6b4c..e66d80b 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -45,10 +45,10 @@ #include "qvg_p.h" #include "qvgimagepool_p.h" -#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE #include <private/qt_s60_p.h> #include <fbs.h> -#include <graphics/sgimage.h> +#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE +#include <sgresource/sgimage.h> typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR); typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR); @@ -465,23 +465,24 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) TInt err = 0; - err = SgDriver::Open(); - if(err != KErrNone) { + RSgDriver driver; + err = driver.Open(); + if (err != KErrNone) { cleanup(); return; } - if(sgImage->IsNull()) { + if (sgImage->IsNull()) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } TSgImageInfo sgImageInfo; err = sgImage->GetInfo(sgImageInfo); - if(err != KErrNone) { + if (err != KErrNone) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } @@ -489,9 +490,9 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); - if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { + if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } @@ -502,17 +503,17 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); - if(eglGetError() != EGL_SUCCESS) { + if (eglGetError() != EGL_SUCCESS) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } vgImage = vgCreateEGLImageTargetKHR(eglImage); - if(vgGetError() != VG_NO_ERROR) { + if (vgGetError() != VG_NO_ERROR) { cleanup(); eglDestroyImageKHR(QEgl::display(), eglImage); - SgDriver::Close(); + driver.Close(); return; } @@ -526,7 +527,7 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) setSerialNumber(++qt_vg_pixmap_serial); // release stuff eglDestroyImageKHR(QEgl::display(), eglImage); - SgDriver::Close(); + driver.Close(); } else if (type == QPixmapData::FbsBitmap) { CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); @@ -584,29 +585,25 @@ void* QVGPixmapData::toNativeType(NativeType type) if (type == QPixmapData::SgImage) { toVGImage(); - if(!isValid() || vgImage == VG_INVALID_HANDLE) + if (!isValid() || vgImage == VG_INVALID_HANDLE) return 0; TInt err = 0; - err = SgDriver::Open(); - if(err != KErrNone) + RSgDriver driver; + err = driver.Open(); + if (err != KErrNone) return 0; TSgImageInfo sgInfo; sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE; sgInfo.iSizeInPixels.SetSize(w, h); - sgInfo.iUsage = ESgUsageOpenVgImage | ESgUsageOpenVgTarget; - sgInfo.iShareable = ETrue; - sgInfo.iCpuAccess = ESgCpuAccessNone; - sgInfo.iScreenId = KSgScreenIdMain; //KSgScreenIdAny; - sgInfo.iUserAttributes = NULL; - sgInfo.iUserAttributeCount = 0; + sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; RSgImage *sgImage = q_check_ptr(new RSgImage()); err = sgImage->Create(sgInfo, NULL, NULL); - if(err != KErrNone) { - SgDriver::Close(); + if (err != KErrNone) { + driver.Close(); return 0; } @@ -614,8 +611,8 @@ void* QVGPixmapData::toNativeType(NativeType type) pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); - if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { - SgDriver::Close(); + if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { + driver.Close(); return 0; } @@ -625,17 +622,17 @@ void* QVGPixmapData::toNativeType(NativeType type) EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); - if(eglGetError() != EGL_SUCCESS) { + if (eglGetError() != EGL_SUCCESS) { sgImage->Close(); - SgDriver::Close(); + driver.Close(); return 0; } VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage); - if(vgGetError() != VG_NO_ERROR) { + if (vgGetError() != VG_NO_ERROR) { eglDestroyImageKHR(QEgl::display(), eglImage); sgImage->Close(); - SgDriver::Close(); + driver.Close(); return 0; } @@ -643,14 +640,14 @@ void* QVGPixmapData::toNativeType(NativeType type) vgImage, 0, 0, w, h, VG_FALSE); - if(vgGetError() != VG_NO_ERROR) { + if (vgGetError() != VG_NO_ERROR) { sgImage->Close(); sgImage = 0; } // release stuff vgDestroyImage(dstVgImage); eglDestroyImageKHR(QEgl::display(), eglImage); - SgDriver::Close(); + driver.Close(); return reinterpret_cast<void*>(sgImage); } else if (type == QPixmapData::FbsBitmap) { CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); diff --git a/src/plugins/phonon/mmf/mmf.pro b/src/plugins/phonon/mmf/mmf.pro index cfaca9d..da41f18 100644 --- a/src/plugins/phonon/mmf/mmf.pro +++ b/src/plugins/phonon/mmf/mmf.pro @@ -20,13 +20,16 @@ phonon_mmf_audio_drm { # '#include <videoplayer.h>' picks up the Symbian header, as intended. PREPEND_INCLUDEPATH = /epoc32/include +PREPEND_INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty + INCLUDEPATH += $$MW_LAYER_SYSTEMINCLUDE HEADERS += \ $$PHONON_MMF_DIR/abstractaudioeffect.h \ $$PHONON_MMF_DIR/abstractmediaplayer.h \ $$PHONON_MMF_DIR/abstractplayer.h \ - $$PHONON_MMF_DIR/ancestormovemonitor.h \ + $$PHONON_MMF_DIR/abstractvideooutput.h \ + $$PHONON_MMF_DIR/abstractvideoplayer.h \ $$PHONON_MMF_DIR/audioequalizer.h \ $$PHONON_MMF_DIR/audiooutput.h \ $$PHONON_MMF_DIR/audioplayer.h \ @@ -40,23 +43,22 @@ HEADERS += \ $$PHONON_MMF_DIR/loudness.h \ $$PHONON_MMF_DIR/mediaobject.h \ $$PHONON_MMF_DIR/mmf_medianode.h \ - $$PHONON_MMF_DIR/mmf_videoplayer.h \ $$PHONON_MMF_DIR/stereowidening.h \ $$PHONON_MMF_DIR/objectdump.h \ $$PHONON_MMF_DIR/objectdump_symbian.h \ $$PHONON_MMF_DIR/objecttree.h \ $$PHONON_MMF_DIR/utils.h \ - $$PHONON_MMF_DIR/videooutput.h \ $$PHONON_MMF_DIR/videowidget.h SOURCES += \ $$PHONON_MMF_DIR/abstractaudioeffect.cpp \ $$PHONON_MMF_DIR/abstractmediaplayer.cpp \ $$PHONON_MMF_DIR/abstractplayer.cpp \ - $$PHONON_MMF_DIR/ancestormovemonitor.cpp \ $$PHONON_MMF_DIR/audioequalizer.cpp \ $$PHONON_MMF_DIR/audiooutput.cpp \ $$PHONON_MMF_DIR/audioplayer.cpp \ + $$PHONON_MMF_DIR/abstractvideooutput.cpp \ + $$PHONON_MMF_DIR/abstractvideoplayer.cpp \ $$PHONON_MMF_DIR/backend.cpp \ $$PHONON_MMF_DIR/bassboost.cpp \ $$PHONON_MMF_DIR/dummyplayer.cpp \ @@ -66,15 +68,34 @@ SOURCES += \ $$PHONON_MMF_DIR/loudness.cpp \ $$PHONON_MMF_DIR/mediaobject.cpp \ $$PHONON_MMF_DIR/mmf_medianode.cpp \ - $$PHONON_MMF_DIR/mmf_videoplayer.cpp \ $$PHONON_MMF_DIR/stereowidening.cpp \ $$PHONON_MMF_DIR/objectdump.cpp \ $$PHONON_MMF_DIR/objectdump_symbian.cpp \ $$PHONON_MMF_DIR/objecttree.cpp \ $$PHONON_MMF_DIR/utils.cpp \ - $$PHONON_MMF_DIR/videooutput.cpp \ $$PHONON_MMF_DIR/videowidget.cpp +# Test for whether the build environment supports video rendering to graphics +# surfaces. +exists($${EPOCROOT}epoc32/include/platform/videoplayer2.h) { + HEADERS += \ + $$PHONON_MMF_DIR/videooutput_surface.h \ + $$PHONON_MMF_DIR/videoplayer_surface.h + SOURCES += \ + $$PHONON_MMF_DIR/videooutput_surface.cpp \ + $$PHONON_MMF_DIR/videoplayer_surface.cpp + DEFINES += PHONON_MMF_VIDEO_SURFACES +} else { + HEADERS += \ + $$PHONON_MMF_DIR/ancestormovemonitor.h \ + $$PHONON_MMF_DIR/videooutput_dsa.h \ + $$PHONON_MMF_DIR/videoplayer_dsa.h + SOURCES += \ + $$PHONON_MMF_DIR/ancestormovemonitor.cpp \ + $$PHONON_MMF_DIR/videooutput_dsa.cpp \ + $$PHONON_MMF_DIR/videoplayer_dsa.cpp \ +} + LIBS += -lcone LIBS += -lws32 diff --git a/src/plugins/qpluginbase.pri b/src/plugins/qpluginbase.pri index 3dd3d2e..8b119b5 100644 --- a/src/plugins/qpluginbase.pri +++ b/src/plugins/qpluginbase.pri @@ -17,5 +17,6 @@ wince*:LIBS += $$QMAKE_LIBS_GUI symbian: { TARGET.EPOCALLOWDLLDATA=1 TARGET.CAPABILITY = All -Tcb + TARGET = $${TARGET}$${QT_LIBINFIX} load(armcc_warnings) } diff --git a/src/plugins/s60/3_1/3_1.pro b/src/plugins/s60/3_1/3_1.pro index 58ff5ce..9437f3d 100644 --- a/src/plugins/s60/3_1/3_1.pro +++ b/src/plugins/s60/3_1/3_1.pro @@ -1,6 +1,6 @@ include(../s60pluginbase.pri) -TARGET = qts60plugin_3_1 +TARGET = qts60plugin_3_1$${QT_LIBINFIX} SOURCES += ../src/qlocale_3_1.cpp \ ../src/qdesktopservices_3_1.cpp \ diff --git a/src/plugins/s60/3_2/3_2.pro b/src/plugins/s60/3_2/3_2.pro index 7700677..0524866 100644 --- a/src/plugins/s60/3_2/3_2.pro +++ b/src/plugins/s60/3_2/3_2.pro @@ -1,6 +1,6 @@ include(../s60pluginbase.pri) -TARGET = qts60plugin_3_2 +TARGET = qts60plugin_3_2$${QT_LIBINFIX} contains(S60_VERSION, 3.1) { SOURCES += ../src/qlocale_3_1.cpp \ diff --git a/src/plugins/s60/5_0/5_0.pro b/src/plugins/s60/5_0/5_0.pro index 164dfaa..00aea1b 100644 --- a/src/plugins/s60/5_0/5_0.pro +++ b/src/plugins/s60/5_0/5_0.pro @@ -1,6 +1,6 @@ include(../s60pluginbase.pri) -TARGET = qts60plugin_5_0 +TARGET = qts60plugin_5_0$${QT_LIBINFIX} contains(S60_VERSION, 3.1) { SOURCES += ../src/qlocale_3_1.cpp \ diff --git a/src/qt3support/network/q3socketdevice_win.cpp b/src/qt3support/network/q3socketdevice_win.cpp index 528b50a..1354cfa 100644 --- a/src/qt3support/network/q3socketdevice_win.cpp +++ b/src/qt3support/network/q3socketdevice_win.cpp @@ -47,7 +47,6 @@ #include <string.h> -# include <qt_windows.h> #if defined (QT_NO_IPV6) # include <winsock.h> #else diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro index b2e873f..db1ee4d 100644 --- a/src/s60installs/s60installs.pro +++ b/src/s60installs/s60installs.pro @@ -7,25 +7,38 @@ symbian: { SUBDIRS= # WARNING: Changing TARGET name will break Symbian SISX upgrade functionality # DO NOT TOUCH TARGET VARIABLE IF YOU ARE NOT SURE WHAT YOU ARE DOING - TARGET = "Qt" - TARGET.UID3 = 0x2001E61C + TARGET = "Qt$${QT_LIBINFIX}" + + isEmpty(QT_LIBINFIX) { + TARGET.UID3 = 0x2001E61C + + # sqlite3 is expected to be already found on phone if infixed configuration is built. + sqlitedeployment = \ + "; Deploy sqlite onto phone that does not have it already" \ + "@\"$$PWD/sqlite3.sis\", (0x2002af5f)" + qtlibraries.pkg_postrules += sqlitedeployment + } else { + # Always use experimental UID for infixed configuration to avoid UID clash + TARGET.UID3 = 0xE001E61C + } VERSION=$${QT_MAJOR_VERSION}.$${QT_MINOR_VERSION}.$${QT_PATCH_VERSION} symbian-abld|symbian-sbsv2 { - qtresources.sources = $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/s60main.rsc + qtresources.sources = $${EPOCROOT}$$HW_ZDIR$$APP_RESOURCE_DIR/s60main$${QT_LIBINFIX}.rsc } else { - qtresources.sources = $$QMAKE_LIBDIR_QT/s60main.rsc + qtresources.sources = $$QMAKE_LIBDIR_QT/s60main$${QT_LIBINFIX}.rsc DESTDIR = $$QMAKE_LIBDIR_QT } qtresources.path = c:$$APP_RESOURCE_DIR + DEPLOYMENT += qtresources qtlibraries.sources = \ - $$QMAKE_LIBDIR_QT/QtCore.dll \ - $$QMAKE_LIBDIR_QT/QtXml.dll \ - $$QMAKE_LIBDIR_QT/QtGui.dll \ - $$QMAKE_LIBDIR_QT/QtNetwork.dll \ - $$QMAKE_LIBDIR_QT/QtTest.dll \ - $$QMAKE_LIBDIR_QT/QtSql.dll + $$QMAKE_LIBDIR_QT/QtCore$${QT_LIBINFIX}.dll \ + $$QMAKE_LIBDIR_QT/QtXml$${QT_LIBINFIX}.dll \ + $$QMAKE_LIBDIR_QT/QtGui$${QT_LIBINFIX}.dll \ + $$QMAKE_LIBDIR_QT/QtNetwork$${QT_LIBINFIX}.dll \ + $$QMAKE_LIBDIR_QT/QtTest$${QT_LIBINFIX}.dll \ + $$QMAKE_LIBDIR_QT/QtSql$${QT_LIBINFIX}.dll symbian-abld|symbian-sbsv2 { pluginLocations = $${EPOCROOT}epoc32/release/$(PLATFORM)/$(TARGET) @@ -35,20 +48,16 @@ symbian: { qts60plugindeployment = \ "IF package(0x1028315F)" \ - " \"$$pluginLocations/qts60plugin_5_0.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0.dll\"" \ + " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ "ELSEIF package(0x102752AE)" \ - " \"$$pluginLocations/qts60plugin_3_2.dll\" - \"c:\\sys\\bin\\qts60plugin_3_2.dll\"" \ + " \"$$pluginLocations/qts60plugin_3_2$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_3_2$${QT_LIBINFIX}.dll\"" \ "ELSEIF package(0x102032BE)" \ - " \"$$pluginLocations/qts60plugin_3_1.dll\" - \"c:\\sys\\bin\\qts60plugin_3_1.dll\"" \ + " \"$$pluginLocations/qts60plugin_3_1$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_3_1$${QT_LIBINFIX}.dll\"" \ "ELSE" \ - " \"$$pluginLocations/qts60plugin_5_0.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0.dll\"" \ + " \"$$pluginLocations/qts60plugin_5_0$${QT_LIBINFIX}.dll\" - \"c:\\sys\\bin\\qts60plugin_5_0$${QT_LIBINFIX}.dll\"" \ "ENDIF" qtlibraries.pkg_postrules += qts60plugindeployment - sqlitedeployment = \ - "; Deploy sqlite onto phone that does not have it already" \ - "@\"$$PWD/sqlite3.sis\", (0x2002af5f)" - qtlibraries.pkg_postrules += sqlitedeployment qtlibraries.path = c:/sys/bin @@ -72,18 +81,18 @@ symbian: { } qtlibraries.pkg_prerules += "(0x2002af5f), 0, 5, 0, {\"sqlite3\"}" - !contains(QT_CONFIG, no-jpeg): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qjpeg.dll - !contains(QT_CONFIG, no-gif): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qgif.dll - !contains(QT_CONFIG, no-mng): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qmng.dll - !contains(QT_CONFIG, no-tiff): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qtiff.dll - !contains(QT_CONFIG, no-ico): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qico.dll + !contains(QT_CONFIG, no-jpeg): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qjpeg$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-gif): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qgif$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-mng): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qmng$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-tiff): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qtiff$${QT_LIBINFIX}.dll + !contains(QT_CONFIG, no-ico): imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qico$${QT_LIBINFIX}.dll imageformats_plugins.path = c:$$QT_PLUGINS_BASE_DIR/imageformats - codecs_plugins.sources = $$QT_BUILD_TREE/plugins/codecs/qcncodecs.dll $$QT_BUILD_TREE/plugins/codecs/qjpcodecs.dll $$QT_BUILD_TREE/plugins/codecs/qtwcodecs.dll $$QT_BUILD_TREE/plugins/codecs/qkrcodecs.dll + codecs_plugins.sources = $$QT_BUILD_TREE/plugins/codecs/qcncodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qjpcodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qtwcodecs$${QT_LIBINFIX}.dll $$QT_BUILD_TREE/plugins/codecs/qkrcodecs$${QT_LIBINFIX}.dll codecs_plugins.path = c:$$QT_PLUGINS_BASE_DIR/codecs contains(QT_CONFIG, phonon-backend) { - phonon_backend_plugins.sources += $$QMAKE_LIBDIR_QT/phonon_mmf.dll + phonon_backend_plugins.sources += $$QMAKE_LIBDIR_QT/phonon_mmf$${QT_LIBINFIX}.dll phonon_backend_plugins.path = c:$$QT_PLUGINS_BASE_DIR/phonon_backend DEPLOYMENT += phonon_backend_plugins @@ -94,10 +103,9 @@ symbian: { qtbackup.path = c:/private/10202D56/import/packages/$$replace(TARGET.UID3, 0x,) bearer_plugins.path = c:$$QT_PLUGINS_BASE_DIR/bearer - bearer_plugins.sources += $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer.dll + bearer_plugins.sources += $$QT_BUILD_TREE/plugins/bearer/qsymbianbearer$${QT_LIBINFIX}.dll - DEPLOYMENT += qtresources \ - qtlibraries \ + DEPLOYMENT += qtlibraries \ qtbackup \ imageformats_plugins \ codecs_plugins \ @@ -105,37 +113,37 @@ symbian: { bearer_plugins contains(QT_CONFIG, svg): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtSvg.dll - imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qsvg.dll - iconengines_plugins.sources = $$QT_BUILD_TREE/plugins/iconengines/qsvgicon.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtSvg$${QT_LIBINFIX}.dll + imageformats_plugins.sources += $$QT_BUILD_TREE/plugins/imageformats/qsvg$${QT_LIBINFIX}.dll + iconengines_plugins.sources = $$QT_BUILD_TREE/plugins/iconengines/qsvgicon$${QT_LIBINFIX}.dll iconengines_plugins.path = c:$$QT_PLUGINS_BASE_DIR/iconengines DEPLOYMENT += iconengines_plugins } contains(QT_CONFIG, phonon): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/phonon.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/phonon$${QT_LIBINFIX}.dll } contains(QT_CONFIG, script): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtScript.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtScript$${QT_LIBINFIX}.dll } contains(QT_CONFIG, xmlpatterns): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtXmlPatterns.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtXmlPatterns$${QT_LIBINFIX}.dll } contains(QT_CONFIG, declarative): { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtDeclarative.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtDeclarative$${QT_LIBINFIX}.dll } graphicssystems_plugins.path = c:$$QT_PLUGINS_BASE_DIR/graphicssystems contains(QT_CONFIG, openvg) { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtOpenVG.dll - graphicssystems_plugins.sources += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtOpenVG$${QT_LIBINFIX}.dll + graphicssystems_plugins.sources += $$QT_BUILD_TREE/plugins/graphicssystems/qvggraphicssystem$${QT_LIBINFIX}.dll } contains(QT_CONFIG, multimedia) { - qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtMultimedia.dll + qtlibraries.sources += $$QMAKE_LIBDIR_QT/QtMultimedia$${QT_LIBINFIX}.dll } BLD_INF_RULES.prj_exports += "qt.iby $$CORE_MW_LAYER_IBY_EXPORT_PATH(qt.iby)" diff --git a/src/script/api/qscriptengine.cpp b/src/script/api/qscriptengine.cpp index 294c3a0..356b4d0 100644 --- a/src/script/api/qscriptengine.cpp +++ b/src/script/api/qscriptengine.cpp @@ -3318,7 +3318,7 @@ void QScriptEngine::installTranslatorFunctions(const QScriptValue &object) JSC::JSValue jscObject = d->scriptValueToJSCValue(object); JSC::JSGlobalObject *glob = d->originalGlobalObject(); if (!jscObject || !jscObject.isObject()) - jscObject = glob; + jscObject = d->globalObject(); // unsigned attribs = JSC::DontEnum; JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 5, JSC::Identifier(exec, "qsTranslate"), QScript::functionQsTranslate)); JSC::asObject(jscObject)->putDirectFunction(exec, new (exec)JSC::NativeFunctionWrapper(exec, glob->prototypeFunctionStructure(), 2, JSC::Identifier(exec, "QT_TRANSLATE_NOOP"), QScript::functionQsTranslateNoOp)); diff --git a/src/script/api/qscriptvalue.cpp b/src/script/api/qscriptvalue.cpp index a3af2d4..5db1165 100644 --- a/src/script/api/qscriptvalue.cpp +++ b/src/script/api/qscriptvalue.cpp @@ -1609,7 +1609,7 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, JSC::MarkedArgumentBuffer applyArgs; if (!array.isUndefinedOrNull()) { if (!array.isObject()) { - return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError)); + return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); } if (JSC::asObject(array)->classInfo() == &JSC::Arguments::info) JSC::asArguments(array)->fillArgList(exec, applyArgs); @@ -1620,8 +1620,7 @@ QScriptValue QScriptValue::call(const QScriptValue &thisObject, for (unsigned i = 0; i < length; ++i) applyArgs.append(JSC::asArray(array)->get(exec, i)); } else { - Q_ASSERT_X(false, Q_FUNC_INFO, "implement me"); -// return JSC::throwError(exec, JSC::TypeError); + return d->engine->scriptValueFromJSCValue(JSC::throwError(exec, JSC::TypeError, "Arguments must be an array")); } } diff --git a/src/script/bridge/qscriptclassobject.cpp b/src/script/bridge/qscriptclassobject.cpp index a7b5f48..dd229f1 100644 --- a/src/script/bridge/qscriptclassobject.cpp +++ b/src/script/bridge/qscriptclassobject.cpp @@ -234,7 +234,7 @@ JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObjec QScriptClass *scriptClass = static_cast<ClassObjectDelegate*>(delegate)->scriptClass(); QScriptEnginePrivate *eng_p = scriptEngineFromExec(exec); - //JSC::ExecState *oldFrame = eng_p->currentFrame; + JSC::ExecState *oldFrame = eng_p->currentFrame; eng_p->pushContext(exec, JSC::JSValue(), args, callee, true); QScriptContext *ctx = eng_p->contextForFrame(eng_p->currentFrame); @@ -242,6 +242,8 @@ JSC::JSObject* ClassObjectDelegate::construct(JSC::ExecState *exec, JSC::JSObjec QScriptValue result = qvariant_cast<QScriptValue>(scriptClass->extension(QScriptClass::Callable, qVariantFromValue(ctx))); if (!result.isObject()) result = defaultObject; + eng_p->popContext(); + eng_p->currentFrame = oldFrame; return JSC::asObject(eng_p->scriptValueToJSCValue(result)); } diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 6729c62..9a982d0 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -738,18 +738,23 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (p.read.isEmpty()) continue; + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } if (p.gspec == PropertyDef::PointerSpec) - fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s())); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n", + propindex, prefix.constData(), p.read.constData()); else if (p.gspec == PropertyDef::ReferenceSpec) - fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s())); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n", + propindex, prefix.constData(), p.read.constData()); else if (cdef->enumDeclarations.value(p.type, false)) - fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s()); break;\n", - propindex, p.read.constData()); + fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n", + propindex, prefix.constData(), p.read.constData()); else - fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s(); break;\n", - propindex, p.type.constData(), p.read.constData()); + fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n", + propindex, p.type.constData(), prefix.constData(), p.read.constData()); } fprintf(out, " }\n"); } @@ -768,12 +773,17 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (p.write.isEmpty()) continue; + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } if (cdef->enumDeclarations.value(p.type, false)) { - fprintf(out, " case %d: %s(QFlag(*reinterpret_cast<int*>(_v))); break;\n", - propindex, p.write.constData()); + fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n", + propindex, prefix.constData(), p.write.constData()); } else { - fprintf(out, " case %d: %s(*reinterpret_cast< %s*>(_v)); break;\n", - propindex, p.write.constData(), p.type.constData()); + fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n", + propindex, prefix.constData(), p.write.constData(), p.type.constData()); } } fprintf(out, " }\n"); @@ -791,8 +801,13 @@ void Generator::generateMetacall() const PropertyDef &p = cdef->propertyList.at(propindex); if (!p.reset.endsWith(')')) continue; - fprintf(out, " case %d: %s; break;\n", - propindex, p.reset.constData()); + QByteArray prefix; + if (p.inPrivateClass.size()) { + prefix = p.inPrivateClass; + prefix.append("->"); + } + fprintf(out, " case %d: %s%s; break;\n", + propindex, prefix.constData(), p.reset.constData()); } fprintf(out, " }\n"); } diff --git a/src/tools/moc/keywords.cpp b/src/tools/moc/keywords.cpp index abc6be0..df1ba0d 100644 --- a/src/tools/moc/keywords.cpp +++ b/src/tools/moc/keywords.cpp @@ -43,12 +43,12 @@ // DO NOT EDIT. static const short keyword_trans[][128] = { - {0,0,0,0,0,0,0,0,0,525,522,0,0,0,0,0, + {0,0,0,0,0,0,0,0,0,533,530,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 525,252,523,526,0,38,239,524,25,26,236,234,30,235,27,237, + 533,252,531,534,0,38,239,532,25,26,236,234,30,235,27,237, 22,22,22,22,22,22,22,22,22,22,34,41,23,39,24,43, 0,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, - 8,21,8,8,8,8,8,8,8,8,8,31,527,32,238,8, + 8,21,8,8,8,8,8,8,8,8,8,31,535,32,238,8, 0,1,2,3,4,5,6,7,8,9,8,8,10,11,12,13, 14,8,15,16,17,18,19,20,8,8,8,36,245,37,248,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -190,7 +190,7 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,42,0,0,0,28,0, - 530,530,530,530,530,530,530,530,530,530,0,0,0,0,0,0, + 538,538,538,538,538,538,538,538,538,538,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -349,7 +349,7 @@ static const short keyword_trans[][128] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,529,0,0,0,0,528, + 0,0,0,0,0,0,0,0,0,0,537,0,0,0,0,536, 0,0,0,0,0,0,0,0,0,0,0,0,0,258,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, @@ -430,6 +430,14 @@ static const short keyword_trans[][128] = { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 522,0,0,481,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, + {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,497,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,486, @@ -925,12 +933,12 @@ static const struct {CHARACTER, 0, 84, 478, CHARACTER}, {CHARACTER, 0, 69, 479, CHARACTER}, {CHARACTER, 0, 95, 480, CHARACTER}, - {CHARACTER, 0, 83, 481, CHARACTER}, + {CHARACTER, 48, 0, 0, CHARACTER}, {CHARACTER, 0, 76, 482, CHARACTER}, {CHARACTER, 0, 79, 483, CHARACTER}, {CHARACTER, 0, 84, 484, CHARACTER}, {Q_PRIVATE_SLOT_TOKEN, 0, 0, 0, CHARACTER}, - {CHARACTER, 48, 0, 0, CHARACTER}, + {CHARACTER, 49, 0, 0, CHARACTER}, {CHARACTER, 0, 77, 487, CHARACTER}, {CHARACTER, 0, 79, 488, CHARACTER}, {CHARACTER, 0, 67, 489, CHARACTER}, @@ -967,6 +975,14 @@ static const struct {CHARACTER, 0, 76, 520, CHARACTER}, {CHARACTER, 0, 69, 521, CHARACTER}, {Q_SCRIPTABLE_TOKEN, 0, 0, 0, CHARACTER}, + {CHARACTER, 0, 82, 523, CHARACTER}, + {CHARACTER, 0, 79, 524, CHARACTER}, + {CHARACTER, 0, 80, 525, CHARACTER}, + {CHARACTER, 0, 69, 526, CHARACTER}, + {CHARACTER, 0, 82, 527, CHARACTER}, + {CHARACTER, 0, 84, 528, CHARACTER}, + {CHARACTER, 0, 89, 529, CHARACTER}, + {Q_PRIVATE_PROPERTY_TOKEN, 0, 0, 0, CHARACTER}, {NEWLINE, 0, 0, 0, NOTOKEN}, {QUOTE, 0, 0, 0, NOTOKEN}, {SINGLEQUOTE, 0, 0, 0, NOTOKEN}, diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 94ad56f..680b8a5 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -658,6 +658,9 @@ void Moc::parse() case Q_PRIVATE_SLOT_TOKEN: parseSlotInPrivate(&def, access); break; + case Q_PRIVATE_PROPERTY_TOKEN: + parsePrivateProperty(&def); + break; case ENUM: { EnumDef enumDef; if (parseEnum(&enumDef)) @@ -872,11 +875,8 @@ void Moc::parseSignals(ClassDef *def) } } - -void Moc::parseProperty(ClassDef *def) +void Moc::createPropertyDef(PropertyDef &propDef) { - next(LPAREN); - PropertyDef propDef; QByteArray type = parseType().name; if (type.isEmpty()) error(); @@ -964,7 +964,6 @@ void Moc::parseProperty(ClassDef *def) error(2); } } - next(RPAREN); if (propDef.read.isNull()) { QByteArray msg; msg += "Property declaration "; @@ -988,6 +987,41 @@ void Moc::parseProperty(ClassDef *def) propDef.constant = false; warning(msg.constData()); } +} + +void Moc::parseProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + createPropertyDef(propDef); + next(RPAREN); + + + if(!propDef.notify.isEmpty()) + def->notifyableProperties++; + def->propertyList += propDef; +} + +void Moc::parsePrivateProperty(ClassDef *def) +{ + next(LPAREN); + PropertyDef propDef; + next(IDENTIFIER); + propDef.inPrivateClass = lexem(); + while (test(SCOPE)) { + propDef.inPrivateClass += lexem(); + next(IDENTIFIER); + propDef.inPrivateClass += lexem(); + } + // also allow void functions + if (test(LPAREN)) { + next(RPAREN); + propDef.inPrivateClass += "()"; + } + + next(COMMA); + + createPropertyDef(propDef); if(!propDef.notify.isEmpty()) def->notifyableProperties++; diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 10abfc6..d365ed5 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -116,7 +116,7 @@ struct FunctionDef struct PropertyDef { PropertyDef():notifyId(-1), constant(false), final(false), gspec(ValueSpec){} - QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify; + QByteArray name, type, read, write, reset, designable, scriptable, editable, stored, user, notify, inPrivateClass; int notifyId; bool constant; bool final; @@ -217,6 +217,7 @@ public: void parseSlots(ClassDef *def, FunctionDef::Access access); void parseSignals(ClassDef *def); void parseProperty(ClassDef *def); + void createPropertyDef(PropertyDef &def); void parseEnumOrFlag(ClassDef *def, bool isFlag); void parseFlag(ClassDef *def); void parseClassInfo(ClassDef *def); @@ -224,6 +225,7 @@ public: void parseDeclareInterface(); void parseDeclareMetatype(); void parseSlotInPrivate(ClassDef *def, FunctionDef::Access access); + void parsePrivateProperty(ClassDef *def); void parseFunctionArguments(FunctionDef *def); diff --git a/src/tools/moc/token.cpp b/src/tools/moc/token.cpp index 98307a1..3da9446 100644 --- a/src/tools/moc/token.cpp +++ b/src/tools/moc/token.cpp @@ -179,6 +179,7 @@ const char *tokenTypeName(Token t) case Q_SIGNAL_TOKEN: return "Q_SIGNAL_TOKEN"; case Q_SLOT_TOKEN: return "Q_SLOT_TOKEN"; case Q_PRIVATE_SLOT_TOKEN: return "Q_PRIVATE_SLOT_TOKEN"; + case Q_PRIVATE_PROPERTY_TOKEN: return "Q_PRIVATE_PROPERTY_TOKEN"; case SPECIAL_TREATMENT_MARK: return "SPECIAL_TREATMENT_MARK"; case MOC_INCLUDE_BEGIN: return "MOC_INCLUDE_BEGIN"; case MOC_INCLUDE_END: return "MOC_INCLUDE_END"; diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index 6b1ad7d..6ca3d84 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -185,6 +185,7 @@ enum Token { Q_QT3_SUPPORT_TOKEN, Q_INVOKABLE_TOKEN, Q_SCRIPTABLE_TOKEN, + Q_PRIVATE_PROPERTY_TOKEN, Q_META_TOKEN_END, SPECIAL_TREATMENT_MARK = Q_META_TOKEN_END, MOC_INCLUDE_BEGIN, diff --git a/src/tools/moc/util/generate_keywords.cpp b/src/tools/moc/util/generate_keywords.cpp index 0641b40..88f187d 100644 --- a/src/tools/moc/util/generate_keywords.cpp +++ b/src/tools/moc/util/generate_keywords.cpp @@ -248,7 +248,7 @@ static const Keyword keywords[] = { { "Q_SIGNAL", "Q_SIGNAL_TOKEN" }, { "Q_SLOT", "Q_SLOT_TOKEN" }, { "Q_SCRIPTABLE", "Q_SCRIPTABLE_TOKEN" }, - + { "Q_PRIVATE_PROPERTY", "Q_PRIVATE_PROPERTY_TOKEN" }, { "\n", "NEWLINE" }, { "\"", "QUOTE" }, { "\'", "SINGLEQUOTE" }, diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index fad4845..30c2721 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -484,6 +484,7 @@ private slots: void singleFunctionKeywordSignalAndSlot(); void templateGtGt(); void qprivateslots(); + void qprivateproperties(); void inlineSlotsWithThrowDeclaration(); void warnOnPropertyWithoutREAD(); void constructors(); @@ -1071,6 +1072,56 @@ void tst_Moc::qprivateslots() QVERIFY(mobj->indexOfMethod("method1()") != -1); //tast204730 } +class PrivatePropertyTest : public QObject +{ + Q_OBJECT + Q_PROPERTY(int foo READ foo WRITE setFoo); + Q_PRIVATE_PROPERTY(d, int bar READ bar WRITE setBar); + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d, int plop READ plop WRITE setPlop); + Q_PRIVATE_PROPERTY(PrivatePropertyTest::d_func(), int baz READ baz WRITE setBaz); + class MyDPointer { + public: + MyDPointer() : mBar(0), mPlop(0) {} + int bar() { return mBar ; } + void setBar(int value) { mBar = value; } + int plop() { return mPlop ; } + void setPlop(int value) { mPlop = value; } + int baz() { return mBaz ; } + void setBaz(int value) { mBaz = value; } + private: + int mBar; + int mPlop; + int mBaz; + }; +public: + PrivatePropertyTest() : mFoo(0), d (new MyDPointer) {} + int foo() { return mFoo ; } + void setFoo(int value) { mFoo = value; } + MyDPointer *d_func() {return d;} +private: + int mFoo; + MyDPointer *d; +}; + + +void tst_Moc::qprivateproperties() +{ + PrivatePropertyTest test; + + test.setProperty("foo", 1); + QCOMPARE(test.property("foo"), qVariantFromValue(1)); + + test.setProperty("bar", 2); + QCOMPARE(test.property("bar"), qVariantFromValue(2)); + + test.setProperty("plop", 3); + QCOMPARE(test.property("plop"), qVariantFromValue(3)); + + test.setProperty("baz", 4); + QCOMPARE(test.property("baz"), qVariantFromValue(4)); + +} + #include "task189996.h" void InlineSlotsWithThrowDeclaration::c() throw() {} diff --git a/tests/auto/qaccessibility/tst_qaccessibility.cpp b/tests/auto/qaccessibility/tst_qaccessibility.cpp index 133cb33..e5a332a 100644 --- a/tests/auto/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/qaccessibility/tst_qaccessibility.cpp @@ -3923,9 +3923,8 @@ void tst_QAccessibility::comboBoxTest() acc = QAccessible::queryAccessibleInterface(cb); - QRect accRect = acc->rect(0); for (int i = 1; i < acc->childCount(); ++i) { - QVERIFY(accRect.contains(acc->rect(i))); + QTRY_VERIFY(acc->rect(0).contains(acc->rect(i))); } QCOMPARE(acc->doAction(QAccessible::Press, 2), true); QTest::qWait(400); diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp index c0ad8bf..92a7f2e 100644 --- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp +++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp @@ -7719,7 +7719,7 @@ void tst_QGraphicsItem::hitTestGraphicsEffectItem() QTest::qWait(50); // Make sure all visible items are repainted. - QCOMPARE(item1->repaints, 0); + QCOMPARE(item1->repaints, 1); QCOMPARE(item2->repaints, 1); QCOMPARE(item3->repaints, 1); @@ -9819,6 +9819,16 @@ void tst_QGraphicsItem::scenePosChange() QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 4); QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); + + root->setX(1); + QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 5); + QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); + QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); + + root->setY(1); + QCOMPARE(child1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 6); + QCOMPARE(grandChild1->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 1); + QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0); } void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor() diff --git a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp index d37ff76..a155222 100644 --- a/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp +++ b/tests/auto/qgraphicsscene/tst_qgraphicsscene.cpp @@ -284,6 +284,7 @@ private slots: void task250680_childClip(); void taskQTBUG_5904_crashWithDeviceCoordinateCache(); void taskQT657_paintIntoCacheWithTransparentParts(); + void taskQTBUG_7863_paintIntoCacheWithTransparentParts(); }; void tst_QGraphicsScene::initTestCase() @@ -4349,12 +4350,14 @@ void tst_QGraphicsScene::taskQTBUG_5904_crashWithDeviceCoordinateCache() void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() { + // Test using DeviceCoordinateCache and opaque item QWidget *w = new QWidget(); - w->setPalette(Qt::blue); + w->setPalette(QColor(0, 0, 255)); w->setGeometry(0, 0, 50, 50); QGraphicsScene *scene = new QGraphicsScene(); - QGraphicsView *view = new QGraphicsView(scene); + CustomView *view = new CustomView; + view->setScene(scene); QGraphicsProxyWidget *proxy = scene->addWidget(w); proxy->setCacheMode(QGraphicsItem::DeviceCoordinateCache); @@ -4362,13 +4365,14 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() view->show(); QTest::qWaitForWindowShown(view); - w->update(10,10,10,10); + view->repaints = 0; + proxy->update(10, 10, 10, 10); QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); QPixmap pix; QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(proxy); - QPixmapCache::Key key = itemp->extraItemCache()->deviceData.value(view->viewport()).key; - QVERIFY(QPixmapCache::find(key, &pix)); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix)); QTransform t = proxy->sceneTransform(); // Map from scene coordinates to pixmap coordinates. @@ -4383,6 +4387,138 @@ void tst_QGraphicsScene::taskQT657_paintIntoCacheWithTransparentParts() for(int j = 0; j < im.height(); j++) QCOMPARE(qAlpha(im.pixel(i, j)), 255); } + + delete w; +} + +void tst_QGraphicsScene::taskQTBUG_7863_paintIntoCacheWithTransparentParts() +{ + // Test using DeviceCoordinateCache and semi-transparent item + { + QGraphicsRectItem *backItem = new QGraphicsRectItem(0, 0, 100, 100); + backItem->setBrush(QColor(255, 255, 0)); + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50); + rectItem->setBrush(QColor(0, 0, 255, 125)); + rectItem->setParentItem(backItem); + + QGraphicsScene *scene = new QGraphicsScene(); + CustomView *view = new CustomView; + view->setScene(scene); + + scene->addItem(backItem); + rectItem->setCacheMode(QGraphicsItem::DeviceCoordinateCache); + backItem->rotate(15); + + view->show(); + QTest::qWaitForWindowShown(view); + view->repaints = 0; + rectItem->update(10, 10, 10, 10); + QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); + + QPixmap pix; + QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->deviceData.value(view->viewport()).key, &pix)); + + QTransform t = rectItem->sceneTransform(); + // Map from scene coordinates to pixmap coordinates. + // X origin in the pixmap is the most-left point + // of the item's boundingRect in the scene. + qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left(); + QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1); + QPixmap subpix = pix.copy(rect); + + QImage im = subpix.toImage(); + for(int i = 0; i < im.width(); i++) { + for(int j = 0; j < im.height(); j++) { + QCOMPARE(qAlpha(im.pixel(i, j)), 125); + } + } + + delete view; + } + + // Test using ItemCoordinateCache and opaque item + { + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50); + rectItem->setBrush(QColor(0, 0, 255)); + + QGraphicsScene *scene = new QGraphicsScene(); + CustomView *view = new CustomView; + view->setScene(scene); + + scene->addItem(rectItem); + rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); + rectItem->rotate(15); + + view->show(); + QTest::qWaitForWindowShown(view); + view->repaints = 0; + rectItem->update(10, 10, 10, 10); + QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); + + QPixmap pix; + QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix)); + + QTransform t = rectItem->sceneTransform(); + // Map from scene coordinates to pixmap coordinates. + // X origin in the pixmap is the most-left point + // of the item's boundingRect in the scene. + qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left(); + QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1); + QPixmap subpix = pix.copy(rect); + + QImage im = subpix.toImage(); + for(int i = 0; i < im.width(); i++) { + for(int j = 0; j < im.height(); j++) + QCOMPARE(qAlpha(im.pixel(i, j)), 255); + } + + delete view; + } + + // Test using ItemCoordinateCache and semi-transparent item + { + QGraphicsRectItem *rectItem = new QGraphicsRectItem(0, 0, 50, 50); + rectItem->setBrush(QColor(0, 0, 255, 125)); + + QGraphicsScene *scene = new QGraphicsScene(); + CustomView *view = new CustomView; + view->setScene(scene); + + scene->addItem(rectItem); + rectItem->setCacheMode(QGraphicsItem::ItemCoordinateCache); + rectItem->rotate(15); + + view->show(); + QTest::qWaitForWindowShown(view); + view->repaints = 0; + rectItem->update(10, 10, 10, 10); + QTest::qWait(50); + QTRY_VERIFY(view->repaints > 0); + + QPixmap pix; + QGraphicsItemPrivate* itemp = QGraphicsItemPrivate::get(rectItem); + QTRY_VERIFY(QPixmapCache::find(itemp->extraItemCache()->key, &pix)); + + QTransform t = rectItem->sceneTransform(); + // Map from scene coordinates to pixmap coordinates. + // X origin in the pixmap is the most-left point + // of the item's boundingRect in the scene. + qreal adjust = t.mapRect(rectItem->boundingRect().toRect()).left(); + QRect rect = t.mapRect(QRect(10, 10, 10, 10)).adjusted(-adjust, 0, -adjust + 1, 1); + QPixmap subpix = pix.copy(rect); + + QImage im = subpix.toImage(); + for(int i = 0; i < im.width(); i++) { + for(int j = 0; j < im.height(); j++) + QCOMPARE(qAlpha(im.pixel(i, j)), 125); + } + + delete view; + } } QTEST_MAIN(tst_QGraphicsScene) diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 6941d23..587b7d5 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -462,7 +462,7 @@ void tst_QGraphicsWidget::focusWidget() QFETCH(int, childWithFocus); SubQGraphicsWidget *widget = children[childWithFocus]; widget->setFocus(); - QVERIFY(widget->hasFocus()); + QTRY_VERIFY(widget->hasFocus()); QCOMPARE(parent->focusWidget(), static_cast<QGraphicsWidget*>(widget)); } } @@ -479,23 +479,23 @@ void tst_QGraphicsWidget::focusWidget2() scene.addItem(widget); - QVERIFY(!widget->hasFocus()); + QTRY_VERIFY(!widget->hasFocus()); widget->setFocusPolicy(Qt::StrongFocus); - QVERIFY(!widget->hasFocus()); + QTRY_VERIFY(!widget->hasFocus()); QGraphicsWidget *subWidget = new QGraphicsWidget(widget); - QVERIFY(!subWidget->hasFocus()); + QTRY_VERIFY(!subWidget->hasFocus()); scene.setFocus(); - QVERIFY(!widget->hasFocus()); - QVERIFY(!subWidget->hasFocus()); + QTRY_VERIFY(!widget->hasFocus()); + QTRY_VERIFY(!subWidget->hasFocus()); widget->setFocus(); - QVERIFY(widget->hasFocus()); - QCOMPARE(focusInSpy.count(), 1); - QVERIFY(!subWidget->hasFocus()); + QTRY_VERIFY(widget->hasFocus()); + QTRY_COMPARE(focusInSpy.count(), 1); + QTRY_VERIFY(!subWidget->hasFocus()); QGraphicsWidget *otherSubWidget = new QGraphicsWidget; EventSpy otherFocusInSpy(otherSubWidget, QEvent::FocusIn); @@ -504,18 +504,18 @@ void tst_QGraphicsWidget::focusWidget2() otherSubWidget->setFocusPolicy(Qt::StrongFocus); otherSubWidget->setParentItem(widget); - QVERIFY(widget->hasFocus()); + QTRY_VERIFY(widget->hasFocus()); QCOMPARE(scene.focusItem(), (QGraphicsItem *)widget); - QVERIFY(!subWidget->hasFocus()); - QVERIFY(!otherSubWidget->hasFocus()); + QTRY_VERIFY(!subWidget->hasFocus()); + QTRY_VERIFY(!otherSubWidget->hasFocus()); widget->hide(); - QVERIFY(!widget->hasFocus()); // lose but still has subfocus + QTRY_VERIFY(!widget->hasFocus()); // lose but still has subfocus QCOMPARE(focusInSpy.count(), 1); QCOMPARE(focusOutSpy.count(), 1); widget->show(); - QVERIFY(!widget->hasFocus()); // no regain + QTRY_VERIFY(!widget->hasFocus()); // no regain QCOMPARE(focusInSpy.count(), 1); QCOMPARE(focusOutSpy.count(), 1); @@ -523,24 +523,24 @@ void tst_QGraphicsWidget::focusWidget2() // try to setup subFocus on item that can't take focus subWidget->setFocus(); - QVERIFY(!subWidget->hasFocus()); + QTRY_VERIFY(!subWidget->hasFocus()); QVERIFY(!scene.focusItem()); // but isn't the scene's focus item // try to setup subFocus on item that can take focus otherSubWidget->setFocus(); - QVERIFY(!otherSubWidget->hasFocus()); + QTRY_VERIFY(!otherSubWidget->hasFocus()); QCOMPARE(widget->focusWidget(), otherSubWidget); QVERIFY(!scene.focusItem()); // but isn't the scene's focus item widget->show(); - QCOMPARE(scene.focusItem(), (QGraphicsItem *)otherSubWidget); // but isn't the scene's focus item + QTRY_COMPARE(scene.focusItem(), (QGraphicsItem *)otherSubWidget); // but isn't the scene's focus item QCOMPARE(otherFocusInSpy.count(), 1); QCOMPARE(otherFocusOutSpy.count(), 0); delete otherSubWidget; - QCOMPARE(otherFocusOutSpy.count(), 1); + QTRY_COMPARE(otherFocusOutSpy.count(), 1); QVERIFY(!scene.focusItem()); QVERIFY(!widget->focusWidget()); } @@ -579,16 +579,16 @@ void tst_QGraphicsWidget::focusPolicy() SubQGraphicsWidget *widget = new SubQGraphicsWidget; scene.addItem(widget); - QCOMPARE(Qt::NoFocus, widget->focusPolicy()); + QTRY_COMPARE(Qt::NoFocus, widget->focusPolicy()); QFETCH(Qt::FocusPolicy, focusPolicy1); widget->setFocusPolicy(focusPolicy1); - QCOMPARE(widget->focusPolicy(), focusPolicy1); + QTRY_COMPARE(widget->focusPolicy(), focusPolicy1); bool isFocusable = widget->flags() & QGraphicsItem::ItemIsFocusable; bool wasFocusable = isFocusable; - QVERIFY(isFocusable == (focusPolicy1 != Qt::NoFocus)); + QTRY_VERIFY(isFocusable == (focusPolicy1 != Qt::NoFocus)); widget->setFocus(); - QCOMPARE(widget->hasFocus(), isFocusable); + QTRY_COMPARE(widget->hasFocus(), isFocusable); QFETCH(Qt::FocusPolicy, focusPolicy2); widget->setFocusPolicy(focusPolicy2); @@ -691,25 +691,21 @@ void tst_QGraphicsWidget::fontChangedEvent() EventSpy rootSpyFont(root, QEvent::FontChange); EventSpy rootSpyPolish(root, QEvent::Polish); - QCOMPARE(rootSpyFont.count(), 0); - QApplication::processEvents(); //The polish event is sent - QCOMPARE(rootSpyPolish.count(), 1); - QApplication::processEvents(); //Process events to see if we get the font change event + QTRY_COMPARE(rootSpyFont.count(), 0); + QTRY_COMPARE(rootSpyPolish.count(), 1); //The font is still the same so no fontChangeEvent - QCOMPARE(rootSpyFont.count(), 0); + QTRY_COMPARE(rootSpyFont.count(), 0); QFont font; font.setPointSize(43); root->setFont(font); - QApplication::processEvents(); //Process events to get the font change event //The font changed - QCOMPARE(rootSpyFont.count(), 1); + QTRY_COMPARE(rootSpyFont.count(), 1); //then roll back to the default one. root->setFont(appFont); - QApplication::processEvents(); //Process events to get the font change event //The font changed - QCOMPARE(rootSpyFont.count(), 2); + QTRY_COMPARE(rootSpyFont.count(), 2); } void tst_QGraphicsWidget::fontPropagationWidgetItemWidget() @@ -770,11 +766,13 @@ void tst_QGraphicsWidget::geometry() { SubQGraphicsWidget widget; QCOMPARE(widget.geometry(), QRectF(widget.pos(), widget.size())); - + QSignalSpy spy(&widget, SIGNAL(geometryChanged())); QFETCH(QPointF, pos); QFETCH(QSizeF, size); widget.setPos(pos); widget.resize(size); + if (!size.isNull()) + QCOMPARE(spy.count(), 1); QCOMPARE(widget.geometry(), QRectF(pos, size)); } @@ -843,7 +841,6 @@ void tst_QGraphicsWidget::initStyleOption() qt_x11_wait_for_window_manager(&view); #endif QApplication::setActiveWindow(&view); - QTest::qWait(25); QTRY_COMPARE(QApplication::activeWindow(), &view); view.setAlignment(Qt::AlignTop | Qt::AlignLeft); @@ -868,7 +865,6 @@ void tst_QGraphicsWidget::initStyleOption() view.resize(300, 300); view.show(); QTest::qWaitForWindowShown(&view); - QTest::qWait(20); sendMouseMove(view.viewport(), view.mapFromScene(widget->mapToScene(widget->boundingRect().center()))); } @@ -921,9 +917,7 @@ void tst_QGraphicsWidget::layout() } widget.setLayout(layout); - QTest::qWait(25); - - QCOMPARE(widget.layout(), static_cast<QGraphicsLayout*>(layout)); + QTRY_COMPARE(widget.layout(), static_cast<QGraphicsLayout*>(layout)); for (int i = 0; i < children.count(); ++i) { SubQGraphicsWidget *item = children[i]; QCOMPARE(item->parentWidget(), (QGraphicsWidget *)&widget); @@ -963,10 +957,9 @@ void tst_QGraphicsWidget::layoutDirection() view->show(); QTest::qWaitForWindowShown(view); for (int i = 0; i < children.count(); ++i) { - QCOMPARE(children[i]->layoutDirection(), layoutDirection); - QCOMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false); + QTRY_COMPARE(children[i]->layoutDirection(), layoutDirection); + QTRY_COMPARE(children[i]->testAttribute(Qt::WA_SetLayoutDirection), false); view->repaint(); - QApplication::processEvents(); QTRY_COMPARE(children[i]->m_painterLayoutDirection, layoutDirection); } delete view; @@ -1179,7 +1172,6 @@ void tst_QGraphicsWidget::setTabOrder() qt_x11_wait_for_window_manager(&view); #endif QApplication::setActiveWindow(&view); - QTest::qWait(25); QTRY_COMPARE(QApplication::activeWindow(), &view); QGraphicsWidget *lastItem = 0; @@ -1200,7 +1192,6 @@ void tst_QGraphicsWidget::setTabOrder() if (!children.isEmpty()) { QGraphicsWidget *first = children.first(); view.viewport()->setFocus(); - QApplication::processEvents(); QTRY_VERIFY(view.viewport()->hasFocus()); first->setFocus(); QVERIFY(first->hasFocus()); @@ -1461,18 +1452,14 @@ void tst_QGraphicsWidget::verifyFocusChain() QTest::qWaitForWindowShown(window); lineEdit->setFocus(); - QTest::qWait(25); QTRY_VERIFY(lineEdit->hasFocus()); QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); - QTest::qWait(25); QTRY_VERIFY(w1_1->hasFocus()); QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); - QTest::qWait(25); QTRY_VERIFY(w1_2->hasFocus()); // remove the tabFocusFirst and insert new item delete w1_1; // calls _q_removeItemLater - QTest::qWait(25); SubQGraphicsWidget *w1_3 = new SubQGraphicsWidget; w1_3->setFocusPolicy(Qt::StrongFocus); w1_3->setData(0, "w1_3"); @@ -1480,14 +1467,11 @@ void tst_QGraphicsWidget::verifyFocusChain() scene.addItem(w1_3); QTRY_VERIFY(w1_2->hasFocus()); QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab); - QTest::qWait(25); QTRY_VERIFY(lineEdit->hasFocus()); // tabFocusFirst should now point to w1_2 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); - QTest::qWait(25); QTRY_VERIFY(w1_2->hasFocus()); QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); - QTest::qWait(25); QTRY_VERIFY(w1_3->hasFocus()); scene.removeItem(w1_2); // does not call _q_removeItemLater delete w1_2; // calls _q_removeItemLater @@ -1498,16 +1482,12 @@ void tst_QGraphicsWidget::verifyFocusChain() w1_4->setGeometry(75,0,25, 25); scene.addItem(w1_4); QTRY_VERIFY(w1_3->hasFocus()); - QTest::qWait(25); QTRY_VERIFY(compareFocusChain(view, QList<QGraphicsItem*>() << w1_3 << w1_4)); QTest::keyPress(QApplication::focusWidget(), Qt::Key_Backtab); - QTest::qWait(25); QTRY_VERIFY(lineEdit->hasFocus()); // tabFocusFirst should now point to w1_3 QTest::keyPress(QApplication::focusWidget(), Qt::Key_Tab); - QTest::qWait(25); QTRY_VERIFY(w1_3->hasFocus()); - QTest::qWait(25); QTRY_VERIFY(compareFocusChain(view, QList<QGraphicsItem*>() << w1_3 << w1_4)); delete window; } @@ -1522,7 +1502,6 @@ void tst_QGraphicsWidget::updateFocusChainWhenChildDie() qt_x11_wait_for_window_manager(&view); #endif QApplication::setActiveWindow(&view); - QTest::qWait(25); QTRY_COMPARE(QApplication::activeWindow(), &view); // delete item in focus chain with no focus and verify chain @@ -1756,31 +1735,29 @@ void tst_QGraphicsWidget::setSizes() widget->setPreferredSize(pref); widget->setMaximumSize(max); - QApplication::processEvents(); - for (i = 0; i < compareInstructions.count(); ++i) { Inst input = compareInstructions.at(i); switch (input.first) { case MinimumSize: - QCOMPARE(widget->minimumSize(), input.second.toSizeF()); + QTRY_COMPARE(widget->minimumSize(), input.second.toSizeF()); break; case PreferredSize: - QCOMPARE(widget->preferredSize(), input.second.toSizeF()); + QTRY_COMPARE(widget->preferredSize(), input.second.toSizeF()); break; case MaximumSize: - QCOMPARE(widget->maximumSize(), input.second.toSizeF()); + QTRY_COMPARE(widget->maximumSize(), input.second.toSizeF()); break; case Size: - QCOMPARE(widget->size(), input.second.toSizeF()); + QTRY_COMPARE(widget->size(), input.second.toSizeF()); break; case MinimumWidth: - QCOMPARE(widget->minimumWidth(), qreal(input.second.toDouble())); + QTRY_COMPARE(widget->minimumWidth(), qreal(input.second.toDouble())); break; case PreferredWidth: - QCOMPARE(widget->preferredWidth(), qreal(input.second.toDouble())); + QTRY_COMPARE(widget->preferredWidth(), qreal(input.second.toDouble())); break; case MaximumWidth: - QCOMPARE(widget->maximumWidth(), qreal(input.second.toDouble())); + QTRY_COMPARE(widget->maximumWidth(), qreal(input.second.toDouble())); break; default: qWarning("instruction not implemented"); @@ -1835,14 +1812,13 @@ void tst_QGraphicsWidget::task236127_bspTreeIndexFails() #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); #endif - QTest::qWait(100); - QVERIFY(!scene.itemAt(25, 25)); + QTRY_VERIFY(!scene.itemAt(25, 25)); widget->setGeometry(0, 112, 360, 528); - QCOMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget); + QTRY_COMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget); widget2->setGeometry(0, 573, 360, 67); - QCOMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget); - QCOMPARE(scene.itemAt(50, 585), (QGraphicsItem *)widget2); + QTRY_COMPARE(scene.itemAt(15, 120), (QGraphicsItem *)widget); + QTRY_COMPARE(scene.itemAt(50, 585), (QGraphicsItem *)widget2); } void tst_QGraphicsWidget::defaultSize() @@ -1857,7 +1833,6 @@ void tst_QGraphicsWidget::defaultSize() #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&view); #endif - QTest::qWait(50); QSizeF initialSize = widget->size(); widget->resize(initialSize); @@ -1867,9 +1842,8 @@ void tst_QGraphicsWidget::defaultSize() widget->setPreferredSize(60, 60); widget->setMaximumSize(110, 110); widget->setVisible(true); - QTest::qWait(50); // should still have its size set to initialsize - QCOMPARE(widget->geometry().size(), initialSize); + QTRY_COMPARE(widget->geometry().size(), initialSize); } @@ -2391,7 +2365,6 @@ void tst_QGraphicsWidget::painterStateProtectionOnWindowFrame() scene.addItem(widget); view.show(); QTest::qWaitForWindowShown(&view); - QTest::qWait(500); } class ProxyStyle : public QCommonStyle @@ -2480,7 +2453,6 @@ void tst_QGraphicsWidget::task250119_shortcutContext() view.setScene(&scene); view.show(); QApplication::setActiveWindow(&view); - QTest::qWait(25); QTRY_COMPARE(QApplication::activeWindow(), &view); @@ -2735,9 +2707,7 @@ void tst_QGraphicsWidget::respectHFW() QTest::qWaitForWindowShown(view); { // here we go - simulate a interactive resize of the window - QTest::qWait(100); QTest::mouseMove(view, view->mapFromScene(71, 71)); // bottom right corner - QTest::qWait(100); QTest::mousePress(view->viewport(), Qt::LeftButton, 0, view->mapFromScene(71, 71), 200); view->grabMouse(); @@ -2751,10 +2721,9 @@ void tst_QGraphicsWidget::respectHFW() QApplication::sendEvent(view->viewport(), &e); view->releaseMouse(); } - QTest::qWait(100); const QSizeF winSize = window->size(); qreal minHFW = window->effectiveSizeHint(Qt::MinimumSize, QSizeF(winSize.width(), -1)).height(); - QVERIFY(qAbs(minHFW - winSize.height()) < 1); + QTRY_VERIFY(qAbs(minHFW - winSize.height()) < 1); #endif } @@ -2806,7 +2775,7 @@ void tst_QGraphicsWidget::addChildInpolishEvent() view.resize(200, 200); view.show(); QTest::qWaitForWindowShown(&view); - QCOMPARE(PolishWidget::numberOfPolish, 2); + QTRY_COMPARE(PolishWidget::numberOfPolish, 2); } void tst_QGraphicsWidget::polishEvent() @@ -2853,10 +2822,8 @@ void tst_QGraphicsWidget::polishEvent2() widget->events.clear(); - QApplication::processEvents(); - // Make sure the item got polish event. - QVERIFY(widget->events.contains(QEvent::Polish)); + QTRY_VERIFY(widget->events.contains(QEvent::Polish)); } void tst_QGraphicsWidget::autoFillBackground() @@ -2902,11 +2869,9 @@ void tst_QGraphicsWidget::initialShow() view.show(); QTest::qWaitForWindowShown(&view); - QTest::qWait(100); scene.addItem(widget); - QTest::qWait(100); - QCOMPARE(widget->repaints, 1); + QTRY_COMPARE(widget->repaints, 1); } void tst_QGraphicsWidget::initialShow2() @@ -2935,7 +2900,6 @@ void tst_QGraphicsWidget::initialShow2() const int expectedRepaintCount = paintSpy.count(); delete dummyView; dummyView = 0; - QTest::qWait(200); MyGraphicsWidget *widget = new MyGraphicsWidget; widget->resize(100, 100); @@ -2948,7 +2912,7 @@ void tst_QGraphicsWidget::initialShow2() view.show(); QTest::qWaitForWindowShown(&view); - QCOMPARE(widget->repaints, expectedRepaintCount); + QTRY_COMPARE(widget->repaints, expectedRepaintCount); } void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems() diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp index 6ef4305..3b2a716 100644 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -93,6 +93,7 @@ private slots: void task232634_childrenDeselectionSignal(); void task260134_layoutChangedWithAllSelected(); void QTBUG5671_layoutChangedWithAllSelected(); + void QTBUG2804_layoutChangedTreeSelection(); private: QAbstractItemModel *model; @@ -2327,5 +2328,31 @@ void tst_QItemSelectionModel::QTBUG5671_layoutChangedWithAllSelected() QVERIFY(selection.isSelected(index)); } +void tst_QItemSelectionModel::QTBUG2804_layoutChangedTreeSelection() +{ + QStandardItemModel model; + QStandardItem top1("Child1"), top2("Child2"), top3("Child3"); + QStandardItem sub11("Alpha"), sub12("Beta"), sub13("Gamma"), sub14("Delta"), + sub21("Alpha"), sub22("Beta"), sub23("Gamma"), sub24("Delta"); + top1.appendColumn(QList<QStandardItem*>() << &sub11 << &sub12 << &sub13 << &sub14); + top2.appendColumn(QList<QStandardItem*>() << &sub21 << &sub22 << &sub23 << &sub24); + model.appendColumn(QList<QStandardItem*>() << &top1 << &top2 << &top3); + + QItemSelectionModel selModel(&model); + + selModel.select(sub11.index(), QItemSelectionModel::Select); + selModel.select(sub12.index(), QItemSelectionModel::Select); + selModel.select(sub21.index(), QItemSelectionModel::Select); + selModel.select(sub23.index(), QItemSelectionModel::Select); + + QModelIndexList list = selModel.selectedIndexes(); + QCOMPARE(list.count(), 4); + + model.sort(0); //this will provoke a relayout + + QCOMPARE(selModel.selectedIndexes().count(), 4); +} + + QTEST_MAIN(tst_QItemSelectionModel) #include "tst_qitemselectionmodel.moc" diff --git a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp index e11900e..4922a89 100644 --- a/tests/auto/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/qnetworkreply/tst_qnetworkreply.cpp @@ -205,6 +205,10 @@ private Q_SLOTS: #endif void ioGetFromHttpBrokenServer_data(); void ioGetFromHttpBrokenServer(); + void ioGetFromHttpStatus100_data(); + void ioGetFromHttpStatus100(); + void ioGetFromHttpNoHeaders_data(); + void ioGetFromHttpNoHeaders(); void ioGetFromHttpWithCache_data(); void ioGetFromHttpWithCache(); @@ -2159,6 +2163,60 @@ void tst_QNetworkReply::ioGetFromHttpBrokenServer() QVERIFY(reply->error() != QNetworkReply::NoError); } +void tst_QNetworkReply::ioGetFromHttpStatus100_data() +{ + QTest::addColumn<QByteArray>("dataToSend"); + QTest::newRow("normal") << QByteArray("HTTP/1.1 100 Continue\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + QTest::newRow("minimal") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + QTest::newRow("minimal2") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\r\n\r\n"); + QTest::newRow("minimal3") << QByteArray("HTTP/1.1 100 Continue\n\nHTTP/1.0 200 OK\n\n"); + QTest::newRow("with_headers") << QByteArray("HTTP/1.1 100 Continue\r\nBla: x\r\n\r\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); + QTest::newRow("with_headers2") << QByteArray("HTTP/1.1 100 Continue\nBla: x\n\nHTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"); +} + +void tst_QNetworkReply::ioGetFromHttpStatus100() +{ + QFETCH(QByteArray, dataToSend); + MiniHttpServer server(dataToSend); + server.doClose = true; + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->url(), request.url()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); + QVERIFY(reply->rawHeader("bla").isNull()); +} + +void tst_QNetworkReply::ioGetFromHttpNoHeaders_data() +{ + QTest::addColumn<QByteArray>("dataToSend"); + QTest::newRow("justStatus+noheaders+disconnect") << QByteArray("HTTP/1.0 200 OK\r\n\r\n"); +} + +void tst_QNetworkReply::ioGetFromHttpNoHeaders() +{ + QFETCH(QByteArray, dataToSend); + MiniHttpServer server(dataToSend); + server.doClose = true; + + QNetworkRequest request(QUrl("http://localhost:" + QString::number(server.serverPort()))); + QNetworkReplyPtr reply = manager.get(request); + + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(10); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(reply->url(), request.url()); + QCOMPARE(reply->error(), QNetworkReply::NoError); + QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 200); +} + void tst_QNetworkReply::ioGetFromHttpWithCache_data() { qRegisterMetaType<MyMemoryCache::CachedContent>(); diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 0161a68..8da3484 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -128,6 +128,7 @@ private slots: void isSignalConnected(); void qMetaObjectConnect(); void qMetaObjectDisconnectOne(); + void sameName(); protected: }; @@ -162,7 +163,7 @@ class SenderObject : public QObject Q_OBJECT public: - SenderObject() : recursionCount(0) {} + SenderObject() : aPublicSlotCalled(0), recursionCount(0) {} void emitSignal1AfterRecursion() { @@ -185,11 +186,12 @@ signals: QT_MOC_COMPAT void signal5(); public slots: - void aPublicSlot(){} + void aPublicSlot() { aPublicSlotCalled++; } public: Q_INVOKABLE void invoke1(){} Q_SCRIPTABLE void sinvoke1(){} + int aPublicSlotCalled; protected: Q_INVOKABLE QT_MOC_COMPAT void invoke2(){} Q_INVOKABLE QT_MOC_COMPAT void invoke2(int){} @@ -429,12 +431,14 @@ public: public slots: void on_Sender_signalNoParams() { ++called_slot1; } - void on_Sender_signalWithParams(int i = 0) { ++called_slot2; } - void on_Sender_signalWithParams(int i, QString string) { ++called_slot3; } + void on_Sender_signalWithParams(int i = 0) { ++called_slot2; Q_UNUSED(i); } + void on_Sender_signalWithParams(int i, QString string) { ++called_slot3; Q_UNUSED(i);Q_UNUSED(string); } void on_Sender_signalManyParams() { ++called_slot4; } - void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot5; } - void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) { ++called_slot6; } - void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot7; } + void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) { ++called_slot5; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); } + void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) + { ++called_slot6; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); Q_UNUSED(dummy);} + void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff) + { ++called_slot7; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); } void slotLoopBack() { ++called_slot8; } protected slots: @@ -2090,21 +2094,21 @@ public slots: void constUintPointerSlot(const uint *) { } void constUlongPointerSlot(const ulong *) { } - void structSlot(Struct s) { } - void classSlot(Class c) { } - void enumSlot(Enum e) { } + void structSlot(Struct s) { Q_UNUSED(s); } + void classSlot(Class c) { Q_UNUSED(c); } + void enumSlot(Enum e) { Q_UNUSED(e); } - void structPointerSlot(Struct *s) { } - void classPointerSlot(Class *c) { } - void enumPointerSlot(Enum *e) { } + void structPointerSlot(Struct *s) { Q_UNUSED(s); } + void classPointerSlot(Class *c) { Q_UNUSED(c); } + void enumPointerSlot(Enum *e) { Q_UNUSED(e); } - void constStructPointerSlot(const Struct *s) { } - void constClassPointerSlot(const Class *c) { } - void constEnumPointerSlot(const Enum *e) { } + void constStructPointerSlot(const Struct *s) { Q_UNUSED(s); } + void constClassPointerSlot(const Class *c) { Q_UNUSED(c); } + void constEnumPointerSlot(const Enum *e) { Q_UNUSED(e); } - void constStructPointerConstPointerSlot(const Struct * const *s) { } - void constClassPointerConstPointerSlot(const Class * const *c) { } - void constEnumPointerConstPointerSlot(const Enum * const *e) { } + void constStructPointerConstPointerSlot(const Struct * const *s) { Q_UNUSED(s); } + void constClassPointerConstPointerSlot(const Class * const *c) { Q_UNUSED(c); } + void constEnumPointerConstPointerSlot(const Enum * const *e) { Q_UNUSED(e); } void uintSlot(uint) {}; void unsignedintSlot(unsigned int) {}; @@ -3550,5 +3554,41 @@ void tst_QObject::qMetaObjectDisconnectOne() delete r1; } +class ConfusingObject : public SenderObject +{ Q_OBJECT +public slots: + void signal1() { s++; } +signals: + void aPublicSlot(); +public: + int s; + ConfusingObject() : s(0) {} + friend class tst_QObject; +}; + +void tst_QObject::sameName() +{ + ConfusingObject c1, c2; + QVERIFY(connect(&c1, SIGNAL(signal1()), &c1, SLOT(signal1()))); + c1.emitSignal1(); + QCOMPARE(c1.s, 1); + + QVERIFY(connect(&c2, SIGNAL(signal1()), &c1, SIGNAL(signal1()))); + c2.emitSignal1(); + QCOMPARE(c1.s, 2); + + QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(signal1()))); + c2.aPublicSlot(); + QCOMPARE(c2.aPublicSlotCalled, 0); + QCOMPARE(c1.aPublicSlotCalled, 0); + QCOMPARE(c1.s, 3); + + QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(aPublicSlot()))); + c2.aPublicSlot(); + QCOMPARE(c2.aPublicSlotCalled, 0); + QCOMPARE(c1.aPublicSlotCalled, 1); + QCOMPARE(c1.s, 4); +} + QTEST_MAIN(tst_QObject) #include "tst_qobject.moc" diff --git a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp index fb0f3e0..d2d86fb 100644 --- a/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp +++ b/tests/auto/qparallelanimationgroup/tst_qparallelanimationgroup.cpp @@ -75,6 +75,8 @@ private slots: void loopCount(); void autoAdd(); void pauseResume(); + + void QTBUG8910_crashWhenRemovingUncontrolledAnimation(); }; tst_QParallelAnimationGroup::tst_QParallelAnimationGroup() @@ -999,9 +1001,22 @@ void tst_QParallelAnimationGroup::pauseResume() QCOMPARE(spy.count(), 2); //this shouldn't have changed group.resume(); QCOMPARE(spy.count(), 2); //this shouldn't have changed +} - +void tst_QParallelAnimationGroup::QTBUG8910_crashWhenRemovingUncontrolledAnimation() +{ + QParallelAnimationGroup group; + TestAnimation *anim = new TestAnimation; + anim->setLoopCount(-1); + TestAnimation *anim2 = new TestAnimation; + anim2->setLoopCount(-1); + group.addAnimation(anim); + group.addAnimation(anim2); + group.start(); + delete anim; + // it would crash here because the internals of the group would still have a reference to anim + delete anim2; } diff --git a/tests/auto/qscriptclass/tst_qscriptclass.cpp b/tests/auto/qscriptclass/tst_qscriptclass.cpp index aca33ce..b4dbe73 100644 --- a/tests/auto/qscriptclass/tst_qscriptclass.cpp +++ b/tests/auto/qscriptclass/tst_qscriptclass.cpp @@ -98,7 +98,12 @@ public: NotCallable, CallableReturnsSum, CallableReturnsArgument, - CallableReturnsInvalidVariant + CallableReturnsInvalidVariant, + CallableReturnsGlobalObject, + CallableReturnsThisObject, + CallableReturnsCallee, + CallableReturnsArgumentsObject, + CallableInitializesThisObject }; TestClass(QScriptEngine *engine); @@ -348,7 +353,7 @@ QVariant TestClass::extension(Extension extension, qsreal sum = 0; for (int i = 0; i < ctx->argumentCount(); ++i) sum += ctx->argument(i).toNumber(); - QScriptValueIterator it(ctx->thisObject()); + QScriptValueIterator it(ctx->callee()); while (it.hasNext()) { it.next(); sum += it.value().toNumber(); @@ -358,6 +363,17 @@ QVariant TestClass::extension(Extension extension, return qVariantFromValue(ctx->argument(0)); } else if (m_callableMode == CallableReturnsInvalidVariant) { return QVariant(); + } else if (m_callableMode == CallableReturnsGlobalObject) { + return qVariantFromValue(engine()->globalObject()); + } else if (m_callableMode == CallableReturnsThisObject) { + return qVariantFromValue(ctx->thisObject()); + } else if (m_callableMode == CallableReturnsCallee) { + return qVariantFromValue(ctx->callee()); + } else if (m_callableMode == CallableReturnsArgumentsObject) { + return qVariantFromValue(ctx->argumentsObject()); + } else if (m_callableMode == CallableInitializesThisObject) { + engine()->newQObject(ctx->thisObject(), engine()); + return QVariant(); } } else if (extension == HasInstance) { Q_ASSERT(m_hasInstance); @@ -797,9 +813,11 @@ void tst_QScriptClass::extension() QVERIFY(cls.supportsExtension(QScriptClass::Callable)); QScriptValue obj = eng.newObject(&cls); + eng.globalObject().setProperty("obj", obj); obj.setProperty("one", QScriptValue(&eng, 1)); obj.setProperty("two", QScriptValue(&eng, 2)); obj.setProperty("three", QScriptValue(&eng, 3)); + // From C++ cls.clearReceivedArgs(); { QScriptValueList args; @@ -810,8 +828,18 @@ void tst_QScriptClass::extension() QVERIFY(ret.isNumber()); QCOMPARE(ret.toNumber(), qsreal(15)); } + // From JS + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("obj(4, 5)"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toNumber(), qsreal(15)); + } cls.setCallableMode(TestClass::CallableReturnsArgument); + // From C++ cls.clearReceivedArgs(); { QScriptValue ret = obj.call(obj, QScriptValueList() << 123); @@ -843,6 +871,13 @@ void tst_QScriptClass::extension() QScriptValue ret = obj.call(obj, QScriptValueList() << QScriptValue()); QVERIFY(ret.isUndefined()); } + // From JS + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("obj(123)"); + QVERIFY(ret.isNumber()); + QCOMPARE(ret.toInt32(), 123); + } cls.setCallableMode(TestClass::CallableReturnsInvalidVariant); { @@ -850,13 +885,92 @@ void tst_QScriptClass::extension() QVERIFY(ret.isUndefined()); } + cls.setCallableMode(TestClass::CallableReturnsThisObject); + // From C++ + { + QScriptValue ret = obj.call(obj); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(obj)); + } + // From JS + { + QScriptValue ret = eng.evaluate("obj()"); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(eng.globalObject())); + } + + cls.setCallableMode(TestClass::CallableReturnsCallee); + // From C++ + { + QScriptValue ret = obj.call(); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(obj)); + } + // From JS + { + QScriptValue ret = eng.evaluate("obj()"); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(obj)); + } + + cls.setCallableMode(TestClass::CallableReturnsArgumentsObject); + // From C++ + { + QScriptValue ret = obj.call(obj, QScriptValueList() << 123); + QVERIFY(ret.isObject()); + QVERIFY(ret.property("length").isNumber()); + QCOMPARE(ret.property("length").toInt32(), 1); + QVERIFY(ret.property(0).isNumber()); + QCOMPARE(ret.property(0).toInt32(), 123); + } + // From JS + { + QScriptValue ret = eng.evaluate("obj(123)"); + QVERIFY(ret.isObject()); + QVERIFY(ret.property("length").isNumber()); + QCOMPARE(ret.property("length").toInt32(), 1); + QVERIFY(ret.property(0).isNumber()); + QCOMPARE(ret.property(0).toInt32(), 123); + } + // construct() + // From C++ cls.clearReceivedArgs(); + cls.setCallableMode(TestClass::CallableReturnsGlobalObject); { QScriptValue ret = obj.construct(); QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(eng.globalObject())); + } + // From JS + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("new obj()"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isObject()); + QVERIFY(ret.strictlyEquals(eng.globalObject())); + } + // From C++ + cls.clearReceivedArgs(); + cls.setCallableMode(TestClass::CallableInitializesThisObject); + { + QScriptValue ret = obj.construct(); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isQObject()); + QCOMPARE(ret.toQObject(), (QObject*)&eng); + } + // From JS + cls.clearReceivedArgs(); + { + QScriptValue ret = eng.evaluate("new obj()"); + QCOMPARE(cls.lastExtensionType(), QScriptClass::Callable); + QCOMPARE(cls.lastExtensionArgument().userType(), qMetaTypeId<QScriptContext*>()); + QVERIFY(ret.isQObject()); + QCOMPARE(ret.toQObject(), (QObject*)&eng); } } // HasInstance diff --git a/tests/auto/qscriptengine/tst_qscriptengine.cpp b/tests/auto/qscriptengine/tst_qscriptengine.cpp index d9beb45..e71d7c3 100644 --- a/tests/auto/qscriptengine/tst_qscriptengine.cpp +++ b/tests/auto/qscriptengine/tst_qscriptengine.cpp @@ -150,6 +150,7 @@ private slots: void getSetAgent(); void reentrancy(); void incDecNonObjectProperty(); + void installTranslatorFunctions_data(); void installTranslatorFunctions(); void functionScopes(); void nativeFunctionScopes(); @@ -4119,22 +4120,46 @@ void tst_QScriptEngine:: incDecNonObjectProperty() } } +void tst_QScriptEngine::installTranslatorFunctions_data() +{ + QTest::addColumn<bool>("useCustomGlobalObject"); + + QTest::newRow("Default global object") << false; + QTest::newRow("Custom global object") << true; +} + void tst_QScriptEngine::installTranslatorFunctions() { + QFETCH(bool, useCustomGlobalObject); + QScriptEngine eng; - QScriptValue global = eng.globalObject(); + QScriptValue globalOrig = eng.globalObject(); + QScriptValue global; + if (useCustomGlobalObject) { + global = eng.newObject(); + eng.setGlobalObject(global); + } else { + global = globalOrig; + } QVERIFY(!global.property("qsTranslate").isValid()); QVERIFY(!global.property("QT_TRANSLATE_NOOP").isValid()); QVERIFY(!global.property("qsTr").isValid()); QVERIFY(!global.property("QT_TR_NOOP").isValid()); - QVERIFY(!global.property("String").property("prototype").property("arg").isValid()); + QVERIFY(!globalOrig.property("String").property("prototype").property("arg").isValid()); eng.installTranslatorFunctions(); QVERIFY(global.property("qsTranslate").isFunction()); QVERIFY(global.property("QT_TRANSLATE_NOOP").isFunction()); QVERIFY(global.property("qsTr").isFunction()); QVERIFY(global.property("QT_TR_NOOP").isFunction()); - QVERIFY(global.property("String").property("prototype").property("arg").isFunction()); + QVERIFY(globalOrig.property("String").property("prototype").property("arg").isFunction()); + + if (useCustomGlobalObject) { + QVERIFY(!globalOrig.property("qsTranslate").isValid()); + QVERIFY(!globalOrig.property("QT_TRANSLATE_NOOP").isValid()); + QVERIFY(!globalOrig.property("qsTr").isValid()); + QVERIFY(!globalOrig.property("QT_TR_NOOP").isValid()); + } { QScriptValue ret = eng.evaluate("qsTr('foo')"); diff --git a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp index 5b79340..dc369aa 100644 --- a/tests/auto/qscriptvalue/tst_qscriptvalue.cpp +++ b/tests/auto/qscriptvalue/tst_qscriptvalue.cpp @@ -2573,6 +2573,10 @@ void tst_QScriptValue::call() // call with something else as arguments QScriptValue ret5 = fun.call(QScriptValue(), QScriptValue(&eng, 123.0)); QCOMPARE(ret5.isError(), true); + // call with a non-array object as arguments + QScriptValue ret6 = fun.call(QScriptValue(), eng.globalObject()); + QVERIFY(ret6.isError()); + QCOMPARE(ret6.toString(), QString::fromLatin1("TypeError: Arguments must be an array")); } // calling things that are not functions @@ -2705,6 +2709,10 @@ void tst_QScriptValue::construct() // construct with something else as arguments QScriptValue ret5 = fun.construct(QScriptValue(&eng, 123.0)); QCOMPARE(ret5.isError(), true); + // construct with a non-array object as arguments + QScriptValue ret6 = fun.construct(eng.globalObject()); + QVERIFY(ret6.isError()); + QCOMPARE(ret6.toString(), QString::fromLatin1("TypeError: Arguments must be an array")); } // construct on things that are not functions diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 8a47991..0aca545 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -973,6 +973,10 @@ void Configure::parseCmdLine() if(i==argCount) break; dictionary[ "QT_LIBINFIX" ] = configCmdLine.at(i); + if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) { + dictionary[ "QT_INSTALL_PLUGINS" ] = + QString("\\resource\\qt%1\\plugins").arg(dictionary[ "QT_LIBINFIX" ]); + } } else if( configCmdLine.at(i) == "-D" ) { ++i; if (i==argCount) @@ -3063,6 +3067,8 @@ void Configure::generateConfigfiles() qconfigList += "QT_NO_CRASHHANDLER"; qconfigList += "QT_NO_PRINTER"; qconfigList += "QT_NO_SYSTEMTRAYICON"; + if (dictionary.contains("QT_LIBINFIX")) + tmpStream << QString("#define QT_LIBINFIX \"%1\"").arg(dictionary["QT_LIBINFIX"]) << endl; } qconfigList.sort(); diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp index af08777..80e5e34 100644 --- a/tools/runonphone/main.cpp +++ b/tools/runonphone/main.cpp @@ -44,6 +44,7 @@ #include <QStringList> #include <QScopedPointer> #include <QTimer> +#include <QFileInfo> #include "symbianutils/trkutils.h" #include "symbianutils/trkdevice.h" #include "symbianutils/launcher.h" @@ -51,9 +52,9 @@ #include "trksignalhandler.h" #include "serenum.h" -void printUsage(QTextStream& outstream) +void printUsage(QTextStream& outstream, QString exeName) { - outstream << "runtest [options] <program> [program arguments]" << endl + outstream << exeName << " [options] [program] [program arguments]" << endl << "-s, --sis <file> specify sis file to install" << endl << "-p, --portname <COMx> specify COM port to use by device name" << endl << "-f, --portfriendlyname <substring> specify COM port to use by friendly name" << endl @@ -61,7 +62,9 @@ void printUsage(QTextStream& outstream) << "-v, --verbose show debugging output" << endl << "-q, --quiet hide progress messages" << endl << endl - << "USB COM ports can usually be autodetected" << endl; + << "USB COM ports can usually be autodetected, use -p or -f to force a specific port." << endl + << "If using System TRK, it is possible to copy the program directly to sys/bin on the phone." << endl + << "-s can be used with both System and Application TRK to install the program" << endl; } int main(int argc, char *argv[]) @@ -86,22 +89,22 @@ int main(int argc, char *argv[]) return 1; } QString param = args.at(i+1); - if(arg.compare("--portname", Qt::CaseSensitive) == 0 + if (arg.compare("--portname", Qt::CaseSensitive) == 0 || arg.compare("-p", Qt::CaseSensitive) == 0) { serialPortName = param; i++; } - else if(arg.compare("--portfriendlyname", Qt::CaseSensitive) == 0 + else if (arg.compare("--portfriendlyname", Qt::CaseSensitive) == 0 || arg.compare("-f", Qt::CaseSensitive) == 0) { serialPortFriendlyName = param; i++; } - else if(arg.compare("--sis", Qt::CaseSensitive) == 0 + else if (arg.compare("--sis", Qt::CaseSensitive) == 0 || arg.compare("-s", Qt::CaseSensitive) == 0) { sisFile = param; i++; } - else if(arg.compare("--timeout", Qt::CaseSensitive) == 0 + else if (arg.compare("--timeout", Qt::CaseSensitive) == 0 || arg.compare("-t", Qt::CaseSensitive) == 0) { bool ok; timeout = param.toInt(&ok); @@ -111,10 +114,10 @@ int main(int argc, char *argv[]) } i++; } - else if(arg.compare("--verbose", Qt::CaseSensitive) == 0 + else if (arg.compare("--verbose", Qt::CaseSensitive) == 0 || arg.compare("-v", Qt::CaseSensitive) == 0) loglevel=2; - else if(arg.compare("--quiet", Qt::CaseSensitive) == 0 + else if (arg.compare("--quiet", Qt::CaseSensitive) == 0 || arg.compare("-q", Qt::CaseSensitive) == 0) loglevel=0; else @@ -128,8 +131,8 @@ int main(int argc, char *argv[]) } } - if(exeFile.isEmpty()) { - printUsage(outstream); + if (exeFile.isEmpty() && sisFile.isEmpty()) { + printUsage(outstream, args[0]); return 1; } @@ -161,24 +164,26 @@ int main(int argc, char *argv[]) } QScopedPointer<trk::Launcher> launcher; - - if (sisFile.isEmpty()) { - launcher.reset(new trk::Launcher(trk::Launcher::ActionCopyRun)); - launcher->setCopyFileName(exeFile, QString("c:\\sys\\bin\\") + exeFile); - errstream << "System TRK required to copy EXE, use --sis if using Application TRK" << endl; - } else { - launcher.reset(new trk::Launcher(trk::Launcher::ActionCopyInstallRun)); - launcher->addStartupActions(trk::Launcher::ActionInstall); + launcher.reset(new trk::Launcher(trk::Launcher::ActionPingOnly)); + QFileInfo info(exeFile); + if (!sisFile.isEmpty()) { + launcher->addStartupActions(trk::Launcher::ActionCopyInstall); launcher->setCopyFileName(sisFile, "c:\\data\\testtemp.sis"); launcher->setInstallFileName("c:\\data\\testtemp.sis"); } + else if (info.exists()) { + launcher->addStartupActions(trk::Launcher::ActionCopy); + launcher->setCopyFileName(exeFile, QString("c:\\sys\\bin\\") + info.fileName()); + } + if (!exeFile.isEmpty()) { + launcher->addStartupActions(trk::Launcher::ActionRun); + launcher->setFileName(QString("c:\\sys\\bin\\") + info.fileName()); + launcher->setCommandLineArgs(cmdLine); + } if (loglevel > 0) outstream << "Connecting to target via " << serialPortName << endl; launcher->setTrkServerName(serialPortName); - launcher->setFileName(QString("c:\\sys\\bin\\") + exeFile); - launcher->setCommandLineArgs(cmdLine); - if (loglevel > 1) launcher->setVerbose(1); diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp index 408829b..92b494a 100644 --- a/tools/runonphone/symbianutils/launcher.cpp +++ b/tools/runonphone/symbianutils/launcher.cpp @@ -44,6 +44,7 @@ #include "trkutils_p.h" #include "trkdevice.h" #include "bluetoothlistener.h" +#include "symbiandevicemanager.h" #include <QtCore/QTimer> #include <QtCore/QDateTime> @@ -100,12 +101,15 @@ Launcher::Launcher(Actions startupActions, d(new LauncherPrivate(dev)) { d->m_startupActions = startupActions; - connect(d->m_device.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult))); - connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close())); + connect(d->m_device.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult))); } Launcher::~Launcher() { + // Destroyed before protocol was through: Close + if (d->m_closeDevice && d->m_device->isOpen()) + d->m_device->close(); + emit destroyed(d->m_device->port()); logMessage("Shutting down.\n"); delete d; } @@ -214,11 +218,6 @@ bool Launcher::startServer(QString *errorMessage) } if (!d->m_device->isOpen() && !d->m_device->open(errorMessage)) return false; - if (d->m_closeDevice) { - connect(this, SIGNAL(finished()), d->m_device.data(), SLOT(close())); - } else { - disconnect(this, SIGNAL(finished()), d->m_device.data(), 0); - } setState(Connecting); // Set up the temporary 'waiting' state if we do not get immediate connection QTimer::singleShot(1000, this, SLOT(slotWaitingForTrk())); @@ -266,6 +265,13 @@ void Launcher::logMessage(const QString &msg) qDebug() << "LAUNCHER: " << qPrintable(msg); } +void Launcher::handleFinished() +{ + if (d->m_closeDevice) + d->m_device->close(); + emit finished(); +} + void Launcher::terminate() { switch (state()) { @@ -287,7 +293,7 @@ void Launcher::terminate() case Connecting: case WaitingForTrk: setState(Disconnected); - emit finished(); + handleFinished(); break; } } @@ -446,7 +452,7 @@ void Launcher::handleTrkVersion(const TrkResult &result) if (result.errorCode() || result.data.size() < 5) { if (d->m_startupActions == ActionPingOnly) { setState(Disconnected); - emit finished(); + handleFinished(); } return; } @@ -455,11 +461,13 @@ void Launcher::handleTrkVersion(const TrkResult &result) d->m_session.trkAppVersion.protocolMajor = result.data.at(3); d->m_session.trkAppVersion.protocolMinor = result.data.at(4); setState(DeviceDescriptionReceived); + const QString msg = deviceDescription(); + emit deviceDescriptionReceived(trkServerName(), msg); // Ping mode: Log & Terminate if (d->m_startupActions == ActionPingOnly) { - qWarning("%s", qPrintable(deviceDescription())); + qWarning("%s", qPrintable(msg)); setState(Disconnected); - emit finished(); + handleFinished(); } } @@ -586,7 +594,7 @@ void Launcher::handleWaitForFinished(const TrkResult &result) { logMessage(" FINISHED: " + stringFromArray(result.data)); setState(Disconnected); - emit finished(); + handleFinished(); } void Launcher::handleSupportMask(const TrkResult &result) @@ -704,18 +712,14 @@ QByteArray Launcher::startProcessMessage(const QString &executable, { // It's not started yet QByteArray ba; - appendShort(&ba, 0, TargetByteOrder); // create new process + appendShort(&ba, 0, TargetByteOrder); // create new process (kDSOSProcessItem) ba.append(char(0)); // options - currently unused - if(arguments.isEmpty()) { - appendString(&ba, executable.toLocal8Bit(), TargetByteOrder); - return ba; - } - // Append full command line as one string (leading length information). - QByteArray commandLineBa; - commandLineBa.append(executable.toLocal8Bit()); - commandLineBa.append('\0'); - commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit()); - appendString(&ba, commandLineBa, TargetByteOrder); + // One string consisting of binary terminated by '\0' and arguments terminated by '\0' + QByteArray commandLineBa = executable.toLocal8Bit(); + commandLineBa.append(char(0)); + if (!arguments.isEmpty()) + commandLineBa.append(arguments.join(QString(QLatin1Char(' '))).toLocal8Bit()); + appendString(&ba, commandLineBa, TargetByteOrder, true); return ba; } @@ -737,4 +741,37 @@ void Launcher::resumeProcess(uint pid, uint tid) appendInt(&ba, tid, BigEndian); d->m_device->sendTrkMessage(TrkContinue, TrkCallback(), ba, "CONTINUE"); } + +// Acquire a device from SymbianDeviceManager, return 0 if not available. +Launcher *Launcher::acquireFromDeviceManager(const QString &serverName, + QObject *parent, + QString *errorMessage) +{ + SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); + const QSharedPointer<trk::TrkDevice> device = sdm->acquireDevice(serverName); + if (device.isNull()) { + *errorMessage = tr("Unable to acquire a device for port '%1'. It appears to be in use.").arg(serverName); + return 0; + } + // Wire release signal. + Launcher *rc = new Launcher(trk::Launcher::ActionPingOnly, device, parent); + connect(rc, SIGNAL(deviceDescriptionReceived(QString,QString)), + sdm, SLOT(setAdditionalInformation(QString,QString))); + connect(rc, SIGNAL(destroyed(QString)), sdm, SLOT(releaseDevice(QString))); + return rc; +} + +// Preliminary release of device, disconnecting the signal. +void Launcher::releaseToDeviceManager(Launcher *launcher) +{ + SymbianUtils::SymbianDeviceManager *sdm = SymbianUtils::SymbianDeviceManager::instance(); + // Disentangle launcher and its device, remove connection from destroyed + launcher->setCloseDevice(false); + TrkDevice *device = launcher->trkDevice().data(); + launcher->disconnect(device); + device->disconnect(launcher); + launcher->disconnect(sdm); + sdm->releaseDevice(launcher->trkServerName()); +} + } // namespace trk diff --git a/tools/runonphone/symbianutils/launcher.h b/tools/runonphone/symbianutils/launcher.h index 2b23fd8..c47285c 100644 --- a/tools/runonphone/symbianutils/launcher.h +++ b/tools/runonphone/symbianutils/launcher.h @@ -97,7 +97,7 @@ public: void setInstallFileName(const QString &name); void setCommandLineArgs(const QStringList &args); bool startServer(QString *errorMessage); - void setVerbose(int v); + void setVerbose(int v); void setSerialFrame(bool b); bool serialFrame() const; // Close device or leave it open @@ -109,6 +109,15 @@ public: // becomes valid after successful execution of ActionPingOnly QString deviceDescription(unsigned verbose = 0u) const; + // Acquire a device from SymbianDeviceManager, return 0 if not available. + // The device will be released on destruction. + static Launcher *acquireFromDeviceManager(const QString &serverName, + QObject *parent, + QString *errorMessage); + // Preliminary release of device, disconnecting the signal. + static void releaseToDeviceManager(Launcher *l); + + // Create Trk message to start a process. static QByteArray startProcessMessage(const QString &executable, const QStringList &arguments); // Parse a TrkNotifyStopped message @@ -119,6 +128,7 @@ public: static QString msgStopped(uint pid, uint tid, uint address, const QString &why); signals: + void deviceDescriptionReceived(const QString &port, const QString &description); void copyingStarted(); void canNotConnect(const QString &errorMessage); void canNotCreateFile(const QString &filename, const QString &errorMessage); @@ -135,6 +145,8 @@ signals: void copyProgress(int percent); void stateChanged(int); void processStopped(uint pc, uint pid, uint tid, const QString& reason); + // Emitted by the destructor, for releasing devices of SymbianDeviceManager by name + void destroyed(const QString &serverName); public slots: void terminate(); @@ -167,6 +179,7 @@ private: void copyFileToRemote(); void installRemotePackageSilently(); void startInferiorIfNeeded(); + void handleFinished(); void logMessage(const QString &msg); void setState(State s); diff --git a/tools/runonphone/symbianutils/symbiandevicemanager.cpp b/tools/runonphone/symbianutils/symbiandevicemanager.cpp index f663816..8877ea1 100644 --- a/tools/runonphone/symbianutils/symbiandevicemanager.cpp +++ b/tools/runonphone/symbianutils/symbiandevicemanager.cpp @@ -40,6 +40,7 @@ ****************************************************************************/ #include "symbiandevicemanager.h" +#include "trkdevice.h" #include <QtCore/QSettings> #include <QtCore/QStringList> @@ -48,6 +49,7 @@ #include <QtCore/QTextStream> #include <QtCore/QSharedData> #include <QtCore/QScopedPointer> +#include <QtCore/QSignalMapper> namespace SymbianUtils { @@ -61,19 +63,51 @@ const char *SymbianDeviceManager::linuxBlueToothDeviceRootC = "/dev/rfcomm"; // ------------- SymbianDevice class SymbianDeviceData : public QSharedData { public: - SymbianDeviceData() : type(SerialPortCommunication) {} + SymbianDeviceData(); + ~SymbianDeviceData(); + + inline bool isOpen() const { return !device.isNull() && device->isOpen(); } + void forcedClose(); QString portName; QString friendlyName; QString deviceDesc; QString manufacturer; + QString additionalInformation; + DeviceCommunicationType type; + QSharedPointer<trk::TrkDevice> device; + bool deviceAcquired; }; +SymbianDeviceData::SymbianDeviceData() : + type(SerialPortCommunication), + deviceAcquired(false) +{ +} + +SymbianDeviceData::~SymbianDeviceData() +{ + forcedClose(); +} + +void SymbianDeviceData::forcedClose() +{ + // Close the device when unplugging. Should devices be in 'acquired' state, + // their owners should hit on write failures. + // Apart from the <shared item> destructor, also called by the devicemanager + // to ensure it also happens if other shared instances are still around. + if (isOpen()) { + if (deviceAcquired) + qWarning("Device on '%s' unplugged while an operation is in progress.", + qPrintable(portName)); + device->close(); + } +} + SymbianDevice::SymbianDevice(SymbianDeviceData *data) : m_data(data) { - } SymbianDevice::SymbianDevice() : @@ -96,6 +130,11 @@ SymbianDevice::~SymbianDevice() { } +void SymbianDevice::forcedClose() +{ + m_data->forcedClose(); +} + QString SymbianDevice::portName() const { return m_data->portName; @@ -106,6 +145,51 @@ QString SymbianDevice::friendlyName() const return m_data->friendlyName; } +QString SymbianDevice::additionalInformation() const +{ + return m_data->additionalInformation; +} + +void SymbianDevice::setAdditionalInformation(const QString &a) +{ + m_data->additionalInformation = a; +} + +SymbianDevice::TrkDevicePtr SymbianDevice::acquireDevice() +{ + if (debug) + qDebug() << "SymbianDevice::acquireDevice" << m_data->portName + << "acquired: " << m_data->deviceAcquired << " open: " << isOpen(); + if (isNull() || m_data->deviceAcquired) + return TrkDevicePtr(); + if (m_data->device.isNull()) { + m_data->device = TrkDevicePtr(new trk::TrkDevice); + m_data->device->setPort(m_data->portName); + m_data->device->setSerialFrame(m_data->type == SerialPortCommunication); + } + m_data->deviceAcquired = true; + return m_data->device; +} + +void SymbianDevice::releaseDevice(TrkDevicePtr *ptr /* = 0 */) +{ + if (debug) + qDebug() << "SymbianDevice::releaseDevice" << m_data->portName + << " open: " << isOpen(); + if (m_data->deviceAcquired) { + if (m_data->device->isOpen()) + m_data->device->clearWriteQueue(); + // Release if a valid pointer was passed in. + if (ptr && !ptr->isNull()) { + ptr->data()->disconnect(); + *ptr = TrkDevicePtr(); + } + m_data->deviceAcquired = false; + } else { + qWarning("Internal error: Attempt to release device that is not acquired."); + } +} + QString SymbianDevice::deviceDesc() const { return m_data->deviceDesc; @@ -123,7 +207,12 @@ DeviceCommunicationType SymbianDevice::type() const bool SymbianDevice::isNull() const { - return !m_data->portName.isEmpty(); + return m_data->portName.isEmpty(); +} + +bool SymbianDevice::isOpen() const +{ + return m_data->isOpen(); } QString SymbianDevice::toString() const @@ -158,7 +247,7 @@ int SymbianDevice::compare(const SymbianDevice &rhs) const return 0; } -QDebug operator<<(QDebug d, const SymbianDevice &cd) +SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &cd) { d.nospace() << cd.toString(); return d; @@ -166,10 +255,11 @@ QDebug operator<<(QDebug d, const SymbianDevice &cd) // ------------- SymbianDeviceManagerPrivate struct SymbianDeviceManagerPrivate { - SymbianDeviceManagerPrivate() : m_initialized(false) {} + SymbianDeviceManagerPrivate() : m_initialized(false), m_destroyReleaseMapper(0) {} bool m_initialized; SymbianDeviceManager::SymbianDeviceList m_devices; + QSignalMapper *m_destroyReleaseMapper; }; SymbianDeviceManager::SymbianDeviceManager(QObject *parent) : @@ -185,8 +275,7 @@ SymbianDeviceManager::~SymbianDeviceManager() SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::devices() const { - if (!d->m_initialized) - const_cast<SymbianDeviceManager*>(this)->update(false); + ensureInitialized(); return d->m_devices; } @@ -194,6 +283,7 @@ QString SymbianDeviceManager::toString() const { QString rc; QTextStream str(&rc); + str << d->m_devices.size() << " devices:\n"; const int count = d->m_devices.size(); for (int i = 0; i < count; i++) { str << '#' << i << ' '; @@ -203,13 +293,37 @@ QString SymbianDeviceManager::toString() const return rc; } +int SymbianDeviceManager::findByPortName(const QString &p) const +{ + ensureInitialized(); + const int count = d->m_devices.size(); + for (int i = 0; i < count; i++) + if (d->m_devices.at(i).portName() == p) + return i; + return -1; +} + QString SymbianDeviceManager::friendlyNameForPort(const QString &port) const { - foreach (const SymbianDevice &device, d->m_devices) { - if (device.portName() == port) - return device.friendlyName(); - } - return QString(); + const int idx = findByPortName(port); + return idx == -1 ? QString() : d->m_devices.at(idx).friendlyName(); +} + +SymbianDeviceManager::TrkDevicePtr + SymbianDeviceManager::acquireDevice(const QString &port) +{ + ensureInitialized(); + const int idx = findByPortName(port); + if (idx == -1) { + qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port)); + if (debug) + qDebug() << *this; + return TrkDevicePtr(); + } + const TrkDevicePtr rc = d->m_devices[idx].acquireDevice(); + if (debug) + qDebug() << "SymbianDeviceManager::acquireDevice" << port << " returns " << !rc.isNull(); + return rc; } void SymbianDeviceManager::update() @@ -217,12 +331,38 @@ void SymbianDeviceManager::update() update(true); } +void SymbianDeviceManager::releaseDevice(const QString &port) +{ + const int idx = findByPortName(port); + if (debug) + qDebug() << "SymbianDeviceManager::releaseDevice" << port << idx << sender(); + if (idx != -1) { + d->m_devices[idx].releaseDevice(); + } else { + qWarning("Attempt to release non-existing device %s.", qPrintable(port)); + } +} + +void SymbianDeviceManager::setAdditionalInformation(const QString &port, const QString &ai) +{ + const int idx = findByPortName(port); + if (idx != -1) + d->m_devices[idx].setAdditionalInformation(ai); +} + +void SymbianDeviceManager::ensureInitialized() const +{ + if (!d->m_initialized) // Flag is set in update() + const_cast<SymbianDeviceManager*>(this)->update(false); +} + void SymbianDeviceManager::update(bool emitSignals) { + static int n = 0; typedef SymbianDeviceList::iterator SymbianDeviceListIterator; if (debug) - qDebug(">SerialDeviceLister::update(%d)\n%s", int(emitSignals), + qDebug(">SerialDeviceLister::update(#%d, signals=%d)\n%s", n++, int(emitSignals), qPrintable(toString())); d->m_initialized = true; @@ -230,8 +370,11 @@ void SymbianDeviceManager::update(bool emitSignals) SymbianDeviceList newDevices = serialPorts() + blueToothDevices(); if (newDevices.size() > 1) qStableSort(newDevices.begin(), newDevices.end()); - if (d->m_devices == newDevices) // Happy, nothing changed. + if (d->m_devices == newDevices) { // Happy, nothing changed. + if (debug) + qDebug("<SerialDeviceLister::update: unchanged\n"); return; + } // Merge the lists and emit the respective added/removed signals, assuming // no one can plug a different device on the same port at the speed of lightning if (!d->m_devices.isEmpty()) { @@ -240,7 +383,8 @@ void SymbianDeviceManager::update(bool emitSignals) if (newDevices.contains(*oldIt)) { ++oldIt; } else { - const SymbianDevice toBeDeleted = *oldIt; + SymbianDevice toBeDeleted = *oldIt; + toBeDeleted.forcedClose(); oldIt = d->m_devices.erase(oldIt); if (emitSignals) emit deviceRemoved(toBeDeleted); @@ -301,16 +445,30 @@ SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::blueToothDevices() // Bluetooth devices are created on connection. List the existing ones // or at least the first one. const QString prefix = QLatin1String(linuxBlueToothDeviceRootC); - const QString friendlyFormat = QLatin1String("Bluetooth device (%1)"); + const QString blueToothfriendlyFormat = QLatin1String("Bluetooth device (%1)"); for (int d = 0; d < 4; d++) { QScopedPointer<SymbianDeviceData> device(new SymbianDeviceData); device->type = BlueToothCommunication; device->portName = prefix + QString::number(d); if (d == 0 || QFileInfo(device->portName).exists()) { - device->friendlyName = friendlyFormat.arg(device->portName); + device->friendlyName = blueToothfriendlyFormat.arg(device->portName); rc.push_back(SymbianDevice(device.take())); } } + // New kernel versions support /dev/ttyUSB0, /dev/ttyUSB1. Trk responds + // on the latter (usually), try first. + static const char *usbTtyDevices[] = { "/dev/ttyUSB1", "/dev/ttyUSB0" }; + const int usbTtyCount = sizeof(usbTtyDevices)/sizeof(const char *); + for (int d = 0; d < usbTtyCount; d++) { + const QString ttyUSBDevice = QLatin1String(usbTtyDevices[d]); + if (QFileInfo(ttyUSBDevice).exists()) { + SymbianDeviceData *device = new SymbianDeviceData; + device->type = SerialPortCommunication; + device->portName = ttyUSBDevice; + device->friendlyName = QString::fromLatin1("USB/Serial device (%1)").arg(device->portName); + rc.push_back(SymbianDevice(device)); + } + } #endif return rc; } @@ -322,7 +480,7 @@ SymbianDeviceManager *SymbianDeviceManager::instance() return symbianDeviceManager(); } -QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm) +SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm) { d.nospace() << sdm.toString(); return d; diff --git a/tools/runonphone/symbianutils/symbiandevicemanager.h b/tools/runonphone/symbianutils/symbiandevicemanager.h index dcf131a..180173d 100644 --- a/tools/runonphone/symbianutils/symbiandevicemanager.h +++ b/tools/runonphone/symbianutils/symbiandevicemanager.h @@ -46,12 +46,17 @@ #include <QtCore/QObject> #include <QtCore/QExplicitlySharedDataPointer> +#include <QtCore/QSharedPointer> QT_BEGIN_NAMESPACE class QDebug; class QTextStream; QT_END_NAMESPACE +namespace trk { + class TrkDevice; +} + namespace SymbianUtils { struct SymbianDeviceManagerPrivate; @@ -62,11 +67,16 @@ enum DeviceCommunicationType { BlueToothCommunication = 1 }; -// SymbianDevice, explicitly shared. +// SymbianDevice: Explicitly shared device data and a TrkDevice +// instance that can be acquired (exclusively) for use. +// A device removal from the manager will result in the +// device being closed. class SYMBIANUTILS_EXPORT SymbianDevice { explicit SymbianDevice(SymbianDeviceData *data); friend class SymbianDeviceManager; public: + typedef QSharedPointer<trk::TrkDevice> TrkDevicePtr; + SymbianDevice(); SymbianDevice(const SymbianDevice &rhs); SymbianDevice &operator=(const SymbianDevice &rhs); @@ -77,6 +87,17 @@ public: bool isNull() const; QString portName() const; QString friendlyName() const; + QString additionalInformation() const; + void setAdditionalInformation(const QString &); + + // Acquire: Mark the device as 'out' and return a shared pointer + // unless it is already in use by another owner. The result should not + // be passed on further. + TrkDevicePtr acquireDevice(); + // Give back a device and mark it as 'free'. + void releaseDevice(TrkDevicePtr *ptr = 0); + + bool isOpen() const; // Windows only. QString deviceDesc() const; @@ -86,10 +107,12 @@ public: QString toString() const; private: + void forcedClose(); + QExplicitlySharedDataPointer<SymbianDeviceData> m_data; }; -QDebug operator<<(QDebug d, const SymbianDevice &); +SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &); inline bool operator==(const SymbianDevice &d1, const SymbianDevice &d2) { return d1.compare(d2) == 0; } @@ -100,13 +123,15 @@ inline bool operator<(const SymbianDevice &d1, const SymbianDevice &d2) /* SymbianDeviceManager: Singleton that maintains a list of Symbian devices. * and emits change signals. - * On Windows, the update slot must be connected to a signal - * emitted from an event handler listening for WM_DEVICECHANGE. */ + * On Windows, the update slot must be connected to a [delayed] signal + * emitted from an event handler listening for WM_DEVICECHANGE. + * Device removal will result in the device being closed. */ class SYMBIANUTILS_EXPORT SymbianDeviceManager : public QObject { Q_OBJECT public: typedef QList<SymbianDevice> SymbianDeviceList; + typedef QSharedPointer<trk::TrkDevice> TrkDevicePtr; static const char *linuxBlueToothDeviceRootC; @@ -120,17 +145,25 @@ public: SymbianDeviceList devices() const; QString toString() const; + // Acquire a device for use. See releaseDevice(). + TrkDevicePtr acquireDevice(const QString &port); + + int findByPortName(const QString &p) const; QString friendlyNameForPort(const QString &port) const; public slots: void update(); + // Relase a device, make it available for further use. + void releaseDevice(const QString &port); + void setAdditionalInformation(const QString &port, const QString &ai); signals: - void deviceRemoved(const SymbianDevice &d); - void deviceAdded(const SymbianDevice &d); + void deviceRemoved(const SymbianUtils::SymbianDevice &d); + void deviceAdded(const SymbianUtils::SymbianDevice &d); void updated(); private: + void ensureInitialized() const; void update(bool emitSignals); SymbianDeviceList serialPorts() const; SymbianDeviceList blueToothDevices() const; @@ -138,7 +171,7 @@ private: SymbianDeviceManagerPrivate *d; }; -QDebug operator<<(QDebug d, const SymbianDeviceManager &); +SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &); } // namespace SymbianUtils diff --git a/tools/runonphone/symbianutils/trkdevice.cpp b/tools/runonphone/symbianutils/trkdevice.cpp index b327ab3..bd24300 100644 --- a/tools/runonphone/symbianutils/trkdevice.cpp +++ b/tools/runonphone/symbianutils/trkdevice.cpp @@ -52,6 +52,7 @@ #include <QtCore/QMutex> #include <QtCore/QWaitCondition> #include <QtCore/QSharedPointer> +#include <QtCore/QScopedPointer> #include <QtCore/QMetaType> #ifdef Q_OS_WIN @@ -102,6 +103,11 @@ QString winErrorMessage(unsigned long error) enum { verboseTrk = 0 }; +static inline QString msgAccessingClosedDevice(const QString &msg) +{ + return QString::fromLatin1("Error: Attempt to access device '%1', which is closed.").arg(msg); +} + namespace trk { /////////////////////////////////////////////////////////////////////// @@ -155,10 +161,11 @@ namespace trk { /////////////////////////////////////////////////////////////////////// class TrkWriteQueue -{ +{ Q_DISABLE_COPY(TrkWriteQueue) public: explicit TrkWriteQueue(); + void clear(); // Enqueue messages. void queueTrkMessage(byte code, TrkCallback callback, @@ -208,13 +215,24 @@ TrkWriteQueue::TrkWriteQueue() : { } +void TrkWriteQueue::clear() +{ + m_trkWriteToken = 0; + m_trkWriteBusy = false; + m_trkWriteQueue.clear(); + const int discarded = m_writtenTrkMessages.size(); + m_writtenTrkMessages.clear(); + if (verboseTrk) + qDebug() << "TrkWriteQueue::clear: discarded " << discarded; +} + byte TrkWriteQueue::nextTrkWriteToken() { ++m_trkWriteToken; if (m_trkWriteToken == 0) ++m_trkWriteToken; if (verboseTrk) - qDebug() << "Write token: " << m_trkWriteToken; + qDebug() << "nextTrkWriteToken:" << m_trkWriteToken; return m_trkWriteToken; } @@ -349,7 +367,7 @@ class WriterThread : public QThread { Q_OBJECT Q_DISABLE_COPY(WriterThread) -public: +public: explicit WriterThread(const QSharedPointer<DeviceContext> &context); // Enqueue messages. @@ -357,6 +375,8 @@ public: const QByteArray &data, const QVariant &cookie); void queueTrkInitialPing(); + void clearWriteQueue(); + // Call this from the device read notification with the results. void slotHandleResult(const TrkResult &result); @@ -374,7 +394,7 @@ public slots: private slots: void invokeNoopMessage(const trk::TrkMessage &); -private: +private: bool write(const QByteArray &data, QString *errorMessage); inline int writePendingMessage(); @@ -462,6 +482,7 @@ void WriterThread::terminate() m_waitCondition.wakeAll(); wait(); m_terminate = false; + m_queue.clear(); } #ifdef Q_OS_WIN @@ -561,6 +582,13 @@ void WriterThread::queueTrkMessage(byte code, TrkCallback callback, tryWrite(); } +void WriterThread::clearWriteQueue() +{ + m_dataMutex.lock(); + m_queue.clear(); + m_dataMutex.unlock(); +} + void WriterThread::queueTrkInitialPing() { m_dataMutex.lock(); @@ -592,6 +620,8 @@ class ReaderThreadBase : public QThread Q_DISABLE_COPY(ReaderThreadBase) public: + int bytesPending() const { return m_trkReadBuffer.size(); } + signals: void messageReceived(const trk::TrkResult &result, const QByteArray &rawData); @@ -692,7 +722,7 @@ int WinReaderThread::tryRead() if (!ClearCommError(m_context->device, NULL, &comStat)){ emit error(QString::fromLatin1("ClearCommError failed: %1").arg(winErrorMessage(GetLastError()))); return -7; - } + } const DWORD bytesToRead = qMax(DWORD(1), qMin(comStat.cbInQue, DWORD(BufSize))); // Trigger read DWORD bytesRead = 0; @@ -708,7 +738,7 @@ int WinReaderThread::tryRead() if (readError != ERROR_IO_PENDING) { emit error(QString::fromLatin1("Read error: %1").arg(winErrorMessage(readError))); return -1; - } + } // Wait for either termination or data const DWORD wr = WaitForMultipleObjects(HandleCount, m_handles, false, INFINITE); if (wr == WAIT_FAILED) { @@ -783,7 +813,7 @@ private: int m_terminatePipeFileDescriptors[2]; }; -UnixReaderThread::UnixReaderThread(const QSharedPointer<DeviceContext> &context) : +UnixReaderThread::UnixReaderThread(const QSharedPointer<DeviceContext> &context) : ReaderThreadBase(context) { m_terminatePipeFileDescriptors[0] = m_terminatePipeFileDescriptors[1] = -1; @@ -877,8 +907,8 @@ struct TrkDevicePrivate TrkDevicePrivate(); QSharedPointer<DeviceContext> deviceContext; - QSharedPointer<WriterThread> writerThread; - QSharedPointer<ReaderThread> readerThread; + QScopedPointer<WriterThread> writerThread; + QScopedPointer<ReaderThread> readerThread; QByteArray trkReadBuffer; int verbose; @@ -917,14 +947,14 @@ TrkDevice::~TrkDevice() bool TrkDevice::open(QString *errorMessage) { - if (d->verbose) + if (d->verbose || verboseTrk) qDebug() << "Opening" << port() << "is open: " << isOpen() << " serialFrame=" << serialFrame(); + if (isOpen()) + return true; if (d->port.isEmpty()) { *errorMessage = QLatin1String("Internal error: No port set on TrkDevice"); return false; } - - close(); #ifdef Q_OS_WIN const QString fullPort = QLatin1String("\\\\.\\") + d->port; d->deviceContext->device = CreateFile(reinterpret_cast<const WCHAR*>(fullPort.utf16()), @@ -975,7 +1005,7 @@ bool TrkDevice::open(QString *errorMessage) return false; } #endif - d->readerThread = QSharedPointer<ReaderThread>(new ReaderThread(d->deviceContext)); + d->readerThread.reset(new ReaderThread(d->deviceContext)); connect(d->readerThread.data(), SIGNAL(error(QString)), this, SLOT(emitError(QString)), Qt::QueuedConnection); connect(d->readerThread.data(), SIGNAL(messageReceived(trk::TrkResult,QByteArray)), @@ -983,18 +1013,22 @@ bool TrkDevice::open(QString *errorMessage) Qt::QueuedConnection); d->readerThread->start(); - d->writerThread = QSharedPointer<WriterThread>(new WriterThread(d->deviceContext)); + d->writerThread.reset(new WriterThread(d->deviceContext)); connect(d->writerThread.data(), SIGNAL(error(QString)), this, SLOT(emitError(QString)), - Qt::QueuedConnection); - d->writerThread->start(); + Qt::QueuedConnection); + d->writerThread->start(); - if (d->verbose) - qDebug() << "Opened" << d->port; + if (d->verbose || verboseTrk) + qDebug() << "Opened" << d->port << d->readerThread.data() << d->writerThread.data(); return true; } void TrkDevice::close() { + if (verboseTrk) + qDebug() << "close" << d->port << " is open: " << isOpen() + << " read pending " << (d->readerThread.isNull() ? 0 : d->readerThread->bytesPending()) + << sender(); if (!isOpen()) return; if (d->readerThread) @@ -1010,6 +1044,7 @@ void TrkDevice::close() #else d->deviceContext->file.close(); #endif + if (d->verbose) emitLogMessage("Close"); } @@ -1030,6 +1065,8 @@ QString TrkDevice::port() const void TrkDevice::setPort(const QString &p) { + if (verboseTrk) + qDebug() << "setPort" << p; d->port = p; } @@ -1045,6 +1082,8 @@ bool TrkDevice::serialFrame() const void TrkDevice::setSerialFrame(bool f) { + if (verboseTrk) + qDebug() << "setSerialFrame" << f; d->deviceContext->serialFrame = f; } @@ -1060,12 +1099,14 @@ void TrkDevice::setVerbose(int b) void TrkDevice::slotMessageReceived(const trk::TrkResult &result, const QByteArray &rawData) { - d->writerThread->slotHandleResult(result); - if (d->verbose > 1) - qDebug() << "Received: " << result.toString(); - emit messageReceived(result); - if (!rawData.isEmpty()) - emit rawDataReceived(rawData); + if (isOpen()) { // Might receive bytes after closing due to queued connections. + d->writerThread->slotHandleResult(result); + if (d->verbose > 1) + qDebug() << "Received: " << result.toString(); + emit messageReceived(result); + if (!rawData.isEmpty()) + emit rawDataReceived(rawData); + } } void TrkDevice::emitError(const QString &s) @@ -1075,15 +1116,27 @@ void TrkDevice::emitError(const QString &s) emit error(s); } +void TrkDevice::clearWriteQueue() +{ + if (isOpen()) + d->writerThread->clearWriteQueue(); +} + void TrkDevice::sendTrkMessage(byte code, TrkCallback callback, const QByteArray &data, const QVariant &cookie) { + if (!isOpen()) { + emitError(msgAccessingClosedDevice(d->port)); + return; + } if (!d->writerThread.isNull()) { if (d->verbose > 1) { - QByteArray msg = "Sending: "; + QByteArray msg = "Sending: 0x"; msg += QByteArray::number(code, 16); msg += ": "; msg += stringFromArray(data).toLatin1(); + if (cookie.isValid()) + msg += " Cookie: " + cookie.toString().toLatin1(); qDebug("%s", msg.data()); } d->writerThread->queueTrkMessage(code, callback, data, cookie); @@ -1092,12 +1145,20 @@ void TrkDevice::sendTrkMessage(byte code, TrkCallback callback, void TrkDevice::sendTrkInitialPing() { + if (!isOpen()) { + emitError(msgAccessingClosedDevice(d->port)); + return; + } if (!d->writerThread.isNull()) d->writerThread->queueTrkInitialPing(); } bool TrkDevice::sendTrkAck(byte token) { + if (!isOpen()) { + emitError(msgAccessingClosedDevice(d->port)); + return false; + } if (d->writerThread.isNull()) return false; // The acknowledgement must not be queued! diff --git a/tools/runonphone/symbianutils/trkdevice.h b/tools/runonphone/symbianutils/trkdevice.h index 78012fd..1021a7d 100644 --- a/tools/runonphone/symbianutils/trkdevice.h +++ b/tools/runonphone/symbianutils/trkdevice.h @@ -64,12 +64,14 @@ struct TrkDevicePrivate; * Trk communications. Provides synchronous write and asynchronous * read operation. * The serialFrames property specifies whether packets are encapsulated in - * "0x90 <length>" frames, which is currently the case for serial ports. + * "0x90 <length>" frames, which is currently the case for serial ports. * Contains a write message queue allowing * for queueing messages with a notification callback. If the message receives * an ACK, the callback is invoked. - * The special message TRK_WRITE_QUEUE_NOOP_CODE code can be used for synchronisation. - * The respective message will not be sent, the callback is just invoked. */ + * The special message TRK_WRITE_QUEUE_NOOP_CODE code can be used for synchronization. + * The respective message will not be sent, the callback is just invoked. + * Note that calling open/close in quick succession can cause crashes + * due to the use of queused signals. */ enum { TRK_WRITE_QUEUE_NOOP_CODE = 0x7f }; @@ -111,6 +113,9 @@ public: // Send an Ack synchronously, bypassing the queue bool sendTrkAck(unsigned char token); +public slots: + void clearWriteQueue(); + signals: void messageReceived(const trk::TrkResult &result); // Emitted with the contents of messages enclosed in 07e, not for log output diff --git a/tools/runonphone/trksignalhandler.cpp b/tools/runonphone/trksignalhandler.cpp index 9fe2035..2abf91f 100644 --- a/tools/runonphone/trksignalhandler.cpp +++ b/tools/runonphone/trksignalhandler.cpp @@ -54,6 +54,7 @@ private: QTextStream out; QTextStream err; int loglevel; + int lastpercent; }; void TrkSignalHandler::copyingStarted() @@ -125,13 +126,18 @@ void TrkSignalHandler::finished() void TrkSignalHandler::applicationOutputReceived(const QString &output) { - d->out << output; + d->out << output << flush; } void TrkSignalHandler::copyProgress(int percent) { if (d->loglevel > 0) { - d->out << percent << "% "; + if (d->lastpercent == 0) + d->out << "[ ]\r[" << flush; + while (percent > d->lastpercent) { + d->out << QLatin1Char('#'); + d->lastpercent+=2; //because typical console is 80 chars wide + } d->out.flush(); if (percent==100) d->out << endl; @@ -167,7 +173,8 @@ void TrkSignalHandler::timeout() TrkSignalHandlerPrivate::TrkSignalHandlerPrivate() : out(stdout), err(stderr), - loglevel(0) + loglevel(0), + lastpercent(0) { } |