summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--examples/widgets/mainwindows/mainwindow/colorswatch.cpp31
-rw-r--r--examples/widgets/widgets/charactermap/mainwindow.cpp32
-rw-r--r--src/corelib/kernel/qobject.cpp4
-rw-r--r--src/corelib/kernel/qobjectdefs.h2
-rw-r--r--src/corelib/tools/qvector.h6
-rw-r--r--src/gui/image/qimage.cpp42
-rw-r--r--src/gui/image/qpixmap.cpp6
-rw-r--r--src/gui/opengl/qopengldebug.cpp40
-rw-r--r--src/gui/painting/qbackingstore.cpp15
-rw-r--r--src/gui/text/qfontengine_ft.cpp5
-rw-r--r--src/platformsupport/fbconvenience/qfbvthandler.cpp18
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp5
-rw-r--r--src/widgets/dialogs/qdialog.cpp6
-rw-r--r--src/widgets/itemviews/qabstractitemdelegate.cpp55
-rw-r--r--src/widgets/itemviews/qabstractitemdelegate_p.h3
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp6
-rw-r--r--src/widgets/itemviews/qabstractitemview_p.h5
-rw-r--r--src/widgets/itemviews/qitemdelegate.cpp42
-rw-r--r--src/widgets/itemviews/qstyleditemdelegate.cpp36
-rw-r--r--src/widgets/styles/qwindowsstyle.cpp47
-rw-r--r--src/widgets/styles/qwindowsstyle_p_p.h2
-rw-r--r--src/widgets/styles/qwindowsvistastyle.cpp22
-rw-r--r--src/widgets/styles/qwindowsxpstyle.cpp15
-rw-r--r--tests/auto/corelib/tools/qvector/tst_qvector.cpp22
-rw-r--r--tests/auto/gui/image/qimage/tst_qimage.cpp38
-rw-r--r--tests/auto/other/qobjectrace/tst_qobjectrace.cpp175
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro2
-rw-r--r--tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp62
30 files changed, 572 insertions, 184 deletions
diff --git a/.gitignore b/.gitignore
index 1beec5c3ec..a48134a899 100644
--- a/.gitignore
+++ b/.gitignore
@@ -147,6 +147,8 @@ tools/activeqt/testcon/testcon.tlb
translations/*.qm
translations/*_untranslated.ts
qrc_*.cpp
+*.version
+*.version.in
# Test generated files
QObject.log
diff --git a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
index 226f335c85..73076c20b0 100644
--- a/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
+++ b/examples/widgets/mainwindows/mainwindow/colorswatch.cpp
@@ -61,6 +61,7 @@
#include <QDialog>
#include <QDialogButtonBox>
#include <QGridLayout>
+#include <QSignalBlocker>
#include <QSpinBox>
#include <QLabel>
#include <QPainterPath>
@@ -426,20 +427,22 @@ void ColorSwatch::updateContextMenu()
allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea);
}
- leftAction->blockSignals(true);
- rightAction->blockSignals(true);
- topAction->blockSignals(true);
- bottomAction->blockSignals(true);
-
- leftAction->setChecked(area == Qt::LeftDockWidgetArea);
- rightAction->setChecked(area == Qt::RightDockWidgetArea);
- topAction->setChecked(area == Qt::TopDockWidgetArea);
- bottomAction->setChecked(area == Qt::BottomDockWidgetArea);
-
- leftAction->blockSignals(false);
- rightAction->blockSignals(false);
- topAction->blockSignals(false);
- bottomAction->blockSignals(false);
+ {
+ const QSignalBlocker blocker(leftAction);
+ leftAction->setChecked(area == Qt::LeftDockWidgetArea);
+ }
+ {
+ const QSignalBlocker blocker(rightAction);
+ rightAction->setChecked(area == Qt::RightDockWidgetArea);
+ }
+ {
+ const QSignalBlocker blocker(topAction);
+ topAction->setChecked(area == Qt::TopDockWidgetArea);
+ }
+ {
+ const QSignalBlocker blocker(bottomAction);
+ bottomAction->setChecked(area == Qt::BottomDockWidgetArea);
+ }
if (areaActions->isEnabled()) {
leftAction->setEnabled(areas & Qt::LeftDockWidgetArea);
diff --git a/examples/widgets/widgets/charactermap/mainwindow.cpp b/examples/widgets/widgets/charactermap/mainwindow.cpp
index 160b77a945..2141850f16 100644
--- a/examples/widgets/widgets/charactermap/mainwindow.cpp
+++ b/examples/widgets/widgets/charactermap/mainwindow.cpp
@@ -167,25 +167,27 @@ void MainWindow::findSizes(const QFont &font)
{
QFontDatabase fontDatabase;
QString currentSize = sizeCombo->currentText();
- sizeCombo->blockSignals(true);
- sizeCombo->clear();
-
- int size;
- if(fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) {
- foreach(size, QFontDatabase::standardSizes()) {
- sizeCombo->addItem(QVariant(size).toString());
- sizeCombo->setEditable(true);
- }
- } else {
- foreach(size, fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font))) {
- sizeCombo->addItem(QVariant(size).toString());
- sizeCombo->setEditable(false);
+ {
+ const QSignalBlocker blocker(sizeCombo);
+ // sizeCombo signals are now blocked until end of scope
+ sizeCombo->clear();
+
+ int size;
+ if (fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) {
+ foreach (size, QFontDatabase::standardSizes()) {
+ sizeCombo->addItem(QVariant(size).toString());
+ sizeCombo->setEditable(true);
+ }
+
+ } else {
+ foreach (size, fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font))) {
+ sizeCombo->addItem(QVariant(size).toString());
+ sizeCombo->setEditable(false);
+ }
}
}
- sizeCombo->blockSignals(false);
-
int sizeIndex = sizeCombo->findText(currentSize);
if(sizeIndex == -1)
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index ffb50ddac3..c235260f1b 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -3693,7 +3693,6 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
continue;
#ifndef QT_NO_THREAD
} else if (c->connectionType == Qt::BlockingQueuedConnection) {
- locker.unlock();
if (receiverInSameThread) {
qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
"Sender is %s(%p), receiver is %s(%p)",
@@ -3705,6 +3704,7 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
new QMetaCallEvent(c->slotObj, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore) :
new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore);
QCoreApplication::postEvent(receiver, ev);
+ locker.unlock();
semaphore.acquire();
locker.relock();
continue;
@@ -4272,7 +4272,7 @@ QDebug operator<<(QDebug dbg, const QObject *o)
\relates QObject
\since 5.5
- This macro registers a single \l{QFlags}{flags types} with the
+ This macro registers a single \l{QFlags}{flags type} with the
meta-object system. It is typically used in a class definition to declare
that values of a given enum can be used as flags and combined using the
bitwise OR operator.
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index f8bebdf617..3660d1c0e1 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -180,6 +180,8 @@ inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {}
#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override")
+#elif defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 510
+# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_GCC("-Wsuggest-override")
#else
# define Q_OBJECT_NO_OVERRIDE_WARNING
#endif
diff --git a/src/corelib/tools/qvector.h b/src/corelib/tools/qvector.h
index b68ca87063..4dbf95c315 100644
--- a/src/corelib/tools/qvector.h
+++ b/src/corelib/tools/qvector.h
@@ -397,7 +397,11 @@ void QVector<T>::reserve(int asize)
{
if (asize > int(d->alloc))
reallocData(d->size, asize);
- if (isDetached())
+ if (isDetached()
+#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
+ && d != Data::unsharableEmpty()
+#endif
+ )
d->capacityReserved = 1;
Q_ASSERT(capacity() >= asize);
}
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 64dafdddc3..de02e9a1dd 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -841,17 +841,6 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
d->cleanupFunction = cleanupFunction;
d->cleanupInfo = cleanupInfo;
- switch (format) {
- case QImage::Format_Mono:
- case QImage::Format_MonoLSB:
- d->colortable.resize(2);
- d->colortable[0] = QColor(Qt::black).rgba();
- d->colortable[1] = QColor(Qt::white).rgba();
- break;
- default:
- break;
- }
-
return d;
}
@@ -2250,21 +2239,30 @@ QRgb QImage::pixel(int x, int y) const
}
const uchar *s = d->data + y * d->bytes_per_line;
- switch(d->format) {
+
+ int index = -1;
+ switch (d->format) {
case Format_Mono:
- return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1);
+ index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
+ break;
case Format_MonoLSB:
- return d->colortable.at((*(s + (x >> 3)) >> (x & 7)) & 1);
+ index = (*(s + (x >> 3)) >> (x & 7)) & 1;
+ break;
case Format_Indexed8:
- {
- int index = (int)s[x];
- if (index < d->colortable.size()) {
- return d->colortable.at(index);
- } else {
- qWarning("QImage::pixel: color table index %d out of range.", index);
- return 0;
- }
+ index = s[x];
+ break;
+ default:
+ break;
+ }
+ if (index >= 0) { // Indexed format
+ if (index >= d->colortable.size()) {
+ qWarning("QImage::pixel: color table index %d out of range.", index);
+ return 0;
}
+ return d->colortable.at(index);
+ }
+
+ switch (d->format) {
case Format_RGB32:
return 0xff000000 | reinterpret_cast<const QRgb *>(s)[x];
case Format_ARGB32: // Keep old behaviour.
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 09d23c0084..59d6dc12c6 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -1418,10 +1418,8 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
QPixmap using the fromImage(). If this is too expensive an
operation, you can use QBitmap::fromImage() instead.
- The QPixmap class also supports conversion to and from HICON:
- the toWinHICON() function creates a HICON equivalent to the
- QPixmap, and returns the HICON handle. The fromWinHICON()
- function returns a QPixmap that is equivalent to the given icon.
+ To convert a QPixmap to and from HICON you can use the QtWinExtras
+ functions QtWin::toHICON() and QtWin::fromHICON() respectively.
\section1 Pixmap Transformations
diff --git a/src/gui/opengl/qopengldebug.cpp b/src/gui/opengl/qopengldebug.cpp
index 24aa6094dd..f6c3af37dd 100644
--- a/src/gui/opengl/qopengldebug.cpp
+++ b/src/gui/opengl/qopengldebug.cpp
@@ -42,6 +42,7 @@
#include <QtCore/qvarlengtharray.h>
#include <QtGui/qopengl.h>
#include <QtGui/qopenglfunctions.h>
+#include <QtGui/qoffscreensurface.h>
#include "qopengldebug.h"
@@ -1287,8 +1288,41 @@ void QOpenGLDebugLoggerPrivate::controlDebugMessages(QOpenGLDebugMessage::Source
*/
void QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed()
{
+ Q_ASSERT(context);
+
+ // Re-make our context current somehow, otherwise stopLogging will fail.
+
+ // Save the current context and its surface in case we need to set them back
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ QSurface *currentSurface = 0;
+
+ QScopedPointer<QOffscreenSurface> offscreenSurface;
+
+ if (context != currentContext) {
+ // Make our old context current on a temporary surface
+ if (currentContext)
+ currentSurface = currentContext->surface();
+
+ offscreenSurface.reset(new QOffscreenSurface);
+ offscreenSurface->setFormat(context->format());
+ offscreenSurface->create();
+ if (!context->makeCurrent(offscreenSurface.data()))
+ qWarning("QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed(): could not make the owning GL context current for cleanup");
+ }
+
Q_Q(QOpenGLDebugLogger);
q->stopLogging();
+
+ if (offscreenSurface) {
+ // We did change the current context: set it back
+ if (currentContext)
+ currentContext->makeCurrent(currentSurface);
+ else
+ context->doneCurrent();
+ }
+
+ QObject::disconnect(context, SIGNAL(aboutToBeDestroyed()), q, SLOT(_q_contextAboutToBeDestroyed()));
+ context = 0;
initialized = false;
}
@@ -1494,6 +1528,12 @@ void QOpenGLDebugLogger::stopLogging()
if (!d->isLogging)
return;
+ QOpenGLContext *currentContext = QOpenGLContext::currentContext();
+ if (!currentContext || currentContext != d->context) {
+ qWarning("QOpenGLDebugLogger::stopLogging(): attempting to stop logging with the wrong OpenGL context current");
+ return;
+ }
+
d->isLogging = false;
d->glDebugMessageCallback(d->oldDebugCallbackFunction, d->oldDebugCallbackParameter);
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 801397751b..e3d18512dd 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -236,11 +236,16 @@ QSize QBackingStore::size() const
*/
bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
{
- Q_UNUSED(area);
- Q_UNUSED(dx);
- Q_UNUSED(dy);
-
- return d_ptr->platformBackingStore->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window), QHighDpi::toNativePixels(dx, d_ptr->window), QHighDpi::toNativePixels(dy, d_ptr->window));
+ // Disable scrolling for non-integer scroll deltas. For this case
+ // the the existing rendered pixels can't be re-used, and we return
+ // false to signal that a repaint is needed.
+ const qreal nativeDx = QHighDpi::toNativePixels(qreal(dx), d_ptr->window);
+ const qreal nativeDy = QHighDpi::toNativePixels(qreal(dy), d_ptr->window);
+ if (qFloor(nativeDx) != nativeDx || qFloor(nativeDy) != nativeDy)
+ return false;
+
+ return d_ptr->platformBackingStore->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window),
+ nativeDx, nativeDy);
}
/*!
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index 26ed81a091..51b1418bc3 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1849,7 +1849,10 @@ static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEng
Q_UNREACHABLE();
};
- return QImage(static_cast<const uchar *>(glyph->data), glyph->width, glyph->height, bytesPerLine, format);
+ QImage img(static_cast<const uchar *>(glyph->data), glyph->width, glyph->height, bytesPerLine, format);
+ if (format == QImage::Format_Mono)
+ img.setColor(1, QColor(Qt::white).rgba()); // Expands color table to 2 items; item 0 set to transparent.
+ return img;
}
QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition,
diff --git a/src/platformsupport/fbconvenience/qfbvthandler.cpp b/src/platformsupport/fbconvenience/qfbvthandler.cpp
index 2e5d00c8bd..4c4a01a82e 100644
--- a/src/platformsupport/fbconvenience/qfbvthandler.cpp
+++ b/src/platformsupport/fbconvenience/qfbvthandler.cpp
@@ -116,14 +116,16 @@ QFbVtHandler::QFbVtHandler(QObject *parent)
m_signalNotifier = new QSocketNotifier(m_sigFd[1], QSocketNotifier::Read, this);
connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal);
- struct sigaction sa;
- sa.sa_flags = 0;
- sa.sa_handler = signalHandler;
- sigemptyset(&sa.sa_mask);
- sigaction(SIGINT, &sa, 0); // Ctrl+C
- sigaction(SIGTSTP, &sa, 0); // Ctrl+Z
- sigaction(SIGCONT, &sa, 0);
- sigaction(SIGTERM, &sa, 0); // default signal used by kill
+ if (!qEnvironmentVariableIntValue("QT_QPA_NO_SIGNAL_HANDLER")) {
+ struct sigaction sa;
+ sa.sa_flags = 0;
+ sa.sa_handler = signalHandler;
+ sigemptyset(&sa.sa_mask);
+ sigaction(SIGINT, &sa, 0); // Ctrl+C
+ sigaction(SIGTSTP, &sa, 0); // Ctrl+Z
+ sigaction(SIGCONT, &sa, 0);
+ sigaction(SIGTERM, &sa, 0); // default signal used by kill
+ }
#endif
}
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 9eb1b26786..434d0ad953 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1599,7 +1599,7 @@ void QWindowsWindow::handleGeometryChange()
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
if (testFlag(SynchronousGeometryChangeEvent))
- QWindowSystemInterface::flushWindowSystemEvents();
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
}
@@ -1689,7 +1689,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
// Our tests depend on it.
fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true);
if (!QWindowsContext::instance()->asyncExpose())
- QWindowSystemInterface::flushWindowSystemEvents();
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
EndPaint(hwnd, &ps);
return true;
@@ -1749,7 +1749,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
switch (state) {
case Qt::WindowMinimized:
handleHidden();
- QWindowSystemInterface::flushWindowSystemEvents(); // Tell QQuickWindow to stop rendering now.
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
break;
case Qt::WindowMaximized:
case Qt::WindowFullScreen:
@@ -1772,7 +1772,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
}
}
if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
- QWindowSystemInterface::flushWindowSystemEvents();
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
}
break;
default:
@@ -1878,7 +1878,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent);
QWindowSystemInterface::handleGeometryChange(window(), r);
- QWindowSystemInterface::flushWindowSystemEvents();
+ QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
} else if (newState != Qt::WindowMinimized) {
// Restore saved state.
unsigned newStyle = m_savedStyle ? m_savedStyle : style();
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index bf1fd2e177..54c93bea39 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -2195,8 +2195,11 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
const bool isWheel = detail >= 4 && detail <= 7;
if (!isWheel && window() != QGuiApplication::focusWindow()) {
QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver();
- if (!(w->flags() & Qt::WindowDoesNotAcceptFocus))
+ if (!(w->flags() & (Qt::WindowDoesNotAcceptFocus | Qt::BypassWindowManagerHint))
+ && w->type() != Qt::ToolTip
+ && w->type() != Qt::Popup) {
w->requestActivate();
+ }
}
updateNetWmUserTime(timestamp);
diff --git a/src/widgets/dialogs/qdialog.cpp b/src/widgets/dialogs/qdialog.cpp
index 8f3072e41c..bfc943966f 100644
--- a/src/widgets/dialogs/qdialog.cpp
+++ b/src/widgets/dialogs/qdialog.cpp
@@ -874,8 +874,10 @@ void QDialog::adjustPosition(QWidget* w)
// QTBUG-52735: Manually set the correct target screen since scaling in a
// subsequent call to QWindow::resize() may otherwise use the wrong factor
// if the screen changed notification is still in an event queue.
- if (QWindow *window = windowHandle())
- window->setScreen(QGuiApplication::screens().at(scrn));
+ if (scrn >= 0) {
+ if (QWindow *window = windowHandle())
+ window->setScreen(QGuiApplication::screens().at(scrn));
+ }
move(p);
}
diff --git a/src/widgets/itemviews/qabstractitemdelegate.cpp b/src/widgets/itemviews/qabstractitemdelegate.cpp
index 6ed019f4a8..5e3b74f7b7 100644
--- a/src/widgets/itemviews/qabstractitemdelegate.cpp
+++ b/src/widgets/itemviews/qabstractitemdelegate.cpp
@@ -376,6 +376,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
const QStyleOptionViewItem &option,
const QModelIndex &index)
{
+ Q_D(QAbstractItemDelegate);
Q_UNUSED(option);
if (!event || !view)
@@ -384,9 +385,10 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
#ifndef QT_NO_TOOLTIP
case QEvent::ToolTip: {
QHelpEvent *he = static_cast<QHelpEvent*>(event);
- QVariant tooltip = index.data(Qt::ToolTipRole);
- if (tooltip.canConvert<QString>()) {
- QToolTip::showText(he->globalPos(), tooltip.toString(), view);
+ const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp
+ const QString tooltip = d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision);
+ if (!tooltip.isEmpty()) {
+ QToolTip::showText(he->globalPos(), tooltip, view);
return true;
}
break;}
@@ -398,9 +400,10 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
break; }
case QEvent::WhatsThis: {
QHelpEvent *he = static_cast<QHelpEvent*>(event);
- QVariant whatsthis = index.data(Qt::WhatsThisRole);
- if (whatsthis.canConvert<QString>()) {
- QWhatsThis::showText(he->globalPos(), whatsthis.toString(), view);
+ const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp
+ const QString whatsthis = d->textForRole(Qt::WhatsThisRole, index.data(Qt::WhatsThisRole), option.locale, precision);
+ if (!whatsthis.isEmpty()) {
+ QWhatsThis::showText(he->globalPos(), whatsthis, view);
return true;
}
break ; }
@@ -543,6 +546,46 @@ bool QAbstractItemDelegatePrivate::tryFixup(QWidget *editor)
return true;
}
+QString QAbstractItemDelegatePrivate::textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale, int precision) const
+{
+ const QLocale::FormatType formatType = (role == Qt::DisplayRole) ? QLocale::ShortFormat : QLocale::LongFormat;
+ QString text;
+ switch (value.userType()) {
+ case QMetaType::Float:
+ text = locale.toString(value.toFloat());
+ break;
+ case QVariant::Double:
+ text = locale.toString(value.toDouble(), 'g', precision);
+ break;
+ case QVariant::Int:
+ case QVariant::LongLong:
+ text = locale.toString(value.toLongLong());
+ break;
+ case QVariant::UInt:
+ case QVariant::ULongLong:
+ text = locale.toString(value.toULongLong());
+ break;
+ case QVariant::Date:
+ text = locale.toString(value.toDate(), formatType);
+ break;
+ case QVariant::Time:
+ text = locale.toString(value.toTime(), formatType);
+ break;
+ case QVariant::DateTime: {
+ const QDateTime dateTime = value.toDateTime();
+ text = locale.toString(dateTime.date(), formatType)
+ + QLatin1Char(' ')
+ + locale.toString(dateTime.time(), formatType);
+ break; }
+ default:
+ text = value.toString();
+ if (role == Qt::DisplayRole)
+ text.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ break;
+ }
+ return text;
+}
+
void QAbstractItemDelegatePrivate::_q_commitDataAndCloseEditor(QWidget *editor)
{
Q_Q(QAbstractItemDelegate);
diff --git a/src/widgets/itemviews/qabstractitemdelegate_p.h b/src/widgets/itemviews/qabstractitemdelegate_p.h
index 2fd38bdfd7..958737dd01 100644
--- a/src/widgets/itemviews/qabstractitemdelegate_p.h
+++ b/src/widgets/itemviews/qabstractitemdelegate_p.h
@@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE
-class QAbstractItemDelegatePrivate : public QObjectPrivate
+class Q_AUTOTEST_EXPORT QAbstractItemDelegatePrivate : public QObjectPrivate
{
Q_DECLARE_PUBLIC(QAbstractItemDelegate)
public:
@@ -66,6 +66,7 @@ public:
bool editorEventFilter(QObject *object, QEvent *event);
bool tryFixup(QWidget *editor);
+ QString textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale, int precision = 6) const;
void _q_commitDataAndCloseEditor(QWidget *editor);
};
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index e67f8d83fb..83b9b7716d 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -4325,6 +4325,12 @@ const QEditorInfo & QAbstractItemViewPrivate::editorForIndex(const QModelIndex &
return it.value();
}
+bool QAbstractItemViewPrivate::hasEditor(const QModelIndex &index) const
+{
+ // Search's implicit cast (QModelIndex to QPersistentModelIndex) is slow; use cheap pre-test to avoid when we can.
+ return !indexEditorHash.isEmpty() && indexEditorHash.contains(index);
+}
+
QModelIndex QAbstractItemViewPrivate::indexForEditor(QWidget *editor) const
{
// do not try to search to avoid slow implicit cast from QModelIndex to QPersistentModelIndex
diff --git a/src/widgets/itemviews/qabstractitemview_p.h b/src/widgets/itemviews/qabstractitemview_p.h
index 60ae1559b1..fcbe25d735 100644
--- a/src/widgets/itemviews/qabstractitemview_p.h
+++ b/src/widgets/itemviews/qabstractitemview_p.h
@@ -276,10 +276,7 @@ public:
}
const QEditorInfo &editorForIndex(const QModelIndex &index) const;
- inline bool hasEditor(const QModelIndex &index) const {
- // Search's implicit cast (QModelIndex to QPersistentModelIndex) is slow; use cheap pre-test to avoid when we can.
- return !indexEditorHash.isEmpty() && indexEditorHash.contains(index);
- }
+ bool hasEditor(const QModelIndex &index) const;
QModelIndex indexForEditor(QWidget *editor) const;
void addEditor(const QModelIndex &index, QWidget *editor, bool isStatic);
diff --git a/src/widgets/itemviews/qitemdelegate.cpp b/src/widgets/itemviews/qitemdelegate.cpp
index 194bd22493..747d5db782 100644
--- a/src/widgets/itemviews/qitemdelegate.cpp
+++ b/src/widgets/itemviews/qitemdelegate.cpp
@@ -67,6 +67,7 @@
#include <limits.h>
+// keep in sync with QAbstractItemDelegate::helpEvent()
#ifndef DBL_DIG
# define DBL_DIG 10
#endif
@@ -102,7 +103,7 @@ public:
return text;
}
- static QString valueToText(const QVariant &value, const QStyleOptionViewItem &option);
+ QString valueToText(const QVariant &value, const QStyleOptionViewItem &option) const;
QItemEditorFactory *f;
bool clipPainting;
@@ -332,40 +333,9 @@ void QItemDelegate::setClipping(bool clip)
d->clipPainting = clip;
}
-QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOptionViewItem &option)
+QString QItemDelegatePrivate::valueToText(const QVariant &value, const QStyleOptionViewItem &option) const
{
- QString text;
- switch (value.userType()) {
- case QMetaType::Float:
- text = option.locale.toString(value.toFloat(), 'g');
- break;
- case QVariant::Double:
- text = option.locale.toString(value.toDouble(), 'g', DBL_DIG);
- break;
- case QVariant::Int:
- case QVariant::LongLong:
- text = option.locale.toString(value.toLongLong());
- break;
- case QVariant::UInt:
- case QVariant::ULongLong:
- text = option.locale.toString(value.toULongLong());
- break;
- case QVariant::Date:
- text = option.locale.toString(value.toDate(), QLocale::ShortFormat);
- break;
- case QVariant::Time:
- text = option.locale.toString(value.toTime(), QLocale::ShortFormat);
- break;
- case QVariant::DateTime:
- text = option.locale.toString(value.toDateTime().date(), QLocale::ShortFormat);
- text += QLatin1Char(' ');
- text += option.locale.toString(value.toDateTime().time(), QLocale::ShortFormat);
- break;
- default:
- text = replaceNewLine(value.toString());
- break;
- }
- return text;
+ return textForRole(Qt::DisplayRole, value, option.locale, DBL_DIG);
}
/*!
@@ -434,7 +404,7 @@ void QItemDelegate::paint(QPainter *painter,
QRect displayRect;
value = index.data(Qt::DisplayRole);
if (value.isValid() && !value.isNull()) {
- text = QItemDelegatePrivate::valueToText(value, opt);
+ text = d->valueToText(value, opt);
displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text);
}
@@ -1061,7 +1031,7 @@ QRect QItemDelegate::rect(const QStyleOptionViewItem &option,
return QRect(QPoint(0, 0), option.decorationSize);
case QVariant::String:
default: {
- QString text = QItemDelegatePrivate::valueToText(value, option);
+ const QString text = d->valueToText(value, option);
value = index.data(Qt::FontRole);
QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
return textRectangle(0, d->textLayoutBounds(option), fnt, text); }
diff --git a/src/widgets/itemviews/qstyleditemdelegate.cpp b/src/widgets/itemviews/qstyleditemdelegate.cpp
index 162ef826da..bab8436dce 100644
--- a/src/widgets/itemviews/qstyleditemdelegate.cpp
+++ b/src/widgets/itemviews/qstyleditemdelegate.cpp
@@ -261,41 +261,7 @@ QStyledItemDelegate::~QStyledItemDelegate()
*/
QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const
{
- QString text;
- switch (value.userType()) {
- case QMetaType::Float:
- case QVariant::Double:
- text = locale.toString(value.toReal());
- break;
- case QVariant::Int:
- case QVariant::LongLong:
- text = locale.toString(value.toLongLong());
- break;
- case QVariant::UInt:
- case QVariant::ULongLong:
- text = locale.toString(value.toULongLong());
- break;
- case QVariant::Date:
- text = locale.toString(value.toDate(), QLocale::ShortFormat);
- break;
- case QVariant::Time:
- text = locale.toString(value.toTime(), QLocale::ShortFormat);
- break;
- case QVariant::DateTime:
- text = locale.toString(value.toDateTime().date(), QLocale::ShortFormat);
- text += QLatin1Char(' ');
- text += locale.toString(value.toDateTime().time(), QLocale::ShortFormat);
- break;
- default:
- // convert new lines into line separators
- text = value.toString();
- for (int i = 0; i < text.count(); ++i) {
- if (text.at(i) == QLatin1Char('\n'))
- text[i] = QChar::LineSeparator;
- }
- break;
- }
- return text;
+ return d_func()->textForRole(Qt::DisplayRole, value, locale);
}
/*!
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index 3eca9aef7f..075cb3719f 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -65,8 +65,12 @@
#include "qlistview.h"
#include <private/qmath_p.h>
#include <qmath.h>
+#include <QtGui/qscreen.h>
+#include <QtGui/qwindow.h>
#include <qpa/qplatformtheme.h>
+#include <qpa/qplatformscreen.h>
#include <private/qguiapplication_p.h>
+#include <private/qhighdpiscaling_p.h>
#include <private/qstylehelper_p.h>
#include <private/qstyleanimation_p.h>
@@ -402,6 +406,47 @@ int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
return QWindowsStylePrivate::InvalidMetric;
}
+static QWindow *windowOf(const QWidget *w)
+{
+ QWindow *result = Q_NULLPTR;
+ if (w) {
+ result = w->windowHandle();
+ if (!result) {
+ if (const QWidget *np = w->nativeParentWidget())
+ result = np->windowHandle();
+ }
+ }
+ return result;
+}
+
+static QScreen *screenOf(const QWidget *w)
+{
+ if (const QWindow *window = windowOf(w))
+ return window->screen();
+ return QGuiApplication::primaryScreen();
+}
+
+// Calculate the overall scale factor to obtain Qt Device Independent
+// Pixels from a native Windows size. Divide by devicePixelRatio
+// and account for secondary screens with differing logical DPI.
+qreal QWindowsStylePrivate::nativeMetricScaleFactor(const QWidget *widget)
+{
+ if (!QHighDpiScaling::isActive())
+ return 1;
+ qreal result = qreal(1) / QWindowsStylePrivate::devicePixelRatio(widget);
+ if (QGuiApplicationPrivate::screen_list.size() > 1) {
+ const QScreen *primaryScreen = QGuiApplication::primaryScreen();
+ const QScreen *screen = screenOf(widget);
+ if (screen != primaryScreen) {
+ const qreal primaryLogicalDpi = primaryScreen->handle()->logicalDpi().first;
+ const qreal logicalDpi = screen->handle()->logicalDpi().first;
+ if (!qFuzzyCompare(primaryLogicalDpi, logicalDpi))
+ result *= logicalDpi / primaryLogicalDpi;
+ }
+ }
+ return result;
+}
+
/*!
\reimp
*/
@@ -409,7 +454,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
{
int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget);
if (ret != QWindowsStylePrivate::InvalidMetric)
- return qRound(qreal(ret) / QWindowsStylePrivate::devicePixelRatio(widget));
+ return qRound(qreal(ret) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
ret = QWindowsStylePrivate::fixedPixelMetric(pm);
if (ret != QWindowsStylePrivate::InvalidMetric)
diff --git a/src/widgets/styles/qwindowsstyle_p_p.h b/src/widgets/styles/qwindowsstyle_p_p.h
index e6c44f401e..f034255837 100644
--- a/src/widgets/styles/qwindowsstyle_p_p.h
+++ b/src/widgets/styles/qwindowsstyle_p_p.h
@@ -72,6 +72,7 @@ public:
static int fixedPixelMetric(QStyle::PixelMetric pm);
static qreal devicePixelRatio(const QWidget *widget = 0)
{ return widget ? widget->devicePixelRatioF() : QWindowsStylePrivate::appDevicePixelRatio(); }
+ static qreal nativeMetricScaleFactor(const QWidget *widget = Q_NULLPTR);
bool hasSeenAlt(const QWidget *widget) const;
bool altDown() const { return alt_down; }
@@ -104,3 +105,4 @@ QT_END_NAMESPACE
#endif // QT_NO_STYLE_WINDOWS
#endif //QWINDOWSSTYLE_P_P_H
+;
diff --git a/src/widgets/styles/qwindowsvistastyle.cpp b/src/widgets/styles/qwindowsvistastyle.cpp
index 5c227b9d5d..1f4598ea14 100644
--- a/src/widgets/styles/qwindowsvistastyle.cpp
+++ b/src/widgets/styles/qwindowsvistastyle.cpp
@@ -432,7 +432,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
XPThemeData themeSize = theme;
themeSize.partId = TVP_HOTGLYPH;
themeSize.stateId = GLPS_OPENED;
- const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
decoration_size = qRound(qMax(size.width(), size.height()));
}
int mid_h = option->rect.x() + option->rect.width() / 2;
@@ -994,7 +994,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
TP_DROPDOWNBUTTON);
if (theme.isValid()) {
- const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
if (!size.isEmpty()) {
mbiw = qRound(size.width());
mbih = qRound(size.height());
@@ -1190,8 +1190,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData themeSize = theme;
themeSize.partId = MENU_POPUPCHECK;
themeSize.stateId = 0;
- const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
- const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
+ const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right()));
}
QRect rect = option->rect;
@@ -1216,7 +1216,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
int yoff = y-2 + h / 2;
- const int separatorSize = 6 / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const int separatorSize = qRound(qreal(6) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
QPoint p1 = QPoint(x + checkcol, yoff);
QPoint p2 = QPoint(x + w + separatorSize, yoff);
stateId = MBI_HOT;
@@ -1249,8 +1249,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData themeSize = theme;
themeSize.partId = MENU_POPUPCHECK;
themeSize.stateId = 0;
- const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
- const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
+ const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()),
qRound(size.height() + margins.bottom() + margins.top()));
checkRect.moveCenter(vCheckRect.center());
@@ -1862,8 +1862,8 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption
XPThemeData themeSize = theme;
themeSize.partId = MENU_POPUPCHECK;
themeSize.stateId = 0;
- const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
- const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
+ const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), sz.height());
sz.rwidth() += qRound(size.width() + margins.left() + margins.right());
}
@@ -1973,7 +1973,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
int arrowWidth = 13;
int arrowHeight = 5;
if (theme.isValid()) {
- const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget);
+ const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
if (!size.isEmpty()) {
arrowWidth = qRound(size.width());
arrowHeight = qRound(size.height());
@@ -2456,7 +2456,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
QWindowsXPStylePrivate::ButtonTheme,
BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
if (theme.isValid()) {
- const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize();
+ const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QIcon linkGlyph;
QPixmap pm(size);
pm.fill(Qt::transparent);
diff --git a/src/widgets/styles/qwindowsxpstyle.cpp b/src/widgets/styles/qwindowsxpstyle.cpp
index 900597cdab..ed4271505b 100644
--- a/src/widgets/styles/qwindowsxpstyle.cpp
+++ b/src/widgets/styles/qwindowsxpstyle.cpp
@@ -489,7 +489,7 @@ const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget)
{
if (!tabbody) {
XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY);
- const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize();
+ const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height());
QPainter painter(tabbody);
@@ -3457,7 +3457,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget);
if (res != QWindowsStylePrivate::InvalidMetric)
- return qRound(qreal(res) / QWindowsStylePrivate::devicePixelRatio(widget));
+ return qRound(qreal(res) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
res = 0;
switch (pm) {
@@ -3603,9 +3603,10 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
const int height = tb->rect.height();
const int width = tb->rect.width();
const int buttonMargin = int(QStyleHelper::dpiScaled(4));
- int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget))
+ const qreal factor = QWindowsStylePrivate::nativeMetricScaleFactor(widget);
+ int buttonHeight = qRound(qreal(GetSystemMetrics(SM_CYSIZE)) * factor)
- buttonMargin;
- int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget))
+ int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * factor)
- buttonMargin;
const int delta = buttonWidth + 2;
int controlTop = option->rect.bottom() - buttonHeight - 2;
@@ -3975,7 +3976,7 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt
if (widget && widget->isWindow()) {
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL);
if (theme.isValid()) {
- const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize();
+ const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size);
}
}
@@ -4009,7 +4010,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_MAXBUTTON, MAXBS_NORMAL);
if (theme.isValid()) {
- const QSize size = (themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize();
+ const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QPixmap pm(size);
pm.fill(Qt::transparent);
QPainter p(&pm);
@@ -4043,7 +4044,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_SMALLCLOSEBUTTON, CBS_NORMAL);
if (theme.isValid()) {
- const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize();
+ const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QPixmap pm(size);
pm.fill(Qt::transparent);
QPainter p(&pm);
diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
index 825cb05d74..374fec221e 100644
--- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp
+++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp
@@ -271,6 +271,7 @@ private slots:
void testOperators() const;
void reserve();
+ void reserveZero();
void reallocAfterCopy_data();
void reallocAfterCopy();
void initializeListInt();
@@ -2365,13 +2366,34 @@ void tst_QVector::reserve()
{
QVector<Foo> a;
a.resize(2);
+ QCOMPARE(fooCtor, 2);
QVector<Foo> b(a);
b.reserve(1);
QCOMPARE(b.size(), a.size());
+ QCOMPARE(fooDtor, 0);
}
QCOMPARE(fooCtor, fooDtor);
}
+// This is a regression test for QTBUG-51758
+void tst_QVector::reserveZero()
+{
+ QVector<int> vec;
+ vec.detach();
+ vec.reserve(0); // should not crash
+ QCOMPARE(vec.size(), 0);
+ QCOMPARE(vec.capacity(), 0);
+ vec.squeeze();
+ QCOMPARE(vec.size(), 0);
+ QCOMPARE(vec.capacity(), 0);
+ vec.reserve(-1);
+ QCOMPARE(vec.size(), 0);
+ QCOMPARE(vec.capacity(), 0);
+ vec.append(42);
+ QCOMPARE(vec.size(), 1);
+ QVERIFY(vec.capacity() >= 1);
+}
+
// This is a regression test for QTBUG-11763, where memory would be reallocated
// soon after copying a QVector.
void tst_QVector::reallocAfterCopy_data()
diff --git a/tests/auto/gui/image/qimage/tst_qimage.cpp b/tests/auto/gui/image/qimage/tst_qimage.cpp
index 9e4a1abbb1..85d258de5b 100644
--- a/tests/auto/gui/image/qimage/tst_qimage.cpp
+++ b/tests/auto/gui/image/qimage/tst_qimage.cpp
@@ -94,6 +94,8 @@ private slots:
void setPixel_data();
void setPixel();
+ void defaultColorTable_data();
+ void defaultColorTable();
void setColorCount();
void setColor();
@@ -1450,6 +1452,38 @@ void tst_QImage::convertToFormatPreserveText()
QCOMPARE(imgResult2.textKeys(), listResult);
}
+void tst_QImage::defaultColorTable_data()
+{
+ QTest::addColumn<QImage::Format>("format");
+ QTest::addColumn<int>("createdDataCount");
+ QTest::addColumn<int>("externalDataCount");
+
+ // For historical reasons, internally created mono images get a default colormap.
+ // Externally created and Indexed8 images do not.
+ QTest::newRow("Mono") << QImage::Format_Mono << 2 << 0;
+ QTest::newRow("MonoLSB") << QImage::Format_MonoLSB << 2 << 0;
+ QTest::newRow("Indexed8") << QImage::Format_Indexed8 << 0 << 0;
+ QTest::newRow("ARGB32_PM") << QImage::Format_A2BGR30_Premultiplied << 0 << 0;
+}
+
+void tst_QImage::defaultColorTable()
+{
+ QFETCH(QImage::Format, format);
+ QFETCH(int, createdDataCount);
+ QFETCH(int, externalDataCount);
+
+ QImage img1(1, 1, format);
+ QCOMPARE(img1.colorCount(), createdDataCount);
+ QCOMPARE(img1.colorTable().size(), createdDataCount);
+
+ quint32 buf;
+ QImage img2(reinterpret_cast<uchar *>(&buf), 1, 1, format);
+ QCOMPARE(img2.colorCount(), externalDataCount);
+
+ QImage nullImg(0, 0, format);
+ QCOMPARE(nullImg.colorCount(), 0);
+}
+
void tst_QImage::setColorCount()
{
QImage img(0, 0, QImage::Format_Indexed8);
@@ -3182,8 +3216,8 @@ void tst_QImage::pixel()
QImage monolsb(&a, 1, 1, QImage::Format_MonoLSB);
QImage indexed(&a, 1, 1, QImage::Format_Indexed8);
- QCOMPARE(QColor(mono.pixel(0, 0)), QColor(Qt::black));
- QCOMPARE(QColor(monolsb.pixel(0, 0)), QColor(Qt::black));
+ mono.pixel(0, 0); // Don't crash
+ monolsb.pixel(0, 0); // Don't crash
indexed.pixel(0, 0); // Don't crash
}
}
diff --git a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
index ae5953aa35..aa78d70716 100644
--- a/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
+++ b/tests/auto/other/qobjectrace/tst_qobjectrace.cpp
@@ -46,6 +46,7 @@ class tst_QObjectRace: public QObject
private slots:
void moveToThreadRace();
void destroyRace();
+ void disconnectRace();
};
class RaceObject : public QObject
@@ -293,6 +294,180 @@ void tst_QObjectRace::destroyRace()
delete threads[i];
}
+static QAtomicInteger<unsigned> countedStructObjectsCount;
+struct CountedFunctor
+{
+ CountedFunctor() : destroyed(false) { countedStructObjectsCount.fetchAndAddRelaxed(1); }
+ CountedFunctor(const CountedFunctor &) : destroyed(false) { countedStructObjectsCount.fetchAndAddRelaxed(1); }
+ CountedFunctor &operator=(const CountedFunctor &) { return *this; }
+ ~CountedFunctor() { destroyed = true; countedStructObjectsCount.fetchAndAddRelaxed(-1);}
+ void operator()() const {QCOMPARE(destroyed, false);}
+
+private:
+ bool destroyed;
+};
+
+class DisconnectRaceSenderObject : public QObject
+{
+ Q_OBJECT
+signals:
+ void theSignal();
+};
+
+class DisconnectRaceThread : public QThread
+{
+ Q_OBJECT
+
+ DisconnectRaceSenderObject *sender;
+ bool emitSignal;
+public:
+ DisconnectRaceThread(DisconnectRaceSenderObject *s, bool emitIt)
+ : QThread(), sender(s), emitSignal(emitIt)
+ {
+ }
+
+ void run()
+ {
+ while (!isInterruptionRequested()) {
+ QMetaObject::Connection conn = connect(sender, &DisconnectRaceSenderObject::theSignal,
+ sender, CountedFunctor(), Qt::BlockingQueuedConnection);
+ if (emitSignal)
+ emit sender->theSignal();
+ disconnect(conn);
+ yieldCurrentThread();
+ }
+ }
+};
+
+class DeleteReceiverRaceSenderThread : public QThread
+{
+ Q_OBJECT
+
+ DisconnectRaceSenderObject *sender;
+public:
+ DeleteReceiverRaceSenderThread(DisconnectRaceSenderObject *s)
+ : QThread(), sender(s)
+ {
+ }
+
+ void run()
+ {
+ while (!isInterruptionRequested()) {
+ emit sender->theSignal();
+ yieldCurrentThread();
+ }
+ }
+};
+
+class DeleteReceiverRaceReceiver : public QObject
+{
+ Q_OBJECT
+
+ DisconnectRaceSenderObject *sender;
+ QObject *receiver;
+ QTimer *timer;
+public:
+ DeleteReceiverRaceReceiver(DisconnectRaceSenderObject *s)
+ : QObject(), sender(s), receiver(0)
+ {
+ timer = new QTimer(this);
+ connect(timer, &QTimer::timeout, this, &DeleteReceiverRaceReceiver::onTimeout);
+ timer->start(1);
+ }
+
+ void onTimeout()
+ {
+ if (receiver)
+ delete receiver;
+ receiver = new QObject;
+ connect(sender, &DisconnectRaceSenderObject::theSignal, receiver, CountedFunctor(), Qt::BlockingQueuedConnection);
+ }
+};
+
+class DeleteReceiverRaceReceiverThread : public QThread
+{
+ Q_OBJECT
+
+ DisconnectRaceSenderObject *sender;
+public:
+ DeleteReceiverRaceReceiverThread(DisconnectRaceSenderObject *s)
+ : QThread(), sender(s)
+ {
+ }
+
+ void run()
+ {
+ QScopedPointer<DeleteReceiverRaceReceiver> receiver(new DeleteReceiverRaceReceiver(sender));
+ exec();
+ }
+};
+
+void tst_QObjectRace::disconnectRace()
+{
+ enum { ThreadCount = 20, TimeLimit = 3000 };
+
+ QCOMPARE(countedStructObjectsCount.load(), 0u);
+
+ {
+ QScopedPointer<DisconnectRaceSenderObject> sender(new DisconnectRaceSenderObject());
+ QScopedPointer<QThread> senderThread(new QThread());
+ senderThread->start();
+ sender->moveToThread(senderThread.data());
+
+ DisconnectRaceThread *threads[ThreadCount];
+ for (int i = 0; i < ThreadCount; ++i) {
+ threads[i] = new DisconnectRaceThread(sender.data(), !(i % 10));
+ threads[i]->start();
+ }
+
+ QTime timeLimiter;
+ timeLimiter.start();
+
+ while (timeLimiter.elapsed() < TimeLimit)
+ QTest::qWait(10);
+
+ for (int i = 0; i < ThreadCount; ++i) {
+ threads[i]->requestInterruption();
+ QVERIFY(threads[i]->wait(300));
+ delete threads[i];
+ }
+
+ senderThread->quit();
+ QVERIFY(senderThread->wait(300));
+ }
+
+ QCOMPARE(countedStructObjectsCount.load(), 0u);
+
+ {
+ QScopedPointer<DisconnectRaceSenderObject> sender(new DisconnectRaceSenderObject());
+ QScopedPointer<DeleteReceiverRaceSenderThread> senderThread(new DeleteReceiverRaceSenderThread(sender.data()));
+ senderThread->start();
+ sender->moveToThread(senderThread.data());
+
+ DeleteReceiverRaceReceiverThread *threads[ThreadCount];
+ for (int i = 0; i < ThreadCount; ++i) {
+ threads[i] = new DeleteReceiverRaceReceiverThread(sender.data());
+ threads[i]->start();
+ }
+
+ QTime timeLimiter;
+ timeLimiter.start();
+
+ while (timeLimiter.elapsed() < TimeLimit)
+ QTest::qWait(10);
+
+ senderThread->requestInterruption();
+ QVERIFY(senderThread->wait(300));
+
+ for (int i = 0; i < ThreadCount; ++i) {
+ threads[i]->quit();
+ QVERIFY(threads[i]->wait(300));
+ delete threads[i];
+ }
+ }
+
+ QCOMPARE(countedStructObjectsCount.load(), 0u);
+}
QTEST_MAIN(tst_QObjectRace)
#include "tst_qobjectrace.moc"
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
index f7fb41e60c..02a71f8101 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
+++ b/tests/auto/widgets/itemviews/qitemdelegate/qitemdelegate.pro
@@ -1,6 +1,6 @@
CONFIG += testcase
TARGET = tst_qitemdelegate
-QT += widgets testlib
+QT += widgets widgets-private testlib
SOURCES += tst_qitemdelegate.cpp
win32:!wince:!winrt: LIBS += -luser32
diff --git a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
index 34713bdff9..972dabdcb8 100644
--- a/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
+++ b/tests/auto/widgets/itemviews/qitemdelegate/tst_qitemdelegate.cpp
@@ -51,6 +51,8 @@
#include <QPlainTextEdit>
#include <QDialog>
+#include <QtWidgets/private/qabstractitemdelegate_p.h>
+
Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint)
#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
@@ -216,6 +218,8 @@ private slots:
void task257859_finalizeEdit();
void QTBUG4435_keepSelectionOnCheck();
+
+ void QTBUG16469_textForRole();
};
@@ -1521,6 +1525,64 @@ void tst_QItemDelegate::testLineEditValidation()
QCOMPARE(item->data(Qt::DisplayRole).toString(), QStringLiteral("abc,def"));
}
+void tst_QItemDelegate::QTBUG16469_textForRole()
+{
+#ifndef QT_BUILD_INTERNAL
+ QSKIP("This test requires a developer build");
+#else
+ struct TestDelegate : public QItemDelegate
+ {
+ QString textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale)
+ {
+ QAbstractItemDelegatePrivate *d = reinterpret_cast<QAbstractItemDelegatePrivate *>(qGetPtrHelper(d_ptr));
+ return d->textForRole(role, value, locale);
+ }
+ } delegate;
+ QLocale locale;
+
+ const float f = 123.456f;
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, f, locale), locale.toString(f));
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, f, locale), locale.toString(f));
+ const double d = 123.456;
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, d, locale), locale.toString(d, 'g', 6));
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, d, locale), locale.toString(d, 'g', 6));
+ const int i = 1234567;
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, i, locale), locale.toString(i));
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, i, locale), locale.toString(i));
+ const qlonglong ll = 1234567;
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, ll, locale), locale.toString(ll));
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, ll, locale), locale.toString(ll));
+ const uint ui = 1234567;
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, ui, locale), locale.toString(ui));
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, ui, locale), locale.toString(ui));
+ const qulonglong ull = 1234567;
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, ull, locale), locale.toString(ull));
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, ull, locale), locale.toString(ull));
+
+ const QDateTime dateTime = QDateTime::currentDateTime();
+ const QDate date = dateTime.date();
+ const QTime time = dateTime.time();
+ const QString shortDate = locale.toString(date, QLocale::ShortFormat);
+ const QString longDate = locale.toString(date, QLocale::LongFormat);
+ const QString shortTime = locale.toString(time, QLocale::ShortFormat);
+ const QString longTime = locale.toString(time, QLocale::LongFormat);
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, date, locale), shortDate);
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, date, locale), longDate);
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, time, locale), shortTime);
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, time, locale), longTime);
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, dateTime, locale), shortDate + QLatin1Char(' ') + shortTime);
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, dateTime, locale), longDate + QLatin1Char(' ') + longTime);
+
+ const QString text("text");
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, text, locale), text);
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, text, locale), text);
+ const QString multipleLines("multiple\nlines");
+ QString multipleLines2 = multipleLines;
+ multipleLines2.replace(QLatin1Char('\n'), QChar::LineSeparator);
+ QCOMPARE(delegate.textForRole(Qt::DisplayRole, multipleLines, locale), multipleLines2);
+ QCOMPARE(delegate.textForRole(Qt::ToolTipRole, multipleLines, locale), multipleLines);
+#endif
+}
// ### _not_ covered: