diff options
96 files changed, 1623 insertions, 1051 deletions
diff --git a/dist/changes-4.6.0 b/dist/changes-4.6.0 index eaacdae..24d8fc0 100644 --- a/dist/changes-4.6.0 +++ b/dist/changes-4.6.0 @@ -630,6 +630,40 @@ Qt Plugins * [258526] Rotate the image if the tiff file contains an orientation tag. * [254317] Add support for mono and indexed format + - QPlainTextEdit + * Fixed crash when clicking on a text edit which was smaller than the + height of the font used. + + - QPrinter + * [QTBUG-4497] Removed redundant SetPen command in the postscript code + when reusing a QPrinter object. + + - QTextLayout + * [QTBUG-4468] Count tabs as multiple characters when applying a fixed + column width. + * [176401] Take into account the negative right bearing of the last + character in an item of text if the glyph extends beyond its ascent. + + - QTextDocument + * [207189] Support setting font size using short hand syntax in the + CSS "font" property. + * [201228] Remove implicit margin on bullet lists when exporting to + HTML. + * [240086] Fixed bug which caused floating objects which span several + pages to float into the second page of the document even when it's + the only existing object, causing the document to contain a blank + first page. + * [240325] Even when wrap mode is set to Qt::TextWordWrap, the layout + would sometimes break outside word boundaries when floating objects + affected the width available to the text. This has been fixed. + + - QFontEngine + * [QTBUG-2354] Support certain 'Microsoft' platform symbol fonts which + also contain a regular unicode table for exactly the symbol range of + code points. + + - QFontMetrics + * [176401] Account for right bearing in bounding rect. **************************************************************************** * Platform Specific Changes * @@ -817,6 +851,19 @@ Qt for Embedded Linux - Compilation fixes for OpenGL/ES 1.0 and OpenGL/ES 1.1 Common Lite. + - Phonon on Windows + * Now much more reliable when reading a file through a QIODevice. + * If Video Mixing Renderer 9 is not available, falls back to software + rendering. + * Fixed a flicker issue when switching source with a transition time of 0 + + - [QTBUG-3620] Fixed bug on X11 that caused bitmap fonts to become so small + it was unreadable when printed or presented in a print preview widget. + + - [QTBUG-4445] Fixed bug on Windows that caused problems when printing + text where several characters were represented by a single glyph, e.g. + a double 't' with the Calibri font. + - EGL and OpenGL/ES * Protect the use of version-specific EGL symbols with #ifdef's. * Make sure an EGL context is current when resolving GL extensions. diff --git a/examples/effects/lighting/lighting.cpp b/examples/effects/lighting/lighting.cpp index 7026b66..51fa9f8 100644 --- a/examples/effects/lighting/lighting.cpp +++ b/examples/effects/lighting/lighting.cpp @@ -94,7 +94,7 @@ void Lighting::setupScene() else item = new QGraphicsRectItem(0, 0, 50, 50); - item->setPen(QPen(Qt::black)); + item->setPen(QPen(Qt::black, 1)); item->setBrush(QBrush(Qt::white)); QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; effect->setBlurRadius(8); diff --git a/examples/graphicsview/anchorlayout/main.cpp b/examples/graphicsview/anchorlayout/main.cpp index 3e19f18..f898d1d 100644 --- a/examples/graphicsview/anchorlayout/main.cpp +++ b/examples/graphicsview/anchorlayout/main.cpp @@ -76,8 +76,8 @@ int main(int argc, char **argv) QGraphicsProxyWidget *c = createItem(minSize, prefSize, maxSize, "C"); QGraphicsProxyWidget *d = createItem(minSize, prefSize, maxSize, "D"); QGraphicsProxyWidget *e = createItem(minSize, prefSize, maxSize, "E"); - QGraphicsProxyWidget *f = createItem(QSizeF(30, 50), QSizeF(150, 50), maxSize, "F"); - QGraphicsProxyWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G"); + QGraphicsProxyWidget *f = createItem(QSizeF(30, 50), QSizeF(150, 50), maxSize, "F (overflow)"); + QGraphicsProxyWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G (overflow)"); QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setSpacing(0); diff --git a/examples/graphicsview/weatheranchorlayout/main.cpp b/examples/graphicsview/weatheranchorlayout/main.cpp index 9002828..d835ae3 100644 --- a/examples/graphicsview/weatheranchorlayout/main.cpp +++ b/examples/graphicsview/weatheranchorlayout/main.cpp @@ -185,20 +185,12 @@ int main(int argc, char **argv) QGraphicsScene scene; scene.setSceneRect(0, 0, 800, 480); -#ifdef DEBUG_MODE - QGraphicsProxyWidget *title = createItem("Title"); - QGraphicsProxyWidget *place = createItem("Place"); - QGraphicsProxyWidget *sun = createItem("Sun"); - QGraphicsProxyWidget *details = createItem("Details"); - QGraphicsProxyWidget *tabbar = createItem("Tabbar"); -#else - // pixmaps widgets - PixmapWidget *title = new PixmapWidget(QPixmap(":/images/title.jpg")); - PlaceWidget *place = new PlaceWidget(QPixmap(":/images/place.jpg")); - PixmapWidget *details = new PixmapWidget(QPixmap(":/images/5days.jpg")); - PixmapWidget *sun = new PixmapWidget(QPixmap(":/images/weather-few-clouds.png")); - PixmapWidget *tabbar = new PixmapWidget(QPixmap(":/images/tabbar.jpg")); -#endif + // pixmaps widgets + PixmapWidget *title = new PixmapWidget(QPixmap(":/images/title.jpg")); + PlaceWidget *place = new PlaceWidget(QPixmap(":/images/place.jpg")); + PixmapWidget *details = new PixmapWidget(QPixmap(":/images/5days.jpg")); + PixmapWidget *sunnyWeather = new PixmapWidget(QPixmap(":/images/weather-few-clouds.png")); + PixmapWidget *tabbar = new PixmapWidget(QPixmap(":/images/tabbar.jpg")); // setup sizes @@ -215,9 +207,9 @@ int main(int argc, char **argv) tabbar->setPreferredSize(QSizeF(70, 24)); tabbar->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - sun->setPreferredSize(QSizeF(128, 97)); - sun->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); - sun->setZValue(9999); + sunnyWeather->setPreferredSize(QSizeF(128, 97)); + sunnyWeather->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + sunnyWeather->setZValue(9999); // start anchor layout QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; @@ -238,8 +230,8 @@ int main(int argc, char **argv) anchor = l->addAnchor(place, Qt::AnchorBottom, l, Qt::AnchorBottom); anchor->setSpacing(12); - anchor = l->addAnchor(sun, Qt::AnchorTop, title, Qt::AnchorTop); - anchor = l->addAnchor(sun, Qt::AnchorBottom, l, Qt::AnchorVerticalCenter); + anchor = l->addAnchor(sunnyWeather, Qt::AnchorTop, title, Qt::AnchorTop); + anchor = l->addAnchor(sunnyWeather, Qt::AnchorBottom, l, Qt::AnchorVerticalCenter); anchor = l->addAnchor(tabbar, Qt::AnchorTop, title, Qt::AnchorBottom); anchor->setSpacing(5); @@ -257,8 +249,8 @@ int main(int argc, char **argv) anchor = l->addAnchor(place, Qt::AnchorRight, details, Qt::AnchorLeft); anchor->setSpacing(35); - anchor = l->addAnchor(sun, Qt::AnchorLeft, place, Qt::AnchorHorizontalCenter); - anchor = l->addAnchor(sun, Qt::AnchorRight, l, Qt::AnchorHorizontalCenter); + anchor = l->addAnchor(sunnyWeather, Qt::AnchorLeft, place, Qt::AnchorHorizontalCenter); + anchor = l->addAnchor(sunnyWeather, Qt::AnchorRight, l, Qt::AnchorHorizontalCenter); anchor = l->addAnchor(tabbar, Qt::AnchorHorizontalCenter, details, Qt::AnchorHorizontalCenter); anchor = l->addAnchor(details, Qt::AnchorRight, l, Qt::AnchorRight); diff --git a/examples/opengl/pbuffers/glwidget.cpp b/examples/opengl/pbuffers/glwidget.cpp index 56ba65b..d843a73 100644 --- a/examples/opengl/pbuffers/glwidget.cpp +++ b/examples/opengl/pbuffers/glwidget.cpp @@ -175,7 +175,11 @@ void GLWidget::perspectiveProjection() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); +#ifdef QT_OPENGL_ES + glFrustumf(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0); +#else glFrustum(-aspect, +aspect, -1.0, +1.0, 4.0, 15.0); +#endif glMatrixMode(GL_MODELVIEW); } @@ -183,7 +187,11 @@ void GLWidget::orthographicProjection() { glMatrixMode(GL_PROJECTION); glLoadIdentity(); +#ifdef QT_OPENGL_ES + glOrthof(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0); +#else glOrtho(-1.0, +1.0, -1.0, +1.0, -90.0, +90.0); +#endif glMatrixMode(GL_MODELVIEW); } diff --git a/mkspecs/symbian-sbsv2/flm/qt/qmake_generate_temp_dirs.flm b/mkspecs/symbian-sbsv2/flm/qt/qmake_generate_temp_dirs.flm deleted file mode 100644 index ca6cca9..0000000 --- a/mkspecs/symbian-sbsv2/flm/qt/qmake_generate_temp_dirs.flm +++ /dev/null @@ -1,22 +0,0 @@ -# /**************************************************************************** -# ** -# ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -# ** Contact: Nokia Corporation (qt-info@nokia.com) -# ** -# ** This file is part of symbian-sbsv2 mkspec. -# ** -# ****************************************************************************/ - -include $(FLMHOME)/metaflm.mk - -SINGLETON:=$(call sanitise,TEMP_DIRS_$(EXTENSION_ROOT)) - -ifeq ($($(SINGLETON)),) -$(SINGLETON):=1 -$(call makepath,$(DIRS)) -$(eval $(call GenerateStandardCleanTarget,'',$(DIRS))) -endif - - - - diff --git a/mkspecs/symbian-sbsv2/flm/qt/qt.xml b/mkspecs/symbian-sbsv2/flm/qt/qt.xml index 5074e47..c99b5e2 100644 --- a/mkspecs/symbian-sbsv2/flm/qt/qt.xml +++ b/mkspecs/symbian-sbsv2/flm/qt/qt.xml @@ -35,11 +35,6 @@ <param name='LINK_TARGET' /> </interface> - <interface name="qt.qmake_generate_temp_dirs" extends="Symbian.UserFLM" - flm="qmake_generate_temp_dirs.flm"> - <param name='DIRS' /> - </interface> - <interface name="qt.qmake_store_build" extends="Symbian.UserFLM" flm="qmake_store_build.flm"> </interface> diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp index 8ec4b3f..1326a49 100644 --- a/qmake/generators/symbian/symmake.cpp +++ b/qmake/generators/symbian/symmake.cpp @@ -610,19 +610,10 @@ void SymbianMakefileGenerator::initMmpVariables() incpaths << project->values("UI_HEADERS_DIR"); incpaths << project->values("UI_DIR"); - QString epocPath("epoc32"); for (int j = 0; j < incpaths.size(); ++j) { QString includepath = canonizePath(incpaths.at(j)); appendIfnotExist(sysincspaths, includepath); - // As a workaround for Symbian toolchain insistence to treat include - // statements as relative to source file rather than the file they appear in, - // we generate extra temporary include directories to make - // relative include paths used in various headers to work properly. - // Note that this is not a fix-all solution; it's just a stop-gap measure - // to make Qt itself build until toolchain can support relative includes in - // a way that Qt expects. - if (!includepath.contains(epocPath)) // No temp dirs for epoc includes - appendIfnotExist(sysincspaths, includepath + QString("/" QT_EXTRA_INCLUDE_DIR)); + appendAbldTempDirs(sysincspaths, includepath); } // Remove duplicate include path entries diff --git a/qmake/generators/symbian/symmake.h b/qmake/generators/symbian/symmake.h index 36f6e05..a3e2c17 100644 --- a/qmake/generators/symbian/symmake.h +++ b/qmake/generators/symbian/symmake.h @@ -147,6 +147,7 @@ protected: virtual void writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension) = 0; virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly) = 0; virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile) = 0; + virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath) = 0; public: diff --git a/qmake/generators/symbian/symmake_abld.cpp b/qmake/generators/symbian/symmake_abld.cpp index 4d1673b..1b5464f 100644 --- a/qmake/generators/symbian/symmake_abld.cpp +++ b/qmake/generators/symbian/symmake_abld.cpp @@ -450,3 +450,17 @@ void SymbianAbldMakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool ad t << "gnumakefile " << gnuMakefileName << endl; } } + +void SymbianAbldMakefileGenerator::appendAbldTempDirs(QStringList& sysincspaths, QString includepath) +{ + // As a workaround for Symbian toolchain insistence to treat include + // statements as relative to source file rather than the file they appear in, + // we generate extra temporary include directories to make + // relative include paths used in various headers to work properly. + // Note that this is not a fix-all solution; it's just a stop-gap measure + // to make Qt itself build until toolchain can support relative includes in + // a way that Qt expects. + QString epocPath("epoc32"); + if (!includepath.contains(epocPath)) // No temp dirs for epoc includes + appendIfnotExist(sysincspaths, includepath + QString("/" QT_EXTRA_INCLUDE_DIR)); +} diff --git a/qmake/generators/symbian/symmake_abld.h b/qmake/generators/symbian/symmake_abld.h index f844096..11b9cd1 100644 --- a/qmake/generators/symbian/symmake_abld.h +++ b/qmake/generators/symbian/symmake_abld.h @@ -55,6 +55,7 @@ protected: virtual void writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension); virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly); virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile); + virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath); void writeStoreBuildTarget(QTextStream &t); bool writeDeploymentTargets(QTextStream &t); diff --git a/qmake/generators/symbian/symmake_sbsv2.cpp b/qmake/generators/symbian/symmake_sbsv2.cpp index cad2736..5e624de 100644 --- a/qmake/generators/symbian/symmake_sbsv2.cpp +++ b/qmake/generators/symbian/symmake_sbsv2.cpp @@ -182,15 +182,22 @@ void SymbianSbsv2MakefileGenerator::writeWrapperMakefile(QFile& wrapperFile, boo } t << endl; + QString winscw("winscw"); // For more specific builds, targets are in this form: build-platform, e.g. release-armv5 foreach(QString item, debugPlatforms) { t << "debug-" << item << ": " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; + if(QString::compare(item, winscw) == 0) + t << "\t$(SBS) -c " << item << "_udeb.mwccinc" << testClause << endl; + else + t << "\t$(SBS) -c " << item << "_udeb" << testClause << endl; } foreach(QString item, releasePlatforms) { t << "release-" << item << ": " << BLD_INF_FILENAME << endl; - t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; + if(QString::compare(item, winscw) == 0) + t << "\t$(SBS) -c " << item << "_urel.mwccinc" << testClause << endl; + else + t << "\t$(SBS) -c " << item << "_urel" << testClause << endl; } t << endl; @@ -379,28 +386,6 @@ void SymbianSbsv2MakefileGenerator::writeBldInfExtensionRulesPart(QTextStream& t t << "END" << endl; } - // Generate temp dirs - QString tempDirs; - for (QMap<QString, QStringList>::iterator it = systeminclude.begin(); it != systeminclude.end(); ++it) { - QStringList values = it.value(); - for (int i = 0; i < values.size(); ++i) { - QString value = values.at(i); - if (value.endsWith("/" QT_EXTRA_INCLUDE_DIR)) { - value = fileInfo(value).absoluteFilePath(); - tempDirs.append(value); - tempDirs.append(" "); - } - } - } - - if (tempDirs.size()) - tempDirs.chop(1); // Remove final space - - t << "START EXTENSION qt/qmake_generate_temp_dirs" << endl; - t << "OPTION DIRS " << tempDirs << endl; - t << "END" << endl; - t << endl; - t << "START EXTENSION qt/qmake_store_build" << endl; t << "END" << endl; t << endl; @@ -414,3 +399,10 @@ void SymbianSbsv2MakefileGenerator::writeBldInfMkFilePart(QTextStream& t, bool a Q_UNUSED(t); Q_UNUSED(addDeploymentExtension); } + +void SymbianSbsv2MakefileGenerator::appendAbldTempDirs(QStringList& sysincspaths, QString includepath) +{ + //Do nothing + Q_UNUSED(sysincspaths); + Q_UNUSED(includepath); +} diff --git a/qmake/generators/symbian/symmake_sbsv2.h b/qmake/generators/symbian/symmake_sbsv2.h index 1cbddb3..9472b68 100644 --- a/qmake/generators/symbian/symmake_sbsv2.h +++ b/qmake/generators/symbian/symmake_sbsv2.h @@ -55,6 +55,7 @@ protected: virtual void writeBldInfMkFilePart(QTextStream& t, bool addDeploymentExtension); virtual void writeMkFile(const QString& wrapperFileName, bool deploymentOnly); virtual void writeWrapperMakefile(QFile& wrapperFile, bool isPrimaryMakefile); + virtual void appendAbldTempDirs(QStringList& sysincspaths, QString includepath); public: diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h index 2a407d4..188b68f 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/wtf/Platform.h @@ -98,6 +98,10 @@ /* regardless of operating environment */ #if defined(_AIX) #define WTF_PLATFORM_AIX 1 +/* 64-bit mode on AIX */ +#ifdef __64BIT__ +#define WTF_PLATFORM_AIX64 1 +#endif #endif /* PLATFORM(HPUX) */ @@ -708,6 +712,8 @@ #define WTF_USE_JSVALUE64 1 #elif (PLATFORM(IA64) && !PLATFORM(IA64_32)) || PLATFORM(SPARC64) #define WTF_USE_JSVALUE64 1 +#elif PLATFORM(AIX64) +#define WTF_USE_JSVALUE64 1 #elif PLATFORM(ARM) || PLATFORM(PPC64) #define WTF_USE_JSVALUE32 1 #elif PLATFORM(WIN_OS) && COMPILER(MINGW) diff --git a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp index a793390..a559249 100644 --- a/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp +++ b/src/3rdparty/phonon/mmf/abstractaudioeffect.cpp @@ -29,6 +29,10 @@ using namespace Phonon::MMF; \internal */ +/*! \namespace Phonon::MMF + \internal +*/ + AbstractAudioEffect::AbstractAudioEffect(QObject *parent, const QList<EffectParameter> ¶ms) : MediaNode::MediaNode(parent) , m_params(params) diff --git a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp index 0447d57..18ced94 100644 --- a/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp +++ b/src/3rdparty/phonon/mmf/ancestormovemonitor.cpp @@ -26,7 +26,7 @@ QT_BEGIN_NAMESPACE using namespace Phonon::MMF; -/*! \class MMF::AncestorMoveMonitor +/*! \class Phonon::MMF::AncestorMoveMonitor \internal \brief Class which installs a global event filter, and listens for move events which may affect the absolute position of widgets registered with @@ -34,6 +34,11 @@ using namespace Phonon::MMF; See QTBUG-4956 */ + +/*! \class Phonon::MMF::VideoOutputObserver + \internal +*/ + //----------------------------------------------------------------------------- // Constructor / destructor //----------------------------------------------------------------------------- diff --git a/src/3rdparty/phonon/mmf/utils.cpp b/src/3rdparty/phonon/mmf/utils.cpp index 58d1ece..d728fcf 100644 --- a/src/3rdparty/phonon/mmf/utils.cpp +++ b/src/3rdparty/phonon/mmf/utils.cpp @@ -24,16 +24,24 @@ QT_BEGIN_NAMESPACE using namespace Phonon; using namespace Phonon::MMF; -/*! \namespace MMF::Utils +/*! \namespace Phonon::MMF::Utils \internal */ -/*! \class MMF::TTraceContext +/*! \class Phonon::MMF::TTraceContext \internal */ -/*! \class MMF::Utils - \internal +/*! \enum Phonon::MMF::PanicCode + \internal +*/ + +/*! \enum Phonon::MMF::TTraceCategory + \internal +*/ + +/*! \enum Phonon::MMF::MediaType + \internal */ _LIT(PanicCategory, "Phonon::MMF"); diff --git a/src/3rdparty/phonon/phonon/audiooutput.cpp b/src/3rdparty/phonon/phonon/audiooutput.cpp index 3d03dc4..0f6a49b 100644 --- a/src/3rdparty/phonon/phonon/audiooutput.cpp +++ b/src/3rdparty/phonon/phonon/audiooutput.cpp @@ -259,6 +259,7 @@ void AudioOutputPrivate::setupBackendObject() // set up attributes pINTERFACE_CALL(setVolume(pow(volume, VOLTAGE_TO_LOUDNESS_EXPONENT))); +#ifndef QT_NO_PHONON_SETTINGSGROUP // if the output device is not available and the device was not explicitly set if (!callSetOutputDevice(this, device) && !outputDeviceOverridden) { // fall back in the preference list of output devices @@ -278,6 +279,7 @@ void AudioOutputPrivate::setupBackendObject() callSetOutputDevice(this, none); handleAutomaticDeviceChange(none, FallbackChange); } +#endif //QT_NO_PHONON_SETTINGSGROUP } void AudioOutputPrivate::_k_volumeChanged(qreal newVolume) @@ -307,6 +309,7 @@ void AudioOutputPrivate::_k_audioDeviceFailed() pDebug() << Q_FUNC_INFO; // outputDeviceIndex identifies a failing device // fall back in the preference list of output devices +#ifndef QT_NO_PHONON_SETTINGSGROUP const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings | GlobalConfig::HideUnavailableDevices); for (int i = 0; i < deviceList.count(); ++i) { const int devIndex = deviceList.at(i); @@ -319,6 +322,7 @@ void AudioOutputPrivate::_k_audioDeviceFailed() } } } +#endif //QT_NO_PHONON_SETTINGSGROUP // if we get here there is no working output device. Tell the backend. const AudioOutputDevice none; callSetOutputDevice(this, none); @@ -328,6 +332,7 @@ void AudioOutputPrivate::_k_audioDeviceFailed() void AudioOutputPrivate::_k_deviceListChanged() { pDebug() << Q_FUNC_INFO; +#ifndef QT_NO_PHONON_SETTINGSGROUP // let's see if there's a usable device higher in the preference list const QList<int> deviceList = GlobalConfig().audioOutputDeviceListFor(category, GlobalConfig::AdvancedDevicesFromSettings); DeviceChangeType changeType = HigherPreferenceChange; @@ -353,6 +358,7 @@ void AudioOutputPrivate::_k_deviceListChanged() break; // found one with higher preference that works } } +#endif //QT_NO_PHONON_SETTINGSGROUP } static struct diff --git a/src/3rdparty/phonon/phonon/backendcapabilities.cpp b/src/3rdparty/phonon/phonon/backendcapabilities.cpp index 0bcc76c..fbeb020 100644 --- a/src/3rdparty/phonon/phonon/backendcapabilities.cpp +++ b/src/3rdparty/phonon/phonon/backendcapabilities.cpp @@ -75,10 +75,12 @@ bool BackendCapabilities::isMimeTypeAvailable(const QString &mimeType) QList<AudioOutputDevice> BackendCapabilities::availableAudioOutputDevices() { QList<AudioOutputDevice> ret; +#ifndef QT_NO_PHONON_SETTINGSGROUP const QList<int> deviceIndexes = GlobalConfig().audioOutputDeviceListFor(Phonon::NoCategory); for (int i = 0; i < deviceIndexes.count(); ++i) { ret.append(AudioOutputDevice::fromIndex(deviceIndexes.at(i))); } +#endif //QT_NO_PHONON_SETTINGSGROUP return ret; } diff --git a/src/3rdparty/phonon/phonon/globalconfig.cpp b/src/3rdparty/phonon/phonon/globalconfig.cpp index 6e6263a..3b77a18 100644 --- a/src/3rdparty/phonon/phonon/globalconfig.cpp +++ b/src/3rdparty/phonon/phonon/globalconfig.cpp @@ -178,13 +178,15 @@ QList<int> GlobalConfig::audioOutputDeviceListFor(Phonon::Category category, int return listSortedByConfig(backendConfig, category, defaultList); } -#endif //QT_NO_SETTINGSGROUPS +#endif //QT_NO_PHONON_SETTINGSGROUP int GlobalConfig::audioOutputDeviceFor(Phonon::Category category, int override) const { +#ifndef QT_NO_PHONON_SETTINGSGROUP QList<int> ret = audioOutputDeviceListFor(category, override); - if (ret.isEmpty()) - return -1; - return ret.first(); + if (!ret.isEmpty()) + return ret.first(); +#endif //QT_NO_PHONON_SETTINGSGROUP + return -1; } #ifndef QT_NO_PHONON_AUDIOCAPTURE diff --git a/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp b/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp index 117393a..bbb676b 100644 --- a/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp +++ b/src/3rdparty/webkit/WebKit/qt/tests/qwebelement/tst_qwebelement.cpp @@ -971,7 +971,10 @@ void tst_QWebElement::render() QImage testImage(resource.width(), resource.height(), QImage::Format_ARGB32); QPainter painter0(&testImage); painter0.fillRect(imageRect, Qt::white); - painter0.drawImage(0, 0, resource); + //render() uses pixmaps internally, and pixmaps might have bit depths + // other than 32, giving different pixel values due to rounding. + QPixmap pix = QPixmap::fromImage(resource); + painter0.drawPixmap(0, 0, pix); painter0.end(); QImage image1(resource.width(), resource.height(), QImage::Format_ARGB32); diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp index 8e2273d..10a61ca 100644 --- a/src/corelib/kernel/qabstractitemmodel.cpp +++ b/src/corelib/kernel/qabstractitemmodel.cpp @@ -2475,10 +2475,8 @@ void QAbstractItemModel::endRemoveRows() bool QAbstractItemModelPrivate::allowMove(const QModelIndex &srcParent, int start, int end, const QModelIndex &destinationParent, int destinationStart, Qt::Orientation orientation) { // Don't move the range within itself. - if ( ( destinationParent == srcParent ) - && ( destinationStart >= start ) - && ( destinationStart <= end + 1) ) - return false; + if (destinationParent == srcParent) + return !(destinationStart >= start && destinationStart <= end + 1); QModelIndex destinationAncestor = destinationParent; int pos = (Qt::Vertical == orientation) ? destinationAncestor.row() : destinationAncestor.column(); diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp index 6bc6b76..3b1befd 100644 --- a/src/gui/dialogs/qfiledialog.cpp +++ b/src/gui/dialogs/qfiledialog.cpp @@ -3022,12 +3022,6 @@ bool QFileDialogPrivate::itemViewKeyboardEvent(QKeyEvent *event) { case Qt::Key_Escape: q->hide(); return true; -#ifdef QT_KEYPAD_NAVIGATION - case Qt::Key_Down: - case Qt::Key_Up: - return (QApplication::navigationMode() != Qt::NavigationModeKeypadTabOrder - && QApplication::navigationMode() != Qt::NavigationModeKeypadDirectional); -#endif default: break; } @@ -3145,20 +3139,16 @@ QSize QFileDialogListView::sizeHint() const void QFileDialogListView::keyPressEvent(QKeyEvent *e) { - if (!d_ptr->itemViewKeyboardEvent(e)) { - QListView::keyPressEvent(e); - } #ifdef QT_KEYPAD_NAVIGATION - else if ((QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder - || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) - && !hasEditFocus()) { - e->ignore(); - } else { - e->accept(); + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + QListView::keyPressEvent(e); + return; } -#else +#endif // QT_KEYPAD_NAVIGATION + + if (!d_ptr->itemViewKeyboardEvent(e)) + QListView::keyPressEvent(e); e->accept(); -#endif } QFileDialogTreeView::QFileDialogTreeView(QWidget *parent) : QTreeView(parent) @@ -3184,20 +3174,16 @@ void QFileDialogTreeView::init(QFileDialogPrivate *d_pointer) void QFileDialogTreeView::keyPressEvent(QKeyEvent *e) { - if (!d_ptr->itemViewKeyboardEvent(e)) { - QTreeView::keyPressEvent(e); - } #ifdef QT_KEYPAD_NAVIGATION - else if ((QApplication::navigationMode() == Qt::NavigationModeKeypadTabOrder - || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) - && !hasEditFocus()) { - e->ignore(); - } else { - e->accept(); + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + QTreeView::keyPressEvent(e); + return; } -#else +#endif // QT_KEYPAD_NAVIGATION + + if (!d_ptr->itemViewKeyboardEvent(e)) + QTreeView::keyPressEvent(e); e->accept(); -#endif } QSize QFileDialogTreeView::sizeHint() const @@ -3213,13 +3199,16 @@ QSize QFileDialogTreeView::sizeHint() const */ void QFileDialogLineEdit::keyPressEvent(QKeyEvent *e) { +#ifdef QT_KEYPAD_NAVIGATION + if (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional) { + QLineEdit::keyPressEvent(e); + return; + } +#endif // QT_KEYPAD_NAVIGATION + int key = e->key(); QLineEdit::keyPressEvent(e); - if (key != Qt::Key_Escape -#ifdef QT_KEYPAD_NAVIGATION - && QApplication::navigationMode() == Qt::NavigationModeNone -#endif - ) + if (key != Qt::Key_Escape) e->accept(); if (hideOnEsc && (key == Qt::Key_Escape || key == Qt::Key_Return || key == Qt::Key_Enter)) { e->accept(); diff --git a/src/gui/dialogs/qprintdialog_unix.cpp b/src/gui/dialogs/qprintdialog_unix.cpp index 6fc270d..9d6cd55 100644 --- a/src/gui/dialogs/qprintdialog_unix.cpp +++ b/src/gui/dialogs/qprintdialog_unix.cpp @@ -835,9 +835,6 @@ void QUnixPrintWidgetPrivate::setOptionsPane(QPrintDialogPrivate *pane) void QUnixPrintWidgetPrivate::_q_btnBrowseClicked() { - const int prevPrinter = widget.printers->currentIndex(); - widget.printers->setCurrentIndex(widget.printers->count() - 2); // the pdf one - QString filename = widget.filename->text(); #ifndef QT_NO_FILEDIALOG filename = QFileDialog::getSaveFileName(parent, QPrintDialog::tr("Print To File ..."), filename, @@ -849,9 +846,11 @@ void QUnixPrintWidgetPrivate::_q_btnBrowseClicked() widget.filename->setText(filename); if (filename.endsWith(QString::fromLatin1(".ps"), Qt::CaseInsensitive)) widget.printers->setCurrentIndex(widget.printers->count() - 1); // the postscript one + else if (filename.endsWith(QString::fromLatin1(".pdf"), Qt::CaseInsensitive)) + widget.printers->setCurrentIndex(widget.printers->count() - 2); // the pdf one + else if (widget.printers->currentIndex() != widget.printers->count() - 1) // if ps is not selected, pdf is default + widget.printers->setCurrentIndex(widget.printers->count() - 2); // the pdf one } - else - widget.printers->setCurrentIndex(prevPrinter); } void QUnixPrintWidgetPrivate::applyPrinterProperties(QPrinter *p) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 39291d3..c0e4890 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -62,6 +62,7 @@ QEglContext::QEglContext() , currentSurface(EGL_NO_SURFACE) , current(false) , ownsContext(true) + , sharing(false) { } @@ -174,6 +175,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties if (apiType == QEgl::OpenGL) contextProps.setValue(EGL_CONTEXT_CLIENT_VERSION, 2); #endif + sharing = false; if (shareContext && shareContext->ctx == EGL_NO_CONTEXT) shareContext = 0; if (shareContext) { @@ -181,6 +183,8 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::createContext(): Could not share context:" << errorString(eglGetError()); shareContext = 0; + } else { + sharing = true; } } if (ctx == EGL_NO_CONTEXT) { diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 16b5b16..51bdbbe 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -81,6 +81,7 @@ public: bool isValid() const; bool isCurrent() const; + bool isSharing() const { return sharing; } QEgl::API api() const { return apiType; } void setApi(QEgl::API api) { apiType = api; } @@ -132,6 +133,7 @@ private: EGLSurface currentSurface; bool current; bool ownsContext; + bool sharing; static EGLDisplay getDisplay(QPaintDevice *device); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index 872ec3c..7e5929e 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -477,9 +477,6 @@ void QGraphicsAnchorLayout::removeAt(int index) return; // Removing an item affects both horizontal and vertical graphs - d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Horizontal); - d->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Vertical); - d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Horizontal); d->removeCenterConstraints(item, QGraphicsAnchorLayoutPrivate::Vertical); d->removeAnchors(item); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h index 01c3a86..063639e 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout.h @@ -76,6 +76,7 @@ private: Q_DECLARE_PRIVATE(QGraphicsAnchor) friend class QGraphicsAnchorLayoutPrivate; + friend struct AnchorData; }; class Q_GUI_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index 594a205..fb67278 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -55,14 +55,13 @@ QT_BEGIN_NAMESPACE QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) : QObjectPrivate(version), layoutPrivate(0), data(0), - sizePolicy(QSizePolicy::Fixed) + sizePolicy(QSizePolicy::Fixed), preferredSize(0), + hasSize(true), reversed(false) { } QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() { - // ### - layoutPrivate->restoreSimplifiedGraph(QGraphicsAnchorLayoutPrivate::Orientation(data->orientation)); layoutPrivate->removeAnchor(data->from, data->to); } @@ -76,31 +75,60 @@ void QGraphicsAnchorPrivate::setSizePolicy(QSizePolicy::Policy policy) void QGraphicsAnchorPrivate::setSpacing(qreal value) { - if (data) { - layoutPrivate->setAnchorSize(data, &value); - } else { + if (!data) { qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + return; + } + + const qreal rawValue = reversed ? -preferredSize : preferredSize; + if (hasSize && (rawValue == value)) + return; + + // The anchor has an user-defined size + hasSize = true; + + // The simplex solver cannot handle negative sizes. To workaround that, + // if value is less than zero, we reverse the anchor and set the absolute + // value; + if (value >= 0) { + preferredSize = value; + if (reversed) + qSwap(data->from, data->to); + reversed = false; + } else { + preferredSize = -value; + if (!reversed) + qSwap(data->from, data->to); + reversed = true; } + + layoutPrivate->q_func()->invalidate(); } void QGraphicsAnchorPrivate::unsetSpacing() { - if (data) { - layoutPrivate->setAnchorSize(data, 0); - } else { + if (!data) { qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + return; } + + // Return to standard direction + hasSize = false; + if (reversed) + qSwap(data->from, data->to); + reversed = false; + + layoutPrivate->q_func()->invalidate(); } qreal QGraphicsAnchorPrivate::spacing() const { - qreal size = 0; - if (data) { - layoutPrivate->anchorSize(data, 0, &size, 0); - } else { + if (!data) { qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + return 0; } - return size; + + return reversed ? -preferredSize : preferredSize; } @@ -139,22 +167,22 @@ static void internalSizeHints(QSizePolicy::Policy policy, *prefSize = prefSizeHint; } -bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) +void AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) { QSizePolicy::Policy policy; qreal minSizeHint; qreal prefSizeHint; qreal maxSizeHint; - // It is an internal anchor if (item) { + // It is an internal anchor, fetch size information from the item if (isLayoutAnchor) { minSize = 0; prefSize = 0; maxSize = QWIDGETSIZE_MAX; if (isCenterAnchor) maxSize /= 2; - return true; + return; } else { if (orientation == QGraphicsAnchorLayoutPrivate::Horizontal) { policy = item->sizePolicy().horizontalPolicy(); @@ -175,14 +203,16 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) } } } else { + // It is a user-created anchor, fetch size information from the associated QGraphicsAnchor Q_ASSERT(graphicsAnchor); - policy = graphicsAnchor->sizePolicy(); + QGraphicsAnchorPrivate *anchorPrivate = graphicsAnchor->d_func(); + policy = anchorPrivate->sizePolicy; minSizeHint = 0; - if (hasSize) { + if (anchorPrivate->hasSize) { // One can only configure the preferred size of a normal anchor. Their minimum and // maximum "size hints" are always 0 and QWIDGETSIZE_MAX, correspondingly. However, // their effective size hints might be narrowed down due to their size policies. - prefSizeHint = prefSize; + prefSizeHint = anchorPrivate->preferredSize; } else { const Qt::Orientation orient = Qt::Orientation(QGraphicsAnchorLayoutPrivate::edgeOrientation(from->m_edge) + 1); qreal s = styleInfo->defaultSpacing(orient); @@ -214,8 +244,6 @@ bool AnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; sizeAtMaximum = prefSize; - - return true; } void ParallelAnchorData::updateChildrenSizes() @@ -224,8 +252,13 @@ void ParallelAnchorData::updateChildrenSizes() firstEdge->sizeAtPreferred = sizeAtPreferred; firstEdge->sizeAtMaximum = sizeAtMaximum; - const bool secondFwd = (secondEdge->from == from); - if (secondFwd) { + // We have the convention that the first children will define the direction of the + // pararell group. So we can check whether the second edge is "forward" in relation + // to the group if it have the same direction as the first edge. Note that we don't + // use 'this->from' because it might be changed by vertex simplification. + const bool secondForward = (firstEdge->from == secondEdge->from); + + if (secondForward) { secondEdge->sizeAtMinimum = sizeAtMinimum; secondEdge->sizeAtPreferred = sizeAtPreferred; secondEdge->sizeAtMaximum = sizeAtMaximum; @@ -239,26 +272,21 @@ void ParallelAnchorData::updateChildrenSizes() secondEdge->updateChildrenSizes(); } -bool ParallelAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) +bool ParallelAnchorData::calculateSizeHints() { - return refreshSizeHints_helper(styleInfo); -} - -bool ParallelAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, - bool refreshChildren) -{ - if (refreshChildren && (!firstEdge->refreshSizeHints(styleInfo) - || !secondEdge->refreshSizeHints(styleInfo))) { - return false; - } + // Note that parallel groups can lead to unfeasibility, so during calculation, we can + // find out one unfeasibility. Because of that this method return boolean. This can't + // happen in sequential, so there the method is void. // Account for parallel anchors where the second edge is backwards. // We rely on the fact that a forward anchor of sizes min, pref, max is equivalent // to a backwards anchor of size (-max, -pref, -min) - const bool secondFwd = (secondEdge->from == from); - const qreal secondMin = secondFwd ? secondEdge->minSize : -secondEdge->maxSize; - const qreal secondPref = secondFwd ? secondEdge->prefSize : -secondEdge->prefSize; - const qreal secondMax = secondFwd ? secondEdge->maxSize : -secondEdge->minSize; + + // Also see comments in updateChildrenSizes(). + const bool secondForward = (firstEdge->from == secondEdge->from); + const qreal secondMin = secondForward ? secondEdge->minSize : -secondEdge->maxSize; + const qreal secondPref = secondForward ? secondEdge->prefSize : -secondEdge->prefSize; + const qreal secondMax = secondForward ? secondEdge->maxSize : -secondEdge->minSize; minSize = qMax(firstEdge->minSize, secondMin); maxSize = qMin(firstEdge->maxSize, secondMax); @@ -386,13 +414,7 @@ void SequentialAnchorData::updateChildrenSizes() } } -bool SequentialAnchorData::refreshSizeHints(const QLayoutStyleInfo *styleInfo) -{ - return refreshSizeHints_helper(styleInfo); -} - -bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, - bool refreshChildren) +void SequentialAnchorData::calculateSizeHints() { minSize = 0; prefSize = 0; @@ -400,11 +422,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style for (int i = 0; i < m_edges.count(); ++i) { AnchorData *edge = m_edges.at(i); - - // If it's the case refresh children information first - if (refreshChildren && !edge->refreshSizeHints(styleInfo)) - return false; - minSize += edge->minSize; prefSize += edge->prefSize; maxSize += edge->maxSize; @@ -414,8 +431,6 @@ bool SequentialAnchorData::refreshSizeHints_helper(const QLayoutStyleInfo *style sizeAtMinimum = prefSize; sizeAtPreferred = prefSize; sizeAtMaximum = prefSize; - - return true; } #ifdef QT_DEBUG @@ -490,7 +505,6 @@ QGraphicsAnchorLayoutPrivate::QGraphicsAnchorLayoutPrivate() interpolationProgress[i] = -1; spacings[i] = -1; - graphSimplified[i] = false; graphHasConflicts[i] = false; layoutFirstVertex[i] = 0; @@ -591,7 +605,7 @@ AnchorData *QGraphicsAnchorLayoutPrivate::addAnchorMaybeParallel(AnchorData *new // At this point we can identify that the parallel anchor is not feasible, e.g. one // anchor minimum size is bigger than the other anchor maximum size. - *feasible = parallel->refreshSizeHints_helper(0, false); + *feasible = parallel->calculateSizeHints(); newAnchor = parallel; } @@ -652,7 +666,7 @@ static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph, sequence->from = before; sequence->to = after; - sequence->refreshSizeHints_helper(0, false); + sequence->calculateSizeHints(); return sequence; } @@ -696,16 +710,18 @@ static AnchorData *createSequence(Graph<AnchorVertex, AnchorData> *graph, */ bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) { - static bool noSimplification = !qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); - if (noSimplification || items.isEmpty()) + if (items.isEmpty()) return true; - if (graphSimplified[orientation]) - return true; - -#if 0 +#if defined(QT_DEBUG) && 0 qDebug("Simplifying Graph for %s", orientation == Horizontal ? "Horizontal" : "Vertical"); + + static int count = 0; + if (orientation == Horizontal) { + count++; + dumpGraph(QString::fromAscii("%1-full").arg(count)); + } #endif // Vertex simplification @@ -723,13 +739,16 @@ bool QGraphicsAnchorLayoutPrivate::simplifyGraph(Orientation orientation) // Note that if we are not feasible, we fallback and make sure that the graph is fully restored if (!feasible) { - graphSimplified[orientation] = true; restoreSimplifiedGraph(orientation); restoreVertices(orientation); return false; } - graphSimplified[orientation] = true; +#if defined(QT_DEBUG) && 0 + dumpGraph(QString::fromAscii("%1-simplified-%2").arg(count).arg( + QString::fromAscii(orientation == Horizontal ? "Horizontal" : "Vertical"))); +#endif + return true; } @@ -1134,10 +1153,6 @@ void QGraphicsAnchorLayoutPrivate::restoreSimplifiedConstraints(ParallelAnchorDa void QGraphicsAnchorLayoutPrivate::restoreSimplifiedGraph(Orientation orientation) { - if (!graphSimplified[orientation]) - return; - graphSimplified[orientation] = false; - #if 0 qDebug("Restoring Simplified Graph for %s", orientation == Horizontal ? "Horizontal" : "Vertical"); @@ -1292,19 +1307,17 @@ void QGraphicsAnchorLayoutPrivate::deleteLayoutEdges() void QGraphicsAnchorLayoutPrivate::createItemEdges(QGraphicsLayoutItem *item) { - Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]); - items.append(item); // Create horizontal and vertical internal anchors for the item and // refresh its size hint / policy values. AnchorData *data = new AnchorData; addAnchor_helper(item, Qt::AnchorLeft, item, Qt::AnchorRight, data); - data->refreshSizeHints(0); // 0 = effectiveSpacing, will not be used + data->refreshSizeHints(); data = new AnchorData; addAnchor_helper(item, Qt::AnchorTop, item, Qt::AnchorBottom, data); - data->refreshSizeHints(0); // 0 = effectiveSpacing, will not be used + data->refreshSizeHints(); } /*! @@ -1336,8 +1349,6 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( return; } - Q_ASSERT(!graphSimplified[orientation]); - // Check if vertex already exists if (internalVertex(item, centerEdge)) return; @@ -1366,14 +1377,14 @@ void QGraphicsAnchorLayoutPrivate::createCenterAnchors( addAnchor_helper(item, firstEdge, item, centerEdge, data); data->isCenterAnchor = true; data->dependency = AnchorData::Master; - data->refreshSizeHints(0); + data->refreshSizeHints(); data = new AnchorData; c->variables.insert(data, -1.0); addAnchor_helper(item, centerEdge, item, lastEdge, data); data->isCenterAnchor = true; data->dependency = AnchorData::Slave; - data->refreshSizeHints(0); + data->refreshSizeHints(); itemCenterConstraints[orientation].append(c); @@ -1404,8 +1415,6 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( return; } - Q_ASSERT(!graphSimplified[orientation]); - // Orientation code Qt::AnchorPoint firstEdge; Qt::AnchorPoint lastEdge; @@ -1442,7 +1451,7 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( // Create the new anchor that should substitute the left-center-right anchors. AnchorData *data = new AnchorData; addAnchor_helper(item, firstEdge, item, lastEdge, data); - data->refreshSizeHints(0); + data->refreshSizeHints(); // Remove old anchors removeAnchor_helper(first, center); @@ -1473,8 +1482,6 @@ void QGraphicsAnchorLayoutPrivate::removeCenterAnchors( void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation) { - Q_ASSERT(!graphSimplified[orientation]); - // Remove the item center constraints associated to this item // ### This is a temporary solution. We should probably use a better // data structure to hold items and/or their associated constraints @@ -1505,15 +1512,21 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem * /*! * \internal + * Implements the high level "addAnchor" feature. Called by the public API + * addAnchor method. * - * Helper function that is called from the anchor functions in the public API. - * If \a spacing is 0, it will pick up the spacing defined by the style. + * The optional \a spacing argument defines the size of the anchor. If not provided, + * the anchor size is either 0 or not-set, depending on type of anchor created (see + * matrix below). + * + * All anchors that remain with size not-set will assume the standard spacing, + * set either by the layout style or through the "setSpacing" layout API. */ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - qreal *spacing) + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *spacing) { Q_Q(QGraphicsAnchorLayout); if ((firstItem == 0) || (secondItem == 0)) { @@ -1534,10 +1547,6 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi return 0; } - // Guarantee that the graph is no simplified when adding this anchor, - // anchor manipulation always happen in the full graph - restoreSimplifiedGraph(edgeOrientation(firstEdge)); - // In QGraphicsAnchorLayout, items are represented in its internal // graph as four anchors that connect: // - Left -> HCenter @@ -1547,12 +1556,10 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi // Ensure that the internal anchors have been created for both items. if (firstItem != q && !items.contains(firstItem)) { - restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal); createItemEdges(firstItem); addChildLayoutItem(firstItem); } if (secondItem != q && !items.contains(secondItem)) { - restoreSimplifiedGraph(edgeOrientation(firstEdge) == Horizontal ? Vertical : Horizontal); createItemEdges(secondItem); addChildLayoutItem(secondItem); } @@ -1565,7 +1572,13 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); AnchorData *data = new AnchorData; - if (!spacing) { + QGraphicsAnchor *graphicsAnchor = acquireGraphicsAnchor(data); + + addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); + + if (spacing) { + graphicsAnchor->setSpacing(*spacing); + } else { // If firstItem or secondItem is the layout itself, the spacing will default to 0. // Otherwise, the following matrix is used (questionmark means that the spacing // is queried from the style): @@ -1578,45 +1591,39 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *fi || secondItem == q || pickEdge(firstEdge, Horizontal) == Qt::AnchorHorizontalCenter || oppositeEdge(firstEdge) != secondEdge) { - data->setPreferredSize(0); + graphicsAnchor->setSpacing(0); } else { - data->unsetSize(); + graphicsAnchor->unsetSpacing(); } - addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); - - } else if (*spacing >= 0) { - data->setPreferredSize(*spacing); - addAnchor_helper(firstItem, firstEdge, secondItem, secondEdge, data); - - } else { - data->setPreferredSize(-*spacing); - addAnchor_helper(secondItem, secondEdge, firstItem, firstEdge, data); } - return acquireGraphicsAnchor(data); + return graphicsAnchor; } +/* + \internal + + This method adds an AnchorData to the internal graph. It is responsible for doing + the boilerplate part of such task. + + If another AnchorData exists between the mentioned vertices, it is deleted and + the new one is inserted. +*/ void QGraphicsAnchorLayoutPrivate::addAnchor_helper(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - AnchorData *data) + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + AnchorData *data) { Q_Q(QGraphicsAnchorLayout); const Orientation orientation = edgeOrientation(firstEdge); - // Guarantee that the graph is no simplified when adding this anchor, - // anchor manipulation always happen in the full graph - restoreSimplifiedGraph(orientation); - - // Is the Vertex (firstItem, firstEdge) already represented in our - // internal structure? + // Create or increase the reference count for the related vertices. AnchorVertex *v1 = addInternalVertex(firstItem, firstEdge); AnchorVertex *v2 = addInternalVertex(secondItem, secondEdge); // Remove previous anchor - // ### Could we update the existing edgeData rather than creating a new one? if (graph[orientation].edgeData(v1, v2)) { removeAnchor_helper(v1, v2); } @@ -1647,15 +1654,13 @@ QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *fi QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) { - Orientation orient = edgeOrientation(firstEdge); - restoreSimplifiedGraph(orient); - + const Orientation orientation = edgeOrientation(firstEdge); AnchorVertex *v1 = internalVertex(firstItem, firstEdge); AnchorVertex *v2 = internalVertex(secondItem, secondEdge); QGraphicsAnchor *graphicsAnchor = 0; - AnchorData *data = graph[orient].edgeData(v1, v2); + AnchorData *data = graph[orientation].edgeData(v1, v2); if (data) graphicsAnchor = acquireGraphicsAnchor(data); return graphicsAnchor; @@ -1740,12 +1745,9 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor(AnchorVertex *firstVertex, void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2) { Q_ASSERT(v1 && v2); - // Guarantee that the graph is no simplified when removing this anchor, - // anchor manipulation always happen in the full graph - Orientation o = edgeOrientation(v1->m_edge); - restoreSimplifiedGraph(o); // Remove edge from graph + const Orientation o = edgeOrientation(v1->m_edge); graph[o].removeEdge(v1, v2); // Decrease vertices reference count (may trigger a deletion) @@ -1753,67 +1755,6 @@ void QGraphicsAnchorLayoutPrivate::removeAnchor_helper(AnchorVertex *v1, AnchorV removeInternalVertex(v2->m_item, v2->m_edge); } -/*! - \internal - Only called from outside. (calls invalidate()) -*/ -void QGraphicsAnchorLayoutPrivate::setAnchorSize(AnchorData *data, const qreal *anchorSize) -{ - Q_Q(QGraphicsAnchorLayout); - // ### we can avoid restoration if we really want to, but we would have to - // search recursively through all composite anchors - Q_ASSERT(data); - restoreSimplifiedGraph(edgeOrientation(data->from->m_edge)); - - QGraphicsLayoutItem *firstItem = data->from->m_item; - QGraphicsLayoutItem *secondItem = data->to->m_item; - Qt::AnchorPoint firstEdge = data->from->m_edge; - Qt::AnchorPoint secondEdge = data->to->m_edge; - - // Use heuristics to find out what the user meant with this anchor. - correctEdgeDirection(firstItem, firstEdge, secondItem, secondEdge); - if (data->from->m_item != firstItem) - qSwap(data->from, data->to); - - if (anchorSize) { - // ### The current implementation makes "setAnchorSize" behavior - // dependent on the argument order for cases where we have - // no heuristic. Ie. two widgets, same anchor point. - - // We cannot have negative sizes inside the graph. This would cause - // the simplex solver to fail because all simplex variables are - // positive by definition. - // "negative spacing" is handled by inverting the standard item order. - if (*anchorSize >= 0) { - data->setPreferredSize(*anchorSize); - } else { - data->setPreferredSize(-*anchorSize); - qSwap(data->from, data->to); - } - } else { - data->unsetSize(); - } - q->invalidate(); -} - -void QGraphicsAnchorLayoutPrivate::anchorSize(const AnchorData *data, - qreal *minSize, - qreal *prefSize, - qreal *maxSize) const -{ - Q_ASSERT(minSize || prefSize || maxSize); - Q_ASSERT(data); - QGraphicsAnchorLayoutPrivate *that = const_cast<QGraphicsAnchorLayoutPrivate *>(this); - that->restoreSimplifiedGraph(Orientation(data->orientation)); - - if (minSize) - *minSize = data->minSize; - if (prefSize) - *prefSize = data->prefSize; - if (maxSize) - *maxSize = data->maxSize; -} - AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item, Qt::AnchorPoint edge) { @@ -1879,8 +1820,6 @@ void QGraphicsAnchorLayoutPrivate::removeVertex(QGraphicsLayoutItem *item, Qt::A void QGraphicsAnchorLayoutPrivate::removeAnchors(QGraphicsLayoutItem *item) { - Q_ASSERT(!graphSimplified[Horizontal] && !graphSimplified[Vertical]); - // remove the center anchor first!! removeCenterAnchors(item, Qt::AnchorHorizontalCenter, false); removeVertex(item, Qt::AnchorLeft); @@ -1983,20 +1922,8 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs() { if (!calculateGraphCacheDirty) return; - -#if defined(QT_DEBUG) && 0 - static int count = 0; - count++; - dumpGraph(QString::fromAscii("%1-before").arg(count)); -#endif - calculateGraphs(Horizontal); calculateGraphs(Vertical); - -#if defined(QT_DEBUG) && 0 - dumpGraph(QString::fromAscii("%1-after").arg(count)); -#endif - calculateGraphCacheDirty = false; } @@ -2044,26 +1971,13 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( lastCalculationUsedSimplex[orientation] = false; #endif - // ### This is necessary because now we do vertex simplification, we still don't know - // differentiate between invalidate()s that doesn't need resimplification and those which - // need. For example, when size hint of an item changes, this may cause an anchor to reach 0 or to - // leave 0 and get a size. In both cases we need resimplify. - // - // ### one possible solution would be tracking all the 0-sized anchors, if this set change, we need - // resimplify. - restoreSimplifiedGraph(orientation); - - // Reset the nominal sizes of each anchor based on the current item sizes. This function - // works with both simplified and non-simplified graphs, so it'll work when the - // simplification is going to be reused. - if (!refreshAllSizeHints(orientation)) { - qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); - graphHasConflicts[orientation] = true; - return; - } + static bool simplificationEnabled = qgetenv("QT_ANCHORLAYOUT_NO_SIMPLIFICATION").isEmpty(); + + // Reset the nominal sizes of each anchor based on the current item sizes + refreshAllSizeHints(orientation); // Simplify the graph - if (!simplifyGraph(orientation)) { + if (simplificationEnabled && !simplifyGraph(orientation)) { qWarning("QGraphicsAnchorLayout: anchor setup is not feasible."); graphHasConflicts[orientation] = true; return; @@ -2127,6 +2041,9 @@ void QGraphicsAnchorLayoutPrivate::calculateGraphs( qDeleteAll(constraints[orientation]); constraints[orientation].clear(); graphPaths[orientation].clear(); // ### + + if (simplificationEnabled) + restoreSimplifiedGraph(orientation); } /*! @@ -2226,29 +2143,19 @@ bool QGraphicsAnchorLayoutPrivate::calculateNonTrunk(const QList<QSimplexConstra /*! \internal - Traverse the graph refreshing the size hints. Complex anchors will call the - refresh method of their children anchors. Simple anchors, if are internal - anchors, will query the associated item for their size hints. - - Returns false if some unfeasibility was found in the graph regarding the - complex anchors. + Traverse the graph refreshing the size hints. Edges will query their associated + item or graphicsAnchor for their size hints. */ -bool QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) +void QGraphicsAnchorLayoutPrivate::refreshAllSizeHints(Orientation orientation) { Graph<AnchorVertex, AnchorData> &g = graph[orientation]; QList<QPair<AnchorVertex *, AnchorVertex *> > vertices = g.connections(); QLayoutStyleInfo styleInf = styleInfo(); for (int i = 0; i < vertices.count(); ++i) { - AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second);; - Q_ASSERT(data->from && data->to); - - // During the traversal we check the feasibility of the complex anchors. - if (!data->refreshSizeHints(&styleInf)) - return false; + AnchorData *data = g.edgeData(vertices.at(i).first, vertices.at(i).second); + data->refreshSizeHints(&styleInf); } - - return true; } /*! @@ -2621,21 +2528,6 @@ void QGraphicsAnchorLayoutPrivate::setItemsGeometries(const QRectF &geom) } /*! - \internal - - Fill the distance in the vertex and in the sub-vertices if its a combined vertex. -*/ -static void setVertexDistance(AnchorVertex *v, qreal distance) -{ - v->distance = distance; - if (v->m_type == AnchorVertex::Pair) { - AnchorVertexPair *pair = static_cast<AnchorVertexPair *>(v); - setVertexDistance(pair->m_first, distance); - setVertexDistance(pair->m_second, distance); - } -} - -/*! \internal Calculate the position of each vertex based on the paths to each of @@ -2650,7 +2542,7 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( // Get root vertex AnchorVertex *root = layoutFirstVertex[orientation]; - setVertexDistance(root, 0); + root->distance = 0; visited.insert(root); // Add initial edges to the queue @@ -2661,16 +2553,12 @@ void QGraphicsAnchorLayoutPrivate::calculateVertexPositions( // Do initial calculation required by "interpolateEdge()" setupEdgesInterpolation(orientation); - // Traverse the graph and calculate vertex positions, we need to - // visit all pairs since each of them could have a sequential - // anchor inside, which hides more vertices. + // Traverse the graph and calculate vertex positions while (!queue.isEmpty()) { QPair<AnchorVertex *, AnchorVertex *> pair = queue.dequeue(); AnchorData *edge = graph[orientation].edgeData(pair.first, pair.second); - // Both vertices were interpolated, and the anchor itself can't have other - // anchors inside (it's not a complex anchor). - if (edge->type == AnchorData::Normal && visited.contains(pair.second)) + if (visited.contains(pair.second)) continue; visited.insert(pair.second); @@ -2710,24 +2598,20 @@ void QGraphicsAnchorLayoutPrivate::setupEdgesInterpolation( } /*! - \internal - - Calculate the current Edge size based on the current Layout size and the - size the edge is supposed to have when the layout is at its: + \internal - - minimum size, - - preferred size, - - maximum size. + Calculate the current Edge size based on the current Layout size and the + size the edge is supposed to have when the layout is at its: - These three key values are calculated in advance using linear - programming (more expensive) or the simplification algorithm, then - subsequential resizes of the parent layout require a simple - interpolation. + - minimum size, + - preferred size, + - maximum size. - If the edge is sequential or parallel, it's possible to have more - vertices to be initalized, so it calls specialized functions that - will recurse back to interpolateEdge(). - */ + These three key values are calculated in advance using linear + programming (more expensive) or the simplification algorithm, then + subsequential resizes of the parent layout require a simple + interpolation. +*/ void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorData *edge) { const Orientation orientation = Orientation(edge->orientation); @@ -2741,64 +2625,10 @@ void QGraphicsAnchorLayoutPrivate::interpolateEdge(AnchorVertex *base, AnchorDat // Calculate the distance for the vertex opposite to the base if (edge->from == base) { - setVertexDistance(edge->to, base->distance + edgeDistance); + edge->to->distance = base->distance + edgeDistance; } else { - setVertexDistance(edge->from, base->distance - edgeDistance); - } - - // Process child anchors - if (edge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast<SequentialAnchorData *>(edge)); - else if (edge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast<ParallelAnchorData *>(edge)); -} - -void QGraphicsAnchorLayoutPrivate::interpolateParallelEdges(ParallelAnchorData *data) -{ - // In parallels the boundary vertices are already calculate, we - // just need to look for sequential groups inside, because only - // them may have new vertices associated. - - // First edge - if (data->firstEdge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast<SequentialAnchorData *>(data->firstEdge)); - else if (data->firstEdge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast<ParallelAnchorData *>(data->firstEdge)); - - // Second edge - if (data->secondEdge->type == AnchorData::Sequential) - interpolateSequentialEdges(static_cast<SequentialAnchorData *>(data->secondEdge)); - else if (data->secondEdge->type == AnchorData::Parallel) - interpolateParallelEdges(static_cast<ParallelAnchorData *>(data->secondEdge)); -} - -void QGraphicsAnchorLayoutPrivate::interpolateSequentialEdges(SequentialAnchorData *data) -{ - // This method is supposed to handle any sequential anchor, even out-of-order - // ones. However, in the current QGAL implementation we should get only the - // well behaved ones. - Q_ASSERT(data->m_edges.first()->from == data->from); - Q_ASSERT(data->m_edges.last()->to == data->to); - - // At this point, the two outter vertices already have their distance - // calculated. - // We use the first as the base to calculate the internal ones - - AnchorVertex *prev = data->from; - - for (int i = 0; i < data->m_edges.count() - 1; ++i) { - AnchorData *edge = data->m_edges.at(i); - interpolateEdge(prev, edge); - - // Use the recently calculated vertex as the base for the next one - const bool edgeIsForward = (edge->from == prev); - prev = edgeIsForward ? edge->to : edge->from; + edge->from->distance = base->distance - edgeDistance; } - - // Treat the last specially, since we already calculated it's end - // vertex, so it's only interesting if it's a complex one - if (data->m_edges.last()->type != AnchorData::Normal) - interpolateEdge(prev, data->m_edges.last()); } bool QGraphicsAnchorLayoutPrivate::solveMinMax(const QList<QSimplexConstraint *> &constraints, diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 5f50c85..2b365fb 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -121,17 +121,17 @@ struct AnchorData : public QSimplexVariable { }; AnchorData() - : QSimplexVariable(), item(0), from(0), to(0), + : QSimplexVariable(), from(0), to(0), minSize(0), prefSize(0), maxSize(0), sizeAtMinimum(0), sizeAtPreferred(0), - sizeAtMaximum(0), + sizeAtMaximum(0), item(0), graphicsAnchor(0), skipInPreferred(0), - type(Normal), hasSize(true), isLayoutAnchor(false), + type(Normal), isLayoutAnchor(false), isCenterAnchor(false), orientation(0), dependency(Independent) {} virtual void updateChildrenSizes() {} - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); + void refreshSizeHints(const QLayoutStyleInfo *styleInfo = 0); virtual ~AnchorData() {} @@ -141,43 +141,36 @@ struct AnchorData : public QSimplexVariable { QString name; #endif - inline void setPreferredSize(qreal size) - { - prefSize = size; - hasSize = true; - } - - inline void unsetSize() - { - hasSize = false; - } - - // Internal anchors have associated items - QGraphicsLayoutItem *item; - // Anchor is semantically directed AnchorVertex *from; AnchorVertex *to; - // Size restrictions of this edge. For anchors internal to items, these - // values are derived from the respective item size hints. For anchors - // that were added by users, these values are equal to the specified anchor - // size. + // Nominal sizes + // These are the intrinsic size restrictions for a given item. They are + // used as input for the calculation of the actual sizes. + // These values are filled by the refreshSizeHints method, based on the + // anchor size policy, the size hints of the item it (possibly) represents + // and the layout spacing information. qreal minSize; qreal prefSize; qreal maxSize; + // Calculated sizes // These attributes define which sizes should that anchor be in when the // layout is at its minimum, preferred or maximum sizes. Values are // calculated by the Simplex solver based on the current layout setup. qreal sizeAtMinimum; qreal sizeAtPreferred; qreal sizeAtMaximum; + + // References to the classes that represent this anchor in the public world + // An anchor may represent a LayoutItem, it may also be acessible externally + // through a GraphicsAnchor "handler". + QGraphicsLayoutItem *item; QGraphicsAnchor *graphicsAnchor; uint skipInPreferred : 1; uint type : 2; // either Normal, Sequential or Parallel - uint hasSize : 1; // if false, get size from style. uint isLayoutAnchor : 1; // if this anchor is an internal layout anchor uint isCenterAnchor : 1; uint orientation : 1; @@ -204,9 +197,7 @@ struct SequentialAnchorData : public AnchorData } virtual void updateChildrenSizes(); - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); - - bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true); + void calculateSizeHints(); QVector<AnchorVertex*> m_children; // list of vertices in the sequence QVector<AnchorData*> m_edges; // keep the list of edges too. @@ -233,9 +224,7 @@ struct ParallelAnchorData : public AnchorData } virtual void updateChildrenSizes(); - virtual bool refreshSizeHints(const QLayoutStyleInfo *styleInfo); - - bool refreshSizeHints_helper(const QLayoutStyleInfo *styleInfo, bool refreshChildren = true); + bool calculateSizeHints(); AnchorData* firstEdge; AnchorData* secondEdge; @@ -350,7 +339,13 @@ public: QGraphicsAnchorLayoutPrivate *layoutPrivate; AnchorData *data; + + // Size information for user controlled anchor QSizePolicy::Policy sizePolicy; + qreal preferredSize; + + uint hasSize : 1; // if false, get size from style. + uint reversed : 1; // if true, the anchor was inverted to keep its value positive }; @@ -445,11 +440,6 @@ public: void removeAnchor(AnchorVertex *firstVertex, AnchorVertex *secondVertex); void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); - void setAnchorSize(AnchorData *data, const qreal *anchorSize); - void anchorSize(const AnchorData *data, - qreal *minSize = 0, - qreal *prefSize = 0, - qreal *maxSize = 0) const; void removeAnchors(QGraphicsLayoutItem *item); @@ -489,7 +479,7 @@ public: const QList<AnchorData *> &variables); // Support functions for calculateGraph() - bool refreshAllSizeHints(Orientation orientation); + void refreshAllSizeHints(Orientation orientation); void findPaths(Orientation orientation); void constraintsFromPaths(Orientation orientation); void updateAnchorSizes(Orientation orientation); @@ -528,8 +518,6 @@ public: void calculateVertexPositions(Orientation orientation); void setupEdgesInterpolation(Orientation orientation); void interpolateEdge(AnchorVertex *base, AnchorData *edge); - void interpolateSequentialEdges(SequentialAnchorData *edge); - void interpolateParallelEdges(ParallelAnchorData *edge); // Linear Programming solver methods bool solveMinMax(const QList<QSimplexConstraint *> &constraints, @@ -576,8 +564,6 @@ public: Interval interpolationInterval[2]; qreal interpolationProgress[2]; - // ### - bool graphSimplified[2]; bool graphHasConflicts[2]; QSet<QGraphicsLayoutItem *> m_floatItems[2]; diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index 13f31b8..5b0643d 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -4551,6 +4551,10 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const viewTransform, QRegion *exposedRegion, QWidget *widget) { + // Make sure we don't have unpolished items before we draw. + if (!unpolishedItems.isEmpty()) + _q_polishItems(); + QRectF exposedSceneRect; if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) { exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1); @@ -5077,6 +5081,10 @@ void QGraphicsScene::drawItems(QPainter *painter, const QStyleOptionGraphicsItem options[], QWidget *widget) { Q_D(QGraphicsScene); + // Make sure we don't have unpolished items before we draw. + if (!d->unpolishedItems.isEmpty()) + d->_q_polishItems(); + QTransform viewTransform = painter->worldTransform(); Q_UNUSED(options); diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index 9d783dd..17baa50 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -349,7 +349,8 @@ QS60PixmapData::QS60PixmapData(PixelType type) : QRasterPixmapData(type), bitmapDevice(0), bitmapGc(0), pengine(0), - bytes(0) + bytes(0), + formatLocked(false) { } @@ -425,11 +426,12 @@ void QS60PixmapData::release() } /*! - * Takes ownership of bitmap + * Takes ownership of bitmap. Used by window surface */ void QS60PixmapData::fromSymbianBitmap(CFbsBitmap* bitmap) { cfbsBitmap = bitmap; + formatLocked = true; if(!initSymbianBitmapContext()) { qWarning("Could not create CBitmapContext"); @@ -693,8 +695,10 @@ void QS60PixmapData::beginDataAccess() bytes = newBytes; TDisplayMode mode = cfbsBitmap->DisplayMode(); QImage::Format format = qt_TDisplayMode2Format(mode); - //on S60 3.1, premultiplied alpha pixels are stored in a bitmap with 16MA type - if (format == QImage::Format_ARGB32) + // On S60 3.1, premultiplied alpha pixels are stored in a bitmap with 16MA type. + // S60 window surface needs backing store pixmap for transparent window in ARGB32 format. + // In that case formatLocked is true. + if (!formatLocked && format == QImage::Format_ARGB32) format = QImage::Format_ARGB32_Premultiplied; // pixel data is actually in premultiplied format QVector<QRgb> savedColorTable; diff --git a/src/gui/image/qpixmap_s60_p.h b/src/gui/image/qpixmap_s60_p.h index b23961a..b1b5824 100644 --- a/src/gui/image/qpixmap_s60_p.h +++ b/src/gui/image/qpixmap_s60_p.h @@ -118,6 +118,8 @@ private: QPaintEngine *pengine; uchar* bytes; + bool formatLocked; + friend class QPixmap; friend class QS60WindowSurface; friend class QS60PaintEngine; diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index c0b840a..3723500 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -1064,9 +1064,7 @@ void QPixmapDropShadowFilter::setOffset(const QPointF &offset) QRectF QPixmapDropShadowFilter::boundingRectFor(const QRectF &rect) const { Q_D(const QPixmapDropShadowFilter); - qreal delta = d->radius + 1; - return rect.adjusted(-2, -2, 2, 2).united( - rect.translated(d->offset).adjusted(-delta, -delta, delta, delta)); + return rect.united(rect.translated(d->offset).adjusted(-d->radius, -d->radius, d->radius, d->radius)); } /*! @@ -1089,19 +1087,24 @@ void QPixmapDropShadowFilter::draw(QPainter *p, return; } - QImage tmp = src.isNull() ? px.toImage() : px.copy(src.toAlignedRect()).toImage(); + QImage tmp(px.size(), QImage::Format_ARGB32_Premultiplied); + tmp.fill(0); + QPainter tmpPainter(&tmp); + tmpPainter.setCompositionMode(QPainter::CompositionMode_Source); + tmpPainter.drawPixmap(d->offset, px); + tmpPainter.end(); // blur the alpha channel tmp = blurred(tmp, tmp.rect(), qRound(d->radius), true); // blacken the image... - QPainter tmpPainter(&tmp); + tmpPainter.begin(&tmp); tmpPainter.setCompositionMode(QPainter::CompositionMode_SourceIn); - tmpPainter.fillRect(0, 0, tmp.width(), tmp.height(), d->color); + tmpPainter.fillRect(tmp.rect(), d->color); tmpPainter.end(); // draw the blurred drop shadow... - p->drawImage(pos + d->offset, tmp); + p->drawImage(pos, tmp); // Draw the actual pixmap... p->drawPixmap(pos, px, src); diff --git a/src/gui/inputmethod/qcoefepinputcontext_p.h b/src/gui/inputmethod/qcoefepinputcontext_p.h index 2c65b4c..e24ee04 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_p.h +++ b/src/gui/inputmethod/qcoefepinputcontext_p.h @@ -84,7 +84,7 @@ public: bool filterEvent(const QEvent *event); void mouseHandler( int x, QMouseEvent *event); - bool isComposing() const { return m_isEditing; } + bool isComposing() const { return !m_preeditString.isEmpty(); } void setFocusWidget(QWidget * w); void widgetDestroyed(QWidget *w); @@ -132,6 +132,7 @@ public: // From MObjectProvider public: TTypeUid::Ptr MopSupplyObject(TTypeUid id); + MObjectProvider *MopNext(); private: QSymbianControl *m_parent; @@ -139,13 +140,14 @@ private: QString m_preeditString; Qt::InputMethodHints m_lastImHints; TUint m_textCapabilities; - bool m_isEditing; bool m_inDestruction; bool m_pendingInputCapabilitiesChanged; int m_cursorVisibility; int m_inlinePosition; MFepInlineTextFormatRetriever *m_formatRetriever; MFepPointerEventHandlerDuringInlineEdit *m_pointerHandler; + int m_longPress; + int m_cursorPos; }; QT_END_NAMESPACE diff --git a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp index 19f296c..bdff5e7 100644 --- a/src/gui/inputmethod/qcoefepinputcontext_s60.cpp +++ b/src/gui/inputmethod/qcoefepinputcontext_s60.cpp @@ -65,13 +65,14 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState(q_check_ptr(new CAknEdwinState)), // CBase derived object needs check on new m_lastImHints(Qt::ImhNone), m_textCapabilities(TCoeInputCapabilities::EAllText), - m_isEditing(false), m_inDestruction(false), m_pendingInputCapabilitiesChanged(false), m_cursorVisibility(1), m_inlinePosition(0), m_formatRetriever(0), - m_pointerHandler(0) + m_pointerHandler(0), + m_longPress(0), + m_cursorPos(0) { m_fepState->SetObjectProvider(this); m_fepState->SetFlags(EAknEditorFlagDefault); @@ -79,7 +80,7 @@ QCoeFepInputContext::QCoeFepInputContext(QObject *parent) m_fepState->SetPermittedInputModes( EAknEditorAllInputModes ); m_fepState->SetDefaultCase( EAknEditorLowerCase ); m_fepState->SetPermittedCases( EAknEditorLowerCase|EAknEditorUpperCase ); - m_fepState->SetSpecialCharacterTableResourceId( 0 ); + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); m_fepState->SetNumericKeymap( EAknEditorStandardNumberModeKeymap ); } @@ -202,14 +203,26 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease) { const QKeyEvent *keyEvent = static_cast<const QKeyEvent *>(event); - Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); - if (keyEvent->key() == Qt::Key_F20 && m_lastImHints & Qt::ImhHiddenText) { - // Special case in Symbian. On editors with secret text, F20 is for some reason - // considered to be a backspace. - QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(), - keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count()); - QApplication::sendEvent(focusWidget(), &modifiedEvent); - return true; + switch (keyEvent->key()) { + case Qt::Key_F20: + Q_ASSERT(m_lastImHints == focusWidget()->inputMethodHints()); + if (m_lastImHints & Qt::ImhHiddenText) { + // Special case in Symbian. On editors with secret text, F20 is for some reason + // considered to be a backspace. + QKeyEvent modifiedEvent(keyEvent->type(), Qt::Key_Backspace, keyEvent->modifiers(), + keyEvent->text(), keyEvent->isAutoRepeat(), keyEvent->count()); + QApplication::sendEvent(focusWidget(), &modifiedEvent); + return true; + } + break; + case Qt::Key_Select: + if (!m_preeditString.isEmpty()) { + commitCurrentString(false); + return true; + } + break; + default: + break; } } @@ -243,7 +256,6 @@ bool QCoeFepInputContext::filterEvent(const QEvent *event) void QCoeFepInputContext::mouseHandler( int x, QMouseEvent *event) { - Q_ASSERT(m_isEditing); Q_ASSERT(focusWidget()); if (event->type() == QEvent::MouseButtonPress && event->button() == Qt::LeftButton) { @@ -407,6 +419,14 @@ void QCoeFepInputContext::applyHints(Qt::InputMethodHints hints) } m_fepState->SetNumericKeymap(static_cast<TAknEditorNumericKeymap>(flags)); + if (hints & ImhEmailCharactersOnly) { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_EMAIL_ADDR_SPECIAL_CHARACTER_TABLE_DIALOG); + } else if (hints & ImhUrlCharactersOnly) { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_URL_SPECIAL_CHARACTER_TABLE_DIALOG); + } else { + m_fepState->SetSpecialCharacterTableResourceId(R_AVKON_SPECIAL_CHARACTER_TABLE_DIALOG); + } + if (hints & ImhHiddenText) { m_textCapabilities = TCoeInputCapabilities::EAllText | TCoeInputCapabilities::ESecretText; } else { @@ -478,8 +498,8 @@ void QCoeFepInputContext::StartFepInlineEditL(const TDesC& aInitialInlineText, if (!w) return; - m_isEditing = true; - + m_cursorPos = w->inputMethodQuery(Qt::ImCursorPosition).toInt(); + QList<QInputMethodEvent::Attribute> attributes; m_cursorVisibility = aCursorVisibility ? 1 : 0; @@ -543,8 +563,6 @@ void QCoeFepInputContext::CancelFepInlineEdit() event.setCommitString(QLatin1String(""), 0, 0); m_preeditString.clear(); sendEvent(event); - - m_isEditing = false; } TInt QCoeFepInputContext::DocumentLengthForFep() const @@ -683,16 +701,22 @@ void QCoeFepInputContext::DoCommitFepInlineEditL() void QCoeFepInputContext::commitCurrentString(bool triggeredBySymbian) { if (m_preeditString.size() == 0) { + QWidget *w = focusWidget(); + if (triggeredBySymbian && w) { + // We must replace the last character only if the input box has already accepted one + if (w->inputMethodQuery(Qt::ImCursorPosition).toInt() != m_cursorPos) + m_longPress = 1; + } return; } QList<QInputMethodEvent::Attribute> attributes; QInputMethodEvent event(QLatin1String(""), attributes); - event.setCommitString(m_preeditString, 0, 0);//m_preeditString.size()); + event.setCommitString(m_preeditString, 0-m_longPress, m_longPress); m_preeditString.clear(); sendEvent(event); - m_isEditing = false; + m_longPress = 0; if (!triggeredBySymbian) { CCoeFep* fep = CCoeEnv::Static()->Fep(); @@ -733,6 +757,14 @@ TTypeUid::Ptr QCoeFepInputContext::MopSupplyObject(TTypeUid /*id*/) return TTypeUid::Null(); } +MObjectProvider *QCoeFepInputContext::MopNext() +{ + QWidget *w = focusWidget(); + if (w) + return w->effectiveWinId(); + return 0; +} + QT_END_NAMESPACE #endif // QT_NO_IM diff --git a/src/gui/itemviews/qitemselectionmodel.cpp b/src/gui/itemviews/qitemselectionmodel.cpp index c6e02a6..2e4a602 100644 --- a/src/gui/itemviews/qitemselectionmodel.cpp +++ b/src/gui/itemviews/qitemselectionmodel.cpp @@ -730,13 +730,14 @@ void QItemSelectionModelPrivate::_q_layoutAboutToBeChanged() savedPersistentIndexes.clear(); savedPersistentCurrentIndexes.clear(); - // special case for when all indexes are selected + // optimisation for when all indexes are selected + // (only if there is lots of items (1000) because this is not entirely correct) if (ranges.isEmpty() && currentSelection.count() == 1) { QItemSelectionRange range = currentSelection.first(); QModelIndex parent = range.parent(); tableRowCount = model->rowCount(parent); tableColCount = model->columnCount(parent); - if (tableRowCount * tableColCount > 100 + if (tableRowCount * tableColCount > 1000 && range.top() == 0 && range.left() == 0 && range.bottom() == tableRowCount - 1 diff --git a/src/gui/itemviews/qtreewidget.cpp b/src/gui/itemviews/qtreewidget.cpp index 040c498..c133ae4 100644 --- a/src/gui/itemviews/qtreewidget.cpp +++ b/src/gui/itemviews/qtreewidget.cpp @@ -2851,7 +2851,14 @@ QTreeWidgetItem *QTreeWidget::itemAt(const QPoint &p) const QRect QTreeWidget::visualItemRect(const QTreeWidgetItem *item) const { Q_D(const QTreeWidget); - return visualRect(d->index(item)); + //the visual rect for an item is across all columns. So we need to determine + //what is the first and last column and get their visual index rects + QModelIndex base = d->index(item); + const int firstVisiblesection = header()->logicalIndexAt(- header()->offset()); + const int lastVisibleSection = header()->logicalIndexAt(header()->length() - header()->offset() - 1); + QModelIndex first = base.sibling(base.row(), header()->logicalIndex(firstVisiblesection)); + QModelIndex last = base.sibling(base.row(), header()->logicalIndex(lastVisibleSection)); + return visualRect(first) | visualRect(last); } /*! diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp index ec95d48..04e4b31 100644 --- a/src/gui/kernel/qapplication_s60.cpp +++ b/src/gui/kernel/qapplication_s60.cpp @@ -319,7 +319,12 @@ void QLongTapTimer::RunL() } QSymbianControl::QSymbianControl(QWidget *w) - : CCoeControl(), qwidget(w), m_ignoreFocusChanged(false) + : CCoeControl() + , qwidget(w) + , m_longTapDetector(0) + , m_ignoreFocusChanged(0) + , m_previousEventLongTap(0) + , m_symbianPopupIsOpen(0) { } @@ -911,6 +916,15 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) return; if (IsFocused() && IsVisible()) { + if (m_symbianPopupIsOpen) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusIn, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = false; + } + QApplication::setActiveWindow(qwidget->window()); #ifdef Q_WS_S60 // If widget is fullscreen, hide status pane and button container @@ -924,6 +938,16 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */) buttonGroup->MakeVisible(!isFullscreen); #endif } else if (QApplication::activeWindow() == qwidget->window()) { + if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) { + QWidget *fw = QApplication::focusWidget(); + if (fw) { + QFocusEvent event(QEvent::FocusOut, Qt::PopupFocusReason); + QCoreApplication::sendEvent(fw, &event); + } + m_symbianPopupIsOpen = true; + return; + } + QApplication::setActiveWindow(0); } // else { We don't touch the active window unless we were explicitly activated or deactivated } diff --git a/src/gui/kernel/qsoftkeymanager.cpp b/src/gui/kernel/qsoftkeymanager.cpp index ecad72f..22ac319 100644 --- a/src/gui/kernel/qsoftkeymanager.cpp +++ b/src/gui/kernel/qsoftkeymanager.cpp @@ -213,11 +213,15 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) CEikButtonGroupContainer* nativeContainer = S60->buttonGroupContainer(); nativeContainer->DrawableWindow()->SetOrdinalPosition(0); nativeContainer->DrawableWindow()->SetPointerCapturePriority(1); //keep softkeys available in modal dialog - QT_TRAP_THROWING(nativeContainer->SetCommandSetL(R_AVKON_SOFTKEYS_EMPTY_WITH_IDS)); + nativeContainer->DrawableWindow()->SetFaded(EFalse, RWindowTreeNode::EFadeIncludeChildren); int position = -1; - int command; bool needsExitButton = true; + QT_TRAP_THROWING( + //Using -1 instead of EAknSoftkeyEmpty to avoid flickering. + nativeContainer->SetCommandL(0, -1, KNullDesC); + nativeContainer->SetCommandL(2, -1, KNullDesC); + ); for (int index = 0; index < softkeys.count(); index++) { const QAction* softKeyAction = softkeys.at(index); @@ -238,7 +242,7 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) break; } - command = (softKeyAction->objectName().contains("_q_menuSoftKeyAction")) + int command = (softKeyAction->objectName().contains("_q_menuSoftKeyAction")) ? EAknSoftkeyOptions : s60CommandStart + index; @@ -255,7 +259,8 @@ void QSoftKeyManagerPrivate::updateSoftKeys_sys(const QList<QAction*> &softkeys) : Qt::Widget; if (needsExitButton && sourceWindowType != Qt::Dialog && sourceWindowType != Qt::Popup) - QT_TRAP_THROWING(nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); + QT_TRAP_THROWING( + nativeContainer->SetCommandL(2, EAknSoftkeyExit, qt_QString2TPtrC(QSoftKeyManager::tr("Exit")))); nativeContainer->DrawDeferred(); // 3.1 needs an extra invitation } diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h index 333458b..ec8c9cb 100644 --- a/src/gui/kernel/qt_s60_p.h +++ b/src/gui/kernel/qt_s60_p.h @@ -175,7 +175,7 @@ public: protected: // from MAknFadedComponent TInt CountFadedComponents() {return 1;} - CCoeControl* FadedComponent(TInt aIndex) {return this;} + CCoeControl* FadedComponent(TInt /*aIndex*/) {return this;} #else #warning No fallback implementation for QSymbianControl::FadeBehindPopup void FadeBehindPopup(bool /*fade*/){ } @@ -202,9 +202,10 @@ private: private: QWidget *qwidget; - bool m_ignoreFocusChanged; QLongTapTimer* m_longTapDetector; - bool m_previousEventLongTap; + bool m_ignoreFocusChanged : 1; + bool m_previousEventLongTap : 1; + bool m_symbianPopupIsOpen : 1; #ifdef Q_WS_S60 // Fader object used to fade everything except this menu and the CBA. diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp index 67bbd9f..b1c37d3 100644 --- a/src/gui/kernel/qwidget_s60.cpp +++ b/src/gui/kernel/qwidget_s60.cpp @@ -213,6 +213,15 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if ((q->windowType() == Qt::Desktop)) return; + + QPoint oldPos(q->pos()); + QSize oldSize(q->size()); + QRect oldGeom(data.crect); + + // Lose maximized status if deliberate resize + if (w != oldSize.width() || h != oldSize.height()) + data.window_state &= ~Qt::WindowMaximized; + if (extra) { // any size restrictions? w = qMin(w,extra->maxw); h = qMin(h,extra->maxh); @@ -228,17 +237,10 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) data.window_state = s; } - QPoint oldPos(q->pos()); - QSize oldSize(q->size()); - QRect oldGeom(data.crect); - bool isResize = w != oldSize.width() || h != oldSize.height(); if (!isMove && !isResize) return; - if (isResize) - data.window_state &= ~Qt::WindowMaximized; - if (q->isWindow()) { if (w == 0 || h == 0) { q->setAttribute(Qt::WA_OutsideWSRange, true); @@ -359,6 +361,7 @@ void QWidgetPrivate::create_sys(WId window, bool /* initializeWindow */, bool de QScopedPointer<QSymbianControl> control( q_check_ptr(new QSymbianControl(q)) ); QT_TRAP_THROWING(control->ConstructL(true, desktop)); + control->SetMopParent(static_cast<CEikAppUi*>(S60->appUi())); // Symbian windows are always created in an inactive state // We perform this assignment for the case where the window is being re-created @@ -1235,7 +1238,7 @@ void QWidget::releaseKeyboard() void QWidget::grabMouse() { - if (!qt_nograb()) { + if (isVisible() && !qt_nograb()) { if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) QWidgetPrivate::mouseGrabber->releaseMouse(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); @@ -1252,7 +1255,7 @@ void QWidget::grabMouse() #ifndef QT_NO_CURSOR void QWidget::grabMouse(const QCursor &cursor) { - if (!qt_nograb()) { + if (isVisible() && !qt_nograb()) { if (QWidgetPrivate::mouseGrabber && QWidgetPrivate::mouseGrabber != this) QWidgetPrivate::mouseGrabber->releaseMouse(); Q_ASSERT(testAttribute(Qt::WA_WState_Created)); diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp index 8737f10..ba1b642 100644 --- a/src/gui/painting/qblendfunctions.cpp +++ b/src/gui/painting/qblendfunctions.cpp @@ -223,21 +223,25 @@ void qt_scale_image_16bit(uchar *destPixels, int dbpl, int h = ty2 - ty1; int w = tx2 - tx1; + quint32 basex; quint32 srcy; + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; + if (sx < 0) { - int dstx = qFloor((tx1 + 0.5 - targetRect.right()) * ix) + 1; + int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1; basex = quint32(srcRect.right() * 65536) + dstx; } else { - int dstx = qCeil((tx1 + 0.5 - targetRect.left()) * ix) - 1; + int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1; basex = quint32(srcRect.left() * 65536) + dstx; } if (sy < 0) { - int dsty = qFloor((ty1 + 0.5 - targetRect.bottom()) * iy) + 1; + int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1; srcy = quint32(srcRect.bottom() * 65536) + dsty; } else { - int dsty = qCeil((ty1 + 0.5 - targetRect.top()) * iy) - 1; + int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1; srcy = quint32(srcRect.top() * 65536) + dsty; } @@ -738,18 +742,22 @@ template <typename T> void qt_scale_image_32bit(uchar *destPixels, int dbpl, quint32 basex; quint32 srcy; + const int dstx = qCeil((tx1 + 0.5 - qMin(targetRect.left(), targetRect.right())) * ix) - 1; + const int dsty = qCeil((ty1 + 0.5 - qMin(targetRect.top(), targetRect.bottom())) * iy) - 1; + + if (sx < 0) { - int dstx = qFloor((tx1 + 0.5 - targetRect.right()) * ix) + 1; + int dstx = qFloor((tx1 + qreal(0.5) - targetRect.right()) * ix) + 1; basex = quint32(srcRect.right() * 65536) + dstx; } else { - int dstx = qCeil((tx1 + 0.5 - targetRect.left()) * ix) - 1; + int dstx = qCeil((tx1 + qreal(0.5) - targetRect.left()) * ix) - 1; basex = quint32(srcRect.left() * 65536) + dstx; } if (sy < 0) { - int dsty = qFloor((ty1 + 0.5 - targetRect.bottom()) * iy) + 1; + int dsty = qFloor((ty1 + qreal(0.5) - targetRect.bottom()) * iy) + 1; srcy = quint32(srcRect.bottom() * 65536) + dsty; } else { - int dsty = qCeil((ty1 + 0.5 - targetRect.top()) * iy) - 1; + int dsty = qCeil((ty1 + qreal(0.5) - targetRect.top()) * iy) - 1; srcy = quint32(srcRect.top() * 65536) + dsty; } diff --git a/src/gui/painting/qpaintbuffer_p.h b/src/gui/painting/qpaintbuffer_p.h index adf0564..e100512 100644 --- a/src/gui/painting/qpaintbuffer_p.h +++ b/src/gui/painting/qpaintbuffer_p.h @@ -66,7 +66,7 @@ class QPaintBufferPlayback; class Q_GUI_EXPORT QPaintBuffer : public QPaintDevice { - Q_DECLARE_PRIVATE(QPaintBuffer); + Q_DECLARE_PRIVATE(QPaintBuffer) public: QPaintBuffer(); QPaintBuffer(const QPaintBuffer &other); diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp index ab2dc33..51d6195 100644 --- a/src/gui/painting/qpathclipper.cpp +++ b/src/gui/painting/qpathclipper.cpp @@ -1650,7 +1650,7 @@ static void clear(QWingedEdge& list, int edge, QPathEdge::Traversal traversal) template <typename InputIterator> InputIterator qFuzzyFind(InputIterator first, InputIterator last, qreal val) { - while (first != last && !qFuzzyCompare(qreal(*first), qreal(val))) + while (first != last && !QT_PREPEND_NAMESPACE(qFuzzyCompare)(qreal(*first), qreal(val))) ++first; return first; } diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 9d1d965..63dec2b 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -3867,23 +3867,28 @@ QRegion::QRegion(const QRect &r, RegionType t) QRegion::QRegion(const QPolygon &a, Qt::FillRule fillRule) { if (a.count() > 2) { - d = new QRegionData; - d->ref = 1; + QRegionPrivate *qt_rgn = PolygonRegion(a.constData(), a.size(), + fillRule == Qt::WindingFill ? WindingRule : EvenOddRule); + if (qt_rgn) { + d = new QRegionData; + d->ref = 1; #if defined(Q_WS_X11) - d->rgn = 0; - d->xrectangles = 0; + d->rgn = 0; + d->xrectangles = 0; #elif defined(Q_WS_WIN) - d->rgn = 0; + d->rgn = 0; #endif - d->qt_rgn = PolygonRegion(a.constData(), a.size(), - fillRule == Qt::WindingFill ? WindingRule : EvenOddRule); + d->qt_rgn = qt_rgn; + } else { + d = &shared_empty; + d->ref.ref(); + } } else { d = &shared_empty; d->ref.ref(); } } - QRegion::QRegion(const QRegion &r) { d = r.d; diff --git a/src/gui/styles/qs60style.cpp b/src/gui/styles/qs60style.cpp index d33dc6a..939ea45 100644 --- a/src/gui/styles/qs60style.cpp +++ b/src/gui/styles/qs60style.cpp @@ -473,7 +473,7 @@ void QS60StylePrivate::setBackgroundTexture(QApplication *app) const Q_UNUSED(app) QPalette applicationPalette = QApplication::palette(); applicationPalette.setBrush(QPalette::Window, backgroundTexture()); - setThemePalette(app); + setThemePalette(&applicationPalette); } void QS60StylePrivate::deleteBackground() @@ -668,7 +668,7 @@ void QS60StylePrivate::setThemePalette(QPalette *palette) const s60Color(QS60StyleEnums::CL_QsnTextColors, 55, 0)); palette->setColor(QPalette::BrightText, palette->color(QPalette::WindowText).lighter()); palette->setColor(QPalette::HighlightedText, - s60Color(QS60StyleEnums::CL_QsnTextColors, 10, 0)); + s60Color(QS60StyleEnums::CL_QsnTextColors, 24, 0)); palette->setColor(QPalette::Link, s60Color(QS60StyleEnums::CL_QsnHighlightColors, 3, 0)); palette->setColor(QPalette::LinkVisited, palette->color(QPalette::Link).darker()); @@ -799,6 +799,9 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag case QS60StyleEnums::SP_QgnGrafTabPassiveR: case QS60StyleEnums::SP_QgnGrafTabPassiveL: case QS60StyleEnums::SP_QgnGrafTabActiveL: + //Returned QSize for tabs must not be square, but narrow rectangle with width:height + //ratio of 1:2 for horizontal tab bars (and 2:1 for vertical ones). + result.setWidth(10); break; case QS60StyleEnums::SP_QgnIndiSliderEdit: result.scale(pixelMetric(QStyle::PM_SliderLength), @@ -809,7 +812,7 @@ QSize QS60StylePrivate::partSize(QS60StyleEnums::SkinParts part, SkinElementFlag case QS60StyleEnums::SP_QgnGrafBarFrameSideR: result.setWidth(pixelMetric(PM_Custom_FrameCornerWidth)); break; - + case QS60StyleEnums::SP_QsnCpScrollHandleBottomPressed: case QS60StyleEnums::SP_QsnCpScrollHandleTopPressed: case QS60StyleEnums::SP_QsnCpScrollHandleMiddlePressed: diff --git a/src/gui/text/qabstracttextdocumentlayout.h b/src/gui/text/qabstracttextdocumentlayout.h index 2f8a746..438b291 100644 --- a/src/gui/text/qabstracttextdocumentlayout.h +++ b/src/gui/text/qabstracttextdocumentlayout.h @@ -122,6 +122,7 @@ protected: QTextCharFormat format(int pos); private: + friend class QTextControl; friend class QTextDocument; friend class QTextDocumentPrivate; friend class QTextEngine; diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 4041717..293eac7 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -755,9 +755,8 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph load_flags = FT_LOAD_NO_BITMAP; // apply our matrix to this, but note that the metrics will not be affected by this. - FT_Matrix matrix = freetype->matrix; FT_Face face = lockFace(); - matrix = this->matrix; + FT_Matrix matrix = this->matrix; FT_Matrix_Multiply(&set->transformationMatrix, &matrix); FT_Set_Transform(face, &matrix, 0); freetype->matrix = matrix; diff --git a/src/gui/text/qtextcontrol.cpp b/src/gui/text/qtextcontrol.cpp index 2bfe33c..be79773 100644 --- a/src/gui/text/qtextcontrol.cpp +++ b/src/gui/text/qtextcontrol.cpp @@ -55,6 +55,7 @@ #include <qstyle.h> #include <qtimer.h> #include "private/qtextdocumentlayout_p.h" +#include "private/qabstracttextdocumentlayout_p.h" #include "private/qtextedit_p.h" #include "qtextdocument.h" #include "private/qtextdocument_p.h" @@ -126,6 +127,7 @@ QTextControlPrivate::QTextControlPrivate() #endif isEnabled(true), hadSelectionOnMousePress(false), + ignoreUnusedNavigationEvents(false), openExternalLinks(false) {} @@ -264,19 +266,25 @@ bool QTextControlPrivate::cursorMoveKeyEvent(QKeyEvent *e) cursor.setVisualNavigation(visualNavigation); q->ensureCursorVisible(); + bool ignoreNavigationEvents = ignoreUnusedNavigationEvents; + bool isNavigationEvent = e->key() == Qt::Key_Up || e->key() == Qt::Key_Down; + +#ifdef QT_KEYPAD_NAVIGATION + ignoreNavigationEvents = ignoreNavigationEvents || QApplication::keypadNavigationEnabled(); + isNavigationEvent = isNavigationEvent || + (QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional + && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right)); +#else + isNavigationEvent = isNavigationEvent || e->key() == Qt::Key_Left || e->key() == Qt::Key_Right; +#endif + if (moved) { if (cursor.position() != oldCursorPos) emit q->cursorPositionChanged(); emit q->microFocusChanged(); - } -#ifdef QT_KEYPAD_NAVIGATION - else if (QApplication::keypadNavigationEnabled() - && ((e->key() == Qt::Key_Up || e->key() == Qt::Key_Down) - || QApplication::navigationMode() == Qt::NavigationModeKeypadDirectional - && (e->key() == Qt::Key_Left || e->key() == Qt::Key_Right))) { + } else if (ignoreNavigationEvents && isNavigationEvent) { return false; } -#endif selectionChanged(/*forceEmitSelectionChanged =*/(mode == QTextCursor::KeepAnchor)); @@ -2263,6 +2271,18 @@ bool QTextControl::openExternalLinks() const return d->openExternalLinks; } +bool QTextControl::ignoreUnusedNavigationEvents() const +{ + Q_D(const QTextControl); + return d->ignoreUnusedNavigationEvents; +} + +void QTextControl::setIgnoreUnusedNavigationEvents(bool ignore) +{ + Q_D(QTextControl); + d->ignoreUnusedNavigationEvents = ignore; +} + void QTextControl::moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode) { Q_D(QTextControl); @@ -2319,6 +2339,9 @@ void QTextControl::print(QPrinter *printer) const tempDoc->setUseDesignMetrics(doc->useDesignMetrics()); QTextCursor(tempDoc).insertFragment(d->cursor.selection()); doc = tempDoc; + + // copy the custom object handlers + doc->documentLayout()->d_func()->handlers = d->doc->documentLayout()->d_func()->handlers; } doc->print(printer); delete tempDoc; diff --git a/src/gui/text/qtextcontrol_p.h b/src/gui/text/qtextcontrol_p.h index 263af31..bc8e063 100644 --- a/src/gui/text/qtextcontrol_p.h +++ b/src/gui/text/qtextcontrol_p.h @@ -95,6 +95,7 @@ class Q_GUI_EXPORT QTextControl : public QObject Q_PROPERTY(int cursorWidth READ cursorWidth WRITE setCursorWidth) Q_PROPERTY(Qt::TextInteractionFlags textInteractionFlags READ textInteractionFlags WRITE setTextInteractionFlags) Q_PROPERTY(bool openExternalLinks READ openExternalLinks WRITE setOpenExternalLinks) + Q_PROPERTY(bool ignoreUnusedNavigationEvents READ ignoreUnusedNavigationEvents WRITE setIgnoreUnusedNavigationEvents) public: explicit QTextControl(QObject *parent = 0); explicit QTextControl(const QString &text, QObject *parent = 0); @@ -163,6 +164,9 @@ public: void setOpenExternalLinks(bool open); bool openExternalLinks() const; + void setIgnoreUnusedNavigationEvents(bool ignore); + bool ignoreUnusedNavigationEvents() const; + void moveCursor(QTextCursor::MoveOperation op, QTextCursor::MoveMode mode = QTextCursor::MoveAnchor); bool canPaste() const; diff --git a/src/gui/text/qtextcontrol_p_p.h b/src/gui/text/qtextcontrol_p_p.h index 66459f6..c230512 100644 --- a/src/gui/text/qtextcontrol_p_p.h +++ b/src/gui/text/qtextcontrol_p_p.h @@ -206,6 +206,7 @@ public: QString anchorOnMousePress; bool hadSelectionOnMousePress; + bool ignoreUnusedNavigationEvents; bool openExternalLinks; QString linkToCopy; diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp index 1aad385..048325c 100644 --- a/src/gui/text/qtextdocument.cpp +++ b/src/gui/text/qtextdocument.cpp @@ -64,6 +64,7 @@ #include "qtextdocument_p.h" #include <private/qprinter_p.h> +#include <private/qabstracttextdocumentlayout_p.h> #include <limits.h> @@ -1722,6 +1723,9 @@ void QTextDocument::print(QPrinter *printer) const QAbstractTextDocumentLayout *layout = doc->documentLayout(); layout->setPaintDevice(p.device()); + // copy the custom object handlers + layout->d_func()->handlers = documentLayout()->d_func()->handlers; + int dpiy = p.device()->logicalDpiY(); int margin = 0; if (printer->fullPage() && !printer->d_func()->hasCustomPageMargins) { diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp index 73434b1..2604879 100644 --- a/src/gui/text/qtextdocumentlayout.cpp +++ b/src/gui/text/qtextdocumentlayout.cpp @@ -1448,13 +1448,13 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p painter->fillRect(r, brush); break; case QTextListFormat::ListCircle: - painter->drawEllipse(r); + painter->setPen(QPen(brush, 0)); + painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering break; case QTextListFormat::ListDisc: painter->setBrush(brush); painter->setPen(Qt::NoPen); painter->drawEllipse(r); - painter->setBrush(Qt::NoBrush); break; case QTextListFormat::ListStyleUndefined: break; diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp index d05d9e5..deda39f 100644 --- a/src/gui/text/qtextformat.cpp +++ b/src/gui/text/qtextformat.cpp @@ -265,21 +265,55 @@ private: friend QDataStream &operator>>(QDataStream &, QTextFormat &); }; -static uint variantHash(const QVariant &variant) +// this is only safe if sizeof(int) == sizeof(float) +static inline uint hash(float d) { - switch (variant.userType()) { - case QVariant::Invalid: return 0; - case QVariant::Bool: return variant.toBool(); - case QVariant::Int: return variant.toInt(); - case QMetaType::Float: return static_cast<int>(variant.toFloat()); - case QVariant::Double: return static_cast<int>(variant.toDouble()); + return reinterpret_cast<uint&>(d); +} + +static inline uint hash(const QColor &color) +{ + return (color.isValid()) ? color.rgba() : 0x234109; +} + +static inline uint hash(const QPen &pen) +{ + return hash(pen.color()) + hash(pen.widthF()); +} + +static inline uint hash(const QBrush &brush) +{ + return hash(brush.color()) + (brush.style() << 3); +} + +static inline uint variantHash(const QVariant &variant) +{ + // simple and fast hash functions to differentiate between type and value + switch (variant.userType()) { // sorted by occurrence frequency case QVariant::String: return qHash(variant.toString()); - case QVariant::Color: return qHash(qvariant_cast<QColor>(variant).rgb()); + case QVariant::Double: return hash(variant.toDouble()); + case QVariant::Int: return 0x811890 + variant.toInt(); + case QVariant::Brush: + return 0x01010101 + hash(qvariant_cast<QBrush>(variant)); + case QVariant::Bool: return 0x371818 + variant.toBool(); + case QVariant::Pen: return 0x02020202 + hash(qvariant_cast<QPen>(variant)); + case QVariant::List: + return 0x8377 + qvariant_cast<QVariantList>(variant).count(); + case QVariant::Color: return hash(qvariant_cast<QColor>(variant)); + case QVariant::TextLength: + return 0x377 + hash(qvariant_cast<QTextLength>(variant).rawValue()); + case QMetaType::Float: return hash(variant.toFloat()); + case QVariant::Invalid: return 0; default: break; } return qHash(variant.typeName()); } +static inline int getHash(const QTextFormatPrivate *d, int format) +{ + return (d ? d->hash() : 0) + format; +} + uint QTextFormatPrivate::recalcHash() const { hashValue = 0; @@ -3033,13 +3067,15 @@ QTextFormatCollection::~QTextFormatCollection() int QTextFormatCollection::indexForFormat(const QTextFormat &format) { - uint hash = format.d ? format.d->hash() : 0; - if (hashes.contains(hash)) { - for (int i = 0; i < formats.size(); ++i) { - if (formats.at(i) == format) - return i; + uint hash = getHash(format.d, format.format_type); + QMultiHash<uint, int>::const_iterator i = hashes.find(hash); + while (i != hashes.end() && i.key() == hash) { + if (formats.value(i.value()) == format) { + return i.value(); } + ++i; } + int idx = formats.size(); formats.append(format); @@ -3049,7 +3085,7 @@ int QTextFormatCollection::indexForFormat(const QTextFormat &format) f.d = new QTextFormatPrivate; f.d->resolveFont(defaultFnt); - hashes.insert(hash); + hashes.insert(hash, idx); } QT_CATCH(...) { formats.pop_back(); @@ -3060,11 +3096,13 @@ int QTextFormatCollection::indexForFormat(const QTextFormat &format) bool QTextFormatCollection::hasFormatCached(const QTextFormat &format) const { - uint hash = format.d ? format.d->hash() : 0; - if (hashes.contains(hash)) { - for (int i = 0; i < formats.size(); ++i) - if (formats.at(i) == format) - return true; + uint hash = getHash(format.d, format.format_type); + QMultiHash<uint, int>::const_iterator i = hashes.find(hash); + while (i != hashes.end() && i.key() == hash) { + if (formats.value(i.value()) == format) { + return true; + } + ++i; } return false; } diff --git a/src/gui/text/qtextformat_p.h b/src/gui/text/qtextformat_p.h index c796343..73ca0ce 100644 --- a/src/gui/text/qtextformat_p.h +++ b/src/gui/text/qtextformat_p.h @@ -55,7 +55,7 @@ #include "QtGui/qtextformat.h" #include "QtCore/qvector.h" -#include "QtCore/qset.h" +#include "QtCore/qhash.h" QT_BEGIN_NAMESPACE @@ -97,7 +97,7 @@ public: FormatVector formats; QVector<qint32> objFormats; - QSet<uint> hashes; + QMultiHash<uint,int> hashes; inline QFont defaultFont() const { return defaultFnt; } void setDefaultFont(const QFont &f); diff --git a/src/gui/widgets/qcalendarwidget.cpp b/src/gui/widgets/qcalendarwidget.cpp index 08ed7f6..ee536ee 100644 --- a/src/gui/widgets/qcalendarwidget.cpp +++ b/src/gui/widgets/qcalendarwidget.cpp @@ -2297,7 +2297,21 @@ int QCalendarWidget::monthShown() const void QCalendarWidget::setCurrentPage(int year, int month) { Q_D(QCalendarWidget); + QDate currentDate = d->getCurrentDate(); + int day = currentDate.day(); + int daysInMonths = QDate(year, month, 1).daysInMonth(); + if (day > daysInMonths) + day = daysInMonths; + d->showMonth(year, month); + + QDate newDate(year, month, day); + int row = -1, col = -1; + d->m_model->cellForDate(newDate, &row, &col); + if (row != -1 && col != -1) { + d->m_view->selectionModel()->setCurrentIndex(d->m_model->index(row, col), + QItemSelectionModel::NoUpdate); + } } /*! diff --git a/src/gui/widgets/qdialogbuttonbox.cpp b/src/gui/widgets/qdialogbuttonbox.cpp index 2231b98..2ee5751 100644 --- a/src/gui/widgets/qdialogbuttonbox.cpp +++ b/src/gui/widgets/qdialogbuttonbox.cpp @@ -315,9 +315,9 @@ void QDialogButtonBoxPrivate::initLayout() buttonLayout = new QVBoxLayout(q); } - int left, top, right, bottom; + int left, top, right, bottom; setLayoutItemMargins(QStyle::SE_PushButtonLayoutItem); - getLayoutItemMargins(&left, &top, &right, &bottom); + getLayoutItemMargins(&left, &top, &right, &bottom); buttonLayout->setContentsMargins(-left, -top, -right, -bottom); if (!q->testAttribute(Qt::WA_WState_OwnSizePolicy)) { @@ -356,7 +356,7 @@ void QDialogButtonBoxPrivate::addButtonsToLayout(const QList<QAbstractButton *> void QDialogButtonBoxPrivate::layoutButtons() { Q_Q(QDialogButtonBox); - const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item + const int MacGap = 36 - 8; // 8 is the default gap between a widget and a spacer item for (int i = buttonLayout->count() - 1; i >= 0; --i) { QLayoutItem *item = buttonLayout->takeAt(i); @@ -581,6 +581,22 @@ QAction* QDialogButtonBoxPrivate::createSoftKey(QAbstractButton *button, QDialog } QObject::connect(action, SIGNAL(triggered()), button, SIGNAL(clicked())); action->setSoftKeyRole(softkeyRole); + + + QWidget *dialog = 0; + QWidget *p = q; + while (p && !p->isWindow()) { + p = p->parentWidget(); + if ((dialog = qobject_cast<QDialog *>(p))) + break; + } + + if (dialog) { + dialog->addAction(action); + } else { + q->addAction(action); + } + return action; } #endif @@ -1193,12 +1209,8 @@ bool QDialogButtonBox::event(QEvent *event) if (!hasDefault && firstAcceptButton) firstAcceptButton->setDefault(true); #ifdef QT_SOFTKEYS_ENABLED - if (dialog) { + if (dialog) setFixedSize(0,0); - dialog->addActions(d->softKeyActions.values()); - } else { - addActions(d->softKeyActions.values()); - } #endif }else if (event->type() == QEvent::LanguageChange) { d->retranslateStrings(); diff --git a/src/gui/widgets/qdockarealayout.cpp b/src/gui/widgets/qdockarealayout.cpp index 953edab..07914b2 100644 --- a/src/gui/widgets/qdockarealayout.cpp +++ b/src/gui/widgets/qdockarealayout.cpp @@ -1931,9 +1931,6 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> item_list.append(item); } else { QDockAreaLayoutItem item(new QDockWidgetItem(widget)); - if (!testing) { - item_list.append(item); - } if (flags & StateFlagFloating) { bool drawer = false; #ifdef Q_WS_MAC // drawer support @@ -1971,11 +1968,13 @@ bool QDockAreaLayoutInfo::restoreState(QDataStream &stream, QList<QDockWidget*> if (!testing) { widget->setVisible(flags & StateFlagVisible); + item_list.append(item); } } else { int dummy; stream >> item.pos >> item.size >> dummy >> dummy; if (!testing) { + item_list.append(item); widget->setFloating(false); widget->setVisible(flags & StateFlagVisible); emit widget->dockLocationChanged(toDockWidgetArea(dockPos)); diff --git a/src/gui/widgets/qlabel.cpp b/src/gui/widgets/qlabel.cpp index 3d908a1..ea711e8 100644 --- a/src/gui/widgets/qlabel.cpp +++ b/src/gui/widgets/qlabel.cpp @@ -1170,22 +1170,10 @@ void QLabelPrivate::updateShortcut() // But then we do want to hide the ampersands, so we can't use shortcutId. hasShortcut = false; - if (control) { - ensureTextPopulated(); - // Underline the first character that follows an ampersand - shortcutCursor = control->document()->find(QLatin1String("&")); - if (shortcutCursor.isNull()) - return; - hasShortcut = true; - shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); - shortcutCursor.deleteChar(); // remove the ampersand - shortcutCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); - } else { - if (!text.contains(QLatin1Char('&'))) - return; - hasShortcut = true; - shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); - } + if (!text.contains(QLatin1Char('&'))) + return; + hasShortcut = true; + shortcutId = q->grabShortcut(QKeySequence::mnemonic(text)); } #endif // QT_NO_SHORTCUT @@ -1456,6 +1444,24 @@ void QLabelPrivate::ensureTextPopulated() const doc->setPlainText(text); #endif doc->setUndoRedoEnabled(false); + +#ifndef QT_NO_SHORTCUT + if (hasShortcut) { + // Underline the first character that follows an ampersand (and remove the others ampersands) + int from = 0; + bool found = false; + QTextCursor cursor; + while (!(cursor = control->document()->find((QLatin1String("&")), from)).isNull()) { + cursor.deleteChar(); // remove the ampersand + cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor); + from = cursor.position(); + if (!found && cursor.selectedText() != QLatin1String("&")) { //not a second & + found = true; + shortcutCursor = cursor; + } + } + } +#endif } } textDirty = false; diff --git a/src/gui/widgets/qlabel_p.h b/src/gui/widgets/qlabel_p.h index c5a74e2..ca17a35 100644 --- a/src/gui/widgets/qlabel_p.h +++ b/src/gui/widgets/qlabel_p.h @@ -113,7 +113,7 @@ public: mutable uint hasShortcut : 1; Qt::TextFormat textformat; mutable QTextControl *control; - QTextCursor shortcutCursor; + mutable QTextCursor shortcutCursor; Qt::TextInteractionFlags textInteractionFlags; inline bool needTextControl() const { diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index 2914164..300a2ea 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -414,7 +414,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) int c = m_cursor; // cursor position after insertion of commit string - if (event->replacementStart() <= 0) + if (event->replacementStart() == 0) c += event->commitString().length() + qMin(-event->replacementStart(), event->replacementLength()); m_cursor += event->replacementStart(); diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp index 027a5d6..fa6f7a1 100644 --- a/src/gui/widgets/qmainwindowlayout.cpp +++ b/src/gui/widgets/qmainwindowlayout.cpp @@ -1641,6 +1641,9 @@ void QMainWindowLayout::animationFinished(QWidget *widget) savedState.clear(); currentGapPos.clear(); pluggingWidget = 0; + //applying the state will make sure that the currentGap is updated correctly + //and all the geometries (especially the one from the central widget) is correct + layoutState.apply(false); } if (!widgetAnimator.animating()) { diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp index 1163eba..1478b09 100644 --- a/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp +++ b/src/opengl/gl2paintengineex/qtriangulatingstroker.cpp @@ -61,6 +61,9 @@ void QTriangulatingStroker::endCapOrJoinClosed(const qreal *start, const qreal * } else { endCap(cur); } + int count = m_vertices.size(); + m_vertices.add(m_vertices.at(count-2)); + m_vertices.add(m_vertices.at(count-1)); } @@ -144,7 +147,6 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen) bool endsAtStart = startPts[0] == *(endPts-2) && startPts[1] == *(endPts-1); - Qt::PenCapStyle cap = m_cap_style; if (endsAtStart || path.hasImplicitClose()) m_cap_style = Qt::FlatCap; moveTo(pts); @@ -166,7 +168,7 @@ void QTriangulatingStroker::process(const QVectorPath &path, const QPen &pen) switch (*types) { case QPainterPath::MoveToElement: { if (pts != path.points()) - endCapOrJoinClosed(startPts, pts, path.hasImplicitClose(), endsAtStart); + endCapOrJoinClosed(startPts, pts-2, path.hasImplicitClose(), endsAtStart); startPts = pts; int end = (endPts - pts) / 2; @@ -244,8 +246,6 @@ void QTriangulatingStroker::cubicTo(const qreal *pts) m_nvy = vy; } - - static void qdashprocessor_moveTo(qreal x, qreal y, void *data) { ((QDashedStrokeProcessor *) data)->addElement(QPainterPath::MoveToElement, x, y); @@ -279,12 +279,12 @@ void QDashedStrokeProcessor::process(const QVectorPath &path, const QPen &pen) m_points.reset(); m_types.reset(); - qreal width = pen.width(); + qreal width = qpen_widthf(pen); if (width == 0) width = 1; m_dash_stroker.setDashPattern(pen.dashPattern()); - m_dash_stroker.setStrokeWidth(width); + m_dash_stroker.setStrokeWidth(pen.isCosmetic() ? width * m_inv_scale : width); m_dash_stroker.setMiterLimit(pen.miterLimit()); qreal curvyness = sqrt(width) * m_inv_scale / 8; diff --git a/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h b/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h index defa3f1..a0117d5 100644 --- a/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h +++ b/src/opengl/gl2paintengineex/qtriangulatingstroker_p.h @@ -188,10 +188,6 @@ inline void QTriangulatingStroker::endCap(const qreal *pts) break; default: break; // to shut gcc up... } - - int count = m_vertices.size(); - m_vertices.add(m_vertices.at(count-2)); - m_vertices.add(m_vertices.at(count-1)); } diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 8063fc8..f8a2ea4 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -3030,7 +3030,7 @@ void QGLContext::setValid(bool valid) bool QGLContext::isSharing() const { Q_D(const QGLContext); - return d->sharing; + return d->group->isSharing(); } QGLFormat QGLContext::format() const diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 9a17c67..45b2942 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -233,6 +233,7 @@ public: QGLExtensionFuncs &extensionFuncs() {return m_extensionFuncs;} const QGLContext *context() const {return m_context;} + bool isSharing() const { return m_shares.size() >= 2; } void addGuard(QGLSharedResourceGuard *guard); void removeGuard(QGLSharedResourceGuard *guard); diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp index 5e59975..a189c20 100644 --- a/src/opengl/qgl_qws.cpp +++ b/src/opengl/qgl_qws.cpp @@ -206,6 +206,9 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) d->eglContext = 0; return false; } + d->sharing = d->eglContext->isSharing(); + if (d->sharing && shareContext) + const_cast<QGLContext *>(shareContext)->d_func()->sharing = true; #if defined(EGL_VERSION_1_1) if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget) diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp index fea2d3a..2553110 100644 --- a/src/opengl/qgl_wince.cpp +++ b/src/opengl/qgl_wince.cpp @@ -166,6 +166,9 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) d->eglContext = 0; return false; } + d->sharing = d->eglContext->isSharing(); + if (d->sharing && shareContext) + const_cast<QGLContext *>(shareContext)->d_func()->sharing = true; #if defined(EGL_VERSION_1_1) if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget) diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 9b20297..b51c239 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -115,6 +115,9 @@ bool QGLContext::chooseContext(const QGLContext* shareContext) d->eglContext = 0; return false; } + d->sharing = d->eglContext->isSharing(); + if (d->sharing && shareContext) + const_cast<QGLContext *>(shareContext)->d_func()->sharing = true; #if defined(EGL_VERSION_1_1) if (d->glFormat.swapInterval() != -1 && devType == QInternal::Widget) diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp index fcb0ea2..c478630 100644 --- a/src/opengl/qglpixmapfilter.cpp +++ b/src/opengl/qglpixmapfilter.cpp @@ -989,7 +989,7 @@ bool QGLPixmapDropShadowFilter::processGL(QPainter *painter, const QPointF &pos, // ensure GL_LINEAR filtering is used painter->setRenderHint(QPainter::SmoothPixmapTransform); filter->setOnPainter(painter); - engine->drawTexture(targetRect, fbo->texture(), fbo->size(), src.rect().translated(0, fbo->height() - src.height())); + engine->drawTexture(targetRect, fbo->texture(), fbo->size(), QRectF(0, fbo->height() - targetRect.height(), targetRect.width(), targetRect.height())); filter->removeFromPainter(painter); painter->restore(); diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h index f552c7b..f6fac88 100644 --- a/src/openvg/qpixmapdata_vg_p.h +++ b/src/openvg/qpixmapdata_vg_p.h @@ -89,10 +89,10 @@ public: // Return the VGImage form of this pixmap, creating it if necessary. // This assumes that there is a VG context current. - VGImage toVGImage(); + virtual VGImage toVGImage(); // Return the VGImage form for a specific opacity setting. - VGImage toVGImage(qreal opacity); + virtual VGImage toVGImage(qreal opacity); QSize size() const { return QSize(w, h); } @@ -108,7 +108,7 @@ protected: void cleanup(); #endif -private: +protected: VGImage vgImage; VGImage vgImageOpacity; qreal cachedOpacity; diff --git a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp index 8756ecb..fb6f5ea 100644 --- a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp +++ b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp @@ -82,6 +82,7 @@ QTraceWindowSurface::~QTraceWindowSurface() QFile outputFile(QString(QLatin1String("qtgraphics-%0.trace")).arg(winId)); if (outputFile.open(QIODevice::WriteOnly)) { QDataStream out(&outputFile); + out.writeBytes("qttrace", 7); out << *buffer << updates; } delete buffer; diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp index 6b2f885..54bbcda 100644 --- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp +++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp @@ -196,52 +196,52 @@ inline QRgb *QImageSmoothScaler::scanLine(const int line, const QImage *src) QImage QImageSmoothScaler::scale() { - long SCALE; - long HALFSCALE; - QRgb *xelrow = 0; - QRgb *tempxelrow = 0; - QRgb *xP; - QRgb *nxP; - int row, rowsread; - int col, needtoreadrow; - uchar maxval = 255; - qreal xscale, yscale; - long sxscale, syscale; - long fracrowtofill, fracrowleft; - long *as; - long *rs; - long *gs; - long *bs; - int rowswritten = 0; - QImage dst; + long SCALE; + long HALFSCALE; + QRgb *xelrow = 0; + QRgb *tempxelrow = 0; + QRgb *xP; + QRgb *nxP; + int row, rowsread; + int col, needtoreadrow; + uchar maxval = 255; + qreal xscale, yscale; + long sxscale, syscale; + long fracrowtofill, fracrowleft; + long *as; + long *rs; + long *gs; + long *bs; + int rowswritten = 0; + QImage dst; if (d->cols > 4096) { - SCALE = 4096; - HALFSCALE = 2048; + SCALE = 4096; + HALFSCALE = 2048; } else { - int fac = 4096; - while (d->cols * fac > 4096) { - fac /= 2; - } + int fac = 4096; + while (d->cols * fac > 4096) + fac /= 2; - SCALE = fac * d->cols; - HALFSCALE = fac * d->cols / 2; + SCALE = fac * d->cols; + HALFSCALE = fac * d->cols / 2; } - xscale = (qreal) d->newcols / (qreal) d->cols; - yscale = (qreal) d->newrows / (qreal) d->rows; + xscale = (qreal)d->newcols / (qreal)d->cols; + yscale = (qreal)d->newrows / (qreal)d->rows; sxscale = (long)(xscale * SCALE); syscale = (long)(yscale * SCALE); - if ( d->newrows != d->rows ) /* shortcut Y scaling if possible */ - tempxelrow = new QRgb[d->cols]; + // shortcut Y scaling if possible + if (d->newrows != d->rows) + tempxelrow = new QRgb[d->cols]; - if ( d->hasAlpha ) { - as = new long[d->cols]; - for ( col = 0; col < d->cols; ++col ) - as[col] = HALFSCALE; + if (d->hasAlpha) { + as = new long[d->cols]; + for (col = 0; col < d->cols; ++col) + as[col] = HALFSCALE; } else { - as = 0; + as = 0; } rs = new long[d->cols]; gs = new long[d->cols]; @@ -249,205 +249,217 @@ QImage QImageSmoothScaler::scale() rowsread = 0; fracrowleft = syscale; needtoreadrow = 1; - for ( col = 0; col < d->cols; ++col ) - rs[col] = gs[col] = bs[col] = HALFSCALE; + for (col = 0; col < d->cols; ++col) + rs[col] = gs[col] = bs[col] = HALFSCALE; fracrowtofill = SCALE; - dst = QImage( d->newcols, d->newrows, d->hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32 ); - - for ( row = 0; row < d->newrows; ++row ) { - /* First scale Y from xelrow into tempxelrow. */ - if ( d->newrows == d->rows ) { - /* shortcut Y scaling if possible */ - tempxelrow = xelrow = scanLine(rowsread++, d->src); - } else { - while ( fracrowleft < fracrowtofill ) { - if ( needtoreadrow && rowsread < d->rows ) { - xelrow = scanLine(rowsread++, d->src); - } - for ( col = 0, xP = xelrow; col < d->cols; ++col, ++xP ) { - if (as) { - as[col] += fracrowleft * qAlpha( *xP ); - rs[col] += fracrowleft * qRed( *xP ) * qAlpha( *xP ) / 255; - gs[col] += fracrowleft * qGreen( *xP ) * qAlpha( *xP ) / 255; - bs[col] += fracrowleft * qBlue( *xP ) * qAlpha( *xP ) / 255; - } else { - rs[col] += fracrowleft * qRed( *xP ); - gs[col] += fracrowleft * qGreen( *xP ); - bs[col] += fracrowleft * qBlue( *xP ); - } - } - fracrowtofill -= fracrowleft; - fracrowleft = syscale; - needtoreadrow = 1; - } - /* Now fracrowleft is >= fracrowtofill, so we can produce a row. */ - if ( needtoreadrow && rowsread < d->rows) { - xelrow = scanLine(rowsread++, d->src); - needtoreadrow = 0; - } - for ( col = 0, xP = xelrow, nxP = tempxelrow; - col < d->cols; ++col, ++xP, ++nxP ) - { - register long a, r, g, b; - - if ( as ) { - r = rs[col] + fracrowtofill * qRed( *xP ) * qAlpha( *xP ) / 255; - g = gs[col] + fracrowtofill * qGreen( *xP ) * qAlpha( *xP ) / 255; - b = bs[col] + fracrowtofill * qBlue( *xP ) * qAlpha( *xP ) / 255; - a = as[col] + fracrowtofill * qAlpha( *xP ); - if ( a ) { - r = r * 255 / a * SCALE; - g = g * 255 / a * SCALE; - b = b * 255 / a * SCALE; - } - } else { - r = rs[col] + fracrowtofill * qRed( *xP ); - g = gs[col] + fracrowtofill * qGreen( *xP ); - b = bs[col] + fracrowtofill * qBlue( *xP ); - a = 0; // unwarn - } - r /= SCALE; - if ( r > maxval ) r = maxval; - g /= SCALE; - if ( g > maxval ) g = maxval; - b /= SCALE; - if ( b > maxval ) b = maxval; - if ( as ) { - a /= SCALE; - if ( a > maxval ) a = maxval; - *nxP = qRgba( (int)r, (int)g, (int)b, (int)a ); - as[col] = HALFSCALE; - } else { - *nxP = qRgb( (int)r, (int)g, (int)b ); - } - rs[col] = gs[col] = bs[col] = HALFSCALE; - } - fracrowleft -= fracrowtofill; - if ( fracrowleft == 0 ) { - fracrowleft = syscale; - needtoreadrow = 1; - } - fracrowtofill = SCALE; - } + dst = QImage(d->newcols, d->newrows, d->hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32); - /* Now scale X from tempxelrow into dst and write it out. */ - if ( d->newcols == d->cols ) { - /* shortcut X scaling if possible */ - memcpy(dst.scanLine(rowswritten++), tempxelrow, d->newcols*4); - } else { - register long a, r, g, b; - register long fraccoltofill, fraccolleft = 0; - register int needcol; - - nxP = (QRgb*)dst.scanLine(rowswritten++); - fraccoltofill = SCALE; - a = r = g = b = HALFSCALE; - needcol = 0; - for ( col = 0, xP = tempxelrow; col < d->cols; ++col, ++xP ) { - fraccolleft = sxscale; - while ( fraccolleft >= fraccoltofill ) { - if ( needcol ) { - ++nxP; - a = r = g = b = HALFSCALE; - } - if ( as ) { - r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255; - g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255; - b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255; - a += fraccoltofill * qAlpha( *xP ); - if ( a ) { - r = r * 255 / a * SCALE; - g = g * 255 / a * SCALE; - b = b * 255 / a * SCALE; - } - } else { - r += fraccoltofill * qRed( *xP ); - g += fraccoltofill * qGreen( *xP ); - b += fraccoltofill * qBlue( *xP ); - } - r /= SCALE; - if ( r > maxval ) r = maxval; - g /= SCALE; - if ( g > maxval ) g = maxval; - b /= SCALE; - if ( b > maxval ) b = maxval; - if (as) { - a /= SCALE; - if ( a > maxval ) a = maxval; - *nxP = qRgba( (int)r, (int)g, (int)b, (int)a ); - } else { - *nxP = qRgb( (int)r, (int)g, (int)b ); - } - fraccolleft -= fraccoltofill; - fraccoltofill = SCALE; - needcol = 1; - } - if ( fraccolleft > 0 ) { - if ( needcol ) { - ++nxP; - a = r = g = b = HALFSCALE; - needcol = 0; - } - if (as) { - a += fraccolleft * qAlpha( *xP ); - r += fraccolleft * qRed( *xP ) * qAlpha( *xP ) / 255; - g += fraccolleft * qGreen( *xP ) * qAlpha( *xP ) / 255; - b += fraccolleft * qBlue( *xP ) * qAlpha( *xP ) / 255; - } else { - r += fraccolleft * qRed( *xP ); - g += fraccolleft * qGreen( *xP ); - b += fraccolleft * qBlue( *xP ); - } - fraccoltofill -= fraccolleft; - } - } - if ( fraccoltofill > 0 ) { - --xP; - if (as) { - a += fraccolleft * qAlpha( *xP ); - r += fraccoltofill * qRed( *xP ) * qAlpha( *xP ) / 255; - g += fraccoltofill * qGreen( *xP ) * qAlpha( *xP ) / 255; - b += fraccoltofill * qBlue( *xP ) * qAlpha( *xP ) / 255; - if ( a ) { - r = r * 255 / a * SCALE; - g = g * 255 / a * SCALE; - b = b * 255 / a * SCALE; - } - } else { - r += fraccoltofill * qRed( *xP ); - g += fraccoltofill * qGreen( *xP ); - b += fraccoltofill * qBlue( *xP ); - } - } - if ( ! needcol ) { - r /= SCALE; - if ( r > maxval ) r = maxval; - g /= SCALE; - if ( g > maxval ) g = maxval; - b /= SCALE; - if ( b > maxval ) b = maxval; - if (as) { - a /= SCALE; - if ( a > maxval ) a = maxval; - *nxP = qRgba( (int)r, (int)g, (int)b, (int)a ); - } else { - *nxP = qRgb( (int)r, (int)g, (int)b ); - } - } - } + for (row = 0; row < d->newrows; ++row) { + // First scale Y from xelrow into tempxelrow. + if (d->newrows == d->rows) { + // shortcut Y scaling if possible + tempxelrow = xelrow = scanLine(rowsread++, d->src); + } else { + while (fracrowleft < fracrowtofill) { + if (needtoreadrow && rowsread < d->rows) + xelrow = scanLine(rowsread++, d->src); + for (col = 0, xP = xelrow; col < d->cols; ++col, ++xP) { + if (as) { + as[col] += fracrowleft * qAlpha(*xP); + rs[col] += fracrowleft * qRed(*xP) * qAlpha(*xP) / 255; + gs[col] += fracrowleft * qGreen(*xP) * qAlpha(*xP) / 255; + bs[col] += fracrowleft * qBlue(*xP) * qAlpha(*xP) / 255; + } else { + rs[col] += fracrowleft * qRed(*xP); + gs[col] += fracrowleft * qGreen(*xP); + bs[col] += fracrowleft * qBlue(*xP); + } + } + fracrowtofill -= fracrowleft; + fracrowleft = syscale; + needtoreadrow = 1; + } + // Now fracrowleft is >= fracrowtofill, so we can produce a row. + if (needtoreadrow && rowsread < d->rows) { + xelrow = scanLine(rowsread++, d->src); + needtoreadrow = 0; + } + for (col = 0, xP = xelrow, nxP = tempxelrow; col < d->cols; ++col, ++xP, ++nxP) { + register long a, r, g, b; + + if (as) { + r = rs[col] + fracrowtofill * qRed(*xP) * qAlpha(*xP) / 255; + g = gs[col] + fracrowtofill * qGreen(*xP) * qAlpha(*xP) / 255; + b = bs[col] + fracrowtofill * qBlue(*xP) * qAlpha(*xP) / 255; + a = as[col] + fracrowtofill * qAlpha(*xP); + if (a) { + r = r * 255 / a * SCALE; + g = g * 255 / a * SCALE; + b = b * 255 / a * SCALE; + } + } else { + r = rs[col] + fracrowtofill * qRed(*xP); + g = gs[col] + fracrowtofill * qGreen(*xP); + b = bs[col] + fracrowtofill * qBlue(*xP); + a = 0; // unwarn + } + r /= SCALE; + if (r > maxval) + r = maxval; + g /= SCALE; + if (g > maxval) + g = maxval; + b /= SCALE; + if (b > maxval) + b = maxval; + if (as) { + a /= SCALE; + if (a > maxval) + a = maxval; + *nxP = qRgba((int)r, (int)g, (int)b, (int)a); + as[col] = HALFSCALE; + } else { + *nxP = qRgb((int)r, (int)g, (int)b); + } + rs[col] = gs[col] = bs[col] = HALFSCALE; + } + fracrowleft -= fracrowtofill; + if (fracrowleft == 0) { + fracrowleft = syscale; + needtoreadrow = 1; + } + fracrowtofill = SCALE; + } + + // Now scale X from tempxelrow into dst and write it out. + if (d->newcols == d->cols) { + // shortcut X scaling if possible + memcpy(dst.scanLine(rowswritten++), tempxelrow, d->newcols * 4); + } else { + register long a, r, g, b; + register long fraccoltofill, fraccolleft = 0; + register int needcol; + + nxP = (QRgb *)dst.scanLine(rowswritten++); + QRgb *nxPEnd = nxP + d->newcols; + fraccoltofill = SCALE; + a = r = g = b = HALFSCALE; + needcol = 0; + for (col = 0, xP = tempxelrow; col < d->cols; ++col, ++xP) { + fraccolleft = sxscale; + while (fraccolleft >= fraccoltofill) { + if (needcol) { + ++nxP; + a = r = g = b = HALFSCALE; + } + if (as) { + r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255; + g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255; + b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255; + a += fraccoltofill * qAlpha(*xP); + if (a) { + r = r * 255 / a * SCALE; + g = g * 255 / a * SCALE; + b = b * 255 / a * SCALE; + } + } else { + r += fraccoltofill * qRed(*xP); + g += fraccoltofill * qGreen(*xP); + b += fraccoltofill * qBlue(*xP); + } + r /= SCALE; + if (r > maxval) + r = maxval; + g /= SCALE; + if (g > maxval) + g = maxval; + b /= SCALE; + if (b > maxval) + b = maxval; + if (as) { + a /= SCALE; + if (a > maxval) + a = maxval; + *nxP = qRgba((int)r, (int)g, (int)b, (int)a); + } else { + *nxP = qRgb((int)r, (int)g, (int)b); + } + fraccolleft -= fraccoltofill; + fraccoltofill = SCALE; + needcol = 1; + } + if (fraccolleft > 0) { + if (needcol) { + ++nxP; + a = r = g = b = HALFSCALE; + needcol = 0; + } + if (as) { + a += fraccolleft * qAlpha(*xP); + r += fraccolleft * qRed(*xP) * qAlpha(*xP) / 255; + g += fraccolleft * qGreen(*xP) * qAlpha(*xP) / 255; + b += fraccolleft * qBlue(*xP) * qAlpha(*xP) / 255; + } else { + r += fraccolleft * qRed(*xP); + g += fraccolleft * qGreen(*xP); + b += fraccolleft * qBlue(*xP); + } + fraccoltofill -= fraccolleft; + } + } + if (fraccoltofill > 0) { + --xP; + if (as) { + a += fraccolleft * qAlpha(*xP); + r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255; + g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255; + b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255; + if (a) { + r = r * 255 / a * SCALE; + g = g * 255 / a * SCALE; + b = b * 255 / a * SCALE; + } + } else { + r += fraccoltofill * qRed(*xP); + g += fraccoltofill * qGreen(*xP); + b += fraccoltofill * qBlue(*xP); + } + } + if (nxP < nxPEnd) { + r /= SCALE; + if (r > maxval) + r = maxval; + g /= SCALE; + if (g > maxval) + g = maxval; + b /= SCALE; + if (b > maxval) + b = maxval; + if (as) { + a /= SCALE; + if (a > maxval) + a = maxval; + *nxP = qRgba((int)r, (int)g, (int)b, (int)a); + } else { + *nxP = qRgb((int)r, (int)g, (int)b); + } + while (++nxP != nxPEnd) + nxP[0] = nxP[-1]; + } + } } - if ( d->newrows != d->rows && tempxelrow )// Robust, tempxelrow might be 0 1 day - delete [] tempxelrow; - if ( as ) // Avoid purify complaint - delete [] as; - if ( rs ) // Robust, rs might be 0 one day - delete [] rs; - if ( gs ) // Robust, gs might be 0 one day - delete [] gs; - if ( bs ) // Robust, bs might be 0 one day - delete [] bs; + if (d->newrows != d->rows && tempxelrow)// Robust, tempxelrow might be 0 1 day + delete [] tempxelrow; + if (as) // Avoid purify complaint + delete [] as; + if (rs) // Robust, rs might be 0 one day + delete [] rs; + if (gs) // Robust, gs might be 0 one day + delete [] gs; + if (bs) // Robust, bs might be 0 one day + delete [] bs; return dst; } diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp index 3669be7..9538745 100644 --- a/src/plugins/imageformats/tiff/qtiffhandler.cpp +++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp @@ -192,7 +192,14 @@ bool QTiffHandler::read(QImage *image) return false; } - if (photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE) { + uint16 bitPerSample; + if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { + TIFFClose(tiff); + return false; + } + + bool grayscale = photometric == PHOTOMETRIC_MINISBLACK || photometric == PHOTOMETRIC_MINISWHITE; + if (grayscale && bitPerSample == 1) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Mono) *image = QImage(width, height, QImage::Format_Mono); QVector<QRgb> colortable(2); @@ -208,42 +215,43 @@ bool QTiffHandler::read(QImage *image) if (!image->isNull()) { for (uint32 y=0; y<height; ++y) { if (TIFFReadScanline(tiff, image->scanLine(y), y, 0) < 0) { - TIFFClose(tiff); - return false; + TIFFClose(tiff); + return false; } } } } else { - uint16 bitPerSample; - if (!TIFFGetField(tiff, TIFFTAG_BITSPERSAMPLE, &bitPerSample)) { - TIFFClose(tiff); - return false; - } - if (photometric == PHOTOMETRIC_PALETTE && bitPerSample == 8) { + if ((grayscale || photometric == PHOTOMETRIC_PALETTE) && bitPerSample == 8) { if (image->size() != QSize(width, height) || image->format() != QImage::Format_Indexed8) *image = QImage(width, height, QImage::Format_Indexed8); if (!image->isNull()) { - // create the color table const uint16 tableSize = 256; - uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); - uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); - uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); - if (!redTable || !greenTable || !blueTable) { - TIFFClose(tiff); - return false; - } - if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { - TIFFClose(tiff); - return false; - } - QVector<QRgb> qtColorTable(tableSize); - for (int i = 0; i<tableSize ;++i) { - const int red = redTable[i] / 257; - const int green = greenTable[i] / 257; - const int blue = blueTable[i] / 257; - qtColorTable[i] = qRgb(red, green, blue); + if (grayscale) { + for (int i = 0; i<tableSize; ++i) { + const int c = (photometric == PHOTOMETRIC_MINISBLACK) ? i : (255 - i); + qtColorTable[i] = qRgb(c, c, c); + } + } else { + // create the color table + uint16 *redTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + uint16 *greenTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + uint16 *blueTable = static_cast<uint16 *>(qMalloc(tableSize * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } + if (!TIFFGetField(tiff, TIFFTAG_COLORMAP, &redTable, &greenTable, &blueTable)) { + TIFFClose(tiff); + return false; + } + for (int i = 0; i<tableSize ;++i) { + const int red = redTable[i] / 257; + const int green = greenTable[i] / 257; + const int blue = blueTable[i] / 257; + qtColorTable[i] = qRgb(red, green, blue); + } } image->setColorTable(qtColorTable); @@ -371,6 +379,20 @@ bool QTiffHandler::read(QImage *image) return true; } +static bool checkGrayscale(const QVector<QRgb> &colorTable) +{ + if (colorTable.size() != 256) + return false; + + const bool increasing = (colorTable.at(0) == 0xff000000); + for (int i = 0; i < 256; ++i) { + if (increasing && colorTable.at(i) != qRgb(i, i, i) + || !increasing && colorTable.at(i) != qRgb(255 - i, 255 - i, 255 - i)) + return false; + } + return true; +} + bool QTiffHandler::write(const QImage &image) { if (!device()->isWritable()) @@ -425,7 +447,8 @@ bool QTiffHandler::write(const QImage &image) if (image.colorTable().at(0) == 0xffffffff) photometric = PHOTOMETRIC_MINISWHITE; if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) - || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE)) { + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_CCITTRLE) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 1)) { TIFFClose(tiff); return false; } @@ -450,43 +473,55 @@ bool QTiffHandler::write(const QImage &image) } TIFFClose(tiff); } else if (format == QImage::Format_Indexed8) { - if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) - || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) - || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { - TIFFClose(tiff); - return false; - } - //// write the color table - // allocate the color tables - uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); - uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); - uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); - if (!redTable || !greenTable || !blueTable) { - TIFFClose(tiff); - return false; - } - - // set the color table const QVector<QRgb> colorTable = image.colorTable(); + bool isGrayscale = checkGrayscale(colorTable); + if (isGrayscale) { + uint16 photometric = PHOTOMETRIC_MINISBLACK; + if (image.colorTable().at(0) == 0xffffffff) + photometric = PHOTOMETRIC_MINISWHITE; + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, photometric) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } + } else { + if (!TIFFSetField(tiff, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_PALETTE) + || !TIFFSetField(tiff, TIFFTAG_COMPRESSION, compression == NoCompression ? COMPRESSION_NONE : COMPRESSION_PACKBITS) + || !TIFFSetField(tiff, TIFFTAG_BITSPERSAMPLE, 8)) { + TIFFClose(tiff); + return false; + } + //// write the color table + // allocate the color tables + uint16 *redTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + uint16 *greenTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + uint16 *blueTable = static_cast<uint16 *>(qMalloc(256 * sizeof(uint16))); + if (!redTable || !greenTable || !blueTable) { + TIFFClose(tiff); + return false; + } - const int tableSize = colorTable.size(); - Q_ASSERT(tableSize <= 256); - for (int i = 0; i<tableSize; ++i) { - const QRgb color = colorTable.at(i); - redTable[i] = qRed(color) * 257; - greenTable[i] = qGreen(color) * 257; - blueTable[i] = qBlue(color) * 257; - } + // set the color table + const int tableSize = colorTable.size(); + Q_ASSERT(tableSize <= 256); + for (int i = 0; i<tableSize; ++i) { + const QRgb color = colorTable.at(i); + redTable[i] = qRed(color) * 257; + greenTable[i] = qGreen(color) * 257; + blueTable[i] = qBlue(color) * 257; + } - const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); + const bool setColorTableSuccess = TIFFSetField(tiff, TIFFTAG_COLORMAP, redTable, greenTable, blueTable); - qFree(redTable); - qFree(greenTable); - qFree(blueTable); + qFree(redTable); + qFree(greenTable); + qFree(blueTable); - if (!setColorTableSuccess) { - TIFFClose(tiff); - return false; + if (!setColorTableSuccess) { + TIFFClose(tiff); + return false; + } } //// write the data diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index f834016..57927fd 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -363,7 +363,10 @@ void QSvgStrokeStyle::apply(QPainter *p, const QRectF &, QSvgNode *, QSvgExtraSt if (m_strokeMiterLimitSet) pen.setMiterLimit(m_stroke.miterLimit()); - if (setDashOffsetNeeded) { + // You can have dash offset on solid strokes in SVG files, but not in Qt. + // QPen::setDashOffset() will set the pen style to Qt::CustomDashLine, + // so don't call the method if the pen is solid. + if (setDashOffsetNeeded && pen.style() != Qt::SolidLine) { qreal currentWidth = pen.widthF(); if (currentWidth == 0) currentWidth = 1; diff --git a/src/xmlpatterns/data/qderivedinteger_p.h b/src/xmlpatterns/data/qderivedinteger_p.h index 859e03d..19dc4c4 100644 --- a/src/xmlpatterns/data/qderivedinteger_p.h +++ b/src/xmlpatterns/data/qderivedinteger_p.h @@ -401,18 +401,18 @@ namespace QPatternist { return ValidationError::createError(QtXmlPatterns::tr( "Value %1 of type %2 exceeds maximum (%3).") - .arg(formatData(static_cast<xsInteger>(num))) + .arg(QPatternist::formatData(static_cast<xsInteger>(num))) .arg(formatType(np, itemType())) - .arg(formatData(static_cast<xsInteger>(maxInclusive)))); + .arg(QPatternist::formatData(static_cast<xsInteger>(maxInclusive)))); } else if((limitsUsage & LimitDownwards) && lessThan(num, minimum)) { return ValidationError::createError(QtXmlPatterns::tr( "Value %1 of type %2 is below minimum (%3).") - .arg(formatData(static_cast<xsInteger>(num))) + .arg(QPatternist::formatData(static_cast<xsInteger>(num))) .arg(formatType(np, itemType())) - .arg(formatData(static_cast<xsInteger>(minInclusive)))); + .arg(QPatternist::formatData(static_cast<xsInteger>(minInclusive)))); } else return AtomicValue::Ptr(new DerivedInteger(num)); diff --git a/src/xmlpatterns/functions/qcomparingaggregator.cpp b/src/xmlpatterns/functions/qcomparingaggregator.cpp index 6d07109..acda08c 100644 --- a/src/xmlpatterns/functions/qcomparingaggregator.cpp +++ b/src/xmlpatterns/functions/qcomparingaggregator.cpp @@ -195,7 +195,7 @@ ComparingAggregator<oper, result>::typeCheck(const StaticContext::Ptr &context, !BuiltinTypes::xsYearMonthDuration->xdtTypeMatches(t1)) { context->error(QtXmlPatterns::tr("The first argument to %1 cannot be of type %2.") - .arg(formatFunction(context->namePool(), signature())) + .arg(QPatternist::formatFunction(context->namePool(), signature())) .arg(formatType(context->namePool(), m_operands.first()->staticType())), ReportContext::FORG0006, this); return me; diff --git a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp index bdc31af..413419d 100644 --- a/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp +++ b/tests/auto/qabstractitemmodel/tst_qabstractitemmodel.cpp @@ -865,15 +865,22 @@ void tst_QAbstractItemModel::testMoveSameParentDown_data() QTest::addColumn<int>("startRow"); QTest::addColumn<int>("endRow"); QTest::addColumn<int>("destRow"); + // We can't put the actual parent index for the move in here because m_model is not defined until init() is run. + QTest::addColumn<bool>("topLevel"); // Move from the start to the middle - QTest::newRow("move01") << 0 << 2 << 8; + QTest::newRow("move01") << 0 << 2 << 8 << true; // Move from the start to the end - QTest::newRow("move02") << 0 << 2 << 10; + QTest::newRow("move02") << 0 << 2 << 10 << true; // Move from the middle to the middle - QTest::newRow("move03") << 3 << 5 << 8; + QTest::newRow("move03") << 3 << 5 << 8 << true; // Move from the middle to the end - QTest::newRow("move04") << 3 << 5 << 10; + QTest::newRow("move04") << 3 << 5 << 10 << true; + + QTest::newRow("move05") << 0 << 2 << 8 << false; + QTest::newRow("move06") << 0 << 2 << 10 << false; + QTest::newRow("move07") << 3 << 5 << 8 << false; + QTest::newRow("move08") << 3 << 5 << 10 << false; } void tst_QAbstractItemModel::testMoveSameParentDown() @@ -881,6 +888,9 @@ void tst_QAbstractItemModel::testMoveSameParentDown() QFETCH( int, startRow); QFETCH( int, endRow); QFETCH( int, destRow); + QFETCH( bool, topLevel); + + QModelIndex moveParent = topLevel ? QModelIndex() : m_model->index(5, 0); QList<QPersistentModelIndex> persistentList; QModelIndexList indexList; @@ -913,33 +923,37 @@ void tst_QAbstractItemModel::testMoveSameParentDown() ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); moveCommand->setNumCols(4); + if (!topLevel) + moveCommand->setAncestorRowNumbers(QList<int>() << 5); moveCommand->setStartRow(startRow); moveCommand->setEndRow(endRow); moveCommand->setDestRow(destRow); + if (!topLevel) + moveCommand->setDestAncestors(QList<int>() << 5); moveCommand->doCommand(); QVariantList beforeSignal = beforeSpy.takeAt(0); QVariantList afterSignal = afterSpy.takeAt(0); QCOMPARE(beforeSignal.size(), 5); - QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), moveParent); QCOMPARE(beforeSignal.at(1).toInt(), startRow); QCOMPARE(beforeSignal.at(2).toInt(), endRow); - QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), moveParent); QCOMPARE(beforeSignal.at(4).toInt(), destRow); QCOMPARE(afterSignal.size(), 5); - QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex()); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), moveParent); QCOMPARE(afterSignal.at(1).toInt(), startRow); QCOMPARE(afterSignal.at(2).toInt(), endRow); - QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), moveParent); QCOMPARE(afterSignal.at(4).toInt(), destRow); for (int i = 0; i < indexList.size(); i++) { QModelIndex idx = indexList.at(i); QModelIndex persistentIndex = persistentList.at(i); - if (idx.parent() == QModelIndex()) + if (idx.parent() == moveParent) { int row = idx.row(); if ( row >= startRow) @@ -976,15 +990,21 @@ void tst_QAbstractItemModel::testMoveSameParentUp_data() QTest::addColumn<int>("startRow"); QTest::addColumn<int>("endRow"); QTest::addColumn<int>("destRow"); + QTest::addColumn<bool>("topLevel"); // Move from the middle to the start - QTest::newRow("move01") << 5 << 7 << 0; + QTest::newRow("move01") << 5 << 7 << 0 << true; // Move from the end to the start - QTest::newRow("move02") << 8 << 9 << 0; + QTest::newRow("move02") << 8 << 9 << 0 << true; // Move from the middle to the middle - QTest::newRow("move03") << 5 << 7 << 2; + QTest::newRow("move03") << 5 << 7 << 2 << true; // Move from the end to the middle - QTest::newRow("move04") << 8 << 9 << 5; + QTest::newRow("move04") << 8 << 9 << 5 << true; + + QTest::newRow("move05") << 5 << 7 << 0 << false; + QTest::newRow("move06") << 8 << 9 << 0 << false; + QTest::newRow("move07") << 5 << 7 << 2 << false; + QTest::newRow("move08") << 8 << 9 << 5 << false; } void tst_QAbstractItemModel::testMoveSameParentUp() @@ -993,6 +1013,9 @@ void tst_QAbstractItemModel::testMoveSameParentUp() QFETCH( int, startRow); QFETCH( int, endRow); QFETCH( int, destRow); + QFETCH( bool, topLevel); + + QModelIndex moveParent = topLevel ? QModelIndex() : m_model->index(5, 0); QList<QPersistentModelIndex> persistentList; QModelIndexList indexList; @@ -1026,26 +1049,30 @@ void tst_QAbstractItemModel::testMoveSameParentUp() ModelMoveCommand *moveCommand = new ModelMoveCommand(m_model, this); moveCommand->setNumCols(4); + if (!topLevel) + moveCommand->setAncestorRowNumbers(QList<int>() << 5); moveCommand->setStartRow(startRow); moveCommand->setEndRow(endRow); moveCommand->setDestRow(destRow); + if (!topLevel) + moveCommand->setDestAncestors(QList<int>() << 5); moveCommand->doCommand(); QVariantList beforeSignal = beforeSpy.takeAt(0); QVariantList afterSignal = afterSpy.takeAt(0); QCOMPARE(beforeSignal.size(), 5); - QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(0).value<QModelIndex>(), moveParent); QCOMPARE(beforeSignal.at(1).toInt(), startRow); QCOMPARE(beforeSignal.at(2).toInt(), endRow); - QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(beforeSignal.at(3).value<QModelIndex>(), moveParent); QCOMPARE(beforeSignal.at(4).toInt(), destRow); QCOMPARE(afterSignal.size(), 5); - QCOMPARE(afterSignal.at(0).value<QModelIndex>(), QModelIndex()); + QCOMPARE(afterSignal.at(0).value<QModelIndex>(), moveParent); QCOMPARE(afterSignal.at(1).toInt(), startRow); QCOMPARE(afterSignal.at(2).toInt(), endRow); - QCOMPARE(afterSignal.at(3).value<QModelIndex>(), QModelIndex()); + QCOMPARE(afterSignal.at(3).value<QModelIndex>(), moveParent); QCOMPARE(afterSignal.at(4).toInt(), destRow); @@ -1053,7 +1080,7 @@ void tst_QAbstractItemModel::testMoveSameParentUp() { QModelIndex idx = indexList.at(i); QModelIndex persistentIndex = persistentList.at(i); - if (idx.parent() == QModelIndex()) + if (idx.parent() == moveParent) { int row = idx.row(); if ( row >= destRow) diff --git a/tests/auto/qabstractslider/tst_qabstractslider.cpp b/tests/auto/qabstractslider/tst_qabstractslider.cpp index d9574df..ee1ba19 100644 --- a/tests/auto/qabstractslider/tst_qabstractslider.cpp +++ b/tests/auto/qabstractslider/tst_qabstractslider.cpp @@ -742,11 +742,9 @@ void tst_QAbstractSlider::wheelEvent_data() << 1 // delta << int(Qt::Horizontal) // orientation of slider << int(Qt::Vertical) // orientation of wheel - << 0 // expected position after + << 1 // expected position after << QPoint(1,1); - // Scrolling in a slider of a different orientation than the wheel works - // if the mouse pointer is within the widget's rect QTest::newRow("Different orientation2")<< 0 // initial position << 0 // minimum << 100 // maximum diff --git a/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp b/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp index 381f46f..a57c1d6 100644 --- a/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp +++ b/tests/auto/qcalendarwidget/tst_qcalendarwidget.cpp @@ -75,6 +75,8 @@ private slots: void resetTextFormat(); void setWeekdayFormat(); + void showPrevNext_data(); + void showPrevNext(); }; // Testing get/set functions @@ -293,5 +295,73 @@ void tst_QCalendarWidget::cleanup() { } + +typedef void (QCalendarWidget::*ShowFunc)(); +Q_DECLARE_METATYPE(ShowFunc) + +void tst_QCalendarWidget::showPrevNext_data() +{ + QTest::addColumn<ShowFunc>("function"); + QTest::addColumn<QDate>("dateOrigin"); + QTest::addColumn<QDate>("expectedDate"); + + QTest::newRow("showNextMonth") << &QCalendarWidget::showNextMonth << QDate(1984,7,30) << QDate(1984,8,30); + QTest::newRow("showPrevMonth") << &QCalendarWidget::showPreviousMonth << QDate(1984,7,30) << QDate(1984,6,30); + QTest::newRow("showNextYear") << &QCalendarWidget::showNextYear << QDate(1984,7,30) << QDate(1985,7,30); + QTest::newRow("showPrevYear") << &QCalendarWidget::showPreviousYear << QDate(1984,7,30) << QDate(1983,7,30); + + QTest::newRow("showNextMonth limit") << &QCalendarWidget::showNextMonth << QDate(2007,12,4) << QDate(2008,1,4); + QTest::newRow("showPreviousMonth limit") << &QCalendarWidget::showPreviousMonth << QDate(2006,1,23) << QDate(2005,12,23); + + QTest::newRow("showNextMonth now") << &QCalendarWidget::showNextMonth << QDate() << QDate::currentDate().addMonths(1); + QTest::newRow("showNextYear now") << &QCalendarWidget::showNextYear << QDate() << QDate::currentDate().addYears(1); + QTest::newRow("showPrevieousMonth now") << &QCalendarWidget::showPreviousMonth << QDate() << QDate::currentDate().addMonths(-1); + QTest::newRow("showPreviousYear now") << &QCalendarWidget::showPreviousYear << QDate() << QDate::currentDate().addYears(-1); + + QTest::newRow("showToday now") << &QCalendarWidget::showToday << QDate(2000,1,31) << QDate::currentDate(); + QTest::newRow("showNextMonth 31") << &QCalendarWidget::showNextMonth << QDate(2000,1,31) << QDate(2000,2,28); + QTest::newRow("selectedDate") << &QCalendarWidget::showSelectedDate << QDate(2008,2,29) << QDate(2008,2,29); + +} + +void tst_QCalendarWidget::showPrevNext() +{ + QFETCH(ShowFunc, function); + QFETCH(QDate, dateOrigin); + QFETCH(QDate, expectedDate); + + QCalendarWidget calWidget; + calWidget.show(); + QTest::qWaitForWindowShown(&calWidget); + if(!dateOrigin.isNull()) { + calWidget.setSelectedDate(dateOrigin); + calWidget.setCurrentPage(dateOrigin.year(), dateOrigin.month()); + + QCOMPARE(calWidget.yearShown(), dateOrigin.year()); + QCOMPARE(calWidget.monthShown(), dateOrigin.month()); + } else { + QCOMPARE(calWidget.yearShown(), QDate::currentDate().year()); + QCOMPARE(calWidget.monthShown(), QDate::currentDate().month()); + } + + (calWidget.*function)(); + + QCOMPARE(calWidget.yearShown(), expectedDate.year()); + QCOMPARE(calWidget.monthShown(), expectedDate.month()); + + // QTBUG-4058 + QTest::qWait(20); + QToolButton *button = qFindChild<QToolButton *>(&calWidget, "qt_calendar_prevmonth"); + QTest::mouseClick(button, Qt::LeftButton); + expectedDate = expectedDate.addMonths(-1); + QCOMPARE(calWidget.yearShown(), expectedDate.year()); + QCOMPARE(calWidget.monthShown(), expectedDate.month()); + + if(!dateOrigin.isNull()) { + //the selectedDate should not have changed + QCOMPARE(calWidget.selectedDate(), dateOrigin); + } +} + QTEST_MAIN(tst_QCalendarWidget) #include "tst_qcalendarwidget.moc" diff --git a/tests/auto/qdockwidget/tst_qdockwidget.cpp b/tests/auto/qdockwidget/tst_qdockwidget.cpp index c9a7f1c..8f72e39 100644 --- a/tests/auto/qdockwidget/tst_qdockwidget.cpp +++ b/tests/auto/qdockwidget/tst_qdockwidget.cpp @@ -50,6 +50,7 @@ #include <qlineedit.h> #include <QDesktopWidget> #include <QtGui/QPainter> +#include "private/qdockwidget_p.h" bool hasFeature(QDockWidget *dockwidget, QDockWidget::DockWidgetFeature feature) { return (dockwidget->features() & feature) == feature; } @@ -865,7 +866,9 @@ void tst_QDockWidget::taskQTBUG_1665_closableChanged() dock.show(); QTest::qWaitForWindowShown(&dock); - if (dock.windowFlags() & Qt::FramelessWindowHint) + QDockWidgetLayout *l = qobject_cast<QDockWidgetLayout*>(dock.layout()); + + if (l && !l->nativeWindowDeco()) QSKIP("this machine doesn't support native dock widget", SkipAll); QVERIFY(dock.windowFlags() & Qt::WindowCloseButtonHint); diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp index c680dec..5dc072d 100644 --- a/tests/auto/qgl/tst_qgl.cpp +++ b/tests/auto/qgl/tst_qgl.cpp @@ -76,6 +76,7 @@ private slots: void partialGLWidgetUpdates_data(); void partialGLWidgetUpdates(); void glWidgetRendering(); + void glFBOSimpleRendering(); void glFBORendering(); void multipleFBOInterleavedRendering(); void glFBOUseInGLWidget(); @@ -711,6 +712,79 @@ void tst_QGL::openGLVersionCheck() #endif //QT_BUILD_INTERNAL } +static bool fuzzyComparePixels(const QRgb testPixel, const QRgb refPixel, const char* file, int line, int x = -1, int y = -1) +{ + static int maxFuzz = 1; + static bool maxFuzzSet = false; + + // On 16 bpp systems, we need to allow for more fuzz: + if (!maxFuzzSet) { + maxFuzzSet = true; + if (appDefaultDepth() < 24) + maxFuzz = 32; + } + + int redFuzz = qAbs(qRed(testPixel) - qRed(refPixel)); + int greenFuzz = qAbs(qGreen(testPixel) - qGreen(refPixel)); + int blueFuzz = qAbs(qBlue(testPixel) - qBlue(refPixel)); + int alphaFuzz = qAbs(qAlpha(testPixel) - qAlpha(refPixel)); + + if (refPixel != 0 && testPixel == 0) { + QString msg; + if (x >= 0) { + msg = QString("Test pixel [%1, %2] is null (black) when it should be (%3,%4,%5,%6)") + .arg(x).arg(y) + .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel)); + } else { + msg = QString("Test pixel is null (black) when it should be (%2,%3,%4,%5)") + .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel)); + } + + QTest::qFail(msg.toLatin1(), file, line); + return false; + } + + if (redFuzz > maxFuzz || greenFuzz > maxFuzz || blueFuzz > maxFuzz || alphaFuzz > maxFuzz) { + QString msg; + + if (x >= 0) + msg = QString("Pixel [%1,%2]: ").arg(x).arg(y); + else + msg = QString("Pixel "); + + msg += QString("Max fuzz (%1) exceeded: (%2,%3,%4,%5) vs (%6,%7,%8,%9)") + .arg(maxFuzz) + .arg(qRed(testPixel)).arg(qGreen(testPixel)).arg(qBlue(testPixel)).arg(qAlpha(testPixel)) + .arg(qRed(refPixel)).arg(qGreen(refPixel)).arg(qBlue(refPixel)).arg(qAlpha(refPixel)); + QTest::qFail(msg.toLatin1(), file, line); + return false; + } + return true; +} + +static void fuzzyCompareImages(const QImage &testImage, const QImage &referenceImage, const char* file, int line) +{ + QCOMPARE(testImage.width(), referenceImage.width()); + QCOMPARE(testImage.height(), referenceImage.height()); + + for (int y = 0; y < testImage.height(); y++) { + for (int x = 0; x < testImage.width(); x++) { + if (!fuzzyComparePixels(testImage.pixel(x, y), referenceImage.pixel(x, y), file, line, x, y)) { + // Might as well save the images for easier debugging: + referenceImage.save("referenceImage.png"); + testImage.save("testImage.png"); + return; + } + } + } +} + +#define QFUZZY_COMPARE_IMAGES(A,B) \ + fuzzyCompareImages(A, B, __FILE__, __LINE__) + +#define QFUZZY_COMPARE_PIXELS(A,B) \ + fuzzyComparePixels(A, B, __FILE__, __LINE__) + class UnclippedWidget : public QWidget { public: @@ -723,8 +797,6 @@ public: void tst_QGL::graphicsViewClipping() { - if (appDefaultDepth() < 24) - QSKIP("This test won't work for bit depths < 24", SkipAll); const int size = 64; UnclippedWidget *widget = new UnclippedWidget; widget->setFixedSize(size, size); @@ -734,6 +806,9 @@ void tst_QGL::graphicsViewClipping() scene.addWidget(widget)->setPos(0, 0); QGraphicsView view(&scene); +#ifdef Q_WS_QWS + view.setWindowFlags(Qt::FramelessWindowHint); +#endif view.resize(2*size, 2*size); QGLWidget *viewport = new QGLWidget; @@ -758,7 +833,7 @@ void tst_QGL::graphicsViewClipping() p.fillRect(QRect(0, 0, size, size), Qt::black); p.end(); - QCOMPARE(image, expected); + QFUZZY_COMPARE_IMAGES(image, expected); } void tst_QGL::partialGLWidgetUpdates_data() @@ -849,7 +924,7 @@ void tst_QGL::glPBufferRendering() p.fillRect(32, 32, 64, 64, Qt::blue); p.end(); - QCOMPARE(fb, reference); + QFUZZY_COMPARE_IMAGES(fb, reference); } class GLWidget : public QGLWidget @@ -868,8 +943,8 @@ public: // This test only ensures it's possible to paint onto a QGLWidget. Full // paint engine feature testing is way out of scope! + p.fillRect(-1, -1, width()+2, height()+2, Qt::red); - p.fillRect(0, 0, width(), height(), Qt::red); // No p.end() or swap buffers, should be done automatically } @@ -877,9 +952,11 @@ public: void tst_QGL::glWidgetRendering() { - if (appDefaultDepth() < 24) - QSKIP("This test won't work for bit depths < 24", SkipAll); GLWidget w; +#ifdef Q_WS_QWS + w.setWindowFlags(Qt::FramelessWindowHint); +#endif + w.setGeometry(100, 100, 200, 200); w.show(); #ifdef Q_WS_X11 @@ -894,7 +971,37 @@ void tst_QGL::glWidgetRendering() QImage reference(fb.size(), QImage::Format_RGB32); reference.fill(0xffff0000); - QCOMPARE(fb, reference); + QFUZZY_COMPARE_IMAGES(fb, reference); +} + +void tst_QGL::glFBOSimpleRendering() +{ + if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) + QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); + + QGLWidget glw; + glw.makeCurrent(); + + // No multisample with combined depth/stencil attachment: + QGLFramebufferObjectFormat fboFormat; + fboFormat.setAttachment(QGLFramebufferObject::NoAttachment); + + // Don't complicate things by using NPOT: + QGLFramebufferObject *fbo = new QGLFramebufferObject(256, 128, fboFormat); + + fbo->bind(); + + glClearColor(1.0, 0.0, 0.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + glFinish(); + + QImage fb = fbo->toImage().convertToFormat(QImage::Format_RGB32); + QImage reference(fb.size(), QImage::Format_RGB32); + reference.fill(0xffff0000); + + QFUZZY_COMPARE_IMAGES(fb, reference); + + delete fbo; } // NOTE: This tests that CombinedDepthStencil attachment works by assuming the @@ -949,14 +1056,14 @@ void tst_QGL::glFBORendering() // As we're doing more than trivial painting, we can't just compare to // an image rendered with raster. Instead, we sample at well-defined // test-points: - QCOMPARE(fb.pixel(39, 64), QColor(Qt::red).rgb()); - QCOMPARE(fb.pixel(89, 64), QColor(Qt::red).rgb()); - QCOMPARE(fb.pixel(64, 39), QColor(Qt::blue).rgb()); - QCOMPARE(fb.pixel(64, 89), QColor(Qt::blue).rgb()); - - QCOMPARE(fb.pixel(167, 39), QColor(Qt::red).rgb()); - QCOMPARE(fb.pixel(217, 39), QColor(Qt::red).rgb()); - QCOMPARE(fb.pixel(192, 64), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb.pixel(39, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb.pixel(89, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb.pixel(64, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb.pixel(64, 89), QColor(Qt::blue).rgb()); + + QFUZZY_COMPARE_PIXELS(fb.pixel(167, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb.pixel(217, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb.pixel(192, 64), QColor(Qt::green).rgb()); } @@ -1047,29 +1154,29 @@ void tst_QGL::multipleFBOInterleavedRendering() // As we're doing more than trivial painting, we can't just compare to // an image rendered with raster. Instead, we sample at well-defined // test-points: - QCOMPARE(fb1.pixel(39, 64), QColor(Qt::red).rgb()); - QCOMPARE(fb1.pixel(89, 64), QColor(Qt::red).rgb()); - QCOMPARE(fb1.pixel(64, 39), QColor(Qt::blue).rgb()); - QCOMPARE(fb1.pixel(64, 89), QColor(Qt::blue).rgb()); - QCOMPARE(fb1.pixel(167, 39), QColor(Qt::red).rgb()); - QCOMPARE(fb1.pixel(217, 39), QColor(Qt::red).rgb()); - QCOMPARE(fb1.pixel(192, 64), QColor(Qt::green).rgb()); - - QCOMPARE(fb2.pixel(39, 64), QColor(Qt::green).rgb()); - QCOMPARE(fb2.pixel(89, 64), QColor(Qt::green).rgb()); - QCOMPARE(fb2.pixel(64, 39), QColor(Qt::red).rgb()); - QCOMPARE(fb2.pixel(64, 89), QColor(Qt::red).rgb()); - QCOMPARE(fb2.pixel(167, 39), QColor(Qt::green).rgb()); - QCOMPARE(fb2.pixel(217, 39), QColor(Qt::green).rgb()); - QCOMPARE(fb2.pixel(192, 64), QColor(Qt::blue).rgb()); - - QCOMPARE(fb3.pixel(39, 64), QColor(Qt::blue).rgb()); - QCOMPARE(fb3.pixel(89, 64), QColor(Qt::blue).rgb()); - QCOMPARE(fb3.pixel(64, 39), QColor(Qt::green).rgb()); - QCOMPARE(fb3.pixel(64, 89), QColor(Qt::green).rgb()); - QCOMPARE(fb3.pixel(167, 39), QColor(Qt::blue).rgb()); - QCOMPARE(fb3.pixel(217, 39), QColor(Qt::blue).rgb()); - QCOMPARE(fb3.pixel(192, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(39, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(89, 64), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(64, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(64, 89), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(167, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(217, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb1.pixel(192, 64), QColor(Qt::green).rgb()); + + QFUZZY_COMPARE_PIXELS(fb2.pixel(39, 64), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(89, 64), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(64, 39), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(64, 89), QColor(Qt::red).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(167, 39), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(217, 39), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb2.pixel(192, 64), QColor(Qt::blue).rgb()); + + QFUZZY_COMPARE_PIXELS(fb3.pixel(39, 64), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(89, 64), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(64, 39), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(64, 89), QColor(Qt::green).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(167, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(217, 39), QColor(Qt::blue).rgb()); + QFUZZY_COMPARE_PIXELS(fb3.pixel(192, 64), QColor(Qt::red).rgb()); } class FBOUseInGLWidget : public QGLWidget @@ -1089,11 +1196,11 @@ protected: QPainter fboPainter; fboPainterBeginOk = fboPainter.begin(fbo); - fboPainter.fillRect(0, 0, 128, 128, Qt::red); + fboPainter.fillRect(-1, -1, 130, 130, Qt::red); fboPainter.end(); fboImage = fbo->toImage(); - widgetPainter.fillRect(rect(), Qt::blue); + widgetPainter.fillRect(-1, -1, width()+2, width()+2, Qt::blue); delete fbo; } @@ -1102,12 +1209,13 @@ protected: void tst_QGL::glFBOUseInGLWidget() { - if (appDefaultDepth() < 24) - QSKIP("This test won't work for bit depths < 24", SkipAll); if (!QGLFramebufferObject::hasOpenGLFramebufferObjects()) QSKIP("QGLFramebufferObject not supported on this platform", SkipSingle); FBOUseInGLWidget w; +#ifdef Q_WS_QWS + w.setWindowFlags(Qt::FramelessWindowHint); +#endif w.resize(128, 128); w.show(); @@ -1122,17 +1230,15 @@ void tst_QGL::glFBOUseInGLWidget() QImage widgetFB = w.grabFrameBuffer(false); QImage widgetReference(widgetFB.size(), widgetFB.format()); widgetReference.fill(0xff0000ff); - QCOMPARE(widgetFB, widgetReference); + QFUZZY_COMPARE_IMAGES(widgetFB, widgetReference); QImage fboReference(w.fboImage.size(), w.fboImage.format()); fboReference.fill(0xffff0000); - QCOMPARE(w.fboImage, fboReference); + QFUZZY_COMPARE_IMAGES(w.fboImage, fboReference); } void tst_QGL::glWidgetReparent() { - if (appDefaultDepth() < 24) - QSKIP("This test won't work for bit depths < 24", SkipAll); // Try it as a top-level first: GLWidget *widget = new GLWidget; widget->setGeometry(0, 0, 200, 30); @@ -1222,7 +1328,7 @@ void tst_QGL::glWidgetRenderPixmap() QImage reference(fb.size(), QImage::Format_RGB32); reference.fill(0xffff0000); - QCOMPARE(fb, reference); + QFUZZY_COMPARE_IMAGES(fb, reference); } class ColormapExtended : public QGLColormap @@ -1495,9 +1601,10 @@ protected: void tst_QGL::replaceClipping() { - if (appDefaultDepth() < 24) - QSKIP("This test won't work for bit depths < 24", SkipAll); ReplaceClippingGLWidget glw; +#ifdef Q_WS_QWS + glw.setWindowFlags(Qt::FramelessWindowHint); +#endif glw.resize(300, 300); glw.show(); @@ -1513,7 +1620,13 @@ void tst_QGL::replaceClipping() const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); - QCOMPARE(widgetFB, reference); + // Sample pixels in a grid pattern which avoids false failures due to + // off-by-one pixel errors on some buggy GL implementations + for (int x = 25; x < reference.width(); x += 50) { + for (int y = 25; y < reference.width(); y += 50) { + QFUZZY_COMPARE_PIXELS(widgetFB.pixel(x, y), reference.pixel(x, y)); + } + } } class ClipTestGLWidget : public QGLWidget @@ -1521,7 +1634,7 @@ class ClipTestGLWidget : public QGLWidget public: void paint(QPainter *painter) { - painter->fillRect(rect(), Qt::white); + painter->fillRect(-1, -1, width()+2, height()+2, Qt::white); painter->setClipRect(10, 10, width()-20, height()-20); painter->fillRect(rect(), Qt::cyan); @@ -1622,9 +1735,10 @@ protected: void tst_QGL::clipTest() { - if (appDefaultDepth() < 24) - QSKIP("This test won't work for bit depths < 24", SkipAll); ClipTestGLWidget glw; +#ifdef Q_WS_QWS + glw.setWindowFlags(Qt::FramelessWindowHint); +#endif glw.resize(220, 220); glw.show(); @@ -1640,7 +1754,13 @@ void tst_QGL::clipTest() const QImage widgetFB = glw.grabFrameBuffer(false).convertToFormat(QImage::Format_RGB32); - QCOMPARE(widgetFB, reference); + // Sample pixels in a grid pattern which avoids false failures due to + // off-by-one pixel errors on some buggy GL implementations + for (int x = 2; x < reference.width(); x += 5) { + for (int y = 2; y < reference.width(); y += 5) { + QFUZZY_COMPARE_PIXELS(widgetFB.pixel(x, y), reference.pixel(x, y)); + } + } } void tst_QGL::destroyFBOAfterContext() @@ -1722,12 +1842,14 @@ void tst_QGL::shareRegister() QVERIFY(qt_shared_test()->value(glw1->context()) == res1); // Create another context that shares with the first. + QVERIFY(!glw1->isSharing()); QGLWidget *glw2 = new QGLWidget(0, glw1); if (!glw2->isSharing()) { delete glw2; delete glw1; QSKIP("Context sharing is not supported", SkipSingle); } + QVERIFY(glw1->isSharing()); QVERIFY(glw1->context() != glw2->context()); // Check that the first context's resource is also on the second. @@ -1759,6 +1881,7 @@ void tst_QGL::shareRegister() // Create a third context, not sharing with the others. QGLWidget *glw3 = new QGLWidget(); + QVERIFY(!glw3->isSharing()); // Create a guard on the standalone context. QGLSharedResourceGuard guard3(glw3->context()); @@ -1807,6 +1930,9 @@ void tst_QGL::shareRegister() // Delete the first context. delete glw1; + // The second context should no longer register as sharing. + QVERIFY(!glw2->isSharing()); + // The first context's resource should transfer to the second context. QCOMPARE(tst_QGLResource::deletions, 0); QVERIFY(qt_shared_test()->value(glw2->context()) == res1); diff --git a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index c7ed309..2ad024f 100644 --- a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -85,6 +85,7 @@ private slots: void simplificationVsOrder(); void parallelSimplificationOfCenter(); void simplificationVsRedundance(); + void spacingPersistency(); }; class RectWidget : public QGraphicsWidget @@ -1866,5 +1867,30 @@ void tst_QGraphicsAnchorLayout::simplificationVsRedundance() QCOMPARE(usedSimplex(l, Qt::Vertical), false); } +/* + Avoid regression where the saved prefSize would be lost. This was + solved by saving the original spacing in the QGraphicsAnchorPrivate class +*/ +void tst_QGraphicsAnchorLayout::spacingPersistency() +{ + QGraphicsWidget w; + QGraphicsWidget *a = createItem(); + QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout(&w); + + l->addAnchors(l, a, Qt::Horizontal); + QGraphicsAnchor *anchor = l->anchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); + + anchor->setSpacing(-30); + QCOMPARE(anchor->spacing(), -30.0); + + anchor->setSpacing(30); + QCOMPARE(anchor->spacing(), 30.0); + + anchor->setSizePolicy(QSizePolicy::Ignored); + w.effectiveSizeHint(Qt::PreferredSize); + + QCOMPARE(anchor->spacing(), 30.0); +} + QTEST_MAIN(tst_QGraphicsAnchorLayout) #include "tst_qgraphicsanchorlayout.moc" diff --git a/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp b/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp index 0fbd069..bca59c3 100644 --- a/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp +++ b/tests/auto/qgraphicsanchorlayout1/tst_qgraphicsanchorlayout1.cpp @@ -1722,7 +1722,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() QRectF expected = truncate(item.rect); QRectF actual = truncate(widgets[item.index]->geometry()); - QCOMPARE(expected, actual); + QCOMPARE(actual, expected); } // Test mirrored mode @@ -1739,7 +1739,7 @@ void tst_QGraphicsAnchorLayout1::testBasicLayout() QRectF expected = truncate(mirroredRect); QRectF actual = truncate(widgets[item.index]->geometry()); - QCOMPARE(expected, actual); + QCOMPARE(actual, expected); delete widgets[item.index]; } diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp index 6b5ad09..829e55c 100644 --- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp +++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp @@ -160,6 +160,7 @@ private slots: void widgetSendsGeometryChanges(); void respectHFW(); void addChildInpolishEvent(); + void polishEvent(); // Task fixes void task236127_bspTreeIndexFails(); @@ -2768,6 +2769,32 @@ void tst_QGraphicsWidget::addChildInpolishEvent() QCOMPARE(PolishWidget::numberOfPolish, 2); } +void tst_QGraphicsWidget::polishEvent() +{ + class MyGraphicsWidget : public QGraphicsWidget + { public: + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) + { events << QEvent::Paint; } + void polishEvent() + { events << QEvent::Polish; } + QList<QEvent::Type> events; + }; + + QGraphicsScene scene; + + MyGraphicsWidget *widget = new MyGraphicsWidget; + scene.addItem(widget); + + QGraphicsView view(&scene); + view.show(); + QTest::qWaitForWindowShown(&view); + + // Make sure the item is painted. + QTRY_VERIFY(widget->events.contains(QEvent::Paint)); + + // Make sure the item got polish before paint. + QCOMPARE(widget->events.at(0), QEvent::Polish); +} QTEST_MAIN(tst_QGraphicsWidget) #include "tst_qgraphicswidget.moc" diff --git a/tests/auto/qimagereader/images/grayscale-ref.tif b/tests/auto/qimagereader/images/grayscale-ref.tif Binary files differnew file mode 100644 index 0000000..960531e --- /dev/null +++ b/tests/auto/qimagereader/images/grayscale-ref.tif diff --git a/tests/auto/qimagereader/images/grayscale.tif b/tests/auto/qimagereader/images/grayscale.tif Binary files differnew file mode 100644 index 0000000..5f4e114 --- /dev/null +++ b/tests/auto/qimagereader/images/grayscale.tif diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp index 05b506c..15b1c1c 100644 --- a/tests/auto/qimagereader/tst_qimagereader.cpp +++ b/tests/auto/qimagereader/tst_qimagereader.cpp @@ -157,6 +157,8 @@ private slots: void tiffOrientation_data(); void tiffOrientation(); + + void tiffGrayscale(); #endif void autoDetectImageFormat(); @@ -1376,6 +1378,13 @@ void tst_QImageReader::tiffOrientation() QCOMPARE(expectedImage, orientedImage); } +void tst_QImageReader::tiffGrayscale() +{ + QImage actualImage(prefix + "grayscale.tif"); + QImage expectedImage(prefix + "grayscale-ref.tif"); + + QCOMPARE(expectedImage, actualImage.convertToFormat(expectedImage.format())); +} #endif void tst_QImageReader::dotsPerMeter_data() diff --git a/tests/auto/qimagewriter/tst_qimagewriter.cpp b/tests/auto/qimagewriter/tst_qimagewriter.cpp index ab5572d..5997f39 100644 --- a/tests/auto/qimagewriter/tst_qimagewriter.cpp +++ b/tests/auto/qimagewriter/tst_qimagewriter.cpp @@ -391,16 +391,27 @@ void tst_QImageWriter::readWriteNonDestructive_data() { QTest::addColumn<QImage::Format>("format"); QTest::addColumn<QImage::Format>("expectedFormat"); - QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono; - QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8; - QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32; + QTest::addColumn<bool>("grayscale"); + QTest::newRow("tiff mono") << QImage::Format_Mono << QImage::Format_Mono << false; + QTest::newRow("tiff indexed") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << false; + QTest::newRow("tiff rgb32") << QImage::Format_ARGB32 << QImage::Format_ARGB32 << false; + QTest::newRow("tiff grayscale") << QImage::Format_Indexed8 << QImage::Format_Indexed8 << true; } void tst_QImageWriter::readWriteNonDestructive() { QFETCH(QImage::Format, format); QFETCH(QImage::Format, expectedFormat); + QFETCH(bool, grayscale); QImage image = QImage(prefix + "colorful.bmp").convertToFormat(format); + + if (grayscale) { + QVector<QRgb> colors; + for (int i = 0; i < 256; ++i) + colors << qRgb(i, i, i); + image.setColorTable(colors); + } + QVERIFY(image.save(prefix + "gen-readWriteNonDestructive.tiff")); QImage image2 = QImage(prefix + "gen-readWriteNonDestructive.tiff"); diff --git a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp index 77c259c..269afbd 100644 --- a/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp +++ b/tests/auto/qitemselectionmodel/tst_qitemselectionmodel.cpp @@ -92,6 +92,7 @@ private slots: void task252069_rowIntersectsSelection(); void task232634_childrenDeselectionSignal(); void task260134_layoutChangedWithAllSelected(); + void QTBUG5671_layoutChangedWithAllSelected(); private: QAbstractItemModel *model; @@ -2025,24 +2026,24 @@ void tst_QItemSelectionModel::task220420_selectedIndexes() class QtTestTableModel: public QAbstractTableModel { Q_OBJECT - + public: QtTestTableModel(int rows = 0, int columns = 0, QObject *parent = 0) : QAbstractTableModel(parent), row_count(rows), column_count(columns) {} - + int rowCount(const QModelIndex& = QModelIndex()) const { return row_count; } int columnCount(const QModelIndex& = QModelIndex()) const { return column_count; } bool isEditable(const QModelIndex &) const { return true; } - + QVariant data(const QModelIndex &idx, int role) const { if (role == Qt::DisplayRole || role == Qt::EditRole) return QString("[%1,%2]").arg(idx.row()).arg(idx.column()); return QVariant(); } - + int row_count; int column_count; friend class tst_QItemSelectionModel; @@ -2055,7 +2056,7 @@ void tst_QItemSelectionModel::task240734_layoutChanged() QItemSelectionModel selectionModel(&model); selectionModel.select(model.index(0,0), QItemSelectionModel::Select); QCOMPARE(selectionModel.selectedIndexes().count() , 1); - + emit model.layoutAboutToBeChanged(); model.row_count = 5; emit model.layoutChanged(); @@ -2107,7 +2108,7 @@ void tst_QItemSelectionModel::merge_data() << QItemSelection(model->index(2, 2) , model->index(3, 4)) << int(QItemSelectionModel::Deselect) << QItemSelection(model->index(2, 1) , model->index(3, 1)); - + QItemSelection r1(model->index(2, 1) , model->index(3, 1)); r1.select(model->index(2, 4) , model->index(3, 4)); QTest::newRow("Toggle") @@ -2274,5 +2275,57 @@ void tst_QItemSelectionModel::task260134_layoutChangedWithAllSelected() } +void tst_QItemSelectionModel::QTBUG5671_layoutChangedWithAllSelected() +{ + struct MyFilterModel : public QSortFilterProxyModel + { // Override sort filter proxy to remove even numbered rows. + bool filtering; + virtual bool filterAcceptsRow( int source_row, const QModelIndex& source_parent ) const + { + return !filtering || !( source_row & 1 ); + } + }; + + //same as task260134_layoutChangedWithAllSelected but with a sightly bigger model + + enum { cNumRows=30, cNumCols=20 }; + + QStandardItemModel model(cNumRows, cNumCols); + MyFilterModel proxy; + proxy.filtering = true; + proxy.setSourceModel(&model); + QItemSelectionModel selection(&proxy); + + // Populate the tree view. + for (unsigned int i = 0; i < cNumCols; i++) + model.setHeaderData( i, Qt::Horizontal, QString::fromLatin1("Column %1").arg(i)); + + for (unsigned int r = 0; r < cNumRows; r++) { + for (unsigned int c = 0; c < cNumCols; c++) { + model.setData(model.index(r, c, QModelIndex()), + QString::fromLatin1("r:%1/c:%2").arg(r, c)); + } + } + + + QCOMPARE(model.rowCount(), int(cNumRows)); + QCOMPARE(proxy.rowCount(), int(cNumRows/2)); + + selection.select( QItemSelection(proxy.index(0,0), proxy.index(proxy.rowCount() - 1, proxy.columnCount() - 1)), QItemSelectionModel::Select); + + QList<QPersistentModelIndex> indexList; + foreach(const QModelIndex &id, selection.selectedIndexes()) + indexList << id; + + proxy.filtering = false; + proxy.invalidate(); + QCOMPARE(proxy.rowCount(), int(cNumRows)); + + //let's check the selection hasn't changed + QCOMPARE(selection.selectedIndexes().count(), indexList.count()); + foreach(QPersistentModelIndex index, indexList) + QVERIFY(selection.isSelected(index)); +} + QTEST_MAIN(tst_QItemSelectionModel) #include "tst_qitemselectionmodel.moc" diff --git a/tests/auto/qlabel/tst_qlabel.cpp b/tests/auto/qlabel/tst_qlabel.cpp index 9d957a5..6b7e106 100644 --- a/tests/auto/qlabel/tst_qlabel.cpp +++ b/tests/auto/qlabel/tst_qlabel.cpp @@ -51,6 +51,7 @@ #include <qmovie.h> #include <qpicture.h> #include <qmessagebox.h> +#include <private/qlabel_p.h> //TESTED_CLASS= //TESTED_FILES= @@ -116,6 +117,9 @@ private slots: void unicodeText_data(); void unicodeText(); + void mnemonic_data(); + void mnemonic(); + private: QLabel *testWidget; QPointer<Widget> test_box; @@ -224,6 +228,7 @@ void tst_QLabel::setBuddy() QVERIFY( !test_edit->hasFocus() ); QTest::keyClick( test_box, 't', Qt::AltModifier ); QVERIFY( test_edit->hasFocus() ); + delete test_box; } void tst_QLabel::text() @@ -245,6 +250,7 @@ void tst_QLabel::setText_data() QTest::newRow( QString(prefix + "data1").toLatin1() ) << QString("This is the first line\nThis is the second line") << QString("Courier"); QTest::newRow( QString(prefix + "data2").toLatin1() ) << QString("This is the first line\nThis is the second line\nThis is the third line") << QString("Helvetica"); QTest::newRow( QString(prefix + "data3").toLatin1() ) << QString("This is <b>bold</b> richtext") << QString("Courier"); + QTest::newRow( QString(prefix + "data4").toLatin1() ) << QString("I Have a &shortcut") << QString("Helvetica"); } void tst_QLabel::setText() @@ -509,5 +515,50 @@ void tst_QLabel::unicodeText() testWidget->show(); } +void tst_QLabel::mnemonic_data() +{ + QTest::addColumn<QString>("text"); + QTest::addColumn<QString>("expectedDocText"); + QTest::addColumn<QString>("expectedShortcutCursor"); + + QTest::newRow("1") << QString("Normal") << QString("Normal") << QString(); + QTest::newRow("2") << QString("&Simple") << QString("Simple") << QString("S"); + QTest::newRow("3") << QString("Also &simple") << QString("Also simple") << QString("s"); + QTest::newRow("4") << QString("&&With &Double &&") << QString("&With Double &") << QString("D"); + QTest::newRow("5") << QString("Hep&&Hop") << QString("Hep&Hop") << QString(""); + QTest::newRow("6") << QString("Hep&&&Hop") << QString("Hep&Hop") << QString("H"); +} + + +void tst_QLabel::mnemonic() +{ + // this test that the mnemonics appears correctly when the label has a text control. + + QFETCH(QString, text); + QFETCH(QString, expectedDocText); + QFETCH(QString, expectedShortcutCursor); + + QWidget w; + QHBoxLayout *hbox = new QHBoxLayout; + QLabel *lab = new QLabel(text); + //lab->setText("plop &plop"); + QLineEdit *lineedit = new QLineEdit; + lab->setBuddy(lineedit); + lab->setTextInteractionFlags(Qt::TextSelectableByMouse); + + hbox->addWidget(lab); + hbox->addWidget(lineedit); + hbox->addWidget(new QLineEdit); + w.setLayout(hbox); + w.show(); + QTest::qWaitForWindowShown(&w); + + QLabelPrivate *d = static_cast<QLabelPrivate *>(QObjectPrivate::get(lab)); + QVERIFY(d->control); + QCOMPARE(d->control->document()->toPlainText(), expectedDocText); + QCOMPARE(d->shortcutCursor.selectedText(), expectedShortcutCursor); +} + + QTEST_MAIN(tst_QLabel) #include "tst_qlabel.moc" diff --git a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp index a80c787..751c7dc 100644 --- a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp +++ b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp @@ -407,7 +407,7 @@ void tst_QPixmapFilter::dropShadowBoundingRectFor() filter.setBlurRadius(2); filter.setOffset(QPointF(0,0)); - int delta = 2 * 2; + qreal delta = 2; QCOMPARE(filter.boundingRectFor(rect1), rect1.adjusted(-delta, -delta, delta, delta)); QCOMPARE(filter.boundingRectFor(rect2), rect2.adjusted(-delta, -delta, delta, delta)); QCOMPARE(filter.boundingRectFor(rect3), rect3.adjusted(-delta, -delta, delta, delta)); diff --git a/tests/auto/qtreewidget/tst_qtreewidget.cpp b/tests/auto/qtreewidget/tst_qtreewidget.cpp index 6defd7b..621072c 100644 --- a/tests/auto/qtreewidget/tst_qtreewidget.cpp +++ b/tests/auto/qtreewidget/tst_qtreewidget.cpp @@ -167,6 +167,7 @@ private slots: void setCurrentItemExpandsParent(); void task239150_editorWidth(); void setTextUpdate(); + void taskQTBUG2844_visualItemRect(); public slots: void itemSelectionChanged(); @@ -601,9 +602,9 @@ void tst_QTreeWidget::setItemHidden() testWidget->scrollToItem(child); QVERIFY(testWidget->visualItemRect(parent).isValid() - && testWidget->viewport()->rect().contains(testWidget->visualItemRect(parent))); + && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent))); QVERIFY(testWidget->visualItemRect(child).isValid() - && testWidget->viewport()->rect().contains(testWidget->visualItemRect(child))); + && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child))); QVERIFY(!testWidget->isItemHidden(parent)); QVERIFY(!testWidget->isItemHidden(child)); @@ -611,9 +612,9 @@ void tst_QTreeWidget::setItemHidden() testWidget->setItemHidden(parent, true); QVERIFY(!(testWidget->visualItemRect(parent).isValid() - && testWidget->viewport()->rect().contains(testWidget->visualItemRect(parent)))); + && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(parent)))); QVERIFY(!(testWidget->visualItemRect(child).isValid() - && testWidget->viewport()->rect().contains(testWidget->visualItemRect(child)))); + && testWidget->viewport()->rect().intersects(testWidget->visualItemRect(child)))); QVERIFY(testWidget->isItemHidden(parent)); QVERIFY(!testWidget->isItemHidden(child)); @@ -3271,6 +3272,25 @@ void tst_QTreeWidget::setTextUpdate() QTRY_VERIFY(delegate.numPaints > 0); } +void tst_QTreeWidget::taskQTBUG2844_visualItemRect() +{ + CustomTreeWidget tree; + tree.resize(150, 100); + tree.setColumnCount(3); + QTreeWidgetItem item(&tree); + + QRect itemRect = tree.visualItemRect(&item); + + QRect rectCol0 = tree.visualRect(tree.indexFromItem(&item, 0)); + QRect rectCol1 = tree.visualRect(tree.indexFromItem(&item, 1)); + QRect rectCol2 = tree.visualRect(tree.indexFromItem(&item, 2)); + + QCOMPARE(tree.visualItemRect(&item), rectCol0 | rectCol2); + tree.setColumnHidden(2, true); + QCOMPARE(tree.visualItemRect(&item), rectCol0 | rectCol1); +} + + QTEST_MAIN(tst_QTreeWidget) diff --git a/tools/qttracereplay/main.cpp b/tools/qttracereplay/main.cpp index 1d21a21..7261082 100644 --- a/tools/qttracereplay/main.cpp +++ b/tools/qttracereplay/main.cpp @@ -56,7 +56,7 @@ public: public slots: void updateRect(); -private: +public: QList<QRegion> updates; QPaintBuffer buffer; @@ -70,7 +70,8 @@ private: void ReplayWidget::updateRect() { - update(updates.at(currentFrame)); + if (!updates.isEmpty()) + update(updates.at(currentFrame)); } void ReplayWidget::paintEvent(QPaintEvent *) @@ -138,12 +139,25 @@ ReplayWidget::ReplayWidget(const QString &filename_) QFile file(filename); QRect bounds; - if (file.open(QIODevice::ReadOnly)) { - QDataStream in(&file); - in >> buffer >> updates; + if (!file.open(QIODevice::ReadOnly)) { + printf("Failed to load input file '%s'\n", qPrintable(filename_)); + return; + } + + QDataStream in(&file); + + char *data; + uint size; + in.readBytes(data, size); + bool isTraceFile = size == 7 && qstrncmp(data, "qttrace", 7) == 0; + delete [] data; + if (!isTraceFile) { + printf("File '%s' is not a trace file\n", qPrintable(filename_)); + return; } - qDebug() << "Read paint buffer with" << buffer.numFrames() << "frames"; + in >> buffer >> updates; + printf("Read paint buffer with %d frames\n", buffer.numFrames()); resize(buffer.boundingRect().size().toSize()); @@ -157,14 +171,18 @@ int main(int argc, char **argv) { QApplication app(argc, argv); - if (argc <= 1) { - printf("Usage: %s filename\n", argv[0]); + if (argc <= 1 || qstrcmp(argv[1], "-h") == 0 || qstrcmp(argv[1], "--help") == 0) { + printf("Replays a tracefile generated with '-graphicssystem trace'\n"); + printf("Usage:\n > %s [traceFile]\n", argv[0]); return 1; } ReplayWidget *widget = new ReplayWidget(argv[1]); - widget->show(); - return app.exec(); + if (!widget->updates.isEmpty()) { + widget->show(); + return app.exec(); + } + } #include "main.moc" diff --git a/tools/qttracereplay/qttracereplay.pro b/tools/qttracereplay/qttracereplay.pro index 766ed04..cc5b98d 100644 --- a/tools/qttracereplay/qttracereplay.pro +++ b/tools/qttracereplay/qttracereplay.pro @@ -11,3 +11,5 @@ SOURCES += main.cpp target.path=$$[QT_INSTALL_BINS] INSTALLS += target + +CONFIG += console |