qt5: 5.7.0 -> 5.7.1
This commit is contained in:
parent
5db8452e79
commit
29de113888
6323
qt5/.footprint
6323
qt5/.footprint
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,4 @@
|
||||
63ec6b584757eef8cd713e4958297251 qt-everywhere-opensource-src-5.7.0.tar.xz
|
||||
7524ffba8411119d867f673155ec91bc qt-everywhere-opensource-src-5.7.1.tar.xz
|
||||
67165bacd3231b57d7b7db1e6bcb7d89 qt5-logo.png
|
||||
9842c327b091b360da7a4d90f5fdf4da qtbase-memory-leak.patch
|
||||
646aea77ca90031c453a65ef61db55f9 qtbug-49452.patch
|
||||
462f079cd46f869def6858903a718bf5 qtbug-53071.patch
|
||||
da4fd787ea877516397a027412e975e1 qtbug-53071b.patch
|
||||
981255fb1aea0d3c0b5c5f306fe374da qtbug-53237.patch
|
||||
c86af27562bbbe05c3defd63d00130fd qtbug-49061.patch
|
||||
7b11584d9ea1ccb6c419e9b9816dee63 qtbug-55583.patch
|
||||
|
26
qt5/Pkgfile
26
qt5/Pkgfile
@ -5,31 +5,21 @@
|
||||
# Depends on: dbus gdk-pixbuf gst-plugins-base libepoxy libmng mtdev xorg-libxcomposite xorg-libxcursor xorg-libxi xorg-libxinerama xorg-libxrandr xorg-xcb-util-image xorg-xcb-util-keysyms xorg-xcb-util-wm
|
||||
|
||||
name=qt5
|
||||
version=5.7.0
|
||||
release=4
|
||||
version=5.7.1
|
||||
release=1
|
||||
source=(http://download.qt.io/official_releases/qt/${version::3}/$version/single/qt-everywhere-opensource-src-$version.tar.xz
|
||||
qt5-logo.png
|
||||
qtbug-53071.patch
|
||||
qtbug-53071b.patch
|
||||
qtbug-53237.patch
|
||||
qtbug-49452.patch
|
||||
qtbase-memory-leak.patch)
|
||||
qtbug-49061.patch
|
||||
qtbug-55583.patch)
|
||||
|
||||
build() {
|
||||
cd qt-everywhere-opensource-src-$version
|
||||
|
||||
# Fix parsing of tzfile(5) POSIX rule zone names with bracket quotes
|
||||
patch -p1 -d qtbase -i $SRC/qtbug-53071.patch
|
||||
patch -p1 -d qtbase -i $SRC/qtbug-53071b.patch
|
||||
# Don't unload plugins in QPluginLoader https://bugreports.qt.io/browse/QTBUG-49061
|
||||
patch -p1 -d qtbase -i $SRC/qtbug-49061.patch
|
||||
|
||||
# Fix UNSIGNED values in QMYSQL
|
||||
patch -p1 -d qtbase -i $SRC/qtbug-53237.patch
|
||||
|
||||
# Fix freetype engine performance
|
||||
patch -p1 -d qtbase -i $SRC/qtbug-49452.patch
|
||||
|
||||
# Fix memory leak
|
||||
patch -p1 -d qtbase -i $SRC/qtbase-memory-leak.patch
|
||||
# Fix file chooser segfault on gnome/wayland https://bugreports.qt.io/browse/QTBUG-55583
|
||||
patch -p1 -d qtbase -i $SRC/qtbug-55583.patch
|
||||
|
||||
# Respect system CXX
|
||||
[ "$CXX" ] || CXX=g++
|
||||
|
@ -1,135 +0,0 @@
|
||||
From 422838685c31d9b57133a8711bfd5db92095d96d Mon Sep 17 00:00:00 2001
|
||||
From: Robin Burchell <robin.burchell@viroteck.net>
|
||||
Date: Wed, 7 Sep 2016 14:34:03 +0200
|
||||
Subject: [PATCH] xcb: Treat bitmap cursors differently from shaped cursors
|
||||
|
||||
QXcbCursor had a "cache" of cursor handles. Unfortunately, as QXcbCursor has its
|
||||
lifetime tied to the screen, this cache grew unbounded whenever the cursor was
|
||||
set: this could be witnessed worst when repeatedly setting the current cursor to
|
||||
a different pixmap each time.
|
||||
|
||||
We fix this by keeping the cursor cache only for the "regular" shaped cursors
|
||||
that are often shared between windows, working on the assumption that custom
|
||||
cursors are generally specific only to a given window. This makes the lifetime
|
||||
of the bitmap cursors much more clear: they are tied to that window, and when
|
||||
the window is destroyed (or changes cursor), so too is the bitmap cursor
|
||||
destroyed (if set).
|
||||
|
||||
Reported-by: Will Thompson <wjt@endlessm.com>
|
||||
Change-Id: Ia558d858ff49e89cd5220344567203eb0267a133
|
||||
Reviewed-by: Uli Schlachter <psychon@znc.in>
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
|
||||
---
|
||||
src/plugins/platforms/xcb/qxcbcursor.cpp | 24 +++++++++++++++++-------
|
||||
src/plugins/platforms/xcb/qxcbwindow.cpp | 22 +++++++++++++++++++---
|
||||
src/plugins/platforms/xcb/qxcbwindow.h | 3 ++-
|
||||
3 files changed, 38 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
|
||||
index b321ed9..4646ced 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
|
||||
@@ -353,17 +353,27 @@ void QXcbCursor::changeCursor(QCursor *cursor, QWindow *widget)
|
||||
return;
|
||||
|
||||
xcb_cursor_t c = XCB_CURSOR_NONE;
|
||||
+ bool isBitmapCursor = false;
|
||||
+
|
||||
if (cursor) {
|
||||
- const QXcbCursorCacheKey key(*cursor);
|
||||
- CursorHash::iterator it = m_cursorHash.find(key);
|
||||
- if (it == m_cursorHash.end()) {
|
||||
- const Qt::CursorShape shape = cursor->shape();
|
||||
- it = m_cursorHash.insert(key, shape == Qt::BitmapCursor ? createBitmapCursor(cursor) : createFontCursor(shape));
|
||||
+ const Qt::CursorShape shape = cursor->shape();
|
||||
+ isBitmapCursor = shape == Qt::BitmapCursor;
|
||||
+
|
||||
+ if (!isBitmapCursor) {
|
||||
+ const QXcbCursorCacheKey key(*cursor);
|
||||
+ CursorHash::iterator it = m_cursorHash.find(key);
|
||||
+ if (it == m_cursorHash.end()) {
|
||||
+ it = m_cursorHash.insert(key, createFontCursor(shape));
|
||||
+ }
|
||||
+ c = it.value();
|
||||
+ } else {
|
||||
+ // Do not cache bitmap cursors, as otherwise they have unclear
|
||||
+ // lifetime (we effectively leak xcb_cursor_t).
|
||||
+ c = createBitmapCursor(cursor);
|
||||
}
|
||||
- c = it.value();
|
||||
}
|
||||
|
||||
- w->setCursor(c);
|
||||
+ w->setCursor(c, isBitmapCursor);
|
||||
}
|
||||
|
||||
static int cursorIdForShape(int cshape)
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
index d46228c..5f402b6 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
|
||||
@@ -302,6 +302,7 @@ QXcbWindow::QXcbWindow(QWindow *window)
|
||||
, m_lastWindowStateEvent(-1)
|
||||
, m_syncState(NoSyncNeeded)
|
||||
, m_pendingSyncRequest(0)
|
||||
+ , m_currentBitmapCursor(XCB_CURSOR_NONE)
|
||||
{
|
||||
setConnection(xcbScreen()->connection());
|
||||
}
|
||||
@@ -620,6 +621,9 @@ void QXcbWindow::create()
|
||||
|
||||
QXcbWindow::~QXcbWindow()
|
||||
{
|
||||
+ if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
|
||||
+ xcb_free_cursor(xcb_connection(), m_currentBitmapCursor);
|
||||
+ }
|
||||
if (window()->type() != Qt::ForeignWindow)
|
||||
destroy();
|
||||
else {
|
||||
@@ -2665,10 +2669,22 @@ bool QXcbWindow::setMouseGrabEnabled(bool grab)
|
||||
return result;
|
||||
}
|
||||
|
||||
-void QXcbWindow::setCursor(xcb_cursor_t cursor)
|
||||
+void QXcbWindow::setCursor(xcb_cursor_t cursor, bool isBitmapCursor)
|
||||
{
|
||||
- xcb_change_window_attributes(xcb_connection(), m_window, XCB_CW_CURSOR, &cursor);
|
||||
- xcb_flush(xcb_connection());
|
||||
+ xcb_connection_t *conn = xcb_connection();
|
||||
+
|
||||
+ xcb_change_window_attributes(conn, m_window, XCB_CW_CURSOR, &cursor);
|
||||
+ xcb_flush(conn);
|
||||
+
|
||||
+ if (m_currentBitmapCursor != XCB_CURSOR_NONE) {
|
||||
+ xcb_free_cursor(conn, m_currentBitmapCursor);
|
||||
+ }
|
||||
+
|
||||
+ if (isBitmapCursor) {
|
||||
+ m_currentBitmapCursor = cursor;
|
||||
+ } else {
|
||||
+ m_currentBitmapCursor = XCB_CURSOR_NONE;
|
||||
+ }
|
||||
}
|
||||
|
||||
void QXcbWindow::windowEvent(QEvent *event)
|
||||
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
index b8bcf44..f2b6904 100644
|
||||
--- a/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
|
||||
@@ -97,7 +97,7 @@ class Q_XCB_EXPORT QXcbWindow : public QXcbObject, public QXcbWindowEventListene
|
||||
bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE;
|
||||
bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE;
|
||||
|
||||
- void setCursor(xcb_cursor_t cursor);
|
||||
+ void setCursor(xcb_cursor_t cursor, bool isBitmapCursor);
|
||||
|
||||
QSurfaceFormat format() const Q_DECL_OVERRIDE;
|
||||
|
||||
@@ -263,6 +263,7 @@ public Q_SLOTS:
|
||||
SyncState m_syncState;
|
||||
|
||||
QXcbSyncWindowRequest *m_pendingSyncRequest;
|
||||
+ xcb_cursor_t m_currentBitmapCursor;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
77
qt5/qtbug-49061.patch
Normal file
77
qt5/qtbug-49061.patch
Normal file
@ -0,0 +1,77 @@
|
||||
From 494376f980e96339b6f1eff7c41336ca4d853065 Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Thu, 12 Nov 2015 10:14:51 -0800
|
||||
Subject: [PATCH] Stop unloading plugins in QPluginLoader and QFactoryLoader
|
||||
|
||||
QPluginLoader hasn't unloaded in its destructor since Qt 5.0, but we
|
||||
missed the equivalent code in QFactoryLoader (which bypasses
|
||||
QPluginLoader). Besides, QPluginLoader::unload() was still doing
|
||||
unloading, which it won't anymore.
|
||||
|
||||
Not unloading plugins is Qt's policy, as decided during the 5.0
|
||||
development process and reaffirmed now in 5.6. This is due to static
|
||||
data in plugins leaking out and remaining in use past the unloading of
|
||||
the plugin, causing crashes.
|
||||
|
||||
This does not affect QLibrary and QLibrary::unload(). Those are meant
|
||||
for non-Qt loadable modules, so unloading them may be safe.
|
||||
|
||||
Task-number: QTBUG-49061
|
||||
Discussed-on: http://lists.qt-project.org/pipermail/development/2015-November/023681.html
|
||||
Change-Id: I461e9fc7199748faa187ffff1416070f138df8db
|
||||
Reviewed-by: Simon Hausmann <simon.hausmann@theqtcompany.com>
|
||||
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
|
||||
---
|
||||
src/corelib/plugin/qfactoryloader.cpp | 6 ++++--
|
||||
src/corelib/plugin/qpluginloader.cpp | 5 +++--
|
||||
2 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp
|
||||
index 53b38c3..c820d53 100644
|
||||
--- a/src/corelib/plugin/qfactoryloader.cpp
|
||||
+++ b/src/corelib/plugin/qfactoryloader.cpp
|
||||
@@ -203,10 +203,12 @@ void QFactoryLoader::update()
|
||||
++keyUsageCount;
|
||||
}
|
||||
}
|
||||
- if (keyUsageCount || keys.isEmpty())
|
||||
+ if (keyUsageCount || keys.isEmpty()) {
|
||||
+ library->setLoadHints(QLibrary::PreventUnloadHint); // once loaded, don't unload
|
||||
d->libraryList += library;
|
||||
- else
|
||||
+ } else {
|
||||
library->release();
|
||||
+ }
|
||||
}
|
||||
}
|
||||
#else
|
||||
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
|
||||
index 62067c7..4752f69 100644
|
||||
--- a/src/corelib/plugin/qpluginloader.cpp
|
||||
+++ b/src/corelib/plugin/qpluginloader.cpp
|
||||
@@ -154,6 +154,7 @@ QPluginLoader::QPluginLoader(const QString &fileName, QObject *parent)
|
||||
: QObject(parent), d(0), did_load(false)
|
||||
{
|
||||
setFileName(fileName);
|
||||
+ setLoadHints(QLibrary::PreventUnloadHint);
|
||||
}
|
||||
|
||||
/*!
|
||||
@@ -348,7 +349,7 @@ static QString locatePlugin(const QString& fileName)
|
||||
void QPluginLoader::setFileName(const QString &fileName)
|
||||
{
|
||||
#if defined(QT_SHARED)
|
||||
- QLibrary::LoadHints lh;
|
||||
+ QLibrary::LoadHints lh = QLibrary::PreventUnloadHint;
|
||||
if (d) {
|
||||
lh = d->loadHints();
|
||||
d->release();
|
||||
@@ -394,7 +395,7 @@ QString QPluginLoader::errorString() const
|
||||
\brief Give the load() function some hints on how it should behave.
|
||||
|
||||
You can give hints on how the symbols in the plugin are
|
||||
- resolved. By default, none of the hints are set.
|
||||
+ resolved. By default since Qt 5.7, QLibrary::PreventUnloadHint is set.
|
||||
|
||||
See the documentation of QLibrary::loadHints for a complete
|
||||
description of how this property works.
|
@ -1,58 +0,0 @@
|
||||
From 6f423555eba55ccdf7287071e10576bc1b687fd2 Mon Sep 17 00:00:00 2001
|
||||
From: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
|
||||
Date: Mon, 1 Aug 2016 13:39:53 +0200
|
||||
Subject: [PATCH] REG: Fix unwanted cache flush in Freetype engine
|
||||
|
||||
The Freetype cache was almost completely disabled by
|
||||
134c6db8587a8ce156d4fa31ffa62605821851b2 because after that
|
||||
change, the lockedAlphaMapForGlyph() function would no longer
|
||||
cut off early for empty glyphs like spaces, but rather go
|
||||
through all alpha map functions before it realized that there
|
||||
was nothing to render. This would in turn invalidate the cache
|
||||
for every empty glyph, causing all glyphs to be rerendered for
|
||||
every isolated word.
|
||||
|
||||
This change adds back a cut off. This is only needed in the
|
||||
lockedAlphaMapForGlyph() function, since the superclass implementation
|
||||
of the other alpha map functions already contains a cut off for
|
||||
width/height == 0.
|
||||
|
||||
[ChangeLog][Qt Gui][Text] Fixed a performance regression in Freetype
|
||||
engine that was introduced in Qt 5.5.
|
||||
|
||||
Change-Id: I381285939909e99cc5fb5f3497fecf9fa871f29a
|
||||
Task-number: QTBUG-49452
|
||||
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
|
||||
---
|
||||
src/gui/text/qfontengine_ft.cpp | 6 +++++-
|
||||
1 file changed, 5 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
|
||||
index 4de41df..7c878da 100644
|
||||
--- a/src/gui/text/qfontengine_ft.cpp
|
||||
+++ b/src/gui/text/qfontengine_ft.cpp
|
||||
@@ -1716,7 +1716,7 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
|
||||
|
||||
static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat)
|
||||
{
|
||||
- if (glyph == Q_NULLPTR)
|
||||
+ if (glyph == Q_NULLPTR || glyph->height == 0 || glyph->width == 0)
|
||||
return QImage();
|
||||
|
||||
QImage::Format format = QImage::Format_Invalid;
|
||||
@@ -1764,11 +1764,15 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
|
||||
|
||||
currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat);
|
||||
|
||||
+ const bool glyphHasGeometry = glyph != Q_NULLPTR && glyph->height != 0 && glyph->width != 0;
|
||||
if (!cacheEnabled && glyph != &emptyGlyph) {
|
||||
currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy();
|
||||
delete glyph;
|
||||
}
|
||||
|
||||
+ if (!glyphHasGeometry)
|
||||
+ return Q_NULLPTR;
|
||||
+
|
||||
if (currentlyLockedAlphaMap.isNull())
|
||||
return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset);
|
||||
|
@ -1,272 +0,0 @@
|
||||
From e9041c7fc1052167f1ec2df0ea9623059e55d00f Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Thu, 28 Apr 2016 22:09:01 -0700
|
||||
Subject: [PATCH] Fix parsing of tzfile(5) POSIX rule zone names with bracket
|
||||
quotes
|
||||
|
||||
POSIX.1-2001 allows quoting a zone name so that it can contain other
|
||||
characters besides letters, by enclosing it in angle brackets ('<' and
|
||||
'>'). This hadn't been used until recently (tzdata2016b), when the
|
||||
Asia/Barnaul rule started using a zone name "+07" (the name variable
|
||||
contained the value "<+07>-7").
|
||||
|
||||
Thanks to Paul Eggert for reporting and investigating the root cause.
|
||||
|
||||
Task-number: QTBUG-53071
|
||||
Change-Id: Id5480807d25e49e78b79ffff1449bc410776cb66
|
||||
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
|
||||
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
|
||||
---
|
||||
src/corelib/tools/qtimezoneprivate_tz.cpp | 176 ++++++++++++++-------
|
||||
.../auto/corelib/tools/qtimezone/tst_qtimezone.cpp | 10 ++
|
||||
2 files changed, 130 insertions(+), 56 deletions(-)
|
||||
|
||||
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
|
||||
index 85ed345..cb9581a 100644
|
||||
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
|
||||
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
|
||||
@@ -41,6 +41,8 @@
|
||||
|
||||
#include <qdebug.h>
|
||||
|
||||
+#include "qlocale_tools_p.h"
|
||||
+
|
||||
#include <algorithm>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
@@ -384,25 +386,100 @@ static QTime parsePosixTime(const QByteArray &timeRule)
|
||||
return QTime(2, 0, 0);
|
||||
}
|
||||
|
||||
-static int parsePosixOffset(const QByteArray &timeRule)
|
||||
+static int parsePosixOffset(const char *begin, const char *end)
|
||||
{
|
||||
// Format "[+|-]hh[:mm[:ss]]"
|
||||
- QList<QByteArray> parts = timeRule.split(':');
|
||||
- int count = parts.count();
|
||||
- if (count == 3) {
|
||||
- int hour = parts.at(0).toInt();
|
||||
- int sign = hour >= 0 ? -1 : 1;
|
||||
- return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60) + parts.at(2).toInt());
|
||||
- } else if (count == 2) {
|
||||
- int hour = parts.at(0).toInt();
|
||||
- int sign = hour >= 0 ? -1 : 1;
|
||||
- return sign * ((qAbs(hour) * 60 * 60) + (parts.at(1).toInt() * 60));
|
||||
- } else if (count == 1) {
|
||||
- int hour = parts.at(0).toInt();
|
||||
- int sign = hour >= 0 ? -1 : 1;
|
||||
- return sign * (qAbs(hour) * 60 * 60);
|
||||
- }
|
||||
- return 0;
|
||||
+ int hour, min = 0, sec = 0;
|
||||
+
|
||||
+ // note that the sign is inverted because POSIX counts in hours West of GMT
|
||||
+ bool negate = true;
|
||||
+ if (*begin == '+') {
|
||||
+ ++begin;
|
||||
+ } else if (*begin == '-') {
|
||||
+ negate = false;
|
||||
+ ++begin;
|
||||
+ }
|
||||
+
|
||||
+ bool ok = false;
|
||||
+ hour = qstrtoll(begin, &begin, 10, &ok);
|
||||
+ if (!ok)
|
||||
+ return INT_MIN;
|
||||
+ if (begin < end && *begin == ':') {
|
||||
+ // minutes
|
||||
+ ++begin;
|
||||
+ min = qstrtoll(begin, &begin, 10, &ok);
|
||||
+ if (!ok || min < 0)
|
||||
+ return INT_MIN;
|
||||
+
|
||||
+ if (begin < end && *begin == ':') {
|
||||
+ // seconds
|
||||
+ ++begin;
|
||||
+ sec = qstrtoll(begin, &begin, 10, &ok);
|
||||
+ if (!ok || sec < 0)
|
||||
+ return INT_MIN;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // we must have consumed everything
|
||||
+ if (begin != end)
|
||||
+ return INT_MIN;
|
||||
+
|
||||
+ int value = (hour * 60 + min) * 60 + sec;
|
||||
+ return negate ? -value : value;
|
||||
+}
|
||||
+
|
||||
+static inline bool asciiIsLetter(char ch)
|
||||
+{
|
||||
+ ch |= 0x20; // lowercases if it is a letter, otherwise just corrupts ch
|
||||
+ return ch >= 'a' && ch <= 'z';
|
||||
+}
|
||||
+
|
||||
+// Returns the zone name, the offset (in seconds) and advances \a begin to
|
||||
+// where the parsing ended. Returns a zone of INT_MIN in case an offset
|
||||
+// couldn't be read.
|
||||
+static QPair<QString, int> parsePosixZoneNameAndOffset(const char *&pos, const char *end)
|
||||
+{
|
||||
+ static const char offsetChars[] = "0123456789:";
|
||||
+ QPair<QString, int> result = qMakePair(QString(), INT_MIN);
|
||||
+
|
||||
+ const char *nameBegin = pos;
|
||||
+ const char *nameEnd;
|
||||
+ Q_ASSERT(pos < end);
|
||||
+
|
||||
+ if (*pos == '<') {
|
||||
+ nameBegin = pos + 1; // skip the '<'
|
||||
+ nameEnd = nameBegin;
|
||||
+ while (nameEnd < end && *nameEnd != '>') {
|
||||
+ // POSIX says only alphanumeric, but we allow anything
|
||||
+ ++nameEnd;
|
||||
+ }
|
||||
+ pos = nameEnd + 1; // skip the '>'
|
||||
+ } else {
|
||||
+ nameBegin = pos;
|
||||
+ nameEnd = nameBegin;
|
||||
+ while (nameEnd < end && asciiIsLetter(*nameEnd))
|
||||
+ ++nameEnd;
|
||||
+ pos = nameEnd;
|
||||
+ }
|
||||
+ if (nameEnd - nameBegin < 3)
|
||||
+ return result; // name must be at least 3 characters long
|
||||
+
|
||||
+ // zone offset, form [+-]hh:mm:ss
|
||||
+ const char *zoneBegin = pos;
|
||||
+ const char *zoneEnd = pos;
|
||||
+ if (zoneEnd < end && (zoneEnd[0] == '+' || zoneEnd[0] == '-'))
|
||||
+ ++zoneEnd;
|
||||
+ while (zoneEnd < end) {
|
||||
+ if (strchr(offsetChars, char(*zoneEnd)) == NULL)
|
||||
+ break;
|
||||
+ ++zoneEnd;
|
||||
+ }
|
||||
+
|
||||
+ result.first = QString::fromUtf8(nameBegin, nameEnd - nameBegin);
|
||||
+ if (zoneEnd > zoneBegin)
|
||||
+ result.second = parsePosixOffset(zoneBegin, zoneEnd);
|
||||
+ pos = zoneEnd;
|
||||
+ return result;
|
||||
}
|
||||
|
||||
static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArray &posixRule,
|
||||
@@ -419,51 +496,38 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
|
||||
// POSIX Format is like "TZ=CST6CDT,M3.2.0/2:00:00,M11.1.0/2:00:00"
|
||||
// i.e. "std offset dst [offset],start[/time],end[/time]"
|
||||
- // See http://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html
|
||||
+ // See the section about TZ at http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
|
||||
QList<QByteArray> parts = posixRule.split(',');
|
||||
|
||||
- QString name = QString::fromUtf8(parts.at(0));
|
||||
- QString stdName;
|
||||
- QString stdOffsetString;
|
||||
- QString dstName;
|
||||
- QString dstOffsetString;
|
||||
- bool parsedStdName = false;
|
||||
- bool parsedStdOffset = false;
|
||||
- for (int i = 0; i < name.size(); ++i) {
|
||||
- if (name.at(i).isLetter()) {
|
||||
- if (parsedStdName) {
|
||||
- parsedStdOffset = true;
|
||||
- dstName.append(name.at(i));
|
||||
- } else {
|
||||
- stdName.append(name.at(i));
|
||||
+ QPair<QString, int> stdZone, dstZone;
|
||||
+ {
|
||||
+ const QByteArray &zoneinfo = parts.at(0);
|
||||
+ const char *begin = zoneinfo.constBegin();
|
||||
+
|
||||
+ stdZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
|
||||
+ if (stdZone.second == INT_MIN) {
|
||||
+ stdZone.second = 0; // reset to UTC if we failed to parse
|
||||
+ } else if (begin < zoneinfo.constEnd()) {
|
||||
+ dstZone = parsePosixZoneNameAndOffset(begin, zoneinfo.constEnd());
|
||||
+ if (dstZone.second == INT_MIN) {
|
||||
+ // if the dst offset isn't provided, it is 1 hour ahead of the standard offset
|
||||
+ dstZone.second = stdZone.second + (60 * 60);
|
||||
}
|
||||
- } else {
|
||||
- parsedStdName = true;
|
||||
- if (parsedStdOffset)
|
||||
- dstOffsetString.append(name.at(i));
|
||||
- else
|
||||
- stdOffsetString.append(name.at(i));
|
||||
}
|
||||
}
|
||||
|
||||
- int utcOffset = parsePosixOffset(stdOffsetString.toUtf8());
|
||||
-
|
||||
// If only the name part then no transitions
|
||||
if (parts.count() == 1) {
|
||||
QTimeZonePrivate::Data data;
|
||||
data.atMSecsSinceEpoch = lastTranMSecs;
|
||||
- data.offsetFromUtc = utcOffset;
|
||||
- data.standardTimeOffset = utcOffset;
|
||||
+ data.offsetFromUtc = stdZone.second;
|
||||
+ data.standardTimeOffset = stdZone.second;
|
||||
data.daylightTimeOffset = 0;
|
||||
- data.abbreviation = stdName;
|
||||
+ data.abbreviation = stdZone.first;
|
||||
result << data;
|
||||
return result;
|
||||
}
|
||||
|
||||
- // If not populated the total dst offset is 1 hour
|
||||
- int dstOffset = utcOffset + (60 * 60);
|
||||
- if (!dstOffsetString.isEmpty())
|
||||
- dstOffset = parsePosixOffset(dstOffsetString.toUtf8());
|
||||
|
||||
// Get the std to dst transtion details
|
||||
QList<QByteArray> dstParts = parts.at(1).split('/');
|
||||
@@ -486,18 +550,18 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
for (int year = startYear; year <= endYear; ++year) {
|
||||
QTimeZonePrivate::Data dstData;
|
||||
QDateTime dst(calculatePosixDate(dstDateRule, year), dstTime, Qt::UTC);
|
||||
- dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (utcOffset * 1000);
|
||||
- dstData.offsetFromUtc = dstOffset;
|
||||
- dstData.standardTimeOffset = utcOffset;
|
||||
- dstData.daylightTimeOffset = dstOffset - utcOffset;
|
||||
- dstData.abbreviation = dstName;
|
||||
+ dstData.atMSecsSinceEpoch = dst.toMSecsSinceEpoch() - (stdZone.second * 1000);
|
||||
+ dstData.offsetFromUtc = dstZone.second;
|
||||
+ dstData.standardTimeOffset = stdZone.second;
|
||||
+ dstData.daylightTimeOffset = dstZone.second - stdZone.second;
|
||||
+ dstData.abbreviation = dstZone.first;
|
||||
QTimeZonePrivate::Data stdData;
|
||||
QDateTime std(calculatePosixDate(stdDateRule, year), stdTime, Qt::UTC);
|
||||
- stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstOffset * 1000);
|
||||
- stdData.offsetFromUtc = utcOffset;
|
||||
- stdData.standardTimeOffset = utcOffset;
|
||||
+ stdData.atMSecsSinceEpoch = std.toMSecsSinceEpoch() - (dstZone.second * 1000);
|
||||
+ stdData.offsetFromUtc = stdZone.second;
|
||||
+ stdData.standardTimeOffset = stdZone.second;
|
||||
stdData.daylightTimeOffset = 0;
|
||||
- stdData.abbreviation = stdName;
|
||||
+ stdData.abbreviation = stdZone.first;
|
||||
// Part of the high year will overflow
|
||||
if (year == 292278994 && (dstData.atMSecsSinceEpoch < 0 || stdData.atMSecsSinceEpoch < 0)) {
|
||||
if (dstData.atMSecsSinceEpoch > 0) {
|
||||
diff --git a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
|
||||
index ea83510..ce72e7c 100644
|
||||
--- a/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
|
||||
+++ b/tests/auto/corelib/tools/qtimezone/tst_qtimezone.cpp
|
||||
@@ -847,6 +847,16 @@ void tst_QTimeZone::tzTest()
|
||||
QTzTimeZonePrivate::Data datatz2 = tztz2.data(std);
|
||||
QTzTimeZonePrivate::Data datautc2 = tzutc2.data(std);
|
||||
QCOMPARE(datatz2.offsetFromUtc, datautc2.offsetFromUtc);
|
||||
+
|
||||
+ // Test a timezone with a name that isn't all letters
|
||||
+ QTzTimeZonePrivate tzBarnaul("Asia/Barnaul");
|
||||
+ if (tzBarnaul.isValid()) {
|
||||
+ QCOMPARE(tzBarnaul.data(std).abbreviation, QString("+07"));
|
||||
+
|
||||
+ // first full day of the new rule (tzdata2016b)
|
||||
+ QDateTime dt(QDate(2016, 3, 28), QTime(0, 0, 0), Qt::UTC);
|
||||
+ QCOMPARE(tzBarnaul.data(dt.toMSecsSinceEpoch()).abbreviation, QString("+07"));
|
||||
+ }
|
||||
#endif // Q_OS_UNIX
|
||||
}
|
||||
|
@ -1,122 +0,0 @@
|
||||
From cd25866f6533923c208f52d58516f3725f69cefb Mon Sep 17 00:00:00 2001
|
||||
From: Thiago Macieira <thiago.macieira@intel.com>
|
||||
Date: Wed, 18 May 2016 13:38:55 -0700
|
||||
Subject: [PATCH] Use the code we already have for parsing the transition time
|
||||
too
|
||||
|
||||
It's there and it's more efficient anyway.
|
||||
|
||||
Change-Id: Ie9fd7afe060b4e4a8052fffd144fc40647430268
|
||||
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
|
||||
Reviewed-by: Brett Stottlemyer <bstottle@ford.com>
|
||||
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
|
||||
---
|
||||
src/corelib/tools/qtimezoneprivate_tz.cpp | 68 ++++++++++++++++++-------------
|
||||
1 file changed, 40 insertions(+), 28 deletions(-)
|
||||
|
||||
diff --git a/src/corelib/tools/qtimezoneprivate_tz.cpp b/src/corelib/tools/qtimezoneprivate_tz.cpp
|
||||
index cb9581a..bfa967e 100644
|
||||
--- a/src/corelib/tools/qtimezoneprivate_tz.cpp
|
||||
+++ b/src/corelib/tools/qtimezoneprivate_tz.cpp
|
||||
@@ -372,37 +372,21 @@ static QDate calculatePosixDate(const QByteArray &dateRule, int year)
|
||||
}
|
||||
}
|
||||
|
||||
-static QTime parsePosixTime(const QByteArray &timeRule)
|
||||
+// returns the time in seconds, INT_MIN if we failed to parse
|
||||
+static int parsePosixTime(const char *begin, const char *end)
|
||||
{
|
||||
- // Format "HH:mm:ss", put check parts count just in case
|
||||
- QList<QByteArray> parts = timeRule.split(':');
|
||||
- int count = parts.count();
|
||||
- if (count == 3)
|
||||
- return QTime(parts.at(0).toInt(), parts.at(1).toInt(), parts.at(2).toInt());
|
||||
- else if (count == 2)
|
||||
- return QTime(parts.at(0).toInt(), parts.at(1).toInt(), 0);
|
||||
- else if (count == 1)
|
||||
- return QTime(parts.at(0).toInt(), 0, 0);
|
||||
- return QTime(2, 0, 0);
|
||||
-}
|
||||
-
|
||||
-static int parsePosixOffset(const char *begin, const char *end)
|
||||
-{
|
||||
- // Format "[+|-]hh[:mm[:ss]]"
|
||||
+ // Format "hh[:mm[:ss]]"
|
||||
int hour, min = 0, sec = 0;
|
||||
|
||||
- // note that the sign is inverted because POSIX counts in hours West of GMT
|
||||
- bool negate = true;
|
||||
- if (*begin == '+') {
|
||||
- ++begin;
|
||||
- } else if (*begin == '-') {
|
||||
- negate = false;
|
||||
- ++begin;
|
||||
- }
|
||||
+ // Note that the calls to qstrtoll do *not* check the end pointer, which
|
||||
+ // means they proceed until they find a non-digit. We check that we're
|
||||
+ // still in range at the end, but we may have read from past end. It's the
|
||||
+ // caller's responsibility to ensure that begin is part of a
|
||||
+ // null-terminated string.
|
||||
|
||||
bool ok = false;
|
||||
hour = qstrtoll(begin, &begin, 10, &ok);
|
||||
- if (!ok)
|
||||
+ if (!ok || hour < 0)
|
||||
return INT_MIN;
|
||||
if (begin < end && *begin == ':') {
|
||||
// minutes
|
||||
@@ -424,7 +408,35 @@ static int parsePosixOffset(const char *begin, const char *end)
|
||||
if (begin != end)
|
||||
return INT_MIN;
|
||||
|
||||
- int value = (hour * 60 + min) * 60 + sec;
|
||||
+ return (hour * 60 + min) * 60 + sec;
|
||||
+}
|
||||
+
|
||||
+static QTime parsePosixTransitionTime(const QByteArray &timeRule)
|
||||
+{
|
||||
+ // Format "hh[:mm[:ss]]"
|
||||
+ int value = parsePosixTime(timeRule.constBegin(), timeRule.constEnd());
|
||||
+ if (value == INT_MIN) {
|
||||
+ // if we failed to parse, return 02:00
|
||||
+ return QTime(2, 0, 0);
|
||||
+ }
|
||||
+ return QTime::fromMSecsSinceStartOfDay(value * 1000);
|
||||
+}
|
||||
+
|
||||
+static int parsePosixOffset(const char *begin, const char *end)
|
||||
+{
|
||||
+ // Format "[+|-]hh[:mm[:ss]]"
|
||||
+ // note that the sign is inverted because POSIX counts in hours West of GMT
|
||||
+ bool negate = true;
|
||||
+ if (*begin == '+') {
|
||||
+ ++begin;
|
||||
+ } else if (*begin == '-') {
|
||||
+ negate = false;
|
||||
+ ++begin;
|
||||
+ }
|
||||
+
|
||||
+ int value = parsePosixTime(begin, end);
|
||||
+ if (value == INT_MIN)
|
||||
+ return value;
|
||||
return negate ? -value : value;
|
||||
}
|
||||
|
||||
@@ -534,7 +546,7 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
QByteArray dstDateRule = dstParts.at(0);
|
||||
QTime dstTime;
|
||||
if (dstParts.count() > 1)
|
||||
- dstTime = parsePosixTime(dstParts.at(1));
|
||||
+ dstTime = parsePosixTransitionTime(dstParts.at(1));
|
||||
else
|
||||
dstTime = QTime(2, 0, 0);
|
||||
|
||||
@@ -543,7 +555,7 @@ static QVector<QTimeZonePrivate::Data> calculatePosixTransitions(const QByteArra
|
||||
QByteArray stdDateRule = stdParts.at(0);
|
||||
QTime stdTime;
|
||||
if (stdParts.count() > 1)
|
||||
- stdTime = parsePosixTime(stdParts.at(1));
|
||||
+ stdTime = parsePosixTransitionTime(stdParts.at(1));
|
||||
else
|
||||
stdTime = QTime(2, 0, 0);
|
||||
|
@ -1,90 +0,0 @@
|
||||
From 8e889378115c69508b050a511621ac8e30ec4158 Mon Sep 17 00:00:00 2001
|
||||
From: Jesus Fernandez <jesus.fernandez@theqtcompany.com>
|
||||
Date: Mon, 13 Jun 2016 19:09:15 +0200
|
||||
Subject: [PATCH] Fix UNSIGNED values in QMYSQL
|
||||
|
||||
The unsigned flag in columns was ignored when creating the list of
|
||||
bound values in a mysql table. So the result iteration with
|
||||
QSqlQuery::next stops after the first wrong truncated value.
|
||||
|
||||
[ChangeLog][QtSql] Fixed QSqlQuery::prepare value truncation error when
|
||||
using UNSIGNED values in a MySQL database.
|
||||
|
||||
Task-number: QTBUG-53969
|
||||
Task-number: QTBUG-53237
|
||||
Change-Id: I10d977993445f2794f1dd8c88b2e83517ef524f3
|
||||
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
|
||||
---
|
||||
src/sql/drivers/mysql/qsql_mysql.cpp | 1 +
|
||||
tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp | 39 +++++++++++++++++++++++
|
||||
2 files changed, 40 insertions(+)
|
||||
|
||||
diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp
|
||||
index 96bdcc4..55bf499 100644
|
||||
--- a/src/sql/drivers/mysql/qsql_mysql.cpp
|
||||
+++ b/src/sql/drivers/mysql/qsql_mysql.cpp
|
||||
@@ -387,6 +387,7 @@ bool QMYSQLResultPrivate::bindInValues()
|
||||
bind->buffer_length = f.bufLength = fieldInfo->length + 1;
|
||||
bind->is_null = &f.nullIndicator;
|
||||
bind->length = &f.bufLength;
|
||||
+ bind->is_unsigned = fieldInfo->flags & UNSIGNED_FLAG ? 1 : 0;
|
||||
f.outField=field;
|
||||
|
||||
++i;
|
||||
diff --git a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
|
||||
index bd553d5..f1c4333 100644
|
||||
--- a/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
|
||||
+++ b/tests/auto/sql/kernel/qsqlquery/tst_qsqlquery.cpp
|
||||
@@ -233,6 +233,9 @@ private slots:
|
||||
void QTBUG_36211_data() { generic_data("QPSQL"); }
|
||||
void QTBUG_36211();
|
||||
|
||||
+ void QTBUG_53969_data() { generic_data("QMYSQL"); }
|
||||
+ void QTBUG_53969();
|
||||
+
|
||||
void sqlite_constraint_data() { generic_data("QSQLITE"); }
|
||||
void sqlite_constraint();
|
||||
|
||||
@@ -3652,6 +3655,42 @@ void tst_QSqlQuery::QTBUG_36211()
|
||||
}
|
||||
}
|
||||
|
||||
+void tst_QSqlQuery::QTBUG_53969()
|
||||
+{
|
||||
+ QFETCH( QString, dbName );
|
||||
+ QVector<int> values = QVector<int>() << 10 << 20 << 127 << 128 << 1, tableValues;
|
||||
+ QSqlDatabase db = QSqlDatabase::database( dbName );
|
||||
+ CHECK_DATABASE( db );
|
||||
+ tableValues.reserve(values.size());
|
||||
+ if (tst_Databases::getDatabaseType(db) == QSqlDriver::MySqlServer) {
|
||||
+ const QString tableName(qTableName("bug53969", __FILE__, db));
|
||||
+ tst_Databases::safeDropTable( db, tableName );
|
||||
+
|
||||
+ QSqlQuery q(db);
|
||||
+ QVERIFY_SQL(q, exec(QString("CREATE TABLE %1 (id INT AUTO_INCREMENT PRIMARY KEY, "
|
||||
+ "test_number TINYINT(3) UNSIGNED)")
|
||||
+ .arg(tableName)));
|
||||
+
|
||||
+ QVERIFY_SQL(q, prepare("INSERT INTO " + tableName + " (test_number) VALUES (:value)"));
|
||||
+
|
||||
+ QVector<int>::iterator begin = values.begin(), end = values.end(), it;
|
||||
+ for (it = begin; it != end; ++it) {
|
||||
+ q.bindValue(":value", *it);
|
||||
+ QVERIFY_SQL(q, exec());
|
||||
+ }
|
||||
+
|
||||
+ QVERIFY_SQL(q, prepare("SELECT test_number FROM " + tableName));
|
||||
+ QVERIFY_SQL(q, exec());
|
||||
+
|
||||
+ while (q.next()) {
|
||||
+ bool ok;
|
||||
+ tableValues.push_back(q.value(0).toUInt(&ok));
|
||||
+ QVERIFY(ok);
|
||||
+ }
|
||||
+ QCOMPARE(values, tableValues);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void tst_QSqlQuery::oraOCINumber()
|
||||
{
|
||||
QFETCH( QString, dbName );
|
38
qt5/qtbug-55583.patch
Normal file
38
qt5/qtbug-55583.patch
Normal file
@ -0,0 +1,38 @@
|
||||
From 84ea00d47049d882f2fabf1446ec6c6eb5fe3038 Mon Sep 17 00:00:00 2001
|
||||
From: J-P Nurmi <jpnurmi@qt.io>
|
||||
Date: Tue, 6 Dec 2016 16:30:31 +0100
|
||||
Subject: [PATCH] QGtk3Dialog: don't crash on Wayland
|
||||
|
||||
Check if it's an X11 window before calling XSetTransientForHint().
|
||||
No transient parent will be set for GTK+ dialogs on Wayland. That
|
||||
has to be implemented separately.
|
||||
|
||||
Task-number: QTBUG-55583
|
||||
Change-Id: Iabc2a72681c8157bb2f2fe500892853aa397106b
|
||||
Reviewed-by: Dmitry Shachnev <mitya57@gmail.com>
|
||||
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
|
||||
---
|
||||
src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp | 10 ++++++----
|
||||
1 file changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
|
||||
index ba5089a..699b058 100644
|
||||
--- a/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
|
||||
+++ b/src/plugins/platformthemes/gtk3/qgtk3dialoghelpers.cpp
|
||||
@@ -135,10 +135,12 @@ bool QGtk3Dialog::show(Qt::WindowFlags flags, Qt::WindowModality modality, QWind
|
||||
|
||||
GdkWindow *gdkWindow = gtk_widget_get_window(gtkWidget);
|
||||
if (parent) {
|
||||
- GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
|
||||
- XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
|
||||
- gdk_x11_window_get_xid(gdkWindow),
|
||||
- parent->winId());
|
||||
+ if (GDK_IS_X11_WINDOW(gdkWindow)) {
|
||||
+ GdkDisplay *gdkDisplay = gdk_window_get_display(gdkWindow);
|
||||
+ XSetTransientForHint(gdk_x11_display_get_xdisplay(gdkDisplay),
|
||||
+ gdk_x11_window_get_xid(gdkWindow),
|
||||
+ parent->winId());
|
||||
+ }
|
||||
}
|
||||
|
||||
if (modality != Qt::NonModal) {
|
Loading…
x
Reference in New Issue
Block a user