From bd8f1171ea1d564bb9b8e04b1a220e5559d60423 Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Sun, 13 Sep 2009 09:40:37 +0200 Subject: Fix libiconv support on FreeBSD. For some reason iconv support was broken in Qt 4.5 on FreeBSD, and this patch was made to fix that. Original patch by Max Brazhnikov . Original message: Enable libiconv support. Didn't get where the real problem is, but using UTF-16LE/BE as default encoding (see patch) fixes the issue. Merge-request: 1480 Reviewed-by: Thiago Macieira --- src/corelib/codecs/qiconvcodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp index 6153d70..e4389b9 100644 --- a/src/corelib/codecs/qiconvcodec.cpp +++ b/src/corelib/codecs/qiconvcodec.cpp @@ -62,7 +62,7 @@ #elif defined(Q_OS_AIX) # define NO_BOM # define UTF16 "UCS-2" -#elif defined(Q_OS_MAC) +#elif defined(Q_OS_FREEBSD) || defined(Q_OS_MAC) # define NO_BOM # if Q_BYTE_ORDER == Q_BIG_ENDIAN # define UTF16 "UTF-16BE" -- cgit v0.12 From c54541adf74bb8a87fd59d31f7e96626d3ca5e43 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 14 Sep 2009 11:53:23 +1000 Subject: Don't have to glEnable(GL_TEXTURE_2D) when using shaders. OpenGL/ES 2.0 systems were giving a GL error when GL_TEXTURE_2D was enabled and disabled. Reviewed-by: trustme --- examples/opengl/hellogl_es2/glwidget.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/examples/opengl/hellogl_es2/glwidget.cpp b/examples/opengl/hellogl_es2/glwidget.cpp index 5200467..a31c34a 100644 --- a/examples/opengl/hellogl_es2/glwidget.cpp +++ b/examples/opengl/hellogl_es2/glwidget.cpp @@ -92,7 +92,6 @@ void GLWidget::showBubbles(bool bubbles) void GLWidget::paintQtLogo() { - glDisable(GL_TEXTURE_2D); program1.setAttributeArray(vertexAttr1, vertices.constData()); program1.setAttributeArray(normalAttr1, normals.constData()); glDrawArrays(GL_TRIANGLES, 0, vertices.size()); @@ -102,7 +101,6 @@ void GLWidget::paintQtLogo() void GLWidget::paintTexturedCube() { - glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, m_uiTexture); GLfloat afVertices[] = { -0.5, 0.5, 0.5, 0.5,-0.5,0.5,-0.5,-0.5,0.5, @@ -172,7 +170,6 @@ void GLWidget::initializeGL () { glClearColor(0.1f, 0.1f, 0.2f, 1.0f); - glEnable(GL_TEXTURE_2D); glGenTextures(1, &m_uiTexture); m_uiTexture = bindTexture(QImage(":/qt.png")); @@ -270,7 +267,6 @@ void GLWidget::paintGL() glClearColor(0.1f, 0.1f, 0.2f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - glEnable(GL_TEXTURE_2D); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); -- cgit v0.12 From f3e2ccf63de242feeba10e75fd00ffd43fc038b0 Mon Sep 17 00:00:00 2001 From: Kurt Korbatits Date: Mon, 14 Sep 2009 12:33:37 +1000 Subject: AudioDevices demo doesn't do anything on Windows -put example audiodevices in layout. -added more checking to testSettings() in win32 implementation. -disabled objects in example audiodevices that are not editable. -added more checking to alsa implementation for preferredFormat(). -changed internal strings from tr to QLatin1String. Reviewed-by:Justin Mcpherson --- .../multimedia/audio/audiodevices/audiodevices.cpp | 12 +- .../audio/audiodevices/audiodevicesbase.ui | 444 ++++++++++----------- src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp | 67 +++- src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp | 36 +- src/multimedia/audio/qaudioinput_alsa_p.cpp | 8 +- src/multimedia/audio/qaudioinput_win32_p.cpp | 2 +- src/multimedia/audio/qaudiooutput_alsa_p.cpp | 8 +- src/multimedia/audio/qaudiooutput_win32_p.cpp | 2 +- 8 files changed, 303 insertions(+), 276 deletions(-) diff --git a/examples/multimedia/audio/audiodevices/audiodevices.cpp b/examples/multimedia/audio/audiodevices/audiodevices.cpp index 52aa4db..0d305ff 100644 --- a/examples/multimedia/audio/audiodevices/audiodevices.cpp +++ b/examples/multimedia/audio/audiodevices/audiodevices.cpp @@ -58,6 +58,14 @@ AudioDevicesBase::~AudioDevicesBase() {} AudioTest::AudioTest( QMainWindow *parent, Qt::WFlags f ) : AudioDevicesBase( parent, f ) { + nearestFreq->setDisabled(true); + nearestChannel->setDisabled(true); + nearestCodec->setDisabled(true); + nearestSampleSize->setDisabled(true); + nearestSampleType->setDisabled(true); + nearestEndian->setDisabled(true); + logOutput->setDisabled(true); + mode = QAudio::AudioOutput; modeBox->addItem("Input"); modeBox->addItem("Output"); @@ -87,6 +95,8 @@ AudioTest::~AudioTest() void AudioTest::test() { // tries to set all the settings picked. + logOutput->clear(); + logOutput->append("NOTE: an invalid codec audio/test exists for testing, to get a fail condition."); if(device) { if(device->isFormatSupported(settings)) { @@ -179,7 +189,7 @@ void AudioTest::deviceChanged(int idx) if(codecz.size()) settings.setCodec(codecz.at(0)); // Add false to create failed condition! - codecsBox->addItem("audio/mpeg"); + codecsBox->addItem("audio/test"); sampleSizesBox->clear(); QList sampleSizez = device->supportedSampleSizes(); diff --git a/examples/multimedia/audio/audiodevices/audiodevicesbase.ui b/examples/multimedia/audio/audiodevices/audiodevicesbase.ui index 674f201..5207338 100644 --- a/examples/multimedia/audio/audiodevices/audiodevicesbase.ui +++ b/examples/multimedia/audio/audiodevices/audiodevicesbase.ui @@ -1,7 +1,8 @@ - + + AudioDevicesBase - - + + 0 0 @@ -9,246 +10,223 @@ 702 - + AudioDevicesBase - - - - 0 - 28 - 504 - 653 - - - - - - 40 - 21 - 321 - 506 - - - - - - - - 1 - 0 - - - - Device - - - - - - - Mode - - - - - - - - - - - - - QFrame::Panel - - - QFrame::Raised - - - Actual Settings - - - Qt::AlignCenter - - - - - - - QFrame::Panel - - - QFrame::Raised - - - Nearest Settings - - - Qt::AlignCenter - - - - - - - Frequency - - - - - - - Frequency - - - - - - - - - - - - - Channels - - - - - - - Channel - - - - - - - - - - - - - Codecs - - - - - - - Codec - - - - - - - - - - - - - SampleSize - - - - - - - SampleSize - - - - - - - - - - - - - SampleType - - - - - - - SampleType - - - - - - - - - - - - - Endianess - - - - - - - Endianess - - - - - - - - - - - - - - 0 - 40 - - - - - - - - Test - - - - - + + + + + + + + + 1 + 0 + + + + Device + + + + + + + Mode + + + + + + + + + + + + + QFrame::Panel + + + QFrame::Raised + + + Actual Settings + + + Qt::AlignCenter + + + + + + + QFrame::Panel + + + QFrame::Raised + + + Nearest Settings + + + Qt::AlignCenter + + + + + + + Frequency + + + + + + + Frequency + + + + + + + + + + + + + Channels + + + + + + + Channel + + + + + + + + + + + + + Codecs + + + + + + + Codec + + + + + + + + + + + + + SampleSize + + + + + + + SampleSize + + + + + + + + + + + + + SampleType + + + + + + + SampleType + + + + + + + + + + + + + Endianess + + + + + + + Endianess + + + + + + + + + + + + + + 0 + 40 + + + + + + + + Test + + + + + + - - + + 0 0 504 - 28 - - - - - - - 0 - 681 - 504 - 21 + 19 + diff --git a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp index 4ed1b41..c944cf0 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_alsa_p.cpp @@ -81,13 +81,18 @@ QAudioFormat QAudioDeviceInfoPrivate::preferredFormat() const nearest.setByteOrder(QAudioFormat::LittleEndian); nearest.setSampleType(QAudioFormat::SignedInt); nearest.setSampleSize(16); - nearest.setCodec(tr("audio/pcm")); + nearest.setCodec(QLatin1String("audio/pcm")); } else { nearest.setFrequency(8000); nearest.setChannels(1); - nearest.setSampleType(QAudioFormat::SignedInt); + nearest.setSampleType(QAudioFormat::UnSignedInt); nearest.setSampleSize(8); - nearest.setCodec(tr("audio/pcm")); + nearest.setCodec(QLatin1String("audio/pcm")); + if(!testSettings(nearest)) { + nearest.setChannels(2); + nearest.setSampleSize(16); + nearest.setSampleType(QAudioFormat::SignedInt); + } } return nearest; } @@ -145,9 +150,9 @@ bool QAudioDeviceInfoPrivate::open() { int err = 0; QString dev = device; - if(!dev.contains(tr("default"))) { + if(!dev.contains(QLatin1String("default"))) { int idx = snd_card_get_index(dev.toLocal8Bit().constData()); - dev = QString(tr("hw:%1,0")).arg(idx); + dev = QString(QLatin1String("hw:%1,0")).arg(idx); } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); @@ -172,16 +177,15 @@ bool QAudioDeviceInfoPrivate::testSettings(const QAudioFormat& format) const { // Set nearest to closest settings that do work. // See if what is in settings will work (return value). - int err = 0; snd_pcm_t* handle; snd_pcm_hw_params_t *params; QString dev = device; // open() - if(!dev.contains(tr("default"))) { + if(!dev.contains(QLatin1String("default"))) { int idx = snd_card_get_index(dev.toLocal8Bit().constData()); - dev = QString(tr("hw:%1,0")).arg(idx); + dev = QString(QLatin1String("hw:%1,0")).arg(idx); } if(mode == QAudio::AudioOutput) { err=snd_pcm_open( &handle,dev.toLocal8Bit().constData(),SND_PCM_STREAM_PLAYBACK,0); @@ -205,8 +209,45 @@ bool QAudioDeviceInfoPrivate::testSettings(const QAudioFormat& format) const snd_pcm_hw_params_alloca( ¶ms ); snd_pcm_hw_params_any( handle, params ); + // set the values! + snd_pcm_hw_params_set_channels(handle,params,format.channels()); + snd_pcm_hw_params_set_rate(handle,params,format.frequency(),dir); + switch(format.sampleSize()) { + case 8: + if(format.sampleType() == QAudioFormat::SignedInt) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S8); + else if(format.sampleType() == QAudioFormat::UnSignedInt) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U8); + break; + case 16: + if(format.sampleType() == QAudioFormat::SignedInt) { + if(format.byteOrder() == QAudioFormat::LittleEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE); + else if(format.byteOrder() == QAudioFormat::BigEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_BE); + } else if(format.sampleType() == QAudioFormat::UnSignedInt) { + if(format.byteOrder() == QAudioFormat::LittleEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_LE); + else if(format.byteOrder() == QAudioFormat::BigEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U16_BE); + } + break; + case 32: + if(format.sampleType() == QAudioFormat::SignedInt) { + if(format.byteOrder() == QAudioFormat::LittleEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_LE); + else if(format.byteOrder() == QAudioFormat::BigEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S32_BE); + } else if(format.sampleType() == QAudioFormat::UnSignedInt) { + if(format.byteOrder() == QAudioFormat::LittleEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_LE); + else if(format.byteOrder() == QAudioFormat::BigEndian) + snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_U32_BE); + } + } + // For now, just accept only audio/pcm codec - if(!format.codec().startsWith(tr("audio/pcm"))) { + if(!format.codec().startsWith(QLatin1String("audio/pcm"))) { err=-1; } else testCodec = true; @@ -313,7 +354,7 @@ void QAudioDeviceInfoPrivate::updateLists() typez.append(QAudioFormat::SignedInt); typez.append(QAudioFormat::UnSignedInt); typez.append(QAudioFormat::Float); - codecz.append(tr("audio/pcm")); + codecz.append(QLatin1String("audio/pcm")); close(); } @@ -346,10 +387,10 @@ QList QAudioDeviceInfoPrivate::deviceList(QAudio::Mode mode) if(io == NULL) _m = mode; - QString str = tr(name); + QString str = QLatin1String(name); - if(str.contains(tr("default"))) { - int pos = str.indexOf(tr("="),0); + if(str.contains(QLatin1String("default"))) { + int pos = str.indexOf(QLatin1String("="),0); devices.append(str.mid(pos+1).toLocal8Bit().constData()); } } diff --git a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp index 371f442..ba9f5e2 100644 --- a/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp +++ b/src/multimedia/audio/qaudiodeviceinfo_win32_p.cpp @@ -99,13 +99,13 @@ QAudioFormat QAudioDeviceInfoPrivate::preferredFormat() const nearest.setByteOrder(QAudioFormat::LittleEndian); nearest.setSampleType(QAudioFormat::SignedInt); nearest.setSampleSize(16); - nearest.setCodec(tr("audio/pcm")); + nearest.setCodec(QLatin1String("audio/pcm")); } else { nearest.setFrequency(11025); nearest.setChannels(1); nearest.setSampleType(QAudioFormat::SignedInt); nearest.setSampleSize(8); - nearest.setCodec(tr("audio/pcm")); + nearest.setCodec(QLatin1String("audio/pcm")); } return nearest; } @@ -174,27 +174,25 @@ bool QAudioDeviceInfoPrivate::testSettings(const QAudioFormat& format) const // Set nearest to closest settings that do work. // See if what is in settings will work (return value). - bool testChannel = false; - bool testCodec = false; - bool testFreq = false; - - int err = 0; + bool failed = false; // For now, just accept only audio/pcm codec - if(!format.codec().startsWith(tr("audio/pcm"))) { - err=-1; - } else - testCodec = true; + if(!format.codec().startsWith(QLatin1String("audio/pcm"))) + failed = true; - if(err>=0 && format.channels() != -1) { - testChannel = true; - } + if(!failed && !(format.channels() == 1 || format.channels() == 2)) + failed = true; - if(err>=0 && format.frequency() != -1) { - testFreq = true; + if(!failed) { + if(!(format.frequency() == 8000 || format.frequency() == 11025 || format.frequency() == 22050 || + format.frequency() == 44100 || format.frequency() == 48000 || format.frequency() == 96000)) + failed = true; } - if(err == 0) { + if(!failed && !(format.sampleSize() == 8 || format.sampleSize() == 16)) + failed = true; + + if(!failed) { // settings work return true; } @@ -209,7 +207,7 @@ void QAudioDeviceInfoPrivate::updateLists() DWORD fmt = NULL; QString tmp; - if(device.compare(tr("default")) == 0) + if(device.compare(QLatin1String("default")) == 0) base = true; if(mode == QAudio::AudioOutput) { @@ -331,7 +329,7 @@ void QAudioDeviceInfoPrivate::updateLists() typez.append(QAudioFormat::SignedInt); typez.append(QAudioFormat::UnSignedInt); - codecz.append(tr("audio/pcm")); + codecz.append(QLatin1String("audio/pcm")); } } diff --git a/src/multimedia/audio/qaudioinput_alsa_p.cpp b/src/multimedia/audio/qaudioinput_alsa_p.cpp index c98102c..f36ffc8 100644 --- a/src/multimedia/audio/qaudioinput_alsa_p.cpp +++ b/src/multimedia/audio/qaudioinput_alsa_p.cpp @@ -78,7 +78,7 @@ QAudioInputPrivate::QAudioInputPrivate(const QByteArray &device, const QAudioFor pullMode = true; resuming = false; - QStringList list1 = QString(tr(device)).split(tr(":")); + QStringList list1 = QString(QLatin1String(device)).split(QLatin1String(":")); m_device = QByteArray(list1.at(0).toLocal8Bit().constData()); timer = new QTimer(this); @@ -254,9 +254,9 @@ bool QAudioInputPrivate::open() int count=0; unsigned int freakuency=settings.frequency(); - QString dev = QString(tr(m_device.constData())); - if(!dev.contains(tr("default"))) { - dev = QString(tr("default:CARD=%1")).arg(tr(m_device.constData())); + QString dev = QString(QLatin1String(m_device.constData())); + if(!dev.contains(QLatin1String("default"))) { + dev = QString(QLatin1String("default:CARD=%1")).arg(QLatin1String(m_device.constData())); } // Step 1: try and open the device diff --git a/src/multimedia/audio/qaudioinput_win32_p.cpp b/src/multimedia/audio/qaudioinput_win32_p.cpp index 315a59b..31441ae 100644 --- a/src/multimedia/audio/qaudioinput_win32_p.cpp +++ b/src/multimedia/audio/qaudioinput_win32_p.cpp @@ -245,7 +245,7 @@ bool QAudioInputPrivate::open() == MMSYSERR_NOERROR) { QString tmp; tmp = QString::fromUtf16((const unsigned short*)wic.szPname); - if(tmp.compare(tr(m_device)) == 0) { + if(tmp.compare(QLatin1String(m_device)) == 0) { devId = ii; break; } diff --git a/src/multimedia/audio/qaudiooutput_alsa_p.cpp b/src/multimedia/audio/qaudiooutput_alsa_p.cpp index 45ff115..e8a3f5c 100644 --- a/src/multimedia/audio/qaudiooutput_alsa_p.cpp +++ b/src/multimedia/audio/qaudiooutput_alsa_p.cpp @@ -81,7 +81,7 @@ QAudioOutputPrivate::QAudioOutputPrivate(const QByteArray &device, const QAudioF resuming = false; opened = false; - QStringList list1 = QString(tr(device)).split(tr(":")); + QStringList list1 = QString(QLatin1String(device)).split(QLatin1String(":")); m_device = QByteArray(list1.at(0).toLocal8Bit().constData()); timer = new QTimer(this); @@ -277,9 +277,9 @@ bool QAudioOutputPrivate::open() int count=0; unsigned int freakuency=settings.frequency(); - QString dev = tr(m_device.constData()); - if(!dev.contains(tr("default"))) { - dev = QString(tr("default:CARD=%1")).arg(tr(m_device.constData())); + QString dev = QLatin1String(m_device.constData()); + if(!dev.contains(QLatin1String("default"))) { + dev = QString(QLatin1String("default:CARD=%1")).arg(QLatin1String(m_device.constData())); } // Step 1: try and open the device while((count < 5) && (err < 0)) { diff --git a/src/multimedia/audio/qaudiooutput_win32_p.cpp b/src/multimedia/audio/qaudiooutput_win32_p.cpp index fae680c..aea3a3f 100644 --- a/src/multimedia/audio/qaudiooutput_win32_p.cpp +++ b/src/multimedia/audio/qaudiooutput_win32_p.cpp @@ -241,7 +241,7 @@ bool QAudioOutputPrivate::open() == MMSYSERR_NOERROR) { QString tmp; tmp = QString::fromUtf16((const unsigned short*)woc.szPname); - if(tmp.compare(tr(m_device)) == 0) { + if(tmp.compare(QLatin1String(m_device)) == 0) { devId = ii; break; } -- cgit v0.12 From 7809276c405d4b32eb671737ea0967b673ea271c Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 14 Sep 2009 13:26:25 +1000 Subject: Use redF(), etc when setting GL colors Reviewed-by: Sarah Smith --- src/opengl/qgl.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 1bcfab8..f8a88601 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -3983,7 +3983,7 @@ void QGLWidget::qglColor(const QColor& c) const { #if !defined(QT_OPENGL_ES_2) #ifdef QT_OPENGL_ES - glColor4f(c.red()/255.0, c.green()/255.0, c.blue()/255.0, c.alpha()/255.0); + glColor4f(c.redF(), c.greenF(), c.blueF(), c.alphaF()); #else Q_D(const QGLWidget); const QGLContext *ctx = QGLContext::currentContext(); @@ -4015,15 +4015,13 @@ void QGLWidget::qglColor(const QColor& c) const void QGLWidget::qglClearColor(const QColor& c) const { #ifdef QT_OPENGL_ES - glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0, - (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0); + glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); #else Q_D(const QGLWidget); const QGLContext *ctx = QGLContext::currentContext(); if (ctx) { if (ctx->format().rgba()) - glClearColor((GLfloat)c.red() / 255.0, (GLfloat)c.green() / 255.0, - (GLfloat)c.blue() / 255.0, (GLfloat) c.alpha() / 255.0); + glClearColor(c.redF(), c.greenF(), c.blueF(), c.alphaF()); else if (!d->cmap.isEmpty()) { // QGLColormap in use? int i = d->cmap.find(c.rgb()); if (i < 0) -- cgit v0.12 From 732660e89af34c76f6aa8a46ce8507dfd5fad077 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 14 Sep 2009 13:30:38 +1000 Subject: qdoc: QGLWidget::colormap() returns a QGLColormap, not a QColormap --- src/opengl/qgl.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index f8a88601..c2b747a 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -4092,10 +4092,10 @@ QImage QGLWidget::convertToGLFormat(const QImage& img) colormaps installed. Asking for the colormap of a child widget will return the colormap for the child's top-level widget. - If no colormap has been set for this widget, the QColormap + If no colormap has been set for this widget, the QGLColormap returned will be empty. - \sa setColormap() + \sa setColormap(), QGLColormap::isEmpty() */ /*! -- cgit v0.12 From 9e3fb515207f8d80fe87b6e34e78d3d201b0b438 Mon Sep 17 00:00:00 2001 From: Rhys Weatherley Date: Mon, 14 Sep 2009 12:30:44 +1000 Subject: Performance: reduce TLS overhead of QGLContext::currentContext() The handling for the current QGLContext was looking up the same TLS data several times per call (hasLocalData() and localData() calls particularly). This change also refactors the code a little so that the setting of the QGLContext within makeCurrent() and doneCurrent() is in one location in the code instead of six (one per platform). Reviewed-by: Michael Brasser Reviewed-by: Sarah Smith --- src/opengl/qgl.cpp | 27 ++++++++++++++++++++++++--- src/opengl/qgl_mac.mm | 10 ++-------- src/opengl/qgl_p.h | 7 ++----- src/opengl/qgl_qws.cpp | 13 +++---------- src/opengl/qgl_win.cpp | 10 ++-------- src/opengl/qgl_wince.cpp | 13 +++---------- src/opengl/qgl_x11.cpp | 13 +++---------- src/opengl/qgl_x11egl.cpp | 13 +++---------- 8 files changed, 42 insertions(+), 64 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index c2b747a..1a0957c 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -103,7 +103,11 @@ QT_BEGIN_NAMESPACE QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; #endif -QThreadStorage qgl_context_storage; +struct QGLThreadContext { + QGLContext *context; +}; + +static QThreadStorage qgl_context_storage; Q_GLOBAL_STATIC(QGLFormat, qgl_default_format) @@ -2939,11 +2943,28 @@ void QGLContext::setInitialized(bool on) const QGLContext* QGLContext::currentContext() { - if (qgl_context_storage.hasLocalData()) - return qgl_context_storage.localData()->context; + QGLThreadContext *threadContext = qgl_context_storage.localData(); + if (threadContext) + return threadContext->context; return 0; } +void QGLContextPrivate::setCurrentContext(QGLContext *context) +{ + QGLThreadContext *threadContext = qgl_context_storage.localData(); + if (!threadContext) { + if (!QThread::currentThread()) { + // We don't have a current QThread, so just set the static. + QGLContext::currentCtx = context; + return; + } + threadContext = new QGLThreadContext; + qgl_context_storage.setLocalData(threadContext); + } + threadContext->context = context; + QGLContext::currentCtx = context; // XXX: backwards-compat, not thread-safe +} + /*! \fn bool QGLContext::chooseContext(const QGLContext* shareContext = 0) diff --git a/src/opengl/qgl_mac.mm b/src/opengl/qgl_mac.mm index dd9d9ff..063082b 100644 --- a/src/opengl/qgl_mac.mm +++ b/src/opengl/qgl_mac.mm @@ -493,11 +493,7 @@ void QGLContext::makeCurrent() #else [static_cast(d->cx) makeCurrentContext]; #endif - currentCtx = this; - if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) - qgl_context_storage.setLocalData(new QGLThreadContext); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = this; + QGLContextPrivate::setCurrentContext(this); } #ifndef QT_MAC_USE_COCOA @@ -656,9 +652,7 @@ void QGLContext::doneCurrent() ) return; - currentCtx = 0; - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = 0; + QGLContextPrivate::setCurrentContext(0); #ifndef QT_MAC_USE_COCOA aglSetCurrentContext(0); #else diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 57b40fb..2b74e69 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -351,6 +351,8 @@ public: static inline QGLExtensionFuncs& extensionFuncs(QGLContextGroup *) { return qt_extensionFuncs; } #endif + static void setCurrentContext(QGLContext *context); + QPixmapFilter *createPixmapFilter(int type) const; }; @@ -398,11 +400,6 @@ public: Q_DECLARE_OPERATORS_FOR_FLAGS(QGLExtensions::Extensions) -struct QGLThreadContext { - QGLContext *context; -}; -extern QThreadStorage qgl_context_storage; - class QGLShareRegister { public: diff --git a/src/opengl/qgl_qws.cpp b/src/opengl/qgl_qws.cpp index 759f9de..7197776 100644 --- a/src/opengl/qgl_qws.cpp +++ b/src/opengl/qgl_qws.cpp @@ -260,13 +260,8 @@ void QGLContext::makeCurrent() return; } - if (d->eglContext->makeCurrent()) { - if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) - qgl_context_storage.setLocalData(new QGLThreadContext); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = this; - currentCtx = this; - } + if (d->eglContext->makeCurrent()) + QGLContextPrivate::setCurrentContext(this); } void QGLContext::doneCurrent() @@ -275,9 +270,7 @@ void QGLContext::doneCurrent() if (d->eglContext) d->eglContext->doneCurrent(); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = 0; - currentCtx = 0; + QGLContextPrivate::setCurrentContext(0); } diff --git a/src/opengl/qgl_win.cpp b/src/opengl/qgl_win.cpp index 78dad80..2f9e225 100644 --- a/src/opengl/qgl_win.cpp +++ b/src/opengl/qgl_win.cpp @@ -1173,11 +1173,7 @@ void QGLContext::makeCurrent() } if (wglMakeCurrent(d->dc, d->rc)) { - if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) - qgl_context_storage.setLocalData(new QGLThreadContext); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = this; - currentCtx = this; + QGLContextPrivate::setCurrentContext(this); } else { qwglError("QGLContext::makeCurrent()", "wglMakeCurrent"); } @@ -1187,10 +1183,8 @@ void QGLContext::makeCurrent() void QGLContext::doneCurrent() { Q_D(QGLContext); - currentCtx = 0; wglMakeCurrent(0, 0); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = 0; + QGLContextPrivate::setCurrentContext(0); if (deviceIsPixmap() && d->hbitmap) { QPixmap *pm = static_cast(d->paintDevice); *pm = QPixmap::fromWinHBITMAP(d->hbitmap); diff --git a/src/opengl/qgl_wince.cpp b/src/opengl/qgl_wince.cpp index 83efca8..4e655f1 100644 --- a/src/opengl/qgl_wince.cpp +++ b/src/opengl/qgl_wince.cpp @@ -450,13 +450,8 @@ void QGLContext::makeCurrent() return; } - if (d->eglContext->makeCurrent()) { - if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) - qgl_context_storage.setLocalData(new QGLThreadContext); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = this; - currentCtx = this; - } + if (d->eglContext->makeCurrent()) + QGLContextPrivate::setCurrentContext(this); } @@ -467,9 +462,7 @@ void QGLContext::doneCurrent() if (d->eglContext) d->eglContext->doneCurrent(); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = 0; - currentCtx = 0; + QGLContextPrivate::setCurrentContext(0); } void QGLContext::swapBuffers() const diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index cb1da18..da7972d 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -791,22 +791,15 @@ void QGLContext::makeCurrent() if (!ok) qWarning("QGLContext::makeCurrent(): Failed."); - if (ok) { - if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) - qgl_context_storage.setLocalData(new QGLThreadContext); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = this; - currentCtx = this; - } + if (ok) + QGLContextPrivate::setCurrentContext(this); } void QGLContext::doneCurrent() { Q_D(QGLContext); glXMakeCurrent(qt_x11Info(d->paintDevice)->display(), 0, 0); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = 0; - currentCtx = 0; + QGLContextPrivate::setCurrentContext(0); } diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index c54315f..7dfd642 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -146,13 +146,8 @@ void QGLContext::makeCurrent() return; } - if (d->eglContext->makeCurrent()) { - if (!qgl_context_storage.hasLocalData() && QThread::currentThread()) - qgl_context_storage.setLocalData(new QGLThreadContext); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = this; - currentCtx = this; - } + if (d->eglContext->makeCurrent()) + QGLContextPrivate::setCurrentContext(this); } void QGLContext::doneCurrent() @@ -161,9 +156,7 @@ void QGLContext::doneCurrent() if (d->eglContext) d->eglContext->doneCurrent(); - if (qgl_context_storage.hasLocalData()) - qgl_context_storage.localData()->context = 0; - currentCtx = 0; + QGLContextPrivate::setCurrentContext(0); } -- cgit v0.12 From 2cc93f74b531c653fde19c52f925b20b04c69b36 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 10 Sep 2009 07:42:20 +0200 Subject: Autotest preventing gl from crashing on shutdown with dangling contexts --- tests/auto/qgl/tst_qgl.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp index ebbfbae..a0b8b5d 100644 --- a/tests/auto/qgl/tst_qgl.cpp +++ b/tests/auto/qgl/tst_qgl.cpp @@ -81,6 +81,8 @@ private slots: void stackedFBOs(); void colormap(); void fboFormat(); + + void testDontCrashOnDanglingResources(); }; tst_QGL::tst_QGL() @@ -1513,5 +1515,16 @@ void tst_QGL::fboFormat() QVERIFY(format1c != format4c); } +void tst_QGL::testDontCrashOnDanglingResources() +{ + // We have a number of Q_GLOBAL_STATICS inside the QtOpenGL + // library. This test is verify that we don't crash as a result of + // them calling into libgl on application shutdown. + QWidget *widget = new UnclippedWidget(); + widget->show(); + qApp->processEvents(); + widget->hide(); +} + QTEST_MAIN(tst_QGL) #include "tst_qgl.moc" -- cgit v0.12 From b7f3fe8557f4c4b9ec90449649a9a929f8f50393 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Fri, 11 Sep 2009 09:26:08 +0200 Subject: fix compile error debug output --- src/gui/text/qfontdatabase_win.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/text/qfontdatabase_win.cpp b/src/gui/text/qfontdatabase_win.cpp index 6b874af..ae26dab 100644 --- a/src/gui/text/qfontdatabase_win.cpp +++ b/src/gui/text/qfontdatabase_win.cpp @@ -471,7 +471,7 @@ static void initializeDb() // print the database for (int f = 0; f < db->count; f++) { QtFontFamily *family = db->families[f]; - qDebug(" %s: %p", family->name.latin1(), family); + qDebug(" %s: %p", qPrintable(family->name), family); populate_database(family->name); #if 0 -- cgit v0.12 From 97ac103fb5a0139c007c8e2073a7a2cee1423618 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 14 Sep 2009 07:13:40 +0200 Subject: Fixed compilation of some ifdef'ed out debug messages. Reviewed-by: trustme --- src/gui/painting/qpaintengine_raster.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 46a3362..bac0a76 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -114,7 +114,7 @@ extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale); // // #define QT_DEBUG_DRAW #ifdef QT_DEBUG_DRAW -void dumpClip(int width, int height, QClipData *clip); +void dumpClip(int width, int height, const QClipData *clip); #endif #define QT_FAST_SPANS @@ -495,7 +495,7 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) << ") devType:" << device->devType() << "devRect:" << d->deviceRect; if (d->baseClip) { - dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), d->baseClip); + dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->baseClip); } #endif @@ -534,7 +534,7 @@ bool QRasterPaintEngine::end() Q_D(QRasterPaintEngine); qDebug() << "QRasterPaintEngine::end devRect:" << d->deviceRect; if (d->baseClip) { - dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), d->baseClip); + dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->baseClip); } #endif @@ -1181,6 +1181,11 @@ static void qrasterpaintengine_dirty_clip(QRasterPaintEnginePrivate *d, QRasterP d->solid_color_filler.clip = d->clip(); d->solid_color_filler.adjustSpanMethods(); + +#ifdef QT_DEBUG_DRAW + dumpClip(d->rasterBuffer->width(), d->rasterBuffer->height(), &*d->clip()); +#endif + } @@ -1780,9 +1785,7 @@ void QRasterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) if (path.isEmpty()) return; #ifdef QT_DEBUG_DRAW - QRealRect vectorPathBounds = path.controlPointRect(); - QRectF rf(vectorPathBounds.x1, vectorPathBounds.y1, - vectorPathBounds.x2 - vectorPathBounds.x1, vectorPathBounds.y2 - vectorPathBounds.y1); + QRectF rf = path.controlPointRect(); qDebug() << "QRasterPaintEngine::fill(): " << "size=" << path.elementCount() << ", hints=" << hex << path.hints() @@ -6068,7 +6071,7 @@ static void drawEllipse_midpoint_i(const QRect &rect, const QRect &clip, */ #ifdef QT_DEBUG_DRAW -void dumpClip(int width, int height, QClipData *clip) +void dumpClip(int width, int height, const QClipData *clip) { QImage clipImg(width, height, QImage::Format_ARGB32_Premultiplied); clipImg.fill(0xffff0000); @@ -6078,8 +6081,10 @@ void dumpClip(int width, int height, QClipData *clip) int y0 = height; int y1 = 0; + ((QClipData *) clip)->spans(); // Force allocation of the spans structure... + for (int i = 0; i < clip->count; ++i) { - QSpan *span = clip->spans() + i; + const QSpan *span = ((QClipData *) clip)->spans() + i; for (int j = 0; j < span->len; ++j) clipImg.setPixel(span->x + j, span->y, 0xffffff00); x0 = qMin(x0, int(span->x)); -- cgit v0.12 From 3aa5fec77b2e1edbcbd1d7735389725076f91cbf Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 14 Sep 2009 08:14:12 +0200 Subject: Fixed groupbox drawing on xp when hitting the fallback code. When swapping the alphachannel we need to make sure we create proper premultiplied pixels. When setting alpha to 0, that means also setting the other pixel values to 0. This bug was made visible by the gl graphics system. Reviewed-by: MariusSO --- src/gui/styles/qwindowsxpstyle.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/styles/qwindowsxpstyle.cpp b/src/gui/styles/qwindowsxpstyle.cpp index 5645950..0dc1832 100644 --- a/src/gui/styles/qwindowsxpstyle.cpp +++ b/src/gui/styles/qwindowsxpstyle.cpp @@ -586,7 +586,7 @@ bool QWindowsXPStylePrivate::swapAlphaChannel(const QRect &rect, bool allPixels) } register unsigned int alphaValue = (*buffer) & 0xFF000000; if (alphaValue == 0xFF000000) { - *buffer &= 0x00FFFFFF; + *buffer = 0; valueChange = true; } else if (alphaValue == 0) { *buffer |= 0xFF000000; -- cgit v0.12 From 2ffcf454806d0167c36bb626f07c3cc969206709 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Fri, 11 Sep 2009 10:18:12 +0200 Subject: Clean up properly in the QPF1 font engine We have to munmap() what we have mmap()ed Reviewed-by: Gunnar Reviewed-by: Jeremy --- src/gui/text/qfontengine_qws.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/gui/text/qfontengine_qws.cpp b/src/gui/text/qfontengine_qws.cpp index 0c988e0..730fc2c 100644 --- a/src/gui/text/qfontengine_qws.cpp +++ b/src/gui/text/qfontengine_qws.cpp @@ -380,6 +380,8 @@ class QFontEngineQPF1Data public: QPFFontMetrics fm; QPFGlyphTree *tree; + void *mmapStart; + size_t mmapLength; }; @@ -409,6 +411,8 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) ::close(f); d = new QFontEngineQPF1Data; + d->mmapStart = data; + d->mmapLength = st.st_size; memcpy(reinterpret_cast(&d->fm),data,sizeof(d->fm)); data += sizeof(d->fm); @@ -430,6 +434,8 @@ QFontEngineQPF1::QFontEngineQPF1(const QFontDef&, const QString &fn) QFontEngineQPF1::~QFontEngineQPF1() { + if (d->mmapStart) + munmap(d->mmapStart, d->mmapLength); delete d->tree; delete d; } -- cgit v0.12 From 8d596ad475a5874c9d271799ee65e0607658c82b Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 14 Sep 2009 10:38:45 +0200 Subject: Fixed bad gradient offsets on Mac OS X When an engine supports pixmap transformations natively, there will still be a redirection offset in the matrix even after calling resetMatrix(), so this is not enough, we need to set it to an actual identity. Reviewed-by: Trond --- src/gui/painting/qpainter.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp index a9257c7..beda9d6 100644 --- a/src/gui/painting/qpainter.cpp +++ b/src/gui/painting/qpainter.cpp @@ -475,7 +475,8 @@ void QPainterPrivate::draw_helper(const QPainterPath &originalPath, DrawOperatio p.end(); q->save(); - q->resetMatrix(); + state->matrix = QTransform(); + state->dirtyFlags |= QPaintEngine::DirtyTransform; updateState(state); engine->drawImage(absPathRect, image, -- cgit v0.12 From 9d075f383597f727b0c5c1e6bdbb9646e35c0fa0 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 14 Sep 2009 11:00:01 +0200 Subject: Fix drawTiledPixmap for NPOT pixmaps on OpenGL ES 2.0 OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead, we emulate GL_REPEAT by only taking the fractional part of the texture coords in the fragment shader. Task-number: 260982 Reviewed-by: Samuel --- src/opengl/gl2paintengineex/qglengineshadersource_p.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/opengl/gl2paintengineex/qglengineshadersource_p.h b/src/opengl/gl2paintengineex/qglengineshadersource_p.h index acd4461..6bcf010 100644 --- a/src/opengl/gl2paintengineex/qglengineshadersource_p.h +++ b/src/opengl/gl2paintengineex/qglengineshadersource_p.h @@ -260,12 +260,24 @@ static const char* const qglslPositionWithTextureBrushVertexShader = "\ static const char* const qglslAffinePositionWithTextureBrushVertexShader = qglslPositionWithTextureBrushVertexShader; +#if defined(QT_OPENGL_ES_2) +// OpenGL ES does not support GL_REPEAT wrap modes for NPOT textures. So instead, +// we emulate GL_REPEAT by only taking the fractional part of the texture coords. +// TODO: Special case POT textures which don't need this emulation +static const char* const qglslTextureBrushSrcFragmentShader = "\ + varying highp vec2 brushTextureCoords; \ + uniform lowp sampler2D brushTexture; \ + lowp vec4 srcPixel() { \ + return texture2D(brushTexture, fract(brushTextureCoords)); \ + }"; +#else static const char* const qglslTextureBrushSrcFragmentShader = "\ varying highp vec2 brushTextureCoords; \ uniform lowp sampler2D brushTexture; \ lowp vec4 srcPixel() { \ return texture2D(brushTexture, brushTextureCoords); \ }"; +#endif static const char* const qglslTextureBrushSrcWithPatternFragmentShader = "\ varying highp vec2 brushTextureCoords; \ -- cgit v0.12 From 24334c206e0611c2a8c5ef7265b96465c9459939 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 14 Sep 2009 11:15:51 +0200 Subject: Fixed crash in gl when stroking with a Qt::NoBrush pen Reviewed-by: Samuel --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index e32bbbd..adde89c 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1052,7 +1052,9 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) { Q_D(QGL2PaintEngineEx); - if (pen.style() == Qt::NoPen) + Qt::PenStyle penStyle = qpen_style(pen); + const QBrush &penBrush = qpen_brush(pen); + if (penStyle == Qt::NoPen || qbrush_style(penBrush) == Qt::NoBrush) return; ensureActive(); -- cgit v0.12 From 75426b7cd200a502d3a0b821c49ef3f1ea3029d2 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 14 Sep 2009 11:19:41 +0200 Subject: Some small optimizations to gl2 engine. Use qpen_ and qbrush_ accessors for slightly better performance and avoid calling for the same value again and again. Secondly, the engine doesn't use its pen and brush states so there is no point in maintaining them, so don't reset old brush all the time. Reviewed-by: Samuel --- .../gl2paintengineex/qglengineshadermanager.cpp | 4 ++- .../gl2paintengineex/qpaintengineex_opengl2.cpp | 37 +++++----------------- 2 files changed, 11 insertions(+), 30 deletions(-) diff --git a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp index 2d1885c..2502069 100644 --- a/src/opengl/gl2paintengineex/qglengineshadermanager.cpp +++ b/src/opengl/gl2paintengineex/qglengineshadermanager.cpp @@ -216,6 +216,8 @@ void QGLEngineSharedShaders::shaderDestroyed(QObject *shader) QGLShader *QGLEngineSharedShaders::compileNamedShader(ShaderName name, QGLShader::ShaderType type) { Q_ASSERT(name != CustomImageSrcFragmentShader); + Q_ASSERT(name < InvalidShaderName); + if (compiledShaders[name]) return compiledShaders[name]; @@ -514,7 +516,7 @@ bool QGLEngineShaderManager::useCorrectShaderProg() else switch (srcPixelType) { default: case Qt::NoBrush: - qCritical("QGLEngineShaderManager::useCorrectShaderProg() - I'm scared, Qt::NoBrush style is set"); + qFatal("QGLEngineShaderManager::useCorrectShaderProg() - Qt::NoBrush style is set"); break; case QGLEngineShaderManager::ImageSrc: srcPixelFragShaderName = QGLEngineSharedShaders::ImageSrcFragmentShader; diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index adde89c..ea5bec8 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1039,13 +1039,12 @@ void QGL2PaintEngineEx::fill(const QVectorPath &path, const QBrush &brush) { Q_D(QGL2PaintEngineEx); - if (brush.style() == Qt::NoBrush) + if (qbrush_style(brush) == Qt::NoBrush) return; if (!d->inRenderText) ensureActive(); d->setBrush(&brush); d->fill(path); - d->setBrush(&(state()->brush)); // reset back to the state's brush } void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) @@ -1059,42 +1058,26 @@ void QGL2PaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) ensureActive(); - if ( (pen.isCosmetic() && (pen.style() == Qt::SolidLine)) && (pen.widthF() < 2.5f) ) + qreal penWidth = qpen_widthf(pen); + if ( (pen.isCosmetic() && (penStyle == Qt::SolidLine)) && (penWidth < 2.5f) ) { // We only handle solid, cosmetic pens with a width of 1 pixel const QBrush& brush = pen.brush(); d->setBrush(&brush); - if (pen.widthF() < 0.01f) + if (penWidth < 0.01f) glLineWidth(1.0); else - glLineWidth(pen.widthF()); + glLineWidth(penWidth); d->drawOutline(path); - d->setBrush(&(state()->brush)); } else return QPaintEngineEx::stroke(path, pen); } -void QGL2PaintEngineEx::penChanged() -{ -// qDebug("QGL2PaintEngineEx::penChanged() not implemented!"); -} - - -void QGL2PaintEngineEx::brushChanged() -{ -// qDebug("QGL2PaintEngineEx::brushChanged()"); - Q_D(QGL2PaintEngineEx); - d->setBrush(&(state()->brush)); -} - -void QGL2PaintEngineEx::brushOriginChanged() -{ -// qDebug("QGL2PaintEngineEx::brushOriginChanged()"); - Q_D(QGL2PaintEngineEx); - d->brushUniformsDirty = true; -} +void QGL2PaintEngineEx::penChanged() { } +void QGL2PaintEngineEx::brushChanged() { } +void QGL2PaintEngineEx::brushOriginChanged() { } void QGL2PaintEngineEx::opacityChanged() { @@ -1302,8 +1285,6 @@ void QGL2PaintEngineExPrivate::drawCachedGlyphs(const QPointF &p, const QTextIte glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinateArray.data()); glDrawArrays(GL_TRIANGLES, 0, 6 * glyphs.size()); - - setBrush(&(q->state()->brush)); //### } bool QGL2PaintEngineEx::begin(QPaintDevice *pdev) @@ -1717,8 +1698,6 @@ void QGL2PaintEngineEx::setState(QPainterState *new_state) d->matrixDirty = true; d->compositionModeDirty = true; - d->brushTextureDirty = true; - d->brushUniformsDirty = true; d->simpleShaderDepthUniformDirty = true; d->depthUniformDirty = true; d->simpleShaderMatrixUniformDirty = true; -- cgit v0.12 From ab10c5b4be5c0d06edd79d8b4a8da090c1511d7e Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Mon, 14 Sep 2009 11:25:11 +0200 Subject: Don't call into paint engines when we don't have pens and brushes Reviewed-by: sroedal --- src/gui/painting/qpaintengineex.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index e75240c..656f383 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -535,8 +535,13 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) void QPaintEngineEx::draw(const QVectorPath &path) { - fill(path, state()->brush); - stroke(path, state()->pen); + const QBrush &brush = state()->brush; + if (qbrush_style(brush) != Qt::NoBrush) + fill(path, brush); + + const QPen &pen = state()->pen; + if (qpen_style(pen) != Qt::NoPen && qbrush_style(qpen_brush(pen)) != Qt::NoBrush) + stroke(path, pen); } -- cgit v0.12 From 2a46755b307adde38f7075f2add01224fd00846b Mon Sep 17 00:00:00 2001 From: Jure Repinc Date: Wed, 19 Aug 2009 12:01:40 +0200 Subject: Fixed a typo found during translation --- src/3rdparty/webkit/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp b/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp index 5cf86b1..43ef08e 100644 --- a/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp +++ b/src/3rdparty/webkit/WebKit/qt/WebCoreSupport/FrameLoaderClientQt.cpp @@ -723,7 +723,7 @@ WebCore::ResourceError FrameLoaderClientQt::cannotShowURLError(const WebCore::Re WebCore::ResourceError FrameLoaderClientQt::interruptForPolicyChangeError(const WebCore::ResourceRequest& request) { return ResourceError("Error", WebKitErrorFrameLoadInterruptedByPolicyChange, request.url().string(), - QCoreApplication::translate("QWebFrame", "Frame load interruped by policy change", 0, QCoreApplication::UnicodeUTF8)); + QCoreApplication::translate("QWebFrame", "Frame load interrupted by policy change", 0, QCoreApplication::UnicodeUTF8)); } WebCore::ResourceError FrameLoaderClientQt::cannotShowMIMETypeError(const WebCore::ResourceResponse& response) -- cgit v0.12 From f44fe888ee82b9e04879fb353d8f5f29fb4d5229 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 14 Sep 2009 12:59:39 +0200 Subject: Fix RTL text alignment in QComboBox items with SH_ComboBox_Popup Change 93ba0035f4eadfaf7217d95f18a442d418a064b8 removed truncation of a listview item's bounding rect to the viewport as documented in the commit log. An unwanted result was that the style option passed to the item delegates would sometimes contain a rectangle which was larger than the delegated area. The direct result was that a QComboBox drawn with a style with the SH_Combobox_Popup style hint in an RTL language would align its item text to the right edge of a rectangle which was wider than the popup menu, and thus only part of the text would be visible. Task-number: 260974 Reviewed-by: Olivier --- src/gui/itemviews/qlistview.cpp | 6 ++++++ tests/auto/qcombobox/tst_qcombobox.cpp | 36 ++++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/src/gui/itemviews/qlistview.cpp b/src/gui/itemviews/qlistview.cpp index cbb54d8..a4cebe3 100644 --- a/src/gui/itemviews/qlistview.cpp +++ b/src/gui/itemviews/qlistview.cpp @@ -965,6 +965,12 @@ void QListView::paintEvent(QPaintEvent *e) for (QVector::const_iterator it = toBeRendered.constBegin(); it != end; ++it) { Q_ASSERT((*it).isValid()); option.rect = visualRect(*it); + + if (flow() == TopToBottom) + option.rect.setWidth(qMin(viewport()->size().width(), option.rect.width())); + else + option.rect.setHeight(qMin(viewport()->size().height(), option.rect.height())); + option.state = state; if (selections && selections->isSelected(*it)) option.state |= QStyle::State_Selected; diff --git a/tests/auto/qcombobox/tst_qcombobox.cpp b/tests/auto/qcombobox/tst_qcombobox.cpp index e75b9cd..810be04 100644 --- a/tests/auto/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/qcombobox/tst_qcombobox.cpp @@ -147,6 +147,7 @@ private slots: void task253944_itemDelegateIsReset(); void subControlRectsWithOffset_data(); void subControlRectsWithOffset(); + void task260974_menuItemRectangleForComboBoxPopup(); protected slots: void onEditTextChanged( const QString &newString ); @@ -2339,5 +2340,40 @@ void tst_QComboBox::subControlRectsWithOffset() } +void tst_QComboBox::task260974_menuItemRectangleForComboBoxPopup() +{ + class TestStyle: public QWindowsStyle + { + public: + int styleHint(StyleHint hint, const QStyleOption *option, const QWidget *widget, QStyleHintReturn *ret) const + { + if (hint == SH_ComboBox_Popup) return 1; + else return QCommonStyle::styleHint(hint, option, widget, ret); + } + + void drawControl(ControlElement element, const QStyleOption *option, QPainter *, const QWidget *) const + { + if (element == CE_MenuItem) + discoveredRect = option->rect; + } + + mutable QRect discoveredRect; + } style; + + + { + QComboBox comboBox; + comboBox.setStyle(&style); + comboBox.addItem("Item 1"); + + comboBox.show(); + QTest::qWait(100); + comboBox.showPopup(); + QTest::qWait(100); + + QVERIFY(style.discoveredRect.width() <= comboBox.width()); + } +} + QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" -- cgit v0.12 From 7bd5a850ddb247f36fb46f25eb239a126388aff9 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 14 Sep 2009 13:19:33 +0200 Subject: Doc: Ongoing improvements. Reviewed-by: Trust Me --- doc/src/getting-started/examples.qdoc | 153 ++++++++++++++++++---------------- doc/src/modules.qdoc | 4 +- 2 files changed, 84 insertions(+), 73 deletions(-) diff --git a/doc/src/getting-started/examples.qdoc b/doc/src/getting-started/examples.qdoc index 0795c37..81a8363 100644 --- a/doc/src/getting-started/examples.qdoc +++ b/doc/src/getting-started/examples.qdoc @@ -79,8 +79,8 @@ \o{2,1} \l{Widgets Examples}{\bold Widgets} \o{2,1} \l{Dialog Examples}{\bold Dialogs} \row - \i \image widget-examples.png - \i + \o \image widget-examples.png + \o Qt comes with a large range of standard widgets that users of modern applications have come to expect. You can also develop your own custom widgets and controls, and use them alongside standard widgets. @@ -89,28 +89,28 @@ be used to change the appearance of standard widgets and appropriately written custom widgets. - \i \image dialog-examples.png Dialogs - \i + \o \image dialog-examples.png Dialogs + \o Qt includes standard dialogs for many common operations, such as file selection, printing, and color selection. Custom dialogs can also be created for specialized modal or modeless interactions with users. - \row - \o{2,1} \l{Main Window Examples}{\bold{Main Windows}} - \o{2,1} \l{Layout Examples}{\bold Layouts} + \row + \o{2,1} \l{Main Window Examples}{\bold{Main Windows}} + \o{2,1} \l{Layout Examples}{\bold Layouts} - \row - \i \image mainwindow-examples.png MainWindows - \i All the standard features of application main windows are provided by Qt. + \row + \o \image mainwindow-examples.png MainWindows + \o All the standard features of application main windows are provided by Qt. Main windows can have pull down menus, tool bars, and dock windows. These separate forms of user input are unified in an integrated action system that also supports keyboard shortcuts and accelerator keys in menu items. - \i \image layout-examples.png Layouts - \i + \o \image layout-examples.png Layouts + \o Qt uses a layout-based approach to widget management. Widgets are arranged in the optimal positions in windows based on simple layout rules, leading to a consistent look and feel. @@ -118,10 +118,10 @@ Custom layouts can be used to provide more control over the positions and sizes of child widgets. - \row - \o{2,1} \l{Item Views Examples}{\bold{Item Views}} - \o{2,1} \l{Graphics View Examples}{\bold{Graphics View}} - \row + \row + \o{2,1} \l{Item Views Examples}{\bold{Item Views}} + \o{2,1} \l{Graphics View Examples}{\bold{Graphics View}} + \row \o \image itemview-examples.png ItemViews \o Item views are widgets that typically display data sets. Qt 4's model/view @@ -129,21 +129,21 @@ from the way it is represented to the user, and provides support for customized rendering through the use of delegates. - \o \image graphicsview-examples.png GraphicsView - \o + \o \image graphicsview-examples.png GraphicsView + \o Qt is provided with a comprehensive canvas through the GraphicsView classes. - \row - \o{2,1} \l{Painting Examples}{\bold{Painting}} - \o{2,1} \l{Rich Text Examples}{\bold{Rich Text}} - \row - \o \image painting-examples.png Painting - \o - Qt's painting system is able to render vector graphics, images, and outline + \row + \o{2,1} \l{Painting Examples}{\bold{Painting}} + \o{2,1} \l{Rich Text Examples}{\bold{Rich Text}} + \row + \o \image painting-examples.png Painting + \o + Qt's painting system is able to render vector graphics, images, and outline font-based text with sub-pixel accuracy accuracy using anti-aliasing to improve rendering quality. - + \o \image richtext-examples.png RichText \o Qt provides powerful document-oriented rich text engine that supports Unicode @@ -151,10 +151,10 @@ API, and their contents can be imported and exported as both HTML and in a custom XML format. - \row - \o{2,1} \l{Desktop Examples}{\bold Desktop} - \o{2,1} \l{Drag and Drop Examples}{\bold{Drag and Drop}} - \row + \row + \o{2,1} \l{Desktop Examples}{\bold Desktop} + \o{2,1} \l{Drag and Drop Examples}{\bold{Drag and Drop}} + \row \o \image desktop-examples.png \o Qt provides features to enable applications to integrate with the user's @@ -172,9 +172,9 @@ Drag and drop can also be implemented for internal use by applications. - \row - \o{2,1} \l{Threading and Concurrent Programming Examples}{\bold{Threading and Concurrent Programming}} - \o{2,1} \l{Tools Examples}{\bold{Tools}} + \row + \o{2,1} \l{Threading and Concurrent Programming Examples}{\bold{Threading and Concurrent Programming}} + \o{2,1} \l{Tools Examples}{\bold{Tools}} \row \o \image thread-examples.png \o @@ -185,7 +185,7 @@ The QtConcurrent namespace includes a collection of classes and functions for straightforward concurrent programming. - \o \image tool-examples.png Tools + \o \image tool-examples.png Tools \o Qt is equipped with a range of capable tool classes, from containers and iterators to classes for string handling and manipulation. @@ -193,21 +193,21 @@ Other classes provide application infrastructure support, handling plugin loading and managing configuration files. - \row - \o{2,1} \l{Network Examples}{\bold{Network}} - \o{2,1} \l{Inter-Process Communication Examples}{\bold{Inter-Process Communication}} + \row + \o{2,1} \l{Network Examples}{\bold{Network}} + \o{2,1} \l{Inter-Process Communication Examples}{\bold{Inter-Process Communication}} \row \o \image network-examples.png Network \o Qt is provided with an extensive set of network classes to support both client-based and server side network programming. - + \o \image ipc-examples.png IPC \o - \row - \o{2,1} \l{OpenGL Examples}{\bold OpenGL} - \o{2,1} \l{Multimedia Examples}{\bold{Multimedia Framework}} + \row + \o{2,1} \l{OpenGL Examples}{\bold OpenGL} + \o{2,1} \l{Multimedia Examples}{\bold{Multimedia Framework}} \row \o \image opengl-examples.png OpenGL \o @@ -223,9 +223,9 @@ The Phonon Multimedia Framework brings multimedia support to Qt applications. - \row - \o{2,1} \l{SQL Examples}{\bold{SQL}} - \o{2,1} \l{XML Examples}{\bold{XML}} + \row + \o{2,1} \l{SQL Examples}{\bold{SQL}} + \o{2,1} \l{XML Examples}{\bold{XML}} \row \o \image sql-examples.png SQL \o @@ -234,7 +234,7 @@ SQL support is integrated with Qt's model/view architecture, making it easier to provide GUI integration for your database applications. - + \o \image xml-examples.png XML \o XML parsing and handling is supported through SAX and DOM compliant APIs @@ -243,9 +243,9 @@ The XQuery/XPath and XML Schema engines in the QtXmlPatterns modules provide classes for querying XML files and custom data models. - \row - \o{2,1} \l{Qt Designer Examples}{\bold{Qt Designer}} - \o{2,1} \l{UiTools Examples}{\bold UiTools} + \row + \o{2,1} \l{Qt Designer Examples}{\bold{Qt Designer}} + \o{2,1} \l{UiTools Examples}{\bold UiTools} \row \o \image designer-examples.png Designer \o @@ -256,9 +256,9 @@ \o \image uitools-examples.png UiTools \o - \row - \o{2,1} \l{Qt Linguist Examples}{\bold{Qt Linguist}} - \o{2,1} \l{Qt Script Examples}{\bold{Qt Script}} + \row + \o{2,1} \l{Qt Linguist Examples}{\bold{Qt Linguist}} + \o{2,1} \l{Qt Script Examples}{\bold{Qt Script}} \row \o \image linguist-examples.png QtLinguist \o @@ -269,10 +269,10 @@ Qt is provided with a powerful embedded scripting environment through the QtScript classes. - \row - \o{2,1} \l{WebKit Examples}{\bold WebKit} - \o{2,1} \l{Help System Examples}{\bold{Help System}} - \row + \row + \o{2,1} \l{WebKit Examples}{\bold WebKit} + \o{2,1} \l{Help System Examples}{\bold{Help System}} + \row \o \image webkit-examples.png \o Qt provides an integrated Web browser component based on WebKit, the popular @@ -284,37 +284,48 @@ Developers can take advantages of the facilities it offers to display specially-prepared documentation to users of their applications. - \row - \o{2,1} \l{State Machine Examples}{\bold{State Machine}} - \o{2,1} \l{Animation Framework Examples}{\bold{Animation Framework}} + \row + \o{2,1} \l{State Machine Examples}{\bold{State Machine}} + \o{2,1} \l{Animation Framework Examples}{\bold{Animation Framework}} \row \o \image statemachine-examples.png \o Qt provides a powerful hierarchical finite state machine through the Qt State Machine classes. - + \o \image animation-examples.png \o - \row - \o{2,1} \l{Qt for Embedded Linux Examples}{\bold{Qt for Embedded Linux}} - \o{2,1} \l{ActiveQt Examples}{\bold ActiveQt} + \row + \o{2,1} \l{Gestures Examples}{\bold{Gestures}} + \o{2,1} \l{D-Bus Examples}{\bold{D-Bus}} + \row + \o \image gestures-examples.png + \o + Applications can be written to respond to gestures as a natural input method. + These examples show how to enable support for standard and custom gestures in + applications. + + \o \image dbus-examples.png D-Bus + \o + D-Bus is an inter-process communication protocol for Unix/Linux systems. + These examples demonstrate how to write application that communicate with + each other. + \row + \o{2,1} \l{Qt for Embedded Linux Examples}{\bold{Qt for Embedded Linux}} + \o{2,1} \l{ActiveQt Examples}{\bold ActiveQt} \row \o \image qt-embedded-examples.png \o Systems with limited resources, specialized hardware, and small screens require special attention. - + \o \image activeqt-examples.png ActiveQt \o - \row - \o{2,1} \l{D-Bus Examples}{\bold{D-Bus}} - \o{2,1} \l{Qt Quarterly}{\bold{Qt Quarterly}} \row - \o \image dbus-examples.png D-Bus - \o - + \o{2,1} \l{Qt Quarterly}{\bold{Qt Quarterly}} + \row \o \image qq-thumbnail.png QtQuarterly \o One more valuable source for examples and explanations of Qt @@ -322,12 +333,12 @@ \endtable -\omit + \omit In the list below, examples marked with an asterisk (*) are fully documented. Eventually, all the examples will be fully documented, but sometimes we include an example before we have time to write about it. -\endomit + \endomit */ /*! diff --git a/doc/src/modules.qdoc b/doc/src/modules.qdoc index 1c63d46..bbdae9d 100644 --- a/doc/src/modules.qdoc +++ b/doc/src/modules.qdoc @@ -919,8 +919,8 @@ \target The QDBus compiler \brief The QtDBus module is a Unix-only library that you can use - to make Inter-Process Communication using the \l {Introduction to - D-Bus} {D-Bus} protocol. + to perform Inter-Process Communication using the \l{Introduction to + D-Bus}{D-Bus} protocol. Applications using the QtDBus module can provide services to other, remote applications by exporting objects, as well as use -- cgit v0.12 From 30d958f87e6f244d4e8b6704d31e07940a874d02 Mon Sep 17 00:00:00 2001 From: David Boddie Date: Mon, 14 Sep 2009 13:22:27 +0200 Subject: Doc: Fixed grammar. Reviewed-by: Trust Me --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 43aa739..4efdde5 100755 --- a/configure +++ b/configure @@ -3752,7 +3752,7 @@ Qt for Embedded Linux only: proper license for this switch to work. Example values for : arm mips x86 generic - -armfpa ............. Target platform is uses the ARM-FPA floating point format. + -armfpa ............. Target platform uses the ARM-FPA floating point format. -no-armfpa .......... Target platform does not use the ARM-FPA floating point format. The floating point format is usually autodetected by configure. Use this -- cgit v0.12 From 41dbc4406791f82b7e3c1385acc594e22b5b0799 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 14 Sep 2009 14:04:48 +0200 Subject: Fix QMenuBar hover effect. Regression introduced by commit 21cf7b4c431742 Task-number: 261199 Reviewed-by: Prasanth --- src/gui/widgets/qmenubar.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index d5a7982..8591a77 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1252,9 +1252,7 @@ void QMenuBar::keyPressEvent(QKeyEvent *e) void QMenuBar::mouseMoveEvent(QMouseEvent *e) { Q_D(QMenuBar); - bool popupState = d->popupState || e->buttons() & Qt::LeftButton; - if (!d->mouseDown || !popupState) - return; + bool popupState = d->popupState || d->mouseDown; QAction *action = d->actionAt(e->pos()); if (action && d->isVisible(action)) d->setCurrentAction(action, popupState); -- cgit v0.12 From 89620720e9969360254f950fc63d131d82dd3471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?= Date: Fri, 11 Sep 2009 12:34:08 +0200 Subject: API change. This will get rid of the ugly setAnchorSpacing() method. Say hello to QGraphicsAnchor, move the spacing (and removeAnchor) functionality over to that class. This also opens up for a cleaner API when we add support for size policies or min/pref/max sizes for anchors. Also remove - addLeftAndRightAnchors() - addTopAndBottomAnchors() - addAllAnchors() in favor of - addAnchors(itemA, itemB, Qt::Orientations) API change discussed with Caio and Andreas. Reviewed-by: Alexis --- examples/graphicsview/anchorlayout/main.cpp | 83 ++++----- src/gui/graphicsview/qgraphicsanchorlayout.cpp | 185 ++++++++++---------- src/gui/graphicsview/qgraphicsanchorlayout.h | 73 ++++---- src/gui/graphicsview/qgraphicsanchorlayout_p.cpp | 168 +++++++++++++------ src/gui/graphicsview/qgraphicsanchorlayout_p.h | 66 ++++++-- .../tst_qgraphicsanchorlayout.cpp | 186 ++++++++------------- .../tst_qgraphicsanchorlayout.cpp | 4 +- 7 files changed, 393 insertions(+), 372 deletions(-) diff --git a/examples/graphicsview/anchorlayout/main.cpp b/examples/graphicsview/anchorlayout/main.cpp index 4269eaa..a4bf1d0 100644 --- a/examples/graphicsview/anchorlayout/main.cpp +++ b/examples/graphicsview/anchorlayout/main.cpp @@ -79,66 +79,45 @@ int main(int argc, char **argv) QGraphicsProxyWidget *g = createItem(QSizeF(30, 50), QSizeF(30, 100), maxSize, "G"); QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; + l->setSpacing(0); QGraphicsWidget *w = new QGraphicsWidget(0, Qt::Window); w->setPos(20, 20); w->setLayout(l); // vertical - l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorTop, l, Qt::AnchorTop, 0); - l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorTop, l, Qt::AnchorTop, 0); - - l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorTop, a, Qt::AnchorBottom, 0); - l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorTop, b, Qt::AnchorBottom, 0); - l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); - l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, e, Qt::AnchorTop, 0); - - l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(d, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); - l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(e, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); - - l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorTop, f, Qt::AnchorTop, 0); - l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom, 0); - l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop); - l->setAnchorSpacing(f, Qt::AnchorBottom, g, Qt::AnchorTop, 0); - l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorBottom, g, Qt::AnchorBottom, 0); + QGraphicsAnchor *anchor = l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop); + anchor = l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop); + + anchor = l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom); + anchor = l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom); + anchor = l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); + anchor = l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop); + + anchor = l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom); + anchor = l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom); + + anchor = l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop); + anchor = l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom); + anchor = l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop); + anchor = l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom); // horizontal - l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); - l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, d, Qt::AnchorLeft, 0); - l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorLeft, 0); - - l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, c, Qt::AnchorLeft, 0); - l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(c, Qt::AnchorRight, e, Qt::AnchorLeft, 0); - - l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(b, Qt::AnchorRight, l, Qt::AnchorRight, 0); - l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(e, Qt::AnchorRight, l, Qt::AnchorRight, 0); - l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(d, Qt::AnchorRight, e, Qt::AnchorLeft, 0); - - l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, f, Qt::AnchorLeft, 0); - l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, g, Qt::AnchorLeft, 0); - l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight); - l->setAnchorSpacing(f, Qt::AnchorRight, g, Qt::AnchorRight, 0); + anchor = l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); + anchor = l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft); + anchor = l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); + + anchor = l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); + anchor = l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft); + + anchor = l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight); + anchor = l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight); + anchor = l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft); + + anchor = l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft); + anchor = l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft); + anchor = l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight); + scene.addItem(w); scene.setBackgroundBrush(Qt::darkGreen); diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.cpp b/src/gui/graphicsview/qgraphicsanchorlayout.cpp index c7033c6..f57f65f 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout.cpp @@ -84,6 +84,55 @@ QT_BEGIN_NAMESPACE +QGraphicsAnchor::QGraphicsAnchor(QGraphicsAnchorLayout *parentLayout) + : QObject(*(new QGraphicsAnchorPrivate)) +{ + Q_D(QGraphicsAnchor); + Q_ASSERT(parentLayout); + d->layoutPrivate = parentLayout->d_func(); +} + +/*! + Removes the QGraphicsAnchor object from the layout and destroys it. +*/ +QGraphicsAnchor::~QGraphicsAnchor() +{ +} + +/*! + Set the spacing for the anchor to \a spacing. + + \sa spacing(), unsetSpacing() +*/ +void QGraphicsAnchor::setSpacing(qreal spacing) +{ + Q_D(QGraphicsAnchor); + d->setSpacing(spacing); +} + +/*! + Returns the spacing for the anchor + + \sa setSpacing() +*/ +qreal QGraphicsAnchor::spacing() const +{ + Q_D(const QGraphicsAnchor); + return d->spacing(); +} + +/*! + Resets the spacing of the anchor point to be the default spacing. Depending on the anchor type, + the default spacing is either 0 or a value returned from the style. + + \sa setSpacing(), spacing(), QGraphicsAnchorLayout::anchor() +*/ +void QGraphicsAnchor::unsetSpacing() +{ + Q_D(QGraphicsAnchor); + d->unsetSpacing(); +} + /*! Constructs a QGraphicsAnchorLayout instance. \a parent is passed to QGraphicsLayout's constructor. @@ -136,17 +185,30 @@ QGraphicsAnchorLayout::~QGraphicsAnchorLayout() * the default vertical spacing). For all other anchor combinations, the spacing will be 0. * All anchoring functions will follow this rule. * - * The spacing can also be set manually by using setAnchorSpacing() method. + * The spacing can also be set manually by using QGraphicsAnchor::setSpacing() method. * - * \sa removeAnchor(), addCornerAnchors(), addLeftAndRightAnchors(), addTopAndBottomAnchors(), - * addAllAnchors() + * \sa addCornerAnchors(), addAnchors() */ -void QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) +QGraphicsAnchor * +QGraphicsAnchorLayout::addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) { Q_D(QGraphicsAnchorLayout); - d->anchor(firstItem, firstEdge, secondItem, secondEdge); + QGraphicsAnchor *a = d->anchor(firstItem, firstEdge, secondItem, secondEdge); invalidate(); + return a; +} + +/*! + Returns the anchor between the anchor points defined by \a firstItem and \a firstEdge and + \a secondItem and \a secondEdge. If there is no such anchor, the function will return 0. +*/ +QGraphicsAnchor * +QGraphicsAnchorLayout::anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) +{ + Q_D(QGraphicsAnchorLayout); + return d->getAnchor(firstItem, firstEdge, secondItem, secondEdge); } /*! @@ -195,6 +257,37 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, } /*! + Anchors two or four edges of \a firstItem with the corresponding edges of \secondItem, + so that \a firstItem has the same size as \a secondItem in the dimensions specified by + \a orientation. + + Calling this convenience function with the following arguments + \code + l->addAnchors(firstItem, secondItem, Qt::Horizontal) + \endcode + + is the same as + + \code + l->addAnchor(firstItem, Qt::AnchorLeft, secondItem, Qt::AnchorLeft); + l->addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); + \endcode +*/ +void QGraphicsAnchorLayout::addAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem, + Qt::Orientations orientations) +{ + if (orientations & Qt::Horizontal) { + addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft); + addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); + } + if (orientations & Qt::Vertical) { + addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); + addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); + } +} + +/*! \fn QGraphicsAnchorLayout::addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem, QGraphicsLayoutItem *secondItem) Anchors the left and right edges of \a firstItem to the same edges of @@ -234,86 +327,6 @@ void QGraphicsAnchorLayout::addCornerAnchors(QGraphicsLayoutItem *firstItem, */ /*! - Set the spacing between the anchor point defined by \a firstItem and \a firstEdge and - \a secondItem and \a secondEdge to be \a spacing. -*/ -void QGraphicsAnchorLayout::setAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, - qreal spacing) -{ - Q_D(QGraphicsAnchorLayout); - - if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, &spacing)) { - qWarning("setAnchorSpacing: The anchor does not exist."); - return; - } - invalidate(); -} - -/*! - Returns the spacing between the anchor point defined by \a firstItem and \a firstEdge and - \a secondItem and \a secondEdge. The anchor must exist. -*/ -qreal QGraphicsAnchorLayout::anchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) const -{ - Q_D(const QGraphicsAnchorLayout); - qreal size = 0; - if (!d->anchorSize(firstItem, firstEdge, secondItem, secondEdge, 0, &size)) { - qWarning("anchorSpacing: The anchor does not exist."); - } - return size; -} - -/*! - Resets the spacing between the anchor point defined by \a firstItem and \a firstEdge and - \a secondItem and \a secondEdge to be the default spacing. Depending on the anchor type, the - default spacing is either 0 or a value returned from the style. - - \sa setAnchorSpacing(), anchorSpacing(), addAnchor() -*/ -void QGraphicsAnchorLayout::unsetAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) -{ - Q_D(QGraphicsAnchorLayout); - - if (!d->setAnchorSize(firstItem, firstEdge, secondItem, secondEdge, 0)) { - qWarning("unsetAnchorSpacing: The anchor does not exist."); - } - invalidate(); -} - -/*! - Removes the anchor between the edge \a firstEdge of item \a firstItem and the edge \a secondEdge - of item \a secondItem. If such an anchor does not exist, the layout will be left unchanged. -*/ -void QGraphicsAnchorLayout::removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) -{ - Q_D(QGraphicsAnchorLayout); - if ((firstItem == 0) || (secondItem == 0)) { - qWarning("QGraphicsAnchorLayout::removeAnchor: " - "Cannot remove anchor between NULL items"); - return; - } - - if (firstItem == secondItem) { - qWarning("QGraphicsAnchorLayout::removeAnchor: " - "Cannot remove anchor from the item to itself"); - return; - } - - if (d->edgeOrientation(secondEdge) != d->edgeOrientation(firstEdge)) { - qWarning("QGraphicsAnchorLayout::removeAnchor: " - "Cannot remove anchor from edges of different orientations"); - return; - } - - d->removeAnchor(firstItem, firstEdge, secondItem, secondEdge); - invalidate(); -} - -/*! Sets the default horizontal spacing for the anchor layout to \a spacing. \sa horizontalSpacing(), setVerticalSpacing(), setSpacing() diff --git a/src/gui/graphicsview/qgraphicsanchorlayout.h b/src/gui/graphicsview/qgraphicsanchorlayout.h index 70b73ef..d9a87ba 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout.h @@ -54,41 +54,44 @@ QT_MODULE(Gui) #if !defined(QT_NO_GRAPHICSVIEW) || (QT_EDITION & QT_MODULE_GRAPHICSVIEW) != QT_MODULE_GRAPHICSVIEW +class QGraphicsAnchorPrivate; +class QGraphicsAnchorLayout; class QGraphicsAnchorLayoutPrivate; +class Q_GUI_EXPORT QGraphicsAnchor : public QObject +{ + Q_OBJECT + Q_PROPERTY(qreal spacing READ spacing WRITE setSpacing) +public: + void setSpacing(qreal spacing); + void unsetSpacing(); + qreal spacing() const; + ~QGraphicsAnchor(); +private: + QGraphicsAnchor(QGraphicsAnchorLayout *parent); + + Q_DECLARE_PRIVATE(QGraphicsAnchor) + + friend class QGraphicsAnchorLayoutPrivate; +}; + class Q_GUI_EXPORT QGraphicsAnchorLayout : public QGraphicsLayout { public: QGraphicsAnchorLayout(QGraphicsLayoutItem *parent = 0); virtual ~QGraphicsAnchorLayout(); - void addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + QGraphicsAnchor *addAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + QGraphicsAnchor *anchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); void addCornerAnchors(QGraphicsLayoutItem *firstItem, Qt::Corner firstCorner, QGraphicsLayoutItem *secondItem, Qt::Corner secondCorner); - inline void addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem); - - inline void addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem); - - inline void addAllAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem); - - void setAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge, - qreal spacing); - - qreal anchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) const; - - void unsetAnchorSpacing(const QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - - void removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + void addAnchors(QGraphicsLayoutItem *firstItem, + QGraphicsLayoutItem *secondItem, + Qt::Orientations orientations = Qt::Horizontal | Qt::Vertical); void setHorizontalSpacing(qreal spacing); void setVerticalSpacing(qreal spacing); @@ -108,29 +111,9 @@ protected: private: Q_DISABLE_COPY(QGraphicsAnchorLayout) Q_DECLARE_PRIVATE(QGraphicsAnchorLayout) -}; - -void QGraphicsAnchorLayout::addLeftAndRightAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem) -{ - addAnchor(secondItem, Qt::AnchorLeft, firstItem, Qt::AnchorLeft); - addAnchor(firstItem, Qt::AnchorRight, secondItem, Qt::AnchorRight); -} - -void QGraphicsAnchorLayout::addTopAndBottomAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem) -{ - addAnchor(secondItem, Qt::AnchorTop, firstItem, Qt::AnchorTop); - addAnchor(firstItem, Qt::AnchorBottom, secondItem, Qt::AnchorBottom); -} - -void QGraphicsAnchorLayout::addAllAnchors(QGraphicsLayoutItem *firstItem, - QGraphicsLayoutItem *secondItem) -{ - addLeftAndRightAnchors(firstItem, secondItem); - addTopAndBottomAnchors(firstItem, secondItem); -} + friend class QGraphicsAnchor; +}; #endif diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp index f81ede0..a37ec96 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.cpp @@ -51,6 +51,47 @@ QT_BEGIN_NAMESPACE + +QGraphicsAnchorPrivate::QGraphicsAnchorPrivate(int version) + : QObjectPrivate(version), layoutPrivate(0), data(0) +{ +} + +QGraphicsAnchorPrivate::~QGraphicsAnchorPrivate() +{ + layoutPrivate->deleteAnchorData(data); +} + +void QGraphicsAnchorPrivate::setSpacing(qreal value) +{ + if (data) { + layoutPrivate->setAnchorSize(data, &value); + } else { + qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + } +} + +void QGraphicsAnchorPrivate::unsetSpacing() +{ + if (data) { + layoutPrivate->setAnchorSize(data, 0); + } else { + qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + } +} + +qreal QGraphicsAnchorPrivate::spacing() const +{ + qreal size = 0; + if (data) { + layoutPrivate->anchorSize(data, 0, &size, 0); + } else { + qWarning("QGraphicsAnchor::setSpacing: The anchor does not exist."); + } + return size; +} + + void AnchorData::refreshSizeHints(qreal effectiveSpacing) { if (!isLayoutAnchor && from->m_item == to->m_item) { @@ -998,29 +1039,29 @@ void QGraphicsAnchorLayoutPrivate::removeCenterConstraints(QGraphicsLayoutItem * * 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. */ -void QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - qreal *spacing) +QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *spacing) { Q_Q(QGraphicsAnchorLayout); if ((firstItem == 0) || (secondItem == 0)) { qWarning("QGraphicsAnchorLayout::addAnchor(): " "Cannot anchor NULL items"); - return; + return 0; } if (firstItem == secondItem) { qWarning("QGraphicsAnchorLayout::addAnchor(): " "Cannot anchor the item to itself"); - return; + return 0; } if (edgeOrientation(secondEdge) != edgeOrientation(firstEdge)) { qWarning("QGraphicsAnchorLayout::addAnchor(): " "Cannot anchor edges of different orientations"); - return; + return 0; } // Guarantee that the graph is no simplified when adding this anchor, @@ -1079,6 +1120,7 @@ void QGraphicsAnchorLayoutPrivate::anchor(QGraphicsLayoutItem *firstItem, data = new AnchorData(-*spacing); addAnchor(secondItem, secondEdge, firstItem, firstEdge, data); } + return acquireGraphicsAnchor(data); } void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, @@ -1117,77 +1159,97 @@ void QGraphicsAnchorLayoutPrivate::addAnchor(QGraphicsLayoutItem *firstItem, graph[edgeOrientation(firstEdge)].createEdge(v1, v2, data); } +QGraphicsAnchor *QGraphicsAnchorLayoutPrivate::getAnchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge) +{ + Orientation orient = edgeOrientation(firstEdge); + restoreSimplifiedGraph(orient); + + AnchorVertex *v1 = internalVertex(firstItem, firstEdge); + AnchorVertex *v2 = internalVertex(secondItem, secondEdge); + + QGraphicsAnchor *graphicsAnchor = 0; + + AnchorData *data = graph[orient].edgeData(v1, v2); + if (data) + graphicsAnchor = acquireGraphicsAnchor(data); + return graphicsAnchor; +} + void QGraphicsAnchorLayoutPrivate::removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge) { - // Guarantee that the graph is no simplified when adding this anchor, - // anchor manipulation always happen in the full graph - restoreSimplifiedGraph(edgeOrientation(firstEdge)); - - // Look for both vertices - AnchorVertex *v1 = internalVertex(firstItem, firstEdge); - AnchorVertex *v2 = internalVertex(secondItem, secondEdge); + removeAnchor_helper(internalVertex(firstItem, firstEdge), + internalVertex(secondItem, secondEdge)); +} +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 - graph[edgeOrientation(firstEdge)].removeEdge(v1, v2); + graph[o].removeEdge(v1, v2); // Decrease vertices reference count (may trigger a deletion) - removeInternalVertex(firstItem, firstEdge); - removeInternalVertex(secondItem, secondEdge); + removeInternalVertex(v1->m_item, v1->m_edge); + removeInternalVertex(v2->m_item, v2->m_edge); } -bool QGraphicsAnchorLayoutPrivate::setAnchorSize(const QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - const qreal *anchorSize) +/*! + \internal + Only called from outside. (calls invalidate()) +*/ +void QGraphicsAnchorLayoutPrivate::deleteAnchorData(AnchorData *data) { + Q_Q(QGraphicsAnchorLayout); + removeAnchor_helper(data->from, data->to); + q->invalidate(); +} + +/*! + \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 - restoreSimplifiedGraph(edgeOrientation(firstEdge)); - AnchorVertex *v1 = internalVertex(firstItem, firstEdge); - AnchorVertex *v2 = internalVertex(secondItem, secondEdge); - - AnchorData *data = graph[edgeOrientation(firstEdge)].edgeData(v1, v2); - if (data) { - if (anchorSize) { - data->setFixedSize(*anchorSize); - } else { - data->unsetSize(); - } + Q_ASSERT(data); + restoreSimplifiedGraph(edgeOrientation(data->from->m_edge)); + if (anchorSize) { + data->setFixedSize(*anchorSize); + } else { + data->unsetSize(); } - return data; + q->invalidate(); } -bool QGraphicsAnchorLayoutPrivate::anchorSize(const QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, +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(this); - that->restoreSimplifiedGraph(edgeOrientation(firstEdge)); - AnchorVertex *v1 = internalVertex(firstItem, firstEdge); - AnchorVertex *v2 = internalVertex(secondItem, secondEdge); - - AnchorData *data = that->graph[edgeOrientation(firstEdge)].edgeData(v1, v2); - if (data) { - if (minSize) - *minSize = data->minSize; - if (prefSize) - *prefSize = data->prefSize; - if (maxSize) - *maxSize = data->maxSize; - } - return data; + that->restoreSimplifiedGraph(edgeOrientation(data->from->m_edge)); + + if (minSize) + *minSize = data->minSize; + if (prefSize) + *prefSize = data->prefSize; + if (maxSize) + *maxSize = data->maxSize; } AnchorVertex *QGraphicsAnchorLayoutPrivate::addInternalVertex(QGraphicsLayoutItem *item, diff --git a/src/gui/graphicsview/qgraphicsanchorlayout_p.h b/src/gui/graphicsview/qgraphicsanchorlayout_p.h index 31da1a1..f701c3f 100644 --- a/src/gui/graphicsview/qgraphicsanchorlayout_p.h +++ b/src/gui/graphicsview/qgraphicsanchorlayout_p.h @@ -54,6 +54,7 @@ // #include +#include #include "qgraphicslayout_p.h" #include "qgraphicsanchorlayout.h" @@ -153,6 +154,7 @@ struct AnchorData : public QSimplexVariable { minSize(minimumSize), prefSize(preferredSize), maxSize(maximumSize), sizeAtMinimum(preferredSize), sizeAtPreferred(preferredSize), sizeAtMaximum(preferredSize), + graphicsAnchor(0), skipInPreferred(0), type(Normal), hasSize(true), isLayoutAnchor(false) {} @@ -160,6 +162,7 @@ struct AnchorData : public QSimplexVariable { : QSimplexVariable(), from(0), to(0), minSize(size), prefSize(size), maxSize(size), sizeAtMinimum(size), sizeAtPreferred(size), sizeAtMaximum(size), + graphicsAnchor(0), skipInPreferred(0), type(Normal), hasSize(true), isLayoutAnchor(false) {} @@ -167,6 +170,7 @@ struct AnchorData : public QSimplexVariable { : QSimplexVariable(), from(0), to(0), minSize(0), prefSize(0), maxSize(0), sizeAtMinimum(0), sizeAtPreferred(0), sizeAtMaximum(0), + graphicsAnchor(0), skipInPreferred(0), type(Normal), hasSize(false), isLayoutAnchor(false) {} @@ -215,6 +219,7 @@ struct AnchorData : public QSimplexVariable { qreal sizeAtMinimum; qreal sizeAtPreferred; qreal sizeAtMaximum; + QGraphicsAnchor *graphicsAnchor; uint skipInPreferred : 1; uint type : 2; // either Normal, Sequential or Parallel @@ -226,6 +231,7 @@ protected: minSize(size), prefSize(size), maxSize(size), sizeAtMinimum(size), sizeAtPreferred(size), sizeAtMaximum(size), + graphicsAnchor(0), skipInPreferred(0), type(type), hasSize(true), isLayoutAnchor(false) {} }; @@ -309,6 +315,28 @@ public: QSet negatives; }; +class QGraphicsAnchorLayoutPrivate; +/*! + \internal +*/ +class QGraphicsAnchorPrivate : public QObjectPrivate +{ + Q_DECLARE_PUBLIC(QGraphicsAnchor) + +public: + explicit QGraphicsAnchorPrivate(int version = QObjectPrivateVersion); + ~QGraphicsAnchorPrivate(); + + void setSpacing(qreal value); + void unsetSpacing(); + qreal spacing() const; + + QGraphicsAnchorLayoutPrivate *layoutPrivate; + AnchorData *data; +}; + + + /*! \internal @@ -365,12 +393,22 @@ public: void removeCenterAnchors(QGraphicsLayoutItem *item, Qt::AnchorPoint centerEdge, bool substitute = true); void removeCenterConstraints(QGraphicsLayoutItem *item, Orientation orientation); + QGraphicsAnchor *acquireGraphicsAnchor(AnchorData *data) + { + Q_Q(QGraphicsAnchorLayout); + if (!data->graphicsAnchor) { + data->graphicsAnchor = new QGraphicsAnchor(q); + data->graphicsAnchor->d_func()->data = data; + } + return data->graphicsAnchor; + } + // helper function used by the 4 API functions - void anchor(QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - qreal *spacing = 0); + QGraphicsAnchor *anchor(QGraphicsLayoutItem *firstItem, + Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, + Qt::AnchorPoint secondEdge, + qreal *spacing = 0); // Anchor Manipulation methods void addAnchor(QGraphicsLayoutItem *firstItem, @@ -379,21 +417,17 @@ public: Qt::AnchorPoint secondEdge, AnchorData *data); + QGraphicsAnchor *getAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, + QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); + void removeAnchor(QGraphicsLayoutItem *firstItem, Qt::AnchorPoint firstEdge, QGraphicsLayoutItem *secondItem, Qt::AnchorPoint secondEdge); - - bool setAnchorSize(const QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, - const qreal *anchorSize); - - bool anchorSize(const QGraphicsLayoutItem *firstItem, - Qt::AnchorPoint firstEdge, - const QGraphicsLayoutItem *secondItem, - Qt::AnchorPoint secondEdge, + void removeAnchor_helper(AnchorVertex *v1, AnchorVertex *v2); + void deleteAnchorData(AnchorData *data); + void setAnchorSize(AnchorData *data, const qreal *anchorSize); + void anchorSize(const AnchorData *data, qreal *minSize = 0, qreal *prefSize = 0, qreal *maxSize = 0) const; diff --git a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index 95476f0..059ad33 100644 --- a/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/auto/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -64,6 +64,7 @@ private slots: void example(); void setSpacing(); void hardComplexS60(); + void delete_anchor(); }; class RectWidget : public QGraphicsWidget @@ -101,8 +102,8 @@ static void setAnchor(QGraphicsAnchorLayout *l, Qt::AnchorPoint secondEdge, qreal spacing) { - l->addAnchor(firstItem, firstEdge, secondItem, secondEdge); - l->setAnchorSpacing(firstItem, firstEdge, secondItem, secondEdge, spacing); + QGraphicsAnchor *anchor = l->addAnchor(firstItem, firstEdge, secondItem, secondEdge); + anchor->setSpacing(spacing); } static bool checkReverseDirection(QGraphicsWidget *w) @@ -293,47 +294,29 @@ void tst_QGraphicsAnchorLayout::diagonal() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); // vertical l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorTop, l, Qt::AnchorTop, 0); - l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorTop, l, Qt::AnchorTop, 0); - l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorTop, a, Qt::AnchorBottom, 0); l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorTop, b, Qt::AnchorBottom, 0); l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, e, Qt::AnchorTop, 0); - l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(d, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(e, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); // horizontal l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, d, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, c, Qt::AnchorLeft, 0); l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(c, Qt::AnchorRight, e, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(b, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(e, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(d, Qt::AnchorRight, e, Qt::AnchorLeft, 0); QCOMPARE(l->count(), 5); @@ -412,40 +395,25 @@ void tst_QGraphicsAnchorLayout::parallel() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorBottom, c, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); l->addAnchor(d, Qt::AnchorBottom, e, Qt::AnchorTop); - l->setAnchorSpacing(d, Qt::AnchorBottom, e, Qt::AnchorTop, 0); l->addAnchor(e, Qt::AnchorBottom, f, Qt::AnchorTop); - l->setAnchorSpacing(e, Qt::AnchorBottom, f, Qt::AnchorTop, 0); l->addAnchor(f, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(f, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, c, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, d, Qt::AnchorLeft); - l->setAnchorSpacing(b, Qt::AnchorRight, d, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(b, Qt::AnchorRight, e, Qt::AnchorLeft, 0); l->addAnchor(c, Qt::AnchorRight, f, Qt::AnchorLeft); - l->setAnchorSpacing(c, Qt::AnchorRight, f, Qt::AnchorLeft, 0); l->addAnchor(d, Qt::AnchorRight, f, Qt::AnchorLeft); - l->setAnchorSpacing(d, Qt::AnchorRight, f, Qt::AnchorLeft, 0); l->addAnchor(e, Qt::AnchorRight, f, Qt::AnchorLeft); - l->setAnchorSpacing(e, Qt::AnchorRight, f, Qt::AnchorLeft, 0); l->addAnchor(f, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(f, Qt::AnchorRight, l, Qt::AnchorRight, 0); QCOMPARE(l->count(), 6); @@ -503,19 +471,15 @@ void tst_QGraphicsAnchorLayout::parallel2() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(b, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); - l->addLeftAndRightAnchors(l, a); + l->addAnchors(l, a, Qt::Horizontal); l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, b, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, a, Qt::AnchorRight); - l->setAnchorSpacing(b, Qt::AnchorRight, a, Qt::AnchorRight, 0); QCOMPARE(l->count(), 2); @@ -556,24 +520,17 @@ void tst_QGraphicsAnchorLayout::snake() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorBottom, c, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorRight, 0); l->addAnchor(b, Qt::AnchorLeft, c, Qt::AnchorLeft); - l->setAnchorSpacing(b, Qt::AnchorLeft, c, Qt::AnchorLeft, 0); l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(c, Qt::AnchorRight, l, Qt::AnchorRight, 0); QCOMPARE(l->count(), 3); @@ -623,27 +580,20 @@ void tst_QGraphicsAnchorLayout::snakeOppositeDirections() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorBottom, c, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); // Both a and c are 'pointing' to b l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorRight); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorRight, 0); l->addAnchor(c, Qt::AnchorLeft, b, Qt::AnchorLeft); - l->setAnchorSpacing(c, Qt::AnchorLeft, b, Qt::AnchorLeft, 0); l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(c, Qt::AnchorRight, l, Qt::AnchorRight, 0); QCOMPARE(l->count(), 3); @@ -700,30 +650,20 @@ void tst_QGraphicsAnchorLayout::fairDistribution() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorBottom, c, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(d, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, c, Qt::AnchorLeft); - l->setAnchorSpacing(b, Qt::AnchorRight, c, Qt::AnchorLeft, 0); l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(c, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, d, Qt::AnchorLeft, 0); l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(d, Qt::AnchorRight, l, Qt::AnchorRight, 0); QCOMPARE(l->count(), 4); @@ -785,31 +725,21 @@ void tst_QGraphicsAnchorLayout::fairDistributionOppositeDirections() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorBottom, c, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); l->addAnchor(d, Qt::AnchorBottom, e, Qt::AnchorTop); - l->setAnchorSpacing(d, Qt::AnchorBottom, e, Qt::AnchorTop, 0); l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(e, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(a, Qt::AnchorLeft, l, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorLeft, l, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorLeft, a, Qt::AnchorRight); - l->setAnchorSpacing(b, Qt::AnchorLeft, a, Qt::AnchorRight, 0); l->addAnchor(c, Qt::AnchorLeft, b, Qt::AnchorRight); - l->setAnchorSpacing(c, Qt::AnchorLeft, b, Qt::AnchorRight, 0); l->addAnchor(d, Qt::AnchorLeft, c, Qt::AnchorRight); - l->setAnchorSpacing(d, Qt::AnchorLeft, c, Qt::AnchorRight, 0); l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(d, Qt::AnchorRight, l, Qt::AnchorRight, 0); - l->addLeftAndRightAnchors(l, e); + l->addAnchors(l, e, Qt::Horizontal); QCOMPARE(l->count(), 5); @@ -857,32 +787,21 @@ void tst_QGraphicsAnchorLayout::proportionalPreferred() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); l->addAnchor(l, Qt::AnchorTop, a, Qt::AnchorTop); - l->setAnchorSpacing(l, Qt::AnchorTop, a, Qt::AnchorTop, 0); l->addAnchor(a, Qt::AnchorBottom, b, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorBottom, b, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorBottom, c, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorBottom, c, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(d, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); l->addAnchor(l, Qt::AnchorLeft, b, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, b, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, c, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, d, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, d, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(b, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(c, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(c, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(d, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(d, Qt::AnchorRight, l, Qt::AnchorRight, 0); QCOMPARE(l->count(), 4); @@ -935,62 +854,40 @@ void tst_QGraphicsAnchorLayout::example() QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; l->setContentsMargins(0, 0, 0, 0); + l->setSpacing(0); // vertical l->addAnchor(a, Qt::AnchorTop, l, Qt::AnchorTop); - l->setAnchorSpacing(a, Qt::AnchorTop, l, Qt::AnchorTop, 0); l->addAnchor(b, Qt::AnchorTop, l, Qt::AnchorTop); - l->setAnchorSpacing(b, Qt::AnchorTop, l, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorTop, a, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorTop, a, Qt::AnchorBottom, 0); l->addAnchor(c, Qt::AnchorTop, b, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorTop, b, Qt::AnchorBottom, 0); l->addAnchor(c, Qt::AnchorBottom, d, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, d, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, e, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorBottom, e, Qt::AnchorTop, 0); l->addAnchor(d, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(d, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(e, Qt::AnchorBottom, l, Qt::AnchorBottom); - l->setAnchorSpacing(e, Qt::AnchorBottom, l, Qt::AnchorBottom, 0); l->addAnchor(c, Qt::AnchorTop, f, Qt::AnchorTop); - l->setAnchorSpacing(c, Qt::AnchorTop, f, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorVerticalCenter, f, Qt::AnchorBottom, 0); l->addAnchor(f, Qt::AnchorBottom, g, Qt::AnchorTop); - l->setAnchorSpacing(f, Qt::AnchorBottom, g, Qt::AnchorTop, 0); l->addAnchor(c, Qt::AnchorBottom, g, Qt::AnchorBottom); - l->setAnchorSpacing(c, Qt::AnchorBottom, g, Qt::AnchorBottom, 0); // horizontal l->addAnchor(l, Qt::AnchorLeft, a, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, a, Qt::AnchorLeft, 0); l->addAnchor(l, Qt::AnchorLeft, d, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, d, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, b, Qt::AnchorLeft, 0); l->addAnchor(a, Qt::AnchorRight, c, Qt::AnchorLeft); - l->setAnchorSpacing(a, Qt::AnchorRight, c, Qt::AnchorLeft, 0); l->addAnchor(c, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(c, Qt::AnchorRight, e, Qt::AnchorLeft, 0); l->addAnchor(b, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(b, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(e, Qt::AnchorRight, l, Qt::AnchorRight); - l->setAnchorSpacing(e, Qt::AnchorRight, l, Qt::AnchorRight, 0); l->addAnchor(d, Qt::AnchorRight, e, Qt::AnchorLeft); - l->setAnchorSpacing(d, Qt::AnchorRight, e, Qt::AnchorLeft, 0); l->addAnchor(l, Qt::AnchorLeft, f, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, f, Qt::AnchorLeft, 0); l->addAnchor(l, Qt::AnchorLeft, g, Qt::AnchorLeft); - l->setAnchorSpacing(l, Qt::AnchorLeft, g, Qt::AnchorLeft, 0); l->addAnchor(f, Qt::AnchorRight, g, Qt::AnchorRight); - l->setAnchorSpacing(f, Qt::AnchorRight, g, Qt::AnchorRight, 0); QCOMPARE(l->count(), 7); @@ -1039,7 +936,7 @@ void tst_QGraphicsAnchorLayout::setSpacing() l->addCornerAnchors(b, Qt::TopRightCorner, l, Qt::TopRightCorner); l->addAnchor(a, Qt::AnchorRight, b, Qt::AnchorLeft); - l->addLeftAndRightAnchors(l, c); + l->addAnchors(l, c, Qt::Horizontal); l->addAnchor(a, Qt::AnchorBottom, c, Qt::AnchorTop); l->addAnchor(c, Qt::AnchorBottom, l, Qt::AnchorBottom); @@ -1146,5 +1043,58 @@ void tst_QGraphicsAnchorLayout::hardComplexS60() } +void tst_QGraphicsAnchorLayout::delete_anchor() +{ + QGraphicsScene scene; + QSizeF minSize(0, 0); + QSizeF prefSize(50, 50); + QSizeF maxSize(100, 100); + QGraphicsWidget *w1 = createItem(minSize, prefSize, maxSize, "w1"); + QGraphicsWidget *w2 = createItem(minSize, prefSize, maxSize, "w2"); + QGraphicsWidget *w3 = createItem(minSize, prefSize, maxSize, "w3"); + + QGraphicsAnchorLayout *l = new QGraphicsAnchorLayout; + l->setSpacing(0); + l->setContentsMargins(0, 0, 0, 0); + l->addAnchor(l, Qt::AnchorLeft, w1, Qt::AnchorLeft); + l->addAnchor(w1, Qt::AnchorRight, w2, Qt::AnchorLeft); + l->addAnchor(w2, Qt::AnchorRight, l, Qt::AnchorRight); + l->addAnchor(w1, Qt::AnchorRight, w3, Qt::AnchorLeft); + l->addAnchor(w3, Qt::AnchorRight, l, Qt::AnchorRight); + + QGraphicsAnchor *anchor = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight); + anchor->setSpacing(10); + + QGraphicsWidget *p = new QGraphicsWidget; + p->setLayout(l); + + QCOMPARE(l->count(), 3); + + scene.addItem(p); + QGraphicsView *view = new QGraphicsView(&scene); + QApplication::processEvents(); + // Should now be simplified + QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize).width(), qreal(110)); + QGraphicsAnchor *anchor1 = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight); + QVERIFY(anchor1); + QGraphicsAnchor *anchor2 = l->anchor(w3, Qt::AnchorRight, l, Qt::AnchorRight); + QVERIFY(anchor2); + + // should be the same object + QCOMPARE(anchor1, anchor2); + + // check if removal works + delete anchor1; + + QApplication::processEvents(); + + // it should also change the preferred size of the layout + QCOMPARE(l->effectiveSizeHint(Qt::PreferredSize).width(), qreal(100)); + + delete p; + delete view; + +} + QTEST_MAIN(tst_QGraphicsAnchorLayout) #include "tst_qgraphicsanchorlayout.moc" diff --git a/tests/benchmarks/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp b/tests/benchmarks/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp index 028b3a8..000ab6e 100644 --- a/tests/benchmarks/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp +++ b/tests/benchmarks/qgraphicsanchorlayout/tst_qgraphicsanchorlayout.cpp @@ -92,8 +92,8 @@ static void setAnchor(QGraphicsAnchorLayout *l, Qt::AnchorPoint secondEdge, qreal spacing) { - l->addAnchor(firstItem, firstEdge, secondItem, secondEdge); - l->setAnchorSpacing(firstItem, firstEdge, secondItem, secondEdge, spacing); + QGraphicsAnchor *anchor = l->addAnchor(firstItem, firstEdge, secondItem, secondEdge); + anchor->setSpacing(spacing); } void tst_QGraphicsAnchorLayout::s60_hard_complex_data() -- cgit v0.12 From f1710803cc17a50d098e945e86ad75d42b036935 Mon Sep 17 00:00:00 2001 From: Thomas Sondergaard Date: Mon, 14 Sep 2009 14:33:39 +0200 Subject: Fixed off-by-one error in call to XGetKeyboardMapping that meant that max_keycode wasn't retrieved. Merge-request: 1308 Reviewed-by: Oswald Buddenhagen --- src/gui/kernel/qkeymapper_x11.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/kernel/qkeymapper_x11.cpp b/src/gui/kernel/qkeymapper_x11.cpp index 488cc6a..0ce77fe 100644 --- a/src/gui/kernel/qkeymapper_x11.cpp +++ b/src/gui/kernel/qkeymapper_x11.cpp @@ -536,7 +536,7 @@ void QKeyMapperPrivate::clearMappings() coreDesc.keysyms_per_keycode = 0; coreDesc.keysyms = XGetKeyboardMapping(X11->display, coreDesc.min_keycode, - coreDesc.max_keycode - coreDesc.min_keycode, + coreDesc.max_keycode - coreDesc.min_keycode + 1, &coreDesc.keysyms_per_keycode); #if 0 -- cgit v0.12 From 2f331bb76f00e251513c197fd43bee9faa511395 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 14 Sep 2009 14:15:20 +0200 Subject: Workaround QWS Enter/Leave problem. Reviewed-by: bnilsen --- tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp index 491330b..360e433 100644 --- a/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp +++ b/tests/auto/qstylesheetstyle/tst_qstylesheetstyle.cpp @@ -841,6 +841,11 @@ void tst_QStyleSheetStyle::hoverColors() frame.setLayout(layout); frame.show(); +#ifdef Q_WS_QWS +//QWS does not implement enter/leave when windows are shown underneath the cursor + QCursor::setPos(QPoint(0,0)); +#endif + #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&frame); #endif -- cgit v0.12 From f1b134bc57584c64e9703683d2c3bc6c46264d19 Mon Sep 17 00:00:00 2001 From: Paul Olav Tvete Date: Mon, 14 Sep 2009 14:23:06 +0200 Subject: Implement synthetic enter/leave events for QWS. QWS uses alien widgets too, so we need the same logic as the other platforms. Reviewed-by: bnilsen --- src/gui/kernel/qapplication.cpp | 18 ++++++++++++++---- src/gui/kernel/qapplication_p.h | 5 ++++- src/gui/kernel/qapplication_qws.cpp | 3 +++ src/gui/kernel/qwidget.cpp | 12 ++++++++---- tests/auto/qwidget/tst_qwidget.cpp | 5 +++-- 5 files changed, 32 insertions(+), 11 deletions(-) diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 300e519..a19e022 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -469,12 +469,18 @@ QWidget *QApplicationPrivate::oldEditFocus = 0; bool qt_tabletChokeMouse = false; static bool force_reverse = false; -static inline bool isAlien(QWidget *widget) +inline bool QApplicationPrivate::isAlien(QWidget *widget) { if (!widget) return false; -#ifdef Q_WS_MAC // Fake alien behavior on the Mac :) +#if defined(Q_WS_MAC) // Fake alien behavior on the Mac :) return !widget->isWindow() && widget->window()->testAttribute(Qt::WA_DontShowOnScreen); +#elif defined(Q_WS_QWS) + return !widget->isWindow() +# ifdef Q_BACKINGSTORE_SUBSURFACES + && !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface) +# endif + ; #else return !widget->internalWinId(); #endif @@ -2974,7 +2980,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, return result; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) /* This function should only be called when the widget changes visibility, i.e. when the \a widget is shown, hidden or deleted. This function does nothing @@ -2986,9 +2992,13 @@ extern QWidget *qt_button_down; void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) { #ifndef QT_NO_CURSOR +#ifdef Q_WS_QWS + if (!widget || widget->isWindow()) + return; +#else if (!widget || widget->internalWinId() || widget->isWindow()) return; - +#endif const bool widgetInShow = widget->isVisible() && !widget->data->in_destructor; if (!widgetInShow && widget != qt_last_mouse_receiver) return; // Widget was not under the cursor when it was hidden/deleted. diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index c027763..c33eb1a 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -513,7 +513,7 @@ public: #ifdef Q_OS_SYMBIAN static TUint resolveS60ScanCode(TInt scanCode, TUint keysym); #endif -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) void sendSyntheticEnterLeave(QWidget *widget); #endif @@ -586,6 +586,9 @@ private: Qt::FocusPolicy focusPolicy, Qt::FocusReason focusReason); static bool shouldSetFocus(QWidget *w, Qt::FocusPolicy policy); + + + static bool isAlien(QWidget *); }; Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, diff --git a/src/gui/kernel/qapplication_qws.cpp b/src/gui/kernel/qapplication_qws.cpp index e6bfd28..e9284f7 100644 --- a/src/gui/kernel/qapplication_qws.cpp +++ b/src/gui/kernel/qapplication_qws.cpp @@ -430,6 +430,7 @@ static QWidget *popupOfPopupButtonFocus = 0; static bool popupCloseDownMode = false; static bool popupGrabOk; static QPointer *mouseInWidget = 0; +QPointer qt_last_mouse_receiver = 0; static bool sm_blockUserInput = false; // session management @@ -3523,10 +3524,12 @@ bool QETWidget::translateMouseEvent(const QWSMouseEvent *event, int prevstate) if (widget != (*mouseInWidget)) { QApplicationPrivate::dispatchEnterLeave(widget, *mouseInWidget); (*mouseInWidget) = widget; + qt_last_mouse_receiver = widget; } QApplication::sendSpontaneousEvent(widget, &e); if (leaveAfterRelease && !QWidget::mouseGrabber()) { *mouseInWidget = QApplication::widgetAt(globalPos); + qt_last_mouse_receiver = *mouseInWidget; QApplicationPrivate::dispatchEnterLeave(*mouseInWidget, leaveAfterRelease); leaveAfterRelease = 0; } diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index fd44d78..fd89cb9 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -1442,9 +1442,13 @@ QWidget::~QWidget() } } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) else if (!internalWinId() && isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); +#ifdef Q_WS_QWS + } else if (isVisible()) { + qApp->d_func()->sendSyntheticEnterLeave(this); +#endif } #endif @@ -7181,7 +7185,7 @@ void QWidgetPrivate::hide_helper() // next bit tries to move the focus if the focus widget is now // hidden. if (wasVisible) { -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) qApp->d_func()->sendSyntheticEnterLeave(q); #endif @@ -7313,7 +7317,7 @@ void QWidget::setVisible(bool visible) d->show_helper(); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) qApp->d_func()->sendSyntheticEnterLeave(this); #endif } @@ -7428,7 +7432,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous) widget->d_func()->hide_sys(); } } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) qApp->d_func()->sendSyntheticEnterLeave(widget); #endif #ifndef QT_NO_ACCESSIBILITY diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp index 47cd860..86caddb 100644 --- a/tests/auto/qwidget/tst_qwidget.cpp +++ b/tests/auto/qwidget/tst_qwidget.cpp @@ -350,7 +350,7 @@ private slots: void setClearAndResizeMask(); void maskedUpdate(); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) void syntheticEnterLeave(); #endif void windowFlags(); @@ -8990,7 +8990,7 @@ void tst_QWidget::maskedUpdate() QCOMPARE(grandChild.paintedRegion, QRegion(grandChild.rect())); // Full update. } -#if defined(Q_WS_X11) || defined(Q_WS_WIN) +#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_WS_QWS) void tst_QWidget::syntheticEnterLeave() { class MyWidget : public QWidget @@ -9275,6 +9275,7 @@ void tst_QWidget::rectOutsideCoordinatesLimit_task144779() #ifdef Q_WS_X11 qt_x11_wait_for_window_manager(&main); #endif + QCursor::setPos(main.pos()); //get the cursor out of the picture QTest::qWait(100); QPixmap pixmap = QPixmap::grabWindow(main.winId()); -- cgit v0.12 From 3d915e734aaab1a208cd6a823c5e6923d05a2831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 14 Sep 2009 15:00:15 +0200 Subject: Ensured that we use GL 1 engine when -graphicssystem opengl1 is used. Reviewed-by: Trond --- src/opengl/qglpixelbuffer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp index 6cd8968..07bc711 100644 --- a/src/opengl/qglpixelbuffer.cpp +++ b/src/opengl/qglpixelbuffer.cpp @@ -402,7 +402,7 @@ QPaintEngine *QGLPixelBuffer::paintEngine() const #elif defined(QT_OPENGL_ES_2) return qt_buffer_2_engine(); #else - if (d_ptr->qctx->d_func()->internal_context || qt_gl_preferGL2Engine()) + if (qt_gl_preferGL2Engine()) return qt_buffer_2_engine(); else return qt_buffer_engine(); -- cgit v0.12 From c72eaee91136bbe1a9fa99cdb0a7593bec60264b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 14 Sep 2009 15:00:39 +0200 Subject: Fixed clipping bug in portedcanvas with -graphicssystem opengl We need to call ensureActive() when save() is called, to make sure systemStateChanged() gets called and updates the scissorTestEnabled flag, so that we don't lose it on the next restore(). Task-number: 261113 Reviewed-by: Trond --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index ea5bec8..bbb285f 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1720,6 +1720,9 @@ QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const { Q_D(const QGL2PaintEngineEx); + if (orig) + const_cast(this)->syncState(); + QOpenGL2PaintEngineState *s; if (!orig) s = new QOpenGL2PaintEngineState(); -- cgit v0.12 From adb6eea3a135707a220c0b1c1cf8266321af9309 Mon Sep 17 00:00:00 2001 From: con Date: Mon, 14 Sep 2009 14:59:45 +0200 Subject: System locale on Mac returns preferred language/country from sys prefs. Previously it always returned the C locale's language, which is of not much help for an application. Reviewed-by: Morten Sorvig --- src/corelib/tools/qlocale.cpp | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index 619c08c..a1f0712 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -125,7 +125,7 @@ static qulonglong qstrtoull(const char *nptr, const char **endptr, register int #if defined(Q_CC_MWERKS) && defined(Q_OS_WIN32) inline bool isascii(int c) { - return (c >= 0 && c <=127); + return (c >= 0 && c <=127); } #endif @@ -1149,6 +1149,23 @@ static QLocale::MeasurementSystem macMeasurementSystem() } } +static void getMacPreferredLanguageAndCountry(QString *language, QString *country) +{ + QCFType languages = (CFArrayRef)CFPreferencesCopyValue( + CFSTR("AppleLanguages"), + kCFPreferencesAnyApplication, + kCFPreferencesCurrentUser, + kCFPreferencesAnyHost); + if (CFArrayGetCount(languages) > 0) { + QCFType locale = CFLocaleCreate(kCFAllocatorDefault, + CFStringRef(CFArrayGetValueAtIndex(languages, 0))); + if (language) + *language = QCFString::toQString(CFStringRef(CFLocaleGetValue(locale, kCFLocaleLanguageCode))); + if (country) + *country = QCFString::toQString(CFStringRef(CFLocaleGetValue(locale, kCFLocaleCountryCode))); + } +} + QLocale QSystemLocale::fallbackLocale() const { return QLocale(QString::fromUtf8(getMacLocaleName().constData())); @@ -1193,9 +1210,16 @@ QVariant QSystemLocale::query(QueryType type, QVariant in = QVariant()) const case NegativeSign: case PositiveSign: case ZeroDigit: - case LanguageId: - case CountryId: break; + case LanguageId: + case CountryId: { + QString preferredLanguage; + QString preferredCountry; + getMacPreferredLanguageAndCountry(&preferredLanguage, &preferredCountry); + if (type == LanguageId) + return codeToLanguage(preferredLanguage.data()); + return codeToCountry(preferredCountry.data()); + } case MeasurementSystem: return QVariant(static_cast(macMeasurementSystem())); @@ -7181,8 +7205,8 @@ Q_CORE_EXPORT double qstrtod(const char *s00, const char **se, bool *ok) double ret = strtod((char*)s00, (char**)se); if (ok) { if((ret == 0.0l && errno == ERANGE) - || ret == HUGE_VAL || ret == -HUGE_VAL) - *ok = false; + || ret == HUGE_VAL || ret == -HUGE_VAL) + *ok = false; else *ok = true; // the result will be that we don't report underflow in this case } -- cgit v0.12 From f272d891a1fb622ced7a92d426099996f7890945 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 14 Sep 2009 12:40:32 +0200 Subject: Bring back the blurry drop shadow in the lighting example. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Bjørn Erik Nilsen --- examples/effects/lighting/lighting.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/effects/lighting/lighting.cpp b/examples/effects/lighting/lighting.cpp index 0dd6057..7026b66 100644 --- a/examples/effects/lighting/lighting.cpp +++ b/examples/effects/lighting/lighting.cpp @@ -96,7 +96,9 @@ void Lighting::setupScene() item->setPen(QPen(Qt::black)); item->setBrush(QBrush(Qt::white)); - item->setGraphicsEffect(new QGraphicsDropShadowEffect); + QGraphicsDropShadowEffect *effect = new QGraphicsDropShadowEffect; + effect->setBlurRadius(8); + item->setGraphicsEffect(effect); item->setZValue(1); item->setPos(i * 80, j * 80); m_scene.addItem(item); -- cgit v0.12 From 97594601ca84ae11f30bb35e6cbc7e3f70e0624d Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 14 Sep 2009 12:24:33 +0200 Subject: Add strength factor to the colorize filter. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To allow fading between the original and the colorized version of the pixmaps, a new strength factor is introduced, 0.0 means the filter has no effect at all, 1.0 means full colorization. Still missing is the non-raster implementation. Autotest: included Reviewed-by: Bjørn Erik Nilsen --- src/gui/image/qpixmapfilter.cpp | 51 +++++++++++++++++++++++++- src/gui/image/qpixmapfilter_p.h | 3 ++ tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp | 41 +++++++++++++++++++++ 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/src/gui/image/qpixmapfilter.cpp b/src/gui/image/qpixmapfilter.cpp index 15704ba..4fa2e6c 100644 --- a/src/gui/image/qpixmapfilter.cpp +++ b/src/gui/image/qpixmapfilter.cpp @@ -759,6 +759,10 @@ class QPixmapColorizeFilterPrivate : public QPixmapFilterPrivate Q_DECLARE_PUBLIC(QPixmapColorizeFilter) public: QColor color; + qreal strength; + quint32 opaque : 1; + quint32 alphaBlend : 1; + quint32 padding : 30; }; /*! @@ -771,7 +775,11 @@ public: QPixmapColorizeFilter::QPixmapColorizeFilter(QObject *parent) : QPixmapFilter(*new QPixmapColorizeFilterPrivate, ColorizeFilter, parent) { - d_func()->color = QColor(0, 0, 192); + Q_D(QPixmapColorizeFilter); + d->color = QColor(0, 0, 192); + d->strength = qreal(1); + d->opaque = true; + d->alphaBlend = false; } /*! @@ -797,6 +805,31 @@ void QPixmapColorizeFilter::setColor(const QColor &color) } /*! + Gets the strength of the colorize filter, 1.0 means full colorized while + 0.0 equals to no filtering at all. + + \internal +*/ +qreal QPixmapColorizeFilter::strength() const +{ + Q_D(const QPixmapColorizeFilter); + return d->strength; +} + +/*! + Sets the strength of the colorize filter to \a strength. + + \internal +*/ +void QPixmapColorizeFilter::setStrength(qreal strength) +{ + Q_D(QPixmapColorizeFilter); + d->strength = qBound(qreal(0), strength, qreal(1)); + d->opaque = !qFuzzyIsNull(d->strength); + d->alphaBlend = !qFuzzyIsNull(d->strength - 1); +} + +/*! \internal */ void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect) const @@ -807,6 +840,7 @@ void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const Q QPixmapColorizeFilter *colorizeFilter = static_cast(filter); if (colorizeFilter) { colorizeFilter->setColor(d->color); + colorizeFilter->setStrength(d->strength); colorizeFilter->draw(painter, dest, src, srcRect); delete colorizeFilter; return; @@ -814,6 +848,11 @@ void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const Q // falling back to raster implementation + if (!d->opaque) { + painter->drawPixmap(dest, src, srcRect); + return; + } + QImage srcImage; QImage destImage; @@ -836,6 +875,16 @@ void QPixmapColorizeFilter::draw(QPainter *painter, const QPointF &dest, const Q destPainter.fillRect(srcImage.rect(), d->color); destPainter.end(); + if (d->alphaBlend) { + // alpha blending srcImage and destImage + QImage buffer = srcImage; + QPainter bufPainter(&buffer); + bufPainter.setOpacity(d->strength); + bufPainter.drawImage(0, 0, destImage); + bufPainter.end(); + destImage = buffer; + } + if (srcImage.hasAlphaChannel()) destImage.setAlphaChannel(srcImage.alphaChannel()); diff --git a/src/gui/image/qpixmapfilter_p.h b/src/gui/image/qpixmapfilter_p.h index 4cbf7a3..2565110 100644 --- a/src/gui/image/qpixmapfilter_p.h +++ b/src/gui/image/qpixmapfilter_p.h @@ -155,6 +155,9 @@ public: void setColor(const QColor& color); QColor color() const; + void setStrength(qreal strength); + qreal strength() const; + void draw(QPainter *painter, const QPointF &dest, const QPixmap &src, const QRectF &srcRect = QRectF()) const; }; diff --git a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp index 83bd537..5a9bad7 100644 --- a/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp +++ b/tests/auto/qpixmapfilter/tst_qpixmapfilter.cpp @@ -63,8 +63,10 @@ public slots: private slots: void colorizeSetColor(); + void colorizeSetStrength(); void colorizeProcess(); void colorizeDraw(); + void colorizeDrawStrength(); void colorizeDrawSubRect(); void colorizeProcessSubRect(); void convolutionBoundingRectFor(); @@ -127,6 +129,16 @@ void tst_QPixmapFilter::colorizeSetColor() QCOMPARE(filter.color(), QColor(50, 100, 200)); } +void tst_QPixmapFilter::colorizeSetStrength() +{ + QPixmapColorizeFilter filter; + QCOMPARE(filter.strength(), qreal(1)); + filter.setStrength(0.5); + QCOMPARE(filter.strength(), qreal(0.5)); + filter.setStrength(0.0); + QCOMPARE(filter.strength(), qreal(0.0)); +} + void tst_QPixmapFilter::colorizeProcess() { QPixmapColorizeFilter filter; @@ -180,6 +192,35 @@ void tst_QPixmapFilter::colorizeDraw() } } +void tst_QPixmapFilter::colorizeDrawStrength() +{ + QPixmapColorizeFilter filter; + filter.setColor(Qt::blue); + filter.setStrength(0.3); + + QImage source(256, 128, QImage::Format_ARGB32); + source.fill(qRgb(255, 0, 0)); + QPixmap pixmap = QPixmap::fromImage(source); + + QImage result(pixmap.size(), QImage::Format_ARGB32_Premultiplied); + QPainter painter(&result); + painter.setCompositionMode(QPainter::CompositionMode_Source); + filter.draw(&painter, QPointF(0, 0), pixmap); + painter.end(); + + QImage resultImg = result; + for(int y = 0; y < resultImg.height(); y++) + { + for(int x = 0; x < resultImg.width(); x++) + { + QRgb pixel = resultImg.pixel(x,y); + QCOMPARE(qRed(pixel), 206); + QCOMPARE(qGreen(pixel), 26); + QCOMPARE(qBlue(pixel), 75); + } + } +} + void tst_QPixmapFilter::colorizeDrawSubRect() { QPixmapColorizeFilter filter; -- cgit v0.12 From dd24168d42df7b474c0fbc9cd943b0556cb4a25f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 14 Sep 2009 15:25:07 +0200 Subject: Fixed clipping bug in GL 2 engine. When dumping the rectangle clip to the depth buffer due to needing to intersect with a more complex clip, we didn't take into consideration that writeClip will transform the path by the current matrix, whereas the rectangle clip is in device coordinates. Thus, we need to map the path by the inverse matrix. Task-number: 260701 Reviewed-by: Trond --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index bbb285f..9386044 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1538,6 +1538,7 @@ void QGL2PaintEngineEx::clip(const QVectorPath &path, Qt::ClipOperation op) if (state()->rectangleClip.isValid() && op != Qt::NoClip && op != Qt::ReplaceClip) { QPainterPath path; path.addRect(state()->rectangleClip); + path = state()->matrix.inverted().map(path); state()->rectangleClip = QRect(); d->updateDepthScissorTest(); -- cgit v0.12 From 332ed8a32fa25a12f5316bb0420284c0e3e6fe43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B8rgen=20Lind?= Date: Mon, 14 Sep 2009 15:37:02 +0200 Subject: If the font does not exist, then the right bearing becomes to big In the QPF1 engine if the font does not exist, then the default constructor of glyph_metrics_t is used which sets the x and y values to the unlikely value of 100000. These glyph_metrics_t instances are not suppose to be used in the text layout calculations. Task-number: pending --- src/gui/text/qtextengine.cpp | 3 ++- src/gui/text/qtextengine_p.h | 1 + src/gui/text/qtextlayout.cpp | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp index 88837ca..b43bd06 100644 --- a/src/gui/text/qtextengine.cpp +++ b/src/gui/text/qtextengine.cpp @@ -1645,7 +1645,8 @@ glyph_metrics_t QTextEngine::boundingBox(int from, int len) const glyph_t glyph = glyphs.glyphs[logClusters[pos + ilen - 1]]; glyph_metrics_t gi = fe->boundingBox(glyph); - gm.width -= qRound(gi.xoff - gi.x - gi.width); + if (gi.isValid()) + gm.width -= qRound(gi.xoff - gi.x - gi.width); } } return gm; diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h index 28ac7d9..85c6928 100644 --- a/src/gui/text/qtextengine_p.h +++ b/src/gui/text/qtextengine_p.h @@ -110,6 +110,7 @@ struct glyph_metrics_t QFixed yoff; glyph_metrics_t transformed(const QTransform &xform) const; + inline bool isValid() const {return x != 100000 && y != 100000;} }; Q_DECLARE_TYPEINFO(glyph_metrics_t, Q_PRIMITIVE_TYPE); diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index 62795f8..f8b0cbc 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -1807,7 +1807,8 @@ void QTextLine::layout_helper(int maxGlyphs) QFontEngine *fontEngine = eng->fontEngine(current); glyph_t glyph = glyphs.glyphs[logClusters[pos - 1]]; glyph_metrics_t gi = fontEngine->boundingBox(glyph); - lbh.rightBearing = -qRound(gi.xoff - gi.x - gi.width); + if (gi.isValid()) + lbh.rightBearing = -qRound(gi.xoff - gi.x - gi.width); } if ((sb_or_ws|breakany) && lbh.checkFullOtherwiseExtend(line)) { -- cgit v0.12 From 488d28d1160cbd26d8728492c72217a39d87eb56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 14 Sep 2009 16:36:10 +0200 Subject: Really fixed clipping bug in portedcanvas with -graphicssystem opengl. Change c72eaee91136bbe1a9fa99cdb0a7593bec60264b was wrong, we should call ensureActive(), not syncState(). Task-number: 261113 Reviewed-by: Trond --- src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp index 9386044..5e790cf 100644 --- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp +++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp @@ -1722,7 +1722,7 @@ QPainterState *QGL2PaintEngineEx::createState(QPainterState *orig) const Q_D(const QGL2PaintEngineEx); if (orig) - const_cast(this)->syncState(); + const_cast(this)->ensureActive(); QOpenGL2PaintEngineState *s; if (!orig) -- cgit v0.12 From ef0f72e2ed861982fdcbf620c88f188b009b0cf1 Mon Sep 17 00:00:00 2001 From: Peter Hartmann Date: Mon, 14 Sep 2009 16:36:39 +0200 Subject: QSslCertificate autotest: allow test from shadow directory Reviewed-by: TrustMe --- tests/auto/qsslcertificate/tst_qsslcertificate.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/auto/qsslcertificate/tst_qsslcertificate.cpp b/tests/auto/qsslcertificate/tst_qsslcertificate.cpp index 9cd9f39..62c64a1 100644 --- a/tests/auto/qsslcertificate/tst_qsslcertificate.cpp +++ b/tests/auto/qsslcertificate/tst_qsslcertificate.cpp @@ -115,12 +115,7 @@ private slots: tst_QSslCertificate::tst_QSslCertificate() { -#ifdef Q_WS_MAC - // applicationDirPath() points to a path inside the app bundle on Mac. - QDir dir(qApp->applicationDirPath() + QLatin1String("/../../../certificates")); -#else QDir dir(SRCDIR + QLatin1String("/certificates")); -#endif QFileInfoList fileInfoList = dir.entryInfoList(QDir::Files | QDir::Readable); QRegExp rxCert(QLatin1String("^.+\\.(pem|der)$")); QRegExp rxSan(QLatin1String("^(.+\\.(?:pem|der))\\.san$")); -- cgit v0.12 From b590ed186b38491dd338e55372f509e7c3feb2b4 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 14 Sep 2009 15:47:06 +0200 Subject: Add simple autotest for QGraphicsGrayscaleEffect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Bjørn Erik Nilsen --- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index b36cf73..c0d23eb 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -63,6 +63,7 @@ private slots: void boundingRect(); void draw(); void opacity(); + void grayscale(); }; void tst_QGraphicsEffect::initTestCase() @@ -365,6 +366,29 @@ void tst_QGraphicsEffect::opacity() QCOMPARE(effect->m_opacity, qreal(0.5)); } +void tst_QGraphicsEffect::grayscale() +{ + QGraphicsScene scene(0, 0, 100, 100); + + QGraphicsRectItem *item = scene.addRect(0, 0, 50, 50); + item->setPen(Qt::NoPen); + item->setBrush(QColor(122, 193, 66)); // Qt light green + + QGraphicsGrayscaleEffect *effect = new QGraphicsGrayscaleEffect; + item->setGraphicsEffect(effect); + + QPainter painter; + QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); + + image.fill(0); + painter.begin(&image); + painter.setRenderHint(QPainter::Antialiasing); + scene.render(&painter); + painter.end(); + + QCOMPARE(image.pixel(10, 10), qRgb(148, 148, 148)); +} + QTEST_MAIN(tst_QGraphicsEffect) #include "tst_qgraphicseffect.moc" -- cgit v0.12 From 3ecf8f5de029e0a67ec90f6eba60754078374f01 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 14 Sep 2009 16:09:47 +0200 Subject: Add simple autotest for QGraphicsColorizeEffect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Bjørn Erik Nilsen --- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 25 ++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index c0d23eb..5363fd6 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -64,6 +64,7 @@ private slots: void draw(); void opacity(); void grayscale(); + void colorize(); }; void tst_QGraphicsEffect::initTestCase() @@ -389,6 +390,30 @@ void tst_QGraphicsEffect::grayscale() QCOMPARE(image.pixel(10, 10), qRgb(148, 148, 148)); } +void tst_QGraphicsEffect::colorize() +{ + QGraphicsScene scene(0, 0, 100, 100); + + QGraphicsRectItem *item = scene.addRect(0, 0, 50, 50); + item->setPen(Qt::NoPen); + item->setBrush(QColor(122, 193, 66)); // Qt light green + + QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect; + effect->setColor(QColor(102, 153, 51)); // Qt dark green + item->setGraphicsEffect(effect); + + QPainter painter; + QImage image(100, 100, QImage::Format_ARGB32_Premultiplied); + + image.fill(0); + painter.begin(&image); + painter.setRenderHint(QPainter::Antialiasing); + scene.render(&painter); + painter.end(); + + QCOMPARE(image.pixel(10, 10), qRgb(191, 212, 169)); +} + QTEST_MAIN(tst_QGraphicsEffect) #include "tst_qgraphicseffect.moc" -- cgit v0.12 From 886feff55f48ebdff0440278e611f822e6326c91 Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Mon, 14 Sep 2009 16:14:54 +0200 Subject: Add filter strength to QGraphics[Colorize,Grayscale]Effect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Autotest: included Reviewed-by: Bjørn Erik Nilsen --- src/gui/effects/qgraphicseffect.cpp | 63 ++++++++++++++++++++++ src/gui/effects/qgraphicseffect.h | 13 +++++ src/gui/effects/qgraphicseffect_p.h | 11 +++- tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp | 40 ++++++++++++++ 4 files changed, 126 insertions(+), 1 deletion(-) diff --git a/src/gui/effects/qgraphicseffect.cpp b/src/gui/effects/qgraphicseffect.cpp index 683a984..26489c5 100644 --- a/src/gui/effects/qgraphicseffect.cpp +++ b/src/gui/effects/qgraphicseffect.cpp @@ -467,12 +467,44 @@ QGraphicsGrayscaleEffect::~QGraphicsGrayscaleEffect() { } + +/*! + \property QGraphicsGrayscaleEffect::strength + \brief the strength of the effect. + + By default, the strength is 1.0. + A strength 0.0 equals to no effect, while 1.0 means full grayscale. +*/ +qreal QGraphicsGrayscaleEffect::strength() const +{ + Q_D(const QGraphicsGrayscaleEffect); + return d->filter->strength(); +} + +void QGraphicsGrayscaleEffect::setStrength(qreal strength) +{ + Q_D(QGraphicsGrayscaleEffect); + if (qFuzzyCompare(d->filter->strength(), strength)) + return; + + d->filter->setStrength(strength); + d->opaque = !qFuzzyIsNull(strength); + update(); + emit strengthChanged(strength); +} + /*! \reimp */ void QGraphicsGrayscaleEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsGrayscaleEffect); + + if (!d->opaque) { + source->draw(painter); + return; + } + QPoint offset; if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). @@ -546,6 +578,31 @@ void QGraphicsColorizeEffect::setColor(const QColor &color) } /*! + \property QGraphicsColorizeEffect::strength + \brief the strength of the effect. + + By default, the strength is 1.0. + A strength 0.0 equals to no effect, while 1.0 means full colorization. +*/ +qreal QGraphicsColorizeEffect::strength() const +{ + Q_D(const QGraphicsColorizeEffect); + return d->filter->strength(); +} + +void QGraphicsColorizeEffect::setStrength(qreal strength) +{ + Q_D(QGraphicsColorizeEffect); + if (qFuzzyCompare(d->filter->strength(), strength)) + return; + + d->filter->setStrength(strength); + d->opaque = !qFuzzyIsNull(strength); + update(); + emit strengthChanged(strength); +} + +/*! \fn void QGraphicsColorizeEffect::colorChanged(const QColor &color) This signal is emitted whenever the effect's color changes. @@ -558,6 +615,12 @@ void QGraphicsColorizeEffect::setColor(const QColor &color) void QGraphicsColorizeEffect::draw(QPainter *painter, QGraphicsEffectSource *source) { Q_D(QGraphicsColorizeEffect); + + if (!d->opaque) { + source->draw(painter); + return; + } + QPoint offset; if (source->isPixmap()) { // No point in drawing in device coordinates (pixmap will be scaled anyways). diff --git a/src/gui/effects/qgraphicseffect.h b/src/gui/effects/qgraphicseffect.h index 5822d8c..5062826 100644 --- a/src/gui/effects/qgraphicseffect.h +++ b/src/gui/effects/qgraphicseffect.h @@ -144,13 +144,22 @@ class QGraphicsGrayscaleEffectPrivate; class Q_GUI_EXPORT QGraphicsGrayscaleEffect: public QGraphicsEffect { Q_OBJECT + Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) public: QGraphicsGrayscaleEffect(QObject *parent = 0); ~QGraphicsGrayscaleEffect(); + qreal strength() const; + protected: void draw(QPainter *painter, QGraphicsEffectSource *source); +public Q_SLOTS: + void setStrength(qreal strength); + +Q_SIGNALS: + void strengthChanged(qreal strength); + private: Q_DECLARE_PRIVATE(QGraphicsGrayscaleEffect) Q_DISABLE_COPY(QGraphicsGrayscaleEffect) @@ -161,17 +170,21 @@ class Q_GUI_EXPORT QGraphicsColorizeEffect: public QGraphicsEffect { Q_OBJECT Q_PROPERTY(QColor color READ color WRITE setColor NOTIFY colorChanged) + Q_PROPERTY(qreal strength READ strength WRITE setStrength NOTIFY strengthChanged) public: QGraphicsColorizeEffect(QObject *parent = 0); ~QGraphicsColorizeEffect(); QColor color() const; + qreal strength() const; public Q_SLOTS: void setColor(const QColor &c); + void setStrength(qreal strength); Q_SIGNALS: void colorChanged(const QColor &color); + void strengthChanged(qreal strength); protected: void draw(QPainter *painter, QGraphicsEffectSource *source); diff --git a/src/gui/effects/qgraphicseffect_p.h b/src/gui/effects/qgraphicseffect_p.h index 4771384..e109790 100644 --- a/src/gui/effects/qgraphicseffect_p.h +++ b/src/gui/effects/qgraphicseffect_p.h @@ -113,6 +113,7 @@ class QGraphicsGrayscaleEffectPrivate : public QGraphicsEffectPrivate Q_DECLARE_PUBLIC(QGraphicsGrayscaleEffect) public: QGraphicsGrayscaleEffectPrivate() + : opaque(true) { filter = new QPixmapColorizeFilter; filter->setColor(Qt::black); @@ -120,16 +121,24 @@ public: ~QGraphicsGrayscaleEffectPrivate() { delete filter; } QPixmapColorizeFilter *filter; + quint32 opaque : 1; + quint32 padding : 31; }; class QGraphicsColorizeEffectPrivate : public QGraphicsEffectPrivate { Q_DECLARE_PUBLIC(QGraphicsColorizeEffect) public: - QGraphicsColorizeEffectPrivate() { filter = new QPixmapColorizeFilter; } + QGraphicsColorizeEffectPrivate() + : opaque(true) + { + filter = new QPixmapColorizeFilter; + } ~QGraphicsColorizeEffectPrivate() { delete filter; } QPixmapColorizeFilter *filter; + quint32 opaque : 1; + quint32 padding : 31; }; class QGraphicsPixelizeEffectPrivate : public QGraphicsEffectPrivate diff --git a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp index 5363fd6..d5205cd 100644 --- a/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp +++ b/tests/auto/qgraphicseffect/tst_qgraphicseffect.cpp @@ -388,6 +388,26 @@ void tst_QGraphicsEffect::grayscale() painter.end(); QCOMPARE(image.pixel(10, 10), qRgb(148, 148, 148)); + + effect->setStrength(0.5); + + image.fill(0); + painter.begin(&image); + painter.setRenderHint(QPainter::Antialiasing); + scene.render(&painter); + painter.end(); + + QCOMPARE(image.pixel(10, 10), qRgb(135, 171, 107)); + + effect->setStrength(0.0); + + image.fill(0); + painter.begin(&image); + painter.setRenderHint(QPainter::Antialiasing); + scene.render(&painter); + painter.end(); + + QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66)); } void tst_QGraphicsEffect::colorize() @@ -412,6 +432,26 @@ void tst_QGraphicsEffect::colorize() painter.end(); QCOMPARE(image.pixel(10, 10), qRgb(191, 212, 169)); + + effect->setStrength(0.5); + + image.fill(0); + painter.begin(&image); + painter.setRenderHint(QPainter::Antialiasing); + scene.render(&painter); + painter.end(); + + QCOMPARE(image.pixel(10, 10), qRgb(156, 203, 117)); + + effect->setStrength(0.0); + + image.fill(0); + painter.begin(&image); + painter.setRenderHint(QPainter::Antialiasing); + scene.render(&painter); + painter.end(); + + QCOMPARE(image.pixel(10, 10), qRgb(122, 193, 66)); } QTEST_MAIN(tst_QGraphicsEffect) -- cgit v0.12 From ab35f0f8b0d872bc2e963c6ef869fade71b83e3f Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Mon, 14 Sep 2009 17:50:30 +0200 Subject: Fixed gradient referencing in SVGs. An SVG element can now reference a gradient or solid-color defined anywhere in the same SVG file. Task-number: 245602 Reviewed-by: Trond --- src/svg/qsvghandler.cpp | 94 +++++++++++++++++------------------- src/svg/qsvghandler_p.h | 1 + src/svg/qsvgnode.cpp | 110 ++++++++++++++++++++----------------------- src/svg/qsvgnode_p.h | 6 +-- src/svg/qsvgstructure.cpp | 50 ++++---------------- src/svg/qsvgstructure_p.h | 3 +- src/svg/qsvgstyle.cpp | 4 +- src/svg/qsvgtinydocument.cpp | 20 ++++++++ src/svg/qsvgtinydocument_p.h | 6 +++ 9 files changed, 135 insertions(+), 159 deletions(-) diff --git a/src/svg/qsvghandler.cpp b/src/svg/qsvghandler.cpp index f287d5e..a6e4855 100644 --- a/src/svg/qsvghandler.cpp +++ b/src/svg/qsvghandler.cpp @@ -975,15 +975,7 @@ static void parseColor(QSvgNode *, static QSvgStyleProperty *styleFromUrl(QSvgNode *node, const QString &url) { - while (node && (node->type() != QSvgNode::DOC && - node->type() != QSvgNode::G && - node->type() != QSvgNode::DEFS && - node->type() != QSvgNode::SWITCH)) { - node = node->parent(); - } - if (!node) - return 0; - return static_cast(node)->scopeStyle(idFromUrl(url)); + return node ? node->styleProperty(idFromUrl(url)) : 0; } static void parseBrush(QSvgNode *node, @@ -3559,10 +3551,9 @@ void QSvgHandler::parse() case QXmlStreamReader::ProcessingInstruction: processingInstruction(xml->processingInstructionTarget().toString(), xml->processingInstructionData().toString()); break; - default: - ; } } + resolveGradients(m_doc); } bool QSvgHandler::startElement(const QString &localName, @@ -3672,7 +3663,7 @@ bool QSvgHandler::startElement(const QString &localName, QSvgStyleProperty *prop = method(m_nodes.top(), attributes, this); if (prop) { m_style = prop; - m_nodes.top()->appendStyleProperty(prop, someId(attributes), true); + m_nodes.top()->appendStyleProperty(prop, someId(attributes)); } else { qWarning("Could not parse node: %s", qPrintable(localName)); } @@ -3713,53 +3704,52 @@ bool QSvgHandler::endElement(const QStringRef &localName) if (m_inStyle && localName == QLatin1String("style")) m_inStyle = false; - if (node == Graphics) { - // Iterate through the m_renderers to resolve any unresolved gradients. - QSvgNode* curNode = static_cast(m_nodes.top()); - if (curNode->type() == QSvgNode::DOC || - curNode->type() == QSvgNode::G || - curNode->type() == QSvgNode::DEFS || - curNode->type() == QSvgNode::SWITCH) { - QSvgStructureNode* structureNode = static_cast(curNode); - QList ren = structureNode->renderers(); - QList::iterator itr = ren.begin(); - while (itr != ren.end()) { - QSvgNode *eleNode = *itr++; - QSvgFillStyle *fill = static_cast(eleNode->styleProperty(QSvgStyleProperty::FILL)); - if (fill && !(fill->isGradientResolved())) { - QString id = fill->gradientId(); - QSvgStyleProperty *style = structureNode->scopeStyle(id); - if (style) { - if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT) - fill->setFillStyle(reinterpret_cast(style)); - } else { - qWarning("Could not resolve property : %s",qPrintable(id)); - fill->setBrush(QBrush(Qt::NoBrush)); - } - } - QSvgStrokeStyle *stroke = static_cast(eleNode->styleProperty(QSvgStyleProperty::STROKE)); - if (stroke && !(stroke->isGradientResolved())) { - QString id = stroke->gradientId(); - QSvgStyleProperty *style = structureNode->scopeStyle(id); - if (style) { - if (style->type() == QSvgStyleProperty::SOLID_COLOR || style->type() == QSvgStyleProperty::GRADIENT) - stroke->setStyle(reinterpret_cast(style)); - } else { - qWarning("Could not resolve property : %s",qPrintable(id)); - stroke->setStroke(QBrush(Qt::NoBrush)); - } - } - } - } + if (node == Graphics) m_nodes.pop(); - } - else if (m_style && !m_skipNodes.isEmpty() && m_skipNodes.top() != Style) m_style = 0; return true; } +void QSvgHandler::resolveGradients(QSvgNode *node) +{ + if (!node || (node->type() != QSvgNode::DOC && node->type() != QSvgNode::G + && node->type() != QSvgNode::DEFS && node->type() != QSvgNode::SWITCH)) { + return; + } + QSvgStructureNode *structureNode = static_cast(node); + + QList ren = structureNode->renderers(); + for (QList::iterator it = ren.begin(); it != ren.end(); ++it) { + QSvgFillStyle *fill = static_cast((*it)->styleProperty(QSvgStyleProperty::FILL)); + if (fill && !fill->isGradientResolved()) { + QString id = fill->gradientId(); + QSvgFillStyleProperty *style = structureNode->styleProperty(id); + if (style) { + fill->setFillStyle(style); + } else { + qWarning("Could not resolve property : %s", qPrintable(id)); + fill->setBrush(Qt::NoBrush); + } + } + + QSvgStrokeStyle *stroke = static_cast((*it)->styleProperty(QSvgStyleProperty::STROKE)); + if (stroke && !stroke->isGradientResolved()) { + QString id = stroke->gradientId(); + QSvgFillStyleProperty *style = structureNode->styleProperty(id); + if (style) { + stroke->setStyle(style); + } else { + qWarning("Could not resolve property : %s", qPrintable(id)); + stroke->setStroke(Qt::NoBrush); + } + } + + resolveGradients(*it); + } +} + bool QSvgHandler::characters(const QStringRef &str) { if (m_inStyle) { diff --git a/src/svg/qsvghandler_p.h b/src/svg/qsvghandler_p.h index aff6f1d..daf1b1c 100644 --- a/src/svg/qsvghandler_p.h +++ b/src/svg/qsvghandler_p.h @@ -172,6 +172,7 @@ private: QXmlStreamReader *const xml; QCss::Parser m_cssParser; void parse(); + void resolveGradients(QSvgNode *node); QPen m_defaultPen; /** diff --git a/src/svg/qsvgnode.cpp b/src/svg/qsvgnode.cpp index 6b8254e..2e27cd5 100644 --- a/src/svg/qsvgnode.cpp +++ b/src/svg/qsvgnode.cpp @@ -60,56 +60,57 @@ QSvgNode::~QSvgNode() } -void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id, - bool justLink) +void QSvgNode::appendStyleProperty(QSvgStyleProperty *prop, const QString &id) { //qDebug()<<"appending "<type()<< " ("<< id <<") "<<"to "<type(); - if (!justLink) { - switch (prop->type()) { - case QSvgStyleProperty::QUALITY: - m_style.quality = static_cast(prop); - break; - case QSvgStyleProperty::FILL: - m_style.fill = static_cast(prop); - break; - case QSvgStyleProperty::VIEWPORT_FILL: - m_style.viewportFill = static_cast(prop); - break; - case QSvgStyleProperty::FONT: - m_style.font = static_cast(prop); - break; - case QSvgStyleProperty::STROKE: - m_style.stroke = static_cast(prop); - break; - case QSvgStyleProperty::SOLID_COLOR: - m_style.solidColor = static_cast(prop); - break; - case QSvgStyleProperty::GRADIENT: - m_style.gradient = static_cast(prop); - break; - case QSvgStyleProperty::TRANSFORM: - m_style.transform = static_cast(prop); - break; - case QSvgStyleProperty::ANIMATE_COLOR: - m_style.animateColor = static_cast(prop); - break; - case QSvgStyleProperty::ANIMATE_TRANSFORM: - m_style.animateTransforms.append( - static_cast(prop)); - break; - case QSvgStyleProperty::OPACITY: - m_style.opacity = static_cast(prop); - break; - case QSvgStyleProperty::COMP_OP: - m_style.compop = static_cast(prop); - break; - default: - qDebug("QSvgNode: Trying to append unknown property!"); - break; - } - } - if (!id.isEmpty()) { - m_styles.insert(id, prop); + QSvgTinyDocument *doc; + switch (prop->type()) { + case QSvgStyleProperty::QUALITY: + m_style.quality = static_cast(prop); + break; + case QSvgStyleProperty::FILL: + m_style.fill = static_cast(prop); + break; + case QSvgStyleProperty::VIEWPORT_FILL: + m_style.viewportFill = static_cast(prop); + break; + case QSvgStyleProperty::FONT: + m_style.font = static_cast(prop); + break; + case QSvgStyleProperty::STROKE: + m_style.stroke = static_cast(prop); + break; + case QSvgStyleProperty::SOLID_COLOR: + m_style.solidColor = static_cast(prop); + doc = document(); + if (doc && !id.isEmpty()) + doc->addNamedStyle(id, m_style.solidColor); + break; + case QSvgStyleProperty::GRADIENT: + m_style.gradient = static_cast(prop); + doc = document(); + if (doc && !id.isEmpty()) + doc->addNamedStyle(id, m_style.gradient); + break; + case QSvgStyleProperty::TRANSFORM: + m_style.transform = static_cast(prop); + break; + case QSvgStyleProperty::ANIMATE_COLOR: + m_style.animateColor = static_cast(prop); + break; + case QSvgStyleProperty::ANIMATE_TRANSFORM: + m_style.animateTransforms.append( + static_cast(prop)); + break; + case QSvgStyleProperty::OPACITY: + m_style.opacity = static_cast(prop); + break; + case QSvgStyleProperty::COMP_OP: + m_style.compop = static_cast(prop); + break; + default: + qDebug("QSvgNode: Trying to append unknown property!"); + break; } } @@ -185,20 +186,13 @@ QSvgStyleProperty * QSvgNode::styleProperty(QSvgStyleProperty::Type type) const return 0; } -QSvgStyleProperty * QSvgNode::styleProperty(const QString &id) const +QSvgFillStyleProperty * QSvgNode::styleProperty(const QString &id) const { QString rid = id; if (rid.startsWith(QLatin1Char('#'))) rid.remove(0, 1); - const QSvgNode *node = this; - while (node) { - QSvgStyleProperty *style = node->m_styles[rid]; - if (style) - return style; - node = node->parent(); - } - - return 0; + QSvgTinyDocument *doc = document(); + return doc ? doc->namedStyle(rid) : 0; } QRectF QSvgNode::bounds() const diff --git a/src/svg/qsvgnode_p.h b/src/svg/qsvgnode_p.h index 2831e65..1f5606a 100644 --- a/src/svg/qsvgnode_p.h +++ b/src/svg/qsvgnode_p.h @@ -117,12 +117,11 @@ public: QSvgNode *parent() const; - void appendStyleProperty(QSvgStyleProperty *prop, const QString &id, - bool justLink=false); + void appendStyleProperty(QSvgStyleProperty *prop, const QString &id); void applyStyle(QPainter *p, QSvgExtraStates &states); void revertStyle(QPainter *p, QSvgExtraStates &states); QSvgStyleProperty *styleProperty(QSvgStyleProperty::Type type) const; - QSvgStyleProperty *styleProperty(const QString &id) const; + QSvgFillStyleProperty *styleProperty(const QString &id) const; QSvgTinyDocument *document() const; @@ -162,7 +161,6 @@ protected: qreal strokeWidth() const; private: QSvgNode *m_parent; - QHash > m_styles; QStringList m_requiredFeatures; QStringList m_requiredExtensions; diff --git a/src/svg/qsvgstructure.cpp b/src/svg/qsvgstructure.cpp index 47a544f..82c800d 100644 --- a/src/svg/qsvgstructure.cpp +++ b/src/svg/qsvgstructure.cpp @@ -45,6 +45,7 @@ #include "qsvgnode_p.h" #include "qsvgstyle_p.h" +#include "qsvgtinydocument_p.h" #include "qpainter.h" #include "qlocale.h" @@ -90,35 +91,20 @@ QSvgStructureNode::QSvgStructureNode(QSvgNode *parent) QSvgNode * QSvgStructureNode::scopeNode(const QString &id) const { - const QSvgStructureNode *group = this; - while (group && group->type() != QSvgNode::DOC) { - group = static_cast(group->parent()); - } - if (group) - return group->m_scope[id]; - return 0; + QSvgTinyDocument *doc = document(); + return doc ? doc->namedNode(id) : 0; } -void QSvgStructureNode::addChild(QSvgNode *child, const QString &id, bool def) +void QSvgStructureNode::addChild(QSvgNode *child, const QString &id) { - if (!def) - m_renderers.append(child); - - if (child->type() == QSvgNode::DEFS) { - QSvgDefs *defs = - static_cast(child); - m_linkedScopes.append(defs); - } + m_renderers.append(child); if (id.isEmpty()) return; //we can't add it to scope without id - QSvgStructureNode *group = this; - while (group && group->type() != QSvgNode::DOC) { - group = static_cast(group->parent()); - } - if (group) - group->m_scope.insert(id, child); + QSvgTinyDocument *doc = document(); + if (doc) + doc->addNamedNode(id, child); } QSvgDefs::QSvgDefs(QSvgNode *parent) @@ -136,26 +122,6 @@ QSvgNode::Type QSvgDefs::type() const return DEFS; } -QSvgStyleProperty * QSvgStructureNode::scopeStyle(const QString &id) const -{ - const QSvgStructureNode *group = this; - while (group) { - QSvgStyleProperty *prop = group->styleProperty(id); - if (prop) - return prop; - QList::const_iterator itr = group->m_linkedScopes.constBegin(); - while (itr != group->m_linkedScopes.constEnd()) { - prop = (*itr)->styleProperty(id); - if (prop) - return prop; - ++itr; - } - group = static_cast(group->parent()); - } - return 0; -} - - /* Below is a lookup function based on the gperf output using the following set: diff --git a/src/svg/qsvgstructure_p.h b/src/svg/qsvgstructure_p.h index d873f54..444f885 100644 --- a/src/svg/qsvgstructure_p.h +++ b/src/svg/qsvgstructure_p.h @@ -73,8 +73,7 @@ public: QSvgStructureNode(QSvgNode *parent); ~QSvgStructureNode(); QSvgNode *scopeNode(const QString &id) const; - QSvgStyleProperty *scopeStyle(const QString &id) const; - void addChild(QSvgNode *child, const QString &id, bool def = false); + void addChild(QSvgNode *child, const QString &id); virtual QRectF bounds() const; QSvgNode *previousSiblingNode(QSvgNode *n) const; QList renderers() const { return m_renderers; } diff --git a/src/svg/qsvgstyle.cpp b/src/svg/qsvgstyle.cpp index 564bf24..f834016 100644 --- a/src/svg/qsvgstyle.cpp +++ b/src/svg/qsvgstyle.cpp @@ -934,7 +934,7 @@ void QSvgGradientStyle::setStopLink(const QString &link, QSvgTinyDocument *doc) void QSvgGradientStyle::resolveStops() { if (!m_link.isEmpty() && m_doc) { - QSvgStyleProperty *prop = m_doc->scopeStyle(m_link); + QSvgStyleProperty *prop = m_doc->styleProperty(m_link); if (prop) { if (prop->type() == QSvgStyleProperty::GRADIENT) { QSvgGradientStyle *st = @@ -943,6 +943,8 @@ void QSvgGradientStyle::resolveStops() m_gradient->setStops(st->qgradient()->stops()); m_gradientStopsSet = st->gradientStopsSet(); } + } else { + qWarning("Could not resolve property : %s", qPrintable(m_link)); } m_link = QString(); } diff --git a/src/svg/qsvgtinydocument.cpp b/src/svg/qsvgtinydocument.cpp index 5d58f79..e2cefeb 100644 --- a/src/svg/qsvgtinydocument.cpp +++ b/src/svg/qsvgtinydocument.cpp @@ -350,6 +350,26 @@ QSvgFont * QSvgTinyDocument::svgFont(const QString &family) const return m_fonts[family]; } +void QSvgTinyDocument::addNamedNode(const QString &id, QSvgNode *node) +{ + m_namedNodes.insert(id, node); +} + +QSvgNode *QSvgTinyDocument::namedNode(const QString &id) const +{ + return m_namedNodes.value(id); +} + +void QSvgTinyDocument::addNamedStyle(const QString &id, QSvgFillStyleProperty *style) +{ + m_namedStyles.insert(id, style); +} + +QSvgFillStyleProperty *QSvgTinyDocument::namedStyle(const QString &id) const +{ + return m_namedStyles.value(id); +} + void QSvgTinyDocument::restartAnimation() { m_time.restart(); diff --git a/src/svg/qsvgtinydocument_p.h b/src/svg/qsvgtinydocument_p.h index bde28c7..38a1f92 100644 --- a/src/svg/qsvgtinydocument_p.h +++ b/src/svg/qsvgtinydocument_p.h @@ -108,6 +108,10 @@ public: void addSvgFont(QSvgFont *); QSvgFont *svgFont(const QString &family) const; + void addNamedNode(const QString &id, QSvgNode *node); + QSvgNode *namedNode(const QString &id) const; + void addNamedStyle(const QString &id, QSvgFillStyleProperty *style); + QSvgFillStyleProperty *namedStyle(const QString &id) const; void restartAnimation(); int currentElapsed() const; @@ -127,6 +131,8 @@ private: mutable QRectF m_viewBox; QHash > m_fonts; + QHash m_namedNodes; + QHash > m_namedStyles; QTime m_time; bool m_animated; -- cgit v0.12 From 037e5066f8ef5279fae8fd9636a1b710cf187d1f Mon Sep 17 00:00:00 2001 From: Ariya Hidayat Date: Sun, 13 Sep 2009 18:28:45 +0200 Subject: Add an example that shows strength animation QGraphicsColorizeEffect. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a button is pressed, a popup message is shown and the background (everything, every items, behind the popup message) is faded to light green. Reviewed-by: Bjørn Erik Nilsen --- examples/effects/effects.pro | 3 +- examples/effects/fademessage/README.txt | 2 + examples/effects/fademessage/background.jpg | Bin 0 -> 159108 bytes examples/effects/fademessage/fademessage.cpp | 124 +++++++++++++++++++++++++++ examples/effects/fademessage/fademessage.h | 72 ++++++++++++++++ examples/effects/fademessage/fademessage.pro | 13 +++ examples/effects/fademessage/fademessage.qrc | 5 ++ examples/effects/fademessage/main.cpp | 56 ++++++++++++ 8 files changed, 274 insertions(+), 1 deletion(-) create mode 100644 examples/effects/fademessage/README.txt create mode 100644 examples/effects/fademessage/background.jpg create mode 100644 examples/effects/fademessage/fademessage.cpp create mode 100644 examples/effects/fademessage/fademessage.h create mode 100644 examples/effects/fademessage/fademessage.pro create mode 100644 examples/effects/fademessage/fademessage.qrc create mode 100644 examples/effects/fademessage/main.cpp diff --git a/examples/effects/effects.pro b/examples/effects/effects.pro index 60b5baf..01fa293 100644 --- a/examples/effects/effects.pro +++ b/examples/effects/effects.pro @@ -2,7 +2,8 @@ TEMPLATE = \ subdirs SUBDIRS = \ blurpicker \ - lighting + lighting \ + fademessage contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2):SUBDIRS += customshader diff --git a/examples/effects/fademessage/README.txt b/examples/effects/fademessage/README.txt new file mode 100644 index 0000000..f639e76 --- /dev/null +++ b/examples/effects/fademessage/README.txt @@ -0,0 +1,2 @@ +The background is taken from a public domain photo at: +http://www.photos8.com/view/windows_problem_blue-800x600.html diff --git a/examples/effects/fademessage/background.jpg b/examples/effects/fademessage/background.jpg new file mode 100644 index 0000000..9884233 Binary files /dev/null and b/examples/effects/fademessage/background.jpg differ diff --git a/examples/effects/fademessage/fademessage.cpp b/examples/effects/fademessage/fademessage.cpp new file mode 100644 index 0000000..818d00f --- /dev/null +++ b/examples/effects/fademessage/fademessage.cpp @@ -0,0 +1,124 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "fademessage.h" + +#include + +FadeMessage::FadeMessage(QWidget *parent): QGraphicsView(parent), m_index(0.0) +{ + setScene(&m_scene); + setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + + setupScene(); + + m_timeLine = new QTimeLine(500, this); + m_timeLine->setCurveShape(QTimeLine::EaseInOutCurve); + connect(m_timeLine, SIGNAL(valueChanged(qreal)), m_effect, SLOT(setStrength(qreal))); + + setRenderHint(QPainter::Antialiasing, true); + setFrameStyle(QFrame::NoFrame); +} + +void FadeMessage::togglePopup() +{ + if (m_message->isVisible()) { + m_message->setVisible(false); + m_timeLine->setDirection(QTimeLine::Backward); + m_timeLine->start(); + } else { + m_message->setVisible(true); + m_timeLine->setDirection(QTimeLine::Forward); + m_timeLine->start(); + } +} + +void FadeMessage::setupScene() +{ + QGraphicsRectItem *parent = m_scene.addRect(0, 0, 400, 600); + parent->setPen(Qt::NoPen); + parent->setZValue(0); + + QGraphicsPixmapItem *bg = m_scene.addPixmap(QPixmap(":/background.jpg")); + bg->setParentItem(parent); + bg->setZValue(-1); + + for (int i = 1; i < 5; ++i) + for (int j = 2; j < 5; ++j) { + QGraphicsRectItem *item = m_scene.addRect(i * 50, j * 50, 38, 38); + item->setParentItem(parent); + item->setZValue(1); + int hue = 12 * (i * 5 + j); + item->setBrush(QColor::fromHsv(hue, 128, 128)); + } + + QFont font; + font.setPointSize(font.pointSize() * 2); + font.setBold(true); + int fh = QFontMetrics(font).height(); + + QGraphicsRectItem *block = m_scene.addRect(50, 300, 300, fh + 3); + block->setPen(Qt::NoPen); + block->setBrush(QColor(102, 153, 51)); + + QGraphicsTextItem *text = m_scene.addText("Qt Everywhere!", font); + text->setDefaultTextColor(Qt::white); + text->setPos(50, 300); + block->setZValue(2); + block->hide(); + + text->setParentItem(block); + m_message = block; + + m_effect = new QGraphicsColorizeEffect; + m_effect->setColor(QColor(122, 193, 66)); + m_effect->setStrength(0); + m_effect->setEnabled(true); + parent->setGraphicsEffect(m_effect); + + QPushButton *press = new QPushButton; + press->setText(tr("Press me")); + connect(press, SIGNAL(clicked()), SLOT(togglePopup())); + m_scene.addWidget(press); + press->move(300, 500); +} + diff --git a/examples/effects/fademessage/fademessage.h b/examples/effects/fademessage/fademessage.h new file mode 100644 index 0000000..34e2fb8 --- /dev/null +++ b/examples/effects/fademessage/fademessage.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef FADEMESSAGE_H +#define FADEMESSAGE_H + +#include +#include +#include + +#include "fademessage.h" + +class FadeMessage: public QGraphicsView +{ + Q_OBJECT + +public: + FadeMessage(QWidget *parent = 0); + +private: + void setupScene(); + +private slots: + void togglePopup(); + +private: + qreal m_index; + QGraphicsScene m_scene; + QGraphicsColorizeEffect *m_effect; + QGraphicsItem *m_message; + QTimeLine *m_timeLine; +}; + +#endif // FADEMESSAGE_H diff --git a/examples/effects/fademessage/fademessage.pro b/examples/effects/fademessage/fademessage.pro new file mode 100644 index 0000000..ed9e53d --- /dev/null +++ b/examples/effects/fademessage/fademessage.pro @@ -0,0 +1,13 @@ +SOURCES += main.cpp fademessage.cpp +HEADERS += fademessage.h +RESOURCES += fademessage.qrc +INSTALLS += target sources + +# install +target.path = $$[QT_INSTALL_EXAMPLES]/effects/fademessage +sources.files = $$SOURCES \ + $$HEADERS \ + $$RESOURCES \ + $$FORMS \ + fademessage.pro +sources.path = $$[QT_INSTALL_EXAMPLES]/effects/fademessage diff --git a/examples/effects/fademessage/fademessage.qrc b/examples/effects/fademessage/fademessage.qrc new file mode 100644 index 0000000..9efea6a --- /dev/null +++ b/examples/effects/fademessage/fademessage.qrc @@ -0,0 +1,5 @@ + + + background.jpg + + diff --git a/examples/effects/fademessage/main.cpp b/examples/effects/fademessage/main.cpp new file mode 100644 index 0000000..65a4291 --- /dev/null +++ b/examples/effects/fademessage/main.cpp @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include + +#include "fademessage.h" + +int main(int argc, char **argv) +{ + QApplication app(argc, argv); + + FadeMessage widget; + widget.setWindowTitle(QT_TRANSLATE_NOOP(QGraphicsView, "Popup Message with Effect")); + widget.setFixedSize(400, 600); + widget.show(); + + return app.exec(); +} -- cgit v0.12 From bbb471f82159b58bbeb63e68cba1ae0a47faf77b Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 14 Sep 2009 18:49:23 +0200 Subject: Move the QT_GUI_LIB check to qtestevent.h instead of qtestmouse.h. This allows #including qtestmouse.h and qtestkeyboard directly to get mouse testing. All QtTest headers are still unsupported (you should always include QtTest/QtTest) but we can still fix issues like this. I have verified with the preprocessor that no GUI code is enabled by including QtTest if QT_GUI_LIB isn't defined. This should not bring the MinGW autotest failures back that the a250ca3a3c0 commit was trying to fix. Reviewed-by: Trust Me --- src/testlib/qtestevent.h | 2 ++ src/testlib/qtestkeyboard.h | 2 +- src/testlib/qtestmouse.h | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/testlib/qtestevent.h b/src/testlib/qtestevent.h index 95f2028..55df572 100644 --- a/src/testlib/qtestevent.h +++ b/src/testlib/qtestevent.h @@ -48,8 +48,10 @@ #endif #include +#ifdef QT_GUI_LIB #include #include +#endif #include #include diff --git a/src/testlib/qtestkeyboard.h b/src/testlib/qtestkeyboard.h index 42012e9..11c3b70 100644 --- a/src/testlib/qtestkeyboard.h +++ b/src/testlib/qtestkeyboard.h @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#if !defined(QTESTKEYBOARD_H) && defined(QT_GUI_LIB) +#if !defined(QTESTKEYBOARD_H) #define QTESTKEYBOARD_H #if 0 diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h index feb64cf..f339a5a 100644 --- a/src/testlib/qtestmouse.h +++ b/src/testlib/qtestmouse.h @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#if !defined(QTESTMOUSE_H) && defined(QT_GUI_LIB) +#if !defined(QTESTMOUSE_H) #define QTESTMOUSE_H #if 0 -- cgit v0.12 From 0d2d8f944bee6a13bdb50be2468130e937e0c010 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 14 Sep 2009 18:51:07 +0200 Subject: Make qtest_gui.h define QT_GUI_LIB to enable GUI tests. This also creates a new header called QtTest/QtTestGui. This header is not supported. You should #include . But if you're using a build system that is not qmake, QT_GUI_LIB isn't defined, so it's possibly easier to #include this new header. Reviewed-by: Trust Me --- src/testlib/qtest_gui.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/testlib/qtest_gui.h b/src/testlib/qtest_gui.h index 92ca055..13063a8 100644 --- a/src/testlib/qtest_gui.h +++ b/src/testlib/qtest_gui.h @@ -42,6 +42,14 @@ #ifndef QTEST_GUI_H #define QTEST_GUI_H +// enable GUI features +#ifndef QT_GUI_LIB +#define QT_GUI_LIB +#endif +#if 0 +#pragma qt_class(QtTestGui) +#endif + #include #include #include -- cgit v0.12 From 655e19b862e54ad61b7b2fa6d05463382c7baa61 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 14 Sep 2009 18:53:49 +0200 Subject: Fix closing the menu of a QMenuBar with the mouse Ammend commit 41dbc4406 and 21cf7b4c431742 We do not always get the mouseReleaseEvent (because the popups grabs the mouse. So set mouseDown to false in the mouseMoveEvent if no buttons are pressed. We also need to call setCurrentAction(0) in the case we are hovering on the empty area with no popup open. (in otder to remove the highlight) The code is now much closer to the code before the two previous commit Reviewed-by: Prasanth --- src/gui/widgets/qmenubar.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/widgets/qmenubar.cpp b/src/gui/widgets/qmenubar.cpp index 8591a77..7b0f37e 100644 --- a/src/gui/widgets/qmenubar.cpp +++ b/src/gui/widgets/qmenubar.cpp @@ -1252,9 +1252,11 @@ void QMenuBar::keyPressEvent(QKeyEvent *e) void QMenuBar::mouseMoveEvent(QMouseEvent *e) { Q_D(QMenuBar); + if (!(e->buttons() & Qt::LeftButton)) + d->mouseDown = false; bool popupState = d->popupState || d->mouseDown; QAction *action = d->actionAt(e->pos()); - if (action && d->isVisible(action)) + if ((action && d->isVisible(action)) || !popupState) d->setCurrentAction(action, popupState); } -- cgit v0.12 From a1d6c4e508cb2ea9a2d33d4f197da416c3f492c8 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 14 Sep 2009 20:46:25 +0200 Subject: Remove spurious, wrong semi-colon There should be no semi-colon after Q_DISABLE_COPY. Reviewed-By: Trust Me --- src/gui/widgets/qmenudata.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/widgets/qmenudata.h b/src/gui/widgets/qmenudata.h index 69f0cbc..c9d8b47 100644 --- a/src/gui/widgets/qmenudata.h +++ b/src/gui/widgets/qmenudata.h @@ -68,7 +68,7 @@ private: void setId(int); void setSignalValue(int); - Q_DISABLE_COPY(QMenuItem); + Q_DISABLE_COPY(QMenuItem) }; QT_END_NAMESPACE -- cgit v0.12 From b2d7bcf1e77e8b9bc8fc1b40777907d7a8d47c09 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 14 Sep 2009 16:39:26 +1000 Subject: Fixes crash when calling numRows on unknown query type (ibase) Reviewed-by: Justin McPherson --- src/sql/drivers/ibase/qsql_ibase.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sql/drivers/ibase/qsql_ibase.cpp b/src/sql/drivers/ibase/qsql_ibase.cpp index bde3930..7a4609d 100644 --- a/src/sql/drivers/ibase/qsql_ibase.cpp +++ b/src/sql/drivers/ibase/qsql_ibase.cpp @@ -1262,6 +1262,9 @@ int QIBaseResult::numRowsAffected() case isc_info_sql_stmt_insert: cCountType = isc_info_req_insert_count; break; + default: + qWarning() << "numRowsAffected: Unknown statement type (" << d->queryType << ")"; + return -1; } char acBuffer[33]; -- cgit v0.12 From e6f191185d0a80ced3434a8b378b139386c43760 Mon Sep 17 00:00:00 2001 From: Bill King Date: Mon, 14 Sep 2009 16:45:26 +1000 Subject: Fixes QSqlTableModel: trying to delete the wrong row. Uses the primary key from the index in the query, not the resulting location in the modified dataset. Task-number: 222678 --- src/sql/models/qsqltablemodel.cpp | 9 ++-- tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp | 61 ++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 4 deletions(-) diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index a532449..a91dc9f 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -559,7 +559,7 @@ bool QSqlTableModel::setData(const QModelIndex &index, const QVariant &value, in if (row.op == QSqlTableModelPrivate::None) { row.op = QSqlTableModelPrivate::Update; row.rec = d->rec; - row.primaryValues = d->primaryValues(indexInQuery(index).row()); + row.primaryValues = d->primaryValues(indexInQuery(index).row()); } row.rec.setValue(index.column(), value); emit dataChanged(index, index); @@ -669,7 +669,7 @@ bool QSqlTableModel::deleteRowFromTable(int row) Q_D(QSqlTableModel); emit beforeDelete(row); - QSqlRecord rec = d->primaryValues(row); + const QSqlRecord whereValues = d->strategy == OnManualSubmit ? d->cache[row].primaryValues : d->primaryValues(row); bool prepStatement = d->db.driver()->hasFeature(QSqlDriver::PreparedQueries); QString stmt = d->db.driver()->sqlStatement(QSqlDriver::DeleteStatement, d->tableName, @@ -677,7 +677,7 @@ bool QSqlTableModel::deleteRowFromTable(int row) prepStatement); QString where = d->db.driver()->sqlStatement(QSqlDriver::WhereStatement, d->tableName, - rec, + whereValues, prepStatement); if (stmt.isEmpty() || where.isEmpty()) { @@ -687,7 +687,7 @@ bool QSqlTableModel::deleteRowFromTable(int row) } stmt.append(QLatin1Char(' ')).append(where); - return d->exec(stmt, prepStatement, rec); + return d->exec(stmt, prepStatement, whereValues); } /*! @@ -1097,6 +1097,7 @@ bool QSqlTableModel::removeRows(int row, int count, const QModelIndex &parent) revertRow(idx); else { d->cache[idx].op = QSqlTableModelPrivate::Delete; + d->cache[idx].primaryValues = d->primaryValues(indexInQuery(createIndex(idx, 0)).row()); emit headerDataChanged(Qt::Vertical, idx, idx); } } diff --git a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp index 15fe686..0369e86 100644 --- a/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp +++ b/tests/auto/qsqltablemodel/tst_qsqltablemodel.cpp @@ -119,6 +119,11 @@ private slots: void tableModifyWithBlank_data() { generic_data(); } void tableModifyWithBlank(); // For mail task + void removeColumnAndRow_data() { generic_data(); } + void removeColumnAndRow(); // task 256032 + + void insertBeforeDelete_data() { generic_data(); } + void insertBeforeDelete(); private: void generic_data(const QString& engine=QString()); }; @@ -985,5 +990,61 @@ void tst_QSqlTableModel::tableModifyWithBlank() QCOMPARE(model.record(0).value(1).toString(), QLatin1String("col1ModelData")); } +void tst_QSqlTableModel::removeColumnAndRow() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlTableModel model(0, db); + model.setTable(qTableName("test")); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); + QVERIFY_SQL(model, select()); + QCOMPARE(model.rowCount(), 3); + QCOMPARE(model.columnCount(), 3); + + QVERIFY(model.removeColumn(0)); + QVERIFY(model.removeRow(0)); + QVERIFY(model.submitAll()); + QCOMPARE(model.rowCount(), 2); + QCOMPARE(model.columnCount(), 2); + + // check with another table because the model has been modified + // but not the sql table + QSqlTableModel model2(0, db); + model2.setTable(qTableName("test")); + QVERIFY_SQL(model2, select()); + QCOMPARE(model2.rowCount(), 2); + QCOMPARE(model2.columnCount(), 3); +} + +void tst_QSqlTableModel::insertBeforeDelete() +{ + QFETCH(QString, dbName); + QSqlDatabase db = QSqlDatabase::database(dbName); + CHECK_DATABASE(db); + + QSqlQuery q(db); + QVERIFY_SQL( q, exec("insert into " + qTableName("test") + " values(9, 'andrew', 9)")); + QVERIFY_SQL( q, exec("insert into " + qTableName("test") + " values(10, 'justin', 10)")); + + QSqlTableModel model(0, db); + model.setTable(qTableName("test")); + model.setEditStrategy(QSqlTableModel::OnManualSubmit); + QVERIFY_SQL(model, select()); + + qDebug() << model.rowCount(); + + QSqlRecord rec = model.record(); + rec.setValue(0, 4); + rec.setValue(1, QString("bill")); + rec.setValue(2, 4); + QVERIFY_SQL(model, insertRecord(4, rec)); + + QVERIFY_SQL(model, removeRow(5)); + QVERIFY_SQL(model, submitAll()); + QCOMPARE(model.rowCount(), 5); +} + QTEST_MAIN(tst_QSqlTableModel) #include "tst_qsqltablemodel.moc" -- cgit v0.12