summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--doc/src/deployment.qdoc5
-rw-r--r--doc/src/designer-manual.qdoc43
-rw-r--r--doc/src/sharedlibrary.qdoc186
-rw-r--r--src/corelib/global/qglobal.cpp20
-rw-r--r--src/gui/dialogs/qfileinfogatherer.cpp20
-rw-r--r--src/gui/dialogs/qfileinfogatherer_p.h1
-rw-r--r--src/gui/dialogs/qfilesystemmodel.cpp18
-rw-r--r--src/gui/dialogs/qfilesystemmodel_p.h4
-rw-r--r--src/gui/graphicsview/qgraphicswidget.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp2
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.h2
-rw-r--r--src/gui/image/qpixmap_x11.cpp6
-rw-r--r--src/gui/image/qpixmapdata_p.h1
-rw-r--r--src/gui/inputmethod/qximinputcontext_p.h1
-rw-r--r--src/gui/inputmethod/qximinputcontext_x11.cpp10
-rw-r--r--src/gui/itemviews/qsortfilterproxymodel.cpp7
-rw-r--r--src/gui/kernel/qapplication.cpp4
-rw-r--r--src/gui/kernel/qt_mac.cpp2
-rw-r--r--src/gui/painting/qblendfunctions.cpp2
-rw-r--r--src/gui/painting/qregion.cpp2
-rw-r--r--src/gui/widgets/qcocoamenu_mac.mm4
-rw-r--r--tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp64
-rw-r--r--tests/auto/qpainter/tst_qpainter.cpp74
-rw-r--r--tests/auto/qpixmap/tst_qpixmap.cpp16
-rw-r--r--tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp112
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp14
26 files changed, 572 insertions, 50 deletions
diff --git a/doc/src/deployment.qdoc b/doc/src/deployment.qdoc
index d2c7a9e..7e02f1a 100644
--- a/doc/src/deployment.qdoc
+++ b/doc/src/deployment.qdoc
@@ -89,8 +89,9 @@
of Qt, you get Qt as a shared library.
The disadvantage with the shared library approach is that you
- will get more files to deploy.
-
+ will get more files to deploy. For more information, see
+ \l{sharedlibrary.html}{Creating Shared Libraries}.
+
\section1 Deploying Qt's Libraries
\table
diff --git a/doc/src/designer-manual.qdoc b/doc/src/designer-manual.qdoc
index 083d782..0521063 100644
--- a/doc/src/designer-manual.qdoc
+++ b/doc/src/designer-manual.qdoc
@@ -2537,6 +2537,10 @@ pixmap property in the property editor.
\target BuildingandInstallingthePlugin
\section1 Building and Installing the Plugin
+ \section2 A Simple Plugin
+
+ The \l{Custom Widget Plugin Example} demonstrates a simple \QD plugin.
+
The \c{.pro} file for a plugin must specify the headers and sources for
both the custom widget and the plugin interface. Typically, this file only
has to specify that the plugin's project is to be built as a library, but
@@ -2571,6 +2575,45 @@ pixmap property in the property editor.
See QCoreApplication::libraryPaths() for more information about customizing
paths for libraries and plugins with Qt applications.
+ \section2 Splitting up the Plugin
+
+ In a real world scenario, you do not want to have dependencies of the
+ application making use of the custom widgets to the \QD headers and
+ libraries as introduced by the simple approach explained above.
+
+ There are two ways to resolve this:
+
+ \list
+ \i Create a \c{.pri} file that contains the headers sources and sources
+ of the custom widget:
+
+ \code
+ INCLUDEPATH += $$PWD
+ HEADERS += $$PWD/analogclock.h
+ SOURCES += $$PWD/analogclock.cpp
+ \endcode
+
+ This file would then be included by the \c{.pro} file of the plugin and
+ the application:
+
+ \code
+ include(customwidget.pri)
+ \endcode
+
+ Running \c{qmake -Wall} on the \c{.pro} files causes a warning to be
+ printed if an included \c{.pri} file cannot be found.
+
+ \i Create a standalone shared library containing the custom widgets only
+ as described in
+ \l{sharedlibrary.html}{Creating Shared Libraries}.
+
+ This library would then be used by the application as well as by the
+ \QD plugin. Care must be taken to ensure that the plugin can locate
+ the library at runtime.
+ \endlist
+
+
+
\omit
\section1 Using Qt Script to Aid in Building Forms
diff --git a/doc/src/sharedlibrary.qdoc b/doc/src/sharedlibrary.qdoc
new file mode 100644
index 0000000..3febb8f
--- /dev/null
+++ b/doc/src/sharedlibrary.qdoc
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the Qt GUI Toolkit.
+** EDITIONS: FREE, PROFESSIONAL, ENTERPRISE
+**
+****************************************************************************/
+
+/*!
+ \group deployment
+ \page sharedlibrary.html
+ \ingroup buildsystem
+
+ \title Creating Shared Libraries
+ The following sections list certain things that should be taken into
+ account when creating shared libraries.
+
+ \section1 Using Symbols from Shared Libraries
+
+ Symbols - functions, variables or classes - contained in shared libraries
+ intended to be used by \e{clients}, such as applications or other
+ libraries, must be marked in a special way. These symbols are called
+ \e{public symbols} that are \e{exported} or made publicly visible.
+
+ The remaining symbols should not be visible from the outside. On most
+ platforms, compilers will hide them by default. On some platforms, a
+ special compiler option is required to hide these symbols.
+
+ When compiling a shared library, it must be marked for \e{export}. To use
+ the shared library from a client, some platforms may require a special
+ \e{import} declaration as well.
+
+ Depending on your target platform, Qt provides special macros that contain
+ the necessary definitions:
+ \list
+ \o \c{Q_DECL_EXPORT} must be added to the declarations of symbols used
+ when compiling a shared library.
+ \o \c{Q_DECL_IMPORT} must be added to the declarations of symbols used
+ when compiling a client that uses the shared library.
+ \endlist
+
+ Now, we need to ensure that the right macro is invoked -- whether we
+ compile a share library itself, or just the client using the shared
+ library.
+ Typically, this can be solved by adding a special header.
+
+ Let us assume we want to create a shared library called \e{mysharedlib}.
+ A special header for this library, \c{mysharedlib_global.h}, looks like
+ this:
+
+ \code
+ #include <QtCore/QtGlobal>
+
+ #if defined(MYSHAREDLIB_LIBRARY)
+ # define MYSHAREDLIB_EXPORT Q_DECL_EXPORT
+ #else
+ # define MYSHAREDLIB_EXPORT Q_DECL_IMPORT
+ #endif
+ \endcode
+
+ In the \c{.pro} file of the shared library, we add:
+
+ \code
+ DEFINES += MYSHAREDLIB_LIBRARY
+ \endcode
+
+ In each header of the library, we specify the following:
+
+ \code
+ #include "mysharedlib_global.h"
+
+ MYSHAREDLIB_EXPORT void foo();
+ class MYSHAREDLIB_EXPORT MyClass...
+ \endcode
+ This ensures that the right macro is seen by both library and clients. We
+ also use this technique in Qt's sources.
+
+
+ \section1 Header File Considerations
+
+ Typically, clients will include only the public header files of shared
+ libraries. These libraries might be installed in a different location, when
+ deployed. Therefore, it is important to exclude other internal header files
+ that were used when building the shared library.
+
+ For example, the library might provide a class that wraps a hardware device
+ and contains a handle to that device, provided by some 3rd-party library:
+
+ \code
+ #include <footronics/device.h>
+
+ class MyDevice {
+ private:
+ FOOTRONICS_DEVICE_HANDLE handle;
+ };
+ \endcode
+
+ A similar situation arises with forms created by Qt Designer when using
+ aggregation or multiple inheritance:
+
+ \code
+ #include "ui_widget.h"
+
+ class MyWidget : public QWidget {
+ private:
+ Ui::MyWidget m_ui;
+ };
+ \endcode
+
+ When deploying the library, there should be no dependency to the internal
+ headers \c{footronics/device.h} or \c{ui_widget.h}.
+
+ This can be avoided by making use of the \e{Pointer to implementation}
+ idiom described in various C++ programming books. For classes with
+ \e{value semantics}, consider using QSharedDataPointer.
+
+
+ \section1 Binary compatibility
+
+ For clients loading a shared library, to work correctly, the memory
+ layout of the classes being used must match exactly the memory layout of
+ the library version that was used to compile the client. In other words,
+ the library found by the client at runtime must be \e{binary compatible}
+ with the version used at compile time.
+
+ This is usually not a problem if the client is a self-contained software
+ package that ships all the libraries it needs.
+
+ However, if the client application relies on a shared library that belongs
+ to a different installation package or to the operating system, then we
+ need to think of a versioning scheme for shared libraries and decide at
+ which level \e{Binary compatibility} is to be maintained. For example, Qt
+ libraries of the same \e{major version number} are guaranteed to be binary
+ compatible.
+
+ Maintaining \e{Binary compatibility} places some restrictions on the changes
+ you can make to the classes. A good explanation can be found at
+ \l{http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++}
+ {KDE - Policies/Binary Compatibility Issues With C++}. These issues should
+ be considered right from the start of library design.
+ We recommend that the principle of \e{Information hiding} and the
+ \e{Pointer to implementation} technique be used wherever possible.
+*/
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index 2767f6f..e3075c3 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2966,4 +2966,24 @@ bool QInternal::callFunction(InternalFunction func, void **args)
\snippet doc/src/snippets/code/src_gui_dialogs_qmessagebox.cpp 4
*/
+/*!
+ \macro Q_DECL_EXPORT
+ \relates <QtGlobal>
+
+ This macro marks a symbol for shared library export (see
+ \l{sharedlibrary.html}{Creating Shared Libraries}).
+
+ \sa Q_DECL_IMPORT
+*/
+
+/*!
+ \macro Q_DECL_IMPORT
+ \relates <QtGlobal>
+
+ This macro declares a symbol to be an import from a shared library (see
+ \l{sharedlibrary.html}{Creating Shared Libraries}).
+
+ \sa Q_DECL_EXPORT
+*/
+
QT_END_NAMESPACE
diff --git a/src/gui/dialogs/qfileinfogatherer.cpp b/src/gui/dialogs/qfileinfogatherer.cpp
index 3fe64ff..23a2cbc 100644
--- a/src/gui/dialogs/qfileinfogatherer.cpp
+++ b/src/gui/dialogs/qfileinfogatherer.cpp
@@ -168,6 +168,20 @@ void QFileInfoGatherer::clear()
}
/*
+ Remove a \a path from the watcher
+
+ \sa listed()
+*/
+void QFileInfoGatherer::removePath(const QString &path)
+{
+#ifndef QT_NO_FILESYSTEMWATCHER
+ mutex.lock();
+ watcher->removePath(path);
+ mutex.unlock();
+#endif
+}
+
+/*
List all files in \a directoryPath
\sa listed()
@@ -286,15 +300,9 @@ QString QFileInfoGatherer::translateDriveName(const QFileInfo &drive) const
void QFileInfoGatherer::getFileInfos(const QString &path, const QStringList &files)
{
#ifndef QT_NO_FILESYSTEMWATCHER
- //### We test here if the path still exist before adding it in the watcher
- //### because sometime the file is deleted just before enter here so QStringList files is not up to date
- //### It is not a proper fix, perhaps in 4.6 we should have a better way to avoid that
- //### to ensure the gatherer have fresh information
- QFileInfo info(path);
if (files.isEmpty()
&& !watcher->directories().contains(path)
&& !path.isEmpty()
- && info.exists()
&& !path.startsWith(QLatin1String("//")) /*don't watch UNC path*/) {
watcher->addPath(path);
}
diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h
index eac0d46..60b9d5f 100644
--- a/src/gui/dialogs/qfileinfogatherer_p.h
+++ b/src/gui/dialogs/qfileinfogatherer_p.h
@@ -161,6 +161,7 @@ public:
~QFileInfoGatherer();
void clear();
+ void removePath(const QString &path);
QExtendedInformation getInfo(const QFileInfo &info) const;
public Q_SLOTS:
diff --git a/src/gui/dialogs/qfilesystemmodel.cpp b/src/gui/dialogs/qfilesystemmodel.cpp
index 51d3314..c7b3137 100644
--- a/src/gui/dialogs/qfilesystemmodel.cpp
+++ b/src/gui/dialogs/qfilesystemmodel.cpp
@@ -166,6 +166,8 @@ bool QFileSystemModel::remove(const QModelIndex &aindex) const
{
//### TODO optim
QString path = filePath(aindex);
+ QFileSystemModelPrivate * d = const_cast<QFileSystemModelPrivate*>(d_func());
+ d->fileInfoGatherer.removePath(path);
QDirIterator it(path,
QDir::AllDirs | QDir:: Files | QDir::NoDotAndDotDot,
QDirIterator::Subdirectories);
@@ -375,7 +377,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
if (!info.exists())
return rootNode;
QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);
- p->addNode(rootNode, host);
+ p->addNode(rootNode, host,info);
p->addVisibleFiles(rootNode, QStringList(host));
}
r = rootNode->visibleLocation(host);
@@ -395,6 +397,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
#endif
QFileSystemModelPrivate::QFileSystemNode *parent = node(index);
+
for (int i = 0; i < pathElements.count(); ++i) {
QString element = pathElements.at(i);
#ifdef Q_OS_WIN
@@ -423,7 +426,7 @@ QFileSystemModelPrivate::QFileSystemNode *QFileSystemModelPrivate::node(const QS
if (!info.exists())
return const_cast<QFileSystemModelPrivate::QFileSystemNode*>(&root);
QFileSystemModelPrivate *p = const_cast<QFileSystemModelPrivate*>(this);
- node = p->addNode(parent, element);
+ node = p->addNode(parent, element,info);
#ifndef QT_NO_FILESYSTEMWATCHER
node->populate(fileInfoGatherer.getInfo(info));
#endif
@@ -843,7 +846,7 @@ bool QFileSystemModel::setData(const QModelIndex &idx, const QVariant &value, in
QFileSystemModelPrivate::QFileSystemNode *parentNode = indexNode->parent;
int visibleLocation = parentNode->visibleLocation(parentNode->children.value(indexNode->fileName)->fileName);
- d->addNode(parentNode, newName);
+ d->addNode(parentNode, newName,indexNode->info->fileInfo());
parentNode->visibleChildren.removeAt(visibleLocation);
QFileSystemModelPrivate::QFileSystemNode * oldValue = parentNode->children.value(oldName);
parentNode->children[newName] = oldValue;
@@ -1282,7 +1285,7 @@ QModelIndex QFileSystemModel::mkdir(const QModelIndex &parent, const QString &na
if (!dir.mkdir(name))
return QModelIndex();
QFileSystemModelPrivate::QFileSystemNode *parentNode = d->node(parent);
- d->addNode(parentNode, name);
+ d->addNode(parentNode, name, QFileInfo());
Q_ASSERT(parentNode->children.contains(name));
QFileSystemModelPrivate::QFileSystemNode *node = parentNode->children[name];
node->populate(d->fileInfoGatherer.getInfo(QFileInfo(dir.absolutePath() + QDir::separator() + name)));
@@ -1601,10 +1604,13 @@ void QFileSystemModelPrivate::_q_directoryChanged(const QString &directory, cons
*WARNING* this will change the count of children
*/
-QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFileSystemNode *parentNode, const QString &fileName)
+QFileSystemModelPrivate::QFileSystemNode* QFileSystemModelPrivate::addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo& info)
{
// In the common case, itemLocation == count() so check there first
QFileSystemModelPrivate::QFileSystemNode *node = new QFileSystemModelPrivate::QFileSystemNode(fileName, parentNode);
+#ifndef QT_NO_FILESYSTEMWATCHER
+ node->populate(info);
+#endif
parentNode->children.insert(fileName, node);
return node;
}
@@ -1722,7 +1728,7 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, const QL
QExtendedInformation info = fileInfoGatherer.getInfo(updates.at(i).second);
bool previouslyHere = parentNode->children.contains(fileName);
if (!previouslyHere) {
- addNode(parentNode, fileName);
+ addNode(parentNode, fileName, info.fileInfo());
}
QFileSystemModelPrivate::QFileSystemNode * node = parentNode->children.value(fileName);
bool isCaseSensitive = parentNode->caseSensitive();
diff --git a/src/gui/dialogs/qfilesystemmodel_p.h b/src/gui/dialogs/qfilesystemmodel_p.h
index f1e798b..77c35a2 100644
--- a/src/gui/dialogs/qfilesystemmodel_p.h
+++ b/src/gui/dialogs/qfilesystemmodel_p.h
@@ -182,7 +182,7 @@ public:
QList<QString> visibleChildren;
QFileSystemNode *parent;
- private:
+
QExtendedInformation *info;
};
@@ -216,7 +216,7 @@ public:
bool filtersAcceptsNode(const QFileSystemNode *node) const;
bool passNameFilters(const QFileSystemNode *node) const;
void removeNode(QFileSystemNode *parentNode, const QString &name);
- QFileSystemNode* addNode(QFileSystemNode *parentNode, const QString &fileName);
+ QFileSystemNode* addNode(QFileSystemNode *parentNode, const QString &fileName, const QFileInfo &info);
void addVisibleFiles(QFileSystemNode *parentNode, const QStringList &newFiles);
void removeVisibleFile(QFileSystemNode *parentNode, int visibleLocation);
void sortChildren(int column, const QModelIndex &parent);
diff --git a/src/gui/graphicsview/qgraphicswidget.cpp b/src/gui/graphicsview/qgraphicswidget.cpp
index 5cc18f9..64ec0e7 100644
--- a/src/gui/graphicsview/qgraphicswidget.cpp
+++ b/src/gui/graphicsview/qgraphicswidget.cpp
@@ -1269,6 +1269,8 @@ bool QGraphicsWidget::event(QEvent *event)
break;
case QEvent::Polish:
polishEvent();
+ d->polished = true;
+ d->updateFont(d->font);
break;
case QEvent::WindowActivate:
case QEvent::WindowDeactivate:
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 641409d..789f8da 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -274,6 +274,8 @@ void QGraphicsWidgetPrivate::updateFont(const QFont &font)
}
}
+ if (!polished)
+ return;
// Notify change.
QEvent event(QEvent::FontChange);
QApplication::sendEvent(q, &event);
diff --git a/src/gui/graphicsview/qgraphicswidget_p.h b/src/gui/graphicsview/qgraphicswidget_p.h
index afa6812..455a129 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.h
+++ b/src/gui/graphicsview/qgraphicswidget_p.h
@@ -85,6 +85,7 @@ public:
inheritedPaletteResolveMask(0),
inheritedFontResolveMask(0),
inSetGeometry(0),
+ polished(0),
focusPolicy(Qt::NoFocus),
focusNext(0),
focusPrev(0),
@@ -193,6 +194,7 @@ public:
}
quint32 attributes : 10;
quint32 inSetGeometry : 1;
+ quint32 polished: 1;
// Focus
Qt::FocusPolicy focusPolicy;
diff --git a/src/gui/image/qpixmap_x11.cpp b/src/gui/image/qpixmap_x11.cpp
index 9d99d2e..725caeb 100644
--- a/src/gui/image/qpixmap_x11.cpp
+++ b/src/gui/image/qpixmap_x11.cpp
@@ -1288,6 +1288,12 @@ void QX11PixmapData::setMask(const QBitmap &newmask)
0, 0, 0, 0, 0, 0, w, h);
release();
*this = newData;
+ // the new QX11PixmapData object isn't referenced yet, so
+ // ref it
+ ref.ref();
+
+ // the below is to make sure the QX11PixmapData destructor
+ // doesn't delete our newly created render picture
newData.hd = 0;
newData.x11_mask = 0;
newData.picture = 0;
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index df26c42..abb3181 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -110,6 +110,7 @@ protected:
private:
friend class QPixmap;
friend class QGLContextPrivate;
+ friend class QX11PixmapData;
QAtomicInt ref;
int detach_no;
diff --git a/src/gui/inputmethod/qximinputcontext_p.h b/src/gui/inputmethod/qximinputcontext_p.h
index ca2103b..3773122 100644
--- a/src/gui/inputmethod/qximinputcontext_p.h
+++ b/src/gui/inputmethod/qximinputcontext_p.h
@@ -98,6 +98,7 @@ public:
QString text;
QBitArray selectedChars;
bool composing;
+ bool preeditEmpty;
void clear();
};
diff --git a/src/gui/inputmethod/qximinputcontext_x11.cpp b/src/gui/inputmethod/qximinputcontext_x11.cpp
index 48a96b1..1c8560f 100644
--- a/src/gui/inputmethod/qximinputcontext_x11.cpp
+++ b/src/gui/inputmethod/qximinputcontext_x11.cpp
@@ -264,6 +264,7 @@ extern "C" {
qic->standardFormat(QInputContext::PreeditFormat));
attrs << QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursor, sellen ? 0 : 1, QVariant());
QInputMethodEvent e(data->text, attrs);
+ data->preeditEmpty = data->text.isEmpty();
qic->sendEvent(e);
return 0;
@@ -286,6 +287,7 @@ void QXIMInputContext::ICData::clear()
text = QString();
selectedChars.clear();
composing = false;
+ preeditEmpty = true;
}
QXIMInputContext::ICData *QXIMInputContext::icData() const
@@ -537,9 +539,12 @@ void QXIMInputContext::reset()
if (mb) {
e.setCommitString(QString::fromLocal8Bit(mb));
XFree(mb);
+ data->preeditEmpty = false; // force sending an event
+ }
+ if (!data->preeditEmpty) {
+ sendEvent(e);
+ update();
}
- sendEvent(e);
- update();
}
data->clear();
}
@@ -686,6 +691,7 @@ QXIMInputContext::ICData *QXIMInputContext::createICData(QWidget *w)
{
ICData *data = new ICData;
data->widget = w;
+ data->preeditEmpty = true;
XVaNestedList preedit_attr = 0;
XIMCallback startcallback, drawcallback, donecallback;
diff --git a/src/gui/itemviews/qsortfilterproxymodel.cpp b/src/gui/itemviews/qsortfilterproxymodel.cpp
index b3993c7..10bcb9a 100644
--- a/src/gui/itemviews/qsortfilterproxymodel.cpp
+++ b/src/gui/itemviews/qsortfilterproxymodel.cpp
@@ -1103,6 +1103,8 @@ void QSortFilterProxyModelPrivate::_q_sourceReset()
// All internal structures are deleted in clear()
q->reset();
update_source_sort_column();
+ if (dynamic_sortfilter)
+ sort();
}
void QSortFilterProxyModelPrivate::_q_sourceLayoutAboutToBeChanged()
@@ -1495,6 +1497,7 @@ void QSortFilterProxyModel::setSourceModel(QAbstractItemModel *sourceModel)
d->clear_mapping();
reset();
+ d->update_source_sort_column();
}
/*!
@@ -1893,7 +1896,7 @@ QSize QSortFilterProxyModel::span(const QModelIndex &index) const
void QSortFilterProxyModel::sort(int column, Qt::SortOrder order)
{
Q_D(QSortFilterProxyModel);
- if (d->proxy_sort_column == column && d->sort_order == order)
+ if (d->dynamic_sortfilter && d->proxy_sort_column == column && d->sort_order == order)
return;
d->sort_order = order;
d->proxy_sort_column = column;
@@ -2107,6 +2110,8 @@ void QSortFilterProxyModel::setDynamicSortFilter(bool enable)
{
Q_D(QSortFilterProxyModel);
d->dynamic_sortfilter = enable;
+ if (enable)
+ d->sort();
}
/*!
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index 1bbb019..7e59fad 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -2461,7 +2461,9 @@ void QApplication::setActiveWindow(QWidget* act)
} else {
// If the focus widget is not in the activate_window, clear the focus
w = QApplicationPrivate::focus_widget;
- if (w && !QApplicationPrivate::active_window->isAncestorOf(w))
+ if (!w && QApplicationPrivate::active_window->focusPolicy() != Qt::NoFocus)
+ QApplicationPrivate::setFocusWidget(QApplicationPrivate::active_window, Qt::ActiveWindowFocusReason);
+ else if (!QApplicationPrivate::active_window->isAncestorOf(w))
QApplicationPrivate::setFocusWidget(0, Qt::ActiveWindowFocusReason);
}
}
diff --git a/src/gui/kernel/qt_mac.cpp b/src/gui/kernel/qt_mac.cpp
index b462b13..4703475 100644
--- a/src/gui/kernel/qt_mac.cpp
+++ b/src/gui/kernel/qt_mac.cpp
@@ -93,6 +93,8 @@ static QColor qcolorFromCGColor(CGColorRef cgcolor)
pc.setRgbF(components[0], components[1], components[2], components[3]);
} else if (model == kCGColorSpaceModelCMYK) {
pc.setCmykF(components[0], components[1], components[2], components[3]);
+ } else if (model == kCGColorSpaceModelMonochrome) {
+ pc.setRgbF(components[0], components[0], components[0], components[1]);
} else {
// Colorspace we can't deal with.
qWarning("Qt: qcolorFromCGColor: cannot convert from colorspace model: %d", model);
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index d2f4ab7..6589439 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -535,6 +535,8 @@ static void qt_blend_argb32_on_rgb16(uchar *destPixels, int dbpl,
s += BYTE_MUL_RGB16(*dst, 255 - alpha);
*dst = s;
}
+ ++dst;
+ ++src;
}
dst += dstExtraStride;
src += srcExtraStride;
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index f728f9d..8169ef8 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qregion.h"
+#include "qpainterpath.h"
#include "qpolygon.h"
#include "qbuffer.h"
#include "qdatastream.h"
@@ -49,7 +50,6 @@
#include <qdebug.h>
#if defined(Q_OS_UNIX) || defined(Q_OS_WINCE)
-#include "qpainterpath.h"
#include "qimage.h"
#include "qbitmap.h"
#include <stdlib.h>
diff --git a/src/gui/widgets/qcocoamenu_mac.mm b/src/gui/widgets/qcocoamenu_mac.mm
index c5977e4..c92dfc0 100644
--- a/src/gui/widgets/qcocoamenu_mac.mm
+++ b/src/gui/widgets/qcocoamenu_mac.mm
@@ -56,6 +56,10 @@ QT_FORWARD_DECLARE_CLASS(QAction)
QT_FORWARD_DECLARE_CLASS(QWidget)
QT_FORWARD_DECLARE_CLASS(QApplication)
+QT_BEGIN_NAMESPACE
+extern bool qt_sendSpontaneousEvent(QObject*, QEvent*); //qapplication.cpp
+QT_END_NAMESPACE
+
@implementation QT_MANGLE_NAMESPACE(QCocoaMenu)
- (id)initWithQMenu:(QMenu*)menu
diff --git a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
index de023f5..dee3f54 100644
--- a/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
+++ b/tests/auto/qgraphicswidget/tst_qgraphicswidget.cpp
@@ -259,6 +259,35 @@ void tst_QGraphicsWidget::cleanup()
{
}
+class SizeHinter : public QGraphicsWidget
+{
+public:
+ SizeHinter(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0,
+ const QSizeF &min = QSizeF(5,5),
+ const QSizeF &pref = QSizeF(50, 50),
+ const QSizeF &max = QSizeF(500, 500))
+ : QGraphicsWidget(parent, wFlags)
+ {
+ m_sizes[Qt::MinimumSize] = min;
+ m_sizes[Qt::PreferredSize] = pref;
+ m_sizes[Qt::MaximumSize] = max;
+
+ }
+ void setSizeHint(Qt::SizeHint which, const QSizeF &newSizeHint)
+ {
+ m_sizes[which] = newSizeHint;
+ }
+
+protected:
+ QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
+ {
+ Q_UNUSED(constraint);
+ return m_sizes[which];
+ }
+private:
+ QSizeF m_sizes[4];
+};
+
void tst_QGraphicsWidget::qgraphicswidget()
{
SubQGraphicsWidget widget;
@@ -282,6 +311,12 @@ void tst_QGraphicsWidget::qgraphicswidget()
QCOMPARE(widget.type(), (int)QGraphicsWidget::Type);
QCOMPARE(widget.call_propertyChange(QString(), QVariant()), QVariant());
widget.call_sizeHint(Qt::PreferredSize, QSizeF());
+
+ QGraphicsScene scene;
+ QGraphicsWidget *parent = new QGraphicsWidget;
+ SizeHinter *child = new SizeHinter(parent);
+
+ QCOMPARE(child->minimumSize(), QSizeF(5, 5));
}
void tst_QGraphicsWidget::activation()
@@ -1516,35 +1551,6 @@ enum WhichSize {
None,
};
-class SizeHinter : public QGraphicsWidget
-{
-public:
- SizeHinter(QGraphicsItem *parent = 0, Qt::WindowFlags wFlags = 0,
- const QSizeF &min = QSizeF(5,5),
- const QSizeF &pref = QSizeF(50, 50),
- const QSizeF &max = QSizeF(500, 500))
- : QGraphicsWidget(parent, wFlags)
- {
- m_sizes[Qt::MinimumSize] = min;
- m_sizes[Qt::PreferredSize] = pref;
- m_sizes[Qt::MaximumSize] = max;
-
- }
- void setSizeHint(Qt::SizeHint which, const QSizeF &newSizeHint)
- {
- m_sizes[which] = newSizeHint;
- }
-
-protected:
- QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint = QSizeF()) const
- {
- Q_UNUSED(constraint);
- return m_sizes[which];
- }
-private:
- QSizeF m_sizes[4];
-};
-
typedef QPair<int, QVariant> Inst;
Q_DECLARE_METATYPE(Inst)
diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp
index 5a15683..2e1335c 100644
--- a/tests/auto/qpainter/tst_qpainter.cpp
+++ b/tests/auto/qpainter/tst_qpainter.cpp
@@ -204,6 +204,9 @@ private slots:
void drawImage_task217400();
void drawRect_task215378();
+ void drawImage_data();
+ void drawImage();
+
void clippedImage();
void stateResetBetweenQPainters();
@@ -3586,6 +3589,77 @@ void tst_QPainter::drawRect_task215378()
QVERIFY(img.pixel(0, 0) != img.pixel(1, 1));
}
+void tst_QPainter::drawImage_data()
+{
+ QTest::addColumn<int>("x");
+ QTest::addColumn<int>("y");
+ QTest::addColumn<int>("w");
+ QTest::addColumn<int>("h");
+ QTest::addColumn<QImage::Format>("srcFormat");
+ QTest::addColumn<QImage::Format>("dstFormat");
+
+ for (int srcFormat = QImage::Format_Mono; srcFormat < QImage::NImageFormats; ++srcFormat) {
+ for (int dstFormat = QImage::Format_Mono; dstFormat < QImage::NImageFormats; ++dstFormat) {
+ if (dstFormat == QImage::Format_Indexed8)
+ continue;
+ for (int odd_x = 0; odd_x <= 1; ++odd_x) {
+ for (int odd_width = 0; odd_width <= 1; ++odd_width) {
+ QString description =
+ QString("srcFormat %1, dstFormat %2, odd x: %3, odd width: %4")
+ .arg(srcFormat).arg(dstFormat).arg(odd_x).arg(odd_width);
+
+ QTest::newRow(description) << (10 + odd_x) << 10 << (20 + odd_width) << 20
+ << QImage::Format(srcFormat)
+ << QImage::Format(dstFormat);
+ }
+ }
+ }
+ }
+}
+
+bool verifyImage(const QImage &img, int x, int y, int w, int h, uint background)
+{
+ int imgWidth = img.width();
+ int imgHeight = img.height();
+ for (int i = 0; i < imgHeight; ++i) {
+ for (int j = 0; j < imgWidth; ++j) {
+ uint pixel = img.pixel(j, i);
+ bool outside = j < x || j >= (x + w) || i < y || i >= (y + h);
+ if (outside != (pixel == background)) {
+ //printf("%d %d, expected %x, got %x, outside: %d\n", x, y, background, pixel, outside);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void tst_QPainter::drawImage()
+{
+ QFETCH(int, x);
+ QFETCH(int, y);
+ QFETCH(int, w);
+ QFETCH(int, h);
+ QFETCH(QImage::Format, srcFormat);
+ QFETCH(QImage::Format, dstFormat);
+
+ QImage dst(40, 40, QImage::Format_RGB32);
+ dst.fill(0xffffffff);
+
+ dst = dst.convertToFormat(dstFormat);
+ uint background = dst.pixel(0, 0);
+
+ QImage src(w, h, QImage::Format_RGB32);
+ src.fill(0xff000000);
+ src = src.convertToFormat(srcFormat);
+
+ QPainter p(&dst);
+ p.drawImage(x, y, src);
+ p.end();
+
+ QVERIFY(verifyImage(dst, x, y, w, h, background));
+}
void tst_QPainter::imageCoordinateLimit()
{
diff --git a/tests/auto/qpixmap/tst_qpixmap.cpp b/tests/auto/qpixmap/tst_qpixmap.cpp
index 1590fc0..8a6b63b 100644
--- a/tests/auto/qpixmap/tst_qpixmap.cpp
+++ b/tests/auto/qpixmap/tst_qpixmap.cpp
@@ -106,6 +106,7 @@ private slots:
void grabWidget();
void grabWindow();
void isNull();
+ void task_246446();
#ifdef Q_WS_QWS
void convertFromImageNoDetach();
@@ -1111,5 +1112,20 @@ void tst_QPixmap::fromData()
QCOMPARE(img.pixel(0, 1), QRgb(0xff000000));
}
+void tst_QPixmap::task_246446()
+{
+ // This crashed without the bugfix in 246446
+ QPixmap pm(10, 10);
+ pm.fill(Qt::transparent); // force 32-bit depth
+ QBitmap bm;
+ pm.setMask(bm);
+ {
+ QPixmap pm2(pm);
+ }
+ QVERIFY(pm.width() == 10);
+ QVERIFY(pm.mask().isNull());
+}
+
+
QTEST_MAIN(tst_QPixmap)
#include "tst_qpixmap.moc"
diff --git a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
index 9f92c37..0a48066 100644
--- a/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
+++ b/tests/auto/qsortfilterproxymodel/tst_qsortfilterproxymodel.cpp
@@ -129,6 +129,8 @@ private slots:
void task236755_hiddenColumns();
void task247867_insertRowsSort();
+ void task248868_staticSorting();
+ void task248868_dynamicSorting();
protected:
void buildHierarchy(const QStringList &data, QAbstractItemModel *model);
@@ -2479,5 +2481,115 @@ void tst_QSortFilterProxyModel::task247867_insertRowsSort()
QCOMPARE(proxyModel.sortColumn(), 0);
}
+void tst_QSortFilterProxyModel::task248868_staticSorting()
+{
+ QStandardItemModel model(0, 1);
+ QSortFilterProxyModel proxy;
+ proxy.setSourceModel(&model);
+ proxy.setDynamicSortFilter(false);
+ QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(" ");
+
+ // prepare model
+ QStandardItem *root = model.invisibleRootItem ();
+ QList<QStandardItem *> items;
+ for (int i = 0; i < initial.count(); ++i) {
+ items.append(new QStandardItem(initial.at(i)));
+ }
+ root->insertRows(0, items);
+ QCOMPARE(model.rowCount(QModelIndex()), initial.count());
+ QCOMPARE(model.columnCount(QModelIndex()), 1);
+
+ // make sure the proxy is unsorted
+ QCOMPARE(proxy.columnCount(QModelIndex()), 1);
+ QCOMPARE(proxy.rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ // sort
+ proxy.sort(0);
+
+ QStringList expected = initial;
+ expected.sort();
+ // make sure the proxy is sorted
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ //update one item.
+ model.setItem(0, 0, new QStandardItem("girafe"));
+
+ // make sure the proxy is updated but not sorted
+ expected.replaceInStrings("bateau", "girafe");
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ // sort again
+ proxy.sort(0);
+ expected.sort();
+
+ // make sure the proxy is sorted
+ for (int row = 0; row < proxy.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy.index(row, 0, QModelIndex());
+ QCOMPARE(proxy.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+}
+
+void tst_QSortFilterProxyModel::task248868_dynamicSorting()
+{
+ QStringListModel model1;
+ const QStringList initial = QString("bateau avion dragon hirondelle flamme camion elephant").split(" ");
+ model1.setStringList(initial);
+ QSortFilterProxyModel proxy1;
+ proxy1.sort(0);
+ proxy1.setSourceModel(&model1);
+
+ QCOMPARE(proxy1.columnCount(QModelIndex()), 1);
+ //the model should not be sorted because sorting has not been set to dynamic yet.
+ QCOMPARE(proxy1.rowCount(QModelIndex()), initial.count());
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), initial.at(row));
+ }
+
+ proxy1.setDynamicSortFilter(true);
+
+ //now the model should be sorted.
+ QStringList expected = initial;
+ expected.sort();
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+
+ QStringList initial2 = initial;
+ initial2.replaceInStrings("bateau", "girafe");
+ model1.setStringList(initial2); //this will cause a reset
+
+ QStringList expected2 = initial2;
+ expected2.sort();
+
+ //now the model should still be sorted.
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected2.at(row));
+ }
+
+ QStringListModel model2(initial);
+ proxy1.setSourceModel(&model2);
+
+ //the model should again be sorted
+ for (int row = 0; row < proxy1.rowCount(QModelIndex()); ++row) {
+ QModelIndex index = proxy1.index(row, 0, QModelIndex());
+ QCOMPARE(proxy1.data(index, Qt::DisplayRole).toString(), expected.at(row));
+ }
+}
+
+
QTEST_MAIN(tst_QSortFilterProxyModel)
#include "tst_qsortfilterproxymodel.moc"
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index 42f496a..dfd0792 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -343,6 +343,7 @@ private slots:
void paintOutsidePaintEvent();
#endif
void updateOnDestroyedSignal();
+ void toplevelLineEditFocus();
private:
bool ensureScreenSize(int width, int height);
@@ -8727,5 +8728,18 @@ void tst_QWidget::updateOnDestroyedSignal()
QTest::qWait(200);
}
+void tst_QWidget::toplevelLineEditFocus()
+{
+ testWidget->hide();
+
+ QLineEdit w;
+ w.show();
+ qt_x11_wait_for_window_manager(&w);
+ QTest::qWait(200);
+
+ QCOMPARE(QApplication::activeWindow(), &w);
+ QCOMPARE(QApplication::focusWidget(), &w);
+}
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"