From 1771526b2e13607f9e5e3cef15622f74349f4e48 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?=
Date: Thu, 28 Jan 2010 17:50:49 +0100
Subject: Warn if the plugin seems to not exist instead of simply passing.
follow-up to 0585997b7dbe25ece9f60684171c16206d10d65f
Task-number: related to QTBUG-7688
Reviewed-by: TRUSTME
---
tests/auto/qimagereader/tst_qimagereader.cpp | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp
index e7cfe68..b1a5d26 100644
--- a/tests/auto/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/qimagereader/tst_qimagereader.cpp
@@ -1641,10 +1641,16 @@ void tst_QImageReader::pixelCompareWithBaseline()
{
QFETCH(QString, fileName);
+ static int enteredCount = 0; // Used for better error diagnostics if something fails. We
+ static int loadFailCount = 0; // don't know if the reason load() fails is that the plugin
+ // does not exist or because of a bug in the plugin. But if at
+ // least one file succeeded we know that the plugin was built.
+ // The other failures are then real failures.
QImage icoImg;
const QString inputFileName(QString::fromAscii("images/%1").arg(fileName));
QFileInfo fi(inputFileName);
+ ++enteredCount;
// might fail if the plugin does not exist, which is ok.
if (icoImg.load(inputFileName)) {
icoImg = icoImg.convertToFormat(QImage::Format_ARGB32_Premultiplied);
@@ -1658,6 +1664,13 @@ void tst_QImageReader::pixelCompareWithBaseline()
QCOMPARE(int(baseImg.format()), int(icoImg.format()));
QCOMPARE(baseImg, icoImg);
#endif
+ } else {
+ ++loadFailCount;
+ if (enteredCount != loadFailCount) {
+ QFAIL("Plugin is built, but some did not load properly");
+ } else {
+ qWarning("loading failed, check if ico plugin is built");
+ }
}
}
--
cgit v0.12
From d98d31ca34a84a03dbac20fbf1dc88c0f8fd93cb Mon Sep 17 00:00:00 2001
From: Alexis Menard
Date: Fri, 29 Jan 2010 11:41:28 +0100
Subject: Doc fix. No need to put something deprecated if it's not.
Reviewed-by:TrustMe
---
src/gui/dialogs/qfiledialog.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/gui/dialogs/qfiledialog.cpp b/src/gui/dialogs/qfiledialog.cpp
index 21650bb..089e04a 100644
--- a/src/gui/dialogs/qfiledialog.cpp
+++ b/src/gui/dialogs/qfiledialog.cpp
@@ -229,11 +229,10 @@ Q_GUI_EXPORT _qt_filedialog_save_filename_hook qt_filedialog_save_filename_hook
\value ReadOnly Indicates that the model is readonly.
\value HideNameFilterDetails Indicates if the is hidden or not.
- This value is obsolete and does nothing since Qt 4.5:
\value DontUseSheet In previous versions of Qt, the static
functions would create a sheet by default if the static function
- was given a parent. This is no longer supported in Qt 4.5, The
+ was given a parent. This is no longer supported and does nothing in Qt 4.5, The
static functions will always be an application modal dialog. If
you want to use sheets, use QFileDialog::open() instead.
--
cgit v0.12
From 9e95ce2a68ef167e17dccc5789cbf3bf74712280 Mon Sep 17 00:00:00 2001
From: Tom Cooksey
Date: Fri, 29 Jan 2010 11:39:06 +0100
Subject: Fix GL texture leaks when pixmaps are deleted
This fixes quite a lot of issues:
* QtOpenGL only registered qpixmap destruction hooks on X11 and
those only cleanup the EGL/GLX surface, not the texture object.
* The QPixmap destruction hooks were only being called from the
QPixmap destructor. However, this means when a QPixmap is assigned
to another QPixmap, the hooks don't get called.
Task-number: QTBUG-7647
Reviewed-By: Samuel
Reviewed-By: Trond
---
src/gui/image/qimagepixmapcleanuphooks.cpp | 20 +--
src/gui/image/qimagepixmapcleanuphooks_p.h | 23 +--
src/gui/image/qpixmap.cpp | 12 +-
src/gui/image/qpixmap_x11.cpp | 7 +
src/gui/image/qpixmapdata.cpp | 11 ++
src/gui/image/qpixmapdata_p.h | 8 +
src/opengl/qgl.cpp | 32 ++--
src/opengl/qgl_p.h | 9 +-
src/opengl/qglpixmapfilter.cpp | 22 +--
tests/auto/qgl/qgl.pro | 4 +-
tests/auto/qgl/qgl.qrc | 5 +
tests/auto/qgl/tst_qgl.cpp | 240 +++++++++++++++++++++++++++++
12 files changed, 326 insertions(+), 67 deletions(-)
create mode 100644 tests/auto/qgl/qgl.qrc
diff --git a/src/gui/image/qimagepixmapcleanuphooks.cpp b/src/gui/image/qimagepixmapcleanuphooks.cpp
index 61d538f..ace4bb6 100644
--- a/src/gui/image/qimagepixmapcleanuphooks.cpp
+++ b/src/gui/image/qimagepixmapcleanuphooks.cpp
@@ -62,12 +62,12 @@ QImagePixmapCleanupHooks *QImagePixmapCleanupHooks::instance()
return qt_image_and_pixmap_cleanup_hooks();
}
-void QImagePixmapCleanupHooks::addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.append(hook);
}
-void QImagePixmapCleanupHooks::addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.append(hook);
}
@@ -78,12 +78,12 @@ void QImagePixmapCleanupHooks::addImageHook(_qt_image_cleanup_hook_64 hook)
imageHooks.append(hook);
}
-void QImagePixmapCleanupHooks::removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapModificationHooks.removeAll(hook);
}
-void QImagePixmapCleanupHooks::removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm hook)
+void QImagePixmapCleanupHooks::removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd hook)
{
pixmapDestructionHooks.removeAll(hook);
}
@@ -93,24 +93,24 @@ void QImagePixmapCleanupHooks::removeImageHook(_qt_image_cleanup_hook_64 hook)
imageHooks.removeAll(hook);
}
-void QImagePixmapCleanupHooks::executePixmapModificationHooks(QPixmap* pm)
+void QImagePixmapCleanupHooks::executePixmapDataModificationHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
for (int i = 0; i < h->pixmapModificationHooks.count(); ++i)
- h->pixmapModificationHooks[i](pm);
+ h->pixmapModificationHooks[i](pmd);
if (qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(pm->cacheKey());
+ qt_pixmap_cleanup_hook_64(pmd->cacheKey());
}
-void QImagePixmapCleanupHooks::executePixmapDestructionHooks(QPixmap* pm)
+void QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(QPixmapData* pmd)
{
QImagePixmapCleanupHooks *h = qt_image_and_pixmap_cleanup_hooks();
for (int i = 0; i < h->pixmapDestructionHooks.count(); ++i)
- h->pixmapDestructionHooks[i](pm);
+ h->pixmapDestructionHooks[i](pmd);
if (qt_pixmap_cleanup_hook_64)
- qt_pixmap_cleanup_hook_64(pm->cacheKey());
+ qt_pixmap_cleanup_hook_64(pmd->cacheKey());
}
void QImagePixmapCleanupHooks::executeImageHooks(qint64 key)
diff --git a/src/gui/image/qimagepixmapcleanuphooks_p.h b/src/gui/image/qimagepixmapcleanuphooks_p.h
index 7176044..88dd3a6 100644
--- a/src/gui/image/qimagepixmapcleanuphooks_p.h
+++ b/src/gui/image/qimagepixmapcleanuphooks_p.h
@@ -58,7 +58,8 @@
QT_BEGIN_NAMESPACE
typedef void (*_qt_image_cleanup_hook_64)(qint64);
-typedef void (*_qt_pixmap_cleanup_hook_pm)(QPixmap*);
+typedef void (*_qt_pixmap_cleanup_hook_pmd)(QPixmapData*);
+
class QImagePixmapCleanupHooks;
@@ -71,27 +72,27 @@ public:
static void enableCleanupHooks(const QPixmap &pixmap);
static void enableCleanupHooks(QPixmapData *pixmapData);
- // Gets called when a pixmap is about to be modified:
- void addPixmapModificationHook(_qt_pixmap_cleanup_hook_pm);
+ // Gets called when a pixmap data is about to be modified:
+ void addPixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
- // Gets called when a pixmap is about to be destroyed:
- void addPixmapDestructionHook(_qt_pixmap_cleanup_hook_pm);
+ // Gets called when a pixmap data is about to be destroyed:
+ void addPixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
// Gets called when an image is about to be modified or destroyed:
void addImageHook(_qt_image_cleanup_hook_64);
- void removePixmapModificationHook(_qt_pixmap_cleanup_hook_pm);
- void removePixmapDestructionHook(_qt_pixmap_cleanup_hook_pm);
+ void removePixmapDataModificationHook(_qt_pixmap_cleanup_hook_pmd);
+ void removePixmapDataDestructionHook(_qt_pixmap_cleanup_hook_pmd);
void removeImageHook(_qt_image_cleanup_hook_64);
- static void executePixmapModificationHooks(QPixmap*);
- static void executePixmapDestructionHooks(QPixmap*);
+ static void executePixmapDataModificationHooks(QPixmapData*);
+ static void executePixmapDataDestructionHooks(QPixmapData*);
static void executeImageHooks(qint64 key);
private:
QList<_qt_image_cleanup_hook_64> imageHooks;
- QList<_qt_pixmap_cleanup_hook_pm> pixmapModificationHooks;
- QList<_qt_pixmap_cleanup_hook_pm> pixmapDestructionHooks;
+ QList<_qt_pixmap_cleanup_hook_pmd> pixmapModificationHooks;
+ QList<_qt_pixmap_cleanup_hook_pmd> pixmapDestructionHooks;
};
QT_END_NAMESPACE
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index f823fdc..d1e5c40 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -320,8 +320,6 @@ QPixmap::QPixmap(const char * const xpm[])
QPixmap::~QPixmap()
{
Q_ASSERT(!data || data->ref >= 1); // Catch if ref-counting changes again
- if (data && data->is_cached && data->ref == 1) // ref will be decrememnted after destructor returns
- QImagePixmapCleanupHooks::executePixmapDestructionHooks(this);
}
/*!
@@ -1025,12 +1023,8 @@ qint64 QPixmap::cacheKey() const
if (isNull())
return 0;
- int classKey = data->classId();
- if (classKey >= 1024)
- classKey = -(classKey >> 10);
- return ((((qint64) classKey) << 56)
- | (((qint64) data->serialNumber()) << 32)
- | ((qint64) (data->detach_no)));
+ Q_ASSERT(data);
+ return data->cacheKey();
}
static void sendResizeEvents(QWidget *target)
@@ -1943,7 +1937,7 @@ void QPixmap::detach()
}
if (data->is_cached && data->ref == 1)
- QImagePixmapCleanupHooks::executePixmapModificationHooks(this);
+ QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data());
#if defined(Q_WS_MAC)
QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast(data.data()) : 0;
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 0e66e09..169a2ec 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -68,6 +68,7 @@
#include "qx11info_x11.h"
#include
#include
+#include
#include
@@ -1228,6 +1229,12 @@ void QX11PixmapData::fill(const QColor &fillColor)
QX11PixmapData::~QX11PixmapData()
{
+ // Cleanup hooks have to be called before the handles are freed
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
+ is_cached = false;
+ }
+
release();
}
diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp
index 65032da..ea4fe6b 100644
--- a/src/gui/image/qpixmapdata.cpp
+++ b/src/gui/image/qpixmapdata.cpp
@@ -45,6 +45,7 @@
#include
#include
#include
+#include
QT_BEGIN_NAMESPACE
@@ -80,6 +81,16 @@ QPixmapData::QPixmapData(PixelType pixelType, int objectId)
QPixmapData::~QPixmapData()
{
+ // Sometimes the pixmap cleanup hooks will be called from derrived classes, which will
+ // then set is_cached to false. For example, on X11 QtOpenGL needs to delete the GLXPixmap
+ // or EGL Pixmap Surface for a given pixmap _before_ the native X11 pixmap is deleted,
+ // otherwise some drivers will leak the GL surface. In this case, QX11PixmapData will
+ // call the cleanup hooks itself before deleting the native pixmap and set is_cached to
+ // false.
+ if (is_cached) {
+ QImagePixmapCleanupHooks::executePixmapDataDestructionHooks(this);
+ is_cached = false;
+ }
}
QPixmapData *QPixmapData::createCompatiblePixmapData() const
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 1125515..827fa18 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -117,6 +117,14 @@ public:
inline int colorCount() const { return metric(QPaintDevice::PdmNumColors); }
inline int depth() const { return d; }
inline bool isNull() const { return is_null; }
+ inline qint64 cacheKey() const {
+ int classKey = id;
+ if (classKey >= 1024)
+ classKey = -(classKey >> 10);
+ return ((((qint64) classKey) << 56)
+ | (((qint64) ser_no) << 32)
+ | ((qint64) detach_no));
+ }
#if defined(Q_OS_SYMBIAN)
virtual void* toNativeType(NativeType type);
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 2a60708..dd977cb 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -1590,10 +1590,8 @@ QGLTextureCache::QGLTextureCache()
Q_ASSERT(qt_gl_texture_cache == 0);
qt_gl_texture_cache = this;
- QImagePixmapCleanupHooks::instance()->addPixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
+ QImagePixmapCleanupHooks::instance()->addPixmapDataModificationHook(cleanupTextures);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->addImageHook(imageCleanupHook);
}
@@ -1601,10 +1599,8 @@ QGLTextureCache::~QGLTextureCache()
{
qt_gl_texture_cache = 0;
- QImagePixmapCleanupHooks::instance()->removePixmapModificationHook(cleanupTextures);
-#ifdef Q_WS_X11
- QImagePixmapCleanupHooks::instance()->removePixmapDestructionHook(cleanupPixmapSurfaces);
-#endif
+ QImagePixmapCleanupHooks::instance()->removePixmapDataModificationHook(cleanupTextures);
+ QImagePixmapCleanupHooks::instance()->removePixmapDataDestructionHook(cleanupBeforePixmapDestruction);
QImagePixmapCleanupHooks::instance()->removeImageHook(imageCleanupHook);
}
@@ -1672,30 +1668,30 @@ void QGLTextureCache::imageCleanupHook(qint64 cacheKey)
}
-void QGLTextureCache::cleanupTextures(QPixmap* pixmap)
+void QGLTextureCache::cleanupTextures(QPixmapData* pmd)
{
// ### remove when the GL texture cache becomes thread-safe
if (qApp->thread() == QThread::currentThread()) {
- const qint64 cacheKey = pixmap->cacheKey();
+ const qint64 cacheKey = pmd->cacheKey();
QGLTexture *texture = instance()->getTexture(cacheKey);
if (texture && texture->options & QGLContext::MemoryManagedBindOption)
instance()->remove(cacheKey);
}
}
-#if defined(Q_WS_X11)
-void QGLTextureCache::cleanupPixmapSurfaces(QPixmap* pixmap)
+void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
{
// Remove any bound textures first:
- cleanupTextures(pixmap);
+ cleanupTextures(pmd);
+ Q_ASSERT(instance()->getTexture(pmd->cacheKey()) == 0);
- QPixmapData *pd = pixmap->data_ptr().data();
- if (pd->classId() == QPixmapData::X11Class) {
- Q_ASSERT(pd->ref == 1); // Make sure reference counting isn't broken
- QGLContextPrivate::destroyGlSurfaceForPixmap(pd);
+#if defined(Q_WS_X11)
+ if (pmd->classId() == QPixmapData::X11Class) {
+ Q_ASSERT(pmd->ref == 0); // Make sure reference counting isn't broken
+ QGLContextPrivate::destroyGlSurfaceForPixmap(pmd);
}
-}
#endif
+}
void QGLTextureCache::deleteIfEmpty()
{
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index 0104f07..713b067 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -522,7 +522,7 @@ public:
QSize bindCompressedTexturePVR(const char *buf, int len);
};
-class QGLTextureCache {
+class Q_AUTOTEST_EXPORT QGLTextureCache {
public:
QGLTextureCache();
~QGLTextureCache();
@@ -539,11 +539,8 @@ public:
static QGLTextureCache *instance();
static void deleteIfEmpty();
static void imageCleanupHook(qint64 cacheKey);
- static void cleanupTextures(QPixmap* pixmap);
-#ifdef Q_WS_X11
- // X11 needs to catch pixmap data destruction to delete EGL/GLX pixmap surfaces
- static void cleanupPixmapSurfaces(QPixmap* pixmap);
-#endif
+ static void cleanupTextures(QPixmapData* pixmap);
+ static void cleanupBeforePixmapDestruction(QPixmapData* pixmap);
private:
QCache m_cache;
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index 11011ee..37bb7c0 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -319,14 +319,14 @@ public:
~QGLBlurTextureCache();
QGLBlurTextureInfo *takeBlurTextureInfo(const QPixmap &pixmap);
- bool hasBlurTextureInfo(const QPixmap &pixmap) const;
+ bool hasBlurTextureInfo(quint64 cacheKey) const;
void insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info);
- void clearBlurTextureInfo(const QPixmap &pixmap);
+ void clearBlurTextureInfo(quint64 cacheKey);
void timerEvent(QTimerEvent *event);
private:
- static void pixmapDestroyed(QPixmap *pixmap);
+ static void pixmapDestroyed(QPixmapData *pixmap);
QCache cache;
@@ -379,21 +379,21 @@ QGLBlurTextureInfo *QGLBlurTextureCache::takeBlurTextureInfo(const QPixmap &pixm
return cache.take(pixmap.cacheKey());
}
-void QGLBlurTextureCache::clearBlurTextureInfo(const QPixmap &pixmap)
+void QGLBlurTextureCache::clearBlurTextureInfo(quint64 cacheKey)
{
- cache.remove(pixmap.cacheKey());
+ cache.remove(cacheKey);
}
-bool QGLBlurTextureCache::hasBlurTextureInfo(const QPixmap &pixmap) const
+bool QGLBlurTextureCache::hasBlurTextureInfo(quint64 cacheKey) const
{
- return cache.contains(pixmap.cacheKey());
+ return cache.contains(cacheKey);
}
void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTextureInfo *info)
{
static bool hookAdded = false;
if (!hookAdded) {
- QImagePixmapCleanupHooks::instance()->addPixmapDestructionHook(pixmapDestroyed);
+ QImagePixmapCleanupHooks::instance()->addPixmapDataDestructionHook(pixmapDestroyed);
hookAdded = true;
}
@@ -406,11 +406,11 @@ void QGLBlurTextureCache::insertBlurTextureInfo(const QPixmap &pixmap, QGLBlurTe
timerId = startTimer(8000);
}
-void QGLBlurTextureCache::pixmapDestroyed(QPixmap *pixmap)
+void QGLBlurTextureCache::pixmapDestroyed(QPixmapData *pmd)
{
foreach (QGLBlurTextureCache *cache, blurTextureCaches) {
- if (cache->hasBlurTextureInfo(*pixmap))
- cache->clearBlurTextureInfo(*pixmap);
+ if (cache->hasBlurTextureInfo(pmd->cacheKey()))
+ cache->clearBlurTextureInfo(pmd->cacheKey());
}
}
diff --git a/tests/auto/qgl/qgl.pro b/tests/auto/qgl/qgl.pro
index 420c4bb..9116f39 100644
--- a/tests/auto/qgl/qgl.pro
+++ b/tests/auto/qgl/qgl.pro
@@ -6,6 +6,6 @@ load(qttest_p4)
requires(contains(QT_CONFIG,opengl))
QT += opengl
-SOURCES += tst_qgl.cpp
-
+SOURCES += tst_qgl.cpp
+RESOURCES = qgl.qrc
diff --git a/tests/auto/qgl/qgl.qrc b/tests/auto/qgl/qgl.qrc
new file mode 100644
index 0000000..653794a
--- /dev/null
+++ b/tests/auto/qgl/qgl.qrc
@@ -0,0 +1,5 @@
+
+
+ ../qpixmap/images/designer.png
+
+
diff --git a/tests/auto/qgl/tst_qgl.cpp b/tests/auto/qgl/tst_qgl.cpp
index cf4616e..d37d727 100644
--- a/tests/auto/qgl/tst_qgl.cpp
+++ b/tests/auto/qgl/tst_qgl.cpp
@@ -56,6 +56,7 @@
#ifdef QT_BUILD_INTERNAL
#include
+#include
#endif
//TESTED_CLASS=
@@ -91,6 +92,8 @@ private slots:
void clipTest();
void destroyFBOAfterContext();
void shareRegister();
+ void qglContextDefaultBindTexture();
+ void textureCleanup();
};
tst_QGL::tst_QGL()
@@ -1938,5 +1941,242 @@ void tst_QGL::shareRegister()
#endif
}
+// Tests QGLContext::bindTexture with default options
+void tst_QGL::qglContextDefaultBindTexture()
+{
+#ifdef QT_BUILD_INTERNAL
+ QGLWidget w;
+ w.makeCurrent();
+
+ QGLContext *ctx = const_cast(w.context());
+
+ QImage *boundImage = new QImage(256, 256, QImage::Format_RGB32);
+ boundImage->fill(0xFFFFFFFF);
+ QPixmap *boundPixmap = new QPixmap(256, 256);
+ boundPixmap->fill(Qt::red);
+
+ // Check that calling QGLContext::bindTexture with default args adds textures to cache
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ GLuint boundImageTextureId = ctx->bindTexture(*boundImage);
+ GLuint boundPixmapTextureId = ctx->bindTexture(*boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ // Make sure the texture IDs returned are valid:
+ QCOMPARE((bool)glIsTexture(boundImageTextureId), GL_TRUE);
+ QCOMPARE((bool)glIsTexture(boundPixmapTextureId), GL_TRUE);
+
+ // Make sure the textures are still there after we delete the image/pixmap:
+ delete boundImage;
+ boundImage = 0;
+ delete boundPixmap;
+ boundPixmap = 0;
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ // Make sure the textures are deleted from the cache after calling QGLContext::deleteTexture()
+ ctx->deleteTexture(boundImageTextureId);
+ ctx->deleteTexture(boundPixmapTextureId);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ // Finally, make sure QGLContext::deleteTexture also deleted the texture IDs:
+ QCOMPARE((bool)glIsTexture(boundImageTextureId), GL_FALSE);
+ QCOMPARE((bool)glIsTexture(boundPixmapTextureId), GL_FALSE);
+#endif
+}
+
+void tst_QGL::textureCleanup()
+{
+#ifdef QT_BUILD_INTERNAL
+ QGLWidget w;
+ w.resize(200,200);
+ w.show();
+ w.makeCurrent();
+
+ // Test pixmaps which have been loaded via QPixmapCache are removed from the texture cache
+ // when the pixmap cache is cleared
+ {
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ QPainter p(&w);
+
+ QPixmap boundPixmap(":designer.png");
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ p.drawPixmap(0, 0, boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ // Need to call end for the GL2 paint engine to release references to pixmap if using tfp
+ p.end();
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ // Check that the texture doesn't get removed from the cache when the pixmap is cleared
+ // as it should still be in the cache:
+ boundPixmap = QPixmap();
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ QPixmapCache::clear();
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+ }
+
+ // Test pixmaps which have been loaded via QPixmapCache are removed from the texture cache
+ // when they are explicitly removed from the pixmap cache
+ {
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ QPainter p(&w);
+
+ QPixmap boundPixmap(128, 128);
+ QString cacheKey = QString::fromLatin1("myPixmap");
+ QPixmapCache::insert(cacheKey, boundPixmap);
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ p.drawPixmap(0, 0, boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ // Need to call end for the GL2 paint engine to release references to pixmap if using tfp
+ p.end();
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ // Check that the texture doesn't get removed from the cache when the pixmap is cleared
+ // as it should still be in the cache:
+ boundPixmap = QPixmap();
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ // Finally, we check that the texture cache entry is removed when we remove the
+ // pixmap cache entry, which should hold the last reference:
+ QPixmapCache::remove(cacheKey);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+ }
+
+ // Check images & pixmaps are removed from the cache when they are deleted
+ {
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ QPainter p(&w);
+
+ QImage *boundImage = new QImage(256, 256, QImage::Format_RGB32);
+ boundImage->fill(0xFFFFFFFF);
+ QPixmap *boundPixmap = new QPixmap(256, 256);
+ boundPixmap->fill(Qt::red);
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ p.drawImage(0, 0, *boundImage);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ p.drawPixmap(0, 0, *boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ // Need to call end for the GL2 paint engine to release references to pixmap if using tfp
+ p.end();
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ delete boundImage;
+ boundImage = 0;
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ delete boundPixmap;
+ boundPixmap = 0;
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+ }
+
+ // Check images & pixmaps are removed from the cache when they are assigned to
+ {
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ QPainter p(&w);
+
+ QImage boundImage(256, 256, QImage::Format_RGB32);
+ boundImage.fill(0xFFFFFFFF);
+ QPixmap boundPixmap(256, 256);
+ boundPixmap.fill(Qt::red);
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ p.drawImage(0, 0, boundImage);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ p.drawPixmap(0, 0, boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ // Need to call end for the GL2 paint engine to release references to pixmap if using tfp
+ p.end();
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ boundImage = QImage(64, 64, QImage::Format_RGB32);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ boundPixmap = QPixmap(64, 64);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+ }
+
+ // Check images & pixmaps are removed from the cache when they are modified (detached)
+ {
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ QPainter p(&w);
+
+ QImage boundImage(256, 256, QImage::Format_RGB32);
+ boundImage.fill(0xFFFFFFFF);
+ QPixmap boundPixmap(256, 256);
+ boundPixmap.fill(Qt::red);
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ p.drawImage(0, 0, boundImage);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ p.drawPixmap(0, 0, boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ // Need to call end for the GL2 paint engine to release references to pixmap if using tfp
+ p.end();
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ boundImage.fill(0x00000000);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ boundPixmap.fill(Qt::blue);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+ }
+
+ // Check that images/pixmaps aren't removed from the cache if a shallow copy has been made
+ QImage copyOfImage;
+ QPixmap copyOfPixmap;
+ int startCacheItemCount = QGLTextureCache::instance()->size();
+ {
+ QPainter p(&w);
+
+ QImage boundImage(256, 256, QImage::Format_RGB32);
+ boundImage.fill(0xFFFFFFFF);
+ QPixmap boundPixmap(256, 256);
+ boundPixmap.fill(Qt::red);
+
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+
+ p.drawImage(0, 0, boundImage);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ p.drawPixmap(0, 0, boundPixmap);
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ // Need to call end for the GL2 paint engine to release references to pixmap if using tfp
+ p.end();
+
+ copyOfImage = boundImage;
+ copyOfPixmap = boundPixmap;
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+ } // boundImage & boundPixmap would have been deleted when they went out of scope
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+2);
+
+ copyOfImage = QImage();
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount+1);
+
+ copyOfPixmap = QPixmap();
+ QCOMPARE(QGLTextureCache::instance()->size(), startCacheItemCount);
+#endif
+}
+
QTEST_MAIN(tst_QGL)
#include "tst_qgl.moc"
--
cgit v0.12
From db4415d06ab58c5c37afc4cb032b4eb89f68594f Mon Sep 17 00:00:00 2001
From: ck
Date: Fri, 29 Jan 2010 15:32:32 +0100
Subject: Assistant: Eliminate private tr contexts.
Merging private tr contexts into the surrounding class keeps
related strings together.
Contributed-by: Ritt Konstantin
Reviewed-by: kh1
---
tools/assistant/lib/qhelpenginecore.cpp | 2 +-
tools/assistant/lib/qhelpsearchresultwidget.cpp | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/tools/assistant/lib/qhelpenginecore.cpp b/tools/assistant/lib/qhelpenginecore.cpp
index 0fceaaa..4809de6 100644
--- a/tools/assistant/lib/qhelpenginecore.cpp
+++ b/tools/assistant/lib/qhelpenginecore.cpp
@@ -119,7 +119,7 @@ bool QHelpEngineCorePrivate::setup()
QHelpDBReader *reader = new QHelpDBReader(absFileName,
QHelpGlobal::uniquifyConnectionName(info.fileName, this), this);
if (!reader->init()) {
- emit q->warning(tr("Cannot open documentation file %1: %2!")
+ emit q->warning(QHelpEngineCore::tr("Cannot open documentation file %1: %2!")
.arg(absFileName, reader->errorMessage()));
continue;
}
diff --git a/tools/assistant/lib/qhelpsearchresultwidget.cpp b/tools/assistant/lib/qhelpsearchresultwidget.cpp
index a3f5aed..e1987d4 100644
--- a/tools/assistant/lib/qhelpsearchresultwidget.cpp
+++ b/tools/assistant/lib/qhelpsearchresultwidget.cpp
@@ -304,7 +304,7 @@ private:
last = resultLastToShow > count ? count : resultLastToShow;
}
}
- hitsLabel->setText(tr("%1 - %2 of %3 Hits").arg(first).arg(last).arg(count));
+ hitsLabel->setText(QHelpSearchResultWidget::tr("%1 - %2 of %3 Hits").arg(first).arg(last).arg(count));
}
private:
--
cgit v0.12
From 4a5e81f5320daa82352b13e670718998b0d2d23b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?=
Date: Fri, 29 Jan 2010 16:14:00 +0100
Subject: Fixed a crash when QPixmaps are destroyed after the ~QApplication.
Destroying QPixmaps after the QApp destructor will leak native pixmap
objects on X11, and it's a general rule that all GUI objects must
be destroyed before the QApp destuctor is called.
Task-number: QTBUG-7746
Reviewed-by: Kim
---
src/gui/image/qpixmap_x11.cpp | 7 ++++++-
src/gui/painting/qpainter.cpp | 4 ++--
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 169a2ec..e1e8a0d 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -1243,8 +1243,13 @@ void QX11PixmapData::release()
delete pengine;
pengine = 0;
- if (!X11)
+ if (!X11) {
+#ifndef QT_NO_DEBUG
+ qWarning("~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication"
+ " object, otherwise the native pixmap object will be leaked.");
+#endif
return;
+ }
if (x11_mask) {
#ifndef QT_NO_XRENDER
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index cde6a2d..bf12c6b 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7509,7 +7509,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
return widgetPrivate->redirected(offset);
}
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return 0;
QMutexLocker locker(globalRedirectionsMutex());
@@ -7529,7 +7529,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
void qt_painter_removePaintDevice(QPaintDevice *dev)
{
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return;
QMutex *mutex = 0;
--
cgit v0.12
From 519760c4256997f26c039cb4b047c6207470b54f Mon Sep 17 00:00:00 2001
From: Leonardo Sobral Cunha
Date: Thu, 28 Jan 2010 18:09:39 +0100
Subject: Adds convenience functions QGraphicsItemPrivate::isOpacityNull
This should unify the error constant used along the code and enforce qreal
to avoid unnecessary double conversions.
Reviewed-by: bnilsen
---
src/gui/graphicsview/qgraphicsitem_p.h | 10 ++++++++--
src/gui/graphicsview/qgraphicsscene.cpp | 7 ++++---
src/gui/graphicsview/qgraphicssceneindex.cpp | 4 ++--
3 files changed, 14 insertions(+), 7 deletions(-)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 5ad6cd5..b3ca3b5 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -358,14 +358,20 @@ public:
return o;
}
+ inline bool isOpacityNull() const
+ { return (opacity < qreal(0.001)); }
+
+ static inline bool isOpacityNull(qreal opacity)
+ { return (opacity < qreal(0.001)); }
+
inline bool isFullyTransparent() const
{
- if (opacity < 0.001)
+ if (isOpacityNull())
return true;
if (!parent)
return false;
- return calcEffectiveOpacity() < 0.001;
+ return isOpacityNull(calcEffectiveOpacity());
}
inline qreal effectiveOpacity() const {
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 54d47fa..842d368 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -4630,7 +4630,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
return; // Item has neither contents nor children!(?)
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
return;
@@ -4750,7 +4750,7 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
qreal opacity, const QTransform *effectTransform,
bool wasDirtyParentSceneTransform, bool drawItem)
{
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemClipsChildrenToShape = (item->d_ptr->flags & QGraphicsItem::ItemClipsChildrenToShape);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
@@ -4980,7 +4980,8 @@ void QGraphicsScenePrivate::processDirtyItemsRecursive(QGraphicsItem *item, bool
}
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity && opacity < 0.0001;
+ const bool itemIsFullyTransparent = !item->d_ptr->ignoreOpacity
+ && QGraphicsItemPrivate::isOpacityNull(opacity);
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity())) {
resetDirtyItem(item, /*recursive=*/itemHasChildren);
return;
diff --git a/src/gui/graphicsview/qgraphicssceneindex.cpp b/src/gui/graphicsview/qgraphicssceneindex.cpp
index 043c4eb..707c71f 100644
--- a/src/gui/graphicsview/qgraphicssceneindex.cpp
+++ b/src/gui/graphicsview/qgraphicssceneindex.cpp
@@ -279,7 +279,7 @@ void QGraphicsSceneIndexPrivate::recursive_items_helper(QGraphicsItem *item, QRe
return;
const qreal opacity = item->d_ptr->combineOpacityFromParent(parentOpacity);
- const bool itemIsFullyTransparent = (opacity < 0.0001);
+ const bool itemIsFullyTransparent = QGraphicsItemPrivate::isOpacityNull(opacity);
const bool itemHasChildren = !item->d_ptr->children.isEmpty();
if (itemIsFullyTransparent && (!itemHasChildren || item->d_ptr->childrenCombineOpacity()))
return;
@@ -554,7 +554,7 @@ QList QGraphicsSceneIndex::estimateTopLevelItems(const QRectF &
/*!
\fn QList QGraphicsSceneIndex::items(Qt::SortOrder order = Qt::DescendingOrder) const
-
+
This pure virtual function all items in the index and sort them using
\a order.
*/
--
cgit v0.12
From 3db33d41ad48953ec7c8d74db24d17fc3685895f Mon Sep 17 00:00:00 2001
From: Leonardo Sobral Cunha
Date: Wed, 27 Jan 2010 13:47:25 +0100
Subject: Cleanup in graphicsitem autotest
Unified multiple class definitions for MyGraphicsView and cleaned whitespaces.
Reviewed-by: bnilsen
---
tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 68 ++++++--------------------
1 file changed, 16 insertions(+), 52 deletions(-)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index 14b9ef0..a515481 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -251,6 +251,21 @@ public:
QBrush brush;
};
+class MyGraphicsView : public QGraphicsView
+{
+public:
+ int repaints;
+ QRegion paintedRegion;
+ MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
+ void paintEvent(QPaintEvent *e)
+ {
+ paintedRegion += e->region();
+ ++repaints;
+ QGraphicsView::paintEvent(e);
+ }
+ void reset() { repaints = 0; paintedRegion = QRegion(); }
+};
+
class tst_QGraphicsItem : public QObject
{
Q_OBJECT
@@ -3165,7 +3180,6 @@ void tst_QGraphicsItem::childrenBoundingRect()
childChild->setPos(500, 500);
child->rotate(90);
-
scene.addPolygon(parent->mapToScene(parent->boundingRect() | parent->childrenBoundingRect()))->setPen(QPen(Qt::red));;
QGraphicsView view(&scene);
@@ -6252,13 +6266,6 @@ void tst_QGraphicsItem::opacity2()
QGraphicsScene scene;
scene.addItem(parent);
- class MyGraphicsView : public QGraphicsView
- { public:
- int repaints;
- MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
- void paintEvent(QPaintEvent *e) { ++repaints; QGraphicsView::paintEvent(e); }
- };
-
MyGraphicsView view(&scene);
view.show();
QTest::qWaitForWindowShown(&view);
@@ -6336,20 +6343,6 @@ void tst_QGraphicsItem::opacityZeroUpdates()
QGraphicsScene scene;
scene.addItem(parent);
- class MyGraphicsView : public QGraphicsView
- { public:
- int repaints;
- QRegion paintedRegion;
- MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
- void paintEvent(QPaintEvent *e)
- {
- ++repaints;
- paintedRegion += e->region();
- QGraphicsView::paintEvent(e);
- }
- void reset() { repaints = 0; paintedRegion = QRegion(); }
- };
-
MyGraphicsView view(&scene);
view.show();
QTest::qWaitForWindowShown(&view);
@@ -7076,21 +7069,6 @@ void tst_QGraphicsItem::deviceTransform()
QCOMPARE(rect3->deviceTransform(deviceX).map(QPointF(50, 50)), mapResult3);
}
-class MyGraphicsView : public QGraphicsView
-{
-public:
- int repaints;
- QRegion paintedRegion;
- MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
- void paintEvent(QPaintEvent *e)
- {
- paintedRegion += e->region();
- ++repaints;
- QGraphicsView::paintEvent(e);
- }
- void reset() { repaints = 0; paintedRegion = QRegion(); }
-};
-
void tst_QGraphicsItem::update()
{
QGraphicsScene scene;
@@ -9835,7 +9813,7 @@ void tst_QGraphicsItem::scenePosChange()
QCOMPARE(child2->changes.count(QGraphicsItem::ItemScenePositionHasChanged), 0);
}
-void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
+void tst_QGraphicsItem::QTBUG_5418_textItemSetDefaultColor()
{
struct Item : public QGraphicsTextItem
{
@@ -9914,20 +9892,6 @@ void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
QGraphicsScene scene;
scene.addItem(parent);
- class MyGraphicsView : public QGraphicsView
- { public:
- int repaints;
- QRegion paintedRegion;
- MyGraphicsView(QGraphicsScene *scene) : QGraphicsView(scene), repaints(0) {}
- void paintEvent(QPaintEvent *e)
- {
- ++repaints;
- paintedRegion += e->region();
- QGraphicsView::paintEvent(e);
- }
- void reset() { repaints = 0; paintedRegion = QRegion(); }
- };
-
MyGraphicsView view(&scene);
view.show();
QTest::qWaitForWindowShown(&view);
--
cgit v0.12
From 08c649e6a81ab13d0c7db6aa1b480ed149e3f770 Mon Sep 17 00:00:00 2001
From: Leonardo Sobral Cunha
Date: Wed, 20 Jan 2010 15:11:58 +0100
Subject: Avoids missing opacity updates by not propagating the ignoreOpacity
flag
When doing a full update of a parent item, by setting one of these flags,
QGraphicsItem::ItemIgnoresTransformations | ItemClipsChildrenToShape |
ItemIsSelectable, the child items that were transparent would not be
shown when setting their respective opacity to 1.0
We just need to set the ignoreOpacity flag when setting opacity to 0.0.
This avoids propagating this flag to the child items when it's not
needed.
Task-number: QT-2653
Reviewed-by: bnilsen
---
src/gui/graphicsview/qgraphicsitem.cpp | 2 +-
tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 40 ++++++++++++++++++++++++++
2 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index ed36f87..86780da 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -2584,7 +2584,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
d_ptr->scene->d_func()->markDirty(this, QRectF(),
/*invalidateChildren=*/true,
/*force=*/false,
- /*ignoreOpacity=*/true);
+ /*ignoreOpacity=*/d_ptr->isOpacityNull());
}
if (d_ptr->isObject)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index a515481..dd8d555 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -434,6 +434,7 @@ private slots:
void QTBUG_4233_updateCachedWithSceneRect();
void QTBUG_5418_textItemSetDefaultColor();
void QTBUG_6738_missingUpdateWithSetParent();
+ void QT_2653_fullUpdateDiscardingOpacityUpdate();
private:
QList paintedItems;
@@ -9919,5 +9920,44 @@ void tst_QGraphicsItem::QTBUG_6738_missingUpdateWithSetParent()
QTRY_VERIFY(view.repaints == 1);
}
+void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ MyGraphicsView view(&scene);
+
+ EventTester *parentGreen = new EventTester();
+ parentGreen->setGeometry(QRectF(20, 20, 100, 100));
+ parentGreen->brush = Qt::green;
+
+ EventTester *childYellow = new EventTester(parentGreen);
+ childYellow->setGeometry(QRectF(10, 10, 50, 50));
+ childYellow->brush = Qt::yellow;
+
+ scene.addItem(parentGreen);
+
+ childYellow->setOpacity(0.0);
+ parentGreen->setOpacity(0.0);
+
+ // set any of the flags below to trigger a fullUpdate to reproduce the bug:
+ // ItemIgnoresTransformations, ItemClipsChildrenToShape, ItemIsSelectable
+ parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ view.show();
+ QTest::qWaitForWindowShown(&view);
+ view.reset();
+
+ parentGreen->setOpacity(1.0);
+
+ QTRY_COMPARE(view.repaints, 1);
+
+ view.reset();
+ childYellow->repaints = 0;
+
+ childYellow->setOpacity(1.0);
+
+ QTRY_COMPARE(view.repaints, 1);
+ QTRY_COMPARE(childYellow->repaints, 1);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"
--
cgit v0.12
From 37f1aec1a4e71a7102e8cd2e2908c8d3be7e29f5 Mon Sep 17 00:00:00 2001
From: Leonardo Sobral Cunha
Date: Thu, 28 Jan 2010 15:43:12 +0100
Subject: Fixes missing update when setting opacity on an item that had opacity
0.0
We need to set the paintedViewBoundingRectsNeedRepaint flag when an item
becomes visible again because when the item has opacity 0.0 the
paintedViewBoundingRects struct can get set as outside of viewport, so the
next time the item is set to visible again we need to diregard this cached
data (otherwise the item will not be updated).
Task-number: QTBUG-7714
Reviewed-by: bnilsen
---
src/gui/graphicsview/qgraphicsitem.cpp | 3 ++
tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 39 ++++++++++++++++++++++++++
2 files changed, 42 insertions(+)
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index 86780da..b4e19d1 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -2569,6 +2569,7 @@ void QGraphicsItem::setOpacity(qreal opacity)
if (newOpacity == d_ptr->opacity)
return;
+ bool wasFullyTransparent = d_ptr->isOpacityNull();
d_ptr->opacity = newOpacity;
// Notify change.
@@ -2585,6 +2586,8 @@ void QGraphicsItem::setOpacity(qreal opacity)
/*invalidateChildren=*/true,
/*force=*/false,
/*ignoreOpacity=*/d_ptr->isOpacityNull());
+ if (wasFullyTransparent)
+ d_ptr->paintedViewBoundingRectsNeedRepaint = 1;
}
if (d_ptr->isObject)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index dd8d555..ae038e7 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -434,6 +434,7 @@ private slots:
void QTBUG_4233_updateCachedWithSceneRect();
void QTBUG_5418_textItemSetDefaultColor();
void QTBUG_6738_missingUpdateWithSetParent();
+ void QTBUG_7714_fullUpdateDiscardingOpacityUpdate2();
void QT_2653_fullUpdateDiscardingOpacityUpdate();
private:
@@ -9959,5 +9960,43 @@ void tst_QGraphicsItem::QT_2653_fullUpdateDiscardingOpacityUpdate()
QTRY_COMPARE(childYellow->repaints, 1);
}
+void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
+{
+ QGraphicsScene scene(0, 0, 200, 200);
+ MyGraphicsView view(&scene);
+ MyGraphicsView origView(&scene);
+
+ EventTester *parentGreen = new EventTester();
+ parentGreen->setGeometry(QRectF(20, 20, 100, 100));
+ parentGreen->brush = Qt::green;
+
+ EventTester *childYellow = new EventTester(parentGreen);
+ childYellow->setGeometry(QRectF(10, 10, 50, 50));
+ childYellow->brush = Qt::yellow;
+
+ scene.addItem(parentGreen);
+
+ origView.show();
+ QTest::qWaitForWindowShown(&origView);
+
+ parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
+
+ origView.reset();
+ childYellow->setOpacity(0.0);
+
+ QTRY_COMPARE(origView.repaints, 1);
+
+ view.show();
+
+ QTest::qWaitForWindowShown(&view);
+ view.reset();
+ origView.reset();
+
+ childYellow->setOpacity(1.0);
+
+ QTRY_COMPARE(origView.repaints, 1);
+ QTRY_COMPARE(view.repaints, 1);
+}
+
QTEST_MAIN(tst_QGraphicsItem)
#include "tst_qgraphicsitem.moc"
--
cgit v0.12
From 465a63d00c2294641539af820435a9a4315f0251 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jan-Arve=20S=C3=A6ther?=
Date: Mon, 1 Feb 2010 09:03:48 +0100
Subject: Don't crash when running Qt on KDE with Oxygen style.
It crashed on application exit because of the order of Q_GLOBAL_STATICs
are not defined if the global statics are in different modules. Thus,
the globalRedirectionAtomic was destroyed first, then the
K_GLOBAL_STATIC(OxygenHelper, ...) got destroyed. Since the
OxygeneHelper contained a QCache of pixmaps it would eventually call
~QPixmap() and reference the destroyed globalRedirectionAtomic....
Task-number: QTBUG-7734
Reviewed-by: gunnar
---
src/gui/painting/qpainter.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index cde6a2d..0f28f7a 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -7529,7 +7529,7 @@ QPaintDevice *QPainter::redirected(const QPaintDevice *device, QPoint *offset)
void qt_painter_removePaintDevice(QPaintDevice *dev)
{
- if (*globalRedirectionAtomic() == 0)
+ if (!globalRedirectionAtomic() || *globalRedirectionAtomic() == 0)
return;
QMutex *mutex = 0;
--
cgit v0.12
From d785467dbb97d4be9de66504dd6fb891da19abff Mon Sep 17 00:00:00 2001
From: Joerg Bornemann
Date: Mon, 1 Feb 2010 12:49:37 +0100
Subject: fix crash in Phonon::DS9 backend
When using a VideoWidget in a QGraphicsProxyWidget, then Phonon::DS9
crashed, if the VideoWidget didn't have a MediaSource.
Reviewed-by: Thierry
---
src/3rdparty/phonon/ds9/videowidget.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/3rdparty/phonon/ds9/videowidget.cpp b/src/3rdparty/phonon/ds9/videowidget.cpp
index 091be16..95423c6 100644
--- a/src/3rdparty/phonon/ds9/videowidget.cpp
+++ b/src/3rdparty/phonon/ds9/videowidget.cpp
@@ -218,6 +218,9 @@ namespace Phonon
if (toNative && m_noNativeRendererSupported)
return current; //no switch here
+ if (!mediaObject())
+ return current;
+
//firt we delete the renderer
//initialization of the widgets
for(int i = 0; i < FILTER_COUNT; ++i) {
--
cgit v0.12
From fe849f50ca83f50f6068b7d494cb228fae1d6309 Mon Sep 17 00:00:00 2001
From: Gunnar Sletta
Date: Mon, 1 Feb 2010 14:30:01 +0100
Subject: Geometry Shader support in QGLShaderProgram
---
src/opengl/qglextensions.cpp | 6 ++
src/opengl/qglextensions_p.h | 46 ++++++++++++
src/opengl/qglshaderprogram.cpp | 153 ++++++++++++++++++++++++++++++++++++++++
src/opengl/qglshaderprogram.h | 24 ++++++-
4 files changed, 228 insertions(+), 1 deletion(-)
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index c091191..a4b2dc1 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -220,6 +220,12 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
+ // Geometry shaders are optional...
+ glProgramParameteriEXT = (_glProgramParameteriEXT) ctx->getProcAddress(QLatin1String("glProgramParameteriEXT"));
+ glFramebufferTextureEXT = (_glFramebufferTextureEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureEXT"));
+ glFramebufferTextureLayerEXT = (_glFramebufferTextureLayerEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureLayerEXT"));
+ glFramebufferTextureFaceEXT = (_glFramebufferTextureFaceEXT) ctx->getProcAddress(QLatin1String("glFramebufferTextureFaceEXT"));
+
#if defined(QT_OPENGL_ES_2)
// The GLSL shader functions are always present in OpenGL/ES 2.0.
// The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index 86096d2..e65e3a1 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -184,6 +184,15 @@ typedef void (APIENTRY *_glBlitFramebufferEXT) (int srcX0, int srcY0, int srcX1,
typedef void (APIENTRY *_glRenderbufferStorageMultisampleEXT) (GLenum target, GLsizei samples,
GLenum internalformat, GLsizei width, GLsizei height);
+// GL_EXT_geometry_shader4
+typedef void (APIENTRY *_glProgramParameteriEXT)(GLuint program, GLenum pname, GLint value);
+typedef void (APIENTRY *_glFramebufferTextureEXT)(GLenum target, GLenum attachment,
+ GLuint texture, GLint level);
+typedef void (APIENTRY *_glFramebufferTextureLayerEXT)(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLint layer);
+typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum attachment,
+ GLuint texture, GLint level, GLenum face);
+
// ARB_texture_compression
typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei,
GLsizei, GLint, GLsizei, const GLvoid *);
@@ -294,6 +303,10 @@ struct QGLExtensionFuncs
qt_glMapBufferARB = 0;
qt_glUnmapBufferARB = 0;
+ qt_glProgramParameteriEXT = 0;
+ qt_glFramebufferTextureEXT = 0;
+ qt_glFramebufferTextureLayerEXT = 0;
+ qt_glFramebufferTextureFaceEXT = 0;
#if !defined(QT_OPENGL_ES)
// Texture compression
qt_glCompressedTexImage2DARB = 0;
@@ -406,6 +419,11 @@ struct QGLExtensionFuncs
_glMapBufferARB qt_glMapBufferARB;
_glUnmapBufferARB qt_glUnmapBufferARB;
+ // Geometry shaders...
+ _glProgramParameteriEXT qt_glProgramParameteriEXT;
+ _glFramebufferTextureEXT qt_glFramebufferTextureEXT;
+ _glFramebufferTextureLayerEXT qt_glFramebufferTextureLayerEXT;
+ _glFramebufferTextureFaceEXT qt_glFramebufferTextureFaceEXT;
#if !defined(QT_OPENGL_ES)
// Texture compression
_glCompressedTexImage2DARB qt_glCompressedTexImage2DARB;
@@ -642,6 +660,29 @@ struct QGLExtensionFuncs
#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
#endif
+// Geometry shader defines
+#ifndef GL_GEOMETRY_SHADER_EXT
+# define GL_GEOMETRY_SHADER_EXT 0x8DD9
+# define GL_GEOMETRY_VERTICES_OUT_EXT 0x8DDA
+# define GL_GEOMETRY_INPUT_TYPE_EXT 0x8DDB
+# define GL_GEOMETRY_OUTPUT_TYPE_EXT 0x8DDC
+# define GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT 0x8C29
+# define GL_MAX_GEOMETRY_VARYING_COMPONENTS_EXT 0x8DDD
+# define GL_MAX_VERTEX_VARYING_COMPONENTS_EXT 0x8DDE
+# define GL_MAX_VARYING_COMPONENTS_EXT 0x8B4B
+# define GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT 0x8DDF
+# define GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT 0x8DE0
+# define GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT 0x8DE1
+# define GL_LINES_ADJACENCY_EXT 0xA
+# define GL_LINE_STRIP_ADJACENCY_EXT 0xB
+# define GL_TRIANGLES_ADJACENCY_EXT 0xC
+# define GL_TRIANGLE_STRIP_ADJACENCY_EXT 0xD
+# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT 0x8DA8
+# define GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_EXT 0x8DA9
+# define GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT 0x8DA7
+# define GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER_EXT 0x8CD4
+# define GL_PROGRAM_POINT_SIZE_EXT 0x8642
+#endif
#if !defined(QT_OPENGL_ES_2)
#define glProgramStringARB QGLContextPrivate::extensionFuncs(ctx).qt_glProgramStringARB
@@ -759,6 +800,11 @@ struct QGLExtensionFuncs
#define glClearDepth glClearDepthf
#endif
+#define glProgramParameteriEXT QGLContextPrivate::extensionFuncs(ctx).qt_glProgramParameteriEXT
+#define glFramebufferTextureEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureEXT
+#define glFramebufferTextureLayerEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureLayerEXT
+#define glFramebufferTextureFaceEXT QGLContextPrivate::extensionFuncs(ctx).qt_glFramebufferTextureFaceEXT
+
#if !defined(QT_OPENGL_ES)
#define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB
#endif
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 5e2f1f5..43d1df8 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -213,6 +213,8 @@ bool QGLShaderPrivate::create()
GLuint shader;
if (shaderType == QGLShader::Vertex)
shader = glCreateShader(GL_VERTEX_SHADER);
+ else if (shaderType == QGLShader::Geometry)
+ shader = glCreateShader(GL_GEOMETRY_SHADER_EXT);
else
shader = glCreateShader(GL_FRAGMENT_SHADER);
if (!shader) {
@@ -496,6 +498,10 @@ GLuint QGLShader::shaderId() const
return d->shaderGuard.id();
}
+
+
+
+
#undef ctx
#define ctx programGuard.context()
@@ -508,8 +514,12 @@ public:
, linked(false)
, inited(false)
, removingShaders(false)
+ , geometryVertexCount(64)
+ , geometryInputType(0)
+ , geometryOutputType(0)
, vertexShader(0)
, fragmentShader(0)
+ , geometryShader(0)
{
}
~QGLShaderProgramPrivate();
@@ -518,11 +528,17 @@ public:
bool linked;
bool inited;
bool removingShaders;
+
+ int geometryVertexCount;
+ GLenum geometryInputType;
+ GLenum geometryOutputType;
+
QString log;
QList shaders;
QList anonShaders;
QGLShader *vertexShader;
QGLShader *fragmentShader;
+ QGLShader *geometryShader;
bool hasShader(QGLShader::ShaderType type) const;
};
@@ -820,6 +836,22 @@ bool QGLShaderProgram::link()
GLuint program = d->programGuard.id();
if (!program)
return false;
+
+ // Set up the geometry shader parameters
+ if (glProgramParameteriEXT) {
+ foreach (QGLShader *shader, d->shaders) {
+ if (shader->shaderType() & QGLShader::Geometry) {
+ glProgramParameteriEXT(program, GL_GEOMETRY_INPUT_TYPE_EXT,
+ d->geometryInputType);
+ glProgramParameteriEXT(program, GL_GEOMETRY_OUTPUT_TYPE_EXT,
+ d->geometryOutputType);
+ glProgramParameteriEXT(program, GL_GEOMETRY_VERTICES_OUT_EXT,
+ d->geometryVertexCount);
+ break;
+ }
+ }
+ }
+
glLinkProgram(program);
GLint value = 0;
glGetProgramiv(program, GL_LINK_STATUS, &value);
@@ -2830,6 +2862,97 @@ void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *
#undef ctx
/*!
+ Returns the hardware limit for how many vertices a geometry shader
+ can output.
+
+ \sa setGeometryShaderOutputVertexCount
+*/
+int QGLShaderProgram::maxGeometryOutputVertices() const
+{
+ int n;
+ glGetIntegerv(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT, &n);
+ return n;
+}
+
+
+
+/*!
+ Sets the maximum number of vertices the current geometry shader
+ program will produce, if active.
+
+ This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryOutputVertexCount(int count)
+{
+#ifndef QT_NO_DEBUG
+ int max = maxGeometryOutputVertices();
+ if (count > max) {
+ qWarning("QGLShaderProgram::setGeometryOutputVertexCount: count: %d higher than maximum: %d",
+ count, max);
+ }
+#endif
+ d_func()->geometryVertexCount = count;
+}
+
+
+/*!
+ Returns the maximum number of vertices the current geometry shader
+ program will produce, if active.
+
+ This parameter takes effect the ntext time the program is linked.
+*/
+int QGLShaderProgram::geometryOutputVertexCount() const
+{
+ return d_func()->geometryVertexCount;
+}
+
+
+/*!
+ Sets the output type from the geometry shader, if active.
+
+ This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryInputType(GLenum inputType)
+{
+ d_func()->geometryInputType = inputType;
+}
+
+
+/*!
+ Returns the geometry shader input type, if active.
+
+ This parameter takes effect the next time the program is linked.
+ */
+
+GLenum QGLShaderProgram::geometryInputType() const
+{
+ return d_func()->geometryInputType;
+}
+
+
+/*!
+ Sets the output type from the geometry shader, if active.
+
+ This parameter takes effect the next time the program is linked.
+*/
+void QGLShaderProgram::setGeometryOutputType(GLenum outputType)
+{
+ d_func()->geometryOutputType = outputType;
+}
+
+
+/*!
+ Returns the geometry shader output type, if active.
+
+ This parameter takes effect the next time the program is linked.
+ */
+GLenum QGLShaderProgram::geometryOutputType() const
+{
+ return d_func()->geometryOutputType;
+}
+
+
+/*!
Returns true if shader programs written in the OpenGL Shading
Language (GLSL) are supported on this system; false otherwise.
@@ -2861,6 +2984,36 @@ void QGLShaderProgram::shaderDestroyed()
removeShader(shader);
}
+
+#undef ctx
+#undef context
+
+/*!
+ Returns true if shader programs of type \a type are supported on
+ this system; false otherwise.
+
+ The \a context is used to resolve the GLSL extensions.
+ If \a context is null, then QGLContext::currentContext() is used.
+*/
+bool QGLShader::hasShaders(ShaderType type, const QGLContext *context)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+#endif
+ bool resolved = qt_resolve_glsl_extensions(const_cast(context));
+ if (!resolved)
+ return false;
+ const QGLContext *ctx = context;
+ if ((type & Geometry) && !glProgramParameteriEXT)
+ return false;
+ return true;
+}
+
+
+
#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
/*! \internal */
void QGLShaderProgram::setUniformValue(int location, QMacCompatGLint value)
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index 24ab986..face66e 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -66,7 +66,8 @@ public:
enum ShaderTypeBit
{
Vertex = 0x0001,
- Fragment = 0x0002
+ Fragment = 0x0002,
+ Geometry = 0x0004
};
Q_DECLARE_FLAGS(ShaderType, ShaderTypeBit)
@@ -88,6 +89,8 @@ public:
GLuint shaderId() const;
+ static bool hasShaders(ShaderType type, const QGLContext *context = 0);
+
private:
friend class QGLShaderProgram;
@@ -104,6 +107,14 @@ class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
{
Q_OBJECT
public:
+ enum GeometryTypes
+ {
+ LinesWithAdjacencyGeometryType = 0xa,
+ LineStripWithAdjacencyGeometryType = 0xb,
+ TrianglesWithAdjacencyGeometryType = 0xc,
+ TriangleStripWithAdjacencyGeometryType = 0xd
+ };
+
explicit QGLShaderProgram(QObject *parent = 0);
explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
virtual ~QGLShaderProgram();
@@ -128,6 +139,17 @@ public:
GLuint programId() const;
+ int maxGeometryOutputVertices() const;
+
+ void setGeometryOutputVertexCount(int count);
+ int geometryOutputVertexCount() const;
+
+ void setGeometryInputType(GLenum inputType);
+ GLenum geometryInputType() const;
+
+ void setGeometryOutputType(GLenum outputType);
+ GLenum geometryOutputType() const;
+
void bindAttributeLocation(const char *name, int location);
void bindAttributeLocation(const QByteArray& name, int location);
void bindAttributeLocation(const QString& name, int location);
--
cgit v0.12
From afe0f17eb5974adbedd1bc1f2fcd98459d92df47 Mon Sep 17 00:00:00 2001
From: Kim Motoyoshi Kalland
Date: Mon, 1 Feb 2010 14:30:15 +0100
Subject: Fixed garbled 3D Qt logo in the overpainting example.
Disable vertex attribute arrays in the GL2 paint engine when
calling QPainter::beginNativePainting() and QPainter::end().
Task-number: QTBUG-7781
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 b282676..35e95be 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -558,6 +558,9 @@ void QGL2PaintEngineExPrivate::resetGLState()
glStencilMask(0xff);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glStencilFunc(GL_ALWAYS, 0, 0xff);
+ glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
+ glDisableVertexAttribArray(QT_OPACITY_ATTR);
}
void QGL2PaintEngineEx::endNativePainting()
--
cgit v0.12
From 849257a1cf993275d6d1e7f39f8374cc4d879d13 Mon Sep 17 00:00:00 2001
From: ck
Date: Mon, 1 Feb 2010 16:27:30 +0100
Subject: QAbstractItemModel docs: Fix typo.
---
src/corelib/kernel/qabstractitemmodel.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index fdbc5ba..bf69b4c 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -1265,7 +1265,7 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
/*!
\fn QModelIndex QAbstractItemModel::parent(const QModelIndex &index) const = 0
- Returns the parent of the model item with the given \a index. If the model
+ Returns the parent of the model item with the given \a index. If the item
has no parent, an invalid QModelIndex is returned.
A common convention used in models that expose tree data structures is that
--
cgit v0.12
From 94f5f21ac88de0d940d6ac27d222f1ef8e66d939 Mon Sep 17 00:00:00 2001
From: Gabriel de Dietrich
Date: Mon, 1 Feb 2010 18:03:06 +0100
Subject: Assert failure when setting a widget focus proxy as its successor in
tab order
Now we check that and skip it from the tab list. Auto-test included.
Reviewed-by: leo
Task-number: QTBUG-7532
---
src/gui/kernel/qwidget.cpp | 2 ++
tests/auto/qwidget/tst_qwidget.cpp | 14 ++++++++++++++
2 files changed, 16 insertions(+)
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index ffad38b..4054d2a 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -6414,6 +6414,8 @@ void QWidget::setTabOrder(QWidget* first, QWidget *second)
first = fp;
}
+ if (fp == second)
+ return;
if (QWidget *sp = second->focusProxy())
second = sp;
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index ea90ae3..1fb323e 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -396,6 +396,8 @@ private slots:
void focusProxyAndInputMethods();
void scrollWithoutBackingStore();
+ void taskQTBUG_7532_tabOrderWithFocusProxy();
+
private:
bool ensureScreenSize(int width, int height);
QWidget *testWidget;
@@ -9783,5 +9785,17 @@ void tst_QWidget::scrollWithoutBackingStore()
QCOMPARE(child.pos(),QPoint(25,25));
}
+void tst_QWidget::taskQTBUG_7532_tabOrderWithFocusProxy()
+{
+ QWidget w;
+ w.setFocusPolicy(Qt::TabFocus);
+ QWidget *fp = new QWidget(&w);
+ fp->setFocusPolicy(Qt::TabFocus);
+ w.setFocusProxy(fp);
+ QWidget::setTabOrder(&w, fp);
+
+ // No Q_ASSERT, then it's allright.
+}
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"
--
cgit v0.12
From cf3eddb9c917aa5180a961c2bc9700e47a5f8434 Mon Sep 17 00:00:00 2001
From: Robert Loehning
Date: Mon, 1 Feb 2010 19:24:25 +0100
Subject: Fixed handling of paths containing ".." in QFileSystemModel on
Windows.
Reviewed-by: Jan-Arve
---
src/gui/dialogs/qfilesystemmodel.cpp | 84 ++++++++++++++++--------------------
1 file changed, 38 insertions(+), 46 deletions(-)
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index ae75126..1016980 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -51,6 +51,9 @@
#ifdef Q_OS_WIN
#include
#endif
+#ifdef Q_OS_WIN32
+#include
+#endif
QT_BEGIN_NAMESPACE
@@ -278,53 +281,38 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QM
return indexNode;
}
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
static QString qt_GetLongPathName(const QString &strShortPath)
{
- QString longPath;
- int i = 0;
- if (strShortPath == QLatin1String(".")
- || (strShortPath.startsWith(QLatin1String("//")))
- || (strShortPath.startsWith(QLatin1String("\\\\")))) // unc
+ if (strShortPath.isEmpty()
+ || strShortPath == QLatin1String(".") || strShortPath == QLatin1String(".."))
return strShortPath;
- QString::const_iterator it = strShortPath.constBegin();
- QString::const_iterator constEnd = strShortPath.constEnd();
- do {
- bool isSep = (*it == QLatin1Char('\\') || *it == QLatin1Char('/'));
- if (isSep || it == constEnd) {
- QString section = (it == constEnd ? strShortPath : strShortPath.left(i));
- // FindFirstFile does not handle volumes ("C:"), so we have to catch that ourselves.
- if (section.endsWith(QLatin1Char(':'))) {
- longPath.append(section.toUpper());
- } else {
- HANDLE h;
-#ifndef Q_OS_WINCE
- //We add the extend length prefix to handle long path
- QString longSection = QLatin1String("\\\\?\\")+QDir::toNativeSeparators(section);
-#else
- QString longSection = QDir::toNativeSeparators(section);
-#endif
- WIN32_FIND_DATA findData;
- h = ::FindFirstFile((wchar_t*)longSection.utf16(), &findData);
- if (h != INVALID_HANDLE_VALUE) {
- longPath.append(QString::fromWCharArray(findData.cFileName));
- ::FindClose(h);
- } else {
- longPath.append(section);
- break;
- }
- }
- if (it != constEnd)
- longPath.append(*it);
- else
- break;
- }
- ++it;
- if (isSep && it == constEnd) // break out if the last character is a separator
- break;
- ++i;
- } while (true);
- return longPath;
+ if (strShortPath.length() == 2 && strShortPath.endsWith(QLatin1Char(':')))
+ return strShortPath.toUpper();
+ const QString absPath = QDir(strShortPath).absolutePath();
+ if (absPath.startsWith(QLatin1String("//"))
+ || absPath.startsWith(QLatin1String("\\\\"))) // unc
+ return QDir::fromNativeSeparators(absPath);
+ if (absPath.startsWith(QLatin1Char('/')))
+ return QString();
+ const QString inputString = QLatin1String("\\\\?\\") + QDir::toNativeSeparators(absPath);
+ QVarLengthArray buffer(MAX_PATH);
+ DWORD result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ if (result > DWORD(buffer.size())) {
+ buffer.resize(result);
+ result = ::GetLongPathName((wchar_t*)inputString.utf16(),
+ buffer.data(),
+ buffer.size());
+ }
+ if (result > 4) {
+ QString longPath = QString::fromWCharArray(buffer.data() + 4); // ignoring prefix
+ longPath[0] = longPath.at(0).toUpper(); // capital drive letters
+ return QDir::fromNativeSeparators(longPath);
+ } else {
+ return QDir::fromNativeSeparators(strShortPath);
+ }
}
#endif
@@ -342,7 +330,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
// Construct the nodes up to the new root path if they need to be built
QString absolutePath;
-#ifdef Q_OS_WIN
+#ifdef Q_OS_WIN32
QString longPath = qt_GetLongPathName(path);
#else
QString longPath = path;
@@ -1357,7 +1345,11 @@ QModelIndex QFileSystemModel::setRootPath(const QString &newPath)
{
Q_D(QFileSystemModel);
#ifdef Q_OS_WIN
- QString longNewPath = QDir::fromNativeSeparators(qt_GetLongPathName(newPath));
+#ifdef Q_OS_WIN32
+ QString longNewPath = qt_GetLongPathName(newPath);
+#else
+ QString longNewPath = QDir::fromNativeSeparators(newPath);
+#endif
#else
QString longNewPath = newPath;
#endif
--
cgit v0.12
From 9258959f4f81b9c3efa4418aa344a5be5f9d12ab Mon Sep 17 00:00:00 2001
From: Leonardo Sobral Cunha
Date: Mon, 1 Feb 2010 19:55:07 +0100
Subject: Fix QTBUG_7714_fullUpdateDiscardingOpacityUpdate2 autotest in
qws-linux
The two views were displayed on top of each other, so some repaints were
not triggered.
---
tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
index ae038e7..7b54a3b 100644
--- a/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
+++ b/tests/auto/qgraphicsitem/tst_qgraphicsitem.cpp
@@ -9978,6 +9978,8 @@ void tst_QGraphicsItem::QTBUG_7714_fullUpdateDiscardingOpacityUpdate2()
origView.show();
QTest::qWaitForWindowShown(&origView);
+ origView.setGeometry(origView.width() + 20, 20,
+ origView.width(), origView.height());
parentGreen->setFlag(QGraphicsItem::ItemIgnoresTransformations);
--
cgit v0.12
From 787824cb4add4d45a0e90fd736a54e75fa048475 Mon Sep 17 00:00:00 2001
From: Kim Motoyoshi Kalland
Date: Tue, 2 Feb 2010 10:18:15 +0100
Subject: Fixed missing textures in the boxes demo.
The boxes demo assumed that the current GL colour was the default white,
but the GL2 paint engine set it to black. Fixed by resetting the colour
to white in resetGLState().
Task-number: QTBUG-7779
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 35e95be..406112a 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -561,6 +561,7 @@ void QGL2PaintEngineExPrivate::resetGLState()
glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
glDisableVertexAttribArray(QT_OPACITY_ATTR);
+ glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib()
}
void QGL2PaintEngineEx::endNativePainting()
--
cgit v0.12
From e8b6c949c006393ab690aa3e890cd48defc97b77 Mon Sep 17 00:00:00 2001
From: Olivier Goffart
Date: Tue, 2 Feb 2010 11:06:59 +0100
Subject: Document that QModelIndex::child does not work for the root item
Reviewed-by: Thierry
---
src/corelib/kernel/qabstractitemmodel.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/corelib/kernel/qabstractitemmodel.cpp b/src/corelib/kernel/qabstractitemmodel.cpp
index dbf422e..36e4af9 100644
--- a/src/corelib/kernel/qabstractitemmodel.cpp
+++ b/src/corelib/kernel/qabstractitemmodel.cpp
@@ -1006,6 +1006,9 @@ void QAbstractItemModelPrivate::columnsRemoved(const QModelIndex &parent,
Returns the child of the model index that is stored in the given \a row and
\a column.
+ \note This function does not work for an invalid model index which is often
+ used as the root index.
+
\sa parent(), sibling()
*/
--
cgit v0.12
From f063786144477336c462b06642fc3725c060311d Mon Sep 17 00:00:00 2001
From: ck
Date: Tue, 2 Feb 2010 11:45:04 +0100
Subject: Assistant: Give meaningful context to translations.
Reviewed-by: kh1
Instigated-by: Friedemann Kleint
---
tools/assistant/lib/qhelp_global.cpp | 3 +-
tools/assistant/lib/qhelpprojectdata.cpp | 47 ++++++++++++++--------
tools/assistant/tools/assistant/cmdlineparser.cpp | 6 ++-
tools/assistant/tools/assistant/helpviewer.cpp | 5 ++-
tools/assistant/tools/assistant/main.cpp | 40 +++++++++++-------
.../assistant/tools/qcollectiongenerator/main.cpp | 21 ++++++----
tools/assistant/tools/qhelpgenerator/main.cpp | 11 +++--
7 files changed, 85 insertions(+), 48 deletions(-)
diff --git a/tools/assistant/lib/qhelp_global.cpp b/tools/assistant/lib/qhelp_global.cpp
index 8e96b55..d8a94d3 100644
--- a/tools/assistant/lib/qhelp_global.cpp
+++ b/tools/assistant/lib/qhelp_global.cpp
@@ -39,6 +39,7 @@
**
****************************************************************************/
+#include
#include
#include
#include
@@ -60,7 +61,7 @@ QString QHelpGlobal::uniquifyConnectionName(const QString &name, void *pointer)
QString QHelpGlobal::documentTitle(const QString &content)
{
- QString title = QObject::tr("Untitled");
+ QString title = QCoreApplication::translate("QHelp", "Untitled");
if (!content.isEmpty()) {
int start = content.indexOf(QLatin1String(""), 0, Qt::CaseInsensitive) + 7;
int end = content.indexOf(QLatin1String(" "), 0, Qt::CaseInsensitive);
diff --git a/tools/assistant/lib/qhelpprojectdata.cpp b/tools/assistant/lib/qhelpprojectdata.cpp
index 869a446..83491a0 100644
--- a/tools/assistant/lib/qhelpprojectdata.cpp
+++ b/tools/assistant/lib/qhelpprojectdata.cpp
@@ -41,6 +41,7 @@
#include "qhelpprojectdata_p.h"
+#include
#include
#include
#include
@@ -82,7 +83,7 @@ private:
void QHelpProjectDataPrivate::raiseUnknownTokenError()
{
- raiseError(QObject::tr("Unknown token."));
+ raiseError(QCoreApplication::translate("QHelpProject", "Unknown token."));
}
void QHelpProjectDataPrivate::readData(const QByteArray &contents)
@@ -95,12 +96,14 @@ void QHelpProjectDataPrivate::readData(const QByteArray &contents)
&& attributes().value(QLatin1String("version")) == QLatin1String("1.0"))
readProject();
else
- raiseError(QObject::tr("Unknown token. Expected \"QtHelpProject\"!"));
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "Unknown token. Expected \"QtHelpProject\"!"));
}
}
if (hasError()) {
- raiseError(QObject::tr("Error in line %1: %2").arg(lineNumber())
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "Error in line %1: %2").arg(lineNumber())
.arg(errorString()));
}
}
@@ -113,11 +116,15 @@ void QHelpProjectDataPrivate::readProject()
if (name() == QLatin1String("virtualFolder")) {
virtualFolder = readElementText();
if (virtualFolder.contains(QLatin1String("/")))
- raiseError(QObject::tr("A virtual folder must not contain a \'/\' character!"));
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "A virtual folder must not contain "
+ "a \'/\' character!"));
} else if (name() == QLatin1String("namespace")) {
namespaceName = readElementText();
if (namespaceName.contains(QLatin1String("/")))
- raiseError(QObject::tr("A namespace must not contain a \'/\' character!"));
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "A namespace must not contain a "
+ "\'/\' character!"));
} else if (name() == QLatin1String("customFilter")) {
readCustomFilter();
} else if (name() == QLatin1String("filterSection")) {
@@ -125,17 +132,21 @@ void QHelpProjectDataPrivate::readProject()
} else if (name() == QLatin1String("metaData")) {
QString n = attributes().value(QLatin1String("name")).toString();
if (!metaData.contains(n))
- metaData[n] = attributes().value(QLatin1String("value")).toString();
+ metaData[n]
+ = attributes().value(QLatin1String("value")).toString();
else
- metaData.insert(n, attributes().value(QLatin1String("value")).toString());
+ metaData.insert(n, attributes().
+ value(QLatin1String("value")).toString());
} else {
raiseUnknownTokenError();
}
} else if (isEndElement() && name() == QLatin1String("QtHelpProject")) {
if (namespaceName.isEmpty())
- raiseError(QObject::tr("Missing namespace in QtHelpProject."));
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "Missing namespace in QtHelpProject."));
else if (virtualFolder.isEmpty())
- raiseError(QObject::tr("Missing virtual folder in QtHelpProject"));
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "Missing virtual folder in QtHelpProject"));
break;
}
}
@@ -223,12 +234,14 @@ void QHelpProjectDataPrivate::readKeywords()
if (attributes().value(QLatin1String("ref")).toString().isEmpty()
|| (attributes().value(QLatin1String("name")).toString().isEmpty()
&& attributes().value(QLatin1String("id")).toString().isEmpty()))
- raiseError(QObject::tr("Missing attribute in keyword at line %1.")
- .arg(lineNumber()));
- filterSectionList.last().addIndex(
- QHelpDataIndexItem(attributes().value(QLatin1String("name")).toString(),
- attributes().value(QLatin1String("id")).toString(),
- attributes().value(QLatin1String("ref")).toString()));
+ raiseError(QCoreApplication::translate("QHelpProject",
+ "Missing attribute in keyword at line %1.")
+ .arg(lineNumber()));
+ filterSectionList.last()
+ .addIndex(QHelpDataIndexItem(attributes().
+ value(QLatin1String("name")).toString(),
+ attributes().value(QLatin1String("id")).toString(),
+ attributes().value(QLatin1String("ref")).toString()));
} else {
raiseUnknownTokenError();
}
@@ -346,8 +359,8 @@ bool QHelpProjectData::readData(const QString &fileName)
d->rootPath = QFileInfo(fileName).absolutePath();
QFile file(fileName);
if (!file.open(QIODevice::ReadOnly)) {
- d->errorMsg = QObject::tr("The input file %1 could not be opened!")
- .arg(fileName);
+ d->errorMsg = QCoreApplication::translate("QHelpProject",
+ "The input file %1 could not be opened!").arg(fileName);
return false;
}
diff --git a/tools/assistant/tools/assistant/cmdlineparser.cpp b/tools/assistant/tools/assistant/cmdlineparser.cpp
index b3ba93c..b063830 100644
--- a/tools/assistant/tools/assistant/cmdlineparser.cpp
+++ b/tools/assistant/tools/assistant/cmdlineparser.cpp
@@ -278,10 +278,12 @@ void CmdLineParser::showMessage(const QString &msg, bool error)
return;
#ifdef Q_OS_WIN
QString s = QLatin1String("") + msg + QLatin1String(" ");
+ const QString &message
+ = QCoreApplication::translate("Assistant", "Qt Assistant"), s);
if (error)
- QMessageBox::critical(0, QObject::tr("Qt Assistant"), s);
+ QMessageBox::critical(0, message);
else
- QMessageBox::information(0, QObject::tr("Qt Assistant"), s);
+ QMessageBox::information(0, message);
#else
fprintf(error ? stderr : stdout, "%s\n", qPrintable(msg));
#endif
diff --git a/tools/assistant/tools/assistant/helpviewer.cpp b/tools/assistant/tools/assistant/helpviewer.cpp
index bd75f3a..00504e7 100644
--- a/tools/assistant/tools/assistant/helpviewer.cpp
+++ b/tools/assistant/tools/assistant/helpviewer.cpp
@@ -67,8 +67,9 @@ QT_BEGIN_NAMESPACE
namespace {
const QString PageNotFoundMessage =
- QObject::tr("Error 404... "
- "
The page could not be found '%1'
");
+ QCoreApplication::translate("HelpViewer",
+ "Error 404... "
+ "
The page could not be found '%1' ");
}
#if !defined(QT_NO_WEBKIT)
diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp
index 434a211..cc76f81 100644
--- a/tools/assistant/tools/assistant/main.cpp
+++ b/tools/assistant/tools/assistant/main.cpp
@@ -174,8 +174,9 @@ bool synchronizeDocs(QHelpEngineCore &collection,
if (!cachedDocs.contains(doc)) {
const QString &docFile = collection.documentationFileName(doc);
if (!cachedCollection.registerDocumentation(docFile)) {
- cmd.showMessage(QObject::tr("Error registering documentation file '%1': %2").
- arg(docFile).arg(cachedCollection.error()), true);
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error registering documentation file '%1': %2").
+ arg(docFile).arg(cachedCollection.error()), true);
return false;
}
}
@@ -212,7 +213,8 @@ bool rebuildSearchIndex(QCoreApplication &app, const QString &collectionFile,
TRACE_OBJ
QHelpEngine engine(collectionFile);
if (!engine.setupData()) {
- cmd.showMessage(QObject::tr("Error: %1").arg(engine.error()), true);
+ cmd.showMessage(QCoreApplication::translate("Assistant", "Error: %1")
+ .arg(engine.error()), true);
return false;
}
@@ -250,13 +252,14 @@ bool registerDocumentation(QHelpEngineCore &collection, CmdLineParser &cmd,
{
TRACE_OBJ
if (!collection.registerDocumentation(cmd.helpFile())) {
- cmd.showMessage(
- QObject::tr("Could not register documentation file\n%1\n\nReason:\n%2")
- .arg(cmd.helpFile()).arg(collection.error()), true);
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Could not register documentation file\n%1\n\nReason:\n%2")
+ .arg(cmd.helpFile()).arg(collection.error()), true);
return false;
}
if (printSuccess)
- cmd.showMessage(QObject::tr("Documentation successfully registered."),
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Documentation successfully registered."),
false);
CollectionConfiguration::updateLastRegisterTime(collection);
return true;
@@ -267,14 +270,16 @@ bool unregisterDocumentation(QHelpEngineCore &collection,
{
TRACE_OBJ
if (!collection.unregisterDocumentation(namespaceName)) {
- cmd.showMessage(QObject::tr("Could not unregister documentation"
- " file\n%1\n\nReason:\n%2").
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Could not unregister documentation"
+ " file\n%1\n\nReason:\n%2").
arg(cmd.helpFile()).arg(collection.error()), true);
return false;
}
updateLastPagesOnUnregister(collection, namespaceName);
if (printSuccess)
- cmd.showMessage(QObject::tr("Documentation successfully unregistered."),
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Documentation successfully unregistered."),
false);
return true;
}
@@ -328,7 +333,8 @@ int main(int argc, char *argv[])
if (collectionFileGiven) {
collection.reset(new QHelpEngineCore(collectionFile));
if (!collection->setupData()) {
- cmd.showMessage(QObject::tr("Error reading collection file '%1': %2.").
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error reading collection file '%1': %2.").
arg(collectionFile).arg(collection->error()), true);
return EXIT_FAILURE;
}
@@ -338,13 +344,15 @@ int main(int argc, char *argv[])
: MainWindow::defaultHelpCollectionFileName();
if (collectionFileGiven && !QFileInfo(cachedCollectionFile).exists()
&& !collection->copyCollectionFile(cachedCollectionFile)) {
- cmd.showMessage(QObject::tr("Error creating collection file '%1': %2.").
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error creating collection file '%1': %2.").
arg(cachedCollectionFile).arg(collection->error()), true);
return EXIT_FAILURE;
}
QHelpEngineCore cachedCollection(cachedCollectionFile);
if (!cachedCollection.setupData()) {
- cmd.showMessage(QObject::tr("Error reading collection file '%1': %2").
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Error reading collection file '%1': %2").
arg(cachedCollectionFile).
arg(cachedCollection.error()), true);
return EXIT_FAILURE;
@@ -365,7 +373,8 @@ int main(int argc, char *argv[])
const QString &namespaceName =
QHelpEngineCore::namespaceName(cmd.helpFile());
if (cmd.registerRequest() == CmdLineParser::Register) {
- if (collectionFileGiven && !registerDocumentation(*collection, cmd, true))
+ if (collectionFileGiven
+ && !registerDocumentation(*collection, cmd, true))
return EXIT_FAILURE;
if (!cachedDocs.contains(namespaceName)
&& !registerDocumentation(cachedCollection, cmd, !collectionFileGiven))
@@ -395,7 +404,8 @@ int main(int argc, char *argv[])
}
if (!QSqlDatabase::isDriverAvailable(QLatin1String("QSQLITE"))) {
- cmd.showMessage(QObject::tr("Cannot load sqlite database driver!"),
+ cmd.showMessage(QCoreApplication::translate("Assistant",
+ "Cannot load sqlite database driver!"),
true);
return EXIT_FAILURE;
}
diff --git a/tools/assistant/tools/qcollectiongenerator/main.cpp b/tools/assistant/tools/qcollectiongenerator/main.cpp
index f75d891..7fcb4e1 100644
--- a/tools/assistant/tools/qcollectiongenerator/main.cpp
+++ b/tools/assistant/tools/qcollectiongenerator/main.cpp
@@ -45,6 +45,7 @@
#include
#include
+#include
#include
#include
#include
@@ -122,7 +123,8 @@ private:
void CollectionConfigReader::raiseErrorWithLine()
{
- raiseError(QObject::tr("Unknown token at line %1.")
+ raiseError(QCoreApplication::translate("QCollectionGenerator",
+ "Unknown token at line %1.")
.arg(lineNumber()));
}
@@ -142,8 +144,10 @@ void CollectionConfigReader::readData(const QByteArray &contents)
&& attributes().value(QLatin1String("version")) == QLatin1String("1.0"))
readConfig();
else
- raiseError(QObject::tr("Unknown token at line %1. Expected \"QtHelpCollectionProject\"!")
- .arg(lineNumber()));
+ raiseError(QCoreApplication::translate("QCollectionGenerator",
+ "Unknown token at line %1. "
+ "Expected \"QtHelpCollectionProject\"!")
+ .arg(lineNumber()));
}
}
}
@@ -353,7 +357,8 @@ int main(int argc, char *argv[])
QFileInfo fi(QString::fromLocal8Bit(argv[i]));
collectionFile = fi.absoluteFilePath();
} else {
- error = QObject::tr("Missing output file name!");
+ error = QCoreApplication::translate("QCollectionGenerator",
+ "Missing output file name!");
}
} else if (arg == QLatin1String("-h")) {
showHelp = true;
@@ -367,14 +372,16 @@ int main(int argc, char *argv[])
}
if (showVersion) {
- fprintf(stdout, "Qt Collection Generator version 1.0 (Qt %s)\n", QT_VERSION_STR);
+ fprintf(stdout, "Qt Collection Generator version 1.0 (Qt %s)\n",
+ QT_VERSION_STR);
return 0;
}
if (configFile.isEmpty() && !showHelp)
- error = QObject::tr("Missing collection config file!");
+ error = QCoreApplication::translate("QCollectionGenerator",
+ "Missing collection config file!");
- QString help = QObject::tr("\nUsage:\n\n"
+ QString help = QCoreApplication::translate("QCollectionGenerator", "\nUsage:\n\n"
"qcollectiongenerator [options]\n\n"
" -o Generates a collection file\n"
" called . If\n"
diff --git a/tools/assistant/tools/qhelpgenerator/main.cpp b/tools/assistant/tools/qhelpgenerator/main.cpp
index 00a0a3d..a309f42 100644
--- a/tools/assistant/tools/qhelpgenerator/main.cpp
+++ b/tools/assistant/tools/qhelpgenerator/main.cpp
@@ -67,7 +67,8 @@ int main(int argc, char *argv[])
QFileInfo fi(QString::fromLocal8Bit(argv[i]));
compressedFile = fi.absoluteFilePath();
} else {
- error = QObject::tr("Missing output file name!");
+ error = QCoreApplication::translate("QHelpGenerator",
+ "Missing output file name!");
}
} else if (arg == QLatin1String("-v")) {
showVersion = true;
@@ -83,14 +84,16 @@ int main(int argc, char *argv[])
}
if (showVersion) {
- fprintf(stdout, "Qt Help Generator version 1.0 (Qt %s)\n", QT_VERSION_STR);
+ fprintf(stdout, "Qt Help Generator version 1.0 (Qt %s)\n",
+ QT_VERSION_STR);
return 0;
}
if (projectFile.isEmpty() && !showHelp)
- error = QObject::tr("Missing Qt help project file!");
+ error = QCoreApplication::translate("QHelpGenerator",
+ "Missing Qt help project file!");
- QString help = QObject::tr("\nUsage:\n\n"
+ QString help = QCoreApplication::translate("QHelpGenerator", "\nUsage:\n\n"
"qhelpgenerator [options]\n\n"
" -o Generates a Qt compressed help\n"
" file called .\n"
--
cgit v0.12
From db5f673ccf5a56772ff83cad52beab7b14cd9520 Mon Sep 17 00:00:00 2001
From: Thomas Zander
Date: Tue, 2 Feb 2010 12:46:52 +0100
Subject: fix whitespace
---
configure | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/configure b/configure
index dc23392..9a3ee32 100755
--- a/configure
+++ b/configure
@@ -3369,10 +3369,10 @@ Configure options:
-debug-and-release . Compile and link two versions of Qt, with and without
debugging turned on (Mac only).
- -developer-build.... Compile and link Qt with Qt developer options (including auto-tests exporting)
+ -developer-build ... Compile and link Qt with Qt developer options (including auto-tests exporting)
- -opensource......... Compile and link the Open-Source Edition of Qt.
- -commercial......... Compile and link the Commercial Edition of Qt.
+ -opensource ........ Compile and link the Open-Source Edition of Qt.
+ -commercial ........ Compile and link the Commercial Edition of Qt.
* -shared ............ Create and use shared Qt libraries.
@@ -3765,7 +3765,7 @@ Qt/X11 only:
Requires fontconfig/fontconfig.h, libfontconfig,
freetype.h and libfreetype.
- $XIN -no-xinput.......... Do not compile Xinput support.
+ $XIN -no-xinput ......... Do not compile Xinput support.
$XIY -xinput ............ Compile Xinput support. This also enabled tablet support
which requires IRIX with wacom.h and libXi or
XFree86 with X11/extensions/XInput.h and libXi.
--
cgit v0.12
From 88c4000c21be7af37bc490a2edd9d1f481b3a862 Mon Sep 17 00:00:00 2001
From: Kim Motoyoshi Kalland
Date: Tue, 2 Feb 2010 13:20:10 +0100
Subject: Fixed compilation of the GL2 engine for OpenGL ES 2.
glColor4f is not defined in OpenGL ES 2.
Reviewed-by: Trond
---
src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 406112a..07f3159 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -561,7 +561,9 @@ void QGL2PaintEngineExPrivate::resetGLState()
glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR);
glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR);
glDisableVertexAttribArray(QT_OPACITY_ATTR);
+#ifndef QT_OPENGL_ES_2
glColor4f(1.0f, 1.0f, 1.0f, 1.0f); // color may have been changed by glVertexAttrib()
+#endif
}
void QGL2PaintEngineEx::endNativePainting()
--
cgit v0.12
From 0a2daeed026eca14bafe8463c7d0e629fd196c59 Mon Sep 17 00:00:00 2001
From: ck
Date: Tue, 2 Feb 2010 14:07:38 +0100
Subject: Assistant: Treat "unfiltered" filter in a apecial way.
- Don't put the translated string into the help engine.
- Don't let it be edited by users.
Reviewed-by: kh1
---
.../tools/assistant/helpenginewrapper.cpp | 39 ++++++++++++----------
.../assistant/tools/assistant/helpenginewrapper.h | 9 ++---
tools/assistant/tools/assistant/mainwindow.cpp | 7 ----
.../tools/assistant/preferencesdialog.cpp | 4 ++-
4 files changed, 30 insertions(+), 29 deletions(-)
diff --git a/tools/assistant/tools/assistant/helpenginewrapper.cpp b/tools/assistant/tools/assistant/helpenginewrapper.cpp
index 9785710..ddc056a 100644
--- a/tools/assistant/tools/assistant/helpenginewrapper.cpp
+++ b/tools/assistant/tools/assistant/helpenginewrapper.cpp
@@ -57,6 +57,7 @@
QT_BEGIN_NAMESPACE
namespace {
+ const QString Unfiltered;
const QString AppFontKey(QLatin1String("appFont"));
const QString AppWritingSystemKey(QLatin1String("appWritingSystem"));
const QString BookmarksKey(QLatin1String("Bookmarks"));
@@ -67,7 +68,6 @@ namespace {
const QString MainWindowGeometryKey(QLatin1String("MainWindowGeometry"));
const QString SearchWasAttachedKey(QLatin1String("SearchWasAttached"));
const QString StartOptionKey(QLatin1String("StartOption"));
- const QString UnfilteredInsertedKey(QLatin1String("UnfilteredFilterInserted"));
const QString UseAppFontKey(QLatin1String("useAppFont"));
const QString UseBrowserFontKey(QLatin1String("useBrowserFont"));
const QString VersionKey(QString(QLatin1String("qtVersion%1$$$%2")).
@@ -114,6 +114,8 @@ private:
QMap m_recentQchUpdates;
};
+const QString HelpEngineWrapper::TrUnfiltered = tr("Unfiltered");
+
HelpEngineWrapper *HelpEngineWrapper::helpEngineWrapper = 0;
HelpEngineWrapper &HelpEngineWrapper::instance(const QString &collectionFile)
@@ -144,7 +146,7 @@ HelpEngineWrapper::HelpEngineWrapper(const QString &collectionFile)
connect(d, SIGNAL(documentationUpdated(QString)),
this, SIGNAL(documentationUpdated(QString)));
connect(d->m_helpEngine, SIGNAL(currentFilterChanged(QString)),
- this, SIGNAL(currentFilterChanged(QString)));
+ this, SLOT(handleCurrentFilterChanged(QString)));
connect(d->m_helpEngine, SIGNAL(setupFinished()),
this, SIGNAL(setupFinished()));
}
@@ -242,19 +244,25 @@ bool HelpEngineWrapper::removeCustomFilter(const QString &filterName)
void HelpEngineWrapper::setCurrentFilter(const QString ¤tFilter)
{
TRACE_OBJ
- d->m_helpEngine->setCurrentFilter(currentFilter);
+ const QString &filter
+ = currentFilter == TrUnfiltered ? Unfiltered : currentFilter;
+ d->m_helpEngine->setCurrentFilter(filter);
}
const QString HelpEngineWrapper::currentFilter() const
{
TRACE_OBJ
- return d->m_helpEngine->currentFilter();
+ const QString &filter = d->m_helpEngine->currentFilter();
+ return filter == Unfiltered ? TrUnfiltered : filter;
}
const QStringList HelpEngineWrapper::customFilters() const
{
TRACE_OBJ
- return d->m_helpEngine->customFilters();
+ QStringList filters = d->m_helpEngine->customFilters();
+ filters.removeOne(Unfiltered);
+ filters.prepend(TrUnfiltered);
+ return filters;
}
QUrl HelpEngineWrapper::findFile(const QUrl &url) const
@@ -293,18 +301,6 @@ QString HelpEngineWrapper::error() const
return d->m_helpEngine->error();
}
-bool HelpEngineWrapper::unfilteredInserted() const
-{
- TRACE_OBJ
- return d->m_helpEngine->customValue(UnfilteredInsertedKey).toInt() == 1;
-}
-
-void HelpEngineWrapper::setUnfilteredInserted()
-{
- TRACE_OBJ
- d->m_helpEngine->setCustomValue(UnfilteredInsertedKey, 1);
-}
-
const QStringList HelpEngineWrapper::qtDocInfo(const QString &component) const
{
TRACE_OBJ
@@ -679,6 +675,13 @@ void HelpEngineWrapper::setBrowserWritingSystem(QFontDatabase::WritingSystem sys
d->m_helpEngine->setCustomValue(BrowserWritingSystemKey, system);
}
+void HelpEngineWrapper::handleCurrentFilterChanged(const QString &filter)
+{
+ const QString &filterToReport
+ = filter == Unfiltered ? TrUnfiltered : filter;
+ emit currentFilterChanged(filterToReport);
+}
+
TimeoutForwarder::TimeoutForwarder(const QString &fileName)
: m_fileName(fileName)
@@ -698,6 +701,8 @@ HelpEngineWrapperPrivate::HelpEngineWrapperPrivate(const QString &collectionFile
m_qchWatcher(new QFileSystemWatcher(this))
{
TRACE_OBJ
+ if (!m_helpEngine->customFilters().contains(Unfiltered))
+ m_helpEngine->addCustomFilter(Unfiltered, QStringList());
initFileSystemWatchers();
}
diff --git a/tools/assistant/tools/assistant/helpenginewrapper.h b/tools/assistant/tools/assistant/helpenginewrapper.h
index ea7b762..a30fab8 100644
--- a/tools/assistant/tools/assistant/helpenginewrapper.h
+++ b/tools/assistant/tools/assistant/helpenginewrapper.h
@@ -101,10 +101,6 @@ public:
const QStringList filterAttributes(const QString &filterName) const;
QString error() const;
- // Access to a collection's custom values.
- bool unfilteredInserted() const;
- void setUnfilteredInserted();
-
const QStringList qtDocInfo(const QString &component) const;
void setQtDocInfo(const QString &component, const QStringList &doc);
@@ -185,6 +181,8 @@ public:
QFontDatabase::WritingSystem browserWritingSystem() const;
void setBrowserWritingSystem(QFontDatabase::WritingSystem system);
+ static const QString TrUnfiltered;
+
signals:
// For asynchronous doc updates triggered by external actions.
@@ -195,6 +193,9 @@ signals:
void currentFilterChanged(const QString ¤tFilter);
void setupFinished();
+private slots:
+ void handleCurrentFilterChanged(const QString &filter);
+
private:
HelpEngineWrapper(const QString &collectionFile);
~HelpEngineWrapper();
diff --git a/tools/assistant/tools/assistant/mainwindow.cpp b/tools/assistant/tools/assistant/mainwindow.cpp
index ac33fc5..cfd0fee 100644
--- a/tools/assistant/tools/assistant/mainwindow.cpp
+++ b/tools/assistant/tools/assistant/mainwindow.cpp
@@ -315,13 +315,6 @@ bool MainWindow::initHelpDB()
needsSetup = true;
}
- if (!helpEngineWrapper.unfilteredInserted()) {
- helpEngineWrapper.addCustomFilter(tr("Unfiltered"), QStringList());
- helpEngineWrapper.setUnfilteredInserted();
- helpEngineWrapper.setCurrentFilter(tr("Unfiltered"));
- needsSetup = true;
- }
-
if (needsSetup)
helpEngineWrapper.setupData();
return true;
diff --git a/tools/assistant/tools/assistant/preferencesdialog.cpp b/tools/assistant/tools/assistant/preferencesdialog.cpp
index fb41590..f0ef054 100644
--- a/tools/assistant/tools/assistant/preferencesdialog.cpp
+++ b/tools/assistant/tools/assistant/preferencesdialog.cpp
@@ -160,8 +160,10 @@ void PreferencesDialog::updateFilterPage()
m_ui.attributeWidget->clear();
m_filterMapBackup.clear();
- const QStringList filters = helpEngine.customFilters();
+ const QStringList &filters = helpEngine.customFilters();
foreach (const QString &filter, filters) {
+ if (filter == HelpEngineWrapper::TrUnfiltered)
+ continue;
QStringList atts = helpEngine.filterAttributes(filter);
m_filterMapBackup.insert(filter, atts);
if (!m_filterMap.contains(filter))
--
cgit v0.12
From 94b3918fb52858064811c4993dac6392d0043b24 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?=
Date: Tue, 2 Feb 2010 15:05:54 +0100
Subject: Implemented QGifHandler::imageCount().
Task-number: QTBUG-7514
Reviewed-by: Kim
---
src/plugins/imageformats/gif/qgifhandler.cpp | 235 ++++++++++++++++++++++++++-
src/plugins/imageformats/gif/qgifhandler.h | 1 +
tests/auto/qimagereader/tst_qimagereader.cpp | 6 +
3 files changed, 241 insertions(+), 1 deletion(-)
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index 6f049be..6cd7841 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -72,6 +72,7 @@ public:
int decode(QImage *image, const uchar* buffer, int length,
int *nextFrameDelay, int *loopCount, QSize *nextSize);
+ static int imageCount(QIODevice *device);
bool newFrame;
bool partialNewFrame;
@@ -645,6 +646,234 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
return initial-length;
}
+/*!
+ Returns the number of images that can be read from \a device.
+*/
+
+int QGIFFormat::imageCount(QIODevice *device)
+{
+ if (!device)
+ return 0;
+
+ qint64 oldPos = device->pos();
+ if (!device->seek(0))
+ return 0;
+
+ int colorCount = 0;
+ int localColorCount = 0;
+ int globalColorCount = 0;
+ int colorReadCount = 0;
+ bool localColormap = false;
+ bool globalColormap = false;
+ int count = 0;
+ int blockSize = 0;
+ bool done = false;
+ uchar hold[16];
+ int imageCount = 0;
+ State state = Header;
+
+ const int readBufferSize = 40960; // 40k read buffer
+ QByteArray readBuffer(device->read(readBufferSize));
+
+ if (readBuffer.isEmpty())
+ return 0;
+
+ // this is a specialized version of the state machine from decode(),
+ // which doesn't do any image decoding or mallocing, and has an
+ // optimized way of skipping SkipBlocks, ImageDataBlocks and
+ // Global/LocalColorMaps.
+
+ while (!readBuffer.isEmpty()) {
+ int length = readBuffer.size();
+ const uchar *buffer = (const uchar *) readBuffer.constData();
+ while (!done && length) {
+ length--;
+ uchar ch = *buffer++;
+ switch (state) {
+ case Header:
+ hold[count++] = ch;
+ if (count == 6) {
+ state = LogicalScreenDescriptor;
+ count = 0;
+ }
+ break;
+ case LogicalScreenDescriptor:
+ hold[count++] = ch;
+ if (count == 7) {
+ globalColormap = !!(hold[4] & 0x80);
+ globalColorCount = 2 << (hold[4] & 0x7);
+ count = 0;
+ colorCount = globalColorCount;
+ if (globalColormap) {
+ int colorTableSize = 3 * globalColorCount;
+ if (length >= colorTableSize) {
+ // skip the global color table in one go
+ length -= colorTableSize;
+ buffer += colorTableSize;
+ state = Introducer;
+ } else {
+ colorReadCount = 0;
+ state = GlobalColorMap;
+ }
+ } else {
+ state=Introducer;
+ }
+ }
+ break;
+ case GlobalColorMap:
+ case LocalColorMap:
+ hold[count++] = ch;
+ if (count == 3) {
+ if (++colorReadCount >= colorCount) {
+ if (state == LocalColorMap)
+ state = TableImageLZWSize;
+ else
+ state = Introducer;
+ }
+ count = 0;
+ }
+ break;
+ case Introducer:
+ hold[count++] = ch;
+ switch (ch) {
+ case 0x2c:
+ state = ImageDescriptor;
+ break;
+ case 0x21:
+ state = ExtensionLabel;
+ break;
+ case 0x3b:
+ state = Done;
+ break;
+ default:
+ done = true;
+ state = Error;
+ }
+ break;
+ case ImageDescriptor:
+ hold[count++] = ch;
+ if (count == 10) {
+ localColormap = !!(hold[9] & 0x80);
+ localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
+ if (localColorCount)
+ colorCount = localColorCount;
+ else
+ colorCount = globalColorCount;
+ imageCount++;
+
+ count = 0;
+ if (localColormap) {
+ int colorTableSize = 3 * localColorCount;
+ if (length >= colorTableSize) {
+ // skip the local color table in one go
+ length -= colorTableSize;
+ buffer += colorTableSize;
+ state = TableImageLZWSize;
+ } else {
+ colorReadCount = 0;
+ state = LocalColorMap;
+ }
+ } else {
+ state = TableImageLZWSize;
+ }
+ }
+ break;
+ case TableImageLZWSize:
+ if (ch > max_lzw_bits)
+ state = Error;
+ else
+ state = ImageDataBlockSize;
+ count = 0;
+ break;
+ case ImageDataBlockSize:
+ blockSize = ch;
+ if (blockSize) {
+ if (length >= blockSize) {
+ // we can skip the block in one go
+ length -= blockSize;
+ buffer += blockSize;
+ count = 0;
+ } else {
+ state = ImageDataBlock;
+ }
+ } else {
+ state = Introducer;
+ }
+ break;
+ case ImageDataBlock:
+ ++count;
+ if (count == blockSize) {
+ count = 0;
+ state = ImageDataBlockSize;
+ }
+ break;
+ case ExtensionLabel:
+ switch (ch) {
+ case 0xf9:
+ state = GraphicControlExtension;
+ break;
+ case 0xff:
+ state = ApplicationExtension;
+ break;
+ default:
+ state = SkipBlockSize;
+ }
+ count = 0;
+ break;
+ case ApplicationExtension:
+ if (count < 11)
+ hold[count] = ch;
+ ++count;
+ if (count == hold[0] + 1) {
+ state = SkipBlockSize;
+ count = 0;
+ }
+ break;
+ case GraphicControlExtension:
+ if (count < 5)
+ hold[count] = ch;
+ ++count;
+ if (count == hold[0] + 1) {
+ count = 0;
+ state = SkipBlockSize;
+ }
+ break;
+ case NetscapeExtensionBlockSize: // fallthrough
+ case SkipBlockSize:
+ blockSize = ch;
+ count = 0;
+ if (blockSize) {
+ if (length >= blockSize) {
+ // we can skip the block in one go
+ length -= blockSize;
+ buffer += blockSize;
+ } else {
+ state = SkipBlock;
+ }
+ } else {
+ state = Introducer;
+ }
+ break;
+ case NetscapeExtensionBlock: // fallthrough
+ case SkipBlock:
+ ++count;
+ if (count == blockSize)
+ state = SkipBlockSize;
+ break;
+ case Done:
+ done = true;
+ break;
+ case Error:
+ device->seek(oldPos);
+ return 0;
+ }
+ }
+ readBuffer = device->read(readBufferSize);
+ }
+ device->seek(oldPos);
+ return imageCount;
+}
+
void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb color)
{
if (w>0) {
@@ -766,6 +995,7 @@ QGifHandler::QGifHandler()
loopCnt = 0;
frameNumber = -1;
nextSize = QSize();
+ imageCnt = -1;
}
QGifHandler::~QGifHandler()
@@ -883,7 +1113,10 @@ int QGifHandler::nextImageDelay() const
int QGifHandler::imageCount() const
{
- return 0; // Don't know
+ if (imageCnt != -1)
+ return imageCnt;
+ imageCnt = QGIFFormat::imageCount(device());
+ return imageCnt;
}
int QGifHandler::loopCount() const
diff --git a/src/plugins/imageformats/gif/qgifhandler.h b/src/plugins/imageformats/gif/qgifhandler.h
index a6e520f..830cd38 100644
--- a/src/plugins/imageformats/gif/qgifhandler.h
+++ b/src/plugins/imageformats/gif/qgifhandler.h
@@ -88,6 +88,7 @@ private:
mutable int loopCnt;
int frameNumber;
mutable QSize nextSize;
+ mutable int imageCnt;
};
QT_END_NAMESPACE
diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp
index b1a5d26..debc090 100644
--- a/tests/auto/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/qimagereader/tst_qimagereader.cpp
@@ -765,6 +765,8 @@ void tst_QImageReader::gifImageCount()
QVERIFY(io.canRead());
QImage greenFrame = io.read();
+ QVERIFY(io.imageCount() == 4);
+
QVERIFY(io.canRead());
QImage blueFrame = io.read();
@@ -876,6 +878,10 @@ void tst_QImageReader::gifImageCount()
QCOMPARE(blueFrame.size(), QSize(64,64));
QVERIFY(emptyFrame.isNull());
}
+ {
+ QImageReader io(":images/trolltech.gif");
+ QVERIFY(io.imageCount() == 34);
+ }
}
#endif
--
cgit v0.12
From fc92419c2058b8c3af8fc1c723e9d957118bcb8f Mon Sep 17 00:00:00 2001
From: Robert Loehning
Date: Tue, 2 Feb 2010 15:44:28 +0100
Subject: Expanded tst_QFileSystemModel::rootPath() to check directories ending
in "." or ".."
Reviewed-by: Jan-Arve
---
tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp
index 287f472..9f67a5e 100644
--- a/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp
+++ b/tests/auto/qfilesystemmodel/tst_qfilesystemmodel.cpp
@@ -236,6 +236,26 @@ void tst_QFileSystemModel::rootPath()
QCOMPARE(model->rootPath(), QString(QDir::homePath()));
QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? 0 : 1);
QCOMPARE(model->rootDirectory().absolutePath(), QDir::homePath());
+
+ model->setRootPath(QDir::rootPath());
+ int oldCount = rootChanged.count();
+ oldRootPath = model->rootPath();
+ root = model->setRootPath(QDir::homePath() + QLatin1String("/."));
+ QTRY_VERIFY(model->rowCount(root) >= 0);
+ QCOMPARE(model->rootPath(), QDir::homePath());
+ QCOMPARE(rootChanged.count(), oldRootPath == model->rootPath() ? oldCount : oldCount + 1);
+ QCOMPARE(model->rootDirectory().absolutePath(), QDir::homePath());
+
+ QDir newdir = QDir::home();
+ if (newdir.cdUp()) {
+ oldCount = rootChanged.count();
+ oldRootPath = model->rootPath();
+ root = model->setRootPath(QDir::homePath() + QLatin1String("/.."));
+ QTRY_VERIFY(model->rowCount(root) >= 0);
+ QCOMPARE(model->rootPath(), newdir.path());
+ QCOMPARE(rootChanged.count(), oldCount + 1);
+ QCOMPARE(model->rootDirectory().absolutePath(), newdir.path());
+ }
}
void tst_QFileSystemModel::naturalCompare_data()
--
cgit v0.12
From 3d2dbeb65089efaff4b92b7d13c13c1a234f71b0 Mon Sep 17 00:00:00 2001
From: Thierry Bastian
Date: Tue, 2 Feb 2010 16:39:40 +0100
Subject: Avoids a possible crash when saving the state of a main window
The crash could appear when saving the state of the main window in
response to the visibilityChanged of the dock widgets.
Task-number: QTBUG-7838
Reviewed-by: ogoffart
---
src/gui/widgets/qmainwindowlayout.cpp | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/gui/widgets/qmainwindowlayout.cpp b/src/gui/widgets/qmainwindowlayout.cpp
index d1e7285..fc75c92 100644
--- a/src/gui/widgets/qmainwindowlayout.cpp
+++ b/src/gui/widgets/qmainwindowlayout.cpp
@@ -1627,6 +1627,13 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
tb->d_func()->plug(currentGapRect);
#endif
+ savedState.clear();
+ currentGapPos.clear();
+ pluggingWidget = 0;
+ //applying the state will make sure that the currentGap is updated correctly
+ //and all the geometries (especially the one from the central widget) is correct
+ layoutState.apply(false);
+
#ifndef QT_NO_DOCKWIDGET
#ifndef QT_NO_TABBAR
if (qobject_cast(widget) != 0) {
@@ -1637,13 +1644,6 @@ void QMainWindowLayout::animationFinished(QWidget *widget)
}
#endif
#endif
-
- savedState.clear();
- currentGapPos.clear();
- pluggingWidget = 0;
- //applying the state will make sure that the currentGap is updated correctly
- //and all the geometries (especially the one from the central widget) is correct
- layoutState.apply(false);
}
if (!widgetAnimator.animating()) {
--
cgit v0.12
From 85578c6c37d9e4eb0da888937b20ba93a26d8805 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?=
Date: Tue, 2 Feb 2010 17:39:19 +0100
Subject: 4.6.2 changes
---
dist/changes-4.6.2 | 23 ++++++++++++++++++-----
1 file changed, 18 insertions(+), 5 deletions(-)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index d35f945..2a884fe 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -46,8 +46,14 @@ QtCore
QtGui
-----
- - foo
- * bar
+ - QBmpHandler
+ * [QTBUG-7530] Fixed an infinite loop that could occur when reading invalid BMP images.
+
+ - QImage
+ * [QTBUG-7231] Avoid an unnecessary copy in QImage::scaled().
+
+ - QPDFEngine
+ * [QTBUG-7249] Fixed the encoding of the Tile and Creator tags in the PDF engine.
QtDBus
------
@@ -64,8 +70,14 @@ QtNetwork
QtOpenGL
--------
- - foo
- * bar
+ - QGLWidget
+ * [QTBUG-7213] Fixed QGLWidget::renderPixmap() on Windows.
+
+ - QGLPixelBuffer
+ * [QTBUG-7476] Fixed a crash under X11 when drawing QPixmaps to QGLPixelBuffers.
+
+ - QGL2PaintEngineEx
+ * [QTBUG-7203] Reset the GL stencil mask, op and function in resetGLState().
QtScript
--------
@@ -121,7 +133,8 @@ Qt for Windows
Qt for Mac OS X
---------------
- -
+ - QPrintPreviewDialog
+ * [QTBUG-7481] Re-added the Close button in QPrintPreviewDialog for Mac/Carbon.
Qt for Embedded Linux
---------------------
--
cgit v0.12
From d5d882280fe9577c580d41f1efb5abbd5d57f6dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?=
Date: Tue, 2 Feb 2010 17:57:19 +0100
Subject: Fixed a failure in tst_qgl.
The assert wrong, it may be that the texture isn't removed from the
cache if it doesn't have the MemoryManaged bind option set.
Reviewed-by: Samuel
---
src/opengl/qgl.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index dd977cb..fce9fdb 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -1683,7 +1683,6 @@ void QGLTextureCache::cleanupBeforePixmapDestruction(QPixmapData* pmd)
{
// Remove any bound textures first:
cleanupTextures(pmd);
- Q_ASSERT(instance()->getTexture(pmd->cacheKey()) == 0);
#if defined(Q_WS_X11)
if (pmd->classId() == QPixmapData::X11Class) {
--
cgit v0.12
From 8acb069bd3a68afc36566503ca7f9d0fc808e170 Mon Sep 17 00:00:00 2001
From: David Boddie
Date: Tue, 2 Feb 2010 20:42:44 +0100
Subject: Doc: Synchronize configuration files for easier maintenance.
Reviewed-by: Trust Me
---
tools/qdoc3/test/qt-build-docs.qdocconf | 7 ++++---
tools/qdoc3/test/qt.qdocconf | 2 +-
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/tools/qdoc3/test/qt-build-docs.qdocconf b/tools/qdoc3/test/qt-build-docs.qdocconf
index e8595f6..dae5ca1 100644
--- a/tools/qdoc3/test/qt-build-docs.qdocconf
+++ b/tools/qdoc3/test/qt-build-docs.qdocconf
@@ -8,9 +8,9 @@ project = Qt
description = Qt Reference Documentation
url = http://qt.nokia.com/doc/4.7
-edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript QtScriptTools QtSql QtSvg \
- QtWebKit QtXml QtXmlPatterns Qt3Support QtHelp \
- QtDesigner QtAssistant QAxContainer Phonon \
+edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript \
+ QtScriptTools QtSql QtSvg QtWebKit QtXml QtXmlPatterns \
+ Qt3Support QtHelp QtDesigner QtAssistant QAxContainer Phonon \
QAxServer QtUiTools QtTest QtDBus
edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest
@@ -94,6 +94,7 @@ excludedirs = $QT_SOURCE_TREE/src/3rdparty/clucene \
$QT_SOURCE_TREE/src/3rdparty/phonon/gstreamer \
$QT_SOURCE_TREE/src/3rdparty/phonon/ds9 \
$QT_SOURCE_TREE/src/3rdparty/phonon/qt7 \
+ $QT_SOURCE_TREE/src/3rdparty/phonon/mmf \
$QT_SOURCE_TREE/src/3rdparty/phonon/waveout
sources.fileextensions = "*.cpp *.qdoc *.mm"
diff --git a/tools/qdoc3/test/qt.qdocconf b/tools/qdoc3/test/qt.qdocconf
index a066021..4dfabcf 100644
--- a/tools/qdoc3/test/qt.qdocconf
+++ b/tools/qdoc3/test/qt.qdocconf
@@ -12,7 +12,7 @@ url = http://qt.nokia.com/doc/4.7
edition.Desktop.modules = QtCore QtDBus QtGui QtNetwork QtOpenGL QtScript \
QtScriptTools QtSql QtSvg QtWebKit QtXml QtXmlPatterns \
- Qt3Support QtHelp QtDesigner QAxContainer Phonon \
+ Qt3Support QtHelp QtDesigner QtAssistant QAxContainer Phonon \
QAxServer QtUiTools QtTest QtDBus
edition.DesktopLight.modules = QtCore QtDBus QtGui Qt3SupportLight QtTest
edition.DesktopLight.groups = -graphicsview-api
--
cgit v0.12
From 7a4d0130441bae27a302e694828ec71ade9e6005 Mon Sep 17 00:00:00 2001
From: David Boddie
Date: Tue, 2 Feb 2010 20:44:08 +0100
Subject: qdoc: Added support for different source and output character
encodings.
Previously, qdoc assumed Latin1 (ISO-8859-1) for source code and other
documentation, and wrote out XHTML with the same encoding. This change
adds additional configuration options (sourceencoding, outputencoding,
naturallanguage) that enable translated documentation in non-Latin1
encodings to be built with qdoc.
To be reviewed before merge into the master branch.
Reviewed-by: Trust Me
---
tools/qdoc3/config.h | 3 +
tools/qdoc3/cppcodeparser.cpp | 12 ++--
tools/qdoc3/htmlgenerator.cpp | 137 ++++++++++++++++++++++------------------
tools/qdoc3/htmlgenerator.h | 3 +-
tools/qdoc3/pagegenerator.cpp | 2 +-
tools/qdoc3/pagegenerator.h | 6 ++
tools/qdoc3/qsakernelparser.cpp | 6 +-
tools/qdoc3/qscodeparser.cpp | 6 +-
tools/qdoc3/tokenizer.cpp | 25 ++++++--
tools/qdoc3/tokenizer.h | 9 ++-
10 files changed, 125 insertions(+), 84 deletions(-)
diff --git a/tools/qdoc3/config.h b/tools/qdoc3/config.h
index 5e7e6f1..6f23469 100644
--- a/tools/qdoc3/config.h
+++ b/tools/qdoc3/config.h
@@ -140,8 +140,10 @@ class Config
#define CONFIG_INDEXES "indexes"
#define CONFIG_LANGUAGE "language"
#define CONFIG_MACRO "macro"
+#define CONFIG_NATURALLANGUAGE "naturallanguage"
#define CONFIG_OBSOLETELINKS "obsoletelinks"
#define CONFIG_OUTPUTDIR "outputdir"
+#define CONFIG_OUTPUTENCODING "outputencoding"
#define CONFIG_OUTPUTLANGUAGE "outputlanguage"
#define CONFIG_OUTPUTFORMATS "outputformats"
#define CONFIG_PROJECT "project"
@@ -150,6 +152,7 @@ class Config
#define CONFIG_SLOW "slow"
#define CONFIG_SHOWINTERNAL "showinternal"
#define CONFIG_SOURCEDIRS "sourcedirs"
+#define CONFIG_SOURCEENCODING "sourceencoding"
#define CONFIG_SOURCES "sources"
#define CONFIG_SPURIOUS "spurious"
#define CONFIG_STYLESHEETS "stylesheets"
diff --git a/tools/qdoc3/cppcodeparser.cpp b/tools/qdoc3/cppcodeparser.cpp
index 9b6a516..129fa7d 100644
--- a/tools/qdoc3/cppcodeparser.cpp
+++ b/tools/qdoc3/cppcodeparser.cpp
@@ -280,8 +280,8 @@ void CppCodeParser::parseHeaderFile(const Location& location,
const QString& filePath,
Tree *tree)
{
- FILE *in = fopen(QFile::encodeName(filePath), "r");
- if (!in) {
+ QFile in(filePath);
+ if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Cannot open C++ header file '%1'").arg(filePath));
return;
}
@@ -294,7 +294,7 @@ void CppCodeParser::parseHeaderFile(const Location& location,
matchDeclList(tree->root());
if (!fileTokenizer.version().isEmpty())
tree->setVersion(fileTokenizer.version());
- fclose(in);
+ in.close();
if (fileLocation.fileName() == "qiterator.h")
parseQiteratorDotH(location, filePath);
@@ -311,8 +311,8 @@ void CppCodeParser::parseSourceFile(const Location& location,
const QString& filePath,
Tree *tree)
{
- FILE *in = fopen(QFile::encodeName(filePath), "r");
- if (!in) {
+ QFile in(filePath);
+ if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Cannot open C++ source file '%1' (%2)").arg(filePath).arg(strerror(errno)));
return;
}
@@ -324,7 +324,7 @@ void CppCodeParser::parseSourceFile(const Location& location,
readToken();
usedNamespaces.clear();
matchDocsAndStuff();
- fclose(in);
+ in.close();
}
/*!
diff --git a/tools/qdoc3/htmlgenerator.cpp b/tools/qdoc3/htmlgenerator.cpp
index a3cdae6..21b358a 100644
--- a/tools/qdoc3/htmlgenerator.cpp
+++ b/tools/qdoc3/htmlgenerator.cpp
@@ -54,6 +54,7 @@
#include
#include
#include
+#include
QT_BEGIN_NAMESPACE
@@ -266,6 +267,15 @@ void HtmlGenerator::initializeGenerator(const Config &config)
projectUrl = config.getString(CONFIG_URL);
+ outputEncoding = config.getString(CONFIG_OUTPUTENCODING);
+ if (outputEncoding.isEmpty())
+ outputEncoding = QLatin1String("ISO-8859-1");
+ outputCodec = QTextCodec::codecForName(outputEncoding.toLocal8Bit());
+
+ naturalLanguage = config.getString(CONFIG_NATURALLANGUAGE);
+ if (naturalLanguage.isEmpty())
+ naturalLanguage = QLatin1String("en");
+
QSet editionNames = config.subVars(CONFIG_EDITION);
QSet::ConstIterator edition = editionNames.begin();
while (edition != editionNames.end()) {
@@ -431,11 +441,11 @@ int HtmlGenerator::generateAtom(const Atom *atom,
endLink();
}
else {
- out() << protect(atom->string());
+ out() << protectEnc(atom->string());
}
}
else {
- out() << protect(atom->string());
+ out() << protectEnc(atom->string());
}
break;
case Atom::BaseName:
@@ -483,7 +493,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
case Atom::C:
out() << formattingLeftMap()[ATOM_FORMATTING_TELETYPE];
if (inLink) {
- out() << protect(plainCode(atom->string()));
+ out() << protectEnc(plainCode(atom->string()));
}
else {
out() << highlightedCode(atom->string(), marker, relative);
@@ -516,7 +526,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
// fallthrough
case Atom::CodeBad:
out() << ""
- << trimmedTrailing(protect(plainCode(indent(codeIndent,atom->string()))))
+ << trimmedTrailing(protectEnc(plainCode(indent(codeIndent,atom->string()))))
<< " \n";
break;
case Atom::FootnoteLeft:
@@ -768,7 +778,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
out() << " \n";
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
if (idx == Class)
generateCompactList(0, marker, ncmap.value(), QString("Q"));
else if (idx == MemberFunction) {
@@ -792,7 +802,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
<< linkForNode(pmap.key(), 0)
<< "\">";
QStringList pieces = fullName(pmap.key(), 0, marker).split("::");
- out() << protect(pieces.last());
+ out() << protectEnc(pieces.last());
out() << "" << ": \n";
generateSection(nlist, 0, marker, CodeMarker::Summary);
@@ -820,12 +830,12 @@ int HtmlGenerator::generateAtom(const Atom *atom,
out() << "";
if (fileName.isEmpty()) {
out() << "[Missing image "
- << protect(atom->string()) << "] ";
+ << protectEnc(atom->string()) << "]";
}
else {
- out() << " ";
helpProjectWriter->addExtraFile(fileName);
}
@@ -923,7 +933,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
// ### Trenton
out() << "
"
- << protect(plainCode(marker->markedUpEnumValue(atom->next()->string(),
+ << protectEnc(plainCode(marker->markedUpEnumValue(atom->next()->string(),
relative)))
<< " ";
@@ -936,7 +946,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
if (itemValue.isEmpty())
out() << "?";
else
- out() << "" << protect(itemValue) << " ";
+ out() << "" << protectEnc(itemValue) << " ";
skipAhead = 1;
}
@@ -1052,7 +1062,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
generateLink(atom, relative, marker);
}
else {
- out() << protect(atom->string());
+ out() << protectEnc(atom->string());
}
break;
case Atom::TableLeft:
@@ -1166,7 +1176,7 @@ int HtmlGenerator::generateAtom(const Atom *atom,
out() << "<Missing HTML> ";
break;
case Atom::UnknownCommand:
- out() << "\\" << protect(atom->string())
+ out() << "\\" << protectEnc(atom->string())
<< "
";
break;
#ifdef QDOC_QML
@@ -1295,7 +1305,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
out() << " \n";
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
generateSection(s->members, inner, marker, CodeMarker::Summary);
}
if (!s->reimpMembers.isEmpty()) {
@@ -1304,7 +1314,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
out() << " \n";
- out() << "" << protect(name) << " \n";
+ out() << "" << protectEnc(name) << " \n";
generateSection(s->reimpMembers, inner, marker, CodeMarker::Summary);
}
@@ -1343,7 +1353,7 @@ void HtmlGenerator::generateClassLikeNode(const InnerNode *inner,
s = sections.begin();
while (s != sections.end()) {
out() << " \n";
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
NodeList::ConstIterator m = (*s).members.begin();
while (m != (*s).members.end()) {
@@ -1513,7 +1523,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
s = sections.begin();
while (s != sections.end()) {
out() << " \n";
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
generateQmlSummary(*s,fake,marker);
++s;
}
@@ -1529,7 +1539,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
sections = marker->qmlSections(qml_cn,CodeMarker::Detailed);
s = sections.begin();
while (s != sections.end()) {
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
NodeList::ConstIterator m = (*s).members.begin();
while (m != (*s).members.end()) {
generateDetailedQmlMember(*m, fake, marker);
@@ -1549,7 +1559,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
s = sections.begin();
while (s != sections.end()) {
out() << " \n";
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
generateSectionList(*s, fake, marker, CodeMarker::Summary);
++s;
}
@@ -1578,7 +1588,7 @@ void HtmlGenerator::generateFakeNode(const FakeNode *fake, CodeMarker *marker)
s = sections.begin();
while (s != sections.end()) {
out() << " \n";
- out() << "" << protect((*s).name) << " \n";
+ out() << "" << protectEnc((*s).name) << " \n";
NodeList::ConstIterator m = (*s).members.begin();
while (m != (*s).members.end()) {
@@ -1624,11 +1634,11 @@ void HtmlGenerator::generateHeader(const QString& title,
CodeMarker *marker,
bool mainPage)
{
- out() << "\n";
+ out() << QString("\n").arg(outputEncoding);
out() << "\n"
- "\n";
+ " PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"DTD/xhtml1-strict.dtd\">\n";
+ out() << QString("\n").arg(naturalLanguage);
QString shortVersion;
if ((project != "Qtopia") && (project != "Qt Extended")) {
@@ -1648,7 +1658,9 @@ void HtmlGenerator::generateHeader(const QString& title,
}
out() << "\n"
- " " << shortVersion << protect(title) << " \n";
+ " " << shortVersion << protectEnc(title) << " \n";
+ out() << QString(" ").arg(outputEncoding);
+
if (!style.isEmpty())
out() << " \n";
@@ -1657,8 +1669,8 @@ void HtmlGenerator::generateHeader(const QString& title,
QMapIterator i(metaMap);
while (i.hasNext()) {
i.next();
- out() << " \n";
+ out() << " \n";
}
}
@@ -1682,9 +1694,9 @@ void HtmlGenerator::generateHeader(const QString& title,
navigationLinks += "[Previous: ";
if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
- navigationLinks += protect(anchorPair.second);
+ navigationLinks += protectEnc(anchorPair.second);
else
- navigationLinks += protect(linkPair.second);
+ navigationLinks += protectEnc(linkPair.second);
navigationLinks += " ]\n";
}
if (node->links().contains(Node::ContentsLink)) {
@@ -1700,9 +1712,9 @@ void HtmlGenerator::generateHeader(const QString& title,
navigationLinks += "[";
if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
- navigationLinks += protect(anchorPair.second);
+ navigationLinks += protectEnc(anchorPair.second);
else
- navigationLinks += protect(linkPair.second);
+ navigationLinks += protectEnc(linkPair.second);
navigationLinks += " ]\n";
}
if (node->links().contains(Node::NextLink)) {
@@ -1718,9 +1730,9 @@ void HtmlGenerator::generateHeader(const QString& title,
navigationLinks += "[Next: ";
if (linkPair.first == linkPair.second && !anchorPair.second.isEmpty())
- navigationLinks += protect(anchorPair.second);
+ navigationLinks += protectEnc(anchorPair.second);
else
- navigationLinks += protect(linkPair.second);
+ navigationLinks += protectEnc(linkPair.second);
navigationLinks += " ]\n";
}
if (node->links().contains(Node::IndexLink)) {
@@ -1771,7 +1783,7 @@ void HtmlGenerator::generateTitle(const QString& title,
const Node *relative,
CodeMarker *marker)
{
- out() << "" << protect(title);
+ out() << "" << protectEnc(title);
if (!subTitle.isEmpty()) {
out() << " ";
if (subTitleSize == SmallSubTitle)
@@ -2009,18 +2021,18 @@ QString HtmlGenerator::generateLowStatusMemberFile(const InnerNode *inner,
out() << "
\n";
for (i = 0; i < sections.size(); ++i) {
- out() << "" << protect(sections.at(i).name) << " \n";
+ out() << "" << protectEnc(sections.at(i).name) << " \n";
generateSectionList(sections.at(i), inner, marker, CodeMarker::Summary);
}
sections = marker->sections(inner, CodeMarker::Detailed, status);
for (i = 0; i < sections.size(); ++i) {
out() << " \n";
- out() << "" << protect(sections.at(i).name) << " \n";
+ out() << "" << protectEnc(sections.at(i).name) << " \n";
NodeList::ConstIterator m = sections.at(i).members.begin();
while (m != sections.at(i).members.end()) {
@@ -2113,7 +2125,7 @@ void HtmlGenerator::generateAnnotatedList(const Node *relative,
}
else {
out() << "";
- out() << protect(node->doc().briefText().toString());
+ out() << protectEnc(node->doc().briefText().toString());
out() << " ";
}
out() << "
\n";
@@ -2315,7 +2327,7 @@ void HtmlGenerator::generateCompactList(const Node *relative,
<< linkForNode(it.value(), relative)
<< "\">";
QStringList pieces = fullName(it.value(), relative, marker).split("::");
- out() << protect(pieces.last());
+ out() << protectEnc(pieces.last());
out() << "";
if (pieces.size() > 1) {
out() << " (";
@@ -2357,7 +2369,7 @@ void HtmlGenerator::generateFunctionIndex(const Node *relative,
#else
out() << "";
#endif
- out() << protect(f.key()) << ":";
+ out() << protectEnc(f.key()) << ":";
currentLetter = f.key()[0].unicode();
while (islower(currentLetter) && currentLetter >= nextLetter) {
@@ -2411,7 +2423,7 @@ void HtmlGenerator::generateLegaleseList(const Node *relative,
QString marked = marker->markedUpSynopsis(node, relative, style);
QRegExp templateTag("(<[^@>]*>)");
if (marked.indexOf(templateTag) != -1) {
- QString contents = protect(marked.mid(templateTag.pos(1),
+ QString contents = protectEnc(marked.mid(templateTag.pos(1),
templateTag.cap(1).length()));
marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
contents);
@@ -2450,7 +2462,7 @@ void HtmlGenerator::generateQmlItem(const Node *node,
QString marked = marker->markedUpQmlItem(node,summary);
QRegExp templateTag("(<[^@>]*>)");
if (marked.indexOf(templateTag) != -1) {
- QString contents = protect(marked.mid(templateTag.pos(1),
+ QString contents = protectEnc(marked.mid(templateTag.pos(1),
templateTag.cap(1).length()));
marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
contents);
@@ -2556,7 +2568,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
const FakeNode *groupNode = groupTitlesMap[groupTitle];
out() << QString("
\n").arg(
linkForNode(groupNode, relative)).arg(
- protect(groupNode->fullTitle()));
+ protectEnc(groupNode->fullTitle()));
if (fakeNodeMap[groupNode].count() == 0)
continue;
@@ -2568,7 +2580,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
if (title.startsWith("The "))
title.remove(0, 4);
out() << ""
- << protect(title) << " \n";
+ << protectEnc(title) << "\n";
}
out() << "\n";
}
@@ -2582,7 +2594,7 @@ void HtmlGenerator::generateOverviewList(const Node *relative, CodeMarker * /* m
if (title.startsWith("The "))
title.remove(0, 4);
out() << ""
- << protect(title) << " \n";
+ << protectEnc(title) << "\n";
}
out() << "\n";
}
@@ -2745,7 +2757,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section,
}
out() << " inherited from "
- << protect(marker->plainFullName((*p).first, relative))
+ << protectEnc(marker->plainFullName((*p).first, relative))
<< " \n";
++p;
}
@@ -2760,7 +2772,7 @@ void HtmlGenerator::generateSynopsis(const Node *node,
QString marked = marker->markedUpSynopsis(node, relative, style);
QRegExp templateTag("(<[^@>]*>)");
if (marked.indexOf(templateTag) != -1) {
- QString contents = protect(marked.mid(templateTag.pos(1),
+ QString contents = protectEnc(marked.mid(templateTag.pos(1),
templateTag.cap(1).length()));
marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
contents);
@@ -3029,7 +3041,7 @@ void HtmlGenerator::generateSectionInheritedList(const Section& section,
}
out() << " inherited from "
- << protect(marker->plainFullName((*p).first, relative))
+ << protectEnc(marker->plainFullName((*p).first, relative))
<< " \n";
++p;
}
@@ -3043,7 +3055,7 @@ void HtmlGenerator::generateSynopsis(const Node *node,
QString marked = marker->markedUpSynopsis(node, relative, style);
QRegExp templateTag("(<[^@>]*>)");
if (marked.indexOf(templateTag) != -1) {
- QString contents = protect(marked.mid(templateTag.pos(1),
+ QString contents = protectEnc(marked.mid(templateTag.pos(1),
templateTag.cap(1).length()));
marked.replace(templateTag.pos(1), templateTag.cap(1).length(),
contents);
@@ -3241,7 +3253,7 @@ void HtmlGenerator::generateLink(const Atom* atom,
if (funcLeftParen.indexIn(atom->string()) != -1 && marker->recognizeLanguage("Cpp")) {
// hack for C++: move () outside of link
int k = funcLeftParen.pos(1);
- out() << protect(atom->string().left(k));
+ out() << protectEnc(atom->string().left(k));
if (link.isEmpty()) {
if (showBrokenLinks)
out() << "";
@@ -3249,7 +3261,7 @@ void HtmlGenerator::generateLink(const Atom* atom,
out() << "";
}
inLink = false;
- out() << protect(atom->string().mid(k));
+ out() << protectEnc(atom->string().mid(k));
} else if (marker->recognizeLanguage("Java")) {
// hack for Java: remove () and use when appropriate
bool func = atom->string().endsWith("()");
@@ -3257,13 +3269,13 @@ void HtmlGenerator::generateLink(const Atom* atom,
if (tt)
out() << "";
if (func) {
- out() << protect(atom->string().left(atom->string().length() - 2));
+ out() << protectEnc(atom->string().left(atom->string().length() - 2));
} else {
- out() << protect(atom->string());
+ out() << protectEnc(atom->string());
}
out() << " ";
} else {
- out() << protect(atom->string());
+ out() << protectEnc(atom->string());
}
}
@@ -3337,7 +3349,12 @@ QString HtmlGenerator::registerRef(const QString& ref)
return clean;
}
-QString HtmlGenerator::protect(const QString& string)
+QString HtmlGenerator::protectEnc(const QString &string)
+{
+ return protect(string, outputEncoding);
+}
+
+QString HtmlGenerator::protect(const QString &string, const QString &outputEncoding)
{
#define APPEND(x) \
if (html.isEmpty()) { \
@@ -3360,7 +3377,7 @@ QString HtmlGenerator::protect(const QString& string)
APPEND(">");
} else if (ch == QLatin1Char('"')) {
APPEND(""");
- } else if (ch.unicode() > 0x007F
+ } else if ((outputEncoding == "ISO-8859-1" && ch.unicode() > 0x007F)
|| (ch == QLatin1Char('*') && i + 1 < n && string.at(i) == QLatin1Char('/'))
|| (ch == QLatin1Char('.') && i > 2 && string.at(i - 2) == QLatin1Char('.'))) {
// we escape '*/' and the last dot in 'e.g.' and 'i.e.' for the Javadoc generator
@@ -3490,7 +3507,7 @@ QString HtmlGenerator::refForNode(const Node *node)
ref = node->name() + "-var";
break;
case Node::Target:
- return protect(node->name());
+ return protectEnc(node->name());
}
return registerRef(ref);
}
@@ -3564,7 +3581,7 @@ void HtmlGenerator::generateFullName(const Node *apparentNode,
}
}
out() << "\">";
- out() << protect(fullName(apparentNode, relative, marker));
+ out() << protectEnc(fullName(apparentNode, relative, marker));
out() << "";
}
@@ -3625,12 +3642,12 @@ void HtmlGenerator::generateDetailedMember(const Node *node,
else if (node->type() == Node::Enum) {
const EnumNode *enume = static_cast(node);
if (enume->flagsType()) {
- out() << "The " << protect(enume->flagsType()->name())
+ out() << "
The " << protectEnc(enume->flagsType()->name())
<< " type is a typedef for "
<< "QFlags <"
- << protect(enume->name())
+ << protectEnc(enume->name())
<< ">. It stores an OR combination of "
- << protect(enume->name())
+ << protectEnc(enume->name())
<< " values.
\n";
}
}
diff --git a/tools/qdoc3/htmlgenerator.h b/tools/qdoc3/htmlgenerator.h
index 19a7c78..5ed26e0 100644
--- a/tools/qdoc3/htmlgenerator.h
+++ b/tools/qdoc3/htmlgenerator.h
@@ -104,7 +104,8 @@ class HtmlGenerator : public PageGenerator
virtual QString format();
virtual void generateTree(const Tree *tree, CodeMarker *marker);
- static QString protect(const QString& string);
+ QString protectEnc(const QString &string);
+ static QString protect(const QString &string, const QString &encoding = "ISO-8859-1");
static QString cleanRef(const QString& ref);
static QString sinceTitle(int i) { return sinceTitles[i]; }
diff --git a/tools/qdoc3/pagegenerator.cpp b/tools/qdoc3/pagegenerator.cpp
index a001c10..e637109 100644
--- a/tools/qdoc3/pagegenerator.cpp
+++ b/tools/qdoc3/pagegenerator.cpp
@@ -176,7 +176,7 @@ void PageGenerator::beginSubPage(const Location& location,
location.fatal(tr("Cannot open output file '%1'")
.arg(outFile->fileName()));
QTextStream *out = new QTextStream(outFile);
- out->setCodec("ISO-8859-1");
+ out->setCodec(outputCodec);
outStreamStack.push(out);
}
diff --git a/tools/qdoc3/pagegenerator.h b/tools/qdoc3/pagegenerator.h
index db24edd..20a6c3c 100644
--- a/tools/qdoc3/pagegenerator.h
+++ b/tools/qdoc3/pagegenerator.h
@@ -54,6 +54,8 @@
QT_BEGIN_NAMESPACE
+class QTextCodec;
+
class ClassNode;
class InnerNode;
class NamespaceNode;
@@ -76,6 +78,10 @@ class PageGenerator : public Generator
virtual void generateInnerNode(const InnerNode *node, CodeMarker *marker);
QTextStream& out();
+ QString naturalLanguage;
+ QString outputEncoding;
+ QTextCodec *outputCodec;
+
private:
QStack outStreamStack;
};
diff --git a/tools/qdoc3/qsakernelparser.cpp b/tools/qdoc3/qsakernelparser.cpp
index 9320a17..8f12eda 100644
--- a/tools/qdoc3/qsakernelparser.cpp
+++ b/tools/qdoc3/qsakernelparser.cpp
@@ -70,8 +70,8 @@ void QsaKernelParser::parseSourceFile( const Location& location,
const QString& filePath,
Tree * /* tree */ )
{
- FILE *in = fopen( QFile::encodeName(filePath), "r" );
- if ( in == 0 ) {
+ QFile in(filePath);
+ if (!in.open(QIODevice::ReadOnly)) {
location.error( tr("Cannot open QSA kernel file '%1'").arg(filePath) );
return;
}
@@ -171,7 +171,7 @@ void QsaKernelParser::parseSourceFile( const Location& location,
readToken();
}
}
- fclose( in );
+ in.close();
}
void QsaKernelParser::doneParsingSourceFiles( Tree * /* tree */ )
diff --git a/tools/qdoc3/qscodeparser.cpp b/tools/qdoc3/qscodeparser.cpp
index 8b3bc98..3b8bc1a 100644
--- a/tools/qdoc3/qscodeparser.cpp
+++ b/tools/qdoc3/qscodeparser.cpp
@@ -151,8 +151,8 @@ void QsCodeParser::parseHeaderFile(const Location& location,
{
qsTre = tree;
- FILE *in = fopen(QFile::encodeName(filePath), "r");
- if (in == 0) {
+ QFile in(filePath);
+ if (!in.open(QIODevice::ReadOnly)) {
location.error(tr("Cannot open Qt Script class list '%1'")
.arg(filePath));
return;
@@ -175,7 +175,7 @@ void QsCodeParser::parseHeaderFile(const Location& location,
}
tok = fileTokenizer.getToken();
}
- fclose(in);
+ in.close();
}
void QsCodeParser::parseSourceFile(const Location& location,
diff --git a/tools/qdoc3/tokenizer.cpp b/tools/qdoc3/tokenizer.cpp
index b391759..7c10de6 100644
--- a/tools/qdoc3/tokenizer.cpp
+++ b/tools/qdoc3/tokenizer.cpp
@@ -47,6 +47,7 @@
#include
#include
#include
+#include
#include
#include
@@ -97,6 +98,8 @@ static QRegExp *definedX = 0;
static QRegExp *defines = 0;
static QRegExp *falsehoods = 0;
+static QTextCodec *sourceCodec = 0;
+
/*
This function is a perfect hash function for the 37 keywords of C99
(with a hash table size of 512). It should perform well on our
@@ -118,13 +121,10 @@ static void insertKwordIntoHash(const char *s, int number)
kwordHashTable[k] = number;
}
-Tokenizer::Tokenizer(const Location& loc, FILE *in)
+Tokenizer::Tokenizer(const Location& loc, QFile &in)
{
init();
- QFile file;
- file.open(in, QIODevice::ReadOnly);
- yyIn = file.readAll();
- file.close();
+ yyIn = in.readAll();
yyPos = 0;
start(loc);
}
@@ -483,6 +483,11 @@ void Tokenizer::initialize(const Config &config)
{
QString versionSym = config.getString(CONFIG_VERSIONSYM);
+ QString sourceEncoding = config.getString(CONFIG_SOURCEENCODING);
+ if (sourceEncoding.isEmpty())
+ sourceEncoding = QLatin1String("ISO-8859-1");
+ sourceCodec = QTextCodec::codecForName(sourceEncoding.toLocal8Bit());
+
comment = new QRegExp("/(?:\\*.*\\*/|/.*\n|/[^\n]*$)");
comment->setMinimal(true);
versionX = new QRegExp("$cannot possibly match^");
@@ -750,4 +755,14 @@ bool Tokenizer::isTrue(const QString &condition)
return !falsehoods->exactMatch(t);
}
+QString Tokenizer::lexeme() const
+{
+ return sourceCodec->toUnicode(yyLex);
+}
+
+QString Tokenizer::previousLexeme() const
+{
+ return sourceCodec->toUnicode(yyPrevLex);
+}
+
QT_END_NAMESPACE
diff --git a/tools/qdoc3/tokenizer.h b/tools/qdoc3/tokenizer.h
index 519cffb..f55d2ef 100644
--- a/tools/qdoc3/tokenizer.h
+++ b/tools/qdoc3/tokenizer.h
@@ -46,11 +46,10 @@
#ifndef TOKENIZER_H
#define TOKENIZER_H
+#include
#include
#include
-#include
-
#include "location.h"
QT_BEGIN_NAMESPACE
@@ -99,7 +98,7 @@ class Tokenizer
{
public:
Tokenizer(const Location& loc, const QByteArray &in);
- Tokenizer(const Location& loc, FILE *in);
+ Tokenizer(const Location& loc, QFile &file);
~Tokenizer();
@@ -108,8 +107,8 @@ class Tokenizer
bool parsingFnOrMacro() const { return parsingMacro; }
const Location &location() const { return yyTokLoc; }
- QString previousLexeme() const { return QString(yyPrevLex); }
- QString lexeme() const { return QString(yyLex); }
+ QString previousLexeme() const;
+ QString lexeme() const;
QString version() const { return yyVersion; }
int braceDepth() const { return yyBraceDepth; }
int parenDepth() const { return yyParenDepth; }
--
cgit v0.12
From c186c0402781ec6ef6ee97e2168d16f0b043044e Mon Sep 17 00:00:00 2001
From: Anders Bakken
Date: Tue, 2 Feb 2010 13:51:43 -0800
Subject: Make DSFLIP_ONSYNC part of the default flip flags.
Reviewed-by: Jervey Kong
---
src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 6b251c7..cd4d5c2 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -921,7 +921,7 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args)
qPrintable(flip));
}
} else {
- flipFlags = DSFLIP_BLIT;
+ flipFlags = DSFLIP_BLIT|DSFLIP_ONSYNC;
}
}
--
cgit v0.12
From 7d4ef9167249df5f00831dc07e57705eb1ddd22a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Samuel=20R=C3=B8dal?=
Date: Wed, 3 Feb 2010 10:36:15 +0100
Subject: Update changes-4.6.2.
---
dist/changes-4.6.2 | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 58dcf0e..292b3ef 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -49,6 +49,10 @@ QtGui
- QBmpHandler
* [QTBUG-7530] Fixed an infinite loop that could occur when reading invalid BMP images.
+ - QGraphicsEffect
+ * [QTBUG-6901] Fixed performance problem when translating items with
+ graphics effects.
+
- QImage
* [QTBUG-7231] Avoid an unnecessary copy in QImage::scaled().
--
cgit v0.12
From 7702b57286b0d02857f5312dbc36c87784ac1b11 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint
Date: Wed, 3 Feb 2010 10:42:26 +0100
Subject: Designer: Support the 'windowOpacity'-property for forms.
Analogous to windowTitle, etc.
Task-number: QTBUG-7822
---
tools/designer/src/components/formeditor/formwindow.cpp | 1 +
tools/designer/src/lib/shared/qdesigner_propertysheet.cpp | 10 ++++++++--
2 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/tools/designer/src/components/formeditor/formwindow.cpp b/tools/designer/src/components/formeditor/formwindow.cpp
index 2d013c9..4cfec95 100644
--- a/tools/designer/src/components/formeditor/formwindow.cpp
+++ b/tools/designer/src/components/formeditor/formwindow.cpp
@@ -484,6 +484,7 @@ void FormWindow::setMainContainer(QWidget *w)
sheet->setVisible(sheet->indexOf(QLatin1String("windowTitle")), true);
sheet->setVisible(sheet->indexOf(QLatin1String("windowIcon")), true);
sheet->setVisible(sheet->indexOf(QLatin1String("windowModality")), true);
+ sheet->setVisible(sheet->indexOf(QLatin1String("windowOpacity")), true);
sheet->setVisible(sheet->indexOf(QLatin1String("windowFilePath")), true);
// ### generalize
}
diff --git a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
index b4b962c..13bb1d7 100644
--- a/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
+++ b/tools/designer/src/lib/shared/qdesigner_propertysheet.cpp
@@ -610,8 +610,9 @@ QDesignerPropertySheet::QDesignerPropertySheet(QObject *object, QObject *parent)
createFakeProperty(QLatin1String("whatsThis"));
createFakeProperty(QLatin1String("acceptDrops"));
createFakeProperty(QLatin1String("dragEnabled"));
- // windowModality is visible only for the main container, in which case the form windows enables it on loading
+ // windowModality/Opacity is visible only for the main container, in which case the form windows enables it on loading
setVisible(createFakeProperty(QLatin1String("windowModality")), false);
+ setVisible(createFakeProperty(QLatin1String("windowOpacity"), double(1.0)), false);
if (qobject_cast(d->m_object)) { // prevent toolbars from being dragged off
createFakeProperty(QLatin1String("floatable"), QVariant(true));
} else {
@@ -1451,8 +1452,13 @@ bool QDesignerPropertySheet::isVisible(int index) const
}
if (isFakeProperty(index)) {
- if (type == PropertyWindowModality) // Hidden for child widgets
+ switch (type) {
+ case PropertyWindowModality: // Hidden for child widgets
+ case PropertyWindowOpacity:
return d->m_info.value(index).visible;
+ default:
+ break;
+ }
return true;
}
--
cgit v0.12
From 7e46016d55a80e9d49797efe34779893d80b71e3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Sakari=20Peltom=C3=A4ki?=
Date: Wed, 3 Feb 2010 10:42:54 +0100
Subject: Proper Fav icon is not shown, for all the links default fav icon
shown
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Added two functions on QtIcoHandler(inherited from QImageIOHandler):
bool supports Option(ImageOption option) const
QVariant option(ImageOption option) const
implementation of these functions make possible to open fav.ico
eg. via web browser.
(if using fav.ico icons via webkit, browser should initialize
webcore::icondatabase using QWebSettings::enablePersistentStorage() )
Merge-request: 2150
Reviewed-by: Jan-Arve Sæther
---
src/plugins/imageformats/ico/qicohandler.cpp | 24 ++++++++++++++++++++++++
src/plugins/imageformats/ico/qicohandler.h | 3 +++
2 files changed, 27 insertions(+)
diff --git a/src/plugins/imageformats/ico/qicohandler.cpp b/src/plugins/imageformats/ico/qicohandler.cpp
index b2351fa..4edb87a 100644
--- a/src/plugins/imageformats/ico/qicohandler.cpp
+++ b/src/plugins/imageformats/ico/qicohandler.cpp
@@ -53,6 +53,7 @@
#include
#include
#include
+#include
// These next two structs represent how the icon information is stored
// in an ICO file.
typedef struct
@@ -772,6 +773,29 @@ QtIcoHandler::~QtIcoHandler()
delete m_pICOReader;
}
+QVariant QtIcoHandler::option(ImageOption option) const
+{
+ if (option == Size) {
+ QIODevice *device = QImageIOHandler::device();
+ qint64 oldPos = device->pos();
+ ICONDIRENTRY iconEntry;
+ if (device->seek(oldPos + ICONDIR_SIZE + (m_currentIconIndex * ICONDIRENTRY_SIZE))) {
+ if (readIconDirEntry(device, &iconEntry)) {
+ device->seek(oldPos);
+ return QSize(iconEntry.bWidth, iconEntry.bHeight);
+ }
+ }
+ if (!device->isSequential())
+ device->seek(oldPos);
+ }
+ return QVariant();
+}
+
+bool QtIcoHandler::supportsOption(ImageOption option) const
+{
+ return option == Size;
+}
+
/*!
* Verifies if some values (magic bytes) are set as expected in the header of the file.
* If the magic bytes were found, it is assumed that the QtIcoHandler can read the file.
diff --git a/src/plugins/imageformats/ico/qicohandler.h b/src/plugins/imageformats/ico/qicohandler.h
index b9ef27e..394a5eb 100644
--- a/src/plugins/imageformats/ico/qicohandler.h
+++ b/src/plugins/imageformats/ico/qicohandler.h
@@ -62,6 +62,9 @@ public:
static bool canRead(QIODevice *device);
+ bool supportsOption(ImageOption option) const;
+ QVariant option(ImageOption option) const;
+
private:
int m_currentIconIndex;
ICOReader *m_pICOReader;
--
cgit v0.12
From d53315d30b38352db11063096ee3867a40bdc234 Mon Sep 17 00:00:00 2001
From: Olivier Goffart
Date: Wed, 3 Feb 2010 11:30:20 +0100
Subject: Revert "QAbstractScrollArea: Wheel over a scrollarea that has only
one horizontal scrollbar"
This reverts commit 46a3e518b3070cf7cb4cbbb2cb58254454cf169d.
This shown to cause more problem than it solved
Also update the changelog
Reviewed-by: Thierry
---
dist/changes-4.6.2 | 3 +
src/gui/widgets/qabstractscrollarea.cpp | 11 +--
src/gui/widgets/qabstractslider.cpp | 2 +
.../tst_qabstractscrollarea.cpp | 97 +---------------------
4 files changed, 11 insertions(+), 102 deletions(-)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 292b3ef..4127e13 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -46,6 +46,9 @@ QtCore
QtGui
-----
+ - QAbstractScrollArea
+ * [QTBUG-1760] Reverted horizontal scrolling with mouse wheel when vertical scrollbar is hidden
+
- QBmpHandler
* [QTBUG-7530] Fixed an infinite loop that could occur when reading invalid BMP images.
diff --git a/src/gui/widgets/qabstractscrollarea.cpp b/src/gui/widgets/qabstractscrollarea.cpp
index 87f6c83..1d496d5 100644
--- a/src/gui/widgets/qabstractscrollarea.cpp
+++ b/src/gui/widgets/qabstractscrollarea.cpp
@@ -1134,13 +1134,10 @@ void QAbstractScrollArea::mouseMoveEvent(QMouseEvent *e)
void QAbstractScrollArea::wheelEvent(QWheelEvent *e)
{
Q_D(QAbstractScrollArea);
- QScrollBar *const bars[2] = { d->hbar, d->vbar };
- int idx = (e->orientation() == Qt::Vertical) ? 1 : 0;
- int other = (idx + 1) % 2;
- if (!bars[idx]->isVisible() && bars[other]->isVisible())
- idx = other; // If the scrollbar of the event orientation is hidden, fallback to the other.
-
- QApplication::sendEvent(bars[idx], e);
+ if (static_cast(e)->orientation() == Qt::Horizontal)
+ QApplication::sendEvent(d->hbar, e);
+ else
+ QApplication::sendEvent(d->vbar, e);
}
#endif
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 2874647..77c5a01 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -697,6 +697,8 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e)
{
Q_D(QAbstractSlider);
e->ignore();
+ if (e->orientation() != d->orientation && !rect().contains(e->pos()))
+ return;
int stepsToScroll = 0;
qreal offset = qreal(e->delta()) / 120;
diff --git a/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp b/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp
index 3e062b8..da83826 100644
--- a/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp
+++ b/tests/auto/qabstractscrollarea/tst_qabstractscrollarea.cpp
@@ -71,8 +71,6 @@ private slots:
void viewportCrash();
void task214488_layoutDirection_data();
void task214488_layoutDirection();
- void wheelEvent_data();
- void wheelEvent();
};
tst_QAbstractScrollArea::tst_QAbstractScrollArea()
@@ -298,10 +296,10 @@ public:
setAttribute(Qt::WA_DropSiteRegistered, true);
- startTimer(200);
+ startTimer(2000);
}
- void timerEvent(QTimerEvent *)
+ void timerEvent(QTimerEvent *event)
{
// should not crash.
(void)new QScrollArea(this);
@@ -387,96 +385,5 @@ void tst_QAbstractScrollArea::patternBackground()
QCOMPARE(image.pixel(QPoint(20,20)) , QColor(Qt::red).rgb());
}
-Q_DECLARE_METATYPE(QWheelEvent *);
-
-void tst_QAbstractScrollArea::wheelEvent_data()
-{
- QTest::addColumn("widgetSize");
- QTest::addColumn("initialOffset");
- QTest::addColumn("event");
- QTest::addColumn("movedX"); // -1 , 0 , or 1
- QTest::addColumn("movedY");
-
- QPoint pos(100,100);
- int delta =-120;
-
- QTest::newRow("1") << QSize(600,600) << QPoint(50,50)
- << new QWheelEvent(pos, delta, 0, 0, Qt::Horizontal) << 1 << 0;
-
- QTest::newRow("2") << QSize(600,600) << QPoint(50,50)
- << new QWheelEvent(pos, delta, 0, 0, Qt::Vertical) << 0 << 1;
-
- QTest::newRow("3") << QSize(600,600) << QPoint(50,50)
- << new QWheelEvent(pos, -delta, 0, 0, Qt::Horizontal) << -1 << 0;
-
- QTest::newRow("4") << QSize(600,600) << QPoint(50,50)
- << new QWheelEvent(pos, -delta, 0, 0, Qt::Vertical) << 0 << -1;
-
- QTest::newRow("5") << QSize(20,600) << QPoint(0,50)
- << new QWheelEvent(pos, delta, 0, 0, Qt::Horizontal) << 0 << 1;
-
- QTest::newRow("6") << QSize(20,600) << QPoint(0,50)
- << new QWheelEvent(pos, delta, 0, 0, Qt::Vertical) << 0 << 1;
-
- QTest::newRow("7") << QSize(20,600) << QPoint(0,50)
- << new QWheelEvent(pos, -delta, 0, 0, Qt::Horizontal) << 0 << -1;
-
- QTest::newRow("8") << QSize(20,600) << QPoint(0,50)
- << new QWheelEvent(pos, -delta, 0, 0, Qt::Vertical) << 0 << -1;
-
- QTest::newRow("9") << QSize(600,20) << QPoint(50,0)
- << new QWheelEvent(pos, delta, 0, 0, Qt::Horizontal) << 1 << 0;
-
- QTest::newRow("a") << QSize(600,20) << QPoint(50,0)
- << new QWheelEvent(pos, delta, 0, 0, Qt::Vertical) << 1 << 0;
-
- QTest::newRow("b") << QSize(600,20) << QPoint(50,0)
- << new QWheelEvent(pos, -delta, 0, 0, Qt::Horizontal) << -1 << 0;
-
- QTest::newRow("c") << QSize(600,20) << QPoint(50,0)
- << new QWheelEvent(pos, -delta, 0, 0, Qt::Vertical) << -1 << 0;
-}
-
-
-
-
-void tst_QAbstractScrollArea::wheelEvent()
-{
- QFETCH(QSize, widgetSize);
- QFETCH(QPoint, initialOffset);
- QFETCH(QWheelEvent *, event);
- QFETCH(int, movedX);
- QFETCH(int, movedY);
-
- QScrollArea scrollArea;
- scrollArea.resize(200, 200);
- QLabel widget("H e l l o");
- widget.resize(widgetSize);
- scrollArea.setWidget(&widget);
- scrollArea.show();
- QTest::qWait(20);
-
- scrollArea.verticalScrollBar()->setValue(initialOffset.y());
- scrollArea.horizontalScrollBar()->setValue(initialOffset.x());
-
- QCOMPARE(scrollArea.verticalScrollBar()->value(), initialOffset.y());
- QCOMPARE(scrollArea.horizontalScrollBar()->value(), initialOffset.x());
-
- QApplication::sendEvent(scrollArea.viewport(), event);
-
- if(movedX == 0)
- QCOMPARE(scrollArea.horizontalScrollBar()->value(), initialOffset.x());
- else
- QVERIFY(movedX * scrollArea.horizontalScrollBar()->value() > movedX * initialOffset.x());
-
- if(movedY == 0)
- QCOMPARE(scrollArea.verticalScrollBar()->value(), initialOffset.y());
- else
- QVERIFY(movedY * scrollArea.verticalScrollBar()->value() > movedY * initialOffset.y());
-
- delete event;
-}
-
-
QTEST_MAIN(tst_QAbstractScrollArea)
#include "tst_qabstractscrollarea.moc"
--
cgit v0.12
From cc585886ba9da17064a7fc858f5d717967da6e85 Mon Sep 17 00:00:00 2001
From: Olivier Goffart
Date: Wed, 3 Feb 2010 12:47:34 +0100
Subject: QStyleSheetStyle: Fix combinaison of border-image and border-radius
Regression since b4d642e639eabde5d72a4
Task-number: QTBUG-7737
Reviewed-by: Gabriel
---
src/gui/styles/qstylesheetstyle.cpp | 2 +
.../baseline/css_qtbug7737_borderimageradius.ui | 44 ++++++++++++++++++++++
2 files changed, 46 insertions(+)
create mode 100644 tests/auto/uiloader/baseline/css_qtbug7737_borderimageradius.ui
diff --git a/src/gui/styles/qstylesheetstyle.cpp b/src/gui/styles/qstylesheetstyle.cpp
index 498313b..b36294a 100644
--- a/src/gui/styles/qstylesheetstyle.cpp
+++ b/src/gui/styles/qstylesheetstyle.cpp
@@ -1125,6 +1125,7 @@ void QRenderRule::fixupBorder(int nativeWidth)
void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
{
+ setClip(p, rect);
static const Qt::TileRule tileMode2TileRule[] = {
Qt::StretchTile, Qt::RoundTile, Qt::StretchTile, Qt::RepeatTile, Qt::StretchTile };
@@ -1142,6 +1143,7 @@ void QRenderRule::drawBorderImage(QPainter *p, const QRect& rect)
QRect(QPoint(), borderImageData->pixmap.size()), sourceMargins,
QTileRules(tileMode2TileRule[borderImageData->horizStretch], tileMode2TileRule[borderImageData->vertStretch]));
p->setRenderHint(QPainter::SmoothPixmapTransform, wasSmoothPixmapTransform);
+ unsetClip(p);
}
QRect QRenderRule::originRect(const QRect &rect, Origin origin) const
diff --git a/tests/auto/uiloader/baseline/css_qtbug7737_borderimageradius.ui b/tests/auto/uiloader/baseline/css_qtbug7737_borderimageradius.ui
new file mode 100644
index 0000000..089cb76
--- /dev/null
+++ b/tests/auto/uiloader/baseline/css_qtbug7737_borderimageradius.ui
@@ -0,0 +1,44 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 207
+ 69
+
+
+
+ Form
+
+
+ QPushButton { border-image: url("images/pushbutton.png") 5 5 5 5; border-radius:8px; }
+
+
+ -
+
+
+ Border image and radius
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 40
+
+
+
+
+
+
+
+
+
--
cgit v0.12
From 80e114ad0b7974894858a17153d6f54546835066 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Wed, 3 Feb 2010 11:17:19 +0100
Subject: QGraphicsScene: Use QPainter::setClipRect instead of setClipPath if
possible.
Using QPainter::setClipPath results in complex (and slow) alphamasking
so this must be avoided if possible.
Task-number: QTBUG-7790
Reviewed-by: samuel
---
src/gui/graphicsview/qgraphicsscene.cpp | 18 +++++++++++++++---
src/gui/painting/qpathclipper.cpp | 4 +---
src/gui/painting/qpathclipper_p.h | 2 ++
3 files changed, 18 insertions(+), 6 deletions(-)
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 842d368..4bfe9ad 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -251,6 +251,7 @@
#endif
#include
#include
+#include
// #define GESTURE_DEBUG
#ifndef GESTURE_DEBUG
@@ -4765,7 +4766,12 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
painter->setWorldTransform(*transformPtr * *effectTransform);
else
painter->setWorldTransform(*transformPtr);
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
}
// Draw children behind
@@ -4801,8 +4807,14 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
painter->setWorldTransform(*transformPtr);
}
- if (itemClipsToShape)
- painter->setClipPath(item->shape(), Qt::IntersectClip);
+ if (itemClipsToShape) {
+ QRectF clipRect;
+ const QPainterPath clipPath(item->shape());
+ if (QPathClipper::pathToRect(clipPath, &clipRect))
+ painter->setClipRect(clipRect, Qt::IntersectClip);
+ else
+ painter->setClipPath(clipPath, Qt::IntersectClip);
+ }
painter->setOpacity(opacity);
if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 7997e77..5702ede 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -90,8 +90,6 @@ static QPointF normalize(const QPointF &p)
return p / qSqrt(p.x() * p.x() + p.y() * p.y());
}
-static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
-
struct QIntersection
{
qreal alphaA;
@@ -1660,7 +1658,7 @@ static bool fuzzyCompare(qreal a, qreal b)
return qFuzzyCompare(a, b);
}
-static bool pathToRect(const QPainterPath &path, QRectF *rect)
+bool QPathClipper::pathToRect(const QPainterPath &path, QRectF *rect)
{
if (path.elementCount() != 5)
return false;
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 0d2c049..b900862 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -86,6 +86,8 @@ public:
bool intersect();
bool contains();
+ static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
+
private:
Q_DISABLE_COPY(QPathClipper)
--
cgit v0.12
From 09fe8e377fea67b4279521e3cb08bb937ef65474 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Wed, 3 Feb 2010 11:26:50 +0100
Subject: Optimize QPathClipper::pathToRect.
Patch speaks for itself :-)
Reviewed-by: samuel
---
src/gui/painting/qpathclipper.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 5702ede..bc81514 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -1691,7 +1691,7 @@ bool QPathClipper::pathToRect(const QPainterPath &path, QRectF *rect)
return false;
if (rect)
- *rect = QRectF(QPointF(x1, y1), QPointF(x2, y2));
+ rect->setCoords(x1, y1, x2, y2);
return true;
}
--
cgit v0.12
From 71e2f9d35a922fb0ec8fff40bdc7d2d47d42dd8c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Wed, 3 Feb 2010 14:56:43 +0100
Subject: Compiler warning in QAbstractSlider.
---
src/gui/widgets/qabstractslider.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index 77c5a01..dca44a4 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -214,8 +214,8 @@ QT_BEGIN_NAMESPACE
*/
QAbstractSliderPrivate::QAbstractSliderPrivate()
- : minimum(0), maximum(99), singleStep(1), pageStep(10),
- value(0), position(0), pressValue(-1), offset_accumulated(0), tracking(true),
+ : minimum(0), maximum(99), pageStep(10), value(0), position(0), pressValue(-1),
+ singleStep(1), offset_accumulated(0), tracking(true),
blocktracking(false), pressed(false),
invertedAppearance(false), invertedControls(false),
orientation(Qt::Horizontal), repeatAction(QAbstractSlider::SliderNoAction)
--
cgit v0.12
From 038893af4241add08cbcf4ee9973b17209bc2272 Mon Sep 17 00:00:00 2001
From: David Boddie
Date: Wed, 3 Feb 2010 17:32:15 +0100
Subject: Doc: Fixed typo.
Reviewed-by: Trust Me
---
src/xml/dom/qdom.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/xml/dom/qdom.cpp b/src/xml/dom/qdom.cpp
index cae959b..8d9ae4f 100644
--- a/src/xml/dom/qdom.cpp
+++ b/src/xml/dom/qdom.cpp
@@ -2973,7 +2973,7 @@ QDomElement QDomNode::lastChildElement(const QString &tagName) const
}
/*!
- Returns the next sibilng element with tag name \a tagName if \a tagName
+ Returns the next sibling element with tag name \a tagName if \a tagName
is non-empty; otherwise returns any next sibling element.
Returns a null element if no such sibling exists.
--
cgit v0.12
From dda8a57c085216db609f822837c50bae38006b4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Wed, 3 Feb 2010 19:39:17 +0100
Subject: QGraphicsWidget is painted twice on the first show.
We want to discard all update requests when we there's a full update
pending. The problem was that 'updateAll' was reset too early causing
update requests to fall through. To prevent this from happening we
reset 'updateAll' right before the items are actually painted.
Auto-test included.
Task-number: QTBUG-6956
---
src/gui/graphicsview/qgraphicsscene.cpp | 7 +++++-
tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 27 ++++++++++++++++++++++
2 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 4bfe9ad..66707fc 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -373,7 +373,10 @@ void QGraphicsScenePrivate::_q_emitUpdated()
}
}
} else {
- updateAll = false;
+ if (views.isEmpty()) {
+ updateAll = false;
+ return;
+ }
for (int i = 0; i < views.size(); ++i)
views.at(i)->d_func()->processPendingUpdates();
// It's important that we update all views before we dispatch, hence two for-loops.
@@ -4604,6 +4607,7 @@ void QGraphicsScenePrivate::drawItems(QPainter *painter, const QTransform *const
if (!unpolishedItems.isEmpty())
_q_polishItems();
+ updateAll = false;
QRectF exposedSceneRect;
if (exposedRegion && indexMethod != QGraphicsScene::NoIndex) {
exposedSceneRect = exposedRegion->boundingRect().adjusted(-1, -1, 1, 1);
@@ -5166,6 +5170,7 @@ void QGraphicsScene::drawItems(QPainter *painter,
if (!d->unpolishedItems.isEmpty())
d->_q_polishItems();
+ d->updateAll = false;
QTransform viewTransform = painter->worldTransform();
Q_UNUSED(options);
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index d3132fe..526486e 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -164,6 +164,7 @@ private slots:
void polishEvent();
void polishEvent2();
void initialShow();
+ void initialShow2();
// Task fixes
void task236127_bspTreeIndexFails();
@@ -2881,6 +2882,32 @@ void tst_QGraphicsWidget::initialShow()
QCOMPARE(widget->repaints, 1);
}
+void tst_QGraphicsWidget::initialShow2()
+{
+ class MyGraphicsWidget : public QGraphicsWidget
+ { public:
+ MyGraphicsWidget() : repaints(0) {}
+ int repaints;
+ void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget*) { ++repaints; }
+ void polishEvent() { update(); }
+ };
+
+ MyGraphicsWidget *widget = new MyGraphicsWidget;
+ widget->resize(100, 100);
+
+ QGraphicsScene scene(0, 0, 200, 200);
+ scene.addItem(widget);
+
+ QGraphicsView view(&scene);
+ view.show();
+ // Not using QTest::qWaitForWindowShown(&view); on purpose, because there's
+ // a bug in qt_x11_wait_for_window_manager that prevents this test
+ // to pass. Denis is looking into it.
+ QTest::qWait(300);
+
+ QCOMPARE(widget->repaints, 1);
+}
+
void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems()
{
QGraphicsScene scene;
--
cgit v0.12
From 1677382148ed9e8d037d03a6fcc7bbe40458d69a Mon Sep 17 00:00:00 2001
From: Rhys Weatherley
Date: Thu, 4 Feb 2010 07:30:37 +1000
Subject: Optimize single-rect IntersectClip in OpenVG using the scissor
Task-number: QTBUG-7791
Reviewed-by: Sarah Smith
---
src/openvg/qpaintengine_vg.cpp | 46 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index cc9ba77..bff3328 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -188,6 +188,7 @@ public:
bool maskValid; // True if vgMask() contains valid data.
bool maskIsSet; // True if mask would be fully set if it was valid.
+ bool scissorMask; // True if scissor is used in place of the mask.
bool rawVG; // True if processing a raw VG escape.
QRect maskRect; // Rectangle version of mask if it is simple.
@@ -355,6 +356,7 @@ void QVGPaintEnginePrivate::init()
maskValid = false;
maskIsSet = false;
+ scissorMask = false;
rawVG = false;
scissorActive = false;
@@ -1664,12 +1666,12 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
if (op == Qt::NoClip) {
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
return;
}
-#if defined(QVG_NO_RENDER_TO_MASK)
// We don't have vgRenderToMask(), so handle simple QRectF's only.
if (path.shape() == QVectorPath::RectangleHint &&
path.elementCount() == 4 && clipTransformIsSimple(d->transform)) {
@@ -1679,8 +1681,10 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
QRectF rect(points[0], points[1], points[2] - points[0],
points[5] - points[1]);
clip(rect.toRect(), op);
+ return;
}
-#else
+
+#if !defined(QVG_NO_RENDER_TO_MASK)
QPaintDevice *pdev = paintDevice();
int width = pdev->width();
int height = pdev->height();
@@ -1711,6 +1715,7 @@ void QVGPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_TRUE);
d->maskValid = true;
d->maskIsSet = false;
+ d->scissorMask = false;
#endif
}
@@ -1731,6 +1736,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
{
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
}
@@ -1746,6 +1752,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
// Special case: if the intersection of the system
@@ -1763,6 +1770,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
if (clip.rectCount() != 1) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
d->modifyMask(this, VG_FILL_MASK, r);
break;
@@ -1771,6 +1779,7 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
}
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = true;
d->maskRect = clipRect;
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
@@ -1781,13 +1790,30 @@ void QVGPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
case Qt::IntersectClip:
{
QRect r = d->transform.mapRect(rect);
- if (d->maskIsSet && isDefaultClipRect(r)) {
+ if (!d->maskValid) {
+ // Mask has not been used yet, so intersect with
+ // the previous scissor-based region in maskRect.
+ if (d->scissorMask)
+ r = r.intersect(d->maskRect);
+ if (isDefaultClipRect(r)) {
+ // The clip is the full window, so turn off clipping.
+ d->maskIsSet = true;
+ d->maskRect = QRect();
+ } else {
+ // Activate the scissor on a smaller maskRect.
+ d->maskIsSet = false;
+ d->maskRect = r;
+ }
+ d->scissorMask = true;
+ updateScissor();
+ } else if (d->maskIsSet && isDefaultClipRect(r)) {
// Intersecting a full-window clip with a full-window
// region is the same as turning off clipping.
if (d->maskValid)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
d->modifyMask(this, VG_INTERSECT_MASK, r);
@@ -1829,6 +1855,7 @@ void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op)
{
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
}
@@ -1844,6 +1871,7 @@ void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
// Special case: if the intersection of the system
@@ -1857,12 +1885,14 @@ void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op)
if (clip.rectCount() == 1) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = true;
d->maskRect = clip.boundingRect();
vgSeti(VG_MASKING, VG_FALSE);
updateScissor();
} else {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
d->modifyMask(this, VG_FILL_MASK, r);
}
@@ -1887,6 +1917,7 @@ void QVGPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
} else {
d->modifyMask(this, VG_INTERSECT_MASK, r);
@@ -1965,6 +1996,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
if (op == Qt::NoClip) {
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
vgSeti(VG_MASKING, VG_FALSE);
return;
@@ -2000,6 +2032,7 @@ void QVGPaintEngine::clip(const QPainterPath &path, Qt::ClipOperation op)
vgSeti(VG_MASKING, VG_TRUE);
d->maskValid = true;
d->maskIsSet = false;
+ d->scissorMask = false;
#else
QPaintEngineEx::clip(path, op);
#endif
@@ -2043,6 +2076,7 @@ void QVGPaintEnginePrivate::modifyMask
vgSeti(VG_MASKING, VG_TRUE);
maskValid = true;
maskIsSet = false;
+ scissorMask = false;
}
void QVGPaintEnginePrivate::modifyMask
@@ -2064,6 +2098,7 @@ void QVGPaintEnginePrivate::modifyMask
vgSeti(VG_MASKING, VG_TRUE);
maskValid = true;
maskIsSet = false;
+ scissorMask = false;
}
#endif // !QVG_SCISSOR_CLIP
@@ -2096,7 +2131,7 @@ void QVGPaintEngine::updateScissor()
{
#if !defined(QVG_SCISSOR_CLIP)
// Combine the system clip with the simple mask rectangle.
- if (!d->maskRect.isNull()) {
+ if (d->scissorMask) {
if (region.isEmpty())
region = d->maskRect;
else
@@ -2187,6 +2222,7 @@ void QVGPaintEngine::clipEnabledChanged()
// Replay the entire clip stack to put the mask into the right state.
d->maskValid = false;
d->maskIsSet = true;
+ d->scissorMask = false;
d->maskRect = QRect();
s->clipRegion = defaultClipRegion();
d->replayClipOperations();
@@ -2196,6 +2232,7 @@ void QVGPaintEngine::clipEnabledChanged()
vgSeti(VG_MASKING, VG_FALSE);
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
}
#endif
@@ -3398,6 +3435,7 @@ void QVGPaintEngine::restoreState(QPaintEngine::DirtyFlags dirty)
QPaintEngine::DirtyClipEnabled)) != 0) {
d->maskValid = false;
d->maskIsSet = false;
+ d->scissorMask = false;
d->maskRect = QRect();
clipEnabledChanged();
}
--
cgit v0.12
From 4c84020bd1c049ce82e0deb77196829616b91f4a Mon Sep 17 00:00:00 2001
From: Rhys Weatherley
Date: Thu, 4 Feb 2010 10:12:14 +1000
Subject: Use OpenVG scissor on 90/180/270 rotations and simple clips.
Task-number: QTBUG-7864
Reviewed-by: Sarah Smith
---
src/openvg/qpaintengine_vg.cpp | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/src/openvg/qpaintengine_vg.cpp b/src/openvg/qpaintengine_vg.cpp
index bff3328..6813d2f 100644
--- a/src/openvg/qpaintengine_vg.cpp
+++ b/src/openvg/qpaintengine_vg.cpp
@@ -1544,7 +1544,28 @@ void QVGPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
static inline bool clipTransformIsSimple(const QTransform& transform)
{
QTransform::TransformationType type = transform.type();
- return (type == QTransform::TxNone || type == QTransform::TxTranslate);
+ if (type == QTransform::TxNone || type == QTransform::TxTranslate)
+ return true;
+ if (type == QTransform::TxRotate) {
+ // Check for 0, 90, 180, and 270 degree rotations.
+ // (0 might happen after 4 rotations of 90 degrees).
+ qreal m11 = transform.m11();
+ qreal m12 = transform.m12();
+ qreal m21 = transform.m21();
+ qreal m22 = transform.m22();
+ if (m11 == 0.0f && m22 == 0.0f) {
+ if (m12 == 1.0f && m21 == -1.0f)
+ return true; // 90 degrees.
+ else if (m12 == -1.0f && m21 == 1.0f)
+ return true; // 270 degrees.
+ } else if (m12 == 0.0f && m21 == 0.0f) {
+ if (m11 == -1.0f && m22 == -1.0f)
+ return true; // 180 degrees.
+ else if (m11 == 1.0f && m22 == 1.0f)
+ return true; // 0 degrees.
+ }
+ }
+ return false;
}
#if defined(QVG_SCISSOR_CLIP)
@@ -2351,12 +2372,7 @@ bool QVGPaintEngine::clearRect(const QRectF &rect, const QColor &color)
Q_D(QVGPaintEngine);
QVGPainterState *s = state();
if (!s->clipEnabled || s->clipOperation == Qt::NoClip) {
- // The transform will either be identity or a simple translation,
- // so do a simpler version of "r = d->transform.map(rect).toRect()".
- QRect r = QRect(qRound(rect.x() + d->transform.dx()),
- qRound(rect.y() + d->transform.dy()),
- qRound(rect.width()),
- qRound(rect.height()));
+ QRect r = d->transform.mapRect(rect).toRect();
int height = paintDevice()->height();
if (d->clearColor != color || d->clearOpacity != s->opacity) {
VGfloat values[4];
--
cgit v0.12
From 39523f9f78a7c93643924711b1ed8006ebfcf5ce Mon Sep 17 00:00:00 2001
From: Olivier Goffart
Date: Thu, 4 Feb 2010 09:54:47 +0100
Subject: Fix the QAbstractSlider autotest.
This reverts part of commit d53315d30b38352db11063096ee3867a40bdc234.
---
src/gui/widgets/qabstractslider.cpp | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/gui/widgets/qabstractslider.cpp b/src/gui/widgets/qabstractslider.cpp
index dca44a4..defebb9 100644
--- a/src/gui/widgets/qabstractslider.cpp
+++ b/src/gui/widgets/qabstractslider.cpp
@@ -697,8 +697,6 @@ void QAbstractSlider::wheelEvent(QWheelEvent * e)
{
Q_D(QAbstractSlider);
e->ignore();
- if (e->orientation() != d->orientation && !rect().contains(e->pos()))
- return;
int stepsToScroll = 0;
qreal offset = qreal(e->delta()) / 120;
--
cgit v0.12
From d950a35334dda4620a138914c8d8198da670b2dd Mon Sep 17 00:00:00 2001
From: Friedemann Kleint
Date: Thu, 4 Feb 2010 10:07:53 +0100
Subject: I10n: Use 'real' Linguist comments in Phonon::EnvironmentalReverb
Reviewed-by: Oswald Buddenhagen
---
src/3rdparty/phonon/mmf/environmentalreverb.cpp | 53 ++++++++++---------------
1 file changed, 22 insertions(+), 31 deletions(-)
diff --git a/src/3rdparty/phonon/mmf/environmentalreverb.cpp b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
index 4a6ce29..d4f5223 100644
--- a/src/3rdparty/phonon/mmf/environmentalreverb.cpp
+++ b/src/3rdparty/phonon/mmf/environmentalreverb.cpp
@@ -139,77 +139,68 @@ bool EnvironmentalReverb::getParameters(CMdaAudioOutputStream *stream,
TInt32 min, max;
TUint32 umin, umax;
- // DecayHFRatio
- // Ratio of high-frequency decay time to the value specified by
- // DecayTime.
effect->DecayHFRatioRange(umin, umax);
+ //: DecayHFRatio: Ratio of high-frequency decay time to the value specified by
+ //: DecayTime.
parameters.append(createParameter(
DecayHFRatio, tr("Decay HF ratio (%)"), effect->DecayHFRatio(),
umin, umax));
- // DecayTime
- // Time over which reverberation is diminished.
effect->DecayTimeRange(umin, umax);
+ //: DecayTime: Time over which reverberation is diminished.
parameters.append(createParameter(
DecayTime, tr("Decay time (ms)"), effect->DecayTime(),
umin, umax));
- // Density
- // Delay between first and subsequent reflections.
- // Note that the S60 platform documentation does not make clear
- // the distinction between this value and the Diffusion value.
+ //: Density Delay between first and subsequent reflections.
+ //: Note that the S60 platform documentation does not make clear
+ //: the distinction between this value and the Diffusion value.
parameters.append(createParameter(
Density, tr("Density (%)"), effect->Density(), 0, 100));
- // Diffusion
- // Delay between first and subsequent reflections.
- // Note that the S60 platform documentation does not make clear
- // the distinction between this value and the Density value.
+ //: Diffusion: Delay between first and subsequent reflections.
+ //: Note that the S60 platform documentation does not make clear
+ //: the distinction between this value and the Density value.
parameters.append(createParameter(
Diffusion, tr("Diffusion (%)"), effect->Diffusion(), 0, 100));
- // ReflectionsDelay
- // Amount of delay between the arrival the direct path from the
- // source and the arrival of the first reflection.
+ //: ReflectionsDelay: Amount of delay between the arrival the direct
+ //: path from the source and the arrival of the first reflection.
parameters.append(createParameter(
ReflectionsDelay, tr("Reflections delay (ms)"),
effect->ReflectionsDelay(), 0, effect->ReflectionsDelayMax()));
- // ReflectionsLevel
- // Amplitude of reflections. This value is corrected by the RoomLevel
- // to give the final reflection amplitude.
- effect->ReflectionLevelRange(min, max);
+ effect->ReflectionLevelRange(min, max);
+ //: ReflectionsLevel: Amplitude of reflections. This value is
+ //: corrected by the RoomLevel to give the final reflection amplitude.
parameters.append(createParameter(
ReflectionsLevel, tr("Reflections level (mB)"),
effect->ReflectionsLevel(),
min, max, EffectParameter::LogarithmicHint));
- // ReverbDelay
- // Amount of time between arrival of the first reflection and start of
- // the late reverberation.
+ //: ReverbDelay: Amount of time between arrival of the first
+ //: reflection and start of the late reverberation.
parameters.append(createParameter(
ReverbDelay, tr("Reverb delay (ms)"), effect->ReverbDelay(),
0, effect->ReverbDelayMax()));
- // ReverbLevel
- // Amplitude of reverberations. This value is corrected by the
- // RoomLevel to give the final reverberation amplitude.
effect->ReverbLevelRange(min, max);
+ //: ReverbLevel Amplitude of reverberations. This value is
+ //: corrected by the RoomLevel to give the final reverberation
+ //: amplitude.
parameters.append(createParameter(
ReverbLevel, tr("Reverb level (mB)"), effect->ReverbLevel(),
min, max, EffectParameter::LogarithmicHint));
- // RoomHFLevel
- // Amplitude of low-pass filter used to attenuate the high frequency
- // component of reflected sound.
effect->RoomHFLevelRange(min, max);
+ //: RoomHFLevel: Amplitude of low-pass filter used to attenuate the
+ //: high frequency component of reflected sound.
parameters.append(createParameter(
RoomHFLevel, tr("Room HF level"), effect->RoomHFLevel(),
min, max));
- // RoomLevel
- // Master volume control for all reflected sound.
effect->RoomLevelRange(min, max);
+ //: RoomLevel: Master volume control for all reflected sound.
parameters.append(createParameter(
RoomLevel, tr("Room level (mB)"), effect->RoomLevel(),
min, max, EffectParameter::LogarithmicHint));
--
cgit v0.12
From 3e6b22f138ad5b592dedbca99f91fdf612f20cea Mon Sep 17 00:00:00 2001
From: Friedemann Kleint
Date: Thu, 4 Feb 2010 10:08:54 +0100
Subject: I10n/German: Update translations for 4.6.2
---
translations/designer_de.ts | 45 ++--
translations/qt_de.ts | 533 +++++++++++++++++++++++++++++++++-----------
2 files changed, 436 insertions(+), 142 deletions(-)
diff --git a/translations/designer_de.ts b/translations/designer_de.ts
index b731595..8c1ba68 100644
--- a/translations/designer_de.ts
+++ b/translations/designer_de.ts
@@ -517,12 +517,12 @@
-
+
Move action
Aktion verschieben
-
+
Change Title
Titel ändern
@@ -1027,7 +1027,7 @@
FormBuilder
-
+
Invalid stretch value for '%1': '%2'
Parsing layout stretch values
Ungültiger Stretch-Wert für '%1': '%2'
@@ -1412,7 +1412,7 @@
Fehler beim Lesen der ui-Datei: Das Wurzelelement <ui> fehlt.
-
+
The creation of a widget of the class '%1' failed.
Es konnte kein Widget der Klasse '%1' erzeugt werden.
@@ -2273,7 +2273,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QFormBuilder
-
+
An empty class name was passed on to %1 (object name: '%2').
Empty class name passed to widget factory method
Der Methode %1 wurde ein leerer Klassennamen übergeben (Name '%2').
@@ -2313,6 +2313,16 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
The property %1 could not be written. The type %2 is not supported yet.
Die Eigenschaft %1 konnte nicht geschrieben werden, da der Typ %2 nicht unterstützt wird.
+
+
+ The enumeration-value '%1' is invalid. The default value '%2' will be used instead.
+ Der Aufzählungswert '%1' ist ungültig. Es wird der Vorgabewert '%2' verwendet.
+
+
+
+ The flag-value '%1' is invalid. Zero will be used instead.
+ Der Flag-Wert '%1' ist ungültig. Es wird der Wert 0 verwendet.
+
QStackedWidgetEventFilter
@@ -2446,7 +2456,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtBoolEdit
-
+
True
@@ -2475,7 +2485,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtCharEdit
-
+
Clear Char
Zeichen löschen
@@ -2491,7 +2501,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtColorPropertyManager
-
+
Red
Rot
@@ -2514,7 +2524,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtCursorDatabase
-
+
Arrow
Pfeil
@@ -3062,6 +3072,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtGradientViewDialog
+
Select Gradient
Gradienten auswählen
@@ -3069,7 +3080,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtKeySequenceEdit
-
+
Clear Shortcut
Tastenkürzel löschen
@@ -3131,7 +3142,7 @@ Container-Seiten sollten ausschließlich im XML der domXML()-Methode spezifizier
QtPropertyBrowserUtils
-
+
[%1, %2, %3] (%4)
[%1, %2, %3] (%4)
@@ -3904,7 +3915,7 @@ Möchten Sie sie überschreiben?
VersionDialog
-
+
<h3>%1</h3><br/><br/>Version %2
<h3>%1</h3><br/><br/>Version %2
@@ -4742,7 +4753,7 @@ Möchten Sie sie überschreiben?
Fehler beim Einfügen
-
+
Lay out
Layout
@@ -4753,7 +4764,7 @@ Möchten Sie sie überschreiben?
Widget einfügen
-
+
Paste %n action(s)
Eine Aktion einfügen
@@ -4794,12 +4805,12 @@ Möchten Sie sie überschreiben?
Übergeordnetes Widget auswählen
-
+
A QMainWindow-based form does not contain a central widget.
Ein auf QMainWindow basierendes Formular enthält kein zentrales Widget.
-
+
Raise widgets
Widgets nach vorn bringen
@@ -4825,7 +4836,7 @@ Möchten Sie sie überschreiben?
qdesigner_internal::FormWindowManager
-
+
Cu&t
&Ausschneiden
diff --git a/translations/qt_de.ts b/translations/qt_de.ts
index d916733..8cbf402 100644
--- a/translations/qt_de.ts
+++ b/translations/qt_de.ts
@@ -4,7 +4,7 @@
CloseButton
-
+
Close Tab
Schließen
@@ -12,7 +12,7 @@
FakeReply
-
+
Fake error !
Fake error !
@@ -143,7 +143,7 @@ Bitte überprüfen Sie Ihre GStreamer-Installation und stellen Sie sicher, dass
Phonon::MMF
-
+
Audio Output
Audio-Ausgabe
@@ -152,60 +152,333 @@ Bitte überprüfen Sie Ihre GStreamer-Installation und stellen Sie sicher, dass
The audio output device
Audio-Ausgabegerät
-
-
- Phonon::MMF::AudioEqualizer
-
- Frequency band, %1 Hz
- Frequenzband, %1 Hz
+
+ No error
+ Kein Fehler
-
-
- Phonon::MMF::EffectFactory
-
- Audio Equalizer
- Audio-Equalizer
+
+ Not found
+ Nicht gefunden
- Bass Boost
- Bass-Boost
+ Out of memory
+ Es ist kein Speicher mehr verfügbar
+
+
+
+ Not supported
+ Nicht unterstützt
+
+
+
+ Overflow
+ Ãœberlauf
+
+
+
+ Underflow
+ Unterlauf
+
+
+
+ Already exists
+ Existiert bereits
+
+
+
+ Path not found
+ Pfad konnte nicht gefunden werden
+
+
+
+ In use
+ Bereits in Verwendung
+
+
+
+ Not ready
+ Nicht bereit
+
+
+
+ Access denied
+ Zugriff verweigert
+
+
+
+ Could not connect
+ Es konnte keine Verbindung hergestellt werden
+
+
+
+ Disconnected
+ Getrennt
+
+
+
+ Permission denied
+ Zugriff verweigert
+
+
+
+ Insufficient bandwidth
+ Unzureichende Bandweite
+
+
+
+ Network unavailable
+ Netzwerk nicht verfügbar
+
+
+
+ Network communication error
+ Fehler bei der Kommunikation über das Netzwerk
- Distance Attenuation
- Abschwächung in Abhängigkeit von der Entfernung
+ Streaming not supported
+ Streaming nicht unterstützt
+ Server alert
+ Server alert
+
+
+
+ Invalid protocol
+ Ungültiges Protokoll
+
+
- Environmental Reverb
- Hall-Effekt der Umgebung
+ Invalid URL
+ Ungültige URL
- Loudness
- Lautstärke
+ Multicast error
+ Multicast-Fehler
+
+
+
+ Proxy server error
+ Fehler bei Proxy-Server-Kommunikation
- Source Orientation
- Ausrichtung der Quelle
+ Proxy server not supported
+ Proxy-Server nicht unterstützt
- Stereo Widening
- Stereo-Basisverbreiterung
+ Audio output error
+ Fehler bei Audio-Ausgabe
+
+
+
+ Video output error
+ Fehler bei Video-Ausgabe
+
+
+
+ Decoder error
+ Fehler im Decoder
+
+
+
+ Audio or video components could not be played
+ Audio- oder Videokomponenten konnten nicht abgespielt werden
+
+
+
+ DRM error
+ DRM-Fehler
+
+
+
+ Unknown error (%1)
+ Unbekannter Fehler (%1)
+
+
+
+ Phonon::MMF::AbstractMediaPlayer
+
+
+ Not ready to play
+ Das Abspielen ist im Grundzustand nicht möglich
+
+
+
+
+ Error opening file
+ Die Datei konnte nicht geöffnet werden
+
+
+
+ Error opening URL
+ Der URL konnte nicht geöffnet werden
+
+
+
+ Setting volume failed
+ Die Lautstärke konnte nicht eingestellt werden
+
+
+
+ Playback complete
+ Abspielen beendet
+
+
+
+ Phonon::MMF::AudioEqualizer
+
+
+ %1 Hz
+ %1 Hz
+
+
+
+ Phonon::MMF::AudioPlayer
+
+
+ Getting position failed
+ Die Position konnte nicht bestimmt werden
+
+
+
+ Opening clip failed
+ Der Clip konnte nicht geöffnet werden
+
+
+
+ Phonon::MMF::EffectFactory
+
+
+ Enabled
+ Aktiviert
+
+
+
+ Phonon::MMF::EnvironmentalReverb
+
+
+ Decay HF ratio (%)
+ DecayHFRatio: Ratio of high-frequency decay time to the value specified by DecayTime.
+ Hochfrequenz-Abklingverhältnis (%)
+
+
+
+ Decay time (ms)
+ Abklingzeit (ms)
+
+
+
+ Density (%)
+ Density Delay between first and subsequent reflections. Note that the S60 platform documentation does not make clear the distinction between this value and the Diffusion value.
+ Dichte (%)
+
+
+
+ Diffusion (%)
+ Diffusion: Delay between first and subsequent reflections. Note that the S60 platform documentation does not make clear the distinction between this value and the Density value.
+ Diffusion (%)
+
+
+
+ Reflections delay (ms)
+ ReflectionsDelay: Amount of delay between the arrival the direct path from the source and the arrival of the first reflection.
+ Verzögerung des Echos (ms)
+
+
+
+ Reflections level (mB)
+ ReflectionsLevel: Amplitude of reflections. This value is corrected by the RoomLevel to give the final reflection amplitude.
+ Stärke des Echos (mB)
+
+
+
+ Reverb delay (ms)
+ ReverbDelay: Amount of time between arrival of the first reflection and start of the late reverberation.
+ Verzögerung des Nachhalls (ms)
+
+
+
+ Reverb level (mB)
+ ReverbLevel Amplitude of reverberations. This value is corrected by the RoomLevel to give the final reverberation amplitude.
+ Stärke des Nachhalls (mB)
+
+
+
+ Room HF level
+ RoomHFLevel: Amplitude of low-pass filter used to attenuate the high frequency component of reflected sound.
+ Hochfrequenz-Pegel des Raums
+
+
+
+ Room level (mB)
+ RoomLevel: Master volume control for all reflected sound.
+ Pegel des Raums (mB)
Phonon::MMF::MediaObject
-
- Media type could not be determined
- Der Typ des Mediums konnte nicht bestimmt werden
+
+ Error opening source: type not supported
+ Die Quelle konnte nicht geöffnet werden: Dieser Typ wird nicht unterstützt
+
+
+
+ Error opening source: media type could not be determined
+ Die Quelle konnte nicht geöffnet werden: Der Medientyp konnte nicht bestimmt werden
+
+
+
+ Phonon::MMF::StereoWidening
+
+
+ Level (%)
+ Stärke (%)
+
+
+
+ Phonon::MMF::VideoPlayer
+
+
+ Pause failed
+ Fehler bei Pause-Funktion
+
+
+
+ Seek failed
+ Suchoperation fehlgeschlagen
+
+
+
+ Getting position failed
+ Die Position konnte nicht bestimmt werden
+
+
+
+ Opening clip failed
+ Der Clip konnte nicht geöffnet werden
+
+
+
+ Buffering clip failed
+ Fehler beim Puffern des Clips
+
+
+
+
+
+
+
+ Video display error
+ Fehler bei der Video-Anzeige
@@ -275,7 +548,7 @@ Bitte überprüfen Sie Ihre GStreamer-Installation und stellen Sie sicher, dass
Q3FileDialog
-
+
Copy or Move a File
Datei kopieren oder verschieben
@@ -300,7 +573,7 @@ Bitte überprüfen Sie Ihre GStreamer-Installation und stellen Sie sicher, dass
-
+
All Files (*)
Alle Dateien (*)
@@ -912,8 +1185,8 @@ nach
QAbstractSocket
-
-
+
+
Host not found
@@ -932,19 +1205,20 @@ nach
Das Zeitlimit für die Verbindung wurde überschritten
-
-
+
+
Operation on socket is not supported
Diese Socket-Operation wird nicht unterstützt
-
+
+
Socket operation timed out
Das Zeitlimit für die Operation wurde überschritten
-
+
Socket is not connected
Nicht verbunden
@@ -957,7 +1231,7 @@ nach
QAbstractSpinBox
-
+
&Step up
&Inkrementieren
@@ -983,7 +1257,7 @@ nach
QApplication
-
+
QT_LAYOUT_DIRECTION
Translate this string to the string 'LTR' in left-to-right languages or to 'RTL' in right-to-left languages (such as Hebrew and Arabic) to get proper widget layout.
LTR
@@ -1053,7 +1327,7 @@ nach
QColorDialog
-
+
Hu&e:
Farb&ton:
@@ -1093,7 +1367,7 @@ nach
Farbauswahl
-
+
&Basic colors
Grundfar&ben
@@ -1180,7 +1454,7 @@ nach
QDB2Driver
-
+
Unable to connect
Es kann keine Verbindung aufgebaut werden
@@ -1203,7 +1477,7 @@ nach
QDB2Result
-
+
Unable to execute statement
Der Befehl kann nicht ausgeführt werden
@@ -1278,7 +1552,7 @@ nach
QDialog
-
+
What's This?
Direkthilfe
@@ -1291,9 +1565,9 @@ nach
QDialogButtonBox
-
+
-
+
OK
OK
@@ -1505,7 +1779,7 @@ nach
QFile
-
+
Destination file exists
Die Zieldatei existiert bereits
@@ -1545,7 +1819,7 @@ nach
QFileDialog
-
+
All Files (*)
Alle Dateien (*)
@@ -1568,13 +1842,13 @@ nach
Details
-
+
File
Datei
-
+
Open
Öffnen
@@ -1584,25 +1858,25 @@ nach
Speichern unter
-
-
-
+
+
+
&Open
&Öffnen
-
-
+
+
&Save
S&peichern
-
+
Recent Places
Zuletzt besucht
-
+
&Rename
&Umbenennen
@@ -1617,17 +1891,17 @@ nach
&Versteckte Dateien anzeigen
-
+
New Folder
Neues Verzeichnis
-
+
Find Directory
Verzeichnis suchen
-
+
Directories
Verzeichnisse
@@ -1637,13 +1911,13 @@ nach
Alle Dateien (*.*)
-
-
+
+
Directory:
Verzeichnis:
-
+
%1 already exists.
Do you want to replace it?
Die Datei %1 existiert bereits.
@@ -1737,7 +2011,7 @@ Möchten Sie die Datei trotzdem löschen?
Unbekannt
-
+
Show
Anzeigen
@@ -1753,8 +2027,8 @@ Möchten Sie die Datei trotzdem löschen?
&Neues Verzeichnis
-
-
+
+
&Choose
&Auswählen
@@ -1764,8 +2038,8 @@ Möchten Sie die Datei trotzdem löschen?
Löschen
-
-
+
+
File &name:
Datei&name:
@@ -2286,7 +2560,7 @@ Möchten Sie die Datei trotzdem löschen?
QHostInfo
-
+
Unknown error
Unbekannter Fehler
@@ -2296,7 +2570,7 @@ Möchten Sie die Datei trotzdem löschen?
-
+
Host not found
Rechner konnte nicht gefunden werden
@@ -2330,7 +2604,7 @@ Möchten Sie die Datei trotzdem löschen?
QHttp
-
+
Connection refused
Verbindung verweigert
@@ -2350,8 +2624,6 @@ Möchten Sie die Datei trotzdem löschen?
-
-
HTTP request failed
HTTP-Anfrage fehlgeschlagen
@@ -2382,7 +2654,7 @@ Möchten Sie die Datei trotzdem löschen?
Verbindung mit %1 beendet
-
+
Connection closed
Verbindung beendet
@@ -2647,7 +2919,7 @@ Möchten Sie die Datei trotzdem löschen?
QIODevice
-
+
Permission denied
Zugriff verweigert
@@ -2667,7 +2939,7 @@ Möchten Sie die Datei trotzdem löschen?
Kein freier Speicherplatz auf dem Gerät vorhanden
-
+
Unknown error
Unbekannter Fehler
@@ -2731,7 +3003,7 @@ Möchten Sie die Datei trotzdem löschen?
Operation unmap fehlgeschlagen für '%1': %2
-
+
The plugin '%1' uses incompatible Qt library. (%2.%3.%4) [%5]
Das Plugin '%1' verwendet eine inkompatible Qt-Bibliothek. (%2.%3.%4) [%5]
@@ -2783,12 +3055,12 @@ Möchten Sie die Datei trotzdem löschen?
QLineEdit
-
+
Select All
Alles auswählen
-
+
&Undo
&Rückgängig
@@ -2798,22 +3070,22 @@ Möchten Sie die Datei trotzdem löschen?
Wieder&herstellen
-
+
Cu&t
&Ausschneiden
-
+
&Copy
&Kopieren
-
+
&Paste
Einf&ügen
-
+
Delete
Löschen
@@ -2916,7 +3188,7 @@ Möchten Sie die Datei trotzdem löschen?
QMYSQLDriver
-
+
Unable to open database '
Die Datenbankverbindung kann nicht geöffnet werden '
@@ -2926,7 +3198,7 @@ Möchten Sie die Datei trotzdem löschen?
Es kann keine Verbindung aufgebaut werden
-
+
Unable to begin transaction
Es kann keine Transaktion gestartet werden
@@ -2944,12 +3216,13 @@ Möchten Sie die Datei trotzdem löschen?
QMYSQLResult
-
+
+
Unable to fetch data
Es konnten keine Daten abgeholt werden
-
+
Unable to execute query
Die Abfrage konnte nicht ausgeführt werden
@@ -3127,7 +3400,7 @@ Möchten Sie die Datei trotzdem löschen?
QMenuBar
-
+
Actions
Optionen
@@ -3163,7 +3436,7 @@ Möchten Sie die Datei trotzdem löschen?
Hilfe
-
+
Show Details...
Details einblenden...
@@ -3346,13 +3619,13 @@ Möchten Sie die Datei trotzdem löschen?
QNetworkAccessFileBackend
-
+
Request for opening non-local file %1
Anforderung zum Öffnen einer Datei über Netzwerk %1
-
+
Error opening %1: %2
%1 konnte nicht geöffnet werden: %2
@@ -3363,7 +3636,7 @@ Möchten Sie die Datei trotzdem löschen?
Fehler beim Schreiben zur Datei %1: %2
-
+
Cannot open %1: Path is a directory
%1 kann nicht geöffnet werden: Der Pfad spezifiziert ein Verzeichnis
@@ -3405,7 +3678,7 @@ Möchten Sie die Datei trotzdem löschen?
QNetworkAccessHttpBackend
-
+
No suitable proxy found
Es konnte kein geeigneter Proxy-Server gefunden werden
@@ -3413,12 +3686,12 @@ Möchten Sie die Datei trotzdem löschen?
QNetworkReply
-
+
Error downloading %1 - server replied: %2
Beim Herunterladen von %1 trat ein Fehler auf - Die Antwort des Servers ist: %2
-
+
Protocol "%1" is unknown
Das Protokoll "%1" ist unbekannt
@@ -3426,7 +3699,7 @@ Möchten Sie die Datei trotzdem löschen?
QNetworkReplyImpl
-
+
Operation canceled
Operation abgebrochen
@@ -3509,7 +3782,7 @@ Möchten Sie die Datei trotzdem löschen?
QODBCDriver
-
+
Unable to connect
Es kann keine Verbindung aufgebaut werden
@@ -3542,14 +3815,14 @@ Möchten Sie die Datei trotzdem löschen?
QODBCResult
-
-
+
+
QODBCResult::reset: Unable to set 'SQL_CURSOR_STATIC' as statement attribute. Please check your ODBC driver configuration
QODBCResult::reset: 'SQL_CURSOR_STATIC' konnte nicht als Attribut des Befehls gesetzt werden. Bitte prüfen Sie die Konfiguration Ihres ODBC-Treibers
-
-
+
+
Unable to execute statement
Der Befehl konnte nicht ausgeführt werden
@@ -3569,7 +3842,7 @@ Möchten Sie die Datei trotzdem löschen?
Die Variable konnte nicht gebunden werden
-
+
Unable to fetch last
@@ -3619,7 +3892,7 @@ Möchten Sie die Datei trotzdem löschen?
Der entfernte Rechner hat die Verbindung zu %1 vorzeitig beendet
-
+
No host name given
Es wurde kein Hostname angegeben
@@ -3803,7 +4076,7 @@ Möchten Sie die Datei trotzdem löschen?
QPrintDialog
-
+
locally connected
direkt verbunden
@@ -4232,12 +4505,12 @@ Bitte wählen Sie einen anderen Dateinamen.
QPrintPreviewDialog
-
+
%1%
%1%
-
+
Print Preview
Druckvorschau
@@ -4317,7 +4590,12 @@ Bitte wählen Sie einen anderen Dateinamen.
Seite einrichten
-
+
+ Close
+ Schließen
+
+
+
Export to PDF
PDF exportieren
@@ -4530,7 +4808,7 @@ Bitte wählen Sie einen anderen Dateinamen.
Zeitüberschreitung
-
+
@@ -4645,7 +4923,7 @@ Bitte wählen Sie einen anderen Dateinamen.
QSQLite2Driver
-
+
Error opening database
Die Datenbankverbindung konnte nicht geöffnet werden
@@ -4668,12 +4946,12 @@ Bitte wählen Sie einen anderen Dateinamen.
QSQLite2Result
-
+
Unable to fetch results
Das Ergebnis konnte nicht abgeholt werden
-
+
Unable to execute statement
Der Befehl konnte nicht ausgeführt werden
@@ -4681,7 +4959,7 @@ Bitte wählen Sie einen anderen Dateinamen.
QSQLiteDriver
-
+
Error opening database
Die Datenbankverbindung konnte nicht geöffnet werden
@@ -5184,7 +5462,7 @@ Bitte wählen Sie einen anderen Dateinamen.
-
+
%1: permission denied
%1: Zugriff verweigert
@@ -6150,7 +6428,7 @@ Bitte wählen Sie einen anderen Dateinamen.
Umdrehen
-
+
Ctrl
Strg
@@ -6184,7 +6462,7 @@ Bitte wählen Sie einen anderen Dateinamen.
F%1
-
+
Home Page
Startseite
@@ -6293,7 +6571,7 @@ Bitte wählen Sie einen anderen Dateinamen.
QSoftKeyManager
-
+
Ok
Ok
@@ -6318,7 +6596,7 @@ Bitte wählen Sie einen anderen Dateinamen.
Abbrechen
-
+
Exit
Beenden
@@ -6401,7 +6679,12 @@ Bitte wählen Sie einen anderen Dateinamen.
Die Daten konnten nicht geschrieben werden: %1
-
+
+ Unable to decrypt data: %1
+ Die Daten konnten nicht entschlüsselt werden: %1
+
+
+
Error while reading: %1
Beim Lesen ist ein Fehler aufgetreten: %1
@@ -6411,7 +6694,7 @@ Bitte wählen Sie einen anderen Dateinamen.
Im Ablauf des SSL-Protokolls ist ein Fehler aufgetreten: %1
-
+
Error creating SSL context (%1)
Es konnte keine SSL-Kontextstruktur erzeugt werden (%1)
@@ -6657,7 +6940,7 @@ Bitte wählen Sie einen anderen Dateinamen.
QTextControl
-
+
&Undo
&Rückgängig
@@ -7375,7 +7658,7 @@ Bitte wählen Sie einen anderen Dateinamen.
%1 (%2x%3 Pixel)
-
+
Bad HTTP request
Ungültige HTTP-Anforderung
@@ -7460,7 +7743,7 @@ Bitte wählen Sie einen anderen Dateinamen.
-
+
JavaScript Alert - %1
JavaScript-Hinweis - %1
@@ -7470,7 +7753,7 @@ Bitte wählen Sie einen anderen Dateinamen.
JavaScript-Bestätigung - %1
-
+
JavaScript Prompt - %1
JavaScript-Eingabeaufforderung - %1
@@ -7706,7 +7989,7 @@ Bitte wählen Sie einen anderen Dateinamen.
QWidget
-
+
*
*
--
cgit v0.12
From 04e34fe3aecca482abeeabe2e31778e9102eeb08 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?=
Date: Mon, 18 Jan 2010 09:14:12 +0100
Subject: Improve raster graphics system performance on Mac (second try).
This fixes the qmlviewer "sluggish animations and lost
mouse events" issue by making sure we don't block and
wait for for the screen refresh when flushing the
backing store to the screen.
NB: This commit fixes build issues found in f5f62c0bed.
Review: msorvig
Details:
- Don't force repaints, flush the backingstore in response
to a Cocoa paint/display events only.
- Flush once per window.
- Get the CGContext from the window (don't create a new one)
- Don't call CGContextiFlush on the context.
---
src/gui/kernel/qcocoapanel_mac.mm | 3 +++
src/gui/kernel/qcocoasharedwindowmethods_mac_p.h | 20 ++++++++++++++++++++
src/gui/kernel/qcocoaview_mac.mm | 9 +++++----
src/gui/kernel/qcocoawindow_mac_p.h | 3 +++
src/gui/kernel/qt_cocoa_helpers_mac.mm | 2 +-
src/gui/kernel/qwidget.cpp | 15 ++++++++++++++-
src/gui/kernel/qwidget_mac.mm | 19 +++++++++++++++++++
src/gui/painting/qwindowsurface_raster.cpp | 4 +---
8 files changed, 66 insertions(+), 9 deletions(-)
diff --git a/src/gui/kernel/qcocoapanel_mac.mm b/src/gui/kernel/qcocoapanel_mac.mm
index e535aac..5e24c84 100644
--- a/src/gui/kernel/qcocoapanel_mac.mm
+++ b/src/gui/kernel/qcocoapanel_mac.mm
@@ -46,6 +46,9 @@
#import
#import
#import
+#include
+#include
+
#include
diff --git a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
index 1a265d0..d2b74d7 100644
--- a/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
+++ b/src/gui/kernel/qcocoasharedwindowmethods_mac_p.h
@@ -51,6 +51,9 @@
NSPanel, while QCocoaWindow needs to inherit NSWindow rather than NSPanel).
****************************************************************************/
+// WARNING: Don't include any header files from within this file. Put them
+// directly into qcocoawindow_mac_p.h and qcocoapanel_mac_p.h
+
QT_BEGIN_NAMESPACE
extern Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); // qcocoaview.mm
extern QPointer qt_button_down; //qapplication_mac.cpp
@@ -185,3 +188,20 @@ QT_END_NAMESPACE
return [super frameViewClassForStyleMask:styleMask];
}
+- (void)displayIfNeeded
+{
+
+ QWidget *qwidget = [[QT_MANGLE_NAMESPACE(QCocoaWindowDelegate) sharedDelegate] qt_qwidgetForWindow:self];
+ if (qwidget == 0) {
+ [super displayIfNeeded];
+ return;
+ }
+
+ if (QApplicationPrivate::graphicsSystem() != 0) {
+ if (QWidgetBackingStore *bs = qt_widget_private(qwidget)->maybeBackingStore())
+ bs->sync(qwidget, qwidget->rect());
+ }
+ [super displayIfNeeded];
+}
+
+
diff --git a/src/gui/kernel/qcocoaview_mac.mm b/src/gui/kernel/qcocoaview_mac.mm
index d255604..2c35be2 100644
--- a/src/gui/kernel/qcocoaview_mac.mm
+++ b/src/gui/kernel/qcocoaview_mac.mm
@@ -520,10 +520,11 @@ extern "C" {
- (void)drawRect:(NSRect)aRect
{
if (QApplicationPrivate::graphicsSystem() != 0) {
- if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore())
- bs->markDirty(qwidget->rect(), qwidget);
- qwidgetprivate->syncBackingStore(qwidget->rect());
- return;
+ if (QWidgetBackingStore *bs = qwidgetprivate->maybeBackingStore()) {
+ // Drawing is handled on the window level
+ // See qcocoasharedwindowmethods_mac_p.
+ return;
+ }
}
CGContextRef cg = (CGContextRef)[[NSGraphicsContext currentContext] graphicsPort];
qwidgetprivate->hd = cg;
diff --git a/src/gui/kernel/qcocoawindow_mac_p.h b/src/gui/kernel/qcocoawindow_mac_p.h
index c0d8252..0474882 100644
--- a/src/gui/kernel/qcocoawindow_mac_p.h
+++ b/src/gui/kernel/qcocoawindow_mac_p.h
@@ -53,6 +53,9 @@
#ifdef QT_MAC_USE_COCOA
#include "qmacdefines_mac.h"
#import
+#include
+#include
+
enum { QtMacCustomizeWindow = 1 << 21 }; // This will one day be run over by
diff --git a/src/gui/kernel/qt_cocoa_helpers_mac.mm b/src/gui/kernel/qt_cocoa_helpers_mac.mm
index e06a810..65c04e5 100644
--- a/src/gui/kernel/qt_cocoa_helpers_mac.mm
+++ b/src/gui/kernel/qt_cocoa_helpers_mac.mm
@@ -1162,7 +1162,7 @@ CGContextRef qt_mac_graphicsContextFor(QWidget *widget)
CGrafPtr port = GetWindowPort(qt_mac_window_for(widget));
QDBeginCGContext(port, &context);
#else
- CGContextRef context = (CGContextRef)[[NSGraphicsContext graphicsContextWithWindow:qt_mac_window_for(widget)] graphicsPort];
+ CGContextRef context = reinterpret_cast([[qt_mac_window_for(widget) graphicsContext] graphicsPort]);
#endif
return context;
}
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index ffad38b..78a25ac 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1660,7 +1660,13 @@ void QWidgetPrivate::syncBackingStore()
repaint_sys(dirty);
dirty = QRegion();
} else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+#ifdef QT_MAC_USE_COCOA
+ Q_UNUSED(bs);
+ void qt_mac_set_needs_display(QWidget *, QRegion);
+ qt_mac_set_needs_display(q_func(), QRegion());
+#else
bs->sync();
+#endif
}
}
@@ -1668,8 +1674,15 @@ void QWidgetPrivate::syncBackingStore(const QRegion ®ion)
{
if (paintOnScreen())
repaint_sys(region);
- else if (QWidgetBackingStore *bs = maybeBackingStore())
+ else if (QWidgetBackingStore *bs = maybeBackingStore()) {
+#ifdef QT_MAC_USE_COCOA
+ Q_UNUSED(bs);
+ void qt_mac_set_needs_display(QWidget *, QRegion);
+ qt_mac_set_needs_display(q_func(), region);
+#else
bs->sync(q_func(), region);
+#endif
+ }
}
void QWidgetPrivate::setUpdatesEnabled_helper(bool enable)
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index 78c1562..b5888b4 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -565,6 +565,25 @@ inline static void qt_mac_set_window_group_to_popup(OSWindowRef window)
}
#endif
+#ifdef QT_MAC_USE_COCOA
+void qt_mac_set_needs_display(QWidget *widget, QRegion region)
+{
+ NSView *theNSView = qt_mac_nativeview_for(widget);
+ if (region.isNull()) {
+ [theNSView setNeedsDisplay:YES];
+ return;
+ }
+
+ QVector rects = region.rects();
+ for (int i = 0; i
Date: Thu, 4 Feb 2010 10:26:27 +0100
Subject: Change log updated
---
dist/changes-4.6.2 | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 00509ed..f80c526 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -120,7 +120,7 @@ Third party components
Qt for Unix (X11 and Mac OS X)
------------------------------
- -
+ -
Qt for Linux/X11
----------------
@@ -141,6 +141,9 @@ Qt for Mac OS X
- [QTBUG-7312]: Menubar and dock disappear after hiding a fullscreen widget on Cocoa.
- [QTBUG-7522]: Drawing fake buttons using QMacStyle+QStyleOptionViewItemV4 lead to crash.
- [QTBUG-7625]: Calling showFullScreen() then showNormal() on a widget results in top menu hiding.
+ - [QTBUG-7086]: QFileDialog now correctly responds to fileMode & acceptMode changes.
+ - [QTBUG-7162]: Fixed a crash in Designer when previewing a QMainWindow with native toolbar.
+ - [QTBUG-7305]: Fixed a crash when deleting QMainWindow with native toolbar on Cocoa.
Qt for Embedded Linux
--
cgit v0.12
From 88a3be84f9a1cb235a8e3a9b25df7763646166b6 Mon Sep 17 00:00:00 2001
From: Jens Bache-Wiig
Date: Thu, 4 Feb 2010 10:32:55 +0100
Subject: Add some entries to the change log
---
dist/changes-4.6.2 | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index f80c526..65c07cb 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -51,6 +51,8 @@ QtGui
* [QTBUG-7029] Fixed a crash when re-creating QApplication object due to a
dangling gesture manager pointer.
+ * [QTBUG-7198] Setting a style sheet could break the checkbox position in item views.
+
QtDBus
------
@@ -130,21 +132,25 @@ Qt for Linux/X11
* Fixed a crash when an input method tries to create a widget after the
application is destroyed.
+ - [QTBUG-6952] Fixed a problem using NoButtons in spinbox with QGtkStyle
+ - [QTBUG-7504] Fixed missing focus rect on check- and radiobutton with
+ some GTK+ themes.
+ - [QTBUG-6522] Fixed missing menu separator in some GTK+ themes.
+
Qt for Windows
--------------
- -
-
Qt for Mac OS X
---------------
+ - [QTBUG-7832]: Restored missing margins around non-unified toolbars.
- [QTBUG-7312]: Menubar and dock disappear after hiding a fullscreen widget on Cocoa.
- [QTBUG-7522]: Drawing fake buttons using QMacStyle+QStyleOptionViewItemV4 lead to crash.
- [QTBUG-7625]: Calling showFullScreen() then showNormal() on a widget results in top menu hiding.
- [QTBUG-7086]: QFileDialog now correctly responds to fileMode & acceptMode changes.
- [QTBUG-7162]: Fixed a crash in Designer when previewing a QMainWindow with native toolbar.
- [QTBUG-7305]: Fixed a crash when deleting QMainWindow with native toolbar on Cocoa.
-
+ - [QTBUG-6882]: Fixed a text layout issue with QHeaderView in right-to-left mode.
Qt for Embedded Linux
---------------------
--
cgit v0.12
From 26b696f9333147218bb7dca0abdf0e5f321763f9 Mon Sep 17 00:00:00 2001
From: Morten Engvoldsen
Date: Thu, 4 Feb 2010 11:18:49 +0100
Subject: Doc: Removed promisse to fix a problem The problem is out of scope
and will not be fixed.
Task-number:QTBUG-4377
Reviewed-by:Trust Me
---
src/gui/widgets/qtoolbar.cpp | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/gui/widgets/qtoolbar.cpp b/src/gui/widgets/qtoolbar.cpp
index 53050ac..8beda55 100644
--- a/src/gui/widgets/qtoolbar.cpp
+++ b/src/gui/widgets/qtoolbar.cpp
@@ -441,8 +441,7 @@ void QToolBarPrivate::plug(const QRect &r)
When a QToolBar is not a child of a QMainWindow, it looses the ability
to populate the extension pop up with widgets added to the toolbar using
addWidget(). Please use widget actions created by inheriting QWidgetAction
- and implementing QWidgetAction::createWidget() instead. This is a known
- issue which will be fixed in a future release.
+ and implementing QWidgetAction::createWidget() instead.
\sa QToolButton, QMenu, QAction, {Application Example}
*/
--
cgit v0.12
From 3569038ffec0c133ff29f80d506f334cc0f2ddb3 Mon Sep 17 00:00:00 2001
From: Iain
Date: Thu, 4 Feb 2010 10:29:34 +0000
Subject: Further bug fixes for enable/disables DEF files mechanism on Symbian
Fix bug where all target types, including apps, plugins and static
libraries were getting DEFFILE statements - now it's just libraries that
get it.
Fix bug where duplicate DEFFILE blocks were being added to projects that
manually specified their own DEFFILE - this now tests for the qmake
variable "defBlock" being set, and doesn't add additional DEFFILE
statements if it is.
NOTE: This means that adding DEFFILE statements to MMP_RULES
manually should be done by creating a variable called defBlock, and
adding that to the MMP_RULES (ie. MMP_RULES += defBlock)
Fix bug in configure.exe, where using -nokia-developer for Windows builds
would warn about Symbian DEF file usage (or lack thereof)
Reviewed-by: Janne Koskinen
Reviewed-by: Jason Barron
---
configure.exe | Bin 1178112 -> 1180160 bytes
mkspecs/features/symbian/def_files.prf | 48 ++++++++++++++----------
mkspecs/features/symbian/def_files_disabled.prf | 12 ++++--
tools/configure/configureapp.cpp | 4 +-
4 files changed, 40 insertions(+), 24 deletions(-)
diff --git a/configure.exe b/configure.exe
index 21fdcfa..8913de1 100644
Binary files a/configure.exe and b/configure.exe differ
diff --git a/mkspecs/features/symbian/def_files.prf b/mkspecs/features/symbian/def_files.prf
index c29d4ec..48d91aa 100644
--- a/mkspecs/features/symbian/def_files.prf
+++ b/mkspecs/features/symbian/def_files.prf
@@ -3,24 +3,32 @@
CONFIG -= def_files_disabled
-!isEmpty(defFilePath) {
- defBlock = \
- "$${LITERAL_HASH}ifdef WINSCW" \
- "DEFFILE $$defFilePath/bwins/$${TARGET}.def" \
- "$${LITERAL_HASH}elif defined EABI" \
- "DEFFILE $$defFilePath/eabi/$${TARGET}.def" \
- "$${LITERAL_HASH}endif"
-
- MMP_RULES += defBlock
-} else {
- # If defFilePath is not defined, then put the folders containing the DEF files at the
- # same level as the .pro (and generated MMP) file(s)
- defBlock = \
- "$${LITERAL_HASH}ifdef WINSCW" \
- "DEFFILE ./bwins/$${TARGET}.def" \
- "$${LITERAL_HASH}elif defined EABI" \
- "DEFFILE ./eabi/$${TARGET}.def" \
- "$${LITERAL_HASH}endif"
-
- MMP_RULES += defBlock
+# Firstly, if the MMP_RULES already contain a defBlock variable, don't generate another one
+# (this bit is slightly magic, because it depends upon everyone creating their DEFFILE statements
+# in a defBlock variable; but otherwise we have to expand MMP_RULES then scan for the DEFFILE keyword)
+!contains(MMP_RULES, defBlock) {
+ # Apps are executables on Symbian, so don't have exports, and therefore don't have DEF files
+ # Plugins use standard DEF files, which qmake generates, so shouldn't be using these DEFFILE
+ # statements - they use the qmake generated statements instead
+ # Static libraries obviously don't have DEF files, as they don't take part in dynamic linkage
+ !contains(TEMPLATE, app):!contains(CONFIG, plugin):!contains(CONFIG, staticlib): {
+ !isEmpty(defFilePath) {
+ defBlock = \
+ "$${LITERAL_HASH}ifdef WINSCW" \
+ "DEFFILE $$defFilePath/bwins/$${TARGET}.def" \
+ "$${LITERAL_HASH}elif defined EABI" \
+ "DEFFILE $$defFilePath/eabi/$${TARGET}.def" \
+ "$${LITERAL_HASH}endif"
+ } else {
+ # If defFilePath is not defined, then put the folders containing the DEF files at the
+ # same level as the .pro (and generated MMP) file(s)
+ defBlock = \
+ "$${LITERAL_HASH}ifdef WINSCW" \
+ "DEFFILE ./bwins/$${TARGET}.def" \
+ "$${LITERAL_HASH}elif defined EABI" \
+ "DEFFILE ./eabi/$${TARGET}.def" \
+ "$${LITERAL_HASH}endif"
+ }
+ MMP_RULES += defBlock
+ }
}
diff --git a/mkspecs/features/symbian/def_files_disabled.prf b/mkspecs/features/symbian/def_files_disabled.prf
index d5c9505..557c5e3 100644
--- a/mkspecs/features/symbian/def_files_disabled.prf
+++ b/mkspecs/features/symbian/def_files_disabled.prf
@@ -2,6 +2,12 @@
CONFIG -= def_files
-# with EXPORTUNFROZEN enabled, new exports are included in the dll without
-# needing to run abld/sbs freeze
-MMP_RULES += EXPORTUNFROZEN
+# See def_files.prf for reasoning on the slight nastiness of this
+!contains(MMP_RULES, defBlock) {
+ # See def_files.prf for reasoning for excluding target types and configs below
+ !contains(TEMPLATE, app):!contains(CONFIG, plugin):!contains(CONFIG, staticlib): {
+ # with EXPORTUNFROZEN enabled, new exports are included in the dll and dso/lib without
+ # needing to run abld/sbs freeze
+ MMP_RULES += EXPORTUNFROZEN
+ }
+}
diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp
index 8d1b640..83b4d9c 100644
--- a/tools/configure/configureapp.cpp
+++ b/tools/configure/configureapp.cpp
@@ -482,7 +482,9 @@ void Configure::parseCmdLine()
dictionary[ "BUILDNOKIA" ] = "yes";
dictionary[ "BUILDDEV" ] = "yes";
dictionary["LICENSE_CONFIRMED"] = "yes";
- dictionary[ "SYMBIAN_DEFFILES" ] = "no";
+ if (dictionary.contains("XQMAKESPEC") && dictionary["XQMAKESPEC"].startsWith("symbian")) {
+ dictionary[ "SYMBIAN_DEFFILES" ] = "no";
+ }
}
else if( configCmdLine.at(i) == "-opensource" ) {
dictionary[ "BUILDTYPE" ] = "opensource";
--
cgit v0.12
From 6d1d425e219b0a5e03603f7d708cd740b7d3a3f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Trond=20Kjern=C3=A5sen?=
Date: Thu, 4 Feb 2010 11:44:44 +0100
Subject: Cache the sizes of the images in an animated GIF.
Rework the previous commit a bit and include caching of image sizes.
Task-number: QTBUG-6696
Reviewed-by: Kim
---
src/plugins/imageformats/gif/qgifhandler.cpp | 85 ++++++++++++++++++----------
src/plugins/imageformats/gif/qgifhandler.h | 4 +-
tests/auto/qimagereader/tst_qimagereader.cpp | 1 +
3 files changed, 59 insertions(+), 31 deletions(-)
diff --git a/src/plugins/imageformats/gif/qgifhandler.cpp b/src/plugins/imageformats/gif/qgifhandler.cpp
index 6cd7841..6d473e3 100644
--- a/src/plugins/imageformats/gif/qgifhandler.cpp
+++ b/src/plugins/imageformats/gif/qgifhandler.cpp
@@ -71,8 +71,8 @@ public:
~QGIFFormat();
int decode(QImage *image, const uchar* buffer, int length,
- int *nextFrameDelay, int *loopCount, QSize *nextSize);
- static int imageCount(QIODevice *device);
+ int *nextFrameDelay, int *loopCount);
+ static void scan(QIODevice *device, QVector *imageSizes);
bool newFrame;
bool partialNewFrame;
@@ -230,7 +230,7 @@ void QGIFFormat::disposePrevious(QImage *image)
Returns the number of bytes consumed.
*/
int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
- int *nextFrameDelay, int *loopCount, QSize *nextSize)
+ int *nextFrameDelay, int *loopCount)
{
// We are required to state that
// "The Graphics Interchange Format(c) is the Copyright property of
@@ -347,10 +347,6 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
bpl = image->bytesPerLine();
bits = image->bits();
memset(bits, 0, image->byteCount());
-
- // ### size of the upcoming frame, should rather
- // be known before decoding it.
- *nextSize = QSize(swidth, sheight);
}
disposePrevious(image);
@@ -647,17 +643,17 @@ int QGIFFormat::decode(QImage *image, const uchar *buffer, int length,
}
/*!
- Returns the number of images that can be read from \a device.
+ Scans through the data stream defined by \a device and returns the image
+ sizes found in the stream in the \a imageSizes vector.
*/
-
-int QGIFFormat::imageCount(QIODevice *device)
+void QGIFFormat::scan(QIODevice *device, QVector *imageSizes)
{
if (!device)
- return 0;
+ return;
qint64 oldPos = device->pos();
if (!device->seek(0))
- return 0;
+ return;
int colorCount = 0;
int localColorCount = 0;
@@ -667,18 +663,21 @@ int QGIFFormat::imageCount(QIODevice *device)
bool globalColormap = false;
int count = 0;
int blockSize = 0;
+ int imageWidth = 0;
+ int imageHeight = 0;
bool done = false;
uchar hold[16];
- int imageCount = 0;
State state = Header;
const int readBufferSize = 40960; // 40k read buffer
QByteArray readBuffer(device->read(readBufferSize));
- if (readBuffer.isEmpty())
- return 0;
+ if (readBuffer.isEmpty()) {
+ device->seek(oldPos);
+ return;
+ }
- // this is a specialized version of the state machine from decode(),
+ // This is a specialized version of the state machine from decode(),
// which doesn't do any image decoding or mallocing, and has an
// optimized way of skipping SkipBlocks, ImageDataBlocks and
// Global/LocalColorMaps.
@@ -700,6 +699,8 @@ int QGIFFormat::imageCount(QIODevice *device)
case LogicalScreenDescriptor:
hold[count++] = ch;
if (count == 7) {
+ imageWidth = LM(hold[0], hold[1]);
+ imageHeight = LM(hold[2], hold[3]);
globalColormap = !!(hold[4] & 0x80);
globalColorCount = 2 << (hold[4] & 0x7);
count = 0;
@@ -753,13 +754,29 @@ int QGIFFormat::imageCount(QIODevice *device)
case ImageDescriptor:
hold[count++] = ch;
if (count == 10) {
+ int newLeft = LM(hold[1], hold[2]);
+ int newTop = LM(hold[3], hold[4]);
+ int newWidth = LM(hold[5], hold[6]);
+ int newHeight = LM(hold[7], hold[8]);
+
+ if (imageWidth/10 > qMax(newWidth,200))
+ imageWidth = -1;
+ if (imageHeight/10 > qMax(newHeight,200))
+ imageHeight = -1;
+
+ if (imageWidth <= 0)
+ imageWidth = newLeft + newWidth;
+ if (imageHeight <= 0)
+ imageHeight = newTop + newHeight;
+
+ *imageSizes << QSize(imageWidth, imageHeight);
+
localColormap = !!(hold[9] & 0x80);
localColorCount = localColormap ? (2 << (hold[9] & 0x7)) : 0;
if (localColorCount)
colorCount = localColorCount;
else
colorCount = globalColorCount;
- imageCount++;
count = 0;
if (localColormap) {
@@ -865,13 +882,13 @@ int QGIFFormat::imageCount(QIODevice *device)
break;
case Error:
device->seek(oldPos);
- return 0;
+ return;
}
}
readBuffer = device->read(readBufferSize);
}
device->seek(oldPos);
- return imageCount;
+ return;
}
void QGIFFormat::fillRect(QImage *image, int col, int row, int w, int h, QRgb color)
@@ -994,8 +1011,7 @@ QGifHandler::QGifHandler()
nextDelay = 0;
loopCnt = 0;
frameNumber = -1;
- nextSize = QSize();
- imageCnt = -1;
+ scanIsCached = false;
}
QGifHandler::~QGifHandler()
@@ -1017,7 +1033,7 @@ bool QGifHandler::imageIsComing() const
}
int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
- &nextDelay, &loopCnt, &nextSize);
+ &nextDelay, &loopCnt);
if (decoded == -1)
break;
buffer.remove(0, decoded);
@@ -1061,7 +1077,7 @@ bool QGifHandler::read(QImage *image)
}
int decoded = gifFormat->decode(&lastImage, (const uchar *)buffer.constData(), buffer.size(),
- &nextDelay, &loopCnt, &nextSize);
+ &nextDelay, &loopCnt);
if (decoded == -1)
break;
buffer.remove(0, decoded);
@@ -1092,8 +1108,18 @@ bool QGifHandler::supportsOption(ImageOption option) const
QVariant QGifHandler::option(ImageOption option) const
{
if (option == Size) {
- if (imageIsComing())
- return nextSize;
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes);
+ scanIsCached = true;
+ }
+ // before the first frame is read, or we have an empty data stream
+ if (frameNumber == -1)
+ return (imageSizes.count() > 0) ? QVariant(imageSizes.at(0)) : QVariant();
+ // after the last frame has been read, the next size is undefined
+ if (frameNumber >= imageSizes.count() - 1)
+ return QVariant();
+ // and the last case: the size of the next frame
+ return imageSizes.at(frameNumber + 1);
} else if (option == Animation) {
return true;
}
@@ -1113,10 +1139,11 @@ int QGifHandler::nextImageDelay() const
int QGifHandler::imageCount() const
{
- if (imageCnt != -1)
- return imageCnt;
- imageCnt = QGIFFormat::imageCount(device());
- return imageCnt;
+ if (!scanIsCached) {
+ QGIFFormat::scan(device(), &imageSizes);
+ scanIsCached = true;
+ }
+ return imageSizes.count();
}
int QGifHandler::loopCount() const
diff --git a/src/plugins/imageformats/gif/qgifhandler.h b/src/plugins/imageformats/gif/qgifhandler.h
index 830cd38..8e07aff 100644
--- a/src/plugins/imageformats/gif/qgifhandler.h
+++ b/src/plugins/imageformats/gif/qgifhandler.h
@@ -87,8 +87,8 @@ private:
mutable int nextDelay;
mutable int loopCnt;
int frameNumber;
- mutable QSize nextSize;
- mutable int imageCnt;
+ mutable QVector imageSizes;
+ mutable bool scanIsCached;
};
QT_END_NAMESPACE
diff --git a/tests/auto/qimagereader/tst_qimagereader.cpp b/tests/auto/qimagereader/tst_qimagereader.cpp
index debc090..3e40527 100644
--- a/tests/auto/qimagereader/tst_qimagereader.cpp
+++ b/tests/auto/qimagereader/tst_qimagereader.cpp
@@ -881,6 +881,7 @@ void tst_QImageReader::gifImageCount()
{
QImageReader io(":images/trolltech.gif");
QVERIFY(io.imageCount() == 34);
+ QVERIFY(io.size() == QSize(128,64));
}
}
#endif
--
cgit v0.12
From 4cd8dd562ea149d5a6cdcc15533e4975682106f6 Mon Sep 17 00:00:00 2001
From: Janne Koskinen
Date: Thu, 4 Feb 2010 13:39:55 +0200
Subject: Revert "Daylight savings time for Symbian take 2"
This reverts commit 7bc18035816a2eac15dfac4d987eb9bf43f90ef6.
---
src/corelib/corelib.pro | 2 --
src/corelib/tools/qdatetime.cpp | 60 +++++++++++++---------------------
tests/auto/qdatetime/tst_qdatetime.cpp | 7 ----
3 files changed, 23 insertions(+), 46 deletions(-)
diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro
index 7f33791..9a15bf1 100644
--- a/src/corelib/corelib.pro
+++ b/src/corelib/corelib.pro
@@ -35,6 +35,4 @@ symbian: {
# Workaroud for problems with paging this dll
MMP_RULES -= PAGED
MMP_RULES *= UNPAGED
- # Timezone server
- LIBS += -ltzclient
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 9a361c0..c1027ed 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -75,7 +75,6 @@
#if defined(Q_OS_SYMBIAN)
#include
-#include
#endif
QT_BEGIN_NAMESPACE
@@ -3722,32 +3721,23 @@ static QDateTimePrivate::Spec utcToLocal(QDate &date, QTime &time)
#elif defined(Q_OS_SYMBIAN)
// months and days are zero index based
_LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = User::UTCOffset();
TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
TTime epochTTime;
TInt err = epochTTime.Set(KUnixEpoch);
tm res;
if(err == KErrNone) {
TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
- TRAP(err,
- RTz tz;
- User::LeaveIfError(tz.Connect());
- CleanupClosePushL(tz);
- res.tm_isdst = tz.IsDaylightSavingOnL(*tz.GetTimeZoneIdL(),utcTTime);
- User::LeaveIfError(tz.ConvertToLocalTime(utcTTime));
- CleanupStack::PopAndDestroy(&tz));
- if (KErrNone == err) {
- TDateTime localDateTime = utcTTime.DateTime();
- res.tm_sec = localDateTime.Second();
- res.tm_min = localDateTime.Minute();
- res.tm_hour = localDateTime.Hour();
- res.tm_mday = localDateTime.Day() + 1; // non-zero based index for tm struct
- res.tm_mon = localDateTime.Month();
- res.tm_year = localDateTime.Year() - 1900;
- // Symbian's timezone server doesn't know how to handle DST before year 1997
- if (res.tm_year < 97)
- res.tm_isdst = -1;
- brokenDown = &res;
- }
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = 0;
+ brokenDown = &res;
}
#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// use the reentrant version of localtime() where available
@@ -3822,27 +3812,23 @@ static void localToUtc(QDate &date, QTime &time, int isdst)
#elif defined(Q_OS_SYMBIAN)
// months and days are zero index based
_LIT(KUnixEpoch, "19700000:000000.000000");
+ TTimeIntervalSeconds utcOffset = TTimeIntervalSeconds(0 - User::UTCOffset().Int());
TTimeIntervalSeconds tTimeIntervalSecsSince1Jan1970UTC(secsSince1Jan1970UTC);
TTime epochTTime;
TInt err = epochTTime.Set(KUnixEpoch);
tm res;
if(err == KErrNone) {
- TTime localTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
- RTz tz;
- if (KErrNone == tz.Connect()) {
- if (KErrNone == tz.ConvertToUniversalTime(localTTime)) {
- TDateTime utcDateTime = localTTime.DateTime();
- res.tm_sec = utcDateTime.Second();
- res.tm_min = utcDateTime.Minute();
- res.tm_hour = utcDateTime.Hour();
- res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
- res.tm_mon = utcDateTime.Month();
- res.tm_year = utcDateTime.Year() - 1900;
- res.tm_isdst = (int)isdst;
- brokenDown = &res;
- }
- tz.Close();
- }
+ TTime utcTTime = epochTTime + tTimeIntervalSecsSince1Jan1970UTC;
+ utcTTime = utcTTime + utcOffset;
+ TDateTime utcDateTime = utcTTime.DateTime();
+ res.tm_sec = utcDateTime.Second();
+ res.tm_min = utcDateTime.Minute();
+ res.tm_hour = utcDateTime.Hour();
+ res.tm_mday = utcDateTime.Day() + 1; // non-zero based index for tm struct
+ res.tm_mon = utcDateTime.Month();
+ res.tm_year = utcDateTime.Year() - 1900;
+ res.tm_isdst = (int)isdst;
+ brokenDown = &res;
}
#elif !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
// use the reentrant version of gmtime() where available
diff --git a/tests/auto/qdatetime/tst_qdatetime.cpp b/tests/auto/qdatetime/tst_qdatetime.cpp
index b9d1d7c..86a4c80 100644
--- a/tests/auto/qdatetime/tst_qdatetime.cpp
+++ b/tests/auto/qdatetime/tst_qdatetime.cpp
@@ -147,16 +147,9 @@ Q_DECLARE_METATYPE(QTime)
tst_QDateTime::tst_QDateTime()
{
-#ifdef Q_OS_SYMBIAN
- // Symbian's timezone server cannot handle DST correctly for dates before year 1997
- uint x1 = QDateTime(QDate(2000, 1, 1), QTime()).toTime_t();
- uint x2 = QDateTime(QDate(2000, 6, 1), QTime()).toTime_t();
- europeanTimeZone = (x1 == 946681200 && x2 == 959810400);
-#else
uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t();
uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t();
europeanTimeZone = (x1 == 631148400 && x2 == 644191200);
-#endif
}
tst_QDateTime::~tst_QDateTime()
--
cgit v0.12
From 4c8b2aa00acc00a95b6f950a4ab7de737631e494 Mon Sep 17 00:00:00 2001
From: Jocelyn Turcotte
Date: Thu, 4 Feb 2010 11:18:47 +0100
Subject: Add the QMAKE_FILE_EXT variable to extra compilers generation.
This give the possibility to get the file name with the extension and
without the path.
Reviewed-by: Joao
Reviewed-by: Marius Storm-Olsen
---
qmake/generators/makefile.cpp | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/qmake/generators/makefile.cpp b/qmake/generators/makefile.cpp
index 69e1d8a..db2737b 100644
--- a/qmake/generators/makefile.cpp
+++ b/qmake/generators/makefile.cpp
@@ -1513,6 +1513,19 @@ MakefileGenerator::replaceExtraCompilerVariables(const QString &orig_var, const
base = fi.fileName();
val += base;
}
+ } else if(var == QLatin1String("QMAKE_FILE_EXT")) {
+ filePath = true;
+ for(int i = 0; i < in.size(); ++i) {
+ QFileInfo fi(fileInfo(Option::fixPathToLocalOS(in.at(i))));
+ QString ext;
+ // Ensure complementarity with QMAKE_FILE_BASE
+ int baseLen = fi.completeBaseName().length();
+ if(baseLen == 0)
+ ext = fi.fileName();
+ else
+ ext = fi.fileName().remove(0, baseLen);
+ val += ext;
+ }
} else if(var == QLatin1String("QMAKE_FILE_PATH") || var == QLatin1String("QMAKE_FILE_IN_PATH")) {
filePath = true;
for(int i = 0; i < in.size(); ++i)
--
cgit v0.12
From 34f1758428282a327c12b0d8040061c1f67ecc7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Thu, 4 Feb 2010 11:35:27 +0100
Subject: Crash when closing any top-level widget on Symbian.
The window surface must be deleted while the window is valid because on
some graphics systems a notifcation is sent to the window when the
surface is released.
This fix is also an optmization as we no longer process any backing
store requests while deleting the top-level. Previously it would
handle requests from the window itself and all its children.
Task-number: QT-2513
Reviewed-by: jbarron
---
src/gui/kernel/qwidget.cpp | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 4054d2a..4520a1b 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -1439,7 +1439,16 @@ QWidget::~QWidget()
}
#endif
- if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
+ if (d->extra && d->extra->topextra && d->extra->topextra->backingStore) {
+ // Okay, we are about to destroy the top-level window that owns
+ // the backing store. Make sure we delete the backing store right away
+ // before the window handle is invalid. This is important because
+ // the backing store will delete its window surface, which may or may
+ // not have a reference to this widget that will be used later to
+ // notify the window it no longer has a surface.
+ delete d->extra->topextra->backingStore;
+ d->extra->topextra->backingStore = 0;
+ } else if (QWidgetBackingStore *bs = d->maybeBackingStore()) {
bs->removeDirtyWidget(this);
if (testAttribute(Qt::WA_StaticContents))
bs->removeStaticWidget(this);
--
cgit v0.12
From b52e4ac1dfcce317872d9104142c026951a29145 Mon Sep 17 00:00:00 2001
From: Markus Goetz
Date: Thu, 4 Feb 2010 12:49:37 +0100
Subject: My Changelog entries for 4.6.2
---
dist/changes-4.6.2 | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 65c07cb..5f3d23c 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -42,6 +42,10 @@ QtCore
- QXmlStreamWriter
* [QTBUG-6893] Fixed adding extra Byte Order Marks when writing to a xml file.
+ - QFSFileEngine
+ * Fix typo that made realpath() not being used
+ - QIODevice
+ * Optimized readAll()
QtGui
-----
@@ -63,8 +67,17 @@ QtDBus
QtNetwork
---------
- - foo
- * bar
+ - QNetworkAccessManager
+ * Optimizations
+ * HTTP: Get rid of QAbstractSocket warnings that were sometimes displayed
+ * HTTP: setReadBufferSize() of the QNetworkReply finally is working on all layers
+ * [QTBUG-7713] HTTP: Fix bug related to re-sending a request
+ - QSslCertificate
+ * [QTBUG-6466] Fix issuerInfo() and subjectInfo()
+ - QTcpSocket
+ * [QTBUG-7344] Fix performance degredation with write() on Windows
+ * [QTBUG-7316] Also handle unknown errors from socket engine
+ * [QTBUG-7317] Also handle unknown errors from socket engine
QtOpenGL
--------
--
cgit v0.12
From 417e269c648fab4ad6e2075014419cc7fad69145 Mon Sep 17 00:00:00 2001
From: Thomas Zander
Date: Thu, 4 Feb 2010 12:29:47 +0100
Subject: Fix copy/pasto
Reviewed-by: trustme
---
src/gui/text/qzipreader_p.h | 2 +-
src/gui/text/qzipwriter_p.h | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/gui/text/qzipreader_p.h b/src/gui/text/qzipreader_p.h
index 1086464..67a2ace 100644
--- a/src/gui/text/qzipreader_p.h
+++ b/src/gui/text/qzipreader_p.h
@@ -49,7 +49,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QZipReader class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
diff --git a/src/gui/text/qzipwriter_p.h b/src/gui/text/qzipwriter_p.h
index 7b97937..9322f4a 100644
--- a/src/gui/text/qzipwriter_p.h
+++ b/src/gui/text/qzipwriter_p.h
@@ -47,7 +47,7 @@
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
-// of the QLibrary class. This header file may change from
+// of the QZipWriter class. This header file may change from
// version to version without notice, or even be removed.
//
// We mean it.
--
cgit v0.12
From bc1638138b71adf056f5972b7b1239f4eeffcfec Mon Sep 17 00:00:00 2001
From: Thomas Zander
Date: Thu, 4 Feb 2010 12:30:18 +0100
Subject: Make sure we define S_IFDIR on Windows
Reviewed-by: Thierry Bastian
---
src/gui/text/qzip.cpp | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/gui/text/qzip.cpp b/src/gui/text/qzip.cpp
index 2fc1940..d30c996 100644
--- a/src/gui/text/qzip.cpp
+++ b/src/gui/text/qzip.cpp
@@ -54,10 +54,13 @@
#include
#if defined(Q_OS_WIN)
-#undef S_IFREG
-#define S_IFREG 0100000
+# undef S_IFREG
+# define S_IFREG 0100000
+# ifndef S_IFDIR
+# define S_IFDIR 0040000
+# endif
# ifndef S_ISDIR
-# define S_ISDIR(x) ((x) & 0040000) > 0
+# define S_ISDIR(x) ((x) & S_IFDIR) > 0
# endif
# ifndef S_ISREG
# define S_ISREG(x) ((x) & 0170000) == S_IFREG
--
cgit v0.12
From db82dda4ae3672844f7637394bf9a403e7c4f4b3 Mon Sep 17 00:00:00 2001
From: Yoann Lopes
Date: Thu, 4 Feb 2010 13:15:31 +0100
Subject: My changelog for 4.6.2
---
dist/changes-4.6.2 | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 5f3d23c..0175f1d 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -56,6 +56,8 @@ QtGui
* [QTBUG-7029] Fixed a crash when re-creating QApplication object due to a
dangling gesture manager pointer.
* [QTBUG-7198] Setting a style sheet could break the checkbox position in item views.
+ * [QTBUG-7253] Fixed wrong stroke clipping with the raster engine when using a QPen
+ with a style other than SolidLine.
QtDBus
--
cgit v0.12
From 3c991df1681471cbfb737f6bed0c679e5ca67aa9 Mon Sep 17 00:00:00 2001
From: Friedemann Kleint
Date: Thu, 4 Feb 2010 13:58:35 +0100
Subject: uic: Fixed code generating setCentralWidget()-calls of QMainWindow.
Regression introduced by QTBUG-5824 change
6809bd020e3307324e136707f32f6f17f77b9591. Do not generate
setCentralWidget() for Qt3Support toolbar/dock widget classes.
Reviewed-by: ogoffart
Task-number: QTBUG-7612
---
src/tools/uic/cpp/cppwriteinitialization.cpp | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/tools/uic/cpp/cppwriteinitialization.cpp b/src/tools/uic/cpp/cppwriteinitialization.cpp
index 8099ffa..dc1d181 100644
--- a/src/tools/uic/cpp/cppwriteinitialization.cpp
+++ b/src/tools/uic/cpp/cppwriteinitialization.cpp
@@ -721,8 +721,9 @@ void WriteInitialization::acceptWidget(DomWidget *node)
m_output << m_indent << parentWidget << "->addDockWidget(" << area << varName << ");\n";
} else if (m_uic->customWidgetsInfo()->extends(className, QLatin1String("QStatusBar"))) {
m_output << m_indent << parentWidget << "->setStatusBar(" << varName << ");\n";
- } else {
- m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
+ } else if (!m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3DockWindow"))
+ && !m_uic->customWidgetsInfo()->extends(className, QLatin1String("Q3ToolBar"))) {
+ m_output << m_indent << parentWidget << "->setCentralWidget(" << varName << ");\n";
}
}
--
cgit v0.12
From 551575ae14de1c80712478ba07fd26c7cccec322 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?=
Date: Thu, 4 Feb 2010 14:15:00 +0100
Subject: My changes for 4.6.2
---
dist/changes-4.6.2 | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 0175f1d..f667c91 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -42,6 +42,12 @@ QtCore
- QXmlStreamWriter
* [QTBUG-6893] Fixed adding extra Byte Order Marks when writing to a xml file.
+ - QFile
+ * Fixed double-buffering issue when opening files in buffered mode.
+ * [QTBUG-7285] QFile::remove would fail if an unrelated operation on the
+ same instance had been previously failed. This manisfested itself in
+ QTemporaryFile failing to auto-remove files and QFile::copy leaving
+ temporary files behind in certain situations.
- QFSFileEngine
* Fix typo that made realpath() not being used
- QIODevice
--
cgit v0.12
From fe2611f98fd4167cd4746100f062380cbc72f6bd Mon Sep 17 00:00:00 2001
From: Friedemann Kleint
Date: Thu, 4 Feb 2010 14:20:07 +0100
Subject: Designer: Emit QDesignerPropertyEditorInterface::propertyChanged().
Broken by introduction of new signal with extended parameters.
Emit both signals and block against each other.
Tested against Eclipse integration.
Reviewed-by: Jarek Kobus
Task-number: QTBUG-7764
---
.../src/components/propertyeditor/propertyeditor.cpp | 4 ++--
.../designer/src/lib/shared/qdesigner_propertyeditor.cpp | 16 ++++++++++++++--
.../designer/src/lib/shared/qdesigner_propertyeditor_p.h | 8 +++++++-
3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/tools/designer/src/components/propertyeditor/propertyeditor.cpp b/tools/designer/src/components/propertyeditor/propertyeditor.cpp
index b171ddc..512cc82 100644
--- a/tools/designer/src/components/propertyeditor/propertyeditor.cpp
+++ b/tools/designer/src/components/propertyeditor/propertyeditor.cpp
@@ -1175,11 +1175,11 @@ void PropertyEditor::slotValueChanged(QtProperty *property, const QVariant &valu
Q_ASSERT(ok);
QVariant v;
qVariantSetValue(v, e);
- emit propertyValueChanged(property->propertyName(), v, true);
+ emitPropertyValueChanged(property->propertyName(), v, true);
return;
}
- emit propertyValueChanged(property->propertyName(), value, enableSubPropertyHandling);
+ emitPropertyValueChanged(property->propertyName(), value, enableSubPropertyHandling);
}
bool PropertyEditor::isDynamicProperty(const QtBrowserItem* item) const
diff --git a/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp b/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp
index e89c47c..9a1739e 100644
--- a/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp
+++ b/tools/designer/src/lib/shared/qdesigner_propertyeditor.cpp
@@ -92,7 +92,8 @@ static const PropertyNameTypeMap &stringPropertyTypes()
}
QDesignerPropertyEditor::QDesignerPropertyEditor(QWidget *parent, Qt::WindowFlags flags) :
- QDesignerPropertyEditorInterface(parent, flags)
+ QDesignerPropertyEditorInterface(parent, flags),
+ m_propertyChangedForwardingBlocked(false)
{
// Make old signal work for compatibility
connect(this, SIGNAL(propertyChanged(QString,QVariant)), this, SLOT(slotPropertyChanged(QString,QVariant)));
@@ -147,9 +148,20 @@ QDesignerPropertyEditor::StringPropertyParameters QDesignerPropertyEditor::textP
return StringPropertyParameters(ValidationSingleLine, true);
}
+void QDesignerPropertyEditor::emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling)
+{
+ // Avoid duplicate signal emission - see below
+ m_propertyChangedForwardingBlocked = true;
+ emit propertyValueChanged(name, value, enableSubPropertyHandling);
+ emit propertyChanged(name, value);
+ m_propertyChangedForwardingBlocked = false;
+}
+
void QDesignerPropertyEditor::slotPropertyChanged(const QString &name, const QVariant &value)
{
- emit propertyValueChanged(name, value, true);
+ // Forward signal from Integration using the old interfaces.
+ if (!m_propertyChangedForwardingBlocked)
+ emit propertyValueChanged(name, value, true);
}
}
diff --git a/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h b/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h
index c618bd7..dac2f11 100644
--- a/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h
+++ b/tools/designer/src/lib/shared/qdesigner_propertyeditor_p.h
@@ -79,7 +79,6 @@ public:
static StringPropertyParameters textPropertyValidationMode(QDesignerFormEditorInterface *core,
const QObject *object, const QString &propertyName, bool isMainContainer);
-
Q_SIGNALS:
void propertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling);
void resetProperty(const QString &name);
@@ -97,6 +96,13 @@ public Q_SLOTS:
private Q_SLOTS:
void slotPropertyChanged(const QString &name, const QVariant &value);
+
+protected:
+ void emitPropertyValueChanged(const QString &name, const QVariant &value, bool enableSubPropertyHandling);
+
+private:
+ bool m_propertyChangedForwardingBlocked;
+
};
} // namespace qdesigner_internal
--
cgit v0.12
From 5160af692fd0352457cdf12cb497e1b8d8eed858 Mon Sep 17 00:00:00 2001
From: Morten Engvoldsen
Date: Thu, 4 Feb 2010 14:32:20 +0100
Subject: Doc: Correcting image Changing "Trolltech" to "Nokia"
Task-number:QTBUG-7370
Reviewed-by:Trust me
---
doc/src/images/qpainter-text.png | Bin 791 -> 1391 bytes
1 file changed, 0 insertions(+), 0 deletions(-)
diff --git a/doc/src/images/qpainter-text.png b/doc/src/images/qpainter-text.png
index af7821c..e95c965 100644
Binary files a/doc/src/images/qpainter-text.png and b/doc/src/images/qpainter-text.png differ
--
cgit v0.12
From 5ddcf96b8339850d1f84db9f487ac15a1ed3364a Mon Sep 17 00:00:00 2001
From: axis
Date: Thu, 4 Feb 2010 14:42:50 +0100
Subject: Added my changes to changes file.
---
dist/changes-4.6.2 | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index f667c91..e7c2860 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -59,6 +59,12 @@ QtGui
- foo
* bar
+ - QApplication
+ * [QTBUG-6098] Added a flag to avoid construction of application panes.
+ - QInputContext
+ * [QTBUG-7439] Avoided the loss of preedit text when losing focus on Symbian.
+
+ * [QT-2629] Implemented event filter functions for Symbian.
* [QTBUG-7029] Fixed a crash when re-creating QApplication object due to a
dangling gesture manager pointer.
* [QTBUG-7198] Setting a style sheet could break the checkbox position in item views.
--
cgit v0.12
From 38d31452b3cafd738c215b5686bf3ff95c1d27d6 Mon Sep 17 00:00:00 2001
From: Thiago Macieira
Date: Thu, 4 Feb 2010 14:48:11 +0100
Subject: My 4.6.2 changes
---
dist/changes-4.6.2 | 63 ++++++++++++++++++++++++++++++++++++++++--------------
1 file changed, 47 insertions(+), 16 deletions(-)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index e7c2860..45b7086 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -1,7 +1,7 @@
Qt 4.6.2 is a bug-fix release. It maintains both forward and backward
-compatibility (source and binary) with Qt 4.6.0. For more details,
-refer to the online documentation included in this distribution. The
-documentation is also available online:
+compatibility (source and binary) with Qt 4.6.0 and 4.6.1. For more
+details, refer to the online documentation included in this
+distribution. The documentation is also available online:
http://qt.nokia.com/doc/4.6
@@ -40,19 +40,29 @@ Optimizations
QtCore
------
- - QXmlStreamWriter
- * [QTBUG-6893] Fixed adding extra Byte Order Marks when writing to a xml file.
+ - QAtomicPointer
+ * [QTBUG-7356] Fixed a compilation failure when using the Intel
+ compiler on IA-64
+
- QFile
* Fixed double-buffering issue when opening files in buffered mode.
* [QTBUG-7285] QFile::remove would fail if an unrelated operation on the
same instance had been previously failed. This manisfested itself in
QTemporaryFile failing to auto-remove files and QFile::copy leaving
temporary files behind in certain situations.
+
- QFSFileEngine
* Fix typo that made realpath() not being used
+
- QIODevice
* Optimized readAll()
+ - QReadWriteLock
+ * [MR 426] Fixed documentation
+
+ - QXmlStreamWriter
+ * [QTBUG-6893] Fixed adding extra Byte Order Marks when writing to a xml file.
+
QtGui
-----
@@ -72,26 +82,31 @@ QtGui
with a style other than SolidLine.
+ * [MR 2077] Integrated merge request 2077
+
QtDBus
------
- - foo
- * bar
+ - QDBusConnection
+ * [QT-2307] Fixed sending of D-Bus method calls with QDBus::BlockWithGui
QtNetwork
---------
- QNetworkAccessManager
- * Optimizations
- * HTTP: Get rid of QAbstractSocket warnings that were sometimes displayed
- * HTTP: setReadBufferSize() of the QNetworkReply finally is working on all layers
- * [QTBUG-7713] HTTP: Fix bug related to re-sending a request
+ * Optimizations
+ * HTTP: Get rid of QAbstractSocket warnings that were sometimes displayed
+ * HTTP: setReadBufferSize() of the QNetworkReply finally is working on all layers
+ * [QTBUG-7713] HTTP: Fix bug related to re-sending a request
+ * [QTBUG-7060] Fixed an issue with parsing of HTTP headers like
+ "private, max-age=300"
+
- QSslCertificate
- * [QTBUG-6466] Fix issuerInfo() and subjectInfo()
+ * [QTBUG-6466] Fix issuerInfo() and subjectInfo()
+
- QTcpSocket
- * [QTBUG-7344] Fix performance degredation with write() on Windows
- * [QTBUG-7316] Also handle unknown errors from socket engine
- * [QTBUG-7317] Also handle unknown errors from socket engine
+ * [QTBUG-7344] Fix performance degredation with write() on Windows
+ * [QTBUG-7316,QTBUG-7317] Also handle unknown errors from socket engine
QtOpenGL
--------
@@ -134,6 +149,15 @@ Qt Plugins
- foo
* bar
+Examples
+--------
+
+ - QtMultimedia
+ * [MR 418] Fixed the example for QAudioOutput
+
+ - WebKit
+ * [MR 2235] Added the framecapture example to the default build
+
Third party components
----------------------
@@ -222,5 +246,12 @@ Qt for Windows CE
* Important Behavior Changes *
****************************************************************************
- -
+ - QNetworkAccessManager cache
+ * QNetworkAccessManager will no longer return expired pages, as
+ stated in the documentation
+ * The behaviour of PreferCache and PreferNetwork modes now match
+ the documentation more closely
+ - QUrl
+ * QUrl will now accept hostnames ending in dot and will not treat
+ those as invalid hostnames
--
cgit v0.12
From 63d50974f104f3626fee13c24251b91a6b3d046b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Thu, 4 Feb 2010 14:51:59 +0100
Subject: Stabilize tst_QGraphicsWidget::initialShow2 (new test)
---
tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 22 +++++++++++++++++++++-
1 file changed, 21 insertions(+), 1 deletion(-)
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index 526486e..a7195c4 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -2892,6 +2892,26 @@ void tst_QGraphicsWidget::initialShow2()
void polishEvent() { update(); }
};
+ // Don't let paint events triggered by the windowing system
+ // influence our test case. We're only interested in knowing
+ // whether a QGraphicsWidget generates an additional repaint
+ // on the inital show. Hence create a dummy scenario to find out
+ // how many repaints we should expect.
+ QGraphicsScene dummyScene(0, 0, 200, 200);
+ dummyScene.addItem(new QGraphicsRectItem(0, 0, 100, 100));
+
+ QGraphicsView *dummyView = new QGraphicsView(&dummyScene);
+ EventSpy paintSpy(dummyView->viewport(), QEvent::Paint);
+ dummyView->show();
+ // Not using QTest::qWaitForWindowShown(&view); on purpose, because there's
+ // a bug in qt_x11_wait_for_window_manager that prevents this test
+ // to pass. Denis is looking into it.
+ QTest::qWait(300);
+ const int expectedRepaintCount = paintSpy.count();
+ delete dummyView;
+ dummyView = 0;
+ QTest::qWait(200);
+
MyGraphicsWidget *widget = new MyGraphicsWidget;
widget->resize(100, 100);
@@ -2905,7 +2925,7 @@ void tst_QGraphicsWidget::initialShow2()
// to pass. Denis is looking into it.
QTest::qWait(300);
- QCOMPARE(widget->repaints, 1);
+ QCOMPARE(widget->repaints, expectedRepaintCount);
}
void tst_QGraphicsWidget::QT_BUG_6544_tabFocusFirstUnsetWhenRemovingItems()
--
cgit v0.12
From 94abb3ee93aa09f79640e14fed89b286c57ce05c Mon Sep 17 00:00:00 2001
From: Janne Anttila
Date: Thu, 4 Feb 2010 15:57:44 +0200
Subject: Initial support for S60 softkey icons.
The logic for resolving the icon size in landscape mode for S60 5.0
(5800XM) is somewhat fragile, but better way is not yet know.
Also the 50% transparent mask what CBA implementation tries to create
for pressed down CB Abuttons fails for some reason. When button is
pressed down there are drawing artifacts in softkey images.
These issues will be tried to resolve with later commits
Task-number: QTBUG-7314
Review-By: Sami Merila
---
src/3rdparty/s60/eiksoftkeyimage.h | 112 +++++++++++++++++++++++++++++++++
src/gui/kernel/qsoftkeymanager_s60.cpp | 89 +++++++++++++++++++-------
src/gui/kernel/qsoftkeymanager_s60_p.h | 4 +-
3 files changed, 180 insertions(+), 25 deletions(-)
create mode 100644 src/3rdparty/s60/eiksoftkeyimage.h
diff --git a/src/3rdparty/s60/eiksoftkeyimage.h b/src/3rdparty/s60/eiksoftkeyimage.h
new file mode 100644
index 0000000..84f6108a
--- /dev/null
+++ b/src/3rdparty/s60/eiksoftkeyimage.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the 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$
+**
+****************************************************************************/
+
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Changes cba button's label to image.
+*
+*/
+
+#ifndef EIKSOFTKEYIMAGE_H
+#define EIKSOFTKEYIMAGE_H
+
+// FORWARD DECLARATIONS
+class CEikButtonGroupContainer;
+
+// CLASS DECLARATION
+
+/**
+* Changes cba button's label to image.
+*
+* @lib EIKCOCTL
+* @since 2.0
+*/
+class EikSoftkeyImage
+ {
+ public:
+
+ /**
+ * Set image to cba button by replacing label
+ * @since 2.0
+ * @param aButtonGroupContainer Button container
+ * @param aImage Image to button,
+ * Takes Images ownership
+ * @param aLeft Boolean: left or right button.
+ * If true, then change left,
+ * if false, change right
+ */
+ IMPORT_C static void SetImage(CEikButtonGroupContainer* aButtonGroupContainer, CEikImage& aImage, TBool aLeft);
+
+ /**
+ * Change to cba button image back to label
+ * @since 2.0
+ * @param aButtonGroupContainer Button container
+ * @param aLeft Boolean: left or right button.
+ * If true, then change left,
+ * if false, change right
+ */
+ IMPORT_C static void SetLabel(CEikButtonGroupContainer* aButtonGroupContainer, TBool aLeft);
+
+ private:
+
+ /**
+ * C++ default constructor.
+ */
+ EikSoftkeyImage() {};
+
+
+ };
+
+#endif // EIKSOFTKEYIMAGE_H
+
+// End of File
+
diff --git a/src/gui/kernel/qsoftkeymanager_s60.cpp b/src/gui/kernel/qsoftkeymanager_s60.cpp
index 67ed8b0..a72d16c 100644
--- a/src/gui/kernel/qsoftkeymanager_s60.cpp
+++ b/src/gui/kernel/qsoftkeymanager_s60.cpp
@@ -49,7 +49,7 @@
#include "private/qsoftkeymanager_p.h"
#include "private/qsoftkeymanager_s60_p.h"
#include "private/qobject_p.h"
-//#include
+#include
#include
#ifndef QT_NO_SOFTKEYMANAGER
@@ -64,6 +64,8 @@ QSoftKeyManagerPrivateS60::QSoftKeyManagerPrivateS60()
{
cachedCbaIconSize[0] = QSize(0,0);
cachedCbaIconSize[1] = QSize(0,0);
+ cachedCbaIconSize[2] = QSize(0,0);
+ cachedCbaIconSize[3] = QSize(0,0);
skipNextUpdate = false;
}
@@ -149,6 +151,39 @@ void QSoftKeyManagerPrivateS60::setNativeSoftkey(CEikButtonGroupContainer &cba,
QT_TRAP_THROWING(cba.SetCommandL(position, command, text));
}
+QPoint QSoftKeyManagerPrivateS60::softkeyIconPosition(int position, QSize sourceSize, QSize targetSize)
+{
+ QPoint iconPosition(0,0);
+ switch( AknLayoutUtils::CbaLocation() )
+ {
+ case AknLayoutUtils::EAknCbaLocationBottom:
+ // RSK must be moved to right, LSK in on correct position by default
+ if (position == RSK_POSITION)
+ iconPosition.setX(targetSize.width() - sourceSize.width());
+ break;
+ case AknLayoutUtils::EAknCbaLocationRight:
+ case AknLayoutUtils::EAknCbaLocationLeft:
+ // Already in correct position
+ default:
+ break;
+ }
+
+ // Align horizontally to center
+ iconPosition.setY((targetSize.height() - sourceSize.height()) >> 1);
+ return iconPosition;
+}
+
+QPixmap QSoftKeyManagerPrivateS60::prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize)
+{
+ QPixmap target(targetSize);
+ target.fill(Qt::transparent);
+ QPainter p;
+ p.begin(&target);
+ p.drawPixmap(softkeyIconPosition(position, src.size(), targetSize), src);
+ p.end();
+ return target;
+}
+
bool QSoftKeyManagerPrivateS60::isOrientationLandscape()
{
// Hard to believe that there is no public API in S60 to
@@ -158,15 +193,11 @@ bool QSoftKeyManagerPrivateS60::isOrientationLandscape()
QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int position)
{
- Q_UNUSED(cba);
- Q_UNUSED(position);
- // Will be implemented when EikSoftkeyImage usage license wise is OK
-/*
- const int index = isOrientationLandscape() ? 0 : 1;
+ int index = position;
+ index += isOrientationLandscape() ? 0 : 1;
if(cachedCbaIconSize[index].isNull()) {
// Only way I figured out to get CBA icon size without RnD SDK, was
- // Only way I figured out to get CBA icon size without RnD SDK, was
// to set some dummy icon to CBA first and then ask CBA button CCoeControl::Size()
// The returned value is cached to avoid unnecessary icon setting every time.
const bool left = (position == LSK_POSITION);
@@ -178,38 +209,49 @@ QSize QSoftKeyManagerPrivateS60::cbaIconSize(CEikButtonGroupContainer *cba, int
setNativeSoftkey(*cba, position, command, KNullDesC());
cachedCbaIconSize[index] = qt_TSize2QSize(cba->ControlOrNull(command)->Size());
EikSoftkeyImage::SetLabel(cba, left);
+
+ if(cachedCbaIconSize[index] == QSize(138,72)) {
+ // Hack for S60 5.0 (5800) landscape orientation, which return wrong icon size
+ cachedCbaIconSize[index] = QSize(60,60);
+ }
}
}
return cachedCbaIconSize[index];
-*/
- return QSize();
}
bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba,
QAction &action, int position)
{
bool ret = false;
- Q_UNUSED(cba);
- Q_UNUSED(action);
- Q_UNUSED(position);
- // Will be implemented when EikSoftkeyImage usage license wise is OK
- /*
const bool left = (position == LSK_POSITION);
if(position == LSK_POSITION || position == RSK_POSITION) {
QIcon icon = action.icon();
if (!icon.isNull()) {
- QPixmap pm = icon.pixmap(cbaIconSize(cba, position));
- pm = pm.scaled(cbaIconSize(cba, position));
- QBitmap mask = pm.mask();
- if (mask.isNull()) {
- mask = QBitmap(pm.size());
- mask.fill(Qt::color1);
+ // Get size of CBA icon area based on button position and orientation
+ QSize requiredIconSize = cbaIconSize(cba, position);
+ // Get pixmap out of icon based on preferred size, the aspect ratio is kept
+ QPixmap pmWihtAspectRatio = icon.pixmap(requiredIconSize);
+ // Native softkeys require that pixmap size is exactly the same as requiredIconSize
+ // prepareSoftkeyPixmap creates a new pixmap with requiredIconSize and blits the 'pmWihtAspectRatio'
+ // to correct location of it
+ QPixmap softkeyPixmap = prepareSoftkeyPixmap(pmWihtAspectRatio, position, requiredIconSize);
+ QBitmap softkeyMask = softkeyPixmap.mask();
+ if (softkeyMask.isNull()) {
+ softkeyMask = QBitmap(softkeyPixmap.size());
+ softkeyMask.fill(Qt::color1);
+ }
+
+ // Softkey mask in > SV_S60_5_1 has to be inverted
+ if(QSysInfo::s60Version() > QSysInfo::SV_S60_5_1) {
+ QImage maskImage = softkeyMask.toImage();
+ maskImage.invertPixels();
+ softkeyMask = QPixmap::fromImage(maskImage);
}
- CFbsBitmap* nBitmap = pm.toSymbianCFbsBitmap();
- CFbsBitmap* nMask = mask.toSymbianCFbsBitmap();
+ CFbsBitmap* nBitmap = softkeyPixmap.toSymbianCFbsBitmap();
+ CFbsBitmap* nMask = softkeyMask.toSymbianCFbsBitmap();
CEikImage* myimage = new (ELeave) CEikImage;
myimage->SetPicture( nBitmap, nMask ); // nBitmap and nMask ownership transfered
@@ -221,7 +263,6 @@ bool QSoftKeyManagerPrivateS60::setSoftkeyImage(CEikButtonGroupContainer *cba,
EikSoftkeyImage::SetLabel(cba, left);
}
}
- */
return ret;
}
@@ -272,6 +313,7 @@ bool QSoftKeyManagerPrivateS60::setRightSoftkey(CEikButtonGroupContainer &cba)
if (windowType != Qt::Dialog && windowType != Qt::Popup) {
QString text(QSoftKeyManager::tr("Exit"));
TPtrC nativeText = qt_QString2TPtrC(text);
+ EikSoftkeyImage::SetLabel(&cba, false);
setNativeSoftkey(cba, RSK_POSITION, EAknSoftkeyExit, nativeText);
return true;
}
@@ -303,7 +345,6 @@ void QSoftKeyManagerPrivateS60::setSoftkeys(CEikButtonGroupContainer &cba)
void QSoftKeyManagerPrivateS60::updateSoftKeys_sys()
{
- //bool status = CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog();
if (skipCbaUpdate())
return;
diff --git a/src/gui/kernel/qsoftkeymanager_s60_p.h b/src/gui/kernel/qsoftkeymanager_s60_p.h
index 46e3596..f8bd6d9 100644
--- a/src/gui/kernel/qsoftkeymanager_s60_p.h
+++ b/src/gui/kernel/qsoftkeymanager_s60_p.h
@@ -84,6 +84,8 @@ private:
QAction *highestPrioritySoftkey(QAction::SoftKeyRole role);
static bool actionPriorityMoreThan(const QAction* item1, const QAction* item2);
void setNativeSoftkey(CEikButtonGroupContainer &cba, TInt position, TInt command, const TDesC& text);
+ QPoint softkeyIconPosition(int position, QSize sourceSize, QSize targetSize);
+ QPixmap prepareSoftkeyPixmap(QPixmap src, int position, QSize targetSize);
bool isOrientationLandscape();
QSize cbaIconSize(CEikButtonGroupContainer *cba, int position);
bool setSoftkeyImage(CEikButtonGroupContainer *cba, QAction &action, int position);
@@ -95,7 +97,7 @@ private:
private:
QHash realSoftKeyActions;
- QSize cachedCbaIconSize[2];
+ QSize cachedCbaIconSize[4];
bool skipNextUpdate;
};
--
cgit v0.12
From 56d1da45bc15989542fe3621c9c9de444219729c Mon Sep 17 00:00:00 2001
From: Jason Barron
Date: Thu, 4 Feb 2010 10:53:05 +0100
Subject: Fix crash when multiple screens are reported from HAL.
The support for multiple screens is not implemented yet in Qt on the
Symbian platform, so there is really no need to query the HAL for the
value since the additional screens can't be used yet anyway. The crash
here occured when the HAL returned more than 1 screen, but the arrays
were resized to contain one element. The loop in resizeEvent() was
iterating past the end of the array because it thought there were more
screens than the arrays did.
Reviewed-by: axis
---
src/gui/kernel/qdesktopwidget_s60.cpp | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/src/gui/kernel/qdesktopwidget_s60.cpp b/src/gui/kernel/qdesktopwidget_s60.cpp
index 77745ea..84e3c5d 100644
--- a/src/gui/kernel/qdesktopwidget_s60.cpp
+++ b/src/gui/kernel/qdesktopwidget_s60.cpp
@@ -88,24 +88,20 @@ QDesktopWidgetPrivate::~QDesktopWidgetPrivate()
void QDesktopWidgetPrivate::init(QDesktopWidget *that)
{
- int screenCount=0;
+// int screenCount=0;
- if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone)
- QDesktopWidgetPrivate::screenCount = screenCount;
- else
- QDesktopWidgetPrivate::screenCount = 0;
+ // ### TODO: Implement proper multi-display support
+ QDesktopWidgetPrivate::screenCount = 1;
+// if (HAL::Get(0, HALData::EDisplayNumberOfScreens, screenCount) == KErrNone)
+// QDesktopWidgetPrivate::screenCount = screenCount;
+// else
+// QDesktopWidgetPrivate::screenCount = 0;
rects = new QVector();
workrects = new QVector();
rects->resize(QDesktopWidgetPrivate::screenCount);
workrects->resize(QDesktopWidgetPrivate::screenCount);
-
- // ### TODO: Implement proper multi-display support
- rects->resize(1);
- rects->replace(0, that->rect());
- workrects->resize(1);
- workrects->replace(0, that->rect());
}
void QDesktopWidgetPrivate::cleanup()
--
cgit v0.12
From 91e236022acd79dfbc4aef9e30edb4d1aeb2685c Mon Sep 17 00:00:00 2001
From: Jason Barron
Date: Thu, 4 Feb 2010 14:15:56 +0100
Subject: Flush the WSERV command buffer after deleting a surface.
For graphics systems that use EGL surfaces in the backing store
destroying the surface does not guarantee that the memory is
immediately freed because this command does not cause a flush. This
implies that a manual flush is instead needed. We do this in 2 places;
the first is when the surface is destroyed due to a visibility changed.
The second case is just after the window has been destroyed. At this
point the backing store has already been deleted so the deletion of
both the surface and window can happen atomically in WSERV.
Task-number: QT-2506
Reviewed-by: Iain
---
src/gui/kernel/qapplication_s60.cpp | 3 +++
src/gui/kernel/qwidget_s60.cpp | 4 ++++
2 files changed, 7 insertions(+)
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 6caac9f..6e03d7c 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -1647,6 +1647,9 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent
if (visChangedEvent->iFlags & TWsVisibilityChangedEvent::ENotVisible) {
delete w->d_func()->topData()->backingStore;
w->d_func()->topData()->backingStore = 0;
+ // In order to ensure that any resources used by the window surface
+ // are immediately freed, we flush the WSERV command buffer.
+ S60->wsSession().Flush();
} else if ((visChangedEvent->iFlags & TWsVisibilityChangedEvent::EPartiallyVisible)
&& !w->d_func()->maybeBackingStore()) {
w->d_func()->topData()->backingStore = new QWidgetBackingStore(w);
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 00f2213..0ce7534 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -1195,6 +1195,10 @@ void QWidget::destroy(bool destroyWindow, bool destroySubWindows)
if (destroyWindow) {
delete id;
+ // At this point the backing store should already be destroyed
+ // so we flush the command buffer to ensure that the freeing of
+ // those resources and deleting the window can happen "atomically"
+ S60->wsSession().Flush();
}
}
--
cgit v0.12
From 760319b312aceb2cc7438ad09eecd305c1b663e8 Mon Sep 17 00:00:00 2001
From: Gunnar Sletta
Date: Thu, 4 Feb 2010 06:48:30 -0800
Subject: Fix Geometry shaders based on review
---
src/opengl/qglshaderprogram.cpp | 24 +++++++++++++++---------
src/opengl/qglshaderprogram.h | 2 +-
2 files changed, 16 insertions(+), 10 deletions(-)
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
index 43d1df8..7af488d 100644
--- a/src/opengl/qglshaderprogram.cpp
+++ b/src/opengl/qglshaderprogram.cpp
@@ -517,9 +517,6 @@ public:
, geometryVertexCount(64)
, geometryInputType(0)
, geometryOutputType(0)
- , vertexShader(0)
- , fragmentShader(0)
- , geometryShader(0)
{
}
~QGLShaderProgramPrivate();
@@ -536,9 +533,6 @@ public:
QString log;
QList shaders;
QList anonShaders;
- QGLShader *vertexShader;
- QGLShader *fragmentShader;
- QGLShader *geometryShader;
bool hasShader(QGLShader::ShaderType type) const;
};
@@ -564,6 +558,17 @@ bool QGLShaderProgramPrivate::hasShader(QGLShader::ShaderType type) const
#define ctx d->programGuard.context()
/*!
+ \enum GeometryTypes
+
+ Defines the geometry types specificed by the GL_EXT_geometry_shader4 extension
+
+ \value LinesWithAdjacencyGeometryType Corresponds to GL_LINES_ADJACENCY.
+ \value LineStripWithAdjacencyGeometryType Corresponds to GL_LINE_STRIP_ADJACENCY.
+ \value TrianglesWithAdjacencyGeometryType Corresponds to GL_TRIANGLES_ADJACENCY.
+ \value TriangleStripWithAdjacencyGeometryType Corresponds to GL_TRIANGLE_STRIP_ADJACENCY.
+ */
+
+/*!
Constructs a new shader program and attaches it to \a parent.
The program will be invalid until addShader() is called.
@@ -2995,7 +3000,7 @@ void QGLShaderProgram::shaderDestroyed()
The \a context is used to resolve the GLSL extensions.
If \a context is null, then QGLContext::currentContext() is used.
*/
-bool QGLShader::hasShaders(ShaderType type, const QGLContext *context)
+bool QGLShader::hasOpenGLShaders(ShaderType type, const QGLContext *context)
{
#if !defined(QT_OPENGL_ES_2)
if (!context)
@@ -3006,9 +3011,10 @@ bool QGLShader::hasShaders(ShaderType type, const QGLContext *context)
bool resolved = qt_resolve_glsl_extensions(const_cast(context));
if (!resolved)
return false;
- const QGLContext *ctx = context;
- if ((type & Geometry) && !glProgramParameteriEXT)
+
+ if ((type & Geometry) && !QByteArray((const char *) glGetString(GL_EXTENSIONS)).contains("GL_EXT_geometry_shader4"))
return false;
+
return true;
}
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
index face66e..6dfbb77 100644
--- a/src/opengl/qglshaderprogram.h
+++ b/src/opengl/qglshaderprogram.h
@@ -89,7 +89,7 @@ public:
GLuint shaderId() const;
- static bool hasShaders(ShaderType type, const QGLContext *context = 0);
+ static bool hasOpenGLShaders(ShaderType type, const QGLContext *context = 0);
private:
friend class QGLShaderProgram;
--
cgit v0.12
From 9cc4ae77a73bd28ff495f36f26dd87c78b76b976 Mon Sep 17 00:00:00 2001
From: Miikka Heikkinen
Date: Thu, 4 Feb 2010 15:08:44 +0200
Subject: Added support for smart installer package generation in Symbian
Smart installer packages bundle normal application sis with a bootstrap
package that will download a smart installer when the package
is installed. Smart installer in turn will download any dependencies
of the application that are available on remote server, such as
Open C, Qt, and QtWebkit packages, and install them
Smart installer packages are generated when DEPLOYMENT.installer_header
variable is defined in applicatoin .pro file.
This commit is still missing properly signed bootstrap.sis package.
Task-number: QTBUG-7908
Reviewed-by: Shane Kearns
---
bin/createpackage.pl | 64 ++++++++++++------
demos/embedded/fluidlauncher/fluidlauncher.pro | 2 +
doc/src/deployment/deployment.qdoc | 34 ++++++----
doc/src/development/qmake-manual.qdoc | 12 ++++
doc/src/snippets/code/doc_src_deployment.qdoc | 13 ++--
doc/src/snippets/code/doc_src_qmake-manual.qdoc | 10 +--
qmake/generators/symbian/symmake.cpp | 86 ++++++++++++++++++++-----
7 files changed, 160 insertions(+), 61 deletions(-)
diff --git a/bin/createpackage.pl b/bin/createpackage.pl
index 197dffe..460df31 100755
--- a/bin/createpackage.pl
+++ b/bin/createpackage.pl
@@ -64,7 +64,7 @@ sub Usage() {
==============================================================================================
Convenience script for creating signed packages you can install on your phone.
-Usage: createpackage.pl [options] templatepkg target-platform [certificate key [passphrase]]
+Usage: createpackage.pl [options] templatepkg [target]-[platform] [certificate key [passphrase]]
Where supported optiobns are as follows:
[-i|install] = Install the package right away using PC suite
@@ -72,9 +72,10 @@ Where supported optiobns are as follows:
[-c|certfile=] = The file containing certificate information for signing.
The file can have several certificates, each specified in
separate line. The certificate, key and passphrase in line
- must be ';' separated. Lines starting with '#' are treated
- as a comments. Also empty lines are ignored. The paths in
+ must be ';' separated. Lines starting with '#' are treated
+ as a comments. Also empty lines are ignored. The paths in
can be absolute or relative to .
+ [-u|unsigned] = Preserves the unsigned package
Where parameters are as follows:
templatepkg = Name of .pkg file template
target = Either debug or release
@@ -86,10 +87,10 @@ Where parameters are as follows:
Example:
createpackage.pl fluidlauncher_template.pkg release-armv5
-
+
Example with certfile:
createpackage.pl -c=mycerts.txt fluidlauncher_template.pkg release-armv5
-
+
Content of 'mycerts.txt' must be something like this:
# This is comment line, also the empty lines are ignored
rd.cer;rd-key.pem
@@ -109,8 +110,12 @@ ENDUSAGESTRING
my $install = "";
my $preprocessonly = "";
my $certfile = "";
+my $preserveUnsigned = "";
-unless (GetOptions('i|install' => \$install, 'p|preprocess' => \$preprocessonly, 'c|certfile=s' => \$certfile)){
+unless (GetOptions('i|install' => \$install,
+ 'p|preprocess' => \$preprocessonly,
+ 'c|certfile=s' => \$certfile,
+ 'u|unsigned' => \$preserveUnsigned,)){
Usage();
}
@@ -134,7 +139,12 @@ my $passphrase = $ARGV[4];
# Generate output pkg basename (i.e. file name without extension)
my $pkgoutputbasename = $templatepkg;
-$pkgoutputbasename =~ s/_template\.pkg/_$targetplatform/g;
+my $preservePkgOutput = "";
+$pkgoutputbasename =~ s/_template/_$targetplatform/g;
+if ($pkgoutputbasename eq $templatepkg) {
+ $preservePkgOutput = "1";
+}
+$pkgoutputbasename =~ s/\.pkg//g;
$pkgoutputbasename = lc($pkgoutputbasename);
# Store output file names to variables
@@ -150,12 +160,20 @@ $certpath =~ s-^(.*[^\\])$-$1\\-o; # ensure path ends with a backslash
$certpath =~ s-/-\\-go; # for those working with UNIX shells
$certpath =~ s-bin\\$-src\\s60installs\\-; # certificates are one step up in hierarcy
-# Check some pre-conditions and print error messages if needed
-unless (length($templatepkg) && length($platform) && length($target)) {
- print "\nError: Template PKG filename, platform or target is not defined!\n";
+# Check some pre-conditions and print error messages if needed.
+unless (length($templatepkg)) {
+ print "\nError: Template PKG filename is not defined!\n";
Usage();
}
+# If the pkg file is not actually a template, there is no need for plaform or target.
+if ($templatepkg =~ m/_template\.pkg/i) {
+ unless (length($platform) && length($target)) {
+ print "\nError: Platform or target is not defined!\n";
+ Usage();
+ }
+}
+
# Check template exist
stat($templatepkg);
unless( -e _ ) {
@@ -192,18 +210,18 @@ if (length($certfile)) {
next if /^(\s)*$/; # skip blank lines
chomp; # remove trailing newline characters
my @certinfo = split(';', $_); # split row to certinfo
-
+
# Trim spaces
for(@certinfo) {
s/^\s+//;
s/\s+$//;
- }
-
+ }
+
# Do some validation
- unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) {
+ unless(scalar(@certinfo) >= 2 && scalar(@certinfo) <= 3 && length($certinfo[0]) && length($certinfo[1]) ) {
print "\nError: $certfile line '$_' does not contain valid information!\n";
- Usage();
- }
+ Usage();
+ }
push @certificates, [@certinfo]; # push data to two dimensional array
}
@@ -212,7 +230,9 @@ if (length($certfile)) {
# Remove any existing .sis packages
unlink $unsigned_sis_name;
unlink $signed_sis_name;
-unlink $pkgoutput;
+if (!$preservePkgOutput) {
+ unlink $pkgoutput;
+}
# Preprocess PKG
local $/;
@@ -254,10 +274,14 @@ if( -e _ ) {
system ("signsis $signed_sis_name $signed_sis_name $abscert $abskey $row->[2]");
print ("\tAdditionally signed the SIS with certificate: $row->[0]!\n");
}
-
+
# remove temporary pkg and unsigned sis
- unlink $pkgoutput;
- unlink $unsigned_sis_name;
+ if (!$preservePkgOutput) {
+ unlink $pkgoutput;
+ }
+ if (!$preserveUnsigned) {
+ unlink $unsigned_sis_name;
+ }
# Install the sis if requested
if ($install) {
diff --git a/demos/embedded/fluidlauncher/fluidlauncher.pro b/demos/embedded/fluidlauncher/fluidlauncher.pro
index 92d6e1e..f71388c 100644
--- a/demos/embedded/fluidlauncher/fluidlauncher.pro
+++ b/demos/embedded/fluidlauncher/fluidlauncher.pro
@@ -213,5 +213,7 @@ symbian {
DEPLOYMENT += config files executables viewerimages saxbookmarks reg_resource resource \
mifs desktopservices_music desktopservices_images fluidbackup
+ DEPLOYMENT.installer_header = 0xA000D7CD
+
TARGET.EPOCHEAPSIZE = 100000 20000000
}
diff --git a/doc/src/deployment/deployment.qdoc b/doc/src/deployment/deployment.qdoc
index 8ba106c..575a6dc 100644
--- a/doc/src/deployment/deployment.qdoc
+++ b/doc/src/deployment/deployment.qdoc
@@ -1573,18 +1573,13 @@
By default \c .pkg file generated by \c qmake adds support for all
S60 3rd edition FP1, S60 3rd edition FP2 and S60 5th edition devices.
- As a last step we will embed the \c qt_installer.sis file to the Wiggly
- deployment file:
+ As a last step we will instruct qmake to generate smart installer \c .pkg file by defining
+ the UID of the installation package. The UID needs to be different than the application UID,
+ and should be reserved via normal Symbian mechanisms. You can use a random UID starting with
+ \c 0xE for testing purposes:
\snippet doc/src/snippets/code/doc_src_deployment.qdoc 58
- When \c qt_installer.sis is embedded to the application deployment file, the
- end-user does not need to download and install all dependencies separately.
- The drawback of \c .sis embedding is that the application \c .sis file size becomes
- big. To address these problems Forum Nokia is planning to release a smart installer
- which will take care of downloading and installing the necessary dependencies
- over-the-air. The expected availability of smart installer is 1Q 2010.
-
Now we are ready to compile the application and create the application
deployment file. Run \c qmake to create Symbian specific makefiles, resources (\.rss)
and deployment packaging files (\c .pkg). And do build to create the
@@ -1593,13 +1588,26 @@
\snippet doc/src/snippets/code/doc_src_deployment.qdoc 59
If everything compiled and linked without any errors, we are now ready to create
- an application installation file:
+ an application package (\c wiggly.sis):
\snippet doc/src/snippets/code/doc_src_deployment.qdoc 60
- If all binaries and dependencies were found, we should now have a self-signed
- \c wiggly_release-gcce.sis ready to be installed on a device. For more information
- about creating a \c .sis file and installing it to device see also
+ Now you can create the smart installer package for the application:
+
+ \snippet doc/src/snippets/code/doc_src_deployment.qdoc 61
+
+ If all binaries and dependencies were found, you should now have a self signed
+ \c wiggly_installer.sis ready to be installed on a device. The smart installer
+ contained in the in the installer package will download the necessary dependencies
+ such as Qt libraries to the device.
+
+ \note If you want to have your application properly Symbian Signed for distribution,
+ you will have to properly sign both the application and the application installer packages.
+ Please see
+ \l{http://developer.symbian.org/wiki/index.php/Category:Symbian_Signed}
+ {Symbian Signed wiki} for more information about Symbian Signed.
+
+ For more information about creating a \c .sis file and installing it to device see also
\l {The Symbian platform - Introduction to Qt#Installing your own applications}{here}.
*/
diff --git a/doc/src/development/qmake-manual.qdoc b/doc/src/development/qmake-manual.qdoc
index d7aa0db..49e1e71 100644
--- a/doc/src/development/qmake-manual.qdoc
+++ b/doc/src/development/qmake-manual.qdoc
@@ -1431,6 +1431,18 @@ is the application private directory on the drive it is installed to.
\snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 141
+ On the Symbian platform, you can use \c{DEPLOYMENT.installer_header}
+ variable to generate smart installer wrapper for your application.
+ If you specify just UID of the installer package as the value, then
+ installer package name and version will be autogenerated:
+
+ \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 146
+
+ If autogenerated values are not suitable, you can also specify the sis
+ header yourself using this variable:
+
+ \snippet doc/src/snippets/code/doc_src_qmake-manual.qdoc 147
+
\target DEPLOYMENT_PLUGIN
\section1 DEPLOYMENT_PLUGIN
diff --git a/doc/src/snippets/code/doc_src_deployment.qdoc b/doc/src/snippets/code/doc_src_deployment.qdoc
index 7eb8808..9c00681 100644
--- a/doc/src/snippets/code/doc_src_deployment.qdoc
+++ b/doc/src/snippets/code/doc_src_deployment.qdoc
@@ -475,11 +475,7 @@ default_deployment.pkg_prerules += supported_platforms
//! [57]
//! [58]
-embedded_deployments = \
- "; Embed Qt dependencies" \
- "@\"$$[QT_INSTALL_PREFIX]/qt_installer.sis\",(0x2001E62D)"
-
-default_deployment.pkg_prerules += embedded_deployments
+DEPLOYMENT.installer_header = 0xE2345678
//! [58]
//! [59]
@@ -489,4 +485,9 @@ make release-gcce
//! [60]
make sis
-//! [60]
\ No newline at end of file
+ren wiggly_release-gcce.sis wiggly.sis
+//! [60]
+
+//! [61]
+createpackage wiggly_installer.pkg
+//! [61]
\ No newline at end of file
diff --git a/doc/src/snippets/code/doc_src_qmake-manual.qdoc b/doc/src/snippets/code/doc_src_qmake-manual.qdoc
index b1cbc72..a48b53f 100644
--- a/doc/src/snippets/code/doc_src_qmake-manual.qdoc
+++ b/doc/src/snippets/code/doc_src_qmake-manual.qdoc
@@ -963,9 +963,9 @@ RSS_RULES += myrssrules
//! [145]
//! [146]
-BLD_INF_RULES.prj_exports += \
- "$${LITERAL_HASH}include " \
- "rom/my.iby APP_LAYER_PUBLIC_EXPORT_PATH(my.iby)" \
- "inc/myheader.h mycomp/myheader.h" \
- ":zip my_api.zip my_api"
+DEPLOYMENT.installer_header = 0x12345678
//! [146]
+
+//! [147]
+DEPLOYMENT.installer_header = "$${LITERAL_HASH}{\"My Application Installer\"},(0x12345678),1,0,0"
+//! [147]
diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp
index 8f712d8..8f0abf4 100644
--- a/qmake/generators/symbian/symmake.cpp
+++ b/qmake/generators/symbian/symmake.cpp
@@ -292,12 +292,23 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
}
generatedFiles << pkgFile.fileName();
+ QTextStream t(&pkgFile);
+
+ QString installerSisHeader = project->values("DEPLOYMENT.installer_header").join("\n");
+ QString wrapperStreamBuffer;
+ QTextStream tw(&wrapperStreamBuffer);
+
+ QString dateStr = QDateTime::currentDateTime().toString(Qt::ISODate);
// Header info
- QTextStream t(&pkgFile);
- t << QString("; %1 generated by qmake at %2").arg(pkgFilename).arg(QDateTime::currentDateTime().toString(Qt::ISODate)) << endl;
- t << "; This file is generated by qmake and should not be modified by the user" << endl;
- t << ";" << endl << endl;
+ QString wrapperPkgFilename = QString("%1_installer.%2")
+ .arg(fixedTarget)
+ .arg("pkg");
+ QString headerComment = "; %1 generated by qmake at %2\n"
+ "; This file is generated by qmake and should not be modified by the user\n"
+ ";\n\n";
+ t << headerComment.arg(pkgFilename).arg(dateStr);
+ tw << headerComment.arg(wrapperPkgFilename).arg(dateStr);
// Construct QStringList from pkg_prerules since we need search it before printed to file
QStringList rawPkgPreRules;
@@ -320,8 +331,9 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
if (!containsStartWithItem('&', rawPkgPreRules)) {
// language, (*** hardcoded to english atm, should be parsed from TRANSLATIONS)
- t << "; Language" << endl;
- t << "&EN" << endl << endl;
+ QString languageCode = "; Language\n&EN\n\n";
+ t << languageCode;
+ tw << languageCode;
} else {
// In case user defines langs, he must take care also about SIS header
if (!containsStartWithItem('#', rawPkgPreRules))
@@ -330,34 +342,51 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
// name of application, UID and version
QString applicationVersion = project->first("VERSION").isEmpty() ? "1,0,0" : project->first("VERSION").replace('.', ',');
+ QString sisHeader = "; SIS header: name, uid, version\n#{\"%1\"},(%2),%3\n\n";
+ QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET")));
+ visualTarget = removePathSeparators(visualTarget);
+ QString wrapperTarget = visualTarget + " installer";
- if (!containsStartWithItem('#', rawPkgPreRules)) {
- QString visualTarget = escapeFilePath(fileFixify(project->first("TARGET")));
- visualTarget = removePathSeparators(visualTarget);
+ if (installerSisHeader.startsWith("0x", Qt::CaseInsensitive)) {
+ tw << sisHeader.arg(wrapperTarget).arg(installerSisHeader).arg(applicationVersion);
+ } else {
+ tw << installerSisHeader << endl;
+ }
- t << "; SIS header: name, uid, version" << endl;
- t << QString("#{\"%1\"},(%2),%3").arg(visualTarget).arg(uid3).arg(applicationVersion) << endl << endl;
+ if (!containsStartWithItem('#', rawPkgPreRules)) {
+ t << sisHeader.arg(visualTarget).arg(uid3).arg(applicationVersion);
}
// Localized vendor name
+ QString vendorName;
if (!containsStartWithItem('%', rawPkgPreRules)) {
- t << "; Localised Vendor name" << endl;
- t << "%{\"Vendor\"}" << endl << endl;
+ vendorName += "; Localised Vendor name\n%{\"Vendor\"}\n\n";
}
// Unique vendor name
if (!containsStartWithItem(':', rawPkgPreRules)) {
- t << "; Unique Vendor name" << endl;
- t << ":\"Vendor\"" << endl << endl;
+ vendorName += "; Unique Vendor name\n:\"Vendor\"\n\n";
}
+ t << vendorName;
+ tw << vendorName;
+
// PKG pre-rules - these are added before actual file installations i.e. SIS package body
if (rawPkgPreRules.size()) {
- t << "; Manual PKG pre-rules from PRO files" << endl;
+ QString comment = "\n; Manual PKG pre-rules from PRO files\n";
+ t << comment;
+ tw << comment;
+
foreach(QString item, rawPkgPreRules) {
+ // Only regular pkg file should have package dependencies or pkg header if that is
+ // defined using prerules.
+ if (!item.startsWith("(") && !item.startsWith("#")) {
+ tw << item << endl;
+ }
t << item << endl;
}
t << endl;
+ tw << endl;
}
// Begin Manufacturer block
@@ -380,7 +409,6 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
QString epocReleasePath = QString("%1epoc32/release/$(PLATFORM)/$(TARGET)")
.arg(epocRoot());
-
if (targetType == TypeExe) {
// deploy .exe file
t << "; Executable and default resource files" << endl;
@@ -469,6 +497,30 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
<< " - \"\", FILETEXT, TEXTEXIT" << endl
<< "ENDIF ; MANUFACTURER" << endl;
}
+
+ // Write wrapper pkg
+ if (!installerSisHeader.isEmpty()) {
+ QFile wrapperPkgFile(wrapperPkgFilename);
+ if (!wrapperPkgFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
+ PRINT_FILE_CREATE_ERROR(wrapperPkgFilename);
+ return;
+ }
+
+ generatedFiles << wrapperPkgFile.fileName();
+ QTextStream twf(&wrapperPkgFile);
+
+ twf << wrapperStreamBuffer << endl;
+
+ // Wrapped files deployment
+ QString currentPath = qmake_getpwd();
+ QString sisName = QString("%1.sis").arg(fixedTarget);
+ twf << "\"" << currentPath << "/" << sisName << "\" - \"c:\\adm\\" << sisName << "\"" << endl;
+
+ QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath);
+ bootStrapPath.append("/src/s60installs/bootstrap.sis");
+ QFileInfo fi(fileInfo(bootStrapPath));
+ twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl;
+ }
}
bool SymbianMakefileGenerator::containsStartWithItem(const QChar &c, const QStringList& src)
--
cgit v0.12
From 030c620e9f3f4e86b77a69e77a604a0c1e946229 Mon Sep 17 00:00:00 2001
From: Denis Dzyubenko
Date: Thu, 4 Feb 2010 13:30:13 +0100
Subject: Improved QTest::qWaitForWindowShown on X11.
The function is supposed to wait until the window has been managed by the
window manager on X11 - i.e. it has been reparented to a frame, mapped and
received at least one Expose event after that.
Reviewed-by: Olivier Goffart
---
src/gui/kernel/qwidget_x11.cpp | 75 +++++++++++++++++++++++++-----------------
1 file changed, 45 insertions(+), 30 deletions(-)
diff --git a/src/gui/kernel/qwidget_x11.cpp b/src/gui/kernel/qwidget_x11.cpp
index 4684bc1..007de7f 100644
--- a/src/gui/kernel/qwidget_x11.cpp
+++ b/src/gui/kernel/qwidget_x11.cpp
@@ -346,11 +346,6 @@ Q_GUI_EXPORT void qt_x11_enforce_cursor(QWidget * w)
qt_x11_enforce_cursor(w, false);
}
-static Bool checkForConfigureAndExpose(Display *, XEvent *e, XPointer)
-{
- return e->type == ConfigureNotify || e->type == Expose;
-}
-
Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
{
if (!w || (!w->isWindow() && !w->internalWinId()))
@@ -363,38 +358,58 @@ Q_GUI_EXPORT void qt_x11_wait_for_window_manager(QWidget* w)
if (!w->testAttribute(Qt::WA_WState_Created))
return;
- if (!(w->windowFlags() & Qt::X11BypassWindowManagerHint)) {
- // if the window is not override-redirect, then the window manager
- // will reparent us to the frame decoration window.
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), ReparentNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
- }
+ // first deliver events that are already in the local queue
+ QApplication::sendPostedEvents();
- while (!XCheckTypedWindowEvent(X11->display, w->effectiveWinId(), MapNotify, &ev)) {
- if (t.elapsed() > maximumWaitTime)
- return;
- qApp->syncX(); // non-busy wait
- }
+ // the normal sequence is:
+ // ... ConfigureNotify ... ReparentNotify ... MapNotify ... Expose
+ // with X11BypassWindowManagerHint:
+ // ConfigureNotify ... MapNotify ... Expose
- qApp->x11ProcessEvent(&ev);
+ enum State {
+ Initial, Reparented, Mapped
+ } state = Initial;
- // ok, seems like the window manager successfully reparented us, we'll wait
- // for the first paint event to arrive, while handling ConfigureNotify in
- // the arrival order
- while(1)
- {
- if (XCheckIfEvent(X11->display, &ev, checkForConfigureAndExpose, 0)) {
+ do {
+ if (XEventsQueued(X11->display, QueuedAlready)) {
+ XNextEvent(X11->display, &ev);
qApp->x11ProcessEvent(&ev);
- if (ev.type == Expose)
- return;
+
+ if (w->windowFlags() & Qt::X11BypassWindowManagerHint) {
+ switch (state) {
+ case Initial:
+ case Reparented:
+ if (ev.type == MapNotify)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose)
+ return;
+ break;
+ }
+ } else {
+ switch (state) {
+ case Initial:
+ if (ev.type == ReparentNotify)
+ state = Reparented;
+ break;
+ case Reparented:
+ if (ev.type == MapNotify)
+ state = Mapped;
+ break;
+ case Mapped:
+ if (ev.type == Expose)
+ return;
+ break;
+ }
+ }
+ } else {
+ if (!XEventsQueued(X11->display, QueuedAfterFlush))
+ qApp->syncX(); // non-busy wait
}
if (t.elapsed() > maximumWaitTime)
return;
- qApp->syncX(); // non-busy wait
- }
+ } while(1);
}
void qt_change_net_wm_state(const QWidget* w, bool set, Atom one, Atom two = 0)
--
cgit v0.12
From 555d5b7a87b8c3a2f207c93c7eda30892de5ecc6 Mon Sep 17 00:00:00 2001
From: Denis Dzyubenko
Date: Thu, 4 Feb 2010 13:55:36 +0100
Subject: Changed qgraphicswidget autotest to use qWaitForWindowShown.
Make use of (yet another time) improved QTest::qWaitForWindowShown.
Reviewed-by: trustme
---
tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index a7195c4..2bf1521 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -2919,11 +2919,9 @@ void tst_QGraphicsWidget::initialShow2()
scene.addItem(widget);
QGraphicsView view(&scene);
+ view.setWindowFlags(Qt::X11BypassWindowManagerHint);
view.show();
- // Not using QTest::qWaitForWindowShown(&view); on purpose, because there's
- // a bug in qt_x11_wait_for_window_manager that prevents this test
- // to pass. Denis is looking into it.
- QTest::qWait(300);
+ QTest::qWaitForWindowShown(&view);
QCOMPARE(widget->repaints, expectedRepaintCount);
}
--
cgit v0.12
From f3bd6565674f163b058bc235670d45631ce559ee Mon Sep 17 00:00:00 2001
From: Andy Shaw
Date: Thu, 4 Feb 2010 16:14:00 +0100
Subject: Another fix for the non unified title+toolbar regarding text under
icons
This makes the case where there is text under the icons in toolbuttons
and the title and toolbar is not unified on Mac. This was a regression
against Qt 4.5.x
Reviewed-by: jbache
---
src/gui/styles/qmacstyle_mac.mm | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm
index aab16cb..78074c7 100644
--- a/src/gui/styles/qmacstyle_mac.mm
+++ b/src/gui/styles/qmacstyle_mac.mm
@@ -3380,8 +3380,14 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
if (tb->toolButtonStyle != Qt::ToolButtonIconOnly) {
needText = true;
if (tb->toolButtonStyle == Qt::ToolButtonTextUnderIcon) {
- pr.setHeight(pixmap.size().height());
- cr.adjust(0, pr.bottom() + 1, 0, 1);
+ QMainWindow *mw = qobject_cast(w->window());
+ if (mw && mw->unifiedTitleAndToolBarOnMac()) {
+ pr.setHeight(pixmap.size().height());
+ cr.adjust(0, pr.bottom() + 1, 0, 1);
+ } else {
+ pr.setHeight(pixmap.size().height() + 6);
+ cr.adjust(0, pr.bottom(), 0, -3);
+ }
alignment |= Qt::AlignCenter;
} else {
pr.setWidth(pixmap.width() + 8);
--
cgit v0.12
From 07d81d0e0f15f015c7436992a99ef4b1ec36ae1c Mon Sep 17 00:00:00 2001
From: Miikka Heikkinen
Date: Thu, 4 Feb 2010 18:04:43 +0200
Subject: Fixed the location where bootstrap.sis is looked for.
Task-number: QTBUG-7908
Reviewed-by: TrustMe
---
qmake/generators/symbian/symmake.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/qmake/generators/symbian/symmake.cpp b/qmake/generators/symbian/symmake.cpp
index 8f0abf4..6c44f0b 100644
--- a/qmake/generators/symbian/symmake.cpp
+++ b/qmake/generators/symbian/symmake.cpp
@@ -517,7 +517,7 @@ void SymbianMakefileGenerator::generatePkgFile(const QString &iconFile, Deployme
twf << "\"" << currentPath << "/" << sisName << "\" - \"c:\\adm\\" << sisName << "\"" << endl;
QString bootStrapPath = QLibraryInfo::location(QLibraryInfo::PrefixPath);
- bootStrapPath.append("/src/s60installs/bootstrap.sis");
+ bootStrapPath.append("/bootstrap.sis");
QFileInfo fi(fileInfo(bootStrapPath));
twf << "@\"" << fi.absoluteFilePath() << "\",(0x2002CCCD)" << endl;
}
--
cgit v0.12
From 96a169ac3f235433906d58ac0e4c613f51c21bf3 Mon Sep 17 00:00:00 2001
From: Miikka Heikkinen
Date: Thu, 4 Feb 2010 18:16:43 +0200
Subject: My changes for 4.6.2
Reviewed-by: TrustMe
---
dist/changes-4.6.2 | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/dist/changes-4.6.2 b/dist/changes-4.6.2
index 00509ed..f5e4e57 100644
--- a/dist/changes-4.6.2
+++ b/dist/changes-4.6.2
@@ -164,6 +164,24 @@ Qt for Windows CE
-
+Qt for Symbian
+--------------
+
+- QProcess
+ * [QTBUG-7667] Fixed no-timeout case for QProcess::waitForFinished.
+
+- qmake
+ * [QTBUG-7695] Added support for ifdeffing for manufacturer in generated
+ pkg files.
+ * [QTBUG-7908] Smart installer package generation support
+
+- Patch_capabilities script
+ * Added support for embedded sis name/uid patching.
+
+- Qt deployment
+ * [QTBUG-7518] Backup and restore support for Qt libs
+
+
****************************************************************************
* Tools *
****************************************************************************
--
cgit v0.12
From 39bbc477e418d4d34c2f44fd10e76950a1ae781d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Thu, 4 Feb 2010 17:44:14 +0100
Subject: Cleanup after "QGraphicsWidget is painted twice on the first show"
Commit: dda8a57c085216db609f822837c50bae38006b4e
We don't want to reset 'updateAll' at that point, for the same reason as
mentioned in the above commit. More details in the task.
Task-number: QTBUG-6956
---
src/gui/graphicsview/qgraphicsview.cpp | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 451f183..96b9373 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -2748,7 +2748,6 @@ bool QGraphicsView::viewportEvent(QEvent *event)
}
}
}
- d->scene->d_func()->updateAll = false;
}
break;
case QEvent::TouchBegin:
--
cgit v0.12
From e2f439d8ff3529d9ef50ac58da61432627a8f350 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?=
Date: Thu, 4 Feb 2010 17:54:24 +0100
Subject: Cleanup after "Changed qgraphicswidget autotest to use
qWaitForWindowShown"
Commit: 555d5b7a87b8c3a2f207c93c7eda30892de5ecc6
We also have to do the same for the "dummyView".
---
tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index 2bf1521..00bf144 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -2901,12 +2901,10 @@ void tst_QGraphicsWidget::initialShow2()
dummyScene.addItem(new QGraphicsRectItem(0, 0, 100, 100));
QGraphicsView *dummyView = new QGraphicsView(&dummyScene);
+ dummyView->setWindowFlags(Qt::X11BypassWindowManagerHint);
EventSpy paintSpy(dummyView->viewport(), QEvent::Paint);
dummyView->show();
- // Not using QTest::qWaitForWindowShown(&view); on purpose, because there's
- // a bug in qt_x11_wait_for_window_manager that prevents this test
- // to pass. Denis is looking into it.
- QTest::qWait(300);
+ QTest::qWaitForWindowShown(dummyView);
const int expectedRepaintCount = paintSpy.count();
delete dummyView;
dummyView = 0;
--
cgit v0.12
From a2fe25025f75ae750df22c59c338005eeda3d744 Mon Sep 17 00:00:00 2001
From: David Boddie
Date: Thu, 4 Feb 2010 21:17:42 +0100
Subject: Doc: Added Simplified Chinese documents and build rules for them.
Also updated qdoc's configuration reader so that we can put UTF-8
content in the .qdocconf files later.
Reviewed-by: Trust Me
---
doc/doc.pri | 11 +-
doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc | 96 +++
doc/src/zh_CN/getting-started/tutorials.qdoc | 103 ++++
doc/src/zh_CN/tutorials/addressbook.qdoc | 673 +++++++++++++++++++++
doc/src/zh_CN/tutorials/widgets-tutorial.qdoc | 244 ++++++++
tools/qdoc3/config.cpp | 4 +-
6 files changed, 1129 insertions(+), 2 deletions(-)
create mode 100644 doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc
create mode 100644 doc/src/zh_CN/getting-started/tutorials.qdoc
create mode 100644 doc/src/zh_CN/tutorials/addressbook.qdoc
create mode 100644 doc/src/zh_CN/tutorials/widgets-tutorial.qdoc
diff --git a/doc/doc.pri b/doc/doc.pri
index 463c447..ccbef1a 100644
--- a/doc/doc.pri
+++ b/doc/doc.pri
@@ -30,8 +30,14 @@ QT_DOCUMENTATION = ($$QDOC qt-api-only.qdocconf assistant.qdocconf designer.qdoc
$$GENERATOR doc-build/html-qmake/qmake.qhp -o doc/qch/qmake.qch \
)
+QT_ZH_CN_DOCUMENTATION = ($$QDOC qt-api-only_zh_CN.qdocconf) && \
+ (cd $$QT_BUILD_TREE && \
+ $$GENERATOR doc-build/html-qt_zh_CN/qt.qhp -o doc/qch/qt_zh_CN.qch \
+ )
+
win32-g++:isEmpty(QMAKE_SH) {
QT_DOCUMENTATION = $$replace(QT_DOCUMENTATION, "/", "\\\\")
+ QT_ZH_CN_DOCUMENTATION = $$replace(QT_ZH_CN_DOCUMENTATION, "/", "\\\\")
}
# Build rules:
@@ -42,6 +48,9 @@ qch_docs.depends += sub-tools
docs.depends = adp_docs qch_docs
+docs_zh_CN.depends = docs
+docs_zh_CN.commands = $$QT_ZH_CN_DOCUMENTATION
+
# Install rules
htmldocs.files = $$QT_BUILD_TREE/doc/html
htmldocs.path = $$[QT_INSTALL_DOCS]
@@ -54,5 +63,5 @@ qchdocs.CONFIG += no_check_exist
docimages.files = $$QT_BUILD_TREE/doc/src/images
docimages.path = $$[QT_INSTALL_DOCS]/src
-QMAKE_EXTRA_TARGETS += qdoc adp_docs qch_docs docs
+QMAKE_EXTRA_TARGETS += qdoc adp_docs qch_docs docs docs_zh_CN
INSTALLS += htmldocs qchdocs docimages
diff --git a/doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc b/doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc
new file mode 100644
index 0000000..5f95dde
--- /dev/null
+++ b/doc/src/zh_CN/getting-started/how-to-learn-qt.qdoc
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation 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$
+**
+****************************************************************************/
+
+/*!
+ \page how-to-learn-qt.html
+ \title 如何å¦ä¹ Qt
+ \brief Links to guides and resources for learning Qt.
+ \nextpage Tutorials
+
+ \section1 Getting Started
+
+ 我们å‡å®šæ‚¨å·²äº†è§£ C++, 并将用于 Qt å¼€å‘。有关将 Qt 与其他编程è¯è¨€ä¸€èµ·ä½¿ç”¨çš„更多信æ¯ï¼Œè¯·å‚è§ \l{Qt website}{Qt 网站}。
+
+ å¦‚æžœä½ æƒ³ä»…ä½¿ç”¨ C++ 编程, ä¸ä½¿ç”¨ä»»ä½•è®¾è®¡å·¥å…·è€Œä»…使用代ç 设计用户界é¢ï¼Œè¯·è§‚看\l{教程}。这些教程是为您了解 Qt 编程é‡èº«å®šåšçš„,并侧é‡äºŽç¼–写å¯ç”¨ä»£ç ,而并éžåŠŸèƒ½ç®€ä»‹ã€‚
+
+ 如果您想使用设计工具æ¥è®¾è®¡ç”¨æˆ·ç•Œé¢ï¼Œåˆ™è‡³å°‘è¦é˜…读 \l{Qt Designer manual}{Qt 设计者手册}çš„å‰å‡ ç« ã€‚
+
+ 现在您已ç»ç¼–写了一些å°åž‹å¯ç”¨çš„应用程åºï¼Œå¹¶å¯¹ Qt ç¼–ç¨‹æœ‰æ›´åŠ å¹¿æ³›çš„äº†è§£ã€‚æ‚¨å¯ä»¥ç›´æŽ¥ç€æ‰‹åšè‡ªå·±çš„é¡¹ç›®ï¼Œä½†æˆ‘ä»¬å»ºè®®æ‚¨é˜…è¯»ä»¥ä¸‹ä¸€äº›å…³é”®ç®€ä»‹ä»¥åŠ æ·±æ‚¨å¯¹ Qt 的了解:\l{Qt Object Model}Qt 对象模型}å’Œ\l{Signals and Slots}{ä¿¡å·å’Œæ§½}。
+
+ \beginfloatleft
+ \inlineimage qtdemo-small.png
+ \endfloat
+
+ \section1 了解概况
+
+ 在这个阶段,我们建议您æµè§ˆä¸€ä¸‹\l{All Overviews and HOWTOs}{简介},然åŽé˜…è¯»ä¸Žæ‚¨é¡¹ç›®ç›¸å…³çš„ç« èŠ‚ã€‚æ‚¨å¯èƒ½è¿˜ä¼šå‘现,æµè§ˆä¸Žæ‚¨é¡¹ç›®ç±»ä¼¼çš„\l{Qt Examples}{示例}çš„æºä»£ç 也会对您有所帮助。由于 Qt æºä»£ç å·²é¢å‘公众开放,您也å¯é˜…读 Qt æºä»£ç 。
+
+ 如果您è¿è¡Œ\l{Examples and Demos Launcher}{示例和演示å¯åŠ¨ç¨‹åº},您就会看到许多æ£åœ¨ä½¿ç”¨çš„ Qt widget。
+
+ \l{Qt Widget Gallery} 还按照在ä¸åŒæ”¯æŒå¹³å°ä¸Šçš„ä½¿ç”¨é£Žæ ¼æ供了精选 Qt widget 简介。
+ \clearfloat
+
+ \section1 Books and Learning Materials
+
+ Qt 附带大é‡æ–‡æ¡£ï¼Œå¹¶å…¨æ–‡å¸¦æœ‰è¶…文本交å‰å¼•ç”¨ï¼Œå¯è½»æ¾åœ°ç‚¹å‡»äº†è§£è‡ªå·±æƒ³çŸ¥é“的内容。您使用最多的文档å¯èƒ½æ˜¯ \l{index.html}{API 引用}。æ¯ä¸ªé“¾æŽ¥éƒ½æ供了æµè§ˆ API 引用的ä¸åŒæ–¹å¼ï¼Œæ‚¨å¯æ¯ä¸ªéƒ½å°è¯•ä¸€ä¸‹ï¼Œçœ‹å“ªä¸ªæ›´é€‚åˆè‡ªå·±ã€‚您还å¯ä»¥å°è¯• \l{Qt Assistant}ï¼Œè¿™æ˜¯éš Qt 附带的工具,å¯è®¿é—®å…¨éƒ¨ Qt API,并æ供全文本æœç´¢åŠŸèƒ½ã€‚
+
+ 有大é‡çš„书ç±æ˜¯å…³äºŽ Qt 编程的。有关 Qt 书ç±çš„完整列表。
+ We recommend the official Qt book,
+ \l{http://www.amazon.com/gp/product/0132354160/ref=ase_trolltech/}{C++
+ GUI Programming with Qt 4, Second Edition} (ISBN 0-13-235416-0).
+ 本书从 "Hello Qt" 到高级功能(如多线程ã€2D å’Œ 3D 图形ã€ç½‘络ã€å†…容视图类与 XML),全é¢è¯¦å®žåœ°è¯´æ˜Žäº† Qt 编程。(第一版基于 Qt 4.1,å¯\l{http://www.qtrac.eu/C++-GUI-Programming-with-Qt-4-1st-ed.zip}{在线}获得。)
+
+ 包括ä¸åŒè¯è¨€çš„翻译版本,请å‚è§\l{Books about Qt Programming}{有关 Qt 编程的书ç±}。
+
+ å¦ä¸€ä¸ªæœ‰å…³å®žä¾‹ä»£ç å’Œ Qt 功能说明的有用资æºå°±æ˜¯å˜æ¡£çš„ \l{Qt Quarterly}{Qt å£è®¯}æ–‡ç« ï¼Œå£è®¯æ˜¯ä¸º Qt 用户æ供的新闻时讯。
+
+ 有关特定 Qt 模å—和其他指å—的文档,请å‚è§\l{All Overviews and HOWTOs}。
+
+ \section1 Further Reading
+
+ Qt has an active and helpful user community who communicate using
+ the \l{Qt Mailing Lists}{qt-interest} mailing list, the \l{Qt Centre}
+ Web site, and a number of other community Web sites and Weblogs.
+ In addition, many Qt developers are active members of the
+ \l{KDE}{KDE community}.
+
+ ç¥æ‚¨å¥½è¿å¹¶ä¸”å¦ä¹ 愉快ï¼
+*/
diff --git a/doc/src/zh_CN/getting-started/tutorials.qdoc b/doc/src/zh_CN/getting-started/tutorials.qdoc
new file mode 100644
index 0000000..56d147e
--- /dev/null
+++ b/doc/src/zh_CN/getting-started/tutorials.qdoc
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation 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$
+**
+****************************************************************************/
+
+/*!
+ \page tutorials.html
+ \title Tutorials
+
+ \contentspage How to Learn Qt
+ \nextpage Qt Examples
+
+ \brief Tutorials, guides and overviews to help you learn Qt.
+
+ \nextpage Qt Examples
+
+ A collection of tutorials and "walkthrough" guides are provided with Qt to
+ help new users get started with Qt development. These documents cover a
+ range of topics, from basic use of widgets to step-by-step tutorials that
+ show how an application is put together.
+
+ \table
+ \row
+ \o{2,1} \l{Widgets 教程}{\bold Widgets}
+ \o{2,1} \l{地å€ç°¿æ•™ç¨‹}{\bold {地å€ç°¿}}
+ \row
+ \o \image widget-examples.png Widgets
+ \o
+ A beginner's guide to getting started with widgets and layouts to create
+ GUI applications.
+
+ \o \image addressbook-tutorial.png 地å€ç°¿
+ \o
+ A seven part guide to creating a fully-functioning address book
+ application. This tutorial is also available with
+ \l{Tutoriel "Carnet d'adresses"}{French explanation}.
+
+ \row
+ \o{2,1} \l{A Quick Start to Qt Designer}{\bold{Qt Designer}}
+ \o{2,1} \l{Qt Linguist Manual: Programmers#Tutorials}{\bold {Qt Linguist}}
+ \row
+ \o \image designer-examples.png QtDesigner
+ \o
+ A quick guide through \QD showing the basic steps to create a
+ form with this interactive tool.
+
+ \o \image linguist-examples.png QtLinguist
+ \o
+ A guided tour through the translations process, explaining the
+ tools provided for developers, translators and release managers.
+
+ \row
+ \o{2,1} \l{QTestLib Tutorial}{\bold QTestLib}
+ \o{2,1} \l{qmake Tutorial}{\bold qmake}
+ \row
+ \o{2,1}
+ This tutorial gives a short introduction to how to use some of the
+ features of Qt's unit-testing framework, QTestLib. It is divided into
+ four chapters.
+
+ \o{2,1}
+ This tutorial teaches you how to use \c qmake. We recommend that
+ you read the \l{qmake Manual}{qmake user guide} after completing
+ this tutorial.
+
+ \endtable
+*/
diff --git a/doc/src/zh_CN/tutorials/addressbook.qdoc b/doc/src/zh_CN/tutorials/addressbook.qdoc
new file mode 100644
index 0000000..5bd0d35
--- /dev/null
+++ b/doc/src/zh_CN/tutorials/addressbook.qdoc
@@ -0,0 +1,673 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation 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$
+**
+****************************************************************************/
+
+/*!
+ \page tutorials-addressbook.html
+
+ \startpage {index.html}{Qt Reference Documentation}
+ \contentspage Tutorials
+ \nextpage {tutorials/addressbook/part1}{ç¬¬ä¸€ç« }
+
+ \title 地å€ç°¿æ•™ç¨‹
+ \brief 本教程介ç»äº†ä½¿ç”¨ Qt 跨平å°æ¡†æž¶çš„ GUI 编程。
+
+ 本教程介ç»äº†ä½¿ç”¨ Qt 跨平å°æ¡†æž¶çš„ GUI 编程。
+
+ \image addressbook-tutorial-screenshot.png
+
+ \omit
+ It doesn't cover everything; the emphasis is on teaching the programming
+ philosophy of GUI programming, and Qt's features are introduced as needed.
+ Some commonly used features are never used in this tutorial.
+ \endomit
+
+ 在å¦ä¹ 过程ä¸ï¼Œæˆ‘们将了解部分 Qt 基本技术,如
+
+ \list
+ \o Widget 和布局管ç†å™¨
+ \o 容器类
+ \o ä¿¡å·å’Œæ§½
+ \o 输入和输出设备
+ \endlist
+
+ 如果您完全ä¸äº†è§£ Qt,请阅读\l{How to Learn Qt}{如何å¦ä¹ Qt}(如果您还未阅读)。
+
+ 教程的æºä»£ç ä½äºŽ Qt çš„ \c examples/tutorials/addressbook 目录下。
+
+ æ•™ç¨‹ç« èŠ‚ï¼š
+
+ \list 1
+ \o \l{tutorials/addressbook/part1}{设计用户界é¢}
+ \o \l{tutorials/addressbook/part2}{æ·»åŠ åœ°å€}
+ \o \l{tutorials/addressbook/part3}{æµè§ˆåœ°å€ç°¿æ¡ç›®}
+ \o \l{tutorials/addressbook/part4}{ç¼–è¾‘å’Œåˆ é™¤åœ°å€}
+ \o \l{tutorials/addressbook/part5}{æ·»åŠ æŸ¥æ‰¾åŠŸèƒ½}
+ \o \l{tutorials/addressbook/part6}{åŠ è½½å’Œä¿å˜}
+ \o \l{tutorials/addressbook/part7}{é™„åŠ åŠŸèƒ½}
+ \endlist
+
+ 虽然这个å°åž‹åº”用程åºçœ‹èµ·æ¥å¹¶ä¸è±¡ä¸€ä¸ªæˆç†Ÿçš„现代 GUI 应用程åºï¼Œä½†å®ƒä½¿ç”¨å¤šç§ç”¨äºŽæ›´å¤æ‚应用程åºçš„基本技术。在您完æˆå¦ä¹ 之åŽï¼Œæˆ‘们建议您查看一下\l{mainwindows/application}{应用程åº}示例,它æ供带有èœå•ã€å·¥å…·æ ã€çŠ¶æ€æ ç‰é¡¹ç›®çš„å°åž‹ GUI 应用程åºã€‚
+*/
+
+/*!
+ \page tutorials-addressbook-part1.html
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \nextpage {tutorials/addressbook/part2}{ç¬¬äºŒç« }
+ \example tutorials/addressbook/part1
+ \title 地å€ç°¿ 1 — 设计用户界é¢
+
+ 本教程的第一部分讲述了用于地å€ç°¿åº”用程åºçš„åŸºæœ¬å›¾å½¢ç”¨æˆ·ç•Œé¢ (GUI) 的设计。
+
+ 创建 GUI 程åºçš„第一æ¥å°±æ˜¯è®¾è®¡ç”¨æˆ·ç•Œé¢ã€‚åœ¨æœ¬ç« ä¸ï¼Œæˆ‘ä»¬çš„ç›®æ ‡æ˜¯è®¾ç½®åº”ç”¨åŸºæœ¬åœ°å€ç°¿åº”用程åºæ‰€éœ€çš„æ ‡ç¾å’Œè¾“å…¥å—段。下图为期望输出的å±å¹•æˆªå›¾ã€‚
+
+ \image addressbook-tutorial-part1-screenshot.png
+
+ 我们需è¦ä½¿ç”¨ä¸¤ä¸ª QLabel 对象:\c nameLabel å’Œ \c addressLabel,以åŠä¸¤ä¸ªè¾“å…¥å—段:QLineEdit 对象 \c nameLine å’Œ QTextEdit
+ 对象 \c addressTextï¼Œè¿™æ ·ç”¨æˆ·æ‰èƒ½è¾“å…¥è”系人的姓å和地å€ã€‚使用的 widget åŠå…¶ä½ç½®å¦‚下图所示。
+
+ \image addressbook-tutorial-part1-labeled-screenshot.png
+
+ è¦åº”用地å€ç°¿éœ€ä½¿ç”¨ä¸‰ä¸ªæ–‡ä»¶ï¼š
+
+ \list
+ \o \c{addressbook.h} — AddressBook 类的定义文件,
+ \o \c{addressbook.cpp} — AddressBook 类的执行文件,以åŠ
+ \o \c{main.cpp} — åŒ…å« \c main() 函数并带有 AddressBook 实例的文件。
+ \endlist
+
+ \section1 Qt 编程 — 使用åç±»
+
+ 在编写 Qt 程åºæ—¶ï¼Œæˆ‘们通常使用 Qt 对象åç±»æ¥æ·»åŠ 功能。这是创建定制 widget æˆ–æ ‡å‡† widget 集åˆçš„基本概念之一。使用åç±»æ‰©å±•æˆ–æ”¹å˜ widget çš„æ“作具有以下优势:
+
+ \list
+ \o 我们å¯ä»¥ç¼–写虚函数或纯虚函数应用,以得到我们确切所需的功能,并在需è¦æ—¶å†ä½¿ç”¨åŸºæœ¬çš„类应用。
+ \o è¿™æ ·æˆ‘ä»¬å°±å¯ä»¥åœ¨ç±»ä¸å°è£…部分用户界é¢ï¼Œåº”用程åºçš„å…¶ä»–éƒ¨åˆ†ä¹Ÿå°±æ— éœ€äº†è§£ç”¨æˆ·ç•Œé¢ä¸å•ç‹¬ä½¿ç”¨çš„ widget。
+ \o å¯ä½¿ç”¨å类在åŒä¸€åº”用程åºæˆ–库ä¸åˆ›å»ºå¤šä¸ªå®šåˆ¶ widgetï¼Œè¿™æ ·å类的代ç å¯åœ¨å…¶ä»–项目é‡å¤ä½¿ç”¨ã€‚
+ \endlist
+
+ 由于 Qt 未æ供特定的地å€ç°¿ widgetï¼Œæˆ‘ä»¬åœ¨æ ‡å‡†çš„ Qt widget ç±»ä¸ä½¿ç”¨å类,然åŽæ·»åŠ 功能。我们在本教程ä¸åˆ›å»ºçš„ \c AddressBook 类在需è¦ä½¿ç”¨åŸºæœ¬åœ°å€ç°¿ widget 的情况下å¯é‡å¤ä½¿ç”¨ã€‚
+
+ \section1 定义 AddressBook 类
+
+ \l{tutorials/addressbook/part1/addressbook.h}{\c addressbook.h} 文件用于定义 \c AddressBook 类。
+
+ 我们从定义 \c AddressBook 为 QWidget åç±»å’Œå£°æ˜Žæž„é€ å™¨å¼€å§‹å…¥æ‰‹ã€‚æˆ‘ä»¬è¿˜ä½¿ç”¨ Q_OBJECT å®è¡¨æ˜Žè¯¥ç±»ä½¿ç”¨å›½é™…化功能与 Qt ä¿¡å·å’Œæ§½åŠŸèƒ½ï¼Œå³ä½¿åœ¨æœ¬é˜¶æ®µä¸ä¼šç”¨åˆ°æ‰€æœ‰è¿™äº›åŠŸèƒ½ã€‚
+
+ \snippet tutorials/addressbook/part1/addressbook.h class definition
+
+ 该类包å«äº† \c nameLine å’Œ \c addressText 的声明ã€ä¸Šæ–‡æ到的 QLineEdit å’Œ QTextEdit çš„ç§æœ‰å®žä¾‹ã€‚在以åŽç« 节ä¸ï¼Œæ‚¨ä¼šçœ‹åˆ°å‚¨å˜åœ¨ \c nameLine å’Œ \c addressText ä¸çš„æ•°æ®åœ¨åœ°å€ç°¿çš„许多功能ä¸éƒ½ä¼šç”¨åˆ°ã€‚
+
+ 我们ä¸å¿…包å«è¦ä½¿ç”¨çš„ QLabel å¯¹è±¡çš„å£°æ˜Žï¼Œè¿™æ˜¯å› ä¸ºåœ¨åˆ›å»ºè¿™äº›å¯¹è±¡åŽæˆ‘们ä¸å¿…对其进行引用。在下一部分ä¸ï¼Œæˆ‘们会说明 Qt 记录对象所属关系的方å¼ã€‚
+
+ Q_OBJECT å®æœ¬èº«åº”用了部分更高级的 Qt 功能。 我们暂时把 Q_OBJECT å®ç†è§£ä¸ºä½¿ç”¨ \l{QObject::}{tr()} å’Œ \l{QObject::}{connect()} 函数的快æ·æ–¹å¼ï¼Œè¿™ç§ç†è§£å¯¹æˆ‘们的å¦ä¹ 更有用。
+
+ æˆ‘ä»¬çŽ°å·²å®Œæˆ \c addressbook.h 文件,接下æ¥æˆ‘们æ¥æ‰§è¡Œå¯¹åº”çš„ \c addressbook.cpp 文件。
+
+ \section1 应用 AddressBook 类
+
+ \c AddressBook çš„æž„é€ å™¨æŽ¥æ”¶ QWidget å‚æ•° \a parent。按惯例,我们将å‚æ•°ä¼ é€’ç»™åŸºæœ¬ç±»çš„æž„é€ å™¨ã€‚è¿™ç§çˆ¶é¡¹å¯æœ‰ä¸€ä¸ªæˆ–多个å项的所属概念对 Qt ä¸çš„ widget 分组ååˆ†æœ‰ç”¨ã€‚ä¾‹å¦‚ï¼Œå¦‚æžœåˆ é™¤çˆ¶é¡¹ï¼Œä¹Ÿä¼šåˆ é™¤å…¶æ‰€æœ‰å项。
+
+ \snippet tutorials/addressbook/part1/addressbook.cpp constructor and input fields
+
+ åœ¨è¯¥æž„é€ å™¨ä¸ï¼Œæˆ‘们声明并通过实例æ¥è¡¨ç¤ºä¸¤ä¸ªå±€éƒ¨ QLabel 对象 \c nameLabel å’Œ \c addressLabelï¼Œä»¥åŠ \c nameLine å’Œ \c addressText。如果å—符串已进行转æ¢ï¼Œåˆ™ \l{QObject::tr()}{tr()} 函数返回已转æ¢çš„å—符串,å¦åˆ™è¿”回å—符串本身。我们å¯ä»¥å°†æ¤å‡½æ•°ç†è§£ \c{} æ ‡è¯†æ¥æ ‡è®°è¦è¿›è¡Œè½¬æ¢ QString 对象。在以åŽç« 节和 \l{Qt Examples} ä¸ï¼Œæ‚¨ä¼šçœ‹åˆ°åªè¦ä½¿ç”¨äº†å¯è½¬æ¢çš„å—符串就是使用该函数。
+
+ 使用 Qt 编程时,了解布局是如何起作用的会对您很有帮助。Qt æ供三个主è¦å¸ƒå±€ç±» QHBoxLayoutã€QVBoxLayout å’Œ QGridLayout æ¥å¤„ç† widget çš„ä½ç½®ã€‚
+
+ \image addressbook-tutorial-part1-labeled-layout.png
+
+ 我们使用 QGridLayout 以结构化的方å¼æ”¾ç½®æ ‡ç¾å’Œè¾“å…¥å—段。QGridLayout å°†å¯ç”¨ç©ºé—´åˆ†ä¸ºç½‘æ ¼ï¼Œå¹¶å°† widget 放置在指定了行列å·çš„å•å…ƒæ ¼ä¸ã€‚上é¢çš„图表显示了布局å•å…ƒæ ¼å’Œ widget çš„ä½ç½®ã€‚我们通过以下代ç 指定这ç§æŽ’列方å¼ï¼š
+
+ \snippet tutorials/addressbook/part1/addressbook.cpp layout
+
+ 请注æ„,\c addressLabel æ˜¯ä½¿ç”¨ä½œä¸ºé™„åŠ å‚æ•°çš„ Qt::AlignTop æ¥æŽ’放ä½ç½®ã€‚è¿™å¯ç¡®ä¿å…¶ä¸ä¼šçºµå‘放置在å•å…ƒæ ¼ (1,0) ä¸å¤®ã€‚有关 Qt 布局的基本简介,请å‚è§\l{Layout Management}{布局类}文档。
+
+ è¦åœ¨ widget 上安装布局对象,必须调用 widget çš„ \l{QWidget::setLayout()}{setLayout()} 函数:
+
+ \snippet tutorials/addressbook/part1/addressbook.cpp setting the layout
+
+ 最åŽï¼Œæˆ‘们将 widget æ ‡é¢˜è®¾ç½®ä¸ºâ€œç®€å•åœ°å€ç°¿â€ã€‚
+
+ \section1 è¿è¡Œåº”用程åº
+
+ \c main() 函数使用å•ç‹¬çš„文件 \c main.cpp。在该函数ä¸ï¼Œæˆ‘们实例化了 QApplication 对象 \c app。QApplication 负责管ç†å¤šç§åº”用范围的资æºï¼ˆå¦‚默认å—ä½“å’Œå…‰æ ‡ï¼‰ï¼Œä»¥åŠè¿è¡Œäº‹ä»¶å¾ªçŽ¯ã€‚å› æ¤ï¼Œåœ¨æ¯ä¸ªä½¿ç”¨ Qt çš„ GUI 应用程åºä¸éƒ½ä¼šæœ‰ä¸€ä¸ª QApplication 对象。
+
+ \snippet tutorials/addressbook/part1/main.cpp main function
+
+ 我们使用 new 关键å—åœ¨å †ä¸æž„é€ ä¸€ä¸ªæ–°çš„ \c AddressBook widget,然åŽè°ƒç”¨ \l{QWidget::show()}{show()} 函数对其进行显示。ä¸è¿‡ï¼Œè¯¥ widget åªæœ‰åœ¨åº”用程åºäº‹ä»¶å¾ªçŽ¯å¼€å§‹æ—¶æ‰ä¼šæ˜¾ç¤ºã€‚我们通过调用应用程åºçš„ \l{QApplication::}{exec()} 函数开始事件循环。该函数返回的结果作为 \c main() 函数的返回值。
+*/
+
+/*!
+ \page tutorials-addressbook-part2.html
+ \previouspage 地å€ç°¿ 1 — 设计用户接å£
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \nextpage {tutorials/addressbook/part3}{ç¬¬ä¸‰ç« }
+ \example tutorials/addressbook/part2
+ \title 地å€ç°¿ 2 — æ·»åŠ åœ°å€
+
+ 创建基本地å€ç°¿åº”用程åºçš„下一æ¥æ˜¯æ·»åŠ 少许用户互动æ“作。
+
+ \image addressbook-tutorial-part2-add-contact.png
+
+ 我们将æ供一个按钮,用户å¯ç‚¹å‡»è¯¥æŒ‰é’®æ¥æ·»åŠ æ–°è”系人。æ¤å¤–,还需è¦å¯¹æ•°æ®ç»“构进行é™å®šï¼Œä»¥ä¾¿æœ‰åºåœ°å‚¨å˜è¿™äº›è”系人。
+
+ \section1 定义 AddressBook 类
+
+ 由于已ç»è®¾ç½®äº†æ ‡ç¾å’Œè¾“å…¥å—段,我们åªéœ€æ·»åŠ 按钮就å¯å®Œæˆæ·»åŠ è”系人这一æ¥éª¤ã€‚也就是说,在 \c addressbook.h 文件ä¸å·²ç»å£°æ˜Žäº†ä¸‰ä¸ª QPushButton 对象和三个对应的公共槽。
+
+ \snippet tutorials/addressbook/part2/addressbook.h slots
+
+ 槽是对特殊信å·è¿›è¡Œå“应的函数。我们将在应用 \c AddressBook 类时进一æ¥è¯¦ç»†è¯´æ˜Žè¿™ä¸€æ¦‚念。如需有关 Qt ä¿¡å·å’Œæ§½æ¦‚念的简介,请å‚è§\l{Signals and Slots}{ä¿¡å·å’Œæ§½}文档。
+
+ 三个 QPushButton 对象分别是 \c addButtonã€\c submitButton å’Œ \c cancelButton,已与è¦åœ¨ä¸Šä¸€ç« ä¸è¯´æ˜Žçš„ \c nameLine å’Œ \c addressText 一åŒåŒ…å«åœ¨ç§æœ‰å˜é‡å£°æ˜Žä¸ã€‚
+
+ \snippet tutorials/addressbook/part2/addressbook.h pushbutton declaration
+
+ 我们需è¦ä¸€ä¸ªå®¹å™¨æ¥å‚¨å˜åœ°å€ç°¿è”ç³»äººï¼Œè¿™æ ·æ‰èƒ½æœç´¢å’Œæ˜¾ç¤ºè”系人。QMap 对象 \c contacts å°±å¯å®žçŽ°æ¤åŠŸèƒ½ï¼Œå› 为其带有一个键-值对:è”系人姓å作为键,而è”系人地å€ä½œä¸º\e{值}。
+
+ \snippet tutorials/addressbook/part2/addressbook.h remaining private variables
+
+ 我们还会声明两个ç§æœ‰ QString 对象:\c oldName å’Œ \c oldAddress。这些对象用æ¥ä¿ç•™åœ¨ç”¨æˆ·ç‚¹å‡»\gui{æ·»åŠ }时最åŽæ˜¾ç¤ºçš„è”系人姓å和地å€ã€‚è¿™æ ·ï¼Œå½“ç”¨æˆ·ç‚¹å‡»\gui{å–消}时,我们就å¯ä»¥è¿”回至上一个è”系人的详细信æ¯ã€‚
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook æž„é€ å™¨ä¸ï¼Œæˆ‘们将 \c nameLine å’Œ \c addressText 设置为åªè¯»ï¼Œè¿™æ ·å°±å¯ä»…显示而ä¸å¿…编辑现有è”系人的详细信æ¯ã€‚
+
+ \dots
+ \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 1
+ \dots
+ \snippet tutorials/addressbook/part2/addressbook.cpp setting readonly 2
+
+ 然åŽï¼Œæˆ‘们实例化以下按钮:\c addButtonã€\c submitButton å’Œ \c cancelButton。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp pushbutton declaration
+
+ 显示 \c addButton 是通过调用 \l{QPushButton::show()}{show()} 函数实现的,而éšè— \c submitButton å’Œ \c cancelButton 则需调用 \l{QPushButton::hide()}{hide()}。这两个按钮仅当用户点击\gui{æ·»åŠ }æ—¶æ‰ä¼šæ˜¾ç¤ºï¼Œè€Œæ¤æ“作是通过在下文ä¸è¯´æ˜Žçš„\c addContact() 函数处ç†çš„。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp connecting signals and slots
+
+ 我们将按钮的 \l{QPushButton::clicked()}{clicked()} ä¿¡å·ä¸Žå…¶ç›¸åº”的槽关è”。下é¢çš„图表说明了æ¤è¿‡ç¨‹ã€‚
+
+ \image addressbook-tutorial-part2-signals-and-slots.png
+
+ 接下æ¥ï¼Œæˆ‘们将按钮整é½çš„排列在地å€ç°¿ widget çš„å³ä¾§ï¼Œä½¿ç”¨ QVBoxLayout 将其进行纵å‘排列。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp vertical layout
+
+ \l{QBoxLayout::addStretch()}{addStretch()} 函数用æ¥ç¡®ä¿æŒ‰é’®å¹¶ä¸æ˜¯é‡‡ç”¨å‡åŒ€é—´éš”排列的,而是更é è¿‘ widget 的顶部。下图显示了是å¦ä½¿ç”¨ \l{QBoxLayout::addStretch()}{addStretch()} 的差别。
+
+ \image addressbook-tutorial-part2-stretch-effects.png
+
+ 然åŽï¼Œæˆ‘们使用 \l{QGridLayout::addLayout()}{addLayout()} å°† \c buttonLayout1 å¢žåŠ è‡³ \c mainLayout。 è¿™æ ·æˆ‘ä»¬å°±æœ‰äº†åµŒå¥—å¸ƒå±€ï¼Œå› ä¸º \c buttonLayout1 现在是 \c mainLayout çš„å项。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp grid layout
+
+ 布局åæ ‡æ˜¾ç¤ºå¦‚ä¸‹ï¼š
+
+ \image addressbook-tutorial-part2-labeled-layout.png
+
+ 在 \c addContact() 函数ä¸ï¼Œæˆ‘们使用 \c oldName å’Œ \c oldAddress 储å˜æœ€åŽæ˜¾ç¤ºçš„è”系人详细信æ¯ã€‚然åŽï¼Œæˆ‘们清空这些输入å—段并关é—åªè¯»æ¨¡å¼ã€‚输入焦点设置在 \c nameLine,显示 \c submitButton å’Œ \c cancelButton。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp addContact
+
+ \c submitContact() 函数å¯åˆ†ä¸ºä¸‰ä¸ªéƒ¨åˆ†ï¼š
+
+ \list 1
+ \o 我们从 \c nameLine å’Œ \c addressText æå–è”系人的详细信æ¯ï¼Œç„¶åŽå°†å…¶å‚¨å˜åœ¨ QString 对象ä¸ã€‚我们还è¦éªŒè¯ç¡®ä¿ç”¨æˆ·æ²¡æœ‰åœ¨è¾“å…¥å—段为空时点击\gui{æ交},å¦åˆ™ï¼Œä¼šæ˜¾ç¤º QMessageBox æ示用户输入姓å和地å€ã€‚
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part1
+
+ \o 我们接ç€ç»§ç»æ£€æŸ¥æ˜¯å¦è”系人已å˜åœ¨ã€‚如果ä¸å˜åœ¨ï¼Œå°†è”ç³»äººæ·»åŠ è‡³ \c contacts,然åŽæ˜¾ç¤º QMessageBox æç¤ºç”¨æˆ·å·²æ·»åŠ è”系人。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part2
+
+ 如果è”系人已å˜åœ¨ï¼Œè¿˜æ˜¯ä¼šæ˜¾ç¤º QMessageBox 以æ示用户,以å…æ·»åŠ é‡å¤çš„è”系人。由于 \c contacts 对象是基于姓å地å€çš„é”®-å€¼å¯¹ï¼Œå› æ¤è¦ç¡®ä¿é”®å”¯ä¸€ã€‚
+
+ \o 在处ç†äº†ä¸Šè¿°ä¸¤ç§æƒ…况åŽï¼Œä½¿ç”¨ä»¥ä¸‹ä»£ç 将按钮æ¢å¤ä¸ºæ£å¸¸çŠ¶æ€ï¼š
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp submitContact part3
+
+ \endlist
+
+ 下é¢çš„å±å¹•æˆªå›¾æ˜¾ç¤ºäº†ç”¨äºŽå‘用户显示æ示信æ¯çš„ QMessageBox 对象。
+
+ \image addressbook-tutorial-part2-add-successful.png
+
+ \c cancel() 函数æ¢å¤ä¸Šæ¬¡æ˜¾ç¤ºçš„è”系人详细信æ¯ï¼Œå¹¶å¯ç”¨ \c addButton,还会éšè— \c submitButton å’Œ
+ \c cancelButton。
+
+ \snippet tutorials/addressbook/part2/addressbook.cpp cancel
+
+ æ·»åŠ è”系人的总体æ€æƒ³å°±æ˜¯æ高用户æ“作的çµæ´»æ€§ï¼Œå¯åœ¨ä»»ä½•æ—¶å€™ç‚¹å‡»\gui{æ交}或\gui{å–消}。下é¢çš„æµç¨‹å›¾è¯¦ç»†è¯´æ˜Žäº†æ¤æ¦‚念:
+
+ \image addressbook-tutorial-part2-add-flowchart.png
+*/
+
+/*!
+ \page tutorials-addressbook-part3.html
+ \previouspage 地å€ç°¿ 2 — æ·»åŠ åœ°å€
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \nextpage {tutorials/addressbook/part4}{ç¬¬å››ç« }
+ \example tutorials/addressbook/part3
+ \title 地å€ç°¿ 3 — æµè§ˆåœ°å€ç°¿æ¡ç›®
+
+ 构建地å€ç°¿åº”用程åºçŽ°å·²è¿›å±•è¿‡åŠã€‚我们需è¦å¢žåŠ 一些函数,以便æµè§ˆè”系人。但首先è¦å†³å®šé‡‡ç”¨ä½•ç§æ•°æ®ç»“æž„æ–¹å¼æ¥å‚¨å˜è¿™äº›è”系人。
+
+ åœ¨ç¬¬äºŒç« ä¸ï¼Œæˆ‘们使用了 QMap é”®-值对,å³è”系人姓å作为\e{é”®},而è”系人地å€ä½œä¸º\e{值}。这ç§æ–¹å¼å¾ˆé€‚åˆæˆ‘们的实例。ä¸è¿‡ï¼Œè¦æµè§ˆå’Œæ˜¾ç¤ºæ¯ä¸ªæ¡ç›®ï¼Œè¿˜éœ€è¦è¿›è¡Œä¸€äº›æ”¹è¿›ã€‚
+
+ 我们改进 QMap çš„æ–¹å¼æ˜¯ï¼Œå°†æ•°æ®ç»“构替æ¢ä¸ºç±»ä¼¼å¾ªçŽ¯é“¾æŽ¥çš„列表,其ä¸æ‰€æœ‰å…ƒç´ 都是相互关è”çš„ï¼ŒåŒ…æ‹¬ç¬¬ä¸€ä¸ªå…ƒç´ å’Œæœ€åŽä¸€ä¸ªå…ƒç´ 。下图图解说明了该数æ®ç»“构。
+
+ \image addressbook-tutorial-part3-linkedlist.png
+
+ \section1 定义 AddressBook 类
+
+ è¦ç»™åœ°å€ç°¿åº”用程åºå¢žåŠ æµè§ˆåŠŸèƒ½ï¼Œæˆ‘们需è¦ä¸º \c AddressBook ç±»å†å¢žåŠ 两个函数:\c next() å’Œ \c previous()ã€‚å°†è¿™ä¸¤ä¸ªå‡½æ•°æ·»åŠ åˆ° \c addressbook.h 文件ä¸ï¼š
+
+ \snippet tutorials/addressbook/part3/addressbook.h navigation functions
+
+ 我们还需è¦ä½¿ç”¨å…¶ä»–两个 QPushButton å¯¹è±¡ï¼Œå› æ¤å°† \c nextButton å’Œ \c previousButton 声明为ç§æœ‰å˜é‡ï¼š
+
+ \snippet tutorials/addressbook/part3/addressbook.h navigation pushbuttons
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook çš„ \c addressbook.cpp æž„é€ å™¨ä¸ï¼Œæˆ‘们实例化 \c nextButton å’Œ \c previousButton,并且这两项默认为ç¦ç”¨ã€‚è¿™æ˜¯å› ä¸ºä»…å½“åœ°å€ç°¿ä¸æœ‰å¤šä¸ªè”系人时æ‰ä¼šå¯ç”¨æµè§ˆåŠŸèƒ½ã€‚
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp navigation pushbuttons
+
+ 然åŽï¼Œæˆ‘们将这两个按钮与其相应的槽关è”:
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp connecting navigation signals
+
+ 下图å³ä¸ºé¢„期的图形用户界é¢ã€‚请注æ„,该用户界é¢å·²å¾ˆæŽ¥è¿‘应用程åºæœ€ç»ˆçš„æ ·å。
+
+ \image addressbook-tutorial-part3-screenshot.png
+
+ 我们按照 \c next() å’Œ \c previous() 函数的基本规范,将 \c nextButton 放置在å³ä¾§ï¼Œè€Œ \c previousButton æ”¾ç½®åœ¨å·¦ä¾§ã€‚ä¸ºäº†ä½¿å¸ƒå±€æ›´åŠ ç›´è§‚ï¼Œæˆ‘ä»¬ä½¿ç”¨ QHBoxLayout å°† widget 并排放置:
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp navigation layout
+
+ 然åŽï¼Œå°† QHBoxLayout 对象 \c buttonLayout2 å¢žåŠ è‡³ \c mainLayout。
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp adding navigation layout
+
+ 下图显示了 widget 在 \c mainLayout ä¸çš„åæ ‡ä½ç½®ã€‚
+
+ \image addressbook-tutorial-part3-labeled-layout.png
+
+ 在 \c addContact() 函数ä¸ï¼Œæˆ‘们必须ç¦ç”¨è¿™å‡ ä¸ªæŒ‰é’®ï¼Œè¿™æ ·ç”¨æˆ·å°±ä¸ä¼šåœ¨å¢žåŠ è”系人时å°è¯•è¿›è¡Œæµè§ˆã€‚
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp disabling navigation
+
+ æ¤å¤–,在 \c submitContact() 函数ä¸ï¼Œæˆ‘们å¯ç”¨äº†æµè§ˆæŒ‰é’® \c nextButton å’Œ \c previousButton,这å–决于 \c contacts 的多少。如上文所述,æµè§ˆåŠŸèƒ½ä»…在地å€ç°¿ä¸æœ‰å¤šä¸ªè”系人时æ‰ä¼šå¯ç”¨ã€‚以下代ç 行说明了如何实现æ¤åŠŸèƒ½ï¼š
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp enabling navigation
+
+ 我们还在 \c cancel() 函数ä¸åŠ å…¥è¿™å‡ è¡Œä»£ç 。
+
+ 记得我们曾使用 QMap 对象 \c contacts æ¨¡æ‹Ÿäº†ä¸€ä¸ªå¾ªçŽ¯é“¾æŽ¥çš„åˆ—è¡¨ã€‚å› æ¤ï¼Œåœ¨ \c next() 函数ä¸ï¼Œæˆ‘ä»¬èŽ·å– \c contacts çš„è¿ä»£å™¨ï¼Œç„¶åŽæ‰§è¡Œä»¥ä¸‹æ“作:
+
+ \list
+ \o 如果è¿ä»£å™¨æœªè¾¾åˆ° \c contacts ç»“å°¾ï¼Œå°±ä¼šå¢žåŠ ä¸€ã€‚
+ \o 如果è¿ä»£å™¨å·²è¾¾åˆ° \c contacts 的结尾,就移至 \c contacts 的起始ä½ç½®ã€‚这给人感觉 QMap å°±åƒæ˜¯ä¸€ä¸ªå¾ªçŽ¯é“¾æŽ¥çš„列表。
+ \endlist
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp next() function
+
+ 一旦在 \c contacts ä¸å¾ªçŽ¯è‡³æ£ç¡®çš„对象,就会通过 \c nameLine å’Œ \c addressText 显示对象的内容。
+
+ åŒæ ·ï¼Œåœ¨ \c previous() 函数ä¸ï¼Œæˆ‘ä»¬èŽ·å– \c contacts çš„è¿ä»£å™¨ï¼Œç„¶åŽæ‰§è¡Œä»¥ä¸‹æ“作:
+
+ \list
+ \o 如果è¿ä»£å™¨è¾¾åˆ° \c contacts 的结尾,就清除显示内容,然åŽè¿”回。
+ \o 如果è¿ä»£å™¨åœ¨ \c contacts 的起始ä½ç½®ï¼Œå°±å°†å…¶ç§»è‡³ç»“尾。
+ \o 然åŽï¼Œå°†è¿ä»£å™¨å‡ä¸€ã€‚
+ \endlist
+
+ \snippet tutorials/addressbook/part3/addressbook.cpp previous() function
+
+ 接ç€ï¼Œé‡æ–°æ˜¾ç¤º \c contacts ä¸å½“å‰å¯¹è±¡çš„内容。
+*/
+
+/*!
+ \page tutorials-addressbook-part4.html
+ \previouspage 地å€ç°¿ 3 — æµè§ˆåœ°å€ç°¿æ¡ç›®
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \nextpage {tutorials/addressbook/part5}{ç¬¬äº”ç« }
+ \example tutorials/addressbook/part4
+ \title 地å€ç°¿ 4 — ç¼–è¾‘å’Œåˆ é™¤åœ°å€
+
+ åœ¨æœ¬ç« ä¸ï¼Œæˆ‘们将了解如何修改储å˜åœ¨åœ°å€ç°¿åº”用程åºä¸çš„è”系人的内容。
+
+ \image addressbook-tutorial-screenshot.png
+
+ 现有的地å€ç°¿ä¸ä»…å¯ä»¥äº•äº•æœ‰æ¡åœ°å‚¨å˜è”系人,还å¯è¿›è¡Œæµè§ˆã€‚å†æ·»åŠ ä¸Šç¼–è¾‘å’Œåˆ é™¤åŠŸèƒ½ï¼Œä»¥ä¾¿åœ¨éœ€è¦æ—¶æ›´æ”¹è”系人的详细信æ¯ï¼Œè¿™æ ·æ›´æ˜“于使用。ä¸è¿‡ï¼Œè¿˜éœ€ä½¿ç”¨ enum 类型进行一些改进。在å‰å‡ ç« ä¸ï¼Œæˆ‘们使用以下两ç§æ¨¡å¼ï¼š\c{AddingMode} å’Œ \c{NavigationMode}。但是,他们并未定义为 enum。我们是采用手动方å¼å¯ç”¨å’Œç¦ç”¨ç›¸åº”的按钮,这就导致有多行é‡å¤çš„代ç 。
+
+ åœ¨æœ¬ç« ä¸ï¼Œæˆ‘们定义带有以下三ç§ä¸åŒå€¼çš„ \c{Mode} enum 类型:
+
+ \list
+ \o \c{NavigationMode}ã€
+ \o \c{AddingMode} 和
+ \o \c{EditingMode}。
+ \endlist
+
+ \section1 定义 AddressBook 类
+
+ \c addressbook.h æ–‡ä»¶å·²æ›´æ–°ä¸ºåŒ…å« Mode \c enum 类型:
+
+ \snippet tutorials/addressbook/part4/addressbook.h Mode enum
+
+ 我们还è¦å‘当å‰çš„å…¬æœ‰æ§½åˆ—è¡¨å¢žåŠ ä¸¤ä¸ªæ–°æ§½ï¼š\c editContact() å’Œ \c removeContact()。
+
+ \snippet tutorials/addressbook/part4/addressbook.h edit and remove slots
+
+ 为了在模å¼é—´åˆ‡æ¢ï¼Œæˆ‘们引入了 \c updateInterface() 函数æ¥æŽ§åˆ¶æ‰€æœ‰ QPushButton 对象的å¯ç”¨å’Œç¦ç”¨ã€‚è¦å®žçŽ°ä¸Šæ–‡æåŠçš„ç¼–è¾‘å’Œåˆ é™¤åŠŸèƒ½ï¼Œæˆ‘ä»¬è¿˜è¦å¢žåŠ 两个新按钮:\c editButton å’Œ \c removeButton。
+
+ \snippet tutorials/addressbook/part4/addressbook.h updateInterface() declaration
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.h buttons declaration
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.h mode declaration
+
+ 最åŽï¼Œæˆ‘们声明 \c currentMode æ¥è·Ÿè¸ª enum 的当å‰æ¨¡å¼ã€‚
+
+ \section1 应用 AddressBook 类
+
+ 我们现在必须应用地å€ç°¿åº”用程åºçš„模å¼æ›´æ”¹åŠŸèƒ½ã€‚\c editButton å’Œ \c removeButton 已实例化并默认为ç¦ç”¨ï¼Œè¿™æ˜¯å› 为地å€ç°¿å¯åŠ¨æ—¶åœ¨å†…å˜ä¸æ²¡æœ‰è”系人。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp edit and remove buttons
+
+ 这些按钮会与其相应的槽 \c editContact() å’Œ \c removeContact() å…³è”,然åŽæˆ‘ä»¬å°†å…¶æ·»åŠ è‡³ \c buttonLayout1。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp connecting edit and remove
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.cpp adding edit and remove to the layout
+
+ 在将模å¼åˆ‡æ¢åˆ° \c EditingMode 之å‰ï¼Œ\c editContact() 函数使用 \c oldName å’Œ \c oldAddress 储å˜è”系人旧的详细信æ¯ã€‚ 在该模å¼ä¸‹ï¼Œ\c submitButton å’Œ \c cancelButton å‡å·²å¯ç”¨ï¼Œè¿™æ ·ç”¨æˆ·å°±å¯ä»¥æ›´æ”¹è”系人的详细信æ¯å¹¶å¯ç‚¹å‡»ä»»ä½•ä¸€ä¸ªæŒ‰é’®ã€‚
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp editContact() function
+
+ \c submitContact() 函数已被 \c{if-else} è¯å¥åˆ†ä¸ºä¸¤éƒ¨åˆ†ã€‚我们查看 \c currentMode 是å¦åœ¨ \c AddingMode 模å¼ä¸‹ã€‚如果是,我们继ç»æ·»åŠ æ“作。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function beginning
+ \dots
+ \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part1
+
+ å¦åˆ™ï¼Œæˆ‘们查看 \c currentMode 是å¦åœ¨ \c EditingMode 模å¼ä¸‹ã€‚如果是,我们比较 \c oldName å’Œ \c name。如果姓å已更改,我们从 \c contacts ä¸åˆ 除旧的è”系人并æ’入已更新的è”系人。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp submitContact() function part2
+
+ 如果仅更改了地å€ï¼ˆä¾‹å¦‚ \c oldAddress 与 \c address ä¸åŒï¼‰ï¼Œæˆ‘们就更新è”系人的地å€ã€‚最åŽï¼Œæˆ‘们将 \c currentMode 设置为 \c NavigationMode。这一æ¥è‡³å…³é‡è¦ï¼Œå› 为它会é‡æ–°å¯ç”¨æ‰€æœ‰å·²ç¦ç”¨çš„按钮。
+
+ è¦ä»Žåœ°å€ç°¿ä¸åˆ 除è”系人,我们采用 \c removeContact() 函数。该函数查看 \c contacts ä¸æ˜¯å¦åŒ…å«è¯¥è”系人。
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp removeContact() function
+
+ 如果有,我们显示 QMessageBoxï¼Œç¡®è®¤ç”¨æˆ·çš„åˆ é™¤æ“作。一旦用户确认æ“作,我们调用 \c previous() ç¡®ä¿ç”¨æˆ·ç•Œé¢æ˜¾ç¤ºå…¶ä»–è”系人,然åŽæˆ‘们使用 QMap çš„ \l{QMap::remove()}{remove()} å‡½æ•°åˆ é™¤å·²å·²ç¡®è®¤çš„è”系人。出于好æ„,我们会显示 QMessageBox æ示用户。在该函数ä¸ä½¿ç”¨ä¸¤ç§ä¿¡æ¯æ¡†æ˜¾ç¤ºå¦‚下:
+
+ \image addressbook-tutorial-part4-remove.png
+
+ \section2 更新用户界é¢
+
+ 我们在上文æ到 \c updateInterface() 函数,它å¯æ ¹æ®å½“å‰çš„模å¼å¯ç”¨å’Œç¦ç”¨æŒ‰é’®ã€‚è¯¥å‡½æ•°ä¼šæ ¹æ®ä¼ 递给它的 \c mode å‚数更新当å‰çš„模å¼ï¼Œåœ¨æ ¡éªŒå€¼ä¹‹å‰å°†å‚数分é…ç»™ \c currentMode。
+
+ è¿™æ ·ï¼Œæ¯ä¸ªæŒ‰é’®å°±æ ¹æ®å½“å‰çš„模å¼è¿›è¡Œå¯ç”¨æˆ–ç¦ç”¨ã€‚\c AddingMode å’Œ \c EditingMode 的代ç 显示如下:
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 1
+
+ ä¸è¿‡å¯¹äºŽ \c NavigationMode,我们在 QPushButton::setEnabled() 函数的å‚æ•°ä¸åŠ 入了æ¡ä»¶ã€‚è¿™æ ·å¯ç¡®ä¿ \c editButton å’Œ \c removeButton 在地å€ç°¿ä¸è‡³å°‘有一个è”系人的情况下å¯ç”¨ï¼Œè€Œ \c nextButton å’Œ \c previousButton 仅在地å€ç°¿ä¸æœ‰å¤šä¸ªè”系人时æ‰å¯ç”¨ã€‚
+
+ \snippet tutorials/addressbook/part4/addressbook.cpp update interface() part 2
+
+ 通过在åŒä¸€å‡½æ•°ä¸è®¾ç½®æ¨¡å¼å’Œæ›´æ–°ç”¨æˆ·ç•Œé¢ï¼Œæˆ‘们å¯ä»¥é¿å…用户界é¢ä¸Žåº”用程åºå†…部状æ€ä¸åŒæ¥çš„å¯èƒ½æ€§ã€‚
+*/
+
+/*!
+ \page tutorials-addressbook-part5.html
+ \previouspage 地å€ç°¿ 4 — ç¼–è¾‘å’Œåˆ é™¤åœ°å€
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \nextpage {tutorials/addressbook/part6}{第å…ç« }
+ \example tutorials/addressbook/part5
+ \title 地å€ç°¿ 5 — æ·»åŠ æŸ¥æ‰¾åŠŸèƒ½
+
+ åœ¨æœ¬ç« ä¸ï¼Œæˆ‘们将了解如何在地å€ç°¿åº”用程åºä¸å®šä½è”系人和地å€ã€‚
+
+ \image addressbook-tutorial-part5-screenshot.png
+
+ éšç€æˆ‘们ä¸æ–为地å€ç°¿åº”用程åºæ·»åŠ è”系人,使用下一个和上一个按钮æµè§ˆè”系人就会å˜å¾—很ç¹ç。在这ç§æƒ…况下,使用查找函数查找è”ç³»äººå°±ä¼šæ›´åŠ æœ‰æ•ˆã€‚ä¸Šé¢çš„å±å¹•æˆªå›¾æ˜¾ç¤ºäº†æŸ¥æ‰¾æŒ‰é’®åŠå…¶åœ¨æŒ‰é’®é¢æ¿ä¸Šçš„ä½ç½®ã€‚
+
+ 当用户点击查找按钮时,有必è¦æ˜¾ç¤ºä¸€ä¸ªå¯¹è¯æ¡†ï¼Œç”¨æˆ·å¯åœ¨å…¶ä¸è¾“å…¥è”系人的姓å。Qt æ供了 QDialogï¼ˆæˆ‘ä»¬ä¼šåœ¨æœ¬ç« ä¸å°†å…¶ç”¨ä½œå类),å¯ä½¿ç”¨ \c FindDialog 类。
+
+ \section1 定义 FindDialog 类
+
+ \image addressbook-tutorial-part5-finddialog.png
+
+ è¦ä½¿ç”¨ QDialog çš„å类,我们首先è¦åœ¨ \c finddialog.h 文件ä¸å£°æ˜Ž QDialog 的头信æ¯ã€‚æ¤å¤–,我们还使用å‘å‰ (forward) 声明æ¥å£°æ˜Ž QLineEdit å’Œ QPushButtonï¼Œè¿™æ ·æˆ‘ä»¬å°±èƒ½åœ¨å¯¹è¯æ¡†ç±»ä¸ä½¿ç”¨è¿™äº› widget。
+
+ å› ä¸ºåœ¨ \c AddressBook ç±»ä¸ï¼Œ\c FindDialog 类包å«äº† Q_OBJECT å®ï¼Œå¹¶ä¸”å…¶æž„é€ å™¨å·²å®šä¹‰ä¸ºæŽ¥æ”¶çˆ¶çº§ QWidget,å³ä½¿å¯¹è¯æ¡†ä»¥å•ç‹¬çš„窗å£æ–¹å¼æ‰“开。
+
+ \snippet tutorials/addressbook/part5/finddialog.h FindDialog header
+
+ 我们定义了公有函数 \c getFindText(),供实例化 \c FindDialog çš„ç±»ä½¿ç”¨ï¼Œè¿™æ ·è¿™äº›ç±»å¯ä»¥èŽ·å–用户输入的文本。公有槽 \c findClicked() 定义为在用户点击\gui{查找}按钮时处ç†æœç´¢å—符串。
+
+ 最åŽï¼Œæˆ‘们定义ç§æœ‰å˜é‡ \c findButtonã€\c lineEdit å’Œ \c findText,分别对应\gui{查找}按钮ã€ç”¨æˆ·è¾“å…¥æœç´¢å—符串的行编辑框和储å˜æœç´¢å—符串供ç¨åŽä½¿ç”¨çš„内部å—符串。
+
+ \section1 应用 FindDialog 类
+
+ 在 \c FindDialog çš„æž„é€ å™¨ä¸ï¼Œæˆ‘们设置ç§æœ‰å˜é‡ \c lineEditã€\c findButton å’Œ \c findText。使用 QHBoxLayout 放置 widget。
+
+ \snippet tutorials/addressbook/part5/finddialog.cpp constructor
+
+ 我们设定布局和窗å£æ ‡é¢˜ï¼Œå¹¶å°†ä¿¡å·ä¸Žå…¶å„自的槽关è”。请注æ„,\c findButton çš„ \l{QPushButton::clicked()}{clicked()} ä¿¡å·å·²ä¸Ž \c findClicked() å’Œ \l{QDialog::accept()}{accept()} å…³è”。QDialog æ供的 \l{QDialog::accept()}{accept()} 槽会éšè—对è¯æ¡†å¹¶å°†ç»“果代ç 设置为 \l{QDialog::}{Accepted}。我们使用该函数有助于 \c AddressBook çš„ \c findContact() 函数知晓 \c FindDialog 对象关é—的时间。我们在讨论 \c findContact() 函数时将对该函数åšè¿›ä¸€æ¥è¯´æ˜Žã€‚
+
+ \image addressbook-tutorial-part5-signals-and-slots.png
+
+ 在 \c findClicked() ä¸ï¼Œæˆ‘ä»¬éªŒè¯ \c lineEdit 以确ä¿ç”¨æˆ·æ²¡æœ‰åœ¨å°šæœªè¾“å…¥è”系人姓å时就点击\gui{查找}按钮。然åŽï¼Œæˆ‘们将 \c findText 设置为从 \c lineEdit æå–çš„æœç´¢å—符串。之åŽï¼Œæˆ‘们清空 \c lineEdit 的内容并éšè—对è¯æ¡†ã€‚
+
+ \snippet tutorials/addressbook/part5/finddialog.cpp findClicked() function
+
+ \c findText å˜é‡å·²æœ‰å…¬æœ‰ getter 函数 \c getFindText() 与其相关è”ã€‚æ—¢ç„¶æˆ‘ä»¬ä»…åœ¨æž„é€ å™¨å’Œ \c findClicked() 函数ä¸ç›´æŽ¥è®¾å®šäº† \c findText, 我们就ä¸åœ¨åˆ›å»º \c getFindText() çš„åŒæ—¶å†åˆ›å»º setter 函数。由于 \c getFindText() 是公有的,实例化和使用 \c FindDialog çš„ç±»å¯å§‹ç»ˆè¯»å–用户已输入并确认的æœç´¢å—符串。
+
+ \snippet tutorials/addressbook/part5/finddialog.cpp getFindText() function
+
+ \section1 定义 AddressBook 类
+
+ è¦ç¡®ä¿æˆ‘们å¯ä½¿ç”¨ \c AddressBook ç±»ä¸çš„ \c FindDialog,我们è¦åœ¨ \c addressbook.h 文件ä¸åŒ…å« \c finddialog.h。
+
+ \snippet tutorials/addressbook/part5/addressbook.h include finddialog's header
+
+ 至æ¤ï¼Œæ‰€æœ‰åœ°å€ç°¿åŠŸèƒ½éƒ½æœ‰äº† QPushButton 和对应的槽。åŒæ ·ï¼Œ\gui{Find} 功能有 \c findButton å’Œ \c findContact()。
+
+ \c findButton 声明为ç§æœ‰å˜é‡ï¼Œè€Œ \c findContact() 函数声明为公有槽。
+
+ \snippet tutorials/addressbook/part5/addressbook.h findContact() declaration
+ \dots
+ \snippet tutorials/addressbook/part5/addressbook.h findButton declaration
+
+ 最åŽï¼Œæˆ‘们声明ç§æœ‰å˜é‡ \c dialog,用于引用 \c FindDialog 的实例。
+
+ \snippet tutorials/addressbook/part5/addressbook.h FindDialog declaration
+
+ 在实例化对è¯æ¡†åŽï¼Œæˆ‘们å¯èƒ½ä¼šå¯¹å…¶è¿›è¡Œå¤šæ¬¡ä½¿ç”¨ã€‚使用ç§æœ‰å˜é‡å¯åœ¨ç±»ä¸ä¸åŒä½ç½®å¯¹å…¶è¿›è¡Œå¤šæ¬¡å¼•ç”¨ã€‚
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook ç±»çš„æž„é€ å™¨ä¸ï¼Œå®žä¾‹åŒ–ç§æœ‰å¯¹è±¡ \c findButton å’Œ \c findDialog:
+
+ \snippet tutorials/addressbook/part5/addressbook.cpp instantiating findButton
+ \dots
+ \snippet tutorials/addressbook/part5/addressbook.cpp instantiating FindDialog
+
+ 接下æ¥ï¼Œå°† \c findButton çš„ \l{QPushButton::clicked()}{clicked()} ä¿¡å·ä¸Ž \c findContact() å…³è”。
+
+ \snippet tutorials/addressbook/part5/addressbook.cpp signals and slots for find
+
+ 现在唯一è¦å®Œæˆçš„就是 \c findContact() 函数的编ç :
+
+ \snippet tutorials/addressbook/part5/addressbook.cpp findContact() function
+
+ 我们从显示 \c FindDialog 的实例 \c dialog 开始入手。这时用户开始输入è”系人姓å进行查找。用户点击对è¯æ¡†çš„ \c findButton åŽï¼Œå¯¹è¯æ¡†ä¼šéšè—,并且结果代ç 设置为 QDialog::Accepted.è¿™æ ·å°±ç¡®ä¿äº† \c if è¯å¥å§‹ç»ˆä¸ºçœŸã€‚
+
+ 然åŽï¼Œæˆ‘们就开始使用 \c FindDialog çš„ \c getFindText() 函数æå–æœç´¢å—符串,这个å—符串也就是本例ä¸çš„ \c contactName。如果地å€ç°¿ä¸æœ‰è”系人,就立å³æ˜¾ç¤ºè¯¥è”系人。å¦åˆ™ï¼Œæ˜¾ç¤ºå¦‚下所示的 QMessageBox 表明æœç´¢å¤±è´¥ã€‚
+
+ \image addressbook-tutorial-part5-notfound.png
+*/
+
+/*!
+ \page tutorials-addressbook-part6.html
+ \previouspage 地å€ç°¿ 5 — æ·»åŠ æŸ¥æ‰¾åŠŸèƒ½
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \nextpage {tutorials/addressbook/part7}{ç¬¬ä¸ƒç« }
+ \example tutorials/addressbook/part6
+ \title 地å€ç°¿ 6 — åŠ è½½å’Œä¿å˜
+
+ æœ¬ç« æ述了用于编写地å€ç°¿åº”用程åºçš„åŠ è½½å’Œä¿å˜ç¨‹åºæ‰€ä½¿ç”¨çš„ Qt 文件处ç†åŠŸèƒ½ã€‚
+
+ \image addressbook-tutorial-part6-screenshot.png
+
+ 虽然æµè§ˆå’Œæœç´¢è”系人是éžå¸¸å®žç”¨çš„功能,但åªæœ‰åœ¨å¯ä»¥ä¿å˜çŽ°æœ‰è”系人并å¯ä»¥åœ¨ä»¥åŽåŠ 载的å‰æ下地å€ç°¿æ‰çœŸæ£å®Œå…¨å¯ç”¨ã€‚Qt æ供大é‡ç”¨äºŽ\l{Input/Output and Networking}{输入和输出}的类,但我们åªé€‰æ‹©ä¸¤ä¸ªæ˜“于åˆå¹¶ä½¿ç”¨çš„类:QFile å’Œ QDataStream。
+
+ QFile 对象表示ç£ç›˜ä¸Šå¯è¯»å–和写入的文件。QFile 是代表多ç§ä¸åŒè®¾å¤‡ä¸”应用更广的 QIODevice 类的å类。
+
+ QDataStream 对象用于按顺åºæŽ’列二进制数æ®ï¼Œä»¥ä¾¿å‚¨å˜åœ¨ QIODevice ä¸å¹¶ä¾›ä»¥åŽæ£€ç´¢ã€‚读å–或写入 QIODevice 就如åŒæ‰“开数æ®æµï¼Œç„¶åŽè¯»å–æˆ–å†™å…¥ä¸€æ ·ç®€å•ï¼Œåªæ˜¯å‚数为ä¸åŒçš„设备。
+
+
+ \section1 定义 AddressBook 类
+
+ 我们声明两个公有槽 \c saveToFile() å’Œ \c loadFromFile(),以åŠä¸¤ä¸ª QPushButton 对象 \c loadButton å’Œ \c saveButton。
+
+ \snippet tutorials/addressbook/part6/addressbook.h save and load functions declaration
+ \dots
+ \snippet tutorials/addressbook/part6/addressbook.h save and load buttons declaration
+
+ \section1 应用 AddressBook 类
+
+ åœ¨æž„é€ å™¨ä¸ï¼Œæˆ‘们实例化 \c loadButton å’Œ \c saveButton。ç†æƒ³æƒ…å†µä¸‹ï¼Œå°†æŒ‰é’®æ ‡ç¾è®¾ç½®ä¸ºâ€œä»Žæ–‡ä»¶åŠ è½½è”系人â€å’Œâ€œå°†è”系人ä¿å˜è‡³æ–‡ä»¶â€ä¼šæ›´æ–¹ä¾¿ç”¨æˆ·ä½¿ç”¨ã€‚ä¸è¿‡ï¼Œç”±äºŽå…¶ä»–按钮的大å°é™åˆ¶ï¼Œæˆ‘ä»¬å°†æ ‡ç¾è®¾ç½®ä¸º\gui{åŠ è½½...}å’Œ\gui{ä¿å˜...}。幸è¿çš„是,Qt æ供了使用 \l{QWidget::setToolTip()}{setToolTip()} æ¥è®¾ç½®å·¥å…·æ示的简å•æ–¹å¼ï¼Œæˆ‘们å¯é€šè¿‡å¦‚下方å¼å°†å…¶ç”¨äºŽæŒ‰é’®ï¼š
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 1
+ \dots
+ \snippet tutorials/addressbook/part6/addressbook.cpp tooltip 2
+
+ 虽然æ¤å¤„æ²¡æœ‰æ˜¾ç¤ºï¼Œä½†ä¸Žå…¶ä»–åº”ç”¨çš„åŠŸèƒ½ä¸€æ ·ï¼Œæˆ‘ä»¬åœ¨å³ä¾§çš„布局é¢æ¿ \c button1Layout ä¸Šæ·»åŠ æŒ‰é’®ï¼Œç„¶åŽå°†æŒ‰é’®çš„ \l{QPushButton::clicked()}{clicked()} ä¿¡å·ä¸Žå…¶ç›¸åº”的槽关è”。
+
+ 至于ä¿å˜åŠŸèƒ½ï¼Œæˆ‘们首先使用 QFileDialog::getSaveFileName() èŽ·å– \c fileName。 这是 QFileDialog æ供的一个便æ·åŠŸèƒ½ï¼Œå¯å¼¹å‡ºæ ·å¼æ–‡ä»¶å¯¹è¯æ¡†å¹¶å…许用户输入文件å或选择现有的 \c{.abk} 文件。\c{.abk} 文件是ä¿å˜è”系人时创建的地å€ç°¿æ‰©å±•å。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part1
+
+ 弹出的文件对è¯æ¡†å±å¹•æˆªå›¾æ˜¾ç¤ºå¦‚下:
+
+ \image addressbook-tutorial-part6-save.png
+
+ 如果 \c fileName ä¸ä¸ºç©ºï¼Œæˆ‘们就使用 \c fileName 创建 QFile 对象 \c file。 QFile 与 QDataStream 一åŒä½¿ç”¨ï¼Œè¿™æ˜¯å› 为QFile 是 QIODevice。
+
+ 接下æ¥ï¼Œæˆ‘们å°è¯•ä»¥ \l{QIODevice::}{WriteOnly} 模å¼æ‰“开文件。如果未能打开,会显示 QMessageBox æ示用户。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part2
+
+ å¦åˆ™ï¼Œä¼šç”¨å®žä¾‹è¡¨ç¤º QDataStream 对象 \c out,以写入打开的文件。QDataStream è¦æ±‚读写æ“作需使用相åŒç‰ˆæœ¬çš„æ•°æ®æµã€‚在将数æ®æŒ‰é¡ºåºå†™å…¥ \c file 之å‰ï¼Œå°†ä½¿ç”¨çš„版本设置为\l{QDataStream::Qt_4_5}{采用 Qt 4.5 的版本}å°±å¯ç¡®ä¿ç‰ˆæœ¬ç›¸åŒã€‚
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp saveToFile() function part3
+
+ è‡³äºŽåŠ è½½åŠŸèƒ½ï¼Œæˆ‘ä»¬ä¹Ÿæ˜¯ä½¿ç”¨ QFileDialog::getOpenFileName() èŽ·å– \c fileName。该函数与 QFileDialog::getSaveFileName() ç›¸å¯¹åº”ï¼Œä¹Ÿæ˜¯å¼¹å‡ºæ ·å¼æ–‡ä»¶å¯¹è¯æ¡†å¹¶å…许用户输入文件å或选择现有的 \c{.abk} æ–‡ä»¶åŠ è½½åˆ°åœ°å€ç°¿ä¸ã€‚
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part1
+
+ 例如,在 Windows 上,该函数弹出本地文件对è¯æ¡†ï¼Œå¦‚以下å±å¹•æˆªå›¾æ‰€ç¤ºã€‚
+
+ \image addressbook-tutorial-part6-load.png
+
+ 如果 \c fileName ä¸ä¸ºç©ºï¼Œè¿˜æ˜¯ä½¿ç”¨ QFile 对象 \c file,然åŽå°è¯•åœ¨ \l{QIODevice::}{ReadOnly} 模å¼ä¸‹æ‰“开文件。与 \c saveToFile() 的应用方å¼ç±»ä¼¼ï¼Œå¦‚æžœå°è¯•å¤±è´¥ï¼Œä¼šæ˜¾ç¤º QMessageBox æ示用户。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part2
+
+ å¦åˆ™ï¼Œä¼šç”¨å®žä¾‹è¡¨ç¤º QDataStream 对象 \c in,按上文所述设置其版本,然åŽå°†æŒ‰é¡ºåºæŽ’列的数æ®è¯»å…¥ \c contacts æ•°æ®ç»“构。请注æ„,在将数æ®è¯»å…¥ä¹‹å‰æ¸…空 \c contacts å¯ç®€åŒ–文件读å–过程。更高级的方法是将è”系人读å–至临时 QMap 对象,然åŽä»…å¤åˆ¶ \c contacts ä¸ä¸å˜åœ¨çš„è”系人。
+
+ \snippet tutorials/addressbook/part6/addressbook.cpp loadFromFile() function part3
+
+ è¦æ˜¾ç¤ºä»Žæ–‡ä»¶ä¸è¯»å–çš„è”系人,必须è¦å…ˆéªŒè¯èŽ·å–çš„æ•°æ®ï¼Œä»¥ç¡®ä¿è¯»å–的文件实际包å«åœ°å€ç°¿è”系人。如果为真,显示第一个è”系人,å¦åˆ™æ˜¾ç¤º QMessageBox æ示出现问题。最åŽï¼Œæˆ‘们更新界é¢ä»¥ç›¸åº”地å¯ç”¨å’Œç¦ç”¨æŒ‰é’®ã€‚
+*/
+
+/*!
+ \page tutorials-addressbook-part7.html
+ \previouspage 地å€ç°¿ 6 — åŠ è½½å’Œä¿å˜
+ \contentspage {地å€ç°¿æ•™ç¨‹}{目录}
+ \example tutorials/addressbook/part7
+ \title 地å€ç°¿ 7 — é™„åŠ åŠŸèƒ½
+
+ æœ¬ç« è®²è¿°äº†éƒ¨åˆ†å¯ä½¿åœ°å€ç°¿åº”用程åºæ—¥å¸¸ä½¿ç”¨æ›´åŠ 便æ·çš„é™„åŠ åŠŸèƒ½ã€‚
+
+ \image addressbook-tutorial-part7-screenshot.png
+
+ 虽然地å€ç°¿åº”用程åºå…¶è‡ªèº«åŠŸèƒ½å·²ç»å¾ˆå®žç”¨ï¼Œä½†æ˜¯å¦‚æžœå¯å’Œå…¶ä»–应用程åºäº’æ¢è”系人数æ®å°±ä¼šæ›´åŠ 有益。vCard æ ¼å¼æ˜¯ä¸€ç§æµè¡Œçš„æ–‡ä»¶æ ¼å¼ï¼Œå°±å¯ç”¨äºŽæ¤ç›®çš„ã€‚åœ¨æœ¬ç« ä¸ï¼Œæˆ‘们会扩展地å€ç°¿å®¢æˆ·ç«¯ï¼Œå¯å°†è”系人导出到 vCard \c{.vcf} 文件ä¸ã€‚
+
+ \section1 定义 AddressBook 类
+
+ 我们在 \c addressbook.h 文件的 \c AddressBook ç±»ä¸æ·»åŠ QPushButton 对象 \c exportButton 以åŠå¯¹åº”的公有槽 \c exportAsVCard()。
+
+ \snippet tutorials/addressbook/part7/addressbook.h exportAsVCard() declaration
+ \dots
+ \snippet tutorials/addressbook/part7/addressbook.h exportButton declaration
+
+ \section1 应用 AddressBook 类
+
+ 在 \c AddressBook æž„é€ å™¨ä¸ï¼Œæˆ‘们将 \c exportButton çš„ \l{QPushButton::clicked()}{clicked()} ä¿¡å·è¿žæŽ¥è‡³ \c exportAsVCard()ã€‚æˆ‘ä»¬è¿˜ä¼šå°†è¯¥æŒ‰é’®æ·»åŠ è‡³ \c buttonLayout1,它是负责å³ä¾§æŒ‰é’®é¢æ¿çš„布局类。
+
+ 在 \c exportAsVCard() 函数ä¸ï¼Œæˆ‘们从æå– \c name ä¸è”系人姓å开始入手。我们声明 \c firstNameã€\c lastName å’Œ \c nameList。接下æ¥ï¼Œæˆ‘们查找 \c name ä¸ç¬¬ä¸€å¤„空白的索引。如果有空白,就将è”系人的姓å分隔为 \c firstName å’Œ lastName。然åŽï¼Œå°†ç©ºç™½æ›¿æ¢ä¸ºä¸‹åˆ’线 ("_")。或者,如果没有空白,就认定è”系人åªæœ‰åå—。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part1
+
+ 至于 \c saveToFile() 函数,会打开文件对è¯æ¡†ï¼Œè®©ç”¨æˆ·é€‰æ‹©æ–‡ä»¶çš„ä½ç½®ã€‚通过选择的文件å称,我们创建è¦å†™å…¥çš„ QFile 实例。
+
+ 我们å°è¯•ä»¥ \l{QIODevice::}{WriteOnly} 模å¼æ‰“开文件。如果æ“作失败,会显示 QMessageBox æ示用户出现问题并返回。å¦åˆ™ï¼Œå°†æ–‡ä»¶ä½œä¸ºå‚æ•°ä¼ é€’ç»™ QTextStream 对象 \c out。与 QDataStream 类似,QTextStream ç±»æ供了读å–çº¯æ–‡æœ¬å’Œå°†å…¶å†™å…¥åˆ°æ–‡ä»¶çš„åŠŸèƒ½ã€‚å› æ¤ï¼Œæ‰€ç”Ÿæˆçš„ \c{.vcf} 文件å¯ä»¥åœ¨æ–‡æœ¬ç¼–辑器ä¸æ‰“开进行编辑。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part2
+
+ 然åŽï¼Œæˆ‘们写出ä¾æ¬¡å¸¦æœ‰ \c{BEGIN:VCARD} å’Œ \c{VERSION:2.1} æ ‡è®°çš„ vCard 文件。è”系人的姓å使用 \c{N:} æ ‡è®°å†™å…¥ã€‚è‡³äºŽå†™å…¥ vCard “File asâ€å±žæ€§çš„ FN: æ ‡è®°ï¼Œæˆ‘ä»¬å¿…é¡»è¦æŸ¥çœ‹æ˜¯å¦è”系人带有姓。如果è”系人有姓,就使用 \c nameList ä¸çš„详细信æ¯å¡«å…¥è¯¥æ ‡è®°ã€‚å¦åˆ™ï¼Œä»…写入 \c firstName。
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part3
+
+ 我们继ç»å†™å…¥è”系人的地å€ã€‚地å€ä¸çš„分å·ä½¿ç”¨ "\\" 进行转义,新行使用分å·è¿›è¡Œæ›¿æ¢ï¼Œè€Œé€—å·ä½¿ç”¨ç©ºç™½è¿›è¡Œæ›¿æ¢ã€‚最åŽï¼Œæˆ‘们ä¾æ¬¡å†™å…¥ \c{ADR;HOME:;}ã€\c address å’Œ \c{END:VCARD} æ ‡è®°ã€‚
+
+ \snippet tutorials/addressbook/part7/addressbook.cpp export function part4
+
+ 最åŽï¼Œä¼šæ˜¾ç¤º QMessageBox æ示用户已æˆåŠŸå¯¼å‡º vCard。
+
+ \e{vCard 是 \l{http://www.imc.org}{Internet Mail Consortium} çš„å•†æ ‡}。
+*/
diff --git a/doc/src/zh_CN/tutorials/widgets-tutorial.qdoc b/doc/src/zh_CN/tutorials/widgets-tutorial.qdoc
new file mode 100644
index 0000000..0e90210
--- /dev/null
+++ b/doc/src/zh_CN/tutorials/widgets-tutorial.qdoc
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the documentation 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$
+**
+****************************************************************************/
+
+/*!
+ \page widgets-tutorial.html
+ \title Widgets 教程
+ \brief This tutorial covers basic usage of widgets and layouts, showing how
+ they are used to build GUI applications.
+
+ \startpage {index.html}{Qt Reference Documentation}
+ \contentspage Tutorials
+ \nextpage {Widgets 教程 — 创建窗å£}
+
+
+ \section1 简介
+
+ Widget 是使用 Qt ç¼–å†™çš„å›¾å½¢ç”¨æˆ·ç•Œé¢ (GUI) 应用程åºçš„基本生æˆå—。æ¯ä¸ª GUI 组件,如按钮ã€æ ‡ç¾æˆ–文本编辑器,都是一个 widget ,并å¯ä»¥æ”¾ç½®åœ¨çŽ°æœ‰çš„用户界é¢ä¸æˆ–作为å•ç‹¬çš„窗å£æ˜¾ç¤ºã€‚æ¯ç§ç±»åž‹çš„组件都是由 QWidget 的特殊åç±»æ供的,而 QWidget 自身åˆæ˜¯ QObject çš„å类。
+
+ QWidget ä¸æ˜¯ä¸€ä¸ªæŠ½è±¡ç±»ï¼›å®ƒå¯ç”¨ä½œå…¶ä»– widget 的容器,并很容易作为å类使用æ¥åˆ›å»ºå®šåˆ¶ widget。它ç»å¸¸ç”¨æ¥åˆ›å»ºæ”¾ç½®å…¶ä»– widget 的窗å£ã€‚
+
+ 至于 QObject,å¯ä½¿ç”¨çˆ¶å¯¹è±¡åˆ›å»º widget 以表明其所属关系,这å¯ç¡®ä¿åˆ 除ä¸å†ä½¿ç”¨çš„对象。使用 widget,这些父å关系就有了更多的æ„义:æ¯ä¸ªå类都显示在其父级所拥有的å±å¹•åŒºåŸŸå†…ã€‚ä¹Ÿå°±æ˜¯è¯´ï¼Œå½“åˆ é™¤çª—å£æ—¶ï¼Œå…¶åŒ…å«çš„所有 widget ä¹Ÿéƒ½è‡ªåŠ¨åˆ é™¤ã€‚
+
+ \section1 Writing a main Function
+
+ Many of the GUI examples in Qt follow the pattern of having a \c{main.cpp}
+ file containing code to initialize the application, and a number of other
+ source and header files containing the application logic and custom GUI
+ components.
+
+ A typical \c main() function, written in \c{main.cpp}, looks like this:
+
+ \snippet doc/src/snippets/widgets-tutorial/template.cpp main.cpp body
+
+ We first construct a QApplication object which is configured using any
+ arguments passed in from the command line. After any widgets have been
+ created and shown, we call QApplication::exec() to start Qt's event loop.
+ Control passes to Qt until this function returns, at which point we return
+ the value we obtain from this function.
+
+ In each part of this tutorial, we provide an example that is written
+ entirely within a \c main() function. In more sophisticated examples, the
+ code to set up widgets and layouts is written in other parts of the
+ example. For example, the GUI for a main window may be set up in the
+ constructor of a QMainWindow subclass.
+
+ The \l{Widgets examples} are a good place to look for
+ more complex and complete examples and applications.
+
+ \section1 Building Examples and Tutorials
+
+ If you obtained a binary package of Qt or compiled it yourself, the
+ examples described in this tutorial should already be ready to run.
+ However, if you may wish to modify them and recompile them, you need to
+ perform the following steps:
+
+ \list 1
+ \o At the command line, enter the directory containing the example you
+ wish to recompile.
+ \o Type \c qmake and press \key{Return}. If this doesn't work, make sure
+ that the executable is on your path, or enter its full location.
+ \o On Linux/Unix and Mac OS X, type \c make and press \key{Return};
+ on Windows with Visual Studio, type \c nmake and press \key{Return}.
+ \endlist
+
+ An executable file should have been created within the current directory.
+ On Windows, this file may be located within a \c debug or \c release
+ subdirectory. You can run this file to see the example code at work.
+*/
+
+/*!
+ \page widgets-tutorial-toplevel.html
+ \contentspage {Widgets 教程}{目录}
+ \previouspage {Widgets 教程}
+ \nextpage {Widgets 教程 — Child Widgets}
+ \example tutorials/widgets/toplevel
+ \title Widgets 教程 — 创建窗å£
+
+ 如果 widget 未使用父级进行创建,则在显示时视为窗å£æˆ–\e{顶层 widget}。由于顶层 widget 没有父级对象类æ¥ç¡®ä¿åœ¨å…¶ä¸å†ä½¿ç”¨æ—¶å°±åˆ é™¤ï¼Œå› æ¤éœ€è¦å¼€å‘人员在应用程åºä¸å¯¹å…¶è¿›è¡Œè·Ÿè¸ªã€‚
+
+ 在下例ä¸ï¼Œæˆ‘们使用 QWidget 创建和显示具有默认大å°çš„窗å£ï¼š
+
+ \raw HTML
+
+
+ \endraw
+ \snippet tutorials/widgets/toplevel/main.cpp main program
+ \raw HTML
+
+ \endraw
+ \inlineimage widgets-tutorial-toplevel.png
+ \raw HTML
+
+
+ \endraw
+
+ To create a real GUI, we need to place widgets inside the window. To do
+ this, we pass a QWidget instance to a widget's constructor, as we will
+ demonstrate in the next part of this tutorial.
+*/
+
+/*!
+ \page widgets-tutorial-childwidget.html
+ \contentspage {Widgets 教程}{目录}
+ \previouspage {Widgets 教程 — 创建窗å£}
+ \nextpage {Widgets 教程 — 使用布局}
+ \example tutorials/widgets/childwidget
+ \title Widgets 教程 — Child Widgets
+
+ 我们å¯ä»¥é€šè¿‡å°† \c window ä½œä¸ºçˆ¶çº§ä¼ é€’ç»™å…¶æž„é€ å™¨æ¥å‘窗å£æ·»åŠ å widget。在这ç§æƒ…况下,我们å‘窗å£æ·»åŠ 按钮并将其放置在特定ä½ç½®ï¼š
+
+ \raw HTML
+
+
+ \endraw
+ \snippet tutorials/widgets/childwidget/main.cpp main program
+ \raw HTML
+
+ \endraw
+ \inlineimage widgets-tutorial-childwidget.png
+ \raw HTML
+
+
+ \endraw
+
+ 该按钮现在为窗å£çš„åé¡¹ï¼Œå¹¶åœ¨åˆ é™¤çª—å£æ—¶ä¸€åŒåˆ 除。请注æ„,éšè—或关é—窗å£ä¸ä¼šè‡ªåŠ¨åˆ 除该按钮。
+*/
+
+/*!
+ \page widgets-tutorial-windowlayout.html
+ \contentspage {Widgets 教程}{目录}
+ \previouspage {Widgets 教程 — Child Widgets}
+ \nextpage {Widgets 教程 — Nested Layouts}
+ \example tutorials/widgets/windowlayout
+ \title Widgets 教程 — 使用布局
+
+ 通常,å widget 是通过使用布局对象在窗å£ä¸è¿›è¡ŒæŽ’列,而ä¸æ˜¯é€šè¿‡æŒ‡å®šä½ç½®å’Œå¤§å°è¿›è¡ŒæŽ’列。在æ¤å¤„ï¼Œæˆ‘ä»¬æž„é€ è¦å¹¶æŽ’æŽ’åˆ—çš„æ ‡ç¾å’Œè¡Œç¼–辑框 widget。
+
+ \raw HTML
+
+
+ \endraw
+ \snippet tutorials/widgets/windowlayout/main.cpp main program
+ \raw HTML
+
+ \endraw
+ \inlineimage widgets-tutorial-windowlayout.png
+ \raw HTML
+
+
+ \endraw
+
+ æˆ‘ä»¬æž„é€ çš„å¸ƒå±€å¯¹è±¡ç®¡ç†é€šè¿‡ \l{QHBoxLayout::}{addWidget()} 函数æ供的 widget çš„ä½ç½®å’Œå¤§å°ã€‚布局本身是通过调用 \l{QWidget::}{setLayout()} æ供给窗å£çš„。布局仅å¯é€šè¿‡å…¶å¯¹æ‰€ç®¡ç†çš„ widget(和其他布局)的效果æ‰å¯æ˜¾ç¤ºã€‚
+
+ 在上文示例ä¸ï¼Œæ¯ä¸ª widget 的所属关系并ä¸æ˜Žæ˜¾ã€‚ç”±äºŽæˆ‘ä»¬æœªä½¿ç”¨çˆ¶çº§å¯¹è±¡æž„é€ widget 和布局,我们会看到一个空窗å£å’Œä¸¤ä¸ªåŒ…å«äº†æ ‡ç¾ä¸Žè¡Œç¼–辑框的窗å£ã€‚ä¸è¿‡ï¼Œå¦‚果我们告知布局æ¥ç®¡ç†æ ‡ç¾å’Œè¡Œç¼–辑框,并在窗å£ä¸è®¾ç½®å¸ƒå±€ï¼Œä¸¤ä¸ª widget 与布局本身就都会æˆä¸ºçª—å£çš„å项。
+*/
+
+/*!
+ \page widgets-tutorial-nestedlayouts.html
+ \contentspage {Widgets 教程}{目录}
+ \previouspage {Widgets 教程 — 使用布局}
+ \example tutorials/widgets/nestedlayouts
+ \title Widgets 教程 - Nested Layouts
+
+ 由于 widget å¯åŒ…å«å…¶ä»– widget,布局å¯ç”¨æ¥æ供按ä¸åŒå±‚次分组的 widget。这里,我们è¦åœ¨æ˜¾ç¤ºæŸ¥è¯¢ç»“果的表视图上方ã€çª—å£é¡¶éƒ¨çš„行编辑框æ—ï¼Œæ˜¾ç¤ºä¸€ä¸ªæ ‡ç¾ã€‚
+
+ We achieve this by creating two layouts: \c{queryLayout} is a QHBoxLayout
+ that contains QLabel and QLineEdit widgets placed side-by-side;
+ \c{mainLayout} is a QVBoxLayout that contains \c{queryLayout} and a
+ QTableView arranged vertically.
+
+ \raw HTML
+
+
+ \endraw
+ \snippet tutorials/widgets/nestedlayouts/main.cpp first part
+ \snippet tutorials/widgets/nestedlayouts/main.cpp last part
+ \raw HTML
+
+ \endraw
+ \inlineimage widgets-tutorial-nestedlayouts.png
+ \raw HTML
+
+
+ \endraw
+
+ Note that we call the \c{mainLayout}'s \l{QBoxLayout::}{addLayout()}
+ function to insert the \c{queryLayout} above the \c{resultView} table.
+
+ We have omitted the code that sets up the model containing the data shown
+ by the QTableView widget, \c resultView. For completeness, we show this below.
+
+ 除了 QHBoxLayout å’Œ QVBoxLayout,Qt 还æ供了 QGridLayout å’Œ QFormLayout ç±»æ¥å助实现更å¤æ‚的用户界é¢ã€‚
+ These can be seen if you run \l{Qt Designer}.
+
+ \section1 Setting up the Model
+
+ In the code above, we did not show where the table's data came from
+ because we wanted to concentrate on the use of layouts. Here, we see
+ that the model holds a number of items corresponding to rows, each of
+ which is set up to contain data for two columns.
+
+ \snippet tutorials/widgets/nestedlayouts/main.cpp set up the model
+
+ The use of models and views is covered in the
+ \l{Item Views Examples} and in the \l{Model/View Programming} overview.
+*/
diff --git a/tools/qdoc3/config.cpp b/tools/qdoc3/config.cpp
index f62ec24..acb1576 100644
--- a/tools/qdoc3/config.cpp
+++ b/tools/qdoc3/config.cpp
@@ -671,7 +671,9 @@ void Config::load(Location location, const QString& fileName)
location.fatal(tr("Cannot open file '%1': %2").arg(fileName).arg(fin.errorString()));
}
- QString text = fin.readAll();
+ QTextStream stream(&fin);
+ stream.setCodec("UTF-8");
+ QString text = stream.readAll();
text += QLatin1String("\n\n");
text += QChar('\0');
fin.close();
--
cgit v0.12
From c8b9acf8abc26e71529b8f5ed6402e70a03b9ac8 Mon Sep 17 00:00:00 2001
From: Justin McPherson
Date: Fri, 5 Feb 2010 10:20:23 +1000
Subject: Make sure include for QAudio namespace is created
Task-number: QTBUG-7891
Reviewed-by: Kurt Korbatits
---
bin/syncqt | 2 ++
1 file changed, 2 insertions(+)
diff --git a/bin/syncqt b/bin/syncqt
index 1fb5304..db6dce6 100755
--- a/bin/syncqt
+++ b/bin/syncqt
@@ -194,6 +194,8 @@ sub classNames {
push @ret, "QtConcurrentFilter"
} elsif(basename($iheader) eq "qtconcurrentrun.h") {
push @ret, "QtConcurrentRun"
+ } elsif(basename($iheader) eq "qaudio.h") {
+ push @ret, "QAudio"
}
my $parsable = "";
--
cgit v0.12
From f92253080a73a60a3d6ce8343b94788334ce9a2b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?=
Date: Thu, 4 Feb 2010 11:05:39 +0100
Subject: Compile.
---
src/gui/kernel/qwidget_mac.mm | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/gui/kernel/qwidget_mac.mm b/src/gui/kernel/qwidget_mac.mm
index b5888b4..9e7517f 100644
--- a/src/gui/kernel/qwidget_mac.mm
+++ b/src/gui/kernel/qwidget_mac.mm
@@ -569,7 +569,7 @@ inline static void qt_mac_set_window_group_to_popup(OSWindowRef window)
void qt_mac_set_needs_display(QWidget *widget, QRegion region)
{
NSView *theNSView = qt_mac_nativeview_for(widget);
- if (region.isNull()) {
+ if (region.isEmpty()) {
[theNSView setNeedsDisplay:YES];
return;
}
--
cgit v0.12
From bd36d753337090a2878fc0ca4117e2250c5ae1b7 Mon Sep 17 00:00:00 2001
From: Aleksandar Sasha Babic
Date: Fri, 5 Feb 2010 09:34:48 +0100
Subject: Fixing 'softvfp+vfpv2' compiling issue for Tb9.2
When compiling with -fpu=softvfp+vfpv2 on Tb9.2 we were getting the
segmentattion fault.
This seems to be due to the RVCT bug when it comes to using int->float
(and reverse) castings. One extra level of indirection (function
call) has to be applied.
Task-number: QTBUG-4893
Reviewed-by: TrustMe
---
src/gui/painting/qdrawhelper.cpp | 4 ++++
src/gui/painting/qmath_p.h | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 194dda3..660a2a8 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -2408,7 +2408,11 @@ static inline int soft_light_op(int dst, int src, int da, int sa)
else if (4 * dst <= da)
return (dst * sa * 255 + da * (src2 - sa) * ((((16 * dst_np - 12 * 255) * dst_np + 3 * 65025) * dst_np) / 65025) + temp) / 65025;
else {
+# ifdef Q_CC_RVCT // needed to avoid compiler crash in RVCT 2.2
+ return (dst * sa * 255 + da * (src2 - sa) * (qIntSqrtInt(dst_np * 255) - dst_np) + temp) / 65025;
+# else
return (dst * sa * 255 + da * (src2 - sa) * (int(sqrt(qreal(dst_np * 255))) - dst_np) + temp) / 65025;
+# endif
}
}
diff --git a/src/gui/painting/qmath_p.h b/src/gui/painting/qmath_p.h
index cd9f5ea..8a5f5ab 100644
--- a/src/gui/painting/qmath_p.h
+++ b/src/gui/painting/qmath_p.h
@@ -54,6 +54,7 @@
//
#include
+#include
QT_BEGIN_NAMESPACE
@@ -61,6 +62,11 @@ static const qreal Q_PI = qreal(3.14159265358979323846); // pi
static const qreal Q_2PI = qreal(6.28318530717958647693); // 2*pi
static const qreal Q_PI2 = qreal(1.57079632679489661923); // pi/2
+inline int qIntSqrtInt(int v)
+{
+ return static_cast(qSqrt(static_cast(v)));
+}
+
QT_END_NAMESPACE
#endif // QMATH_P_H
--
cgit v0.12
From 3baf7b981a8f40ed13c2ffb62d2188a16005f69c Mon Sep 17 00:00:00 2001
From: Joerg Bornemann
Date: Fri, 5 Feb 2010 09:48:22 +0100
Subject: fix regression from Qt 4.5 wrt missing text pixels in QTabBar
The line spacing fix showed a bug in QCommonStylePrivate::tabLayout.
Since QFontMetrics::height() now usually returns one pixel less than
in Qt 4.5, the tab bar is one pixel smaller.
Squeezing the tab rect vertically can result in missing pixels.
This depends on anti-aliasing settings and font size.
The new behaviour in tabLayout is now: If we have to shift the tab
rect, then we move its position instead of changing its height.
Task-number: QTBUG-7137
Reviewed-by: jbache
---
src/gui/styles/qcommonstyle.cpp | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/gui/styles/qcommonstyle.cpp b/src/gui/styles/qcommonstyle.cpp
index 74d3ec3..b1924e7 100644
--- a/src/gui/styles/qcommonstyle.cpp
+++ b/src/gui/styles/qcommonstyle.cpp
@@ -1149,10 +1149,10 @@ void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget
int vpadding = proxyStyle->pixelMetric(QStyle::PM_TabBarTabVSpace, opt, widget) / 2;
if (opt->shape == QTabBar::RoundedSouth || opt->shape == QTabBar::TriangularSouth)
verticalShift = -verticalShift;
- tr.adjust(hpadding, vpadding, horizontalShift - hpadding, verticalShift - vpadding);
+ tr.adjust(hpadding, verticalShift - vpadding, horizontalShift - hpadding, vpadding);
bool selected = opt->state & QStyle::State_Selected;
if (selected) {
- tr.setBottom(tr.bottom() - verticalShift);
+ tr.setTop(tr.top() - verticalShift);
tr.setRight(tr.right() - horizontalShift);
}
--
cgit v0.12
From 79fb890a4f2a13cc0f21e92f5b2a6e10af1430b4 Mon Sep 17 00:00:00 2001
From: Samuel Nevala
Date: Fri, 5 Feb 2010 09:51:00 +0200
Subject: s60 application loses normalGeometry when returning from fullscreen
Problem description: normalGeomerty lost during showFullScreen
1. Reported problen was due on void QSymbianControl::PositionChanged()
over write top->normaGeometry on every position change. As fix
top->normalGeometry is moved to new rect:s top left only when
widget windowState == 0.
2. Also made some new qwidget auto tests. Refactored s60 side
setWindowState to be more readable. Minimized window state now
hides window decoration.
QApplication & QWidget autotest run on emulator and tested on
s60 5.0 hw using attached application.
http://bugreports.qt.nokia.com/browse/QTBUG-6231
Task-number:QTBUG-6231
Merge-request: 2256
Reviewed-by: Jani Hautakangas
---
src/gui/kernel/qapplication_s60.cpp | 17 ++-
src/gui/kernel/qwidget_s60.cpp | 108 +++++------------
tests/auto/qwidget/tst_qwidget.cpp | 224 ++++++++++++++++++++++++++++++++++++
3 files changed, 262 insertions(+), 87 deletions(-)
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index 6e03d7c..4a137ee 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -924,8 +924,8 @@ void QSymbianControl::PositionChanged()
cr.moveTopLeft(newPos);
qwidget->data->crect = cr;
QTLWExtra *top = qwidget->d_func()->maybeTopData();
- if (top)
- top->normalGeometry = cr;
+ if (top && (qwidget->windowState() & (~Qt::WindowActive)) == Qt::WindowNoState)
+ top->normalGeometry.moveTopLeft(newPos);
if (qwidget->isVisible()) {
QMoveEvent e(newPos, oldPos);
qt_sendSpontaneousEvent(qwidget, &e);
@@ -960,15 +960,14 @@ void QSymbianControl::FocusChanged(TDrawNow /* aDrawNow */)
qwidget->d_func()->setWindowIcon_sys(true);
qwidget->d_func()->setWindowTitle_sys(qwidget->windowTitle());
#ifdef Q_WS_S60
- // If widget is fullscreen, hide status pane and button container
- // otherwise show them.
+ // If widget is fullscreen/minimized, hide status pane and button container otherwise show them.
CEikStatusPane* statusPane = S60->statusPane();
CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
- bool isFullscreen = qwidget->windowState() & Qt::WindowFullScreen;
- if (statusPane && (bool)statusPane->IsVisible() == isFullscreen)
- statusPane->MakeVisible(!isFullscreen);
- if (buttonGroup && (bool)buttonGroup->IsVisible() == isFullscreen)
- buttonGroup->MakeVisible(!isFullscreen);
+ TBool visible = !(qwidget->windowState() & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ if (statusPane)
+ statusPane->MakeVisible(visible);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(visible);
#endif
} else if (QApplication::activeWindow() == qwidget->window()) {
if (CCoeEnv::Static()->AppUi()->IsDisplayingMenuOrDialog()) {
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index 0ce7534..c84e1cc 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -1046,96 +1046,48 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
return;
if (isWindow()) {
-#ifdef Q_WS_S60
- // Change window decoration visibility if switching to or from fullsccreen
- // In addition decoration visibility is changed when the initial has been
- // WindowNoState.
- // The window decoration visibility has to be changed before doing actual
- // window state change since in that order the availableGeometry will return
- // directly the right size and we will avoid unnecessarty redraws
- if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen) ||
- oldstate == Qt::WindowNoState) {
- CEikStatusPane* statusPane = S60->statusPane();
- CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
- if (newstate & Qt::WindowFullScreen) {
- if (statusPane)
- statusPane->MakeVisible(false);
- if (buttonGroup)
- buttonGroup->MakeVisible(false);
- } else {
- if (statusPane)
- statusPane->MakeVisible(true);
- if (buttonGroup)
- buttonGroup->MakeVisible(true);
- }
+ QSymbianControl *window = static_cast(effectiveWinId());
+ if (window && newstate & Qt::WindowMinimized) {
+ window->setFocusSafely(false);
+ window->MakeVisible(false);
+ } else if (window && oldstate & Qt::WindowMinimized) {
+ window->setFocusSafely(true);
+ window->MakeVisible(true);
}
+
+#ifdef Q_WS_S60
+ // Hide window decoration when switching to fullsccreen / minimized otherwise show decoration.
+ // The window decoration visibility has to be changed before doing actual window state
+ // change since in that order the availableGeometry will return directly the right size and
+ // we will avoid unnecessarty redraws
+ CEikStatusPane* statusPane = S60->statusPane();
+ CEikButtonGroupContainer* buttonGroup = S60->buttonGroupContainer();
+ TBool visible = !(newstate & (Qt::WindowFullScreen | Qt::WindowMinimized));
+ if (statusPane)
+ statusPane->MakeVisible(visible);
+ if (buttonGroup)
+ buttonGroup->MakeVisible(visible);
#endif // Q_WS_S60
createWinId();
Q_ASSERT(testAttribute(Qt::WA_WState_Created));
- QTLWExtra *top = d->topData();
-
// Ensure the initial size is valid, since we store it as normalGeometry below.
if (!testAttribute(Qt::WA_Resized) && !isVisible())
adjustSize();
- if ((oldstate & Qt::WindowMaximized) != (newstate & Qt::WindowMaximized)) {
- if ((newstate & Qt::WindowMaximized)) {
- const QRect normalGeometry = geometry();
+ QTLWExtra *top = d->topData();
+ const QRect normalGeometry = (top->normalGeometry.width() < 0) ? geometry() : top->normalGeometry;
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->availableGeometry(this));
- top->normalGeometry = r;
+ if (newstate & Qt::WindowFullScreen)
+ setGeometry(qApp->desktop()->screenGeometry(this));
+ else if (newstate & Qt::WindowMaximized)
+ setGeometry(qApp->desktop()->availableGeometry(this));
+ else
+ setGeometry(normalGeometry);
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- } else {
- // restore original geometry
- setGeometry(top->normalGeometry);
- }
- }
- if ((oldstate & Qt::WindowFullScreen) != (newstate & Qt::WindowFullScreen)) {
- if (newstate & Qt::WindowFullScreen) {
- const QRect normalGeometry = geometry();
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->screenGeometry(this));
-
- top->normalGeometry = r;
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- } else {
- if (newstate & Qt::WindowMaximized) {
- const QRect r = top->normalGeometry;
- setGeometry(qApp->desktop()->availableGeometry(this));
- top->normalGeometry = r;
- } else {
- setGeometry(top->normalGeometry);
- }
- }
- }
- if ((oldstate & Qt::WindowMinimized) != (newstate & Qt::WindowMinimized)) {
- if (newstate & Qt::WindowMinimized) {
- if (isVisible()) {
- QSymbianControl *id = static_cast(effectiveWinId());
- if (id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
- id->setFocusSafely(false);
- id->MakeVisible(false);
- }
- } else {
- if (isVisible()) {
- QSymbianControl *id = static_cast(effectiveWinId());
- id->MakeVisible(true);
- if (!id->IsFocused()) // Avoid unnecessary calls to FocusChanged()
- id->setFocusSafely(true);
- }
- const QRect normalGeometry = geometry();
- const QRect r = top->normalGeometry;
- top->normalGeometry = r;
- if (top->normalGeometry.width() < 0)
- top->normalGeometry = normalGeometry;
- }
- }
+ //restore normal geometry
+ top->normalGeometry = normalGeometry;
}
data->window_state = newstate;
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index ea90ae3..88bdc72 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -391,6 +391,10 @@ private slots:
#ifdef Q_OS_SYMBIAN
void cbaVisibility();
+ void fullScreenWindowModeTransitions();
+ void maximizedWindowModeTransitions();
+ void minimizedWindowModeTransitions();
+ void normalWindowModeTransitions();
#endif
void focusProxyAndInputMethods();
@@ -9687,6 +9691,226 @@ void tst_QWidget::cbaVisibility()
CEikButtonGroupContainer* buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
QVERIFY(buttonGroup->IsVisible());
}
+
+void tst_QWidget::fullScreenWindowModeTransitions()
+{
+ QWidget widget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ QPushButton *button = new QPushButton("test Button");
+ layout->addWidget(button);
+ widget.setLayout(layout);
+ widget.show();
+
+ const QRect normalGeometry = widget.normalGeometry();
+ const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+ const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+ CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+ CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+
+ //Enter
+ widget.showNormal();
+ widget.showFullScreen();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showMaximized();
+ widget.showFullScreen();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showMinimized();
+ widget.showFullScreen();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ //Exit
+ widget.showFullScreen();
+ widget.showNormal();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showFullScreen();
+ widget.showMaximized();
+ QCOMPARE(widget.geometry(), maximumScreenGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showFullScreen();
+ widget.showMinimized();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+}
+
+void tst_QWidget::maximizedWindowModeTransitions()
+{
+ QWidget widget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ QPushButton *button = new QPushButton("test Button");
+ layout->addWidget(button);
+ widget.setLayout(layout);
+ widget.show();
+
+ const QRect normalGeometry = widget.normalGeometry();
+ const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+ const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+ CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+ CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+
+ //Enter
+ widget.showNormal();
+ widget.showMaximized();
+ QCOMPARE(widget.geometry(), maximumScreenGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showFullScreen();
+ widget.showMaximized();
+ QCOMPARE(widget.geometry(), maximumScreenGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showMinimized();
+ widget.showMaximized();
+ QCOMPARE(widget.geometry(), maximumScreenGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ //Exit
+ widget.showMaximized();
+ widget.showNormal();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showMaximized();
+ widget.showFullScreen();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showMaximized();
+ widget.showMinimized();
+ // Since showMinimized hides window decoration availableGeometry gives different value
+ // than with decoration visible. Altual size does not really matter since widget is invisible.
+ QCOMPARE(widget.geometry(), qApp->desktop()->availableGeometry(&widget));
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+}
+
+void tst_QWidget::minimizedWindowModeTransitions()
+{
+ QWidget widget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ QPushButton *button = new QPushButton("test Button");
+ layout->addWidget(button);
+ widget.setLayout(layout);
+ widget.show();
+
+ const QRect normalGeometry = widget.normalGeometry();
+ const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+ const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+ CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+ CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+
+ //Enter
+ widget.showNormal();
+ widget.showMinimized();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showFullScreen();
+ widget.showMinimized();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showMaximized();
+ widget.showMinimized();
+ // Since showMinimized hides window decoration availableGeometry gives different value
+ // than with decoration visible. Altual size does not really matter since widget is invisible.
+ QCOMPARE(widget.geometry(), qApp->desktop()->availableGeometry(&widget));
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ //Exit
+ widget.showMinimized();
+ widget.showNormal();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showMinimized();
+ widget.showFullScreen();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showMinimized();
+ widget.showMaximized();
+ QCOMPARE(widget.geometry(), maximumScreenGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+}
+
+void tst_QWidget::normalWindowModeTransitions()
+{
+ QWidget widget;
+ QVBoxLayout *layout = new QVBoxLayout;
+ QPushButton *button = new QPushButton("test Button");
+ layout->addWidget(button);
+ widget.setLayout(layout);
+ widget.show();
+
+ const QRect normalGeometry = widget.normalGeometry();
+ const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
+ const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
+ CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
+ CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
+
+ //Enter
+ widget.showMaximized();
+ widget.showNormal();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showFullScreen();
+ widget.showNormal();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showMinimized();
+ widget.showNormal();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ //Exit
+ widget.showNormal();
+ widget.showMaximized();
+ QCOMPARE(widget.geometry(), maximumScreenGeometry);
+ QVERIFY(buttonGroup->IsVisible());
+ QVERIFY(statusPane->IsVisible());
+
+ widget.showNormal();
+ widget.showFullScreen();
+ QCOMPARE(widget.geometry(), fullScreenGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+
+ widget.showNormal();
+ widget.showMinimized();
+ QCOMPARE(widget.geometry(), normalGeometry);
+ QVERIFY(!buttonGroup->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
+}
#endif
class InputContextTester : public QInputContext
--
cgit v0.12
From fd12fbcf332878ab6a5b6ef8f09804b8598faced Mon Sep 17 00:00:00 2001
From: Jani Hautakangas
Date: Fri, 5 Feb 2010 12:29:08 +0200
Subject: Whitespace/tab fixes.
Reviewed-by: Trust me
---
src/gui/kernel/qwidget_s60.cpp | 2 +-
tests/auto/qwidget/tst_qwidget.cpp | 90 +++++++++++++++++++-------------------
2 files changed, 46 insertions(+), 46 deletions(-)
diff --git a/src/gui/kernel/qwidget_s60.cpp b/src/gui/kernel/qwidget_s60.cpp
index c84e1cc..a844430 100644
--- a/src/gui/kernel/qwidget_s60.cpp
+++ b/src/gui/kernel/qwidget_s60.cpp
@@ -1083,7 +1083,7 @@ void QWidget::setWindowState(Qt::WindowStates newstate)
setGeometry(qApp->desktop()->screenGeometry(this));
else if (newstate & Qt::WindowMaximized)
setGeometry(qApp->desktop()->availableGeometry(this));
- else
+ else
setGeometry(normalGeometry);
//restore normal geometry
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index 88bdc72..80b693c 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -9700,50 +9700,50 @@ void tst_QWidget::fullScreenWindowModeTransitions()
layout->addWidget(button);
widget.setLayout(layout);
widget.show();
-
+
const QRect normalGeometry = widget.normalGeometry();
const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
-
- //Enter
+
+ //Enter
widget.showNormal();
widget.showFullScreen();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
-
+ QVERIFY(!statusPane->IsVisible());
+
widget.showMaximized();
widget.showFullScreen();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
-
+ QVERIFY(!statusPane->IsVisible());
+
widget.showMinimized();
widget.showFullScreen();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
-
- //Exit
+ QVERIFY(!statusPane->IsVisible());
+
+ //Exit
widget.showFullScreen();
widget.showNormal();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
+ QVERIFY(statusPane->IsVisible());
widget.showFullScreen();
widget.showMaximized();
QCOMPARE(widget.geometry(), maximumScreenGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
+ QVERIFY(statusPane->IsVisible());
widget.showFullScreen();
widget.showMinimized();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
}
void tst_QWidget::maximizedWindowModeTransitions()
@@ -9760,38 +9760,38 @@ void tst_QWidget::maximizedWindowModeTransitions()
const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
-
+
//Enter
widget.showNormal();
widget.showMaximized();
QCOMPARE(widget.geometry(), maximumScreenGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
-
+ QVERIFY(statusPane->IsVisible());
+
widget.showFullScreen();
widget.showMaximized();
QCOMPARE(widget.geometry(), maximumScreenGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
-
+ QVERIFY(statusPane->IsVisible());
+
widget.showMinimized();
widget.showMaximized();
QCOMPARE(widget.geometry(), maximumScreenGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
-
+ QVERIFY(statusPane->IsVisible());
+
//Exit
widget.showMaximized();
widget.showNormal();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
+ QVERIFY(statusPane->IsVisible());
widget.showMaximized();
widget.showFullScreen();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
widget.showMaximized();
widget.showMinimized();
@@ -9799,7 +9799,7 @@ void tst_QWidget::maximizedWindowModeTransitions()
// than with decoration visible. Altual size does not really matter since widget is invisible.
QCOMPARE(widget.geometry(), qApp->desktop()->availableGeometry(&widget));
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
}
void tst_QWidget::minimizedWindowModeTransitions()
@@ -9810,52 +9810,52 @@ void tst_QWidget::minimizedWindowModeTransitions()
layout->addWidget(button);
widget.setLayout(layout);
widget.show();
-
+
const QRect normalGeometry = widget.normalGeometry();
const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
-
+
//Enter
widget.showNormal();
widget.showMinimized();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
-
+ QVERIFY(!statusPane->IsVisible());
+
widget.showFullScreen();
widget.showMinimized();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
-
+ QVERIFY(!statusPane->IsVisible());
+
widget.showMaximized();
widget.showMinimized();
// Since showMinimized hides window decoration availableGeometry gives different value
// than with decoration visible. Altual size does not really matter since widget is invisible.
QCOMPARE(widget.geometry(), qApp->desktop()->availableGeometry(&widget));
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
//Exit
widget.showMinimized();
widget.showNormal();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
+ QVERIFY(statusPane->IsVisible());
widget.showMinimized();
widget.showFullScreen();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
widget.showMinimized();
widget.showMaximized();
QCOMPARE(widget.geometry(), maximumScreenGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
+ QVERIFY(statusPane->IsVisible());
}
void tst_QWidget::normalWindowModeTransitions()
@@ -9866,50 +9866,50 @@ void tst_QWidget::normalWindowModeTransitions()
layout->addWidget(button);
widget.setLayout(layout);
widget.show();
-
+
const QRect normalGeometry = widget.normalGeometry();
const QRect fullScreenGeometry = qApp->desktop()->screenGeometry(&widget);
const QRect maximumScreenGeometry = qApp->desktop()->availableGeometry(&widget);
CEikStatusPane *statusPane = CEikonEnv::Static()->AppUiFactory()->StatusPane();
CEikButtonGroupContainer *buttonGroup = CEikonEnv::Static()->AppUiFactory()->Cba();
-
+
//Enter
widget.showMaximized();
widget.showNormal();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
-
+ QVERIFY(statusPane->IsVisible());
+
widget.showFullScreen();
widget.showNormal();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
-
+ QVERIFY(statusPane->IsVisible());
+
widget.showMinimized();
widget.showNormal();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
-
+ QVERIFY(statusPane->IsVisible());
+
//Exit
widget.showNormal();
widget.showMaximized();
QCOMPARE(widget.geometry(), maximumScreenGeometry);
QVERIFY(buttonGroup->IsVisible());
- QVERIFY(statusPane->IsVisible());
+ QVERIFY(statusPane->IsVisible());
widget.showNormal();
widget.showFullScreen();
QCOMPARE(widget.geometry(), fullScreenGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
-
+ QVERIFY(!statusPane->IsVisible());
+
widget.showNormal();
widget.showMinimized();
QCOMPARE(widget.geometry(), normalGeometry);
QVERIFY(!buttonGroup->IsVisible());
- QVERIFY(!statusPane->IsVisible());
+ QVERIFY(!statusPane->IsVisible());
}
#endif
--
cgit v0.12
From 76bcd00f74b0977b5f6ce12295aae987ea9ad4c1 Mon Sep 17 00:00:00 2001
From: aavit
Date: Fri, 5 Feb 2010 12:04:38 +0100
Subject: Performance: Use QImage's smoothscaling instead of old private code
For historical reasons, QJpegHandler had its own smoothscaling code.
QImage's scaling has since evolved to become both faster and better, so
avoid code duplication and just use QImage for scaling.
Reviewed-by: Trond
---
src/plugins/imageformats/jpeg/qjpeghandler.cpp | 574 +++----------------------
1 file changed, 67 insertions(+), 507 deletions(-)
diff --git a/src/plugins/imageformats/jpeg/qjpeghandler.cpp b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
index 6cb93ad..4b4712c 100644
--- a/src/plugins/imageformats/jpeg/qjpeghandler.cpp
+++ b/src/plugins/imageformats/jpeg/qjpeghandler.cpp
@@ -52,8 +52,6 @@
#undef FAR
#endif
-// hw: optimize smoothscaler for returning 24-bit images
-
// including jpeglib.h seems to be a little messy
extern "C" {
// mingw includes rpcndr.h but does not define boolean
@@ -76,433 +74,6 @@ extern "C" {
QT_BEGIN_NAMESPACE
-//#define QT_NO_IMAGE_SMOOTHSCALE
-#ifndef QT_NO_IMAGE_SMOOTHSCALE
-class QImageSmoothScalerPrivate;
-class QImageSmoothScaler
-{
-public:
- QImageSmoothScaler(const int w, const int h, const QImage &src);
- QImageSmoothScaler(const int srcWidth, const int srcHeight,
- const int dstWidth, const int dstHeight);
-
- virtual ~QImageSmoothScaler(void);
-
- QImage scale();
-
-private:
- QImageSmoothScalerPrivate *d;
- virtual QRgb *scanLine(const int line = 0, const QImage *src = 0);
-};
-
-class QImageSmoothScalerPrivate
-{
-public:
- int cols;
- int newcols;
- int rows;
- int newrows;
- bool hasAlpha;
-
- const QImage *src;
-
- void setup(const int srcWidth, const int srcHeight, const int dstWidth,
- const int dstHeight, bool hasAlphaChannel);
-};
-
-QImageSmoothScaler::QImageSmoothScaler(const int w, const int h,
- const QImage &src)
-{
- d = new QImageSmoothScalerPrivate;
-
- d->setup(src.width(), src.height(), w, h, src.hasAlphaChannel() );
- this->d->src = &src;
-}
-
-QImageSmoothScaler::QImageSmoothScaler(const int srcWidth, const int srcHeight,
- const int dstWidth, const int dstHeight)
-{
- d = new QImageSmoothScalerPrivate;
- d->setup(srcWidth, srcHeight, dstWidth, dstHeight, 0);
-}
-
-void QImageSmoothScalerPrivate::setup(const int srcWidth, const int srcHeight,
- const int dstWidth, const int dstHeight,
- bool hasAlphaChannel)
-{
- cols = srcWidth;
- rows = srcHeight;
- newcols = dstWidth;
- newrows = dstHeight;
- hasAlpha = hasAlphaChannel;
-}
-
-QImageSmoothScaler::~QImageSmoothScaler()
-{
- delete d;
-}
-
-inline QRgb *QImageSmoothScaler::scanLine(const int line, const QImage *src)
-{
- return (QRgb*)src->scanLine(line);
-}
-
-/*
- This function uses code based on pnmscale.c by Jef Poskanzer.
-
- pnmscale.c - read a portable anymap and scale it
-
- Copyright (C) 1989, 1991 by Jef Poskanzer.
-
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted, provided
- that the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation. This software is provided "as is" without express or
- implied warranty.
-*/
-
-QImage QImageSmoothScaler::scale()
-{
- long SCALE;
- long HALFSCALE;
- QRgb *xelrow = 0;
- QRgb *tempxelrow = 0;
- QRgb *xP;
- QRgb *nxP;
- int row, rowsread;
- int col, needtoreadrow;
- uchar maxval = 255;
- qreal xscale, yscale;
- long sxscale, syscale;
- long fracrowtofill, fracrowleft;
- long *as;
- long *rs;
- long *gs;
- long *bs;
- int rowswritten = 0;
- QImage dst;
-
- if (d->cols > 4096) {
- SCALE = 4096;
- HALFSCALE = 2048;
- } else {
- int fac = 4096;
- while (d->cols * fac > 4096)
- fac /= 2;
-
- SCALE = fac * d->cols;
- HALFSCALE = fac * d->cols / 2;
- }
-
- xscale = (qreal)d->newcols / (qreal)d->cols;
- yscale = (qreal)d->newrows / (qreal)d->rows;
- sxscale = (long)(xscale * SCALE);
- syscale = (long)(yscale * SCALE);
-
- // shortcut Y scaling if possible
- if (d->newrows != d->rows)
- tempxelrow = new QRgb[d->cols];
-
- if (d->hasAlpha) {
- as = new long[d->cols];
- for (col = 0; col < d->cols; ++col)
- as[col] = HALFSCALE;
- } else {
- as = 0;
- }
- rs = new long[d->cols];
- gs = new long[d->cols];
- bs = new long[d->cols];
- rowsread = 0;
- fracrowleft = syscale;
- needtoreadrow = 1;
- for (col = 0; col < d->cols; ++col)
- rs[col] = gs[col] = bs[col] = HALFSCALE;
- fracrowtofill = SCALE;
-
- dst = QImage(d->newcols, d->newrows, d->hasAlpha ? QImage::Format_ARGB32 : QImage::Format_RGB32);
-
- for (row = 0; row < d->newrows; ++row) {
- // First scale Y from xelrow into tempxelrow.
- if (d->newrows == d->rows) {
- // shortcut Y scaling if possible
- tempxelrow = xelrow = scanLine(rowsread++, d->src);
- } else {
- while (fracrowleft < fracrowtofill) {
- if (needtoreadrow && rowsread < d->rows)
- xelrow = scanLine(rowsread++, d->src);
- for (col = 0, xP = xelrow; col < d->cols; ++col, ++xP) {
- if (as) {
- as[col] += fracrowleft * qAlpha(*xP);
- rs[col] += fracrowleft * qRed(*xP) * qAlpha(*xP) / 255;
- gs[col] += fracrowleft * qGreen(*xP) * qAlpha(*xP) / 255;
- bs[col] += fracrowleft * qBlue(*xP) * qAlpha(*xP) / 255;
- } else {
- rs[col] += fracrowleft * qRed(*xP);
- gs[col] += fracrowleft * qGreen(*xP);
- bs[col] += fracrowleft * qBlue(*xP);
- }
- }
- fracrowtofill -= fracrowleft;
- fracrowleft = syscale;
- needtoreadrow = 1;
- }
- // Now fracrowleft is >= fracrowtofill, so we can produce a row.
- if (needtoreadrow && rowsread < d->rows) {
- xelrow = scanLine(rowsread++, d->src);
- needtoreadrow = 0;
- }
- for (col = 0, xP = xelrow, nxP = tempxelrow; col < d->cols; ++col, ++xP, ++nxP) {
- register long a, r, g, b;
-
- if (as) {
- r = rs[col] + fracrowtofill * qRed(*xP) * qAlpha(*xP) / 255;
- g = gs[col] + fracrowtofill * qGreen(*xP) * qAlpha(*xP) / 255;
- b = bs[col] + fracrowtofill * qBlue(*xP) * qAlpha(*xP) / 255;
- a = as[col] + fracrowtofill * qAlpha(*xP);
- if (a) {
- r = r * 255 / a * SCALE;
- g = g * 255 / a * SCALE;
- b = b * 255 / a * SCALE;
- }
- } else {
- r = rs[col] + fracrowtofill * qRed(*xP);
- g = gs[col] + fracrowtofill * qGreen(*xP);
- b = bs[col] + fracrowtofill * qBlue(*xP);
- a = 0; // unwarn
- }
- r /= SCALE;
- if (r > maxval)
- r = maxval;
- g /= SCALE;
- if (g > maxval)
- g = maxval;
- b /= SCALE;
- if (b > maxval)
- b = maxval;
- if (as) {
- a /= SCALE;
- if (a > maxval)
- a = maxval;
- *nxP = qRgba((int)r, (int)g, (int)b, (int)a);
- as[col] = HALFSCALE;
- } else {
- *nxP = qRgb((int)r, (int)g, (int)b);
- }
- rs[col] = gs[col] = bs[col] = HALFSCALE;
- }
- fracrowleft -= fracrowtofill;
- if (fracrowleft == 0) {
- fracrowleft = syscale;
- needtoreadrow = 1;
- }
- fracrowtofill = SCALE;
- }
-
- // Now scale X from tempxelrow into dst and write it out.
- if (d->newcols == d->cols) {
- // shortcut X scaling if possible
- memcpy(dst.scanLine(rowswritten++), tempxelrow, d->newcols * 4);
- } else {
- register long a, r, g, b;
- register long fraccoltofill, fraccolleft = 0;
- register int needcol;
-
- nxP = (QRgb *)dst.scanLine(rowswritten++);
- QRgb *nxPEnd = nxP + d->newcols;
- fraccoltofill = SCALE;
- a = r = g = b = HALFSCALE;
- needcol = 0;
- for (col = 0, xP = tempxelrow; col < d->cols; ++col, ++xP) {
- fraccolleft = sxscale;
- while (fraccolleft >= fraccoltofill) {
- if (needcol) {
- ++nxP;
- a = r = g = b = HALFSCALE;
- }
- if (as) {
- r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255;
- g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255;
- b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255;
- a += fraccoltofill * qAlpha(*xP);
- if (a) {
- r = r * 255 / a * SCALE;
- g = g * 255 / a * SCALE;
- b = b * 255 / a * SCALE;
- }
- } else {
- r += fraccoltofill * qRed(*xP);
- g += fraccoltofill * qGreen(*xP);
- b += fraccoltofill * qBlue(*xP);
- }
- r /= SCALE;
- if (r > maxval)
- r = maxval;
- g /= SCALE;
- if (g > maxval)
- g = maxval;
- b /= SCALE;
- if (b > maxval)
- b = maxval;
- if (as) {
- a /= SCALE;
- if (a > maxval)
- a = maxval;
- *nxP = qRgba((int)r, (int)g, (int)b, (int)a);
- } else {
- *nxP = qRgb((int)r, (int)g, (int)b);
- }
- fraccolleft -= fraccoltofill;
- fraccoltofill = SCALE;
- needcol = 1;
- }
- if (fraccolleft > 0) {
- if (needcol) {
- ++nxP;
- a = r = g = b = HALFSCALE;
- needcol = 0;
- }
- if (as) {
- a += fraccolleft * qAlpha(*xP);
- r += fraccolleft * qRed(*xP) * qAlpha(*xP) / 255;
- g += fraccolleft * qGreen(*xP) * qAlpha(*xP) / 255;
- b += fraccolleft * qBlue(*xP) * qAlpha(*xP) / 255;
- } else {
- r += fraccolleft * qRed(*xP);
- g += fraccolleft * qGreen(*xP);
- b += fraccolleft * qBlue(*xP);
- }
- fraccoltofill -= fraccolleft;
- }
- }
- if (fraccoltofill > 0) {
- --xP;
- if (as) {
- a += fraccolleft * qAlpha(*xP);
- r += fraccoltofill * qRed(*xP) * qAlpha(*xP) / 255;
- g += fraccoltofill * qGreen(*xP) * qAlpha(*xP) / 255;
- b += fraccoltofill * qBlue(*xP) * qAlpha(*xP) / 255;
- if (a) {
- r = r * 255 / a * SCALE;
- g = g * 255 / a * SCALE;
- b = b * 255 / a * SCALE;
- }
- } else {
- r += fraccoltofill * qRed(*xP);
- g += fraccoltofill * qGreen(*xP);
- b += fraccoltofill * qBlue(*xP);
- }
- }
- if (nxP < nxPEnd) {
- r /= SCALE;
- if (r > maxval)
- r = maxval;
- g /= SCALE;
- if (g > maxval)
- g = maxval;
- b /= SCALE;
- if (b > maxval)
- b = maxval;
- if (as) {
- a /= SCALE;
- if (a > maxval)
- a = maxval;
- *nxP = qRgba((int)r, (int)g, (int)b, (int)a);
- } else {
- *nxP = qRgb((int)r, (int)g, (int)b);
- }
- while (++nxP != nxPEnd)
- nxP[0] = nxP[-1];
- }
- }
- }
-
- if (d->newrows != d->rows && tempxelrow)// Robust, tempxelrow might be 0 1 day
- delete [] tempxelrow;
- if (as) // Avoid purify complaint
- delete [] as;
- if (rs) // Robust, rs might be 0 one day
- delete [] rs;
- if (gs) // Robust, gs might be 0 one day
- delete [] gs;
- if (bs) // Robust, bs might be 0 one day
- delete [] bs;
-
- return dst;
-}
-
-class jpegSmoothScaler : public QImageSmoothScaler
-{
-public:
- jpegSmoothScaler(struct jpeg_decompress_struct *info, const QSize& dstSize, const QRect& clipRect)
- : QImageSmoothScaler(clipRect.width(), clipRect.height(),
- dstSize.width(), dstSize.height())
- {
- cinfo = info;
- clip = clipRect;
- imageCache = QImage(info->output_width, 1, QImage::Format_RGB32);
- }
-
-private:
- QRect clip;
- QImage imageCache;
- struct jpeg_decompress_struct *cinfo;
-
- QRgb *scanLine(const int line = 0, const QImage *src = 0)
- {
- QRgb *out;
- uchar *in;
-
- Q_UNUSED(line);
- Q_UNUSED(src);
-
- uchar* data = imageCache.bits();
-
- // Read ahead if we haven't reached the first clipped scanline yet.
- while (int(cinfo->output_scanline) < clip.y() &&
- cinfo->output_scanline < cinfo->output_height)
- jpeg_read_scanlines(cinfo, &data, 1);
-
- // Read the next scanline. We assume that "line"
- // will never be >= clip.height().
- jpeg_read_scanlines(cinfo, &data, 1);
- if (cinfo->output_scanline == cinfo->output_height)
- jpeg_finish_decompress(cinfo);
-
- out = ((QRgb*)data) + clip.x();
-
- //
- // The smooth scale algorithm only works on 32-bit images;
- // convert from (8|24) bits to 32.
- //
- if (cinfo->output_components == 1) {
- in = data + clip.right();
- for (int i = clip.width(); i--; ) {
- out[i] = qRgb(*in, *in, *in);
- in--;
- }
- } else if (cinfo->out_color_space == JCS_CMYK) {
- in = data + clip.right() * 4;
- for (int i = clip.width(); i--; ) {
- int k = in[3];
- out[i] = qRgb(k * in[0] / 255, k * in[1] / 255, k * in[2] / 255);
- in -= 4;
- }
- } else {
- in = data + clip.right() * 3;
- for (int i = clip.width(); i--; ) {
- out[i] = qRgb(in[0], in[1], in[2]);
- in -= 3;
- }
- }
-
- return out;
- }
-
-};
-#endif
-
struct my_error_mgr : public jpeg_error_mgr {
jmp_buf setjmp_buffer;
};
@@ -844,93 +415,82 @@ static bool read_jpeg_image(QIODevice *device, QImage *outImage,
clip = clip.intersected(imageRect);
}
-#ifndef QT_NO_IMAGE_SMOOTHSCALE
- if (scaledSize.isValid() && scaledSize != clip.size()
- && quality >= HIGH_QUALITY_THRESHOLD) {
+ // Allocate memory for the clipped QImage.
+ if (!ensureValidImage(outImage, &cinfo, clip.size()))
+ longjmp(jerr.setjmp_buffer, 1);
+
+ // Avoid memcpy() overhead if grayscale with no clipping.
+ bool quickGray = (cinfo.output_components == 1 &&
+ clip == imageRect);
+ if (!quickGray) {
+ // Ask the jpeg library to allocate a temporary row.
+ // The library will automatically delete it for us later.
+ // The libjpeg docs say we should do this before calling
+ // jpeg_start_decompress(). We can't use "new" here
+ // because we are inside the setjmp() block and an error
+ // in the jpeg input stream would cause a memory leak.
+ JSAMPARRAY rows = (cinfo.mem->alloc_sarray)
+ ((j_common_ptr)&cinfo, JPOOL_IMAGE,
+ cinfo.output_width * cinfo.output_components, 1);
(void) jpeg_start_decompress(&cinfo);
- jpegSmoothScaler scaler(&cinfo, scaledSize, clip);
- *outImage = scaler.scale();
- } else
-#endif
- {
- // Allocate memory for the clipped QImage.
- if (!ensureValidImage(outImage, &cinfo, clip.size()))
- longjmp(jerr.setjmp_buffer, 1);
-
- // Avoid memcpy() overhead if grayscale with no clipping.
- bool quickGray = (cinfo.output_components == 1 &&
- clip == imageRect);
- if (!quickGray) {
- // Ask the jpeg library to allocate a temporary row.
- // The library will automatically delete it for us later.
- // The libjpeg docs say we should do this before calling
- // jpeg_start_decompress(). We can't use "new" here
- // because we are inside the setjmp() block and an error
- // in the jpeg input stream would cause a memory leak.
- JSAMPARRAY rows = (cinfo.mem->alloc_sarray)
- ((j_common_ptr)&cinfo, JPOOL_IMAGE,
- cinfo.output_width * cinfo.output_components, 1);
-
- (void) jpeg_start_decompress(&cinfo);
-
- while (cinfo.output_scanline < cinfo.output_height) {
- int y = int(cinfo.output_scanline) - clip.y();
- if (y >= clip.height())
- break; // We've read the entire clip region, so abort.
-
- (void) jpeg_read_scanlines(&cinfo, rows, 1);
-
- if (y < 0)
- continue; // Haven't reached the starting line yet.
-
- if (cinfo.output_components == 3) {
- // Expand 24->32 bpp.
- uchar *in = rows[0] + clip.x() * 3;
- QRgb *out = (QRgb*)outImage->scanLine(y);
- for (int i = 0; i < clip.width(); ++i) {
- *out++ = qRgb(in[0], in[1], in[2]);
- in += 3;
- }
- } else if (cinfo.out_color_space == JCS_CMYK) {
- // Convert CMYK->RGB.
- uchar *in = rows[0] + clip.x() * 4;
- QRgb *out = (QRgb*)outImage->scanLine(y);
- for (int i = 0; i < clip.width(); ++i) {
- int k = in[3];
- *out++ = qRgb(k * in[0] / 255, k * in[1] / 255,
- k * in[2] / 255);
- in += 4;
- }
- } else if (cinfo.output_components == 1) {
- // Grayscale.
- memcpy(outImage->scanLine(y),
- rows[0] + clip.x(), clip.width());
+ while (cinfo.output_scanline < cinfo.output_height) {
+ int y = int(cinfo.output_scanline) - clip.y();
+ if (y >= clip.height())
+ break; // We've read the entire clip region, so abort.
+
+ (void) jpeg_read_scanlines(&cinfo, rows, 1);
+
+ if (y < 0)
+ continue; // Haven't reached the starting line yet.
+
+ if (cinfo.output_components == 3) {
+ // Expand 24->32 bpp.
+ uchar *in = rows[0] + clip.x() * 3;
+ QRgb *out = (QRgb*)outImage->scanLine(y);
+ for (int i = 0; i < clip.width(); ++i) {
+ *out++ = qRgb(in[0], in[1], in[2]);
+ in += 3;
}
- }
- } else {
- // Load unclipped grayscale data directly into the QImage.
- (void) jpeg_start_decompress(&cinfo);
- while (cinfo.output_scanline < cinfo.output_height) {
- uchar *row = outImage->scanLine(cinfo.output_scanline);
- (void) jpeg_read_scanlines(&cinfo, &row, 1);
+ } else if (cinfo.out_color_space == JCS_CMYK) {
+ // Convert CMYK->RGB.
+ uchar *in = rows[0] + clip.x() * 4;
+ QRgb *out = (QRgb*)outImage->scanLine(y);
+ for (int i = 0; i < clip.width(); ++i) {
+ int k = in[3];
+ *out++ = qRgb(k * in[0] / 255, k * in[1] / 255,
+ k * in[2] / 255);
+ in += 4;
+ }
+ } else if (cinfo.output_components == 1) {
+ // Grayscale.
+ memcpy(outImage->scanLine(y),
+ rows[0] + clip.x(), clip.width());
}
}
+ } else {
+ // Load unclipped grayscale data directly into the QImage.
+ (void) jpeg_start_decompress(&cinfo);
+ while (cinfo.output_scanline < cinfo.output_height) {
+ uchar *row = outImage->scanLine(cinfo.output_scanline);
+ (void) jpeg_read_scanlines(&cinfo, &row, 1);
+ }
+ }
- if (cinfo.output_scanline == cinfo.output_height)
- (void) jpeg_finish_decompress(&cinfo);
+ if (cinfo.output_scanline == cinfo.output_height)
+ (void) jpeg_finish_decompress(&cinfo);
- if (cinfo.density_unit == 1) {
- outImage->setDotsPerMeterX(int(100. * cinfo.X_density / 2.54));
- outImage->setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54));
- } else if (cinfo.density_unit == 2) {
- outImage->setDotsPerMeterX(int(100. * cinfo.X_density));
- outImage->setDotsPerMeterY(int(100. * cinfo.Y_density));
- }
+ if (cinfo.density_unit == 1) {
+ outImage->setDotsPerMeterX(int(100. * cinfo.X_density / 2.54));
+ outImage->setDotsPerMeterY(int(100. * cinfo.Y_density / 2.54));
+ } else if (cinfo.density_unit == 2) {
+ outImage->setDotsPerMeterX(int(100. * cinfo.X_density));
+ outImage->setDotsPerMeterY(int(100. * cinfo.Y_density));
+ }
- if (scaledSize.isValid() && scaledSize != clip.size())
- *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, Qt::FastTransformation);
+ if (scaledSize.isValid() && scaledSize != clip.size()) {
+ *outImage = outImage->scaled(scaledSize, Qt::IgnoreAspectRatio, quality >= HIGH_QUALITY_THRESHOLD ? Qt::SmoothTransformation : Qt::FastTransformation);
}
}
--
cgit v0.12
From e47c4f7d842724921b0f4c41e4bf0abed380b0ed Mon Sep 17 00:00:00 2001
From: kh1
Date: Mon, 1 Feb 2010 15:32:55 +0100
Subject: Fix some warnings.
Reviewed-by: ck
---
tools/assistant/tools/assistant/main.cpp | 3 +++
1 file changed, 3 insertions(+)
diff --git a/tools/assistant/tools/assistant/main.cpp b/tools/assistant/tools/assistant/main.cpp
index cc76f81..77e5e7c 100644
--- a/tools/assistant/tools/assistant/main.cpp
+++ b/tools/assistant/tools/assistant/main.cpp
@@ -243,6 +243,9 @@ bool useGui(int argc, char *argv[])
}
}
}
+#else
+ Q_UNUSED(argc)
+ Q_UNUSED(argv)
#endif
return gui;
}
--
cgit v0.12
From 1e52af6135f293b353d15d2436e431bac426c5fb Mon Sep 17 00:00:00 2001
From: kh1
Date: Mon, 1 Feb 2010 15:33:48 +0100
Subject: Small style cleanup.
---
tools/assistant/tools/assistant/topicchooser.cpp | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/tools/assistant/tools/assistant/topicchooser.cpp b/tools/assistant/tools/assistant/topicchooser.cpp
index 5aafd5a..262fea8 100644
--- a/tools/assistant/tools/assistant/topicchooser.cpp
+++ b/tools/assistant/tools/assistant/topicchooser.cpp
@@ -62,12 +62,10 @@ TopicChooser::TopicChooser(QWidget *parent, const QString &keyword,
ui.listWidget->setCurrentRow(0);
ui.listWidget->setFocus();
- connect(ui.buttonDisplay, SIGNAL(clicked()),
- this, SLOT(accept()));
- connect(ui.buttonCancel, SIGNAL(clicked()),
- this, SLOT(reject()));
- connect(ui.listWidget, SIGNAL(itemActivated(QListWidgetItem*)),
- this, SLOT(accept()));
+ connect(ui.buttonDisplay, SIGNAL(clicked()), this, SLOT(accept()));
+ connect(ui.buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(ui.listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this,
+ SLOT(accept()));
}
QUrl TopicChooser::link() const
--
cgit v0.12
From 919a8b360950718c68b4da68aeb22a402f99ae3b Mon Sep 17 00:00:00 2001
From: kh1
Date: Wed, 3 Feb 2010 13:54:51 +0100
Subject: Rewrote bookmark handling, the previous code was just plain awful.
Task-number: QT-2603
Reviewed-by: ck
---
tools/assistant/tools/assistant/assistant.pro | 83 +-
tools/assistant/tools/assistant/bookmarkdialog.cpp | 222 +++++
tools/assistant/tools/assistant/bookmarkdialog.h | 88 ++
tools/assistant/tools/assistant/bookmarkdialog.ui | 82 +-
.../tools/assistant/bookmarkfiltermodel.cpp | 322 ++++++
.../tools/assistant/bookmarkfiltermodel.h | 118 +++
tools/assistant/tools/assistant/bookmarkitem.cpp | 138 +++
tools/assistant/tools/assistant/bookmarkitem.h | 90 ++
.../assistant/tools/assistant/bookmarkmanager.cpp | 1029 ++++++--------------
tools/assistant/tools/assistant/bookmarkmanager.h | 201 ++--
tools/assistant/tools/assistant/bookmarkmodel.cpp | 426 ++++++++
tools/assistant/tools/assistant/bookmarkmodel.h | 115 +++
tools/assistant/tools/assistant/bookmarkwidget.ui | 82 ++
tools/assistant/tools/assistant/centralwidget.cpp | 2 +-
tools/assistant/tools/assistant/centralwidget.h | 2 +-
tools/assistant/tools/assistant/mainwindow.cpp | 170 +---
tools/assistant/tools/assistant/mainwindow.h | 29 +-
tools/assistant/tools/assistant/xbelsupport.cpp | 152 ++-
tools/assistant/tools/assistant/xbelsupport.h | 22 +-
19 files changed, 2174 insertions(+), 1199 deletions(-)
create mode 100644 tools/assistant/tools/assistant/bookmarkdialog.cpp
create mode 100644 tools/assistant/tools/assistant/bookmarkdialog.h
create mode 100644 tools/assistant/tools/assistant/bookmarkfiltermodel.cpp
create mode 100644 tools/assistant/tools/assistant/bookmarkfiltermodel.h
create mode 100644 tools/assistant/tools/assistant/bookmarkitem.cpp
create mode 100644 tools/assistant/tools/assistant/bookmarkitem.h
create mode 100644 tools/assistant/tools/assistant/bookmarkmodel.cpp
create mode 100644 tools/assistant/tools/assistant/bookmarkmodel.h
create mode 100644 tools/assistant/tools/assistant/bookmarkwidget.ui
diff --git a/tools/assistant/tools/assistant/assistant.pro b/tools/assistant/tools/assistant/assistant.pro
index 980f078..e62d30c 100644
--- a/tools/assistant/tools/assistant/assistant.pro
+++ b/tools/assistant/tools/assistant/assistant.pro
@@ -16,64 +16,79 @@ DEPENDPATH += ../shared
# ## Work around a qmake issue when statically linking to
# ## not-yet-installed plugins
LIBS += -L$$QT_BUILD_TREE/plugins/sqldrivers
-HEADERS += helpviewer.h \
- mainwindow.h \
- indexwindow.h \
- topicchooser.h \
+HEADERS += aboutdialog.h \
+ bookmarkdialog.h \
+ bookmarkfiltermodel.h \
+ bookmarkitem.h \
+ bookmarkmanager.h \
+ bookmarkmodel.h \
+ centralwidget.h \
+ cmdlineparser.h \
contentwindow.h \
- searchwidget.h \
- preferencesdialog.h \
filternamedialog.h \
- centralwidget.h \
+ helpenginewrapper.h \
+ helpviewer.h \
+ indexwindow.h \
installdialog.h \
- bookmarkmanager.h \
- remotecontrol.h \
- cmdlineparser.h \
- aboutdialog.h \
+ mainwindow.h \
+ preferencesdialog.h \
qtdocinstaller.h \
+ remotecontrol.h \
+ searchwidget.h \
+ topicchooser.h \
+ tracer.h \
xbelsupport.h \
- ../shared/collectionconfiguration.h \
- helpenginewrapper.h \
- tracer.h
+ ../shared/collectionconfiguration.h
win32:HEADERS += remotecontrol_win.h
-SOURCES += helpviewer.cpp \
- main.cpp \
- mainwindow.cpp \
- indexwindow.cpp \
- topicchooser.cpp \
+
+SOURCES += aboutdialog.cpp \
+ bookmarkdialog.cpp \
+ bookmarkfiltermodel.cpp \
+ bookmarkitem.cpp \
+ bookmarkmanager.cpp \
+ bookmarkmodel.cpp \
+ centralwidget.cpp \
+ cmdlineparser.cpp \
contentwindow.cpp \
- searchwidget.cpp \
- preferencesdialog.cpp \
filternamedialog.cpp \
- centralwidget.cpp \
+ helpenginewrapper.cpp \
+ helpviewer.cpp \
+ indexwindow.cpp \
installdialog.cpp \
- bookmarkmanager.cpp \
- remotecontrol.cpp \
- cmdlineparser.cpp \
- aboutdialog.cpp \
+ main.cpp \
+ mainwindow.cpp \
+ preferencesdialog.cpp \
qtdocinstaller.cpp \
+ remotecontrol.cpp \
+ searchwidget.cpp \
+ topicchooser.cpp \
xbelsupport.cpp \
../shared/collectionconfiguration.cpp \
- helpenginewrapper.cpp
-FORMS += topicchooser.ui \
- preferencesdialog.ui \
+
+FORMS += bookmarkdialog.ui \
+ bookmarkwidget.ui \
filternamedialog.ui \
installdialog.ui \
- bookmarkdialog.ui
+ preferencesdialog.ui \
+ topicchooser.ui
+
RESOURCES += assistant.qrc \
assistant_images.qrc
-win32 {
+
+win32 {
!wince*:LIBS += -lshell32
RC_FILE = assistant.rc
}
-mac {
+
+mac {
ICON = assistant.icns
TARGET = Assistant
QMAKE_INFO_PLIST = Info_mac.plist
}
-contains(CONFIG, static): {
+
+contains(CONFIG, static): {
SQLPLUGINS = $$unique(sql-plugins)
- contains(SQLPLUGINS, sqlite): {
+ contains(SQLPLUGINS, sqlite): {
QTPLUGIN += qsqlite
DEFINES += USE_STATIC_SQLITE_PLUGIN
}
diff --git a/tools/assistant/tools/assistant/bookmarkdialog.cpp b/tools/assistant/tools/assistant/bookmarkdialog.cpp
new file mode 100644
index 0000000..f081c15
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkdialog.cpp
@@ -0,0 +1,222 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 "tracer.h"
+
+#include "bookmarkdialog.h"
+#include "bookmarkfiltermodel.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+BookmarkDialog::BookmarkDialog(BookmarkModel *sourceModel, const QString &title,
+ const QString &url, QWidget *parent)
+ : QDialog(parent)
+ , m_url(url)
+ , m_title(title)
+ , bookmarkModel(sourceModel)
+{
+ TRACE_OBJ
+ ui.setupUi(this);
+
+ ui.bookmarkEdit->setText(m_title);
+ ui.newFolderButton->setVisible(false);
+ ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
+
+ connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(accepted()));
+ connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(rejected()));
+ connect(ui.newFolderButton, SIGNAL(clicked()), this, SLOT(addFolder()));
+ connect(ui.toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked()));
+ connect(ui.bookmarkEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+
+ bookmarkProxyModel = new BookmarkFilterModel(this);
+ bookmarkProxyModel->setSourceModel(bookmarkModel);
+ ui.bookmarkFolders->setModel(bookmarkProxyModel);
+ connect(ui.bookmarkFolders, SIGNAL(currentIndexChanged(int)), this,
+ SLOT(currentIndexChanged(int)));
+
+ bookmarkTreeModel = new BookmarkTreeModel(this);
+ bookmarkTreeModel->setSourceModel(bookmarkModel);
+ ui.treeView->setModel(bookmarkTreeModel);
+
+ ui.treeView->expandAll();
+ ui.treeView->setVisible(false);
+ ui.treeView->installEventFilter(this);
+ ui.treeView->viewport()->installEventFilter(this);
+ ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(customContextMenuRequested(QPoint)));
+ connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,
+ QModelIndex)), this, SLOT(currentIndexChanged(QModelIndex)));
+
+ ui.bookmarkFolders->setCurrentIndex(0);
+ ui.treeView->setCurrentIndex(ui.treeView->indexAt(QPoint(2, 2)));
+}
+
+BookmarkDialog::~BookmarkDialog()
+{
+ TRACE_OBJ
+}
+
+bool BookmarkDialog::eventFilter(QObject *object, QEvent *event)
+{
+ TRACE_OBJ
+ if (object != ui.treeView && object != ui.treeView->viewport())
+ return QWidget::eventFilter(object, event);
+
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast(event);
+ switch (ke->key()) {
+ case Qt::Key_F2: {
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(ui.treeView->currentIndex());
+ bookmarkModel->setItemsEditable(false);
+ } break;
+ default: break;
+ }
+ }
+
+ return QObject::eventFilter(object, event);
+}
+
+void BookmarkDialog::currentIndexChanged(int row)
+{
+ TRACE_OBJ
+ QModelIndex next = bookmarkProxyModel->index(row, 0, QModelIndex());
+ if (next.isValid()) {
+ next = bookmarkProxyModel->mapToSource(next);
+ ui.treeView->setCurrentIndex(bookmarkTreeModel->mapFromSource(next));
+ }
+}
+
+void BookmarkDialog::currentIndexChanged(const QModelIndex &index)
+{
+ TRACE_OBJ
+ const QModelIndex current = bookmarkTreeModel->mapToSource(index);
+ if (current.isValid()) {
+ const int row = bookmarkProxyModel->mapFromSource(current).row();
+ ui.bookmarkFolders->setCurrentIndex(row);
+ }
+}
+
+void BookmarkDialog::accepted()
+{
+ TRACE_OBJ
+ QModelIndex index = ui.treeView->currentIndex();
+ if (index.isValid()) {
+ index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index));
+ if (BookmarkItem *item = bookmarkModel->itemFromIndex(index))
+ item->setData(DataVector() << m_title << m_url << false);
+ } else
+ rejected();
+
+ accept();
+}
+
+void BookmarkDialog::rejected()
+{
+ TRACE_OBJ
+ foreach (const QPersistentModelIndex &index, cache)
+ bookmarkModel->removeItem(index);
+ reject();
+}
+
+void BookmarkDialog::addFolder()
+{
+ TRACE_OBJ
+ QModelIndex index = ui.treeView->currentIndex();
+ if (index.isValid()) {
+ index = bookmarkModel->addItem(bookmarkTreeModel->mapToSource(index),
+ true);
+ cache.append(index);
+
+ index = bookmarkTreeModel->mapFromSource(index);
+ if (index.isValid()) {
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(index);
+ ui.treeView->expand(index);
+ ui.treeView->setCurrentIndex(index);
+ bookmarkModel->setItemsEditable(false);
+ }
+ }
+}
+
+void BookmarkDialog::toolButtonClicked()
+{
+ TRACE_OBJ
+ const bool visible = !ui.treeView->isVisible();
+ ui.treeView->setVisible(visible);
+ ui.newFolderButton->setVisible(visible);
+
+ if (visible) {
+ resize(QSize(width(), 400));
+ ui.toolButton->setText(QLatin1String("-"));
+ } else {
+ resize(width(), minimumHeight());
+ ui.toolButton->setText(QLatin1String("+"));
+ }
+}
+
+void BookmarkDialog::textChanged(const QString& text)
+{
+ m_title = text;
+}
+
+void BookmarkDialog::customContextMenuRequested(const QPoint &point)
+{
+ TRACE_OBJ
+ QMenu menu(QLatin1String(""), this);
+ QAction *renameItem = menu.addAction(tr("Rename Folder"));
+
+ QAction *picked = menu.exec(ui.treeView->mapToGlobal(point));
+ if (picked == renameItem) {
+ bookmarkModel->setItemsEditable(true);
+ ui.treeView->edit(ui.treeView->currentIndex());
+ bookmarkModel->setItemsEditable(false);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/tools/assistant/tools/assistant/bookmarkdialog.h b/tools/assistant/tools/assistant/bookmarkdialog.h
new file mode 100644
index 0000000..ba38c7a
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkdialog.h
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 BOOKMARKDIALOG_H
+#define BOOKMARKDIALOG_H
+
+#include "ui_bookmarkdialog.h"
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkModel;
+class BookmarkFilterModel;
+class BookmarkTreeModel;
+
+class BookmarkDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ BookmarkDialog(BookmarkModel *bookmarkModel, const QString &title,
+ const QString &url, QWidget *parent = 0);
+ ~BookmarkDialog();
+
+private:
+ bool eventFilter(QObject *object, QEvent *event);
+
+private slots:
+ void currentIndexChanged(int index);
+ void currentIndexChanged(const QModelIndex &index);
+
+ void accepted();
+ void rejected();
+
+ void addFolder();
+ void toolButtonClicked();
+ void textChanged(const QString& text);
+ void customContextMenuRequested(const QPoint &point);
+
+private:
+ QString m_url;
+ QString m_title;
+ Ui::BookmarkDialog ui;
+ QList cache;
+
+ BookmarkModel *bookmarkModel;
+ BookmarkTreeModel *bookmarkTreeModel;
+ BookmarkFilterModel *bookmarkProxyModel;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKDIALOG_H
diff --git a/tools/assistant/tools/assistant/bookmarkdialog.ui b/tools/assistant/tools/assistant/bookmarkdialog.ui
index 7a878f9..5131531 100644
--- a/tools/assistant/tools/assistant/bookmarkdialog.ui
+++ b/tools/assistant/tools/assistant/bookmarkdialog.ui
@@ -1,38 +1,39 @@
-
+
+
BookmarkDialog
-
-
+
+
0
0
450
- 135
+ 133
-
-
+
+
0
0
-
+
Add Bookmark
-
+
-
-
+
-
-
+
-
-
-
+
+
Bookmark:
-
-
-
+
+
Add in Folder:
@@ -40,35 +41,35 @@
-
-
+
-
-
+
-
-
+
-
-
+
-
-
-
+
+
25
20
-
+
+
-
-
-
+
+
Qt::Horizontal
@@ -76,30 +77,39 @@
-
-
-
-
+
+
+
0
0
+
+ true
+
+
+ true
+
+
+ true
+
-
-
+
-
-
-
+
+
New Folder
-
-
-
+
+
Qt::Horizontal
-
+
QDialogButtonBox::Cancel|QDialogButtonBox::Ok
@@ -116,11 +126,11 @@
BookmarkDialog
accept()
-
+
248
254
-
+
157
274
@@ -132,11 +142,11 @@
BookmarkDialog
reject()
-
+
316
260
-
+
286
274
diff --git a/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp
new file mode 100644
index 0000000..5874493
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkfiltermodel.cpp
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 "bookmarkfiltermodel.h"
+
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
+
+BookmarkFilterModel::BookmarkFilterModel(QObject *parent)
+ : QAbstractProxyModel(parent)
+ , hideBookmarks(true)
+ , sourceModel(0)
+{
+}
+
+void
+BookmarkFilterModel::setSourceModel(QAbstractItemModel *_sourceModel)
+{
+ beginResetModel();
+
+ QAbstractProxyModel::setSourceModel(sourceModel);
+ sourceModel = qobject_cast (_sourceModel);
+
+ connect(sourceModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(changed(QModelIndex, QModelIndex)));
+
+ connect(sourceModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
+ this, SLOT(rowsInserted(QModelIndex, int, int)));
+
+ connect(sourceModel, SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)),
+ this, SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
+ connect(sourceModel, SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
+ SLOT(rowsRemoved(QModelIndex, int, int)));
+
+ connect(sourceModel, SIGNAL(layoutAboutToBeChanged()), this,
+ SLOT(layoutAboutToBeChanged()));
+ connect(sourceModel, SIGNAL(layoutChanged()), this,
+ SLOT(layoutChanged()));
+
+ connect(sourceModel, SIGNAL(modelAboutToBeReset()), this,
+ SLOT(modelAboutToBeReset()));
+ connect(sourceModel, SIGNAL(modelReset()), this, SLOT(modelReset()));
+
+ if (sourceModel)
+ setupCache(sourceModel->index(0, 0, QModelIndex()));
+
+ endResetModel();
+}
+
+int
+BookmarkFilterModel::rowCount(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ return cache.count();
+}
+
+int
+BookmarkFilterModel::columnCount(const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ if (sourceModel)
+ return sourceModel->columnCount();
+ return 0;
+}
+
+QModelIndex
+BookmarkFilterModel::mapToSource(const QModelIndex &proxyIndex) const
+{
+ const int row = proxyIndex.row();
+ if (proxyIndex.isValid() && row >= 0 && row < cache.count())
+ return cache[row];
+ return QModelIndex();
+}
+
+QModelIndex
+BookmarkFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
+{
+ return index(cache.indexOf(sourceIndex), 0, QModelIndex());
+}
+
+QModelIndex
+BookmarkFilterModel::parent(const QModelIndex &child) const
+{
+ Q_UNUSED(child)
+ return QModelIndex();
+}
+
+QModelIndex
+BookmarkFilterModel::index(int row, int column, const QModelIndex &index) const
+{
+ Q_UNUSED(index)
+ if (row < 0 || column < 0 || cache.count() <= row
+ || !sourceModel || sourceModel->columnCount() <= column) {
+ return QModelIndex();
+ }
+ return createIndex(row, 0);
+}
+
+Qt::DropActions
+BookmarkFilterModel::supportedDropActions () const
+{
+ if (sourceModel)
+ return sourceModel->supportedDropActions();
+ return Qt::IgnoreAction;
+}
+
+Qt::ItemFlags
+BookmarkFilterModel::flags(const QModelIndex &index) const
+{
+ if (sourceModel)
+ return sourceModel->flags(index);
+ return Qt::NoItemFlags;
+}
+
+QVariant
+BookmarkFilterModel::data(const QModelIndex &index, int role) const
+{
+ if (sourceModel)
+ return sourceModel->data(mapToSource(index), role);
+ return QVariant();
+}
+
+bool
+BookmarkFilterModel::setData(const QModelIndex &index, const QVariant &value,
+ int role)
+{
+ if (sourceModel)
+ return sourceModel->setData(mapToSource(index), value, role);
+ return false;
+}
+
+void
+BookmarkFilterModel::filterBookmarks()
+{
+ if (sourceModel) {
+ beginResetModel();
+ hideBookmarks = true;
+ setupCache(sourceModel->index(0, 0, QModelIndex()));
+ endResetModel();
+ }
+}
+
+void
+BookmarkFilterModel::filterBookmarkFolders()
+{
+ if (sourceModel) {
+ beginResetModel();
+ hideBookmarks = false;
+ setupCache(sourceModel->index(0, 0, QModelIndex()));
+ endResetModel();
+ }
+}
+
+void
+BookmarkFilterModel::changed(const QModelIndex &topLeft,
+ const QModelIndex &bottomRight)
+{
+ emit dataChanged(mapFromSource(topLeft), mapFromSource(bottomRight));
+}
+
+void
+BookmarkFilterModel::rowsInserted(const QModelIndex &parent, int start, int end)
+{
+ if (!sourceModel)
+ return;
+
+ QModelIndex cachePrevious = parent;
+ if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) {
+ BookmarkItem *newItem = parentItem->child(start);
+
+ // iterate over tree hirarchie to find the previous folder
+ for (int i = 0; i < parentItem->childCount(); ++i) {
+ if (BookmarkItem *child = parentItem->child(i)) {
+ const QModelIndex &tmp = sourceModel->indexFromItem(child);
+ if (tmp.data(UserRoleFolder).toBool() && child != newItem)
+ cachePrevious = tmp;
+ }
+ }
+
+ const QModelIndex &newIndex = sourceModel->indexFromItem(newItem);
+ const bool isFolder = newIndex.data(UserRoleFolder).toBool();
+ if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks)) {
+ beginInsertRows(mapFromSource(parent), start, end);
+ cache.insert(cache.indexOf(cachePrevious) + 1, newIndex);
+ endInsertRows();
+ }
+ }
+}
+
+void
+BookmarkFilterModel::rowsAboutToBeRemoved(const QModelIndex &parent, int start,
+ int end)
+{
+ if (!sourceModel)
+ return;
+
+ if (BookmarkItem *parentItem = sourceModel->itemFromIndex(parent)) {
+ if (BookmarkItem *child = parentItem->child(start)) {
+ indexToRemove = sourceModel->indexFromItem(child);
+ if (cache.contains(indexToRemove))
+ beginRemoveRows(mapFromSource(parent), start, end);
+ }
+ }
+}
+
+void
+BookmarkFilterModel::rowsRemoved(const QModelIndex &/*parent*/, int, int)
+{
+ if (cache.contains(indexToRemove)) {
+ cache.removeAll(indexToRemove);
+ endRemoveRows();
+ }
+}
+
+void
+BookmarkFilterModel::layoutAboutToBeChanged()
+{
+ // TODO: ???
+}
+
+void
+BookmarkFilterModel::layoutChanged()
+{
+ // TODO: ???
+}
+
+void
+BookmarkFilterModel::modelAboutToBeReset()
+{
+ beginResetModel();
+}
+
+void
+BookmarkFilterModel::modelReset()
+{
+ if (sourceModel)
+ setupCache(sourceModel->index(0, 0, QModelIndex()));
+ endResetModel();
+}
+
+void
+BookmarkFilterModel::setupCache(const QModelIndex &parent)
+{
+ cache.clear();
+ collectItems(parent);
+}
+
+void
+BookmarkFilterModel::collectItems(const QModelIndex &parent)
+{
+ if (parent.isValid()) {
+ bool isFolder = sourceModel->data(parent, UserRoleFolder).toBool();
+ if ((isFolder && hideBookmarks) || (!isFolder && !hideBookmarks))
+ cache.append(parent);
+
+ if (sourceModel->hasChildren(parent)) {
+ for (int i = 0; i < sourceModel->rowCount(parent); ++i)
+ collectItems(sourceModel->index(i, 0, parent));
+ }
+ }
+}
+
+// -- BookmarkTreeModel
+
+BookmarkTreeModel::BookmarkTreeModel(QObject *parent)
+ : QSortFilterProxyModel(parent)
+{
+}
+
+int
+BookmarkTreeModel::columnCount(const QModelIndex &parent) const
+{
+ return qMin(1, QSortFilterProxyModel::columnCount(parent));
+}
+
+bool
+BookmarkTreeModel::filterAcceptsRow(int row, const QModelIndex &parent) const
+{
+ Q_UNUSED(row)
+ BookmarkModel *model = qobject_cast (sourceModel());
+ if (model->rowCount(parent) > 0
+ && model->data(model->index(row, 0, parent), UserRoleFolder).toBool())
+ return true;
+ return false;
+}
\ No newline at end of file
diff --git a/tools/assistant/tools/assistant/bookmarkfiltermodel.h b/tools/assistant/tools/assistant/bookmarkfiltermodel.h
new file mode 100644
index 0000000..4ea7ab9
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkfiltermodel.h
@@ -0,0 +1,118 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 BOOKMARKFILTERMODEL_H
+#define BOOKMARKFILTERMODEL_H
+
+#include
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkItem;
+class BookmarkModel;
+
+typedef QList PersistentModelIndexCache;
+
+class BookmarkFilterModel : public QAbstractProxyModel
+{
+ Q_OBJECT
+public:
+ explicit BookmarkFilterModel(QObject *parent = 0);
+
+ void setSourceModel(QAbstractItemModel *sourceModel);
+
+ int rowCount(const QModelIndex &index) const;
+ int columnCount(const QModelIndex &index) const;
+
+ QModelIndex mapToSource(const QModelIndex &proxyIndex) const;
+ QModelIndex mapFromSource(const QModelIndex &sourceIndex) const;
+
+ QModelIndex parent(const QModelIndex &child) const;
+ QModelIndex index(int row, int column, const QModelIndex &parent) const;
+
+ Qt::DropActions supportedDropActions () const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+
+ void filterBookmarks();
+ void filterBookmarkFolders();
+
+private slots:
+ void changed(const QModelIndex &topLeft, const QModelIndex &bottomRight);
+ void rowsInserted(const QModelIndex &parent, int start, int end);
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end);
+ void rowsRemoved(const QModelIndex &parent, int start, int end);
+ void layoutAboutToBeChanged();
+ void layoutChanged();
+ void modelAboutToBeReset();
+ void modelReset();
+
+private:
+ void setupCache(const QModelIndex &parent);
+ void collectItems(const QModelIndex &parent);
+
+private:
+ bool hideBookmarks;
+ BookmarkModel *sourceModel;
+ PersistentModelIndexCache cache;
+ QPersistentModelIndex indexToRemove;
+};
+
+// -- BookmarkTreeModel
+
+class BookmarkTreeModel : public QSortFilterProxyModel
+{
+ Q_OBJECT
+public:
+ BookmarkTreeModel(QObject *parent = 0);
+ int columnCount(const QModelIndex &parent = QModelIndex()) const;
+
+protected:
+ bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKFILTERMODEL_H
diff --git a/tools/assistant/tools/assistant/bookmarkitem.cpp b/tools/assistant/tools/assistant/bookmarkitem.cpp
new file mode 100644
index 0000000..082ffce
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkitem.cpp
@@ -0,0 +1,138 @@
+#include "bookmarkitem.h"
+
+#include
+
+QT_BEGIN_NAMESPACE
+
+BookmarkItem::BookmarkItem(const DataVector &data, BookmarkItem *parent)
+ : m_data(data)
+ , m_parent(parent)
+{
+}
+
+BookmarkItem::~BookmarkItem()
+{
+ qDeleteAll(m_children);
+}
+
+BookmarkItem*
+BookmarkItem::parent() const
+{
+ return m_parent;
+}
+
+void
+BookmarkItem::setParent(BookmarkItem *parent)
+{
+ m_parent = parent;
+}
+
+void
+BookmarkItem::addChild(BookmarkItem *child)
+{
+ child->setParent(this);
+ m_children.append(child);
+}
+
+BookmarkItem*
+BookmarkItem::child(int number) const
+{
+ if (number >= 0 && number < m_children.count())
+ return m_children[number];
+ return 0;
+}
+
+int BookmarkItem::childCount() const
+{
+ return m_children.count();
+}
+
+int BookmarkItem::childNumber() const
+{
+ if (m_parent)
+ return m_parent->m_children.indexOf(const_cast(this));
+ return 0;
+}
+
+QVariant
+BookmarkItem::data(int column) const
+{
+ if (column == 0)
+ return m_data[0];
+
+ if (column == 1 || column == UserRoleUrl)
+ return m_data[1];
+
+ if (column == UserRoleFolder)
+ return m_data[1].toString() == QLatin1String("Folder");
+
+ if (column == UserRoleExpanded)
+ return m_data[2];
+
+ return QVariant();
+}
+
+void
+BookmarkItem::setData(const DataVector &data)
+{
+ m_data = data;
+}
+
+bool
+BookmarkItem::setData(int column, const QVariant &newValue)
+{
+ int index = -1;
+ if (column == 0 || column == 1)
+ index = column;
+
+ if (column == UserRoleUrl || column == UserRoleFolder)
+ index = 1;
+
+ if (column == UserRoleExpanded)
+ index = 2;
+
+ if (index < 0)
+ return false;
+
+ m_data[index] = newValue;
+ return true;
+}
+
+bool
+BookmarkItem::insertChildren(bool isFolder, int position, int count)
+{
+ if (position < 0 || position > m_children.size())
+ return false;
+
+ for (int row = 0; row < count; ++row) {
+ m_children.insert(position, new BookmarkItem(DataVector()
+ << QObject::tr(isFolder ? "New Folder" : "Untitled")
+ << (isFolder ? "Folder" : "about:blank") << false, this));
+ }
+
+ return true;
+}
+
+bool
+BookmarkItem::removeChildren(int position, int count)
+{
+ if (position < 0 || position > m_children.size())
+ return false;
+
+ for (int row = 0; row < count; ++row)
+ delete m_children.takeAt(position);
+
+ return true;
+}
+
+void
+BookmarkItem::dumpTree(int indent) const
+{
+ const QString tree(indent, ' ');
+ qDebug() << tree + (data(UserRoleFolder).toBool() ? "Folder" : "Bookmark")
+ << "Label:" << data(0).toString() << "parent:" << m_parent << "this:"
+ << this;
+
+ foreach (BookmarkItem *item, m_children)
+ item->dumpTree(indent + 4);
+}
diff --git a/tools/assistant/tools/assistant/bookmarkitem.h b/tools/assistant/tools/assistant/bookmarkitem.h
new file mode 100644
index 0000000..be77e24
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkitem.h
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 BOOKMARKITEM_H
+#define BOOKMARKITEM_H
+
+#include
+#include
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ UserRoleUrl = Qt::UserRole + 50,
+ UserRoleFolder = Qt::UserRole + 100,
+ UserRoleExpanded = Qt::UserRole + 150
+};
+
+typedef QVector DataVector;
+
+class BookmarkItem
+{
+public:
+ BookmarkItem(const DataVector &data, BookmarkItem *parent = 0);
+ ~BookmarkItem();
+
+ BookmarkItem *parent() const;
+ void setParent(BookmarkItem *parent);
+
+ void addChild(BookmarkItem *child);
+ BookmarkItem *child(int number) const;
+
+ int childCount() const;
+ int childNumber() const;
+
+ QVariant data(int column) const;
+ void setData(const DataVector &data);
+ bool setData(int column, const QVariant &value);
+
+ bool insertChildren(bool isFolder, int position, int count);
+ bool removeChildren(int position, int count);
+
+ void dumpTree(int indent) const;
+
+private:
+ DataVector m_data;
+
+ BookmarkItem *m_parent;
+ QList m_children;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKITEM_H
diff --git a/tools/assistant/tools/assistant/bookmarkmanager.cpp b/tools/assistant/tools/assistant/bookmarkmanager.cpp
index b7bd449..8fba811 100644
--- a/tools/assistant/tools/assistant/bookmarkmanager.cpp
+++ b/tools/assistant/tools/assistant/bookmarkmanager.cpp
@@ -41,575 +41,207 @@
#include "tracer.h"
#include "bookmarkmanager.h"
+#include "bookmarkdialog.h"
+#include "bookmarkfiltermodel.h"
+#include "bookmarkitem.h"
+#include "bookmarkmodel.h"
#include "centralwidget.h"
#include "helpenginewrapper.h"
+#include
#include
-#include
-#include
-#include
-#include
-#include
-#include
#include
-#include
#include
-#include
-#include
-#include
-#include
-#include
#include
-QT_BEGIN_NAMESPACE
-
-BookmarkDialog::BookmarkDialog(BookmarkManager *manager, const QString &title,
- const QString &url, QWidget *parent)
- : QDialog(parent)
- , m_url(url)
- , m_title(title)
- , bookmarkManager(manager)
-{
- TRACE_OBJ
- ui.setupUi(this);
-
- installEventFilter(this);
- ui.treeView->installEventFilter(this);
- ui.treeView->viewport()->installEventFilter(this);
-
- ui.bookmarkEdit->setText(title);
- ui.newFolderButton->setVisible(false);
- ui.buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
- ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
-
- proxyModel = new QSortFilterProxyModel(this);
- proxyModel->setFilterKeyColumn(0);
- proxyModel->setDynamicSortFilter(true);
- proxyModel->setFilterRole(Qt::UserRole + 10);
- proxyModel->setSourceModel(bookmarkManager->treeBookmarkModel());
- proxyModel->setFilterRegExp(QRegExp(QLatin1String("Folder"),
- Qt::CaseSensitive, QRegExp::FixedString));
- ui.treeView->setModel(proxyModel);
-
- ui.treeView->expandAll();
- ui.treeView->setVisible(false);
- ui.treeView->header()->setVisible(false);
- ui.treeView->setContextMenuPolicy(Qt::CustomContextMenu);
-
- connect(ui.buttonBox, SIGNAL(rejected()), this, SLOT(reject()));
- connect(ui.buttonBox, SIGNAL(accepted()), this, SLOT(addAccepted()));
- connect(ui.newFolderButton, SIGNAL(clicked()), this, SLOT(addNewFolder()));
- connect(ui.toolButton, SIGNAL(clicked()), this, SLOT(toolButtonClicked()));
- connect(ui.bookmarkEdit, SIGNAL(textChanged(QString)), this,
- SLOT(textChanged(QString)));
-
- connect(bookmarkManager->treeBookmarkModel(),
- SIGNAL(itemChanged(QStandardItem*)),
- this, SLOT(itemChanged(QStandardItem*)));
-
- connect(ui.bookmarkFolders, SIGNAL(currentIndexChanged(QString)), this,
- SLOT(selectBookmarkFolder(QString)));
+#include
+#include "xbelsupport.h"
- connect(ui.treeView, SIGNAL(customContextMenuRequested(QPoint)), this,
- SLOT(customContextMenuRequested(QPoint)));
+QT_BEGIN_NAMESPACE
- connect(ui.treeView->selectionModel(), SIGNAL(currentChanged(QModelIndex,
- QModelIndex)), this, SLOT(currentChanged(QModelIndex)));
-}
+// -- BookmarkManager::BookmarkWidget
-BookmarkDialog::~BookmarkDialog()
+void BookmarkManager::BookmarkWidget::focusInEvent(QFocusEvent *event)
{
TRACE_OBJ
-}
+ if (event->reason() != Qt::MouseFocusReason) {
+ ui.lineEdit->selectAll();
+ ui.lineEdit->setFocus();
-void BookmarkDialog::addAccepted()
-{
- TRACE_OBJ
- QItemSelectionModel *model = ui.treeView->selectionModel();
- const QModelIndexList &list = model->selection().indexes();
-
- QModelIndex index;
- if (!list.isEmpty())
- index = proxyModel->mapToSource(list.at(0));
-
- bookmarkManager->addNewBookmark(index, ui.bookmarkEdit->text(), m_url);
- accept();
-}
-
-void BookmarkDialog::addNewFolder()
-{
- TRACE_OBJ
- QItemSelectionModel *model = ui.treeView->selectionModel();
- const QModelIndexList &list = model->selection().indexes();
-
- QModelIndex index;
- if (!list.isEmpty())
- index = list.at(0);
-
- QModelIndex newFolder =
- bookmarkManager->addNewFolder(proxyModel->mapToSource(index));
- if (newFolder.isValid()) {
- ui.treeView->expand(index);
- const QModelIndex &index = proxyModel->mapFromSource(newFolder);
- model->setCurrentIndex(index, QItemSelectionModel::ClearAndSelect);
-
- ui.bookmarkFolders->clear();
- ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
-
- const QString &name = index.data().toString();
- ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
- renameFolder(index, newFolder);
+ // force the focus in event on bookmark manager
+ emit focusInEvent();
}
}
-void BookmarkDialog::toolButtonClicked()
-{
- TRACE_OBJ
- bool visible = !ui.treeView->isVisible();
- ui.treeView->setVisible(visible);
- ui.newFolderButton->setVisible(visible);
-
- if (visible) {
- resize(QSize(width(), 400));
- ui.toolButton->setText(QLatin1String("-"));
- } else {
- resize(width(), minimumHeight());
- ui.toolButton->setText(QLatin1String("+"));
- }
-}
+// -- BookmarkManager::BookmarkTreeView
-void BookmarkDialog::itemChanged(QStandardItem *item)
+BookmarkManager::BookmarkTreeView::BookmarkTreeView(QWidget *parent)
+ : QTreeView(parent)
{
TRACE_OBJ
- if (renameItem != item) {
- renameItem = item;
- oldText = item->text();
- return;
- }
+ setAcceptDrops(true);
+ setDragEnabled(true);
+ setAutoExpandDelay(1000);
+ setUniformRowHeights(true);
+ setDropIndicatorShown(true);
+ setExpandsOnDoubleClick(true);
- if (item->text() != oldText) {
- ui.bookmarkFolders->clear();
- ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
+ connect(this, SIGNAL(expanded(QModelIndex)), this,
+ SLOT(setExpandedData(QModelIndex)));
+ connect(this, SIGNAL(collapsed(QModelIndex)), this,
+ SLOT(setExpandedData(QModelIndex)));
- QString name = tr("Bookmarks");
- const QModelIndex &index = ui.treeView->currentIndex();
- if (index.isValid())
- name = index.data().toString();
- ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
- }
}
-void BookmarkDialog::textChanged(const QString &string)
+void BookmarkManager::BookmarkTreeView::subclassKeyPressEvent(QKeyEvent *event)
{
TRACE_OBJ
- ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!string.isEmpty());
+ QTreeView::keyPressEvent(event);
}
-void BookmarkDialog::selectBookmarkFolder(const QString &folderName)
+void BookmarkManager::BookmarkTreeView::setExpandedData(const QModelIndex &index)
{
TRACE_OBJ
- if (folderName.isEmpty())
- return;
-
- if (folderName == tr("Bookmarks")) {
- ui.treeView->clearSelection();
- return;
- }
-
- QStandardItemModel *model = bookmarkManager->treeBookmarkModel();
- QList list = model->findItems(folderName,
- Qt::MatchCaseSensitive | Qt::MatchRecursive, 0);
- if (!list.isEmpty()) {
- const QModelIndex &index = model->indexFromItem(list.at(0));
- QItemSelectionModel *model = ui.treeView->selectionModel();
- if (model) {
- model->setCurrentIndex(proxyModel->mapFromSource(index),
- QItemSelectionModel::ClearAndSelect);
- }
- }
+ if (BookmarkModel *treeModel = qobject_cast (model()))
+ treeModel->setData(index, isExpanded(index), UserRoleExpanded);
}
-void BookmarkDialog::customContextMenuRequested(const QPoint &point)
-{
- TRACE_OBJ
- QModelIndex index = ui.treeView->indexAt(point);
- if (!index.isValid())
- return;
-
- QMenu menu(QLatin1String(""), this);
+// -- BookmarkManager
- QAction *removeItem = menu.addAction(tr("Delete Folder"));
- QAction *renameItem = menu.addAction(tr("Rename Folder"));
+QMutex BookmarkManager::mutex;
+BookmarkManager* BookmarkManager::bookmarkManager = 0;
- QAction *picked = menu.exec(ui.treeView->mapToGlobal(point));
- if (!picked)
- return;
-
- const QModelIndex &proxyIndex = proxyModel->mapToSource(index);
- if (picked == removeItem) {
- bookmarkManager->removeBookmarkItem(ui.treeView, proxyIndex);
- ui.bookmarkFolders->clear();
- ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
-
- QString name = tr("Bookmarks");
- index = ui.treeView->currentIndex();
- if (index.isValid())
- name = index.data().toString();
- ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
- } else if (picked == renameItem) {
- renameFolder(index, proxyIndex);
- }
-}
+// -- public
-void BookmarkDialog::renameFolder(const QModelIndex &index,
- const QModelIndex &proxyIndex)
+BookmarkManager* BookmarkManager::instance()
{
TRACE_OBJ
- const BookmarkModel * const model = bookmarkManager->treeBookmarkModel();
- if (QStandardItem *item = model->itemFromIndex(proxyIndex)) {
- item->setEditable(true);
- ui.treeView->edit(index);
- item->setEditable(false);
+ if (!bookmarkManager) {
+ QMutexLocker _(&mutex);
+ if (!bookmarkManager)
+ bookmarkManager = new BookmarkManager();
}
+ return bookmarkManager;
}
-void BookmarkDialog::currentChanged(const QModelIndex ¤t)
+void BookmarkManager::destroy()
{
TRACE_OBJ
- QString text = tr("Bookmarks");
- if (current.isValid())
- text = current.data().toString();
- ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(text));
+ delete bookmarkManager;
+ bookmarkManager = 0;
}
-bool BookmarkDialog::eventFilter(QObject *object, QEvent *e)
+QWidget* BookmarkManager::bookmarkDockWidget() const
{
TRACE_OBJ
- if (object != ui.treeView && object != ui.treeView->viewport())
- return QWidget::eventFilter(object, e);
-
- if (e->type() == QEvent::KeyPress) {
- QKeyEvent *ke = static_cast(e);
- switch (ke->key()) {
- case Qt::Key_F2: {
- const QModelIndex &index = ui.treeView->currentIndex();
- const QModelIndex &source = proxyModel->mapToSource(index);
- QStandardItem *item =
- bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
- if (item) {
- item->setEditable(true);
- ui.treeView->edit(index);
- item->setEditable(false);
- }
- } break;
-
- case Qt::Key_Delete: {
- const QModelIndex &index = ui.treeView->currentIndex();
- bookmarkManager->removeBookmarkItem(ui.treeView,
- proxyModel->mapToSource(index));
- ui.bookmarkFolders->clear();
- ui.bookmarkFolders->addItems(bookmarkManager->bookmarkFolders());
-
- QString name = tr("Bookmarks");
- if (index.isValid())
- name = index.data().toString();
- ui.bookmarkFolders->setCurrentIndex(ui.bookmarkFolders->findText(name));
- } break;
-
- default:
- break;
- }
- }
-
- return QObject::eventFilter(object, e);
+ if (bookmarkWidget)
+ return bookmarkWidget;
+ return 0;
}
-
-// BookmarkWidget
-
-
-BookmarkWidget::BookmarkWidget(BookmarkManager *manager, QWidget *parent,
- bool showButtons)
- : QWidget(parent)
- , addButton(0)
- , removeButton(0)
- , bookmarkManager(manager)
+void BookmarkManager::takeBookmarksMenu(QMenu* menu)
{
TRACE_OBJ
- setup(showButtons);
-
- installEventFilter(this);
- treeView->installEventFilter(this);
- treeView->viewport()->installEventFilter(this);
+ bookmarkMenu = menu;
+ refeshBookmarkMenu();
}
-BookmarkWidget::~BookmarkWidget()
-{
- TRACE_OBJ
-}
+// -- public slots
-void BookmarkWidget::removeClicked()
+void BookmarkManager::addBookmark(const QString &title, const QString &url)
{
TRACE_OBJ
- const QModelIndex &index = treeView->currentIndex();
- if (searchField->text().isEmpty()) {
- bookmarkManager->removeBookmarkItem(treeView,
- filterBookmarkModel->mapToSource(index));
- }
+ showBookmarkDialog(title.isEmpty() ? tr("Untiled") : title,
+ url.isEmpty() ? QLatin1String("about:blank") : url);
}
-void BookmarkWidget::filterChanged()
-{
- TRACE_OBJ
- bool searchBookmarks = searchField->text().isEmpty();
- if (!searchBookmarks) {
- regExp.setPattern(searchField->text());
- filterBookmarkModel->setSourceModel(bookmarkManager->listBookmarkModel());
- } else {
- regExp.setPattern(QLatin1String(""));
- filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel());
- }
-
- if (addButton)
- addButton->setEnabled(searchBookmarks);
-
- if (removeButton)
- removeButton->setEnabled(searchBookmarks);
-
- filterBookmarkModel->setFilterRegExp(regExp);
+// -- private
- const QModelIndex &index = treeView->indexAt(QPoint(1, 1));
- if (index.isValid())
- treeView->setCurrentIndex(index);
-
- if (searchBookmarks)
- expandItems();
-}
+BookmarkManager::BookmarkManager()
+ : typeAndSearch(false)
+ , bookmarkMenu(0)
+ , bookmarkModel(new BookmarkModel)
+ , bookmarkWidget(new BookmarkWidget)
+ , bookmarkTreeView(new BookmarkTreeView)
+{
+ TRACE_OBJ
+ bookmarkWidget->installEventFilter(this);
+ connect(bookmarkWidget->ui.add, SIGNAL(clicked()), this,
+ SLOT(addBookmark()));
+ connect(bookmarkWidget->ui.remove, SIGNAL(clicked()), this,
+ SLOT(removeBookmark()));
+ connect(bookmarkWidget->ui.lineEdit, SIGNAL(textChanged(QString)), this,
+ SLOT(textChanged(QString)));
+ connect(bookmarkWidget, SIGNAL(focusInEvent()), this, SLOT(focusInEvent()));
-void BookmarkWidget::expand(const QModelIndex &index)
-{
- TRACE_OBJ
- const QModelIndex &source = filterBookmarkModel->mapToSource(index);
- QStandardItem *item =
- bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
- if (item)
- item->setData(treeView->isExpanded(index), Qt::UserRole + 11);
-}
+ bookmarkTreeView->setModel(bookmarkModel);
+ bookmarkTreeView->installEventFilter(this);
+ bookmarkTreeView->viewport()->installEventFilter(this);
+ bookmarkTreeView->setContextMenuPolicy(Qt::CustomContextMenu);
+ bookmarkWidget->ui.stackedWidget->addWidget(bookmarkTreeView);
-void BookmarkWidget::activated(const QModelIndex &index)
-{
- TRACE_OBJ
- if (!index.isValid())
- return;
+ connect(bookmarkTreeView, SIGNAL(activated(QModelIndex)), this,
+ SLOT(setSourceFromIndex(QModelIndex)));
+ connect(bookmarkTreeView, SIGNAL(customContextMenuRequested(QPoint)), this,
+ SLOT(customContextMenuRequested(QPoint)));
- QString data = index.data(Qt::UserRole + 10).toString();
- if (data != QLatin1String("Folder"))
- emit requestShowLink(data);
+ connect(&HelpEngineWrapper::instance(), SIGNAL(setupFinished()), this,
+ SLOT(setupFinished()));
+ connect(bookmarkModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)), this,
+ SLOT(refeshBookmarkMenu()));
}
-void BookmarkWidget::customContextMenuRequested(const QPoint &point)
+BookmarkManager::~BookmarkManager()
{
TRACE_OBJ
- QModelIndex index = treeView->indexAt(point);
- if (!index.isValid())
- return;
-
- QAction *showItem = 0;
- QAction *removeItem = 0;
- QAction *renameItem = 0;
- QAction *showItemNewTab = 0;
-
- QMenu menu(QLatin1String(""), this);
- QString data = index.data(Qt::UserRole + 10).toString();
- if (data == QLatin1String("Folder")) {
- removeItem = menu.addAction(tr("Delete Folder"));
- renameItem = menu.addAction(tr("Rename Folder"));
- } else {
- showItem = menu.addAction(tr("Show Bookmark"));
- showItemNewTab = menu.addAction(tr("Show Bookmark in New Tab"));
- if (searchField->text().isEmpty()) {
- menu.addSeparator();
- removeItem = menu.addAction(tr("Delete Bookmark"));
- renameItem = menu.addAction(tr("Rename Bookmark"));
- }
- }
-
- QAction *pickedAction = menu.exec(treeView->mapToGlobal(point));
- if (!pickedAction)
- return;
-
- if (pickedAction == showItem) {
- emit requestShowLink(data);
- }
- else if (pickedAction == showItemNewTab) {
- CentralWidget::instance()->setSourceInNewTab(data);
- }
- else if (pickedAction == removeItem) {
- bookmarkManager->removeBookmarkItem(treeView,
- filterBookmarkModel->mapToSource(index));
- }
- else if (pickedAction == renameItem) {
- const QModelIndex &source = filterBookmarkModel->mapToSource(index);
- QStandardItem *item =
- bookmarkManager->treeBookmarkModel()->itemFromIndex(source);
- if (item) {
- item->setEditable(true);
- treeView->edit(index);
- item->setEditable(false);
- }
- }
+ HelpEngineWrapper::instance().setBookmarks(bookmarkModel->bookmarks());
}
-void BookmarkWidget::setup(bool showButtons)
+void BookmarkManager::removeItem(const QModelIndex &index)
{
TRACE_OBJ
- regExp.setPatternSyntax(QRegExp::FixedString);
- regExp.setCaseSensitivity(Qt::CaseInsensitive);
-
- QLayout *vlayout = new QVBoxLayout(this);
- vlayout->setMargin(4);
-
- QLabel *label = new QLabel(tr("Filter:"), this);
- vlayout->addWidget(label);
-
- searchField = new QLineEdit(this);
- vlayout->addWidget(searchField);
- connect(searchField, SIGNAL(textChanged(QString)), this,
- SLOT(filterChanged()));
-
- treeView = new TreeView(this);
- vlayout->addWidget(treeView);
-
-#ifdef Q_OS_MAC
-# define SYSTEM "mac"
-#else
-# define SYSTEM "win"
-#endif
-
- if (showButtons) {
- QLayout *hlayout = new QHBoxLayout();
- vlayout->addItem(hlayout);
-
- hlayout->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding));
-
- addButton = new QToolButton(this);
- addButton->setText(tr("Add"));
- addButton->setIcon(QIcon(QLatin1String(":/trolltech/assistant/images/"
- SYSTEM "/addtab.png")));
- addButton->setAutoRaise(true);
- addButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- hlayout->addWidget(addButton);
- connect(addButton, SIGNAL(clicked()), this, SIGNAL(addBookmark()));
-
- removeButton = new QToolButton(this);
- removeButton->setText(tr("Remove"));
- removeButton->setIcon(QIcon(QLatin1String(":/trolltech/assistant/images/"
- SYSTEM "/closetab.png")));
- removeButton->setAutoRaise(true);
- removeButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
- hlayout->addWidget(removeButton);
- connect(removeButton, SIGNAL(clicked()), this, SLOT(removeClicked()));
+ QModelIndex current = index;
+ if (typeAndSearch) { // need to map because of proxy
+ current = typeAndSearchModel->mapToSource(current);
+ current = bookmarkFilterModel->mapToSource(current);
+ } else if (!bookmarkModel->parent(index).isValid()) {
+ return; // check if we should delete the "Bookmarks Menu", bail
}
- filterBookmarkModel = new QSortFilterProxyModel(this);
- treeView->setModel(filterBookmarkModel);
-
- treeView->setDragEnabled(true);
- treeView->setAcceptDrops(true);
- treeView->setAutoExpandDelay(1000);
- treeView->setDropIndicatorShown(true);
- treeView->header()->setVisible(false);
- treeView->setContextMenuPolicy(Qt::CustomContextMenu);
-
- connect(treeView, SIGNAL(expanded(QModelIndex)), this,
- SLOT(expand(QModelIndex)));
- connect(treeView, SIGNAL(collapsed(QModelIndex)), this,
- SLOT(expand(QModelIndex)));
- connect(treeView, SIGNAL(activated(QModelIndex)), this,
- SLOT(activated(QModelIndex)));
- connect(treeView, SIGNAL(customContextMenuRequested(QPoint)),
- this, SLOT(customContextMenuRequested(QPoint)));
-
- filterBookmarkModel->setFilterKeyColumn(0);
- filterBookmarkModel->setDynamicSortFilter(true);
- filterBookmarkModel->setSourceModel(bookmarkManager->treeBookmarkModel());
-
- expandItems();
-}
-
-void BookmarkWidget::expandItems()
-{
- TRACE_OBJ
- QStandardItemModel *model = bookmarkManager->treeBookmarkModel();
- QListlist = model->findItems(QLatin1String("*"),
- Qt::MatchWildcard | Qt::MatchRecursive, 0);
- foreach (const QStandardItem *item, list) {
- const QModelIndex &index = model->indexFromItem(item);
- treeView->setExpanded(filterBookmarkModel->mapFromSource(index),
- item->data(Qt::UserRole + 11).toBool());
+ if (bookmarkModel->hasChildren(current)) {
+ int value = QMessageBox::question(bookmarkTreeView, tr("Remove"),
+ tr("You are going to delete a Folder, this will also "
+ "remove it's content. Are you sure to continue?"),
+ QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
+ if (value == QMessageBox::Cancel)
+ return;
}
+ bookmarkModel->removeItem(current);
}
-void BookmarkWidget::focusInEvent(QFocusEvent *e)
+bool BookmarkManager::eventFilter(QObject *object, QEvent *event)
{
- TRACE_OBJ
- if (e->reason() != Qt::MouseFocusReason) {
- searchField->selectAll();
- searchField->setFocus();
-
- QModelIndex index = treeView->indexAt(QPoint(1, 1));
- if (index.isValid())
- treeView->setCurrentIndex(index);
-
- }
-}
+ if (object != bookmarkTreeView && object != bookmarkTreeView->viewport()
+ && object != bookmarkWidget)
+ return QObject::eventFilter(object, event);
-bool BookmarkWidget::eventFilter(QObject *object, QEvent *e)
-{
TRACE_OBJ
- if (object != this && object != treeView
- && object != treeView->viewport()) {
- return QWidget::eventFilter(object, e);
- }
-
- if (e->type() == QEvent::KeyPress) {
- QKeyEvent *ke = static_cast(e);
- const bool tree = object == treeView || object == treeView->viewport();
+ const bool isWidget = object == bookmarkWidget;
+ if (event->type() == QEvent::KeyPress) {
+ QKeyEvent *ke = static_cast(event);
switch (ke->key()) {
case Qt::Key_F2: {
- const QModelIndex &index = treeView->currentIndex();
- const QModelIndex &src = filterBookmarkModel->mapToSource(index);
- if (tree && searchField->text().isEmpty()) {
- if (QStandardItem *item = bookmarkManager->treeBookmarkModel()
- ->itemFromIndex(src)) {
- item->setEditable(true);
- treeView->edit(index);
- item->setEditable(false);
- }
- }
- } break;
-
- case Qt::Key_Enter: {
- case Qt::Key_Return:
- if (tree) {
- const QString &data = treeView->selectionModel()->currentIndex()
- .data(Qt::UserRole + 10).toString();
- if (!data.isEmpty() && data != QLatin1String("Folder"))
- emit requestShowLink(data);
- }
+ renameBookmark(bookmarkTreeView->currentIndex());
} break;
case Qt::Key_Delete: {
- const QModelIndex &index = treeView->currentIndex();
- const QModelIndex &src = filterBookmarkModel->mapToSource(index);
- if (tree && searchField->text().isEmpty())
- bookmarkManager->removeBookmarkItem(treeView, src);
+ removeItem(bookmarkTreeView->currentIndex());
} break;
- case Qt::Key_Up: {
+ case Qt::Key_Up: { // needs event filter on widget
case Qt::Key_Down:
- if (!tree)
- treeView->subclassKeyPressEvent(ke);
+ if (isWidget)
+ bookmarkTreeView->subclassKeyPressEvent(ke);
} break;
case Qt::Key_Escape: {
@@ -620,348 +252,255 @@ bool BookmarkWidget::eventFilter(QObject *object, QEvent *e)
}
}
- if (e->type() == QEvent::MouseButtonRelease) {
- QMouseEvent *me = static_cast(e);
- bool controlPressed = me->modifiers() & Qt::ControlModifier;
- if(((me->button() == Qt::LeftButton) && controlPressed)
- || (me->button() == Qt::MidButton)) {
- const QModelIndex &index = treeView->currentIndex();
- const QString &data = index.data(Qt::UserRole + 10).toString();
- if (!data.isEmpty() && data != QLatin1String("Folder"))
- CentralWidget::instance()->setSourceInNewTab(data);
+ if (event->type() == QEvent::MouseButtonRelease && !isWidget) {
+ QMouseEvent *me = static_cast(event);
+ switch (me->button()) {
+ case Qt::LeftButton: {
+ if (me->modifiers() & Qt::ControlModifier)
+ setSourceFromIndex(bookmarkTreeView->currentIndex(), true);
+ } break;
+
+ case Qt::MidButton: {
+ setSourceFromIndex(bookmarkTreeView->currentIndex(), true);
+ } break;
+
+ default: break;
}
}
- return QWidget::eventFilter(object, e);
+ return QObject::eventFilter(object, event);
}
-
-// BookmarkModel
-
-
-BookmarkModel::BookmarkModel(int rows, int columns, QObject *parent)
- : QStandardItemModel(rows, columns, parent)
+void BookmarkManager::buildBookmarksMenu(const QModelIndex &index, QMenu* menu)
{
TRACE_OBJ
-}
+ if (!index.isValid())
+ return;
-BookmarkModel::~BookmarkModel()
-{
- TRACE_OBJ
+ const QString &text = index.data().toString();
+ const QIcon &icon = qVariantValue(index.data(Qt::DecorationRole));
+ if (index.data(UserRoleFolder).toBool()) {
+ if (QMenu* subMenu = menu->addMenu(icon, text)) {
+ for (int i = 0; i < bookmarkModel->rowCount(index); ++i)
+ buildBookmarksMenu(bookmarkModel->index(i, 0, index), subMenu);
+ }
+ } else {
+ QAction *action = menu->addAction(icon, text);
+ action->setData(index.data(UserRoleUrl).toString());
+ }
}
-Qt::DropActions BookmarkModel::supportedDropActions() const
+void BookmarkManager::showBookmarkDialog(const QString &name, const QString &url)
{
TRACE_OBJ
- return Qt::MoveAction;
+ BookmarkDialog dialog(bookmarkModel, name, url, bookmarkTreeView);
+ dialog.exec();
}
-Qt::ItemFlags BookmarkModel::flags(const QModelIndex &index) const
+// -- private slots
+
+void BookmarkManager::setupFinished()
{
TRACE_OBJ
- Qt::ItemFlags defaultFlags = QStandardItemModel::flags(index);
- if ((!index.isValid()) // can only happen for the invisible root item
- || index.data(Qt::UserRole + 10).toString() == QLatin1String("Folder"))
- return (Qt::ItemIsDropEnabled | defaultFlags) &~ Qt::ItemIsDragEnabled;
-
- return (Qt::ItemIsDragEnabled | defaultFlags) &~ Qt::ItemIsDropEnabled;
-}
+ bookmarkModel->setBookmarks(HelpEngineWrapper::instance().bookmarks());
+ bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView);
+ refeshBookmarkMenu();
-// BookmarkManager
+ bookmarkTreeView->hideColumn(1);
+ bookmarkTreeView->header()->setVisible(false);
+ bookmarkTreeView->header()->setStretchLastSection(true);
+ bookmarkFilterModel = new BookmarkFilterModel(this);
+ bookmarkFilterModel->setSourceModel(bookmarkModel);
+ bookmarkFilterModel->filterBookmarkFolders();
-BookmarkManager::BookmarkManager()
- : treeModel(new BookmarkModel(0, 1, this))
- , listModel(new BookmarkModel(0, 1, this))
- , renameItem(0)
-{
- TRACE_OBJ
- folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon);
- bookmarkIcon = QIcon(QLatin1String(":/trolltech/assistant/images/bookmark.png"));
-
- connect(treeModel, SIGNAL(itemChanged(QStandardItem*)), this,
- SLOT(itemChanged(QStandardItem*)));
- connect(treeModel, SIGNAL(itemChanged(QStandardItem*)), this,
- SIGNAL(bookmarksChanged()));
- connect(treeModel, SIGNAL(rowsRemoved(QModelIndex,int,int)),
- this, SIGNAL(bookmarksChanged()));
+ typeAndSearchModel = new QSortFilterProxyModel(this);
+ typeAndSearchModel->setDynamicSortFilter(true);
+ typeAndSearchModel->setSourceModel(bookmarkFilterModel);
}
-BookmarkManager::~BookmarkManager()
+void BookmarkManager::addBookmark()
{
TRACE_OBJ
- treeModel->clear();
- listModel->clear();
+ if (CentralWidget *widget = CentralWidget::instance()) {
+ showBookmarkDialog(widget->currentTitle(),
+ widget->currentSource().toString());
+ }
}
-BookmarkModel* BookmarkManager::treeBookmarkModel()
+void BookmarkManager::removeBookmark()
{
TRACE_OBJ
- return treeModel;
+ removeItem(bookmarkTreeView->currentIndex());
}
-BookmarkModel* BookmarkManager::listBookmarkModel()
-{
- TRACE_OBJ
- return listModel;
-}
+//void BookmarkManager::manageBookmarks()
+//{
+// TRACE_OBJ
+//}
-void BookmarkManager::saveBookmarks()
+void BookmarkManager::refeshBookmarkMenu()
{
TRACE_OBJ
- QByteArray bookmarks;
- QDataStream stream(&bookmarks, QIODevice::WriteOnly);
+ if (!bookmarkMenu)
+ return;
- readBookmarksRecursive(treeModel->invisibleRootItem(), stream, 0);
- HelpEngineWrapper::instance().setBookmarks(bookmarks);
-}
+ bookmarkMenu->clear();
-QStringList BookmarkManager::bookmarkFolders() const
-{
- TRACE_OBJ
- QStringList folders(tr("Bookmarks"));
+ //bookmarkMenu->addAction(tr("Manage Bookmarks..."), this,
+ // SLOT(manageBookmarks()));
+ bookmarkMenu->addAction(tr("Import..."), this, SLOT(importBookmarks()));
+ bookmarkMenu->addAction(tr("Export..."), this, SLOT(exportBookmarks()));
+ bookmarkMenu->addAction(tr("Add Bookmark..."), this, SLOT(addBookmark()),
+ QKeySequence(tr("Ctrl+D")));
+ bookmarkMenu->addSeparator();
- QListlist = treeModel->findItems(QLatin1String("*"),
- Qt::MatchWildcard | Qt::MatchRecursive, 0);
+ const QModelIndex &root = bookmarkModel->index(0, 0, QModelIndex());
+ for (int i = 0; i < bookmarkModel->rowCount(root); ++i)
+ buildBookmarksMenu(bookmarkModel->index(i, 0, root), bookmarkMenu);
- QString data;
- foreach (const QStandardItem *item, list) {
- data = item->data(Qt::UserRole + 10).toString();
- if (data == QLatin1String("Folder"))
- folders << item->data(Qt::DisplayRole).toString();
- }
- return folders;
+ connect(bookmarkMenu, SIGNAL(triggered(QAction*)), this,
+ SLOT(setSourceFromAction(QAction*)));
}
-QModelIndex BookmarkManager::addNewFolder(const QModelIndex &index)
+void BookmarkManager::renameBookmark(const QModelIndex &index)
{
- TRACE_OBJ
- QStandardItem *item = new QStandardItem(uniqueFolderName());
- item->setEditable(false);
- item->setData(false, Qt::UserRole + 11);
- item->setData(QLatin1String("Folder"), Qt::UserRole + 10);
- item->setIcon(QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon));
-
- if (index.isValid()) {
- treeModel->itemFromIndex(index)->appendRow(item);
- } else {
- treeModel->appendRow(item);
- }
- return treeModel->indexFromItem(item);
+ // check if we should rename the "Bookmarks Menu", bail
+ if (!typeAndSearch && !bookmarkModel->parent(index).isValid())
+ return;
+
+ bookmarkModel->setItemsEditable(true);
+ bookmarkTreeView->edit(index);
+ bookmarkModel->setItemsEditable(false);
}
-void BookmarkManager::removeBookmarkItem(QTreeView *treeView,
- const QModelIndex &index)
+void BookmarkManager::importBookmarks()
{
TRACE_OBJ
- QStandardItem *item = treeModel->itemFromIndex(index);
- if (item) {
- QString data = index.data(Qt::UserRole + 10).toString();
- if (data == QLatin1String("Folder") && item->rowCount() > 0) {
- int value = QMessageBox::question(treeView, tr("Remove"),
- tr("You are going to delete a Folder, this will also "
- "remove it's content. Are you sure to continue?"),
- QMessageBox::Yes | QMessageBox::Cancel, QMessageBox::Cancel);
-
- if (value == QMessageBox::Cancel)
- return;
- }
+ const QString &fileName = QFileDialog::getOpenFileName(0, tr("Open File"),
+ QDir::currentPath(), tr("Files (*.xbel)"));
- if (data != QLatin1String("Folder")) {
- QListitemList = listModel->findItems(item->text());
- foreach (const QStandardItem *i, itemList) {
- if (i->data(Qt::UserRole + 10) == data) {
- listModel->removeRow(i->row());
- break;
- }
- }
- } else {
- removeBookmarkFolderItems(item);
- }
- treeModel->removeRow(item->row(), index.parent());
+ if (fileName.isEmpty())
+ return;
+
+ QFile file(fileName);
+ if (file.open(QIODevice::ReadOnly)) {
+ XbelReader reader(bookmarkModel);
+ reader.readFromFile(&file);
}
}
-void BookmarkManager::showBookmarkDialog(QWidget *parent, const QString &name,
- const QString &url)
+void BookmarkManager::exportBookmarks()
{
TRACE_OBJ
- BookmarkDialog dialog(this, name, url, parent);
- dialog.exec();
-}
+ QString fileName = QFileDialog::getSaveFileName(0, tr("Save File"),
+ QLatin1String("untitled.xbel"), tr("Files (*.xbel)"));
-void BookmarkManager::addNewBookmark(const QModelIndex &index,
- const QString &name, const QString &url)
-{
- TRACE_OBJ
- QStandardItem *item = new QStandardItem(name);
- item->setEditable(false);
- item->setIcon(bookmarkIcon);
- item->setData(false, Qt::UserRole + 11);
- item->setData(url, Qt::UserRole + 10);
+ const QLatin1String suffix(".xbel");
+ if (!fileName.endsWith(suffix))
+ fileName.append(suffix);
- if (index.isValid())
- treeModel->itemFromIndex(index)->appendRow(item);
- else
- treeModel->appendRow(item);
- listModel->appendRow(item->clone());
- emit bookmarksChanged();
+ QFile file(fileName);
+ if (file.open(QIODevice::WriteOnly)) {
+ XbelWriter writer(bookmarkModel);
+ writer.writeToFile(&file);
+ } else {
+ QMessageBox::information(bookmarkTreeView, tr("Qt Assistant"),
+ tr("Unable to save bookmarks."), tr("OK"));
+ }
}
-void BookmarkManager::fillBookmarkMenu(QMenu *menu)
+void BookmarkManager::setSourceFromAction(QAction *action)
{
TRACE_OBJ
- if (!menu || !treeModel)
- return;
+ const QVariant &data = action->data();
- map.clear();
- fillBookmarkMenu(menu, treeModel->invisibleRootItem());
+ if (data.canConvert())
+ emit setSource(data.toUrl());
}
-void BookmarkManager::fillBookmarkMenu(QMenu *menu, QStandardItem *root)
+void BookmarkManager::setSourceFromIndex(const QModelIndex &index, bool newTab)
{
TRACE_OBJ
- for (int i = 0; i < root->rowCount(); ++i) {
- QStandardItem *item = root->child(i);
- if (item && item->data(Qt::UserRole + 10)
- .toString() == QLatin1String("Folder")) {
- QMenu* newMenu = menu->addMenu(folderIcon, item->text());
- if (item->rowCount() > 0)
- fillBookmarkMenu(newMenu, item);
- } else {
- map.insert(menu->addAction(item->text()), item->index());
- }
- }
-}
+ QAbstractItemModel *base = bookmarkModel;
+ if (typeAndSearch)
+ base = typeAndSearchModel;
-QUrl BookmarkManager::urlForAction(QAction* action) const
-{
- TRACE_OBJ
- if (map.contains(action)) {
- const QModelIndex &index = map.value(action);
- if (QStandardItem* item = treeModel->itemFromIndex(index))
- return QUrl(item->data(Qt::UserRole + 10).toString());
+ if (base->data(index, UserRoleFolder).toBool())
+ return;
+
+ const QVariant &data = base->data(index, UserRoleUrl);
+ if (data.canConvert()) {
+ if (newTab)
+ emit setSourceInNewTab(data.toUrl());
+ else
+ emit setSource(data.toUrl());
}
- return QUrl();
}
-void BookmarkManager::itemChanged(QStandardItem *item)
+void BookmarkManager::customContextMenuRequested(const QPoint &point)
{
TRACE_OBJ
- if (renameItem != item) {
- renameItem = item;
- oldText = item->text();
+ QModelIndex index = bookmarkTreeView->indexAt(point);
+ if (!index.isValid())
return;
- }
- if (item->text() != oldText) {
- if (item->data(Qt::UserRole + 10).toString() != QLatin1String("Folder")) {
- QListitemList = listModel->findItems(oldText);
- if (itemList.count() > 0)
- itemList.at(0)->setText(item->text());
- }
- }
-}
+ // check if we should open the menu on "Bookmarks Menu", bail
+ if (!typeAndSearch && !bookmarkModel->parent(index).isValid())
+ return;
-void BookmarkManager::setupBookmarkModels()
-{
- TRACE_OBJ
- treeModel->clear();
- listModel->clear();
-
- qint32 depth;
- bool expanded;
- QString name, type;
- QList lastDepths;
- QList parents;
-
- QByteArray ba = HelpEngineWrapper::instance().bookmarks();
- QDataStream stream(ba);
- while (!stream.atEnd()) {
- stream >> depth >> name >> type >> expanded;
-
- QStandardItem *item = new QStandardItem(name);
- item->setEditable(false);
- item->setData(type, Qt::UserRole + 10);
- item->setData(expanded, Qt::UserRole + 11);
- if (depth == 0) {
- parents.clear(); lastDepths.clear();
- treeModel->appendRow(item);
- parents << item; lastDepths << depth;
- } else {
- if (depth <= lastDepths.last()) {
- while (depth <= lastDepths.last() && parents.count() > 0) {
- parents.pop_back(); lastDepths.pop_back();
- }
- }
- parents.last()->appendRow(item);
- if (type == QLatin1String("Folder")) {
- parents << item; lastDepths << depth;
- }
- }
+ QAction *remove = 0;
+ QAction *rename = 0;
+ QAction *showItem = 0;
+ QAction *showItemInNewTab = 0;
- if (type != QLatin1String("Folder")) {
- item->setIcon(bookmarkIcon);
- listModel->appendRow(item->clone());
- } else {
- item->setIcon(folderIcon);
- }
+ QMenu menu(QLatin1String(""));
+ if (!typeAndSearch && bookmarkModel->data(index, UserRoleFolder).toBool()) {
+ remove = menu.addAction(tr("Delete Folder"));
+ rename = menu.addAction(tr("Rename Folder"));
+ } else {
+ showItem = menu.addAction(tr("Show Bookmark"));
+ showItemInNewTab = menu.addAction(tr("Show Bookmark in New Tab"));
+ menu.addSeparator();
+ remove = menu.addAction(tr("Delete Bookmark"));
+ rename = menu.addAction(tr("Rename Bookmark"));
}
-}
-QString BookmarkManager::uniqueFolderName() const
-{
- TRACE_OBJ
- QString folderName = tr("New Folder");
- QList list = treeModel->findItems(folderName,
- Qt::MatchContains | Qt::MatchRecursive, 0);
- if (!list.isEmpty()) {
- QStringList names;
- foreach (const QStandardItem *item, list)
- names << item->text();
-
- for (int i = 1; i <= names.count(); ++i) {
- folderName = (tr("New Folder") + QLatin1String(" %1")).arg(i);
- if (!names.contains(folderName))
- break;
- }
- }
- return folderName;
+ QAction *pickedAction = menu.exec(bookmarkTreeView->mapToGlobal(point));
+ if (pickedAction == rename)
+ renameBookmark(index);
+ else if (pickedAction == remove)
+ removeItem(index);
+ else if (pickedAction == showItem || pickedAction == showItemInNewTab)
+ setSourceFromIndex(index, pickedAction == showItemInNewTab);
}
-void BookmarkManager::removeBookmarkFolderItems(QStandardItem *item)
+void BookmarkManager::focusInEvent()
{
TRACE_OBJ
- for (int j = 0; j < item->rowCount(); ++j) {
- QStandardItem *child = item->child(j);
- if (child->rowCount() > 0)
- removeBookmarkFolderItems(child);
-
- QString data = child->data(Qt::UserRole + 10).toString();
- QListitemList = listModel->findItems(child->text());
- foreach (const QStandardItem *i, itemList) {
- if (i->data(Qt::UserRole + 10) == data) {
- listModel->removeRow(i->row());
- break;
- }
- }
- }
+ const QModelIndex &index = bookmarkTreeView->indexAt(QPoint(2, 2));
+ if (index.isValid())
+ bookmarkTreeView->setCurrentIndex(index);
}
-void BookmarkManager::readBookmarksRecursive(const QStandardItem *item,
- QDataStream &stream, const qint32 depth) const
+void BookmarkManager::textChanged(const QString &text)
{
TRACE_OBJ
- for (int j = 0; j < item->rowCount(); ++j) {
- const QStandardItem *child = item->child(j);
- stream << depth;
- stream << child->data(Qt::DisplayRole).toString();
- stream << child->data(Qt::UserRole + 10).toString();
- stream << child->data(Qt::UserRole + 11).toBool();
-
- if (child->rowCount() > 0)
- readBookmarksRecursive(child, stream, (depth +1));
+ if (!bookmarkWidget->ui.lineEdit->text().isEmpty()) {
+ if (!typeAndSearch) {
+ typeAndSearch = true;
+ bookmarkTreeView->setItemsExpandable(false);
+ bookmarkTreeView->setRootIsDecorated(false);
+ bookmarkTreeView->setModel(typeAndSearchModel);
+ }
+ typeAndSearchModel->setFilterRegExp(QRegExp(text));
+ } else {
+ typeAndSearch = false;
+ bookmarkTreeView->setModel(bookmarkModel);
+ bookmarkTreeView->setItemsExpandable(true);
+ bookmarkTreeView->setRootIsDecorated(true);
+ bookmarkModel->expandFoldersIfNeeeded(bookmarkTreeView);
}
}
diff --git a/tools/assistant/tools/assistant/bookmarkmanager.h b/tools/assistant/tools/assistant/bookmarkmanager.h
index fbacc2c..88342d5 100644
--- a/tools/assistant/tools/assistant/bookmarkmanager.h
+++ b/tools/assistant/tools/assistant/bookmarkmanager.h
@@ -38,179 +38,118 @@
** $QT_END_LICENSE$
**
****************************************************************************/
-
#ifndef BOOKMARKMANAGER_H
#define BOOKMARKMANAGER_H
-#include "ui_bookmarkdialog.h"
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
+#include
#include
-#include
+
+#include "ui_bookmarkwidget.h"
QT_BEGIN_NAMESPACE
-class QEvent;
-class QLineEdit;
-class QTreeView;
-class QToolButton;
-class QStandardItem;
-class QHelpEngineCore;
-class QAbstractItemModel;
+class BookmarkModel;
+class BookmarkFilterModel;
+class QKeyEvent;
class QSortFilterProxyModel;
-class BookmarkManager;
-
-class BookmarkDialog : public QDialog
+class BookmarkManager : public QObject
{
Q_OBJECT
+ class BookmarkWidget;
+ class BookmarkTreeView;
+ class BookmarkListView;
+ Q_DISABLE_COPY(BookmarkManager);
public:
- BookmarkDialog(BookmarkManager *manager, const QString &title,
- const QString &url, QWidget *parent = 0);
- ~BookmarkDialog();
+ static BookmarkManager* instance();
+ static void destroy();
-private slots:
- void addAccepted();
- void addNewFolder();
- void toolButtonClicked();
- void itemChanged(QStandardItem *item);
- void textChanged(const QString& string);
- void selectBookmarkFolder(const QString &folderName);
- void customContextMenuRequested(const QPoint &point);
- void currentChanged(const QModelIndex& current);
+ QWidget* bookmarkDockWidget() const;
+ void takeBookmarksMenu(QMenu* menu);
-private:
- bool eventFilter(QObject *object, QEvent *e);
- void renameFolder(const QModelIndex &index, const QModelIndex &proxyIndex);
+public slots:
+ void addBookmark(const QString &title, const QString &url);
+
+signals:
+ void escapePressed();
+ void setSource(const QUrl &url);
+ void setSourceInNewTab(const QUrl &url);
private:
- QString m_url;
- QString m_title;
+ BookmarkManager();
+ ~BookmarkManager();
- QString oldText;
- QStandardItem *renameItem;
+ void removeItem(const QModelIndex &index);
+ bool eventFilter(QObject *object, QEvent *event);
+ void buildBookmarksMenu(const QModelIndex &index, QMenu *menu);
+ void showBookmarkDialog(const QString &name, const QString &url);
- Ui::BookmarkDialog ui;
- BookmarkManager *bookmarkManager;
- QSortFilterProxyModel *proxyModel;
-};
+private slots:
+ void setupFinished();
-class TreeView : public QTreeView {
- Q_OBJECT
-public:
- TreeView(QWidget* parent = 0) : QTreeView(parent) {}
- void subclassKeyPressEvent(QKeyEvent* event)
- {
- QTreeView::keyPressEvent(event);
- }
-};
+ void addBookmark();
+ void removeBookmark();
+// void manageBookmarks();
+ void refeshBookmarkMenu();
+ void renameBookmark(const QModelIndex &index);
-class BookmarkWidget : public QWidget
-{
- Q_OBJECT
+ void importBookmarks();
+ void exportBookmarks();
-public:
- BookmarkWidget(BookmarkManager *manager, QWidget *parent = 0,
- bool showButtons = true);
- ~BookmarkWidget();
+ void setSourceFromAction(QAction *action);
+ void setSourceFromIndex(const QModelIndex &index, bool newTab = false);
-signals:
- void addBookmark();
- void requestShowLink(const QUrl &url);
- void escapePressed();
-
-private slots:
- void removeClicked();
- void filterChanged();
- void expand(const QModelIndex& index);
- void activated(const QModelIndex &index);
+ void focusInEvent();
+ void textChanged(const QString &text);
void customContextMenuRequested(const QPoint &point);
private:
- void setup(bool showButtons);
- void expandItems();
- void focusInEvent(QFocusEvent *e);
- bool eventFilter(QObject *object, QEvent *event);
+ bool typeAndSearch;
-private:
- QRegExp regExp;
- TreeView *treeView;
- QLineEdit *searchField;
- QToolButton *addButton;
- QToolButton *removeButton;
- BookmarkManager *bookmarkManager;
- QSortFilterProxyModel* filterBookmarkModel;
-};
+ static QMutex mutex;
+ static BookmarkManager *bookmarkManager;
-class BookmarkModel : public QStandardItemModel
-{
- Q_OBJECT
+ QMenu *bookmarkMenu;
-public:
- BookmarkModel(int rows, int columns, QObject *parent = 0);
- ~BookmarkModel();
+ BookmarkModel *bookmarkModel;
+ BookmarkFilterModel *bookmarkFilterModel;
+ QSortFilterProxyModel *typeAndSearchModel;
- Qt::DropActions supportedDropActions() const;
- Qt::ItemFlags flags(const QModelIndex &index) const;
+ BookmarkWidget *bookmarkWidget;
+ BookmarkTreeView *bookmarkTreeView;
};
-class BookmarkManager : public QObject
+class BookmarkManager::BookmarkWidget : public QWidget
{
Q_OBJECT
-
public:
- BookmarkManager();
- ~BookmarkManager();
+ BookmarkWidget(QWidget *parent = 0)
+ : QWidget(parent) { ui.setupUi(this); }
+ virtual ~BookmarkWidget() {}
- BookmarkModel* treeBookmarkModel();
- BookmarkModel* listBookmarkModel();
-
- void saveBookmarks();
- QStringList bookmarkFolders() const;
- QModelIndex addNewFolder(const QModelIndex& index);
- void removeBookmarkItem(QTreeView *treeView, const QModelIndex& index);
- void showBookmarkDialog(QWidget* parent, const QString &name,
- const QString &url);
- void addNewBookmark(const QModelIndex& index, const QString &name,
- const QString &url);
- void setupBookmarkModels();
-
- void fillBookmarkMenu(QMenu *menu);
- QUrl urlForAction(QAction* action) const;
+ Ui::BookmarkWidget ui;
signals:
- void bookmarksChanged();
-
-private slots:
- void itemChanged(QStandardItem *item);
+ void focusInEvent();
private:
- QString uniqueFolderName() const;
- void removeBookmarkFolderItems(QStandardItem *item);
- void readBookmarksRecursive(const QStandardItem *item, QDataStream &stream,
- const qint32 depth) const;
- void fillBookmarkMenu(QMenu *menu, QStandardItem *root);
+ void focusInEvent(QFocusEvent *event);
+};
-private:
- QString oldText;
- QIcon folderIcon;
- QIcon bookmarkIcon;
-
- BookmarkModel *treeModel;
- BookmarkModel *listModel;
- QStandardItem *renameItem;
- QMap map;
+class BookmarkManager::BookmarkTreeView : public QTreeView
+{
+ Q_OBJECT
+public:
+ BookmarkTreeView(QWidget *parent = 0);
+ ~BookmarkTreeView() {}
+
+ void subclassKeyPressEvent(QKeyEvent *event);
+
+private slots:
+ void setExpandedData(const QModelIndex &index);
};
QT_END_NAMESPACE
-#endif
+#endif // BOOKMARKMANAGER_H
diff --git a/tools/assistant/tools/assistant/bookmarkmodel.cpp b/tools/assistant/tools/assistant/bookmarkmodel.cpp
new file mode 100644
index 0000000..f265ca4
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkmodel.cpp
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 "bookmarkmodel.h"
+#include "bookmarkitem.h"
+
+#include
+#include
+
+#include
+#include
+#include
+
+const QLatin1String MIMETYPE("application/bookmarks.assistant");
+
+BookmarkModel::BookmarkModel()
+ : QAbstractItemModel()
+ , m_folder(false)
+ , m_editable(false)
+ , rootItem(0)
+{
+}
+
+BookmarkModel::~BookmarkModel()
+{
+ delete rootItem;
+}
+
+QByteArray
+BookmarkModel::bookmarks() const
+{
+ QByteArray ba;
+ QDataStream stream(&ba, QIODevice::WriteOnly);
+
+ const QModelIndex &root = index(0,0, QModelIndex());
+ for (int i = 0; i < rowCount(root); ++i)
+ collectItems(index(i, 0, root), 0, &stream);
+
+ return ba;
+}
+
+void
+BookmarkModel::setBookmarks(const QByteArray &bookmarks)
+{
+ folderIcon = QApplication::style()->standardIcon(QStyle::SP_DirClosedIcon);
+ bookmarkIcon = QIcon(QLatin1String(":/trolltech/assistant/images/bookmark.png"));
+
+ rootItem = new BookmarkItem(DataVector() << tr("Name") << tr("Address")
+ << true);
+ BookmarkItem* item = new BookmarkItem(DataVector() << tr("Bookmarks Menu")
+ << QLatin1String("Folder") << true);
+ rootItem->addChild(item);
+
+ QStack parents;
+ parents.push(item);
+
+ qint32 depth;
+ bool expanded;
+ QString name, url;
+ QDataStream stream(bookmarks);
+ while (!stream.atEnd()) {
+ stream >> depth >> name >> url >> expanded;
+
+ while ((parents.count() - 1) != depth)
+ parents.pop();
+
+ item = new BookmarkItem(DataVector() << name << url << expanded);
+ if (url == QLatin1String("Folder")) {
+ parents.top()->addChild(item);
+ parents.push(item);
+ } else {
+ parents.top()->addChild(item);
+ }
+ }
+
+ cache.clear();
+ const QModelIndex &root = index(0,0, QModelIndex());
+
+ setupCache(root);
+ cache.insert(static_cast (root.internalPointer()), root);
+}
+
+void
+BookmarkModel::setItemsEditable(bool editable)
+{
+ m_editable = editable;
+}
+
+void
+BookmarkModel::expandFoldersIfNeeeded(QTreeView *treeView)
+{
+ foreach (const QModelIndex &index, cache)
+ treeView->setExpanded(index, index.data(UserRoleExpanded).toBool());
+}
+
+QModelIndex
+BookmarkModel::addItem(const QModelIndex &parent, bool isFolder)
+{
+ m_folder = isFolder;
+ QModelIndex next;
+ if (insertRow(rowCount(parent), parent))
+ next = index(rowCount(parent) - 1, 0, parent);
+ m_folder = false;
+
+ return next;
+}
+
+bool
+BookmarkModel::removeItem(const QModelIndex &index)
+{
+ if (!index.isValid())
+ return false;
+
+ QModelIndexList indexes;
+ if (index.rowCount() > 0)
+ indexes = collectItems(index);
+ indexes.append(index);
+
+ foreach (const QModelIndex &itemToRemove, indexes) {
+ if (!removeRow(itemToRemove.row(), itemToRemove.parent()))
+ return false;
+ cache.remove(itemFromIndex(itemToRemove));
+ }
+ return true;
+}
+
+int
+BookmarkModel::rowCount(const QModelIndex &index) const
+{
+ if (BookmarkItem *item = itemFromIndex(index))
+ return item->childCount();
+ return 0;
+}
+
+int
+BookmarkModel::columnCount(const QModelIndex &/*index*/) const
+{
+ return 2;
+}
+
+QModelIndex
+BookmarkModel::parent(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return QModelIndex();
+
+ if (BookmarkItem *childItem = itemFromIndex(index)) {
+ if (BookmarkItem *parent = childItem->parent()) {
+ if (parent != rootItem)
+ return createIndex(parent->childNumber(), 0, parent);
+ }
+ }
+ return QModelIndex();
+}
+
+QModelIndex
+BookmarkModel::index(int row, int column, const QModelIndex &index) const
+{
+ if (index.isValid() && (index.column() != 0 && index.column() != 1))
+ return QModelIndex();
+
+ if (BookmarkItem *parent = itemFromIndex(index)) {
+ if (BookmarkItem *childItem = parent->child(row))
+ return createIndex(row, column, childItem);
+ }
+ return QModelIndex();
+}
+
+Qt::DropActions
+BookmarkModel::supportedDropActions () const
+{
+ return /* Qt::CopyAction | */Qt::MoveAction;
+}
+
+Qt::ItemFlags
+BookmarkModel::flags(const QModelIndex &index) const
+{
+ if (!index.isValid())
+ return Qt::NoItemFlags;
+
+ Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+
+ if (m_editable)
+ defaultFlags |= Qt::ItemIsEditable;
+
+ if (BookmarkItem *item = itemFromIndex(index)) {
+ if (index.data(UserRoleFolder).toBool()) {
+ if (index.column() > 0)
+ defaultFlags &= ~Qt::ItemIsEditable;
+ return defaultFlags | Qt::ItemIsDropEnabled;
+ }
+ }
+ return defaultFlags | Qt::ItemIsDragEnabled;
+}
+
+QVariant
+BookmarkModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid()) {
+ if (BookmarkItem *item = itemFromIndex(index)) {
+ switch (role) {
+ case Qt::EditRole: {
+ case Qt::DisplayRole:
+ if (index.data(UserRoleFolder).toBool() && index.column() == 1)
+ return QLatin1String("");
+ return item->data(index.column());
+ } break;
+ case Qt::DecorationRole: {
+ if (index.column() == 0)
+ return index.data(UserRoleFolder).toBool()
+ ? folderIcon : bookmarkIcon;
+ } break;
+ default:;
+ return item->data(role);
+ }
+ }
+ }
+ return QVariant();
+}
+
+bool
+BookmarkModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ bool result = false;
+ if (role != Qt::EditRole && role != UserRoleExpanded)
+ return result;
+
+ if (BookmarkItem *item = itemFromIndex(index)) {
+ if (role == Qt::EditRole) {
+ const bool isFolder = index.data(UserRoleFolder).toBool();
+ if (!isFolder || (isFolder && index.column() == 0))
+ result = item->setData(index.column(), value);
+ } else if (role == UserRoleExpanded) {
+ result = item->setData(UserRoleExpanded, value);
+ }
+ }
+
+ if (result)
+ emit dataChanged(index, index);
+ return result;
+}
+
+QVariant
+BookmarkModel::headerData(int section, Qt::Orientation orientation,
+ int role) const
+{
+ if (rootItem && orientation == Qt::Horizontal && role == Qt::DisplayRole)
+ return rootItem->data(section);
+ return QVariant();
+}
+
+QModelIndex
+BookmarkModel::indexFromItem(BookmarkItem *item) const
+{
+ return cache.value(item, QModelIndex());
+}
+
+BookmarkItem*
+BookmarkModel::itemFromIndex(const QModelIndex &index) const
+{
+ if (index.isValid())
+ return static_cast(index.internalPointer());
+ return rootItem;
+}
+
+bool
+BookmarkModel::insertRows(int position, int rows, const QModelIndex &parent)
+{
+ if (!parent.data(UserRoleFolder).toBool())
+ return false;
+
+ bool success = false;
+ if (BookmarkItem *parentItem = itemFromIndex(parent)) {
+ beginInsertRows(parent, position, position + rows - 1);
+ success = parentItem->insertChildren(m_folder, position, rows);
+ if (success) {
+ const QModelIndex ¤t = index(position, 0, parent);
+ cache.insert(itemFromIndex(current), current);
+ }
+ endInsertRows();
+ }
+ return success;
+}
+
+bool
+BookmarkModel::removeRows(int position, int rows, const QModelIndex &index)
+{
+ bool success = false;
+ if (BookmarkItem *parent = itemFromIndex(index)) {
+ beginRemoveRows(index, position, position + rows - 1);
+ success = parent->removeChildren(position, rows);
+ endRemoveRows();
+ }
+ return success;
+}
+
+QStringList
+BookmarkModel::mimeTypes() const
+{
+ return QStringList() << MIMETYPE;
+}
+
+QMimeData*
+BookmarkModel::mimeData(const QModelIndexList &indexes) const
+{
+ if (indexes.isEmpty())
+ return 0;
+
+ QByteArray data;
+ QDataStream stream(&data, QIODevice::WriteOnly);
+
+ foreach (const QModelIndex &index, indexes) {
+ if (index.column() == 0)
+ collectItems(index, 0, &stream);
+ }
+
+ QMimeData *mimeData = new QMimeData();
+ mimeData->setData(MIMETYPE, data);
+ return mimeData;
+}
+
+bool
+BookmarkModel::dropMimeData(const QMimeData *data, Qt::DropAction action,
+ int row, int column, const QModelIndex &parent)
+{
+ if (action == Qt::IgnoreAction)
+ return true;
+
+ if (!data->hasFormat(MIMETYPE) || column > 0)
+ return false;
+
+ QByteArray ba = data->data(MIMETYPE);
+ QDataStream stream(&ba, QIODevice::ReadOnly);
+ while (stream.atEnd())
+ return false;
+
+ qint32 depth;
+ bool expanded;
+ QString name, url;
+ while (!stream.atEnd()) {
+ stream >> depth >> name >> url >> expanded;
+ if (insertRow(qMax(0, row), parent)) {
+ const QModelIndex ¤t = index(qMax(0, row), 0, parent);
+ if (current.isValid()) {
+ BookmarkItem* item = itemFromIndex(current);
+ item->setData(DataVector() << name << url << expanded);
+ }
+ }
+ }
+ return true;
+}
+
+void
+BookmarkModel::setupCache(const QModelIndex &parent)
+{
+ const QModelIndexList &list = collectItems(parent);
+ foreach (const QModelIndex &index, list)
+ cache.insert(itemFromIndex(index), index);
+}
+
+QModelIndexList
+BookmarkModel::collectItems(const QModelIndex &parent) const
+{
+ QModelIndexList list;
+ for (int i = rowCount(parent) - 1; i >= 0 ; --i) {
+ const QModelIndex &next = index(i, 0, parent);
+ if (data(next, UserRoleFolder).toBool())
+ list += collectItems(next);
+ list.append(next);
+ }
+ return list;
+}
+
+void
+BookmarkModel::collectItems(const QModelIndex &parent, qint32 depth,
+ QDataStream *stream) const
+{
+ if (parent.isValid()) {
+ *stream << depth;
+ *stream << parent.data().toString();
+ *stream << parent.data(UserRoleUrl).toString();
+ *stream << parent.data(UserRoleExpanded).toBool();
+
+ for (int i = 0; i < rowCount(parent); ++i) {
+ if (parent.data(UserRoleFolder).toBool())
+ collectItems(index(i, 0 , parent), depth + 1, stream);
+ }
+ }
+}
diff --git a/tools/assistant/tools/assistant/bookmarkmodel.h b/tools/assistant/tools/assistant/bookmarkmodel.h
new file mode 100644
index 0000000..6b2a0b8
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkmodel.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the Qt Assistant 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 BOOKMARKMODEL_H
+#define BOOKMARKMODEL_H
+
+#include
+
+#include
+
+QT_BEGIN_NAMESPACE
+
+class BookmarkItem;
+class QMimeData;
+class QTreeView;
+
+typedef QMap ItemModelIndexCache;
+
+class BookmarkModel : public QAbstractItemModel
+{
+ Q_OBJECT
+public:
+ BookmarkModel();
+ ~BookmarkModel();
+
+ QByteArray bookmarks() const;
+ void setBookmarks(const QByteArray &bookmarks);
+
+ void setItemsEditable(bool editable);
+ void expandFoldersIfNeeeded(QTreeView *treeView);
+
+ QModelIndex addItem(const QModelIndex &parent, bool isFolder = false);
+ bool removeItem(const QModelIndex &index);
+
+ int rowCount(const QModelIndex &index = QModelIndex()) const;
+ int columnCount(const QModelIndex &index = QModelIndex()) const;
+
+ QModelIndex parent(const QModelIndex &index) const;
+ QModelIndex index(int row, int column, const QModelIndex &index) const;
+
+ Qt::DropActions supportedDropActions () const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ QVariant data(const QModelIndex &index, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+ QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+
+ QModelIndex indexFromItem(BookmarkItem *item) const;
+ BookmarkItem *itemFromIndex(const QModelIndex &index) const;
+
+ bool insertRows(int position, int rows, const QModelIndex &parent);
+ bool removeRows(int position, int rows, const QModelIndex &parent);
+
+ QStringList mimeTypes() const;
+ QMimeData* mimeData(const QModelIndexList &indexes) const;
+ bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row,
+ int column, const QModelIndex &parent);
+
+private:
+ void setupCache(const QModelIndex &parent);
+ QModelIndexList collectItems(const QModelIndex &parent) const;
+ void collectItems(const QModelIndex &parent, qint32 depth,
+ QDataStream *stream) const;
+
+private:
+ int columns;
+ bool m_folder;
+ bool m_editable;
+ QIcon folderIcon;
+ QIcon bookmarkIcon;
+ QTreeView *treeView;
+ BookmarkItem *rootItem;
+ ItemModelIndexCache cache;
+};
+
+QT_END_NAMESPACE
+
+#endif // BOOKMARKMODEL_H
diff --git a/tools/assistant/tools/assistant/bookmarkwidget.ui b/tools/assistant/tools/assistant/bookmarkwidget.ui
new file mode 100644
index 0000000..3015740
--- /dev/null
+++ b/tools/assistant/tools/assistant/bookmarkwidget.ui
@@ -0,0 +1,82 @@
+
+
+ BookmarkWidget
+
+