summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qnamespace.qdoc2
-rw-r--r--src/corelib/io/qurl.cpp42
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp6
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp2
-rw-r--r--src/corelib/tools/qbytearraylist.h1
-rw-r--r--src/corelib/tools/qlocale.cpp4
-rw-r--r--src/corelib/tools/qlocale_p.h4
-rw-r--r--src/corelib/tools/qstring.cpp57
-rw-r--r--src/gui/kernel/qguiapplication.cpp25
-rw-r--r--src/gui/kernel/qguiapplication_p.h1
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
-rw-r--r--src/gui/kernel/qwindow.cpp4
-rw-r--r--src/gui/opengl/qopenglframebufferobject.cpp36
-rw-r--r--src/gui/painting/qbrush.cpp3
-rw-r--r--src/gui/painting/qdrawhelper.cpp2
-rw-r--r--src/gui/text/qfontengine_ft.cpp75
-rw-r--r--src/gui/text/qfontengine_ft_p.h3
-rw-r--r--src/gui/util/qvalidator.cpp26
-rw-r--r--src/network/access/qhttpnetworkrequest.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp19
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp21
-rw-r--r--src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h1
-rw-r--r--src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp2
-rw-r--r--src/opengl/qgl.cpp29
-rw-r--r--src/opengl/qgl_p.h2
-rw-r--r--src/opengl/qglframebufferobject.cpp31
-rw-r--r--src/opengl/qglpaintdevice.cpp13
-rw-r--r--src/opengl/qglpixelbuffer.cpp2
-rw-r--r--src/platformsupport/fontdatabases/basic/basic.pri1
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux.cpp12
-rw-r--r--src/plugins/bearer/linux_common/qofonoservice_linux_p.h2
-rw-r--r--src/plugins/bearer/networkmanager/main.cpp5
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp310
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.h13
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp22
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm19
-rw-r--r--src/plugins/platforms/ios/quiview_accessibility.mm11
-rw-r--r--src/plugins/platforms/windows/qwindowsfontengine.cpp4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp45
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h1
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp6
-rw-r--r--src/widgets/accessible/simplewidgets.cpp2
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp14
-rw-r--r--src/widgets/kernel/qapplication.cpp38
-rw-r--r--src/widgets/kernel/qapplication_p.h3
-rw-r--r--src/widgets/kernel/qgesture_p.h3
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp20
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp10
-rw-r--r--src/widgets/kernel/qstandardgestures.cpp53
-rw-r--r--src/widgets/kernel/qstandardgestures_p.h5
-rw-r--r--src/widgets/kernel/qwidget.cpp5
-rw-r--r--src/widgets/styles/qfusionstyle.cpp4
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp5
-rw-r--r--src/widgets/widgets/qmainwindow.cpp7
-rw-r--r--src/widgets/widgets/qmdiarea.cpp16
-rw-r--r--src/widgets/widgets/qmdiarea_p.h9
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp14
-rw-r--r--src/widgets/widgets/qtextedit.cpp14
-rw-r--r--src/widgets/widgets/qwidgettextcontrol.cpp9
61 files changed, 821 insertions, 282 deletions
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index 8d6f7834b0..53d2b7b58b 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -2804,11 +2804,11 @@
This enum type describes the state of a gesture.
+ \value NoGesture No gesture has been detected.
\value GestureStarted A continuous gesture has started.
\value GestureUpdated A gesture continues.
\value GestureFinished A gesture has finished.
\value GestureCanceled A gesture was canceled.
- \omitvalue NoGesture
\sa QGesture
*/
diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp
index d4c5e03058..b21e9b51e1 100644
--- a/src/corelib/io/qurl.cpp
+++ b/src/corelib/io/qurl.cpp
@@ -403,6 +403,7 @@
#include "qdebug.h"
#include "qhash.h"
#include "qdir.h" // for QDir::fromNativeSeparators
+#include "qdatastream.h"
#include "qtldurl_p.h"
#include "private/qipaddress_p.h"
#include "qurlquery.h"
@@ -429,6 +430,16 @@ static inline QString fileScheme()
return QStringLiteral("file");
}
+static inline QString webDavScheme()
+{
+ return QStringLiteral("webdavs");
+}
+
+static inline QString webDavSslTag()
+{
+ return QStringLiteral("@SSL");
+}
+
#ifdef Q_COMPILER_CLASS_ENUM
# define colon_uchar : uchar
#else
@@ -992,10 +1003,15 @@ inline bool QUrlPrivate::setScheme(const QString &value, int len, bool doSetErro
}
// did we set to the file protocol?
- if (scheme == fileScheme())
+ if (scheme == fileScheme()
+#ifdef Q_OS_WIN
+ || scheme == webDavScheme()
+#endif
+ ) {
flags |= IsLocalFile;
- else
+ } else {
flags &= ~IsLocalFile;
+ }
return true;
}
@@ -3738,7 +3754,7 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
QUrl url;
if (localFile.isEmpty())
return url;
- url.setScheme(fileScheme());
+ QString scheme = fileScheme();
QString deslashified = QDir::fromNativeSeparators(localFile);
// magic for drives on windows
@@ -3747,13 +3763,21 @@ QUrl QUrl::fromLocalFile(const QString &localFile)
} else if (deslashified.startsWith(QLatin1String("//"))) {
// magic for shared drive on windows
int indexOfPath = deslashified.indexOf(QLatin1Char('/'), 2);
- url.setHost(deslashified.mid(2, indexOfPath - 2));
+ QString hostSpec = deslashified.mid(2, indexOfPath - 2);
+ // Check for Windows-specific WebDAV specification: "//host@SSL/path".
+ if (hostSpec.endsWith(webDavSslTag(), Qt::CaseInsensitive)) {
+ hostSpec.chop(4);
+ scheme = webDavScheme();
+ }
+ url.setHost(hostSpec);
+
if (indexOfPath > 2)
deslashified = deslashified.right(deslashified.length() - indexOfPath);
else
deslashified.clear();
}
+ url.setScheme(scheme);
url.setPath(deslashified, DecodedMode);
return url;
}
@@ -3783,8 +3807,14 @@ QString QUrl::toLocalFile() const
// magic for shared drive on windows
if (!d->host.isEmpty()) {
- tmp = QStringLiteral("//") + host() + (ourPath.length() > 0 && ourPath.at(0) != QLatin1Char('/')
- ? QLatin1Char('/') + ourPath : ourPath);
+ tmp = QStringLiteral("//") + host();
+#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only.
+ if (scheme() == webDavScheme())
+ tmp += webDavSslTag();
+#endif
+ if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/')))
+ tmp += QLatin1Char('/');
+ tmp += ourPath;
} else {
tmp = ourPath;
#ifdef Q_OS_WIN
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index a95c7dc8b3..3c383532bb 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -1196,11 +1196,7 @@ void QSortFilterProxyModelPrivate::_q_sourceDataChanged(const QModelIndex &sourc
parents << q->mapFromSource(source_parent);
emit q->layoutAboutToBeChanged(parents, QAbstractItemModel::VerticalSortHint);
QModelIndexPairList source_indexes = store_persistent_indexes();
- remove_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
- sort_source_rows(source_rows_resort, source_parent);
- insert_source_items(m->proxy_rows, m->source_rows, source_rows_resort,
- source_parent, Qt::Vertical, false);
+ sort_source_rows(m->source_rows, source_parent);
update_persistent_indexes(source_indexes);
emit q->layoutChanged(parents, QAbstractItemModel::VerticalSortHint);
// Make sure we also emit dataChanged for the rows
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 45647f2056..77900ba906 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -714,9 +714,7 @@ void QCoreApplication::init()
Q_ASSERT_X(!self, "QCoreApplication", "there should be only one application object");
QCoreApplication::self = this;
-#ifndef QT_BOOTSTRAPPED
QLoggingRegistry::instance()->init();
-#endif
#ifndef QT_NO_QOBJECT
// use the event dispatcher created by the app programmer (if any)
diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h
index 9d7e776028..dd84ec642c 100644
--- a/src/corelib/tools/qbytearraylist.h
+++ b/src/corelib/tools/qbytearraylist.h
@@ -63,6 +63,7 @@ class QByteArrayList : public QList<QByteArray>
template <> struct QListSpecialMethods<QByteArray>
#endif
{
+public:
inline QByteArray join() const
{ return QtPrivate::QByteArrayList_join(self(), 0, 0); }
inline QByteArray join(const QByteArray &sep) const
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index a253057435..a923be50c0 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -3144,7 +3144,7 @@ bool QLocaleData::numberToCLocale(const QChar *str, int len,
}
bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArray *buff,
- int decDigits) const
+ int decDigits, bool rejectGroupSeparators) const
{
buff->clear();
buff->reserve(str.length());
@@ -3205,7 +3205,7 @@ bool QLocaleData::validateChars(const QString &str, NumberMode numMode, QByteArr
case ',':
//it can only be placed after a digit which is before the decimal point
- if (!lastWasDigit || decPointCnt > 0)
+ if (rejectGroupSeparators || !lastWasDigit || decPointCnt > 0)
return false;
break;
diff --git a/src/corelib/tools/qlocale_p.h b/src/corelib/tools/qlocale_p.h
index c33ced35d5..c5e62027c4 100644
--- a/src/corelib/tools/qlocale_p.h
+++ b/src/corelib/tools/qlocale_p.h
@@ -251,7 +251,9 @@ public:
inline char digitToCLocale(QChar c) const;
// this function is used in QIntValidator (QtGui)
- Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode, QByteArray *buff, int decDigits = -1) const;
+ Q_CORE_EXPORT bool validateChars(const QString &str, NumberMode numMode,
+ QByteArray *buff, int decDigits = -1,
+ bool rejectGroupSeparators = false) const;
public:
quint16 m_language_id, m_script_id, m_country_id;
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index ef12c1b8e3..29b546770c 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -3863,28 +3863,31 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
{
QStringList sections = split(sep, KeepEmptyParts,
(flags & SectionCaseInsensitiveSeps) ? Qt::CaseInsensitive : Qt::CaseSensitive);
- if (sections.isEmpty())
- return QString();
+ const int sectionsSize = sections.size();
+
if (!(flags & SectionSkipEmpty)) {
if (start < 0)
- start += sections.count();
+ start += sectionsSize;
if (end < 0)
- end += sections.count();
+ end += sectionsSize;
} else {
int skip = 0;
- for (int k=0; k<sections.size(); ++k) {
+ for (int k = 0; k < sectionsSize; ++k) {
if (sections.at(k).isEmpty())
skip++;
}
if (start < 0)
- start += sections.count() - skip;
+ start += sectionsSize - skip;
if (end < 0)
- end += sections.count() - skip;
+ end += sectionsSize - skip;
}
+ if (start >= sectionsSize || end < 0 || start > end)
+ return QString();
+
int x = 0;
QString ret;
int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sections.size(); ++i) {
+ for (int i = 0; x <= end && i < sectionsSize; ++i) {
QString section = sections.at(i);
const bool empty = section.isEmpty();
if (x >= start) {
@@ -3892,16 +3895,16 @@ QString QString::section(const QString &sep, int start, int end, SectionFlags fl
first_i = i;
if(x == end)
last_i = i;
- if(x > start)
+ if (x > start && i > 0)
ret += sep;
ret += section;
}
if (!empty || !(flags & SectionSkipEmpty))
x++;
}
- if((flags & SectionIncludeLeadingSep) && first_i)
+ if ((flags & SectionIncludeLeadingSep) && first_i > 0)
ret.prepend(sep);
- if((flags & SectionIncludeTrailingSep) && last_i < sections.size()-1)
+ if ((flags & SectionIncludeTrailingSep) && last_i < sectionsSize - 1)
ret += sep;
return ret;
}
@@ -3919,15 +3922,32 @@ static QString extractSections(const QList<qt_section_chunk> &sections,
int end,
QString::SectionFlags flags)
{
- if (start < 0)
- start += sections.count();
- if (end < 0)
- end += sections.count();
+ const int sectionsSize = sections.size();
+
+ if (!(flags & QString::SectionSkipEmpty)) {
+ if (start < 0)
+ start += sectionsSize;
+ if (end < 0)
+ end += sectionsSize;
+ } else {
+ int skip = 0;
+ for (int k = 0; k < sectionsSize; ++k) {
+ const qt_section_chunk &section = sections.at(k);
+ if (section.length == section.string.length())
+ skip++;
+ }
+ if (start < 0)
+ start += sectionsSize - skip;
+ if (end < 0)
+ end += sectionsSize - skip;
+ }
+ if (start >= sectionsSize || end < 0 || start > end)
+ return QString();
QString ret;
int x = 0;
int first_i = start, last_i = end;
- for (int i = 0; x <= end && i < sections.size(); ++i) {
+ for (int i = 0; x <= end && i < sectionsSize; ++i) {
const qt_section_chunk &section = sections.at(i);
const bool empty = (section.length == section.string.length());
if (x >= start) {
@@ -3944,12 +3964,13 @@ static QString extractSections(const QList<qt_section_chunk> &sections,
x++;
}
- if ((flags & QString::SectionIncludeLeadingSep) && first_i < sections.size()) {
+ if ((flags & QString::SectionIncludeLeadingSep) && first_i >= 0) {
const qt_section_chunk &section = sections.at(first_i);
ret.prepend(section.string.left(section.length));
}
- if ((flags & QString::SectionIncludeTrailingSep) && last_i+1 <= sections.size()-1) {
+ if ((flags & QString::SectionIncludeTrailingSep)
+ && last_i < sectionsSize - 1) {
const qt_section_chunk &section = sections.at(last_i+1);
ret += section.string.left(section.length);
}
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 59bcd37251..fe92ead846 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -163,7 +163,6 @@ QWindow *QGuiApplicationPrivate::focus_window = 0;
static QBasicMutex applicationFontMutex;
QFont *QGuiApplicationPrivate::app_font = 0;
bool QGuiApplicationPrivate::obey_desktop_settings = true;
-bool QGuiApplicationPrivate::noGrab = false;
static qreal fontSmoothingGamma = 1.7;
@@ -1196,20 +1195,10 @@ void QGuiApplicationPrivate::eventDispatcherReady()
platform_integration->initialize();
}
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
-// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc.
-static bool runningUnderDebugger()
-{
- const QFileInfo parentProcExe(QStringLiteral("/proc/") + QString::number(getppid()) + QStringLiteral("/exe"));
- return parentProcExe.isSymLink() && parentProcExe.symLinkTarget().endsWith(QLatin1String("/gdb"));
-}
-#endif
-
void QGuiApplicationPrivate::init()
{
QCoreApplicationPrivate::is_app_running = false; // Starting up.
- bool doGrabUnderDebugger = false;
bool loadTestability = false;
QList<QByteArray> pluginList;
// Get command line params
@@ -1244,10 +1233,6 @@ void QGuiApplicationPrivate::init()
QDir::setCurrent(qbundlePath.section(QLatin1Char('/'), 0, -2));
}
#endif
- } else if (arg == "-nograb") {
- QGuiApplicationPrivate::noGrab = true;
- } else if (arg == "-dograb") {
- doGrabUnderDebugger = true;
#ifndef QT_NO_SESSIONMANAGER
} else if (arg == "-session" && i < argc-1) {
++i;
@@ -1273,16 +1258,6 @@ void QGuiApplicationPrivate::init()
argc = j;
}
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
- if (!doGrabUnderDebugger && !QGuiApplicationPrivate::noGrab && runningUnderDebugger()) {
- QGuiApplicationPrivate::noGrab = true;
- qDebug("Qt: gdb: -nograb added to command-line options.\n"
- "\t Use the -dograb option to enforce grabbing.");
- }
-#else
- Q_UNUSED(doGrabUnderDebugger)
-#endif
-
// Load environment exported generic plugins
foreach (const QByteArray &plugin, qgetenv("QT_QPA_GENERIC_PLUGINS").split(','))
pluginList << plugin;
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 8988bd461d..eed3d5c10e 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -221,7 +221,6 @@ public:
QStyleHints *styleHints;
static bool obey_desktop_settings;
- static bool noGrab;
QInputMethod *inputMethod;
QString firstWindowTitle;
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index d5a3126176..975553e7cd 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -203,6 +203,7 @@ public:
, workaround_brokenTexSubImage(false)
, workaround_missingPrecisionQualifiers(false)
, active_engine(0)
+ , qgl_current_fbo_invalid(false)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -237,6 +238,8 @@ public:
QPaintEngineEx *active_engine;
+ bool qgl_current_fbo_invalid;
+
QVariant nativeHandle;
static QOpenGLContext *setCurrentContext(QOpenGLContext *context);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 99bf469f87..c6dd0955aa 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1639,8 +1639,6 @@ QPlatformSurface *QWindow::surfaceHandle() const
bool QWindow::setKeyboardGrabEnabled(bool grab)
{
Q_D(QWindow);
- if (grab && QGuiApplicationPrivate::noGrab)
- return false;
if (d->platformWindow)
return d->platformWindow->setKeyboardGrabEnabled(grab);
return false;
@@ -1658,8 +1656,6 @@ bool QWindow::setKeyboardGrabEnabled(bool grab)
bool QWindow::setMouseGrabEnabled(bool grab)
{
Q_D(QWindow);
- if (grab && QGuiApplicationPrivate::noGrab)
- return false;
if (d->platformWindow)
return d->platformWindow->setMouseGrabEnabled(grab);
return false;
diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp
index b185e332e6..124d9d53f6 100644
--- a/src/gui/opengl/qopenglframebufferobject.cpp
+++ b/src/gui/opengl/qopenglframebufferobject.cpp
@@ -469,6 +469,8 @@ void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSi
funcs.glGenFramebuffers(1, &fbo);
funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+ QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
+
GLuint color_buffer = 0;
QT_CHECK_GLERROR();
@@ -997,7 +999,11 @@ bool QOpenGLFramebufferObject::bind()
if (current->shareGroup() != d->fbo_guard->group())
qWarning("QOpenGLFramebufferObject::bind() called from incompatible context");
#endif
+
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
+
if (d->texture_guard || d->format.samples() != 0)
d->valid = d->checkFramebufferStatus(current);
else
@@ -1029,9 +1035,12 @@ bool QOpenGLFramebufferObject::release()
qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
#endif
- if (current)
+ if (current) {
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject());
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
+ }
+
return true;
}
@@ -1194,9 +1203,23 @@ Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format,
If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value
of QOpenGLPaintDevice::paintFlipped().
- Will try to return a premultiplied ARBG32 or RGB32 image. Since 5.2 it will fall back to
- a premultiplied RGBA8888 or RGBx8888 image when reading to ARGB32 is not supported. Since 5.4 an
- A2BGR30 image is returned if the internal format is RGB10_A2.
+ The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
+ only when internalTextureFormat() is set to \c GL_RGB.
+
+ If the rendering in the framebuffer was not done with premultiplied alpha in mind,
+ create a wrapper QImage with a non-premultiplied format. This is necessary before
+ performing operations like QImage::save() because otherwise the image data would get
+ unpremultiplied, even though it was not premultiplied in the first place. To create
+ such a wrapper without performing a copy of the pixel data, do the following:
+
+ \code
+ QImage fboImage(fbo.toImage());
+ QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
+ \endcode
+
+ Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when
+ reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the
+ internal format is RGB10_A2.
For multisampled framebuffer objects the samples are resolved using the
\c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents
@@ -1272,8 +1295,10 @@ bool QOpenGLFramebufferObject::bindDefault()
{
QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
- if (ctx)
+ if (ctx) {
ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
+ QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
+ }
#ifdef QT_DEBUG
else
qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
@@ -1342,6 +1367,7 @@ void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachmen
qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context");
#endif
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
+ QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
d->initAttachments(current, attachment);
}
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index d120175108..d136f3a903 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -708,6 +708,9 @@ void QBrush::setStyle(Qt::BrushStyle style)
void QBrush::setColor(const QColor &c)
{
+ if (d->color == c)
+ return;
+
detach(d->style);
d->color = c;
}
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index f2d27a0e2a..6482cc50f7 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -6829,7 +6829,7 @@ void qInitDrawhelperAsm()
qt_fetch_radial_gradient = qt_fetch_radial_gradient_neon;
#endif
-#ifdef Q_PROCESSOR_MIPS_32
+#if defined(Q_PROCESSOR_MIPS_32) && defined(QT_COMPILER_SUPPORTS_MIPS_DSP)
qt_memfill32 = qt_memfill32_asm_mips_dsp;
#endif // Q_PROCESSOR_MIPS_32
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index b0cfa49b36..83d9edab94 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1459,10 +1459,7 @@ void QFontEngineFT::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, glyph_me
bool QFontEngineFT::supportsTransformation(const QTransform &transform) const
{
- // The freetype engine falls back to QFontEngine for tranformed glyphs,
- // which uses fast-tranform and produces very ugly results, so we claim
- // to support just translations.
- return transform.type() <= QTransform::TxTranslate;
+ return transform.type() <= QTransform::TxRotate;
}
void QFontEngineFT::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags)
@@ -1943,17 +1940,75 @@ void QFontEngineFT::unlockAlphaMapForGlyph()
currentlyLockedAlphaMap = QImage();
}
-QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format)
+QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
+ QFixed subPixelPosition,
+ GlyphFormat format,
+ const QTransform &t)
{
- return defaultGlyphSet.outline_drawing ? 0 :
- loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, g, subPixelPosition, format);
+ FT_Face face = 0;
+ QGlyphSet *glyphSet = 0;
+ FT_Matrix ftMatrix = QTransformToFTMatrix(t);
+ if (cacheEnabled) {
+ if (t.type() > QTransform::TxTranslate && FT_IS_SCALABLE(freetype->face)) {
+ for (int i = 0; i < transformedGlyphSets.count(); ++i) {
+ const QGlyphSet &g = transformedGlyphSets.at(i);
+ if (g.transformationMatrix.xx == ftMatrix.xx
+ && g.transformationMatrix.xy == ftMatrix.xy
+ && g.transformationMatrix.yx == ftMatrix.yx
+ && g.transformationMatrix.yy == ftMatrix.yy) {
+
+ // found a match, move it to the front
+ transformedGlyphSets.move(i, 0);
+ glyphSet = &transformedGlyphSets[0];
+ break;
+ }
+ }
+
+ if (!glyphSet) {
+ // don't cache more than 10 transformations
+ if (transformedGlyphSets.count() >= 10) {
+ transformedGlyphSets.move(transformedGlyphSets.size() - 1, 0);
+ } else {
+ transformedGlyphSets.prepend(QGlyphSet());
+ }
+ glyphSet = &transformedGlyphSets[0];
+ glyphSet->clear();
+ glyphSet->transformationMatrix = ftMatrix;
+ }
+ } else {
+ glyphSet = &defaultGlyphSet;
+ }
+ Q_ASSERT(glyphSet != 0);
+ }
+
+ if (glyphSet != 0 && glyphSet->outline_drawing)
+ return 0;
+
+ Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
+ if (!glyph || glyph->format != format) {
+ face = lockFace();
+ FT_Matrix m = this->matrix;
+ FT_Matrix_Multiply(&ftMatrix, &m);
+ freetype->matrix = m;
+ glyph = loadGlyph(glyphSet, g, subPixelPosition, format, false);
+ }
+
+ if (face)
+ unlockFace();
+
+ return glyph;
}
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
{
+ return alphaMapForGlyph(g, subPixelPosition, QTransform());
+}
+
+QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
+{
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaMapForGlyph(g);
@@ -1987,12 +2042,12 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
{
- if (t.type() > QTransform::TxTranslate)
+ if (t.type() > QTransform::TxRotate)
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
lockFace();
- QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32));
+ QScopedPointer<Glyph> glyph(loadGlyphFor(g, subPixelPosition, Format_A32, t));
if (!glyph || !glyph->data) {
unlockFace();
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h
index a73c281f1d..1894d25d70 100644
--- a/src/gui/text/qfontengine_ft_p.h
+++ b/src/gui/text/qfontengine_ft_p.h
@@ -233,6 +233,7 @@ private:
virtual void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags flags) const;
virtual QImage alphaMapForGlyph(glyph_t g) { return alphaMapForGlyph(g, 0); }
virtual QImage alphaMapForGlyph(glyph_t, QFixed);
+ QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t);
virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t);
virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph,
QFixed subPixelPosition,
@@ -265,7 +266,7 @@ private:
inline Glyph *loadGlyph(uint glyph, QFixed subPixelPosition, GlyphFormat format = Format_None, bool fetchMetricsOnly = false) const
{ return loadGlyph(cacheEnabled ? &defaultGlyphSet : 0, glyph, subPixelPosition, format, fetchMetricsOnly); }
Glyph *loadGlyph(QGlyphSet *set, uint glyph, QFixed subPixelPosition, GlyphFormat = Format_None, bool fetchMetricsOnly = false) const;
- Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format);
+ Glyph *loadGlyphFor(glyph_t g, QFixed subPixelPosition, GlyphFormat format, const QTransform &t);
QGlyphSet *loadTransformedGlyphSet(const QTransform &matrix);
bool loadGlyphs(QGlyphSet *gs, const glyph_t *glyphs, int num_glyphs,
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 1b5a10f733..f879847935 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -316,7 +316,12 @@ void QValidator::fixup(QString &) const
QIntValidator uses its locale() to interpret the number. For example,
in Arabic locales, QIntValidator will accept Arabic digits.
- \sa QDoubleValidator, QRegExpValidator, {Line Edits Example}
+ \note The QLocale::NumberOptions set on the locale() also affect the
+ way the number is interpreted. For example, since QLocale::RejectGroupSeparator
+ is not set by default, the validator will accept group separators. It is thus
+ recommended to use QLocale::toInt() to obtain the numeric value.
+
+ \sa QDoubleValidator, QRegExpValidator, QLocale::toInt(), {Line Edits Example}
*/
/*!
@@ -393,7 +398,8 @@ static qlonglong pow10(int exp)
QValidator::State QIntValidator::validate(QString & input, int&) const
{
QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) {
+ if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff,
+ -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) {
return Invalid;
}
@@ -432,7 +438,8 @@ QValidator::State QIntValidator::validate(QString & input, int&) const
void QIntValidator::fixup(QString &input) const
{
QByteArray buff;
- if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff)) {
+ if (!locale().d->m_data->validateChars(input, QLocaleData::IntegerMode, &buff,
+ -1, locale().numberOptions() & QLocale::RejectGroupSeparator)) {
return;
}
bool ok, overflow;
@@ -548,7 +555,12 @@ public:
in the German locale, "1,234" will be accepted as the fractional number
1.234. In Arabic locales, QDoubleValidator will accept Arabic digits.
- \sa QIntValidator, QRegExpValidator, {Line Edits Example}
+ \note The QLocale::NumberOptions set on the locale() also affect the
+ way the number is interpreted. For example, since QLocale::RejectGroupSeparator
+ is not set by default, the validator will accept group separators. It is thus
+ recommended to use QLocale::toDouble() to obtain the numeric value.
+
+ \sa QIntValidator, QRegExpValidator, QLocale::toDouble(), {Line Edits Example}
*/
/*!
@@ -648,8 +660,10 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
{
Q_Q(const QDoubleValidator);
QByteArray buff;
- if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec))
+ if (!locale.d->m_data->validateChars(input, numMode, &buff, q->dec,
+ locale.numberOptions() & QLocale::RejectGroupSeparator)) {
return QValidator::Invalid;
+ }
if (buff.isEmpty())
return QValidator::Intermediate;
@@ -1003,7 +1017,7 @@ QValidator::State QRegularExpressionValidator::validate(QString &input, int &pos
const QRegularExpressionMatch m = d->usedRe.match(input, 0, QRegularExpression::PartialPreferCompleteMatch);
if (m.hasMatch()) {
return Acceptable;
- } else if (m.hasPartialMatch()) {
+ } else if (input.isEmpty() || m.hasPartialMatch()) {
return Intermediate;
} else {
pos = input.size();
diff --git a/src/network/access/qhttpnetworkrequest.cpp b/src/network/access/qhttpnetworkrequest.cpp
index f50a79b061..66f093e490 100644
--- a/src/network/access/qhttpnetworkrequest.cpp
+++ b/src/network/access/qhttpnetworkrequest.cpp
@@ -151,7 +151,7 @@ QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request
}
if (request.d->operation == QHttpNetworkRequest::Post) {
// add content type, if not set in the request
- if (request.headerField("content-type").isEmpty()) {
+ if (request.headerField("content-type").isEmpty() && ((request.d->uploadByteDevice && request.d->uploadByteDevice->size() > 0) || request.d->url.hasQuery())) {
//Content-Type is mandatory. We can't say anything about the encoding, but x-www-form-urlencoded is the most likely to work.
//This warning indicates a bug in application code not setting a required header.
//Note that if using QHttpMultipart, the content-type is set in QNetworkAccessManagerPrivate::prepareMultipart already
diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
index f4562cdb21..71b8237e03 100644
--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
+++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
@@ -63,6 +63,9 @@
#if defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID)
#include <link.h>
#endif
+#ifdef Q_OS_DARWIN
+#include "private/qcore_mac_p.h"
+#endif
#include <algorithm>
@@ -452,6 +455,15 @@ static QStringList libraryPathList()
# ifdef Q_OS_DARWIN
paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH"))
.split(QLatin1Char(':'), QString::SkipEmptyParts);
+
+ // search in .app/Contents/Frameworks
+ UInt32 packageType;
+ CFBundleGetPackageInfo(CFBundleGetMainBundle(), &packageType, NULL);
+ if (packageType == FOUR_CHAR_CODE('APPL')) {
+ QUrl bundleUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyBundleURL(CFBundleGetMainBundle())));
+ QUrl frameworksUrl = QUrl::fromCFURL(QCFType<CFURLRef>(CFBundleCopyPrivateFrameworksURL(CFBundleGetMainBundle())));
+ paths << bundleUrl.resolved(frameworksUrl).path();
+ }
# else
paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH"))
.split(QLatin1Char(':'), QString::SkipEmptyParts);
@@ -601,7 +613,13 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
}
#endif
+#ifndef Q_OS_DARWIN
// second attempt: find the development files libssl.so and libcrypto.so
+ //
+ // disabled on OS X/iOS:
+ // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
+ // attempt, _after_ <bundle>/Contents/Frameworks has been searched.
+ // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place.
libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1);
if (libcrypto->load() && libssl->load()) {
@@ -611,6 +629,7 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
libssl->unload();
libcrypto->unload();
}
+#endif
// third attempt: loop on the most common library paths and find libssl
QStringList sslList = findAllLibSsl();
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
index 43df311636..1fa5723d85 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2.cpp
@@ -612,6 +612,21 @@ void QGL2PaintEngineExPrivate::resetGLState()
#endif
}
+bool QGL2PaintEngineExPrivate::resetOpenGLContextActiveEngine()
+{
+ QOpenGLContext *guiGlContext = ctx->contextHandle();
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ if (guiGlContextPrivate && guiGlContextPrivate->active_engine) {
+ ctx->d_func()->refreshCurrentFbo();
+ guiGlContextPrivate->active_engine = 0;
+ return true;
+ }
+
+ return false;
+}
+
void QGL2PaintEngineEx::endNativePainting()
{
Q_D(QGL2PaintEngineEx);
@@ -2015,6 +2030,8 @@ bool QGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->ctx = d->device->context();
d->ctx->d_ptr->active_engine = this;
+ d->resetOpenGLContextActiveEngine();
+
const QSize sz = d->device->size();
d->width = sz.width();
d->height = sz.height();
@@ -2080,6 +2097,8 @@ bool QGL2PaintEngineEx::end()
ctx->d_ptr->active_engine = 0;
+ d->resetOpenGLContextActiveEngine();
+
d->resetGLState();
delete d->shaderManager;
@@ -2105,7 +2124,7 @@ void QGL2PaintEngineEx::ensureActive()
Q_D(QGL2PaintEngineEx);
QGLContext *ctx = d->ctx;
- if (isActive() && ctx->d_ptr->active_engine != this) {
+ if (isActive() && (ctx->d_ptr->active_engine != this || d->resetOpenGLContextActiveEngine())) {
ctx->d_ptr->active_engine = this;
d->needsSync = true;
}
diff --git a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
index 528bfdeeb9..ac1d63df17 100644
--- a/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
+++ b/src/opengl/gl2paintengineex/qpaintengineex_opengl2_p.h
@@ -191,6 +191,7 @@ public:
void updateTextureFilter(GLenum target, GLenum wrapMode, bool smoothPixmapTransform, GLuint id = GLuint(-1));
void resetGLState();
+ bool resetOpenGLContextActiveEngine();
// fill, stroke, drawTexture, drawPixmaps & drawCachedGlyphs are the main rendering entry-points,
// however writeClip can also be thought of as en entry point as it does similar things.
diff --git a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
index 211fad267f..8cd26f1ea4 100644
--- a/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
+++ b/src/opengl/gl2paintengineex/qtextureglyphcache_gl.cpp
@@ -167,6 +167,8 @@ void QGLTextureGlyphCache::resizeTextureData(int width, int height)
// ### the QTextureGlyphCache API needs to be reworked to allow
// ### resizeTextureData to fail
+ ctx->d_ptr->refreshCurrentFbo();
+
funcs->glBindFramebuffer(GL_FRAMEBUFFER, m_textureResource->m_fbo);
GLuint tmp_texture;
diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp
index 1e49d95087..35f08e0092 100644
--- a/src/opengl/qgl.cpp
+++ b/src/opengl/qgl.cpp
@@ -510,6 +510,35 @@ void QGLContextPrivate::setupSharing() {
}
}
+void QGLContextPrivate::refreshCurrentFbo()
+{
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ // if QOpenGLFramebufferObjects have been used in the mean-time, we've lost our cached value
+ if (guiGlContextPrivate && guiGlContextPrivate->qgl_current_fbo_invalid) {
+ GLint current;
+ QOpenGLFunctions *funcs = qgl_functions();
+ funcs->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &current);
+
+ current_fbo = current;
+
+ guiGlContextPrivate->qgl_current_fbo_invalid = false;
+ }
+}
+
+void QGLContextPrivate::setCurrentFbo(GLuint fbo)
+{
+ current_fbo = fbo;
+
+ QOpenGLContextPrivate *guiGlContextPrivate =
+ guiGlContext ? QOpenGLContextPrivate::get(guiGlContext) : 0;
+
+ if (guiGlContextPrivate)
+ guiGlContextPrivate->qgl_current_fbo_invalid = false;
+}
+
+
/*!
\fn bool QGLFormat::doubleBuffer() const
diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h
index c4151a3d34..4cf656fd86 100644
--- a/src/opengl/qgl_p.h
+++ b/src/opengl/qgl_p.h
@@ -238,6 +238,8 @@ public:
bool ownContext;
void setupSharing();
+ void refreshCurrentFbo();
+ void setCurrentFbo(GLuint fbo);
QGLFormat glFormat;
QGLFormat reqFormat;
diff --git a/src/opengl/qglframebufferobject.cpp b/src/opengl/qglframebufferobject.cpp
index 4ef50e9334..4537f5bfae 100644
--- a/src/opengl/qglframebufferobject.cpp
+++ b/src/opengl/qglframebufferobject.cpp
@@ -472,6 +472,8 @@ void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,
if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return;
+ ctx->d_ptr->refreshCurrentFbo();
+
size = sz;
target = texture_target;
// texture dimensions
@@ -1027,7 +1029,7 @@ bool QGLFramebufferObject::bind()
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
d->valid = d->checkFramebufferStatus();
if (d->valid && current)
- current->d_ptr->current_fbo = d->fbo();
+ current->d_ptr->setCurrentFbo(d->fbo());
return d->valid;
}
@@ -1060,7 +1062,7 @@ bool QGLFramebufferObject::release()
#endif
if (current) {
- current->d_ptr->current_fbo = current->d_ptr->default_fbo;
+ current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo);
d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo);
}
@@ -1109,6 +1111,20 @@ QGLFramebufferObjectFormat QGLFramebufferObject::format() const
Returns the contents of this framebuffer object as a QImage.
+ The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used
+ only when internalTextureFormat() is set to \c GL_RGB.
+
+ If the rendering in the framebuffer was not done with premultiplied alpha in mind,
+ create a wrapper QImage with a non-premultiplied format. This is necessary before
+ performing operations like QImage::save() because otherwise the image data would get
+ unpremultiplied, even though it was not premultiplied in the first place. To create
+ such a wrapper without performing a copy of the pixel data, do the following:
+
+ \code
+ QImage fboImage(fbo.toImage());
+ QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);
+ \endcode
+
On QNX the back buffer is not preserved when a buffer swap occures. So this function
might return old content.
*/
@@ -1173,7 +1189,7 @@ bool QGLFramebufferObject::bindDefault()
if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
return false;
- ctx->d_ptr->current_fbo = ctx->d_ptr->default_fbo;
+ ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo);
functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo);
#ifdef QT_DEBUG
} else {
@@ -1320,7 +1336,12 @@ bool QGLFramebufferObject::isBound() const
{
Q_D(const QGLFramebufferObject);
const QGLContext *current = QGLContext::currentContext();
- return current ? current->d_ptr->current_fbo == d->fbo() : false;
+ if (current) {
+ current->d_ptr->refreshCurrentFbo();
+ return current->d_ptr->current_fbo == d->fbo();
+ }
+
+ return false;
}
/*!
@@ -1400,6 +1421,8 @@ void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const Q
const int ty0 = th - (targetRect.top() + targetRect.height());
const int ty1 = th - targetRect.top();
+ ctx->d_ptr->refreshCurrentFbo();
+
functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
diff --git a/src/opengl/qglpaintdevice.cpp b/src/opengl/qglpaintdevice.cpp
index 40cc7bb71d..c07d0a761b 100644
--- a/src/opengl/qglpaintdevice.cpp
+++ b/src/opengl/qglpaintdevice.cpp
@@ -74,6 +74,8 @@ void QGLPaintDevice::beginPaint()
QGLContext *ctx = context();
ctx->makeCurrent();
+ ctx->d_func()->refreshCurrentFbo();
+
// Record the currently bound FBO so we can restore it again
// in endPaint() and bind this device's FBO
//
@@ -85,7 +87,7 @@ void QGLPaintDevice::beginPaint()
m_previousFBO = ctx->d_func()->current_fbo;
if (m_previousFBO != m_thisFBO) {
- ctx->d_ptr->current_fbo = m_thisFBO;
+ ctx->d_func()->setCurrentFbo(m_thisFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
}
@@ -102,8 +104,10 @@ void QGLPaintDevice::ensureActiveTarget()
if (ctx != QGLContext::currentContext())
ctx->makeCurrent();
+ ctx->d_func()->refreshCurrentFbo();
+
if (ctx->d_ptr->current_fbo != m_thisFBO) {
- ctx->d_ptr->current_fbo = m_thisFBO;
+ ctx->d_func()->setCurrentFbo(m_thisFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_thisFBO);
}
@@ -114,8 +118,11 @@ void QGLPaintDevice::endPaint()
{
// Make sure the FBO bound at beginPaint is re-bound again here:
QGLContext *ctx = context();
+
+ ctx->d_func()->refreshCurrentFbo();
+
if (m_previousFBO != ctx->d_func()->current_fbo) {
- ctx->d_ptr->current_fbo = m_previousFBO;
+ ctx->d_func()->setCurrentFbo(m_previousFBO);
ctx->contextHandle()->functions()->glBindFramebuffer(GL_FRAMEBUFFER, m_previousFBO);
}
diff --git a/src/opengl/qglpixelbuffer.cpp b/src/opengl/qglpixelbuffer.cpp
index 56bfaebe4f..63b624aea2 100644
--- a/src/opengl/qglpixelbuffer.cpp
+++ b/src/opengl/qglpixelbuffer.cpp
@@ -344,6 +344,8 @@ void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
QOpenGLExtensions extensions(ctx->contextHandle());
+ ctx->d_ptr->refreshCurrentFbo();
+
if (d->blit_fbo) {
QOpenGLFramebufferObject::blitFramebuffer(d->blit_fbo, d->fbo);
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->blit_fbo->handle());
diff --git a/src/platformsupport/fontdatabases/basic/basic.pri b/src/platformsupport/fontdatabases/basic/basic.pri
index 88be809cd8..c2b882ed5a 100644
--- a/src/platformsupport/fontdatabases/basic/basic.pri
+++ b/src/platformsupport/fontdatabases/basic/basic.pri
@@ -17,6 +17,7 @@ contains(QT_CONFIG, freetype) {
$$QT_FREETYPE_DIR/src/base/ftbbox.c \
$$QT_FREETYPE_DIR/src/base/ftdebug.c \
$$QT_FREETYPE_DIR/src/base/ftglyph.c \
+ $$QT_FREETYPE_DIR/src/base/ftlcdfil.c \
$$QT_FREETYPE_DIR/src/base/ftinit.c \
$$QT_FREETYPE_DIR/src/base/ftmm.c \
$$QT_FREETYPE_DIR/src/base/fttype1.c \
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
index b2e2131a92..abbfd445a5 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux.cpp
@@ -269,6 +269,18 @@ QStringList QOfonoDataConnectionManagerInterface::contexts()
return contextList;
}
+PathPropertiesList QOfonoDataConnectionManagerInterface::contextsWithProperties()
+{
+ if (contextListProperties.isEmpty()) {
+ QDBusPendingReply<PathPropertiesList > reply = call(QLatin1String("GetContexts"));
+ reply.waitForFinished();
+ if (!reply.isError()) {
+ contextListProperties = reply.value();
+ }
+ }
+ return contextListProperties;
+}
+
bool QOfonoDataConnectionManagerInterface::roamingAllowed()
{
QVariant var = getProperty(QStringLiteral("RoamingAllowed"));
diff --git a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
index 0ed00d94ff..3b97e06dd3 100644
--- a/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
+++ b/src/plugins/bearer/linux_common/qofonoservice_linux_p.h
@@ -153,6 +153,7 @@ public:
~QOfonoDataConnectionManagerInterface();
QStringList contexts();
+ PathPropertiesList contextsWithProperties();
bool roamingAllowed();
QVariant getProperty(const QString &);
QString bearer();
@@ -162,6 +163,7 @@ private:
QVariantMap getProperties();
QVariantMap propertiesMap;
QStringList contextList;
+ PathPropertiesList contextListProperties;
private slots:
void propertyChanged(const QString &, const QDBusVariant &value);
};
diff --git a/src/plugins/bearer/networkmanager/main.cpp b/src/plugins/bearer/networkmanager/main.cpp
index f416bb42a6..3576ddc37c 100644
--- a/src/plugins/bearer/networkmanager/main.cpp
+++ b/src/plugins/bearer/networkmanager/main.cpp
@@ -66,10 +66,7 @@ QBearerEngine *QNetworkManagerEnginePlugin::create(const QString &key) const
{
if (key == QLatin1String("networkmanager")) {
QNetworkManagerEngine *engine = new QNetworkManagerEngine;
- if (engine->networkManagerAvailable())
- return engine;
- else
- delete engine;
+ return engine;
}
return 0;
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
index a8244f05cf..f0977b4735 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -56,29 +56,34 @@ QT_BEGIN_NAMESPACE
QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent)
: QBearerEngineImpl(parent),
- managerInterface(new QNetworkManagerInterface(this)),
- systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE, this)),
- ofonoManager(new QOfonoManagerInterface(this))
+ managerInterface(NULL),
+ systemSettings(NULL),
+ ofonoManager(NULL),
+ nmAvailable(false)
{
-
- if (!managerInterface->isValid())
- return;
-
qDBusRegisterMetaType<QNmSettingsMap>();
- connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)),
- this, SLOT(deviceAdded(QDBusObjectPath)));
- connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)),
- this, SLOT(deviceRemoved(QDBusObjectPath)));
- connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
- this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
- connect(managerInterface, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
- this, SLOT(interfacePropertiesChanged(QMap<QString,QVariant>)));
- managerInterface->setConnections();
-
- connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)),
- this, SLOT(newConnection(QDBusObjectPath)));
- systemSettings->setConnections();
+ nmWatcher = new QDBusServiceWatcher(NM_DBUS_SERVICE,QDBusConnection::systemBus(),
+ QDBusServiceWatcher::WatchForRegistration |
+ QDBusServiceWatcher::WatchForUnregistration, this);
+ connect(nmWatcher, SIGNAL(serviceRegistered(QString)),
+ this, SLOT(nmRegistered(QString)));
+ connect(nmWatcher, SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(nmUnRegistered(QString)));
+
+ ofonoWatcher = new QDBusServiceWatcher("org.ofono",QDBusConnection::systemBus(),
+ QDBusServiceWatcher::WatchForRegistration |
+ QDBusServiceWatcher::WatchForUnregistration, this);
+ connect(ofonoWatcher, SIGNAL(serviceRegistered(QString)),
+ this, SLOT(ofonoRegistered(QString)));
+ connect(ofonoWatcher, SIGNAL(serviceUnregistered(QString)),
+ this, SLOT(ofonoUnRegistered(QString)));
+
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono"))
+ ofonoRegistered();
+
+ if (QDBusConnection::systemBus().interface()->isServiceRegistered(NM_DBUS_SERVICE))
+ nmRegistered();
}
QNetworkManagerEngine::~QNetworkManagerEngine()
@@ -105,15 +110,13 @@ QNetworkManagerEngine::~QNetworkManagerEngine()
void QNetworkManagerEngine::initialize()
{
- QMutexLocker locker(&mutex);
+ if (nmAvailable)
+ setupConfigurations();
+}
- if (ofonoManager->isValid()) {
- Q_FOREACH (const QString &modem, ofonoManager->getModems()) {
- QOfonoDataConnectionManagerInterface *ofonoContextManager
- = new QOfonoDataConnectionManagerInterface(modem,this);
- ofonoContextManagers.insert(modem, ofonoContextManager);
- }
- }
+void QNetworkManagerEngine::setupConfigurations()
+{
+ QMutexLocker locker(&mutex);
// Get active connections.
foreach (const QDBusObjectPath &acPath, managerInterface->activeConnections()) {
@@ -151,7 +154,7 @@ void QNetworkManagerEngine::initialize()
bool QNetworkManagerEngine::networkManagerAvailable() const
{
- return managerInterface->isValid();
+ return nmAvailable;
}
QString QNetworkManagerEngine::getInterfaceFromId(const QString &settingsPath)
@@ -180,6 +183,9 @@ void QNetworkManagerEngine::connectToId(const QString &id)
const QString settingsPath = connection->connectionInterface()->path();
QString specificPath = configuredAccessPoints.key(settingsPath);
+ if (isConnectionActive(settingsPath))
+ return;
+
QHashIterator<QString, QNetworkManagerInterfaceDevice*> i(interfaceDevices);
while (i.hasNext()) {
i.next();
@@ -229,7 +235,7 @@ void QNetworkManagerEngine::disconnectFromId(const QString &id)
void QNetworkManagerEngine::requestUpdate()
{
- if (managerInterface->wirelessEnabled()) {
+ if (managerInterface && managerInterface->wirelessEnabled()) {
QHashIterator<QString, QNetworkManagerInterfaceDeviceWireless *> i(wirelessDevices);
while (i.hasNext()) {
i.next();
@@ -282,8 +288,9 @@ void QNetworkManagerEngine::interfacePropertiesChanged(const QMap<QString, QVari
if (ptr) {
ptr->mutex.lock();
if (activeConnection->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED &&
- ptr->state != QNetworkConfiguration::Active) {
- ptr->state = QNetworkConfiguration::Active;
+ (ptr->state & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
+
+ ptr->state |= QNetworkConfiguration::Active;
if (activeConnectionsList.value(id) && activeConnectionsList.value(id)->defaultRoute()
&& managerInterface->state() < QNetworkManagerInterface::NM_STATE_CONNECTED_GLOBAL) {
@@ -339,23 +346,25 @@ void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QMap<QString
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
if (ptr) {
- ptr->mutex.lock();
- if (properties.value("State").toUInt() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
- QStringList devices = activeConnection->devices();
- if (!devices.isEmpty()) {
- QNetworkManagerInterfaceDevice device(devices.at(0),this);
- connectionInterfaces.insert(id,device.networkInterface());
- }
+ if (properties.contains(QStringLiteral("State"))) {
+ ptr->mutex.lock();
+ if (properties.value("State").toUInt() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
+ QStringList devices = activeConnection->devices();
+ if (!devices.isEmpty()) {
+ QNetworkManagerInterfaceDevice device(devices.at(0),this);
+ connectionInterfaces.insert(id,device.networkInterface());
+ }
- ptr->state |= QNetworkConfiguration::Active;
- ptr->mutex.unlock();
+ ptr->state |= QNetworkConfiguration::Active;
+ ptr->mutex.unlock();
- locker.unlock();
- emit configurationChanged(ptr);
- locker.relock();
- } else {
- connectionInterfaces.remove(id);
- ptr->mutex.unlock();
+ locker.unlock();
+ emit configurationChanged(ptr);
+ locker.relock();
+ } else {
+ connectionInterfaces.remove(id);
+ ptr->mutex.unlock();
+ }
}
}
}
@@ -403,9 +412,6 @@ void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path)
connect(wirelessDevice,SIGNAL(scanDone()),this,SLOT(scanFinished()));
wirelessDevice->setConnections();
- foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints())
- newAccessPoint(apPath.path());
-
wirelessDevices.insert(path.path(), wirelessDevice);
}
@@ -518,14 +524,9 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
parseConnection(settingsPath, connection->getSettings());
// Check if connection is active.
- QHashIterator<QString, QNetworkManagerConnectionActive*> i(activeConnectionsList);
- while (i.hasNext()) {
- i.next();
- if (i.value()->connection().path() == settingsPath) {
- cpPriv->state |= QNetworkConfiguration::Active;
- break;
- }
- }
+ if (isConnectionActive(settingsPath))
+ cpPriv->state |= QNetworkConfiguration::Active;
+
if (deviceType == DEVICE_TYPE_ETHERNET) {
QHashIterator<QString, QNetworkManagerInterfaceDevice*> i(interfaceDevices);
while (i.hasNext()) {
@@ -539,12 +540,36 @@ void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
}
}
}
+
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
locker.unlock();
emit configurationAdded(ptr);
}
+bool QNetworkManagerEngine::isConnectionActive(const QString &settingsPath)
+{
+ QHashIterator<QString, QNetworkManagerConnectionActive*> i(activeConnectionsList);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value()->connection().path() == settingsPath) {
+ if (i.value()->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATING
+ || i.value()->state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
+ return true;
+ } else {
+ break;
+ }
+ }
+ }
+
+ QNetworkManagerSettingsConnection *settingsConnection = connectionFromId(settingsPath);
+ if (settingsConnection->getType() == DEVICE_TYPE_MODEM) {
+ return isActiveContext(settingsConnection->connectionInterface()->path());
+ }
+
+ return false;
+}
+
void QNetworkManagerEngine::removeConnection(const QString &path)
{
QMutexLocker locker(&mutex);
@@ -652,7 +677,6 @@ void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
void QNetworkManagerEngine::newAccessPoint(const QString &path)
{
QMutexLocker locker(&mutex);
-
QNetworkManagerInterfaceAccessPoint *accessPoint =
new QNetworkManagerInterfaceAccessPoint(path,this);
@@ -683,6 +707,9 @@ void QNetworkManagerEngine::newAccessPoint(const QString &path)
ptr->mutex.lock();
QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined;
ptr->state = (flag | QNetworkConfiguration::Discovered);
+
+ if (isConnectionActive(settingsPath))
+ ptr->state = (flag | QNetworkConfiguration::Active);
ptr->mutex.unlock();
locker.unlock();
@@ -762,7 +789,6 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
QMutexLocker locker(&mutex);
QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate;
cpPriv->name = map.value("connection").value("id").toString();
-
cpPriv->isValid = true;
cpPriv->id = settingsPath;
cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
@@ -811,18 +837,46 @@ QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QStri
}
} else if (connectionType == QLatin1String("gsm")) {
- const QString contextPath = map.value("connection").value("id").toString();
- cpPriv->name = contextName(contextPath);
- cpPriv->bearerType = currentBearerType(contextPath);
-
- if (map.value("connection").contains("timestamp")) {
- cpPriv->state |= QNetworkConfiguration::Discovered;
+ const QString connectionPath = map.value("connection").value("id").toString();
+ cpPriv->name = contextName(connectionPath);
+ cpPriv->bearerType = currentBearerType(connectionPath);
+
+ if (ofonoManager && ofonoManager->isValid()) {
+ const QString contextPart = connectionPath.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ const QString path = i.key() +"/"+contextPart;
+ if (isActiveContext(path)) {
+ cpPriv->state |= QNetworkConfiguration::Active;
+ break;
+ }
+ }
}
}
return cpPriv;
}
+bool QNetworkManagerEngine::isActiveContext(const QString &contextPath)
+{
+ if (ofonoManager && ofonoManager->isValid()) {
+ const QString contextPart = contextPath.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ PathPropertiesList list = i.value()->contextsWithProperties();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).path.path().contains(contextPart)) {
+ return list.at(i).properties.value(QStringLiteral("Active")).toBool();
+
+ }
+ }
+ }
+ }
+ return false;
+}
+
QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const QString &id) const
{
for (int i = 0; i < connections.count(); ++i) {
@@ -967,53 +1021,111 @@ QNetworkConfigurationPrivatePointer QNetworkManagerEngine::defaultConfiguration(
QNetworkConfiguration::BearerType QNetworkManagerEngine::currentBearerType(const QString &id)
{
- if (ofonoManager->isValid()) {
- QString contextPart = id.section('/', -1);
-
- QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
- while (i.hasNext()) {
- i.next();
- QString contextPath = i.key() +"/"+contextPart;
- if (i.value()->contexts().contains(contextPath)) {
-
- QString bearer = i.value()->bearer();
- if (bearer == QStringLiteral("gsm")) {
- return QNetworkConfiguration::Bearer2G;
- } else if (bearer == QStringLiteral("edge")) {
- return QNetworkConfiguration::Bearer2G;
- } else if (bearer == QStringLiteral("umts")) {
- return QNetworkConfiguration::BearerWCDMA;
- } else if (bearer == QStringLiteral("hspa")
- || bearer == QStringLiteral("hsdpa")
- || bearer == QStringLiteral("hsupa")) {
- return QNetworkConfiguration::BearerHSPA;
- } else if (bearer == QStringLiteral("lte")) {
- return QNetworkConfiguration::BearerLTE;
- }
+ QString contextPart = id.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ QString contextPath = i.key() +"/"+contextPart;
+
+ if (i.value()->contexts().contains(contextPath)) {
+
+ QString bearer = i.value()->bearer();
+
+ if (bearer == QStringLiteral("gsm")) {
+ return QNetworkConfiguration::Bearer2G;
+ } else if (bearer == QStringLiteral("edge")) {
+ return QNetworkConfiguration::Bearer2G;
+ } else if (bearer == QStringLiteral("umts")) {
+ return QNetworkConfiguration::BearerWCDMA;
+ } else if (bearer == QStringLiteral("hspa")
+ || bearer == QStringLiteral("hsdpa")
+ || bearer == QStringLiteral("hsupa")) {
+ return QNetworkConfiguration::BearerHSPA;
+ } else if (bearer == QStringLiteral("lte")) {
+ return QNetworkConfiguration::BearerLTE;
}
}
}
+
return QNetworkConfiguration::BearerUnknown;
}
QString QNetworkManagerEngine::contextName(const QString &path)
{
- if (ofonoManager->isValid()) {
- QString contextPart = path.section('/', -1);
- QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
- while (i.hasNext()) {
- i.next();
- Q_FOREACH (const QString &oContext, i.value()->contexts()) {
- if (oContext.contains(contextPart)) {
- QOfonoConnectionContextInterface contextInterface(oContext,this);
- return contextInterface.name();
- }
+ QString contextPart = path.section('/', -1);
+ QHashIterator<QString, QOfonoDataConnectionManagerInterface*> i(ofonoContextManagers);
+ while (i.hasNext()) {
+ i.next();
+ PathPropertiesList list = i.value()->contextsWithProperties();
+ for (int i = 0; i < list.size(); ++i) {
+ if (list.at(i).path.path().contains(contextPart)) {
+ return list.at(i).properties.value(QStringLiteral("Name")).toString();
}
}
}
return path;
}
+void QNetworkManagerEngine::nmRegistered(const QString &)
+{
+ if (ofonoManager) {
+ delete ofonoManager;
+ ofonoManager = NULL;
+ }
+ managerInterface = new QNetworkManagerInterface(this);
+ systemSettings = new QNetworkManagerSettings(NM_DBUS_SERVICE, this);
+
+ connect(managerInterface, SIGNAL(deviceAdded(QDBusObjectPath)),
+ this, SLOT(deviceAdded(QDBusObjectPath)));
+ connect(managerInterface, SIGNAL(deviceRemoved(QDBusObjectPath)),
+ this, SLOT(deviceRemoved(QDBusObjectPath)));
+ connect(managerInterface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
+ this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
+ connect(managerInterface, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
+ this, SLOT(interfacePropertiesChanged(QMap<QString,QVariant>)));
+ managerInterface->setConnections();
+
+ connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)),
+ this, SLOT(newConnection(QDBusObjectPath)));
+ systemSettings->setConnections();
+ nmAvailable = true;
+
+ setupConfigurations();
+}
+
+void QNetworkManagerEngine::nmUnRegistered(const QString &)
+{
+ if (systemSettings) {
+ delete systemSettings;
+ systemSettings = NULL;
+ }
+ if (managerInterface) {
+ delete managerInterface;
+ managerInterface = NULL;
+ }
+}
+
+void QNetworkManagerEngine::ofonoRegistered(const QString &)
+{
+ if (ofonoManager) {
+ delete ofonoManager;
+ ofonoManager = NULL;
+ }
+ ofonoManager = new QOfonoManagerInterface(this);
+ if (ofonoManager && ofonoManager->isValid()) {
+ Q_FOREACH (const QString &modem, ofonoManager->getModems()) {
+ QOfonoDataConnectionManagerInterface *ofonoContextManager
+ = new QOfonoDataConnectionManagerInterface(modem,this);
+ ofonoContextManagers.insert(modem, ofonoContextManager);
+ }
+ }
+}
+
+void QNetworkManagerEngine::ofonoUnRegistered(const QString &)
+{
+ ofonoContextManagers.clear();
+}
+
QT_END_NAMESPACE
#endif // QT_NO_DBUS
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
index 671ed80dab..da6af14c00 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
@@ -109,6 +109,12 @@ private Q_SLOTS:
void wiredCarrierChanged(bool);
+ void nmRegistered(const QString &serviceName = QString());
+ void nmUnRegistered(const QString &serviceName = QString());
+
+ void ofonoRegistered(const QString &serviceName = QString());
+ void ofonoUnRegistered(const QString &serviceName = QString());
+
private:
QNetworkConfigurationPrivate *parseConnection(const QString &settingsPath,
const QNmSettingsMap &map);
@@ -132,6 +138,13 @@ private:
QNetworkConfiguration::BearerType currentBearerType(const QString &id);
QString contextName(const QString &path);
+ bool isConnectionActive(const QString &settingsPath);
+ QDBusServiceWatcher *ofonoWatcher;
+ QDBusServiceWatcher *nmWatcher;
+
+ bool isActiveContext(const QString &contextPath);
+ bool nmAvailable;
+ void setupConfigurations();
};
QT_END_NAMESPACE
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
index dc3b71ec8e..fad94f069d 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
@@ -688,6 +688,15 @@ QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(c
QLatin1String(NM_DBUS_INTERFACE_DEVICE_WIRELESS),
QLatin1String("PropertiesChanged"),
this,SLOT(propertiesSwap(QMap<QString,QVariant>)));
+
+ QDBusPendingReply<QList<QDBusObjectPath> > reply
+ = d->connectionInterface->asyncCall(QLatin1String("GetAccessPoints"));
+
+ QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(reply);
+ connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SLOT(accessPointsFinished(QDBusPendingCallWatcher*)));
+
+
d->valid = true;
}
@@ -749,6 +758,19 @@ bool QNetworkManagerInterfaceDeviceWireless::setConnections()
return allOk;
}
+void QNetworkManagerInterfaceDeviceWireless::accessPointsFinished(QDBusPendingCallWatcher *watcher)
+{
+ QDBusPendingReply<QList<QDBusObjectPath> > reply(*watcher);
+ watcher->deleteLater();
+ if (!reply.isError()) {
+ accessPointsList = reply.value();
+ }
+
+ for (int i = 0; i < accessPointsList.size(); i++) {
+ Q_EMIT accessPointAdded(accessPointsList.at(i).path());
+ }
+}
+
QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() const
{
return d->connectionInterface;
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
index da909c443a..e645159d71 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -369,6 +369,8 @@ private Q_SLOTS:
void slotAccessPointAdded(QDBusObjectPath);
void slotAccessPointRemoved(QDBusObjectPath);
+ void accessPointsFinished(QDBusPendingCallWatcher *watcher);
+
private:
QNetworkManagerInterfaceDeviceWirelessPrivate *d;
QVariantMap propertyMap;
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 791b0805d0..251fe9485c 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -323,17 +323,22 @@ NSMenuItem *QCocoaMenuItem::sync()
text += QLatin1String(" (") + accel.toString(QKeySequence::NativeText) + QLatin1String(")");
QString finalString = qt_mac_removeMnemonics(text);
+ bool useAttributedTitle = false;
// Cocoa Font and title
if (m_font.resolve()) {
NSFont *customMenuFont = [NSFont fontWithName:QCFString::toNSString(m_font.family())
size:m_font.pointSize()];
- NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
- NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
- NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
- NSAttributedString *str = [[[NSAttributedString alloc] initWithString:QCFString::toNSString(finalString)
- attributes:attributes] autorelease];
- [m_native setAttributedTitle: str];
- } else {
+ if (customMenuFont) {
+ NSArray *keys = [NSArray arrayWithObjects:NSFontAttributeName, nil];
+ NSArray *objects = [NSArray arrayWithObjects:customMenuFont, nil];
+ NSDictionary *attributes = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
+ NSAttributedString *str = [[[NSAttributedString alloc] initWithString:QCFString::toNSString(finalString)
+ attributes:attributes] autorelease];
+ [m_native setAttributedTitle: str];
+ useAttributedTitle = true;
+ }
+ }
+ if (!useAttributedTitle) {
[m_native setTitle: QCFString::toNSString(finalString)];
}
diff --git a/src/plugins/platforms/ios/quiview_accessibility.mm b/src/plugins/platforms/ios/quiview_accessibility.mm
index 6565e08302..7e1cb9a4fd 100644
--- a/src/plugins/platforms/ios/quiview_accessibility.mm
+++ b/src/plugins/platforms/ios/quiview_accessibility.mm
@@ -48,7 +48,7 @@
- (void)createAccessibleElement:(QAccessibleInterface *)iface
{
- if (!iface || iface->state().invisible)
+ if (!iface || iface->state().invisible || (iface->text(QAccessible::Name).isEmpty() && iface->text(QAccessible::Value).isEmpty() && iface->text(QAccessible::Description).isEmpty()))
return;
QAccessible::Id accessibleId = QAccessible::uniqueId(iface);
UIAccessibilityElement *elem = [[QMacAccessibilityElement alloc] initWithId: accessibleId withAccessibilityContainer: self];
@@ -60,12 +60,9 @@
if (!iface)
return;
- if (iface->childCount() == 0) {
- [self createAccessibleElement: iface];
- } else {
- for (int i = 0; i < iface->childCount(); ++i)
- [self createAccessibleContainer: iface->child(i)];
- }
+ [self createAccessibleElement: iface];
+ for (int i = 0; i < iface->childCount(); ++i)
+ [self createAccessibleContainer: iface->child(i)];
}
- (void)initAccessibility
diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp
index cfa5914ff8..d8ccb8cd56 100644
--- a/src/plugins/platforms/windows/qwindowsfontengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp
@@ -804,10 +804,8 @@ static bool addGlyphToPath(glyph_t glyph, const QFixedPoint &position, HDC hdc,
uint format = GGO_METRICS;
if (ttf)
format |= GGO_GLYPH_INDEX;
- int res = GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat);
- if (res == GDI_ERROR) {
+ if (GetGlyphOutline(hdc, glyph, format, &gMetric, 0, 0, &mat) == GDI_ERROR)
return false;
- }
// #### obey scale
*metric = glyph_metrics_t(gMetric.gmptGlyphOrigin.x, -gMetric.gmptGlyphOrigin.y,
(int)gMetric.gmBlackBoxX, (int)gMetric.gmBlackBoxY,
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index f31ecf8e03..7286b6b89b 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -471,6 +471,7 @@ public:
QXcbEventReader *eventReader() const { return m_reader; }
+ bool canGrab() const { return m_canGrabServer; }
protected:
bool event(QEvent *e) Q_DECL_OVERRIDE;
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 52269bafea..3818494d99 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -92,11 +92,11 @@
QT_BEGIN_NAMESPACE
-#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
// Find out if our parent process is gdb by looking at the 'exe' symlink under /proc,.
// or, for older Linuxes, read out 'cmdline'.
static bool runningUnderDebugger()
{
+#if defined(QT_DEBUG) && defined(Q_OS_LINUX)
const QString parentProc = QLatin1String("/proc/") + QString::number(getppid());
const QFileInfo parentProcExe(parentProc + QLatin1String("/exe"));
if (parentProcExe.isSymLink())
@@ -113,12 +113,15 @@ static bool runningUnderDebugger()
s += c;
}
return s == "gdb";
-}
+#else
+ return false;
#endif
+}
QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char **argv)
: m_services(new QGenericUnixServices)
, m_instanceName(0)
+ , m_canGrab(true)
{
qRegisterMetaType<QXcbWindow*>();
#ifdef XCB_USE_XLIB
@@ -126,16 +129,10 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
#endif
m_nativeInterface.reset(new QXcbNativeInterface);
- bool canGrab = true;
- #if defined(QT_DEBUG) && defined(Q_OS_LINUX)
- canGrab = !runningUnderDebugger();
- #endif
- static bool canNotGrabEnv = qgetenv("QT_XCB_NO_GRAB_SERVER").length();
- if (canNotGrabEnv)
- canGrab = false;
-
// Parse arguments
const char *displayName = 0;
+ bool noGrabArg = false;
+ bool doGrabArg = false;
if (argc) {
int j = 1;
for (int i = 1; i < argc; i++) {
@@ -146,13 +143,35 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
displayName = argv[++i];
else if (arg == "-name" && i < argc - 1)
m_instanceName = argv[++i];
+ else if (arg == "-nograb")
+ noGrabArg = true;
+ else if (arg == "-dograb")
+ doGrabArg = true;
else
argv[j++] = argv[i];
}
argc = j;
} // argc
- m_connections << new QXcbConnection(m_nativeInterface.data(), canGrab, displayName);
+ bool underDebugger = runningUnderDebugger();
+ if (noGrabArg && doGrabArg && underDebugger) {
+ qWarning() << "Both -nograb and -dograb command line arguments specified. Please pick one. -nograb takes prcedence";
+ doGrabArg = false;
+ }
+
+#if defined(QT_DEBUG)
+ if (!noGrabArg && !doGrabArg && underDebugger) {
+ qDebug("Qt: gdb: -nograb added to command-line options.\n"
+ "\t Use the -dograb option to enforce grabbing.");
+ }
+#endif
+ m_canGrab = (!underDebugger && noGrabArg) || (underDebugger && doGrabArg);
+
+ static bool canNotGrabEnv = qEnvironmentVariableIsSet("QT_XCB_NO_GRAB_SERVER");
+ if (canNotGrabEnv)
+ m_canGrab = false;
+
+ m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName);
for (int i = 0; i < parameters.size() - 1; i += 2) {
#ifdef Q_XCB_DEBUG
@@ -408,12 +427,14 @@ QVariant QXcbIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
case QPlatformIntegration::StartDragTime:
case QPlatformIntegration::KeyboardAutoRepeatRate:
case QPlatformIntegration::PasswordMaskDelay:
- case QPlatformIntegration::FontSmoothingGamma:
case QPlatformIntegration::StartDragVelocity:
case QPlatformIntegration::UseRtlExtensions:
case QPlatformIntegration::PasswordMaskCharacter:
// TODO using various xcb, gnome or KDE settings
break; // Not implemented, use defaults
+ case QPlatformIntegration::FontSmoothingGamma:
+ // Match Qt 4.8 text rendering, and rendering of other X11 toolkits.
+ return qreal(1.0);
case QPlatformIntegration::StartDragDistance: {
// The default (in QPlatformTheme::defaultThemeHint) is 10 pixels, but
// on a high-resolution screen it makes sense to increase it.
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index ffb068ecb3..db6ad541ea 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -117,6 +117,7 @@ private:
mutable QByteArray m_wmClass;
const char *m_instanceName;
+ bool m_canGrab;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 5d3206b097..85af8ee1d2 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2170,6 +2170,9 @@ void QXcbWindow::updateSyncRequestCounter()
bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
{
+ if (grab && !connection()->canGrab())
+ return false;
+
if (!grab) {
xcb_ungrab_keyboard(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
@@ -2185,6 +2188,9 @@ bool QXcbWindow::setKeyboardGrabEnabled(bool grab)
bool QXcbWindow::setMouseGrabEnabled(bool grab)
{
+ if (grab && !connection()->canGrab())
+ return false;
+
if (!grab) {
xcb_ungrab_pointer(xcb_connection(), XCB_TIME_CURRENT_TIME);
return true;
diff --git a/src/widgets/accessible/simplewidgets.cpp b/src/widgets/accessible/simplewidgets.cpp
index ade5cfe3dc..41692d11bd 100644
--- a/src/widgets/accessible/simplewidgets.cpp
+++ b/src/widgets/accessible/simplewidgets.cpp
@@ -414,12 +414,14 @@ QString QAccessibleDisplay::text(QAccessible::Text t) const
if (qobject_cast<QLabel*>(object())) {
QLabel *label = qobject_cast<QLabel*>(object());
str = label->text();
+#ifndef QT_NO_TEXTHTMLPARSER
if (label->textFormat() == Qt::RichText
|| (label->textFormat() == Qt::AutoText && Qt::mightBeRichText(str))) {
QTextDocument doc;
doc.setHtml(str);
str = doc.toPlainText();
}
+#endif
if (label->buddy())
str = qt_accStripAmp(str);
#ifndef QT_NO_LCDNUMBER
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index 300e2f492b..03f22a270f 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -2447,7 +2447,12 @@ void QGraphicsItemPrivate::setVisibleHelper(bool newVisible, bool explicitly,
Items are visible by default; it is unnecessary to call
setVisible() on a new item.
- \sa isVisible(), show(), hide()
+ \note An item with opacity set to 0 will still be considered visible,
+ although it will be treated like an invisible item: mouse events will pass
+ through it, it will not be included in the items returned by
+ QGraphicsView::items(), and so on. However, the item will retain the focus.
+
+ \sa isVisible(), show(), hide(), setOpacity()
*/
void QGraphicsItem::setVisible(bool visible)
{
@@ -2715,7 +2720,11 @@ qreal QGraphicsItem::effectiveOpacity() const
with the parent: ItemIgnoresParentOpacity and
ItemDoesntPropagateOpacityToChildren.
- \sa opacity(), effectiveOpacity()
+ \note Setting the opacity of an item to 0 will not make the item invisible
+ (according to isVisible()), but the item will be treated like an invisible
+ one. See the documentation of setVisible() for more information.
+
+ \sa opacity(), effectiveOpacity(), setVisible()
*/
void QGraphicsItem::setOpacity(qreal opacity)
{
@@ -9782,6 +9791,7 @@ QVariant QGraphicsPixmapItem::extension(const QVariant &variant) const
using textWidth().
\note In order to align HTML text in the center, the item's text width must be set.
+ Otherwise, you can call adjustSize() after setting the item's text.
\image graphicsview-textitem.png
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 8f6c5d748c..82b9fec37f 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -53,6 +53,7 @@
#include "qtranslator.h"
#include "qvariant.h"
#include "qwidget.h"
+#include "qgraphicssceneevent.h"
#include "private/qdnd_p.h"
#include "private/qguiapplication_p.h"
#include "qcolormap.h"
@@ -2286,6 +2287,31 @@ QWidget *QApplicationPrivate::focusNextPrevChild_helper(QWidget *toplevel, bool
return w;
}
+Qt::MouseEventSource QApplicationPrivate::mouseEventSource(const QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::NonClientAreaMouseButtonDblClick:
+ case QEvent::NonClientAreaMouseButtonPress:
+ case QEvent::NonClientAreaMouseButtonRelease:
+ case QEvent::NonClientAreaMouseMove:
+ case QEvent::MouseButtonDblClick:
+ case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonRelease:
+ case QEvent::MouseMove:
+ return static_cast<const QMouseEvent *>(e)->source();
+#ifndef QT_NO_GRAPHICSVIEW
+ case QEvent::GraphicsSceneMouseDoubleClick:
+ case QEvent::GraphicsSceneMousePress:
+ case QEvent::GraphicsSceneMouseRelease:
+ case QEvent::GraphicsSceneMouseMove:
+ return static_cast<const QGraphicsSceneMouseEvent *>(e)->source();
+#endif // !QT_NO_GRAPHICSVIEW
+ default:
+ break;
+ }
+ return Qt::MouseEventNotSynthesized;
+}
+
/*!
\fn void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave, const QPointF &globalPosF)
\internal
@@ -4230,8 +4256,9 @@ bool QApplicationPrivate::shouldSetFocus(QWidget *w, Qt::FocusPolicy policy)
return true;
}
-void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
+bool QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent)
{
+ bool containsPress = false;
for (int i = 0; i < touchEvent->touchPoints().count(); ++i) {
QTouchEvent::TouchPoint &touchPoint = touchEvent->_touchPoints[i];
@@ -4244,7 +4271,11 @@ void QApplicationPrivate::updateTouchPointsForWidget(QWidget *widget, QTouchEven
touchPoint.d->rect = rect;
touchPoint.d->startPos = widget->mapFromGlobal(touchPoint.startScreenPos().toPoint()) + delta;
touchPoint.d->lastPos = widget->mapFromGlobal(touchPoint.lastScreenPos().toPoint()) + delta;
+
+ if (touchPoint.state() == Qt::TouchPointPressed)
+ containsPress = true;
}
+ return containsPress;
}
void QApplicationPrivate::initializeMultitouch()
@@ -4391,11 +4422,14 @@ bool QApplicationPrivate::translateRawTouchEvent(QWidget *window,
QApplication::keyboardModifiers(),
it.value().first,
it.value().second);
- updateTouchPointsForWidget(widget, &touchEvent);
+ bool containsPress = updateTouchPointsForWidget(widget, &touchEvent);
touchEvent.setTimestamp(timestamp);
touchEvent.setWindow(window->windowHandle());
touchEvent.setTarget(widget);
+ if (containsPress)
+ widget->setAttribute(Qt::WA_WState_AcceptedTouchBeginEvent);
+
switch (touchEvent.type()) {
case QEvent::TouchBegin:
{
diff --git a/src/widgets/kernel/qapplication_p.h b/src/widgets/kernel/qapplication_p.h
index 156bf34194..b24b592fbe 100644
--- a/src/widgets/kernel/qapplication_p.h
+++ b/src/widgets/kernel/qapplication_p.h
@@ -168,6 +168,7 @@ public:
static void setFocusWidget(QWidget *focus, Qt::FocusReason reason);
static QWidget *focusNextPrevChild_helper(QWidget *toplevel, bool next,
bool *wrappingOccurred = 0);
+ static Qt::MouseEventSource mouseEventSource(const QEvent *e);
#ifndef QT_NO_GRAPHICSVIEW
// Maintain a list of all scenes to ensure font and palette propagation to
@@ -275,7 +276,7 @@ public:
QPixmap *ignore_cursor;
#endif
- static void updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
+ static bool updateTouchPointsForWidget(QWidget *widget, QTouchEvent *touchEvent);
void initializeMultitouch();
void initializeMultitouch_sys();
void cleanupMultitouch();
diff --git a/src/widgets/kernel/qgesture_p.h b/src/widgets/kernel/qgesture_p.h
index 183a2eba0f..26d9ede59d 100644
--- a/src/widgets/kernel/qgesture_p.h
+++ b/src/widgets/kernel/qgesture_p.h
@@ -80,7 +80,7 @@ class QPanGesturePrivate : public QGesturePrivate
public:
QPanGesturePrivate()
- : acceleration(0), xVelocity(0), yVelocity(0)
+ : acceleration(0), xVelocity(0), yVelocity(0), pointCount(2)
{
}
@@ -95,6 +95,7 @@ public:
qreal acceleration;
qreal xVelocity;
qreal yVelocity;
+ int pointCount; // ### fixme Qt 5.5: Add accessor to QPanGesture.
};
class QPinchGesturePrivate : public QGesturePrivate
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 739e6b1870..c9af3062d3 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -63,6 +63,24 @@
QT_BEGIN_NAMESPACE
+static inline int panTouchPoints()
+{
+ // Override by environment variable for testing.
+ static const char panTouchPointVariable[] = "QT_PAN_TOUCHPOINTS";
+ if (qEnvironmentVariableIsSet(panTouchPointVariable)) {
+ bool ok;
+ const int result = qgetenv(panTouchPointVariable).toInt(&ok);
+ if (ok && result >= 1)
+ return result;
+ qWarning() << "Ignoring invalid value of " << panTouchPointVariable;
+ }
+ // Pan should use 1 finger on a touch screen and 2 fingers on touch pads etc.
+ // where 1 finger movements are used for mouse event synthetization. For now,
+ // default to 2 until all classes inheriting QScrollArea are fixed to handle it
+ // correctly.
+ return 2;
+}
+
QGestureManager::QGestureManager(QObject *parent)
: QObject(parent), state(NotGesture), m_lastCustomGestureId(Qt::CustomGesture)
{
@@ -73,7 +91,7 @@ QGestureManager::QGestureManager(QObject *parent)
registerGestureRecognizer(new QMacPinchGestureRecognizer);
registerGestureRecognizer(new QMacPanGestureRecognizer);
#else
- registerGestureRecognizer(new QPanGestureRecognizer);
+ registerGestureRecognizer(new QPanGestureRecognizer(panTouchPoints()));
registerGestureRecognizer(new QPinchGestureRecognizer);
registerGestureRecognizer(new QSwipeGestureRecognizer);
registerGestureRecognizer(new QTapGestureRecognizer);
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 23bb1f7050..db116b070c 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -578,12 +578,22 @@ GLuint QOpenGLWidgetPrivate::textureId() const
void QOpenGLWidgetPrivate::reset()
{
+ Q_Q(QOpenGLWidget);
+
+ // Destroy the OpenGL resources first. These need the context to be current.
+ if (initialized)
+ q->makeCurrent();
+
delete paintDevice;
paintDevice = 0;
delete fbo;
fbo = 0;
delete resolvedFbo;
resolvedFbo = 0;
+
+ if (initialized)
+ q->doneCurrent();
+
// Delete the context first, then the surface. Slots connected to
// the context's aboutToBeDestroyed() may still call makeCurrent()
// to perform some cleanup.
diff --git a/src/widgets/kernel/qstandardgestures.cpp b/src/widgets/kernel/qstandardgestures.cpp
index 9e3cb473e5..53e5d091fa 100644
--- a/src/widgets/kernel/qstandardgestures.cpp
+++ b/src/widgets/kernel/qstandardgestures.cpp
@@ -38,16 +38,13 @@
#include "qwidget.h"
#include "qabstractscrollarea.h"
#include <qgraphicssceneevent.h>
+#include <QtGui/QTouchDevice>
#include "qdebug.h"
#ifndef QT_NO_GESTURES
QT_BEGIN_NAMESPACE
-QPanGestureRecognizer::QPanGestureRecognizer()
-{
-}
-
QGesture *QPanGestureRecognizer::create(QObject *target)
{
if (target && target->isWidgetType()) {
@@ -62,8 +59,35 @@ QGesture *QPanGestureRecognizer::create(QObject *target)
return new QPanGesture;
}
+static QPointF panOffset(const QList<QTouchEvent::TouchPoint> &touchPoints, int maxCount)
+{
+ QPointF result;
+ const int count = qMin(touchPoints.size(), maxCount);
+ for (int p = 0; p < count; ++p)
+ result += touchPoints.at(p).pos() - touchPoints.at(p).startPos();
+ return result / qreal(count);
+}
+
+// ### fixme: Remove this
+// Use single finger pan to scroll QPlainTextEdit/QTextEdit
+// by changing the number of pan points to 1 for these classes.
+// This used to be Qt 4's behavior on Windows which was achieved using native
+// Windows gesture recognizers for these classes.
+// The other classes inheriting QScrollArea still use standard 2 finger pan.
+// In the long run, they should also use single finger pan to
+// scroll on touch screens, however, this requires a distinct Tap&Hold-followed-by-pan
+// type gesture to avoid clashes with item view selection and DnD.
+
+static inline int panTouchPoints(const QTouchEvent *event, const QObject *object,
+ int defaultTouchPoints)
+{
+ return event->device()->type() == QTouchDevice::TouchScreen && object && object->parent()
+ && (object->parent()->inherits("QPlainTextEdit") || object->parent()->inherits("QTextEdit"))
+ ? 1 : defaultTouchPoints;
+}
+
QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
- QObject *,
+ QObject *object,
QEvent *event)
{
QPanGesture *q = static_cast<QPanGesture *>(state);
@@ -76,18 +100,15 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
result = QGestureRecognizer::MayBeGesture;
QTouchEvent::TouchPoint p = ev->touchPoints().at(0);
d->lastOffset = d->offset = QPointF();
+ d->pointCount = panTouchPoints(ev, object, m_pointCount);
break;
}
case QEvent::TouchEnd: {
if (q->state() != Qt::NoGesture) {
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
- if (ev->touchPoints().size() == 2) {
- QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
- QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ if (ev->touchPoints().size() == d->pointCount) {
d->lastOffset = d->offset;
- d->offset =
- QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
- p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
+ d->offset = panOffset(ev->touchPoints(), d->pointCount);
}
result = QGestureRecognizer::FinishGesture;
} else {
@@ -97,16 +118,12 @@ QGestureRecognizer::Result QPanGestureRecognizer::recognize(QGesture *state,
}
case QEvent::TouchUpdate: {
const QTouchEvent *ev = static_cast<const QTouchEvent *>(event);
- if (ev->touchPoints().size() >= 2) {
- QTouchEvent::TouchPoint p1 = ev->touchPoints().at(0);
- QTouchEvent::TouchPoint p2 = ev->touchPoints().at(1);
+ if (ev->touchPoints().size() >= d->pointCount) {
d->lastOffset = d->offset;
- d->offset =
- QPointF(p1.pos().x() - p1.startPos().x() + p2.pos().x() - p2.startPos().x(),
- p1.pos().y() - p1.startPos().y() + p2.pos().y() - p2.startPos().y()) / 2;
+ d->offset = panOffset(ev->touchPoints(), d->pointCount);
if (d->offset.x() > 10 || d->offset.y() > 10 ||
d->offset.x() < -10 || d->offset.y() < -10) {
- q->setHotSpot(p1.startScreenPos());
+ q->setHotSpot(ev->touchPoints().first().startScreenPos());
result = QGestureRecognizer::TriggerGesture;
} else {
result = QGestureRecognizer::MayBeGesture;
diff --git a/src/widgets/kernel/qstandardgestures_p.h b/src/widgets/kernel/qstandardgestures_p.h
index aeabd9cc7e..15ba31f26a 100644
--- a/src/widgets/kernel/qstandardgestures_p.h
+++ b/src/widgets/kernel/qstandardgestures_p.h
@@ -55,11 +55,14 @@ QT_BEGIN_NAMESPACE
class QPanGestureRecognizer : public QGestureRecognizer
{
public:
- QPanGestureRecognizer();
+ explicit QPanGestureRecognizer(int pointCount = 2) : m_pointCount(pointCount) {}
QGesture *create(QObject *target);
QGestureRecognizer::Result recognize(QGesture *state, QObject *watched, QEvent *event);
void reset(QGesture *state);
+
+private:
+ const int m_pointCount;
};
class QPinchGestureRecognizer : public QGestureRecognizer
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 315d615d89..78eabf3c4c 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -10511,8 +10511,9 @@ void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f)
QWidget *parentWithWindow =
newparent ? (newparent->windowHandle() ? newparent : newparent->nativeParentWidget()) : 0;
if (parentWithWindow) {
- if (f & Qt::Window) {
- q->windowHandle()->setTransientParent(parentWithWindow->windowHandle());
+ QWidget *topLevel = parentWithWindow->window();
+ if ((f & Qt::Window) && topLevel && topLevel->windowHandle()) {
+ q->windowHandle()->setTransientParent(topLevel->windowHandle());
q->windowHandle()->setParent(0);
} else {
q->windowHandle()->setTransientParent(0);
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index c1d6d879a8..71a9b1abd7 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -553,7 +553,9 @@ void QFusionStyle::drawPrimitive(PrimitiveElement elem,
arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor);
} else if (header->sortIndicator & QStyleOptionHeader::SortDown) {
arrow = colorizedImage(QLatin1String(":/qt-project.org/styles/commonstyle/images/fusion_arrow.png"), arrowColor, 180);
- } if (!arrow.isNull()) {
+ }
+
+ if (!arrow.isNull()) {
r.setSize(QSize(arrow.width()/2, arrow.height()/2));
r.moveCenter(header->rect.center());
painter->drawPixmap(r.translated(offset), arrow);
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp
index c18bbb3431..c1f7b599b3 100644
--- a/src/widgets/styles/qwindowsxpstyle.cpp
+++ b/src/widgets/styles/qwindowsxpstyle.cpp
@@ -963,7 +963,8 @@ void QWindowsXPStylePrivate::drawBackgroundThruNativeBuffer(XPThemeData &themeDa
QImage img;
if (!haveCachedPixmap) { // If the pixmap is not cached, generate it! -------------------------
- buffer(w, h); // Ensure a buffer of at least (w, h) in size
+ if (!buffer(w, h)) // Ensure a buffer of at least (w, h) in size
+ return;
HDC dc = bufferHDC();
// Clear the buffer
@@ -2539,7 +2540,7 @@ QRect QWindowsXPStylePrivate::scrollBarGripperBounds(QStyle::State flags, const
const int hSpace = theme->rect.width() - size.width();
const int vSpace = theme->rect.height() - size.height();
- const bool sufficientSpace = horizontal && hSpace > (contentsMargin.left() + contentsMargin.right())
+ const bool sufficientSpace = (horizontal && hSpace > (contentsMargin.left() + contentsMargin.right()))
|| vSpace > contentsMargin.top() + contentsMargin.bottom();
return sufficientSpace ? QRect(theme->rect.topLeft() + QPoint(hSpace, vSpace) / 2, size) : QRect();
}
diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp
index f9376a78d5..ddecea81bf 100644
--- a/src/widgets/widgets/qmainwindow.cpp
+++ b/src/widgets/widgets/qmainwindow.cpp
@@ -1500,6 +1500,13 @@ bool QMainWindow::event(QEvent *event)
/*!
\property QMainWindow::unifiedTitleAndToolBarOnMac
\brief whether the window uses the unified title and toolbar look on Mac OS X
+
+ Note that the Qt 5 implementation has several limitations compared to Qt 4:
+ \list
+ \li Use in windows with OpenGL content is not supported. This includes QGLWidget and QOpenGLWidget.
+ \li Using dockable or movable toolbars may result in painting errors and is not recommended
+ \endlist
+
\since 5.2
*/
void QMainWindow::setUnifiedTitleAndToolBarOnMac(bool set)
diff --git a/src/widgets/widgets/qmdiarea.cpp b/src/widgets/widgets/qmdiarea.cpp
index 1e291f469e..3553baf68a 100644
--- a/src/widgets/widgets/qmdiarea.cpp
+++ b/src/widgets/widgets/qmdiarea.cpp
@@ -1511,7 +1511,7 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor)
#ifndef QT_NO_RUBBERBAND
if (!rubberBand) {
- rubberBand = new QRubberBand(QRubberBand::Rectangle, viewport);
+ rubberBand = new QRubberBand(QRubberBand::Rectangle, q);
// For accessibility to identify this special widget.
rubberBand->setObjectName(QLatin1String("qt_rubberband"));
rubberBand->setWindowFlags(rubberBand->windowFlags() | Qt::WindowStaysOnTopHint);
@@ -1528,6 +1528,20 @@ void QMdiAreaPrivate::highlightNextSubWindow(int increaseFactor)
Q_ASSERT(indexToHighlighted >= 0);
}
+void QMdiAreaPrivate::showRubberBandFor(QMdiSubWindow *subWindow)
+{
+ if (!subWindow || !rubberBand)
+ return;
+
+ if (viewMode == QMdiArea::TabbedView)
+ rubberBand->setGeometry(tabBar->tabRect(childWindows.indexOf(subWindow)));
+ else
+ rubberBand->setGeometry(subWindow->geometry());
+
+ rubberBand->raise();
+ rubberBand->show();
+}
+
/*!
\internal
\since 4.4
diff --git a/src/widgets/widgets/qmdiarea_p.h b/src/widgets/widgets/qmdiarea_p.h
index 1092fd9a30..ba531adaad 100644
--- a/src/widgets/widgets/qmdiarea_p.h
+++ b/src/widgets/widgets/qmdiarea_p.h
@@ -248,14 +248,7 @@ public:
}
#ifndef QT_NO_RUBBERBAND
- inline void showRubberBandFor(QMdiSubWindow *subWindow)
- {
- if (!subWindow || !rubberBand)
- return;
- rubberBand->setGeometry(subWindow->geometry());
- rubberBand->raise();
- rubberBand->show();
- }
+ void showRubberBandFor(QMdiSubWindow *subWindow);
inline void hideRubberBand()
{
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index b6a21f183a..72a556db7c 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -2042,11 +2042,13 @@ void QPlainTextEdit::mouseMoveEvent(QMouseEvent *e)
d->sendControlEvent(e);
if (!(e->buttons() & Qt::LeftButton))
return;
- QRect visible = d->viewport->rect();
- if (visible.contains(pos))
- d->autoScrollTimer.stop();
- else if (!d->autoScrollTimer.isActive())
- d->autoScrollTimer.start(100, this);
+ if (e->source() == Qt::MouseEventNotSynthesized) {
+ const QRect visible = d->viewport->rect();
+ if (visible.contains(pos))
+ d->autoScrollTimer.stop();
+ else if (!d->autoScrollTimer.isActive())
+ d->autoScrollTimer.start(100, this);
+ }
}
/*! \reimp
@@ -2055,7 +2057,7 @@ void QPlainTextEdit::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QPlainTextEdit);
d->sendControlEvent(e);
- if (d->autoScrollTimer.isActive()) {
+ if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
d->autoScrollTimer.stop();
d->ensureCursorVisible();
}
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 2d95009eb3..7ef864139f 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -1574,11 +1574,13 @@ void QTextEdit::mouseMoveEvent(QMouseEvent *e)
d->sendControlEvent(e);
if (!(e->buttons() & Qt::LeftButton))
return;
- QRect visible = d->viewport->rect();
- if (visible.contains(pos))
- d->autoScrollTimer.stop();
- else if (!d->autoScrollTimer.isActive())
- d->autoScrollTimer.start(100, this);
+ if (e->source() == Qt::MouseEventNotSynthesized) {
+ const QRect visible = d->viewport->rect();
+ if (visible.contains(pos))
+ d->autoScrollTimer.stop();
+ else if (!d->autoScrollTimer.isActive())
+ d->autoScrollTimer.start(100, this);
+ }
}
/*! \reimp
@@ -1587,7 +1589,7 @@ void QTextEdit::mouseReleaseEvent(QMouseEvent *e)
{
Q_D(QTextEdit);
d->sendControlEvent(e);
- if (d->autoScrollTimer.isActive()) {
+ if (e->source() == Qt::MouseEventNotSynthesized && d->autoScrollTimer.isActive()) {
d->autoScrollTimer.stop();
ensureCursorVisible();
}
diff --git a/src/widgets/widgets/qwidgettextcontrol.cpp b/src/widgets/widgets/qwidgettextcontrol.cpp
index dfec6a14d4..8f017b7b87 100644
--- a/src/widgets/widgets/qwidgettextcontrol.cpp
+++ b/src/widgets/widgets/qwidgettextcontrol.cpp
@@ -1580,8 +1580,10 @@ void QWidgetTextControlPrivate::mousePressEvent(QEvent *e, Qt::MouseButton butto
cursor.clearSelection();
}
}
+ // Do not start selection on a mouse event synthesized from a touch event.
if (!(button & Qt::LeftButton) ||
- !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))) {
+ !((interactionFlags & Qt::TextSelectableByMouse) || (interactionFlags & Qt::TextEditable))
+ || QApplicationPrivate::mouseEventSource(e) != Qt::MouseEventNotSynthesized) {
e->ignore();
return;
}
@@ -1752,6 +1754,11 @@ void QWidgetTextControlPrivate::mouseReleaseEvent(QEvent *e, Qt::MouseButton but
{
Q_Q(QWidgetTextControl);
+ if (QApplicationPrivate::mouseEventSource(e) != Qt::MouseEventNotSynthesized) {
+ setCursorPosition(pos); // Emulate Tap to set cursor for events synthesized from touch.
+ return;
+ }
+
const QTextCursor oldSelection = cursor;
if (sendMouseEventToInputContext(
e, QEvent::MouseButtonRelease, button, pos, modifiers, buttons, globalPos)) {