Merge remote-tracking branch 'origin/5.6' into 5.7

Conflicts:
	src/widgets/itemviews/qabstractitemview.cpp
	src/widgets/itemviews/qabstractitemview_p.h

Change-Id: I54589b1365103cb1749186af92aab03a49c94b64
This commit is contained in:
Liang Qi 2016-08-01 08:51:18 +02:00
commit 3cb7302480
30 changed files with 570 additions and 182 deletions

2
.gitignore vendored
View File

@ -147,6 +147,8 @@ tools/activeqt/testcon/testcon.tlb
translations/*.qm translations/*.qm
translations/*_untranslated.ts translations/*_untranslated.ts
qrc_*.cpp qrc_*.cpp
*.version
*.version.in
# Test generated files # Test generated files
QObject.log QObject.log

View File

@ -61,6 +61,7 @@
#include <QDialog> #include <QDialog>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QGridLayout> #include <QGridLayout>
#include <QSignalBlocker>
#include <QSpinBox> #include <QSpinBox>
#include <QLabel> #include <QLabel>
#include <QPainterPath> #include <QPainterPath>
@ -426,20 +427,22 @@ void ColorSwatch::updateContextMenu()
allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea); allowBottomAction->setEnabled(area != Qt::BottomDockWidgetArea);
} }
leftAction->blockSignals(true); {
rightAction->blockSignals(true); const QSignalBlocker blocker(leftAction);
topAction->blockSignals(true); leftAction->setChecked(area == Qt::LeftDockWidgetArea);
bottomAction->blockSignals(true); }
{
leftAction->setChecked(area == Qt::LeftDockWidgetArea); const QSignalBlocker blocker(rightAction);
rightAction->setChecked(area == Qt::RightDockWidgetArea); rightAction->setChecked(area == Qt::RightDockWidgetArea);
topAction->setChecked(area == Qt::TopDockWidgetArea); }
bottomAction->setChecked(area == Qt::BottomDockWidgetArea); {
const QSignalBlocker blocker(topAction);
leftAction->blockSignals(false); topAction->setChecked(area == Qt::TopDockWidgetArea);
rightAction->blockSignals(false); }
topAction->blockSignals(false); {
bottomAction->blockSignals(false); const QSignalBlocker blocker(bottomAction);
bottomAction->setChecked(area == Qt::BottomDockWidgetArea);
}
if (areaActions->isEnabled()) { if (areaActions->isEnabled()) {
leftAction->setEnabled(areas & Qt::LeftDockWidgetArea); leftAction->setEnabled(areas & Qt::LeftDockWidgetArea);

View File

@ -167,25 +167,27 @@ void MainWindow::findSizes(const QFont &font)
{ {
QFontDatabase fontDatabase; QFontDatabase fontDatabase;
QString currentSize = sizeCombo->currentText(); QString currentSize = sizeCombo->currentText();
sizeCombo->blockSignals(true);
sizeCombo->clear();
int size; {
if(fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) { const QSignalBlocker blocker(sizeCombo);
foreach(size, QFontDatabase::standardSizes()) { // sizeCombo signals are now blocked until end of scope
sizeCombo->addItem(QVariant(size).toString()); sizeCombo->clear();
sizeCombo->setEditable(true);
}
} else { int size;
foreach(size, fontDatabase.smoothSizes(font.family(), fontDatabase.styleString(font))) { if (fontDatabase.isSmoothlyScalable(font.family(), fontDatabase.styleString(font))) {
sizeCombo->addItem(QVariant(size).toString()); foreach (size, QFontDatabase::standardSizes()) {
sizeCombo->setEditable(false); 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); int sizeIndex = sizeCombo->findText(currentSize);
if(sizeIndex == -1) if(sizeIndex == -1)

View File

@ -3693,7 +3693,6 @@ void QMetaObject::activate(QObject *sender, int signalOffset, int local_signal_i
continue; continue;
#ifndef QT_NO_THREAD #ifndef QT_NO_THREAD
} else if (c->connectionType == Qt::BlockingQueuedConnection) { } else if (c->connectionType == Qt::BlockingQueuedConnection) {
locker.unlock();
if (receiverInSameThread) { if (receiverInSameThread) {
qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: " qWarning("Qt: Dead lock detected while activating a BlockingQueuedConnection: "
"Sender is %s(%p), receiver is %s(%p)", "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->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); new QMetaCallEvent(c->method_offset, c->method_relative, c->callFunction, sender, signal_index, 0, 0, argv ? argv : empty_argv, &semaphore);
QCoreApplication::postEvent(receiver, ev); QCoreApplication::postEvent(receiver, ev);
locker.unlock();
semaphore.acquire(); semaphore.acquire();
locker.relock(); locker.relock();
continue; continue;
@ -4272,7 +4272,7 @@ QDebug operator<<(QDebug dbg, const QObject *o)
\relates QObject \relates QObject
\since 5.5 \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 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 that values of a given enum can be used as flags and combined using the
bitwise OR operator. bitwise OR operator.

View File

@ -180,6 +180,8 @@ inline void qYouForgotTheQ_OBJECT_Macro(T1, T2) {}
#if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306 #if defined(Q_CC_CLANG) && Q_CC_CLANG >= 306
# define Q_OBJECT_NO_OVERRIDE_WARNING QT_WARNING_DISABLE_CLANG("-Winconsistent-missing-override") # 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 #else
# define Q_OBJECT_NO_OVERRIDE_WARNING # define Q_OBJECT_NO_OVERRIDE_WARNING
#endif #endif

View File

@ -397,7 +397,11 @@ void QVector<T>::reserve(int asize)
{ {
if (asize > int(d->alloc)) if (asize > int(d->alloc))
reallocData(d->size, asize); reallocData(d->size, asize);
if (isDetached()) if (isDetached()
#if !defined(QT_NO_UNSHARABLE_CONTAINERS)
&& d != Data::unsharableEmpty()
#endif
)
d->capacityReserved = 1; d->capacityReserved = 1;
Q_ASSERT(capacity() >= asize); Q_ASSERT(capacity() >= asize);
} }

View File

@ -841,17 +841,6 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
d->cleanupFunction = cleanupFunction; d->cleanupFunction = cleanupFunction;
d->cleanupInfo = cleanupInfo; 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; return d;
} }
@ -2250,21 +2239,30 @@ QRgb QImage::pixel(int x, int y) const
} }
const uchar *s = d->data + y * d->bytes_per_line; const uchar *s = d->data + y * d->bytes_per_line;
switch(d->format) {
int index = -1;
switch (d->format) {
case Format_Mono: case Format_Mono:
return d->colortable.at((*(s + (x >> 3)) >> (~x & 7)) & 1); index = (*(s + (x >> 3)) >> (~x & 7)) & 1;
break;
case Format_MonoLSB: case Format_MonoLSB:
return d->colortable.at((*(s + (x >> 3)) >> (x & 7)) & 1); index = (*(s + (x >> 3)) >> (x & 7)) & 1;
break;
case Format_Indexed8: case Format_Indexed8:
{ index = s[x];
int index = (int)s[x]; break;
if (index < d->colortable.size()) { default:
return d->colortable.at(index); break;
} else { }
qWarning("QImage::pixel: color table index %d out of range.", index); if (index >= 0) { // Indexed format
return 0; 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: case Format_RGB32:
return 0xff000000 | reinterpret_cast<const QRgb *>(s)[x]; return 0xff000000 | reinterpret_cast<const QRgb *>(s)[x];
case Format_ARGB32: // Keep old behaviour. case Format_ARGB32: // Keep old behaviour.

View File

@ -1418,10 +1418,8 @@ QPixmap QPixmap::transformed(const QMatrix &matrix, Qt::TransformationMode mode)
QPixmap using the fromImage(). If this is too expensive an QPixmap using the fromImage(). If this is too expensive an
operation, you can use QBitmap::fromImage() instead. operation, you can use QBitmap::fromImage() instead.
The QPixmap class also supports conversion to and from HICON: To convert a QPixmap to and from HICON you can use the QtWinExtras
the toWinHICON() function creates a HICON equivalent to the functions QtWin::toHICON() and QtWin::fromHICON() respectively.
QPixmap, and returns the HICON handle. The fromWinHICON()
function returns a QPixmap that is equivalent to the given icon.
\section1 Pixmap Transformations \section1 Pixmap Transformations

View File

@ -42,6 +42,7 @@
#include <QtCore/qvarlengtharray.h> #include <QtCore/qvarlengtharray.h>
#include <QtGui/qopengl.h> #include <QtGui/qopengl.h>
#include <QtGui/qopenglfunctions.h> #include <QtGui/qopenglfunctions.h>
#include <QtGui/qoffscreensurface.h>
#include "qopengldebug.h" #include "qopengldebug.h"
@ -1287,8 +1288,41 @@ void QOpenGLDebugLoggerPrivate::controlDebugMessages(QOpenGLDebugMessage::Source
*/ */
void QOpenGLDebugLoggerPrivate::_q_contextAboutToBeDestroyed() 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_Q(QOpenGLDebugLogger);
q->stopLogging(); 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; initialized = false;
} }
@ -1494,6 +1528,12 @@ void QOpenGLDebugLogger::stopLogging()
if (!d->isLogging) if (!d->isLogging)
return; 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->isLogging = false;
d->glDebugMessageCallback(d->oldDebugCallbackFunction, d->oldDebugCallbackParameter); d->glDebugMessageCallback(d->oldDebugCallbackFunction, d->oldDebugCallbackParameter);

View File

@ -236,11 +236,16 @@ QSize QBackingStore::size() const
*/ */
bool QBackingStore::scroll(const QRegion &area, int dx, int dy) bool QBackingStore::scroll(const QRegion &area, int dx, int dy)
{ {
Q_UNUSED(area); // Disable scrolling for non-integer scroll deltas. For this case
Q_UNUSED(dx); // the the existing rendered pixels can't be re-used, and we return
Q_UNUSED(dy); // 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), QHighDpi::toNativePixels(dx, d_ptr->window), QHighDpi::toNativePixels(dy, d_ptr->window)); return d_ptr->platformBackingStore->scroll(QHighDpi::toNativeLocalRegion(area, d_ptr->window),
nativeDx, nativeDy);
} }
/*! /*!

View File

@ -1849,7 +1849,10 @@ static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEng
Q_UNREACHABLE(); 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, QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition,

View File

@ -116,14 +116,16 @@ QFbVtHandler::QFbVtHandler(QObject *parent)
m_signalNotifier = new QSocketNotifier(m_sigFd[1], QSocketNotifier::Read, this); m_signalNotifier = new QSocketNotifier(m_sigFd[1], QSocketNotifier::Read, this);
connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal); connect(m_signalNotifier, &QSocketNotifier::activated, this, &QFbVtHandler::handleSignal);
struct sigaction sa; if (!qEnvironmentVariableIntValue("QT_QPA_NO_SIGNAL_HANDLER")) {
sa.sa_flags = 0; struct sigaction sa;
sa.sa_handler = signalHandler; sa.sa_flags = 0;
sigemptyset(&sa.sa_mask); sa.sa_handler = signalHandler;
sigaction(SIGINT, &sa, 0); // Ctrl+C sigemptyset(&sa.sa_mask);
sigaction(SIGTSTP, &sa, 0); // Ctrl+Z sigaction(SIGINT, &sa, 0); // Ctrl+C
sigaction(SIGCONT, &sa, 0); sigaction(SIGTSTP, &sa, 0); // Ctrl+Z
sigaction(SIGTERM, &sa, 0); // default signal used by kill sigaction(SIGCONT, &sa, 0);
sigaction(SIGTERM, &sa, 0); // default signal used by kill
}
#endif #endif
} }

View File

@ -1599,7 +1599,7 @@ void QWindowsWindow::handleGeometryChange()
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
} }
if (testFlag(SynchronousGeometryChangeEvent)) if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents(); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry; qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
} }
@ -1689,7 +1689,7 @@ bool QWindowsWindow::handleWmPaint(HWND hwnd, UINT message,
// Our tests depend on it. // Our tests depend on it.
fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true); fireExpose(QRegion(qrectFromRECT(ps.rcPaint)), true);
if (!QWindowsContext::instance()->asyncExpose()) if (!QWindowsContext::instance()->asyncExpose())
QWindowSystemInterface::flushWindowSystemEvents(); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
EndPaint(hwnd, &ps); EndPaint(hwnd, &ps);
return true; return true;
@ -1749,7 +1749,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
switch (state) { switch (state) {
case Qt::WindowMinimized: case Qt::WindowMinimized:
handleHidden(); handleHidden();
QWindowSystemInterface::flushWindowSystemEvents(); // Tell QQuickWindow to stop rendering now. QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents); // Tell QQuickWindow to stop rendering now.
break; break;
case Qt::WindowMaximized: case Qt::WindowMaximized:
case Qt::WindowFullScreen: case Qt::WindowFullScreen:
@ -1772,7 +1772,7 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state)
} }
} }
if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose()) if (exposeEventsSent && !QWindowsContext::instance()->asyncExpose())
QWindowSystemInterface::flushWindowSystemEvents(); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
} }
break; break;
default: default:
@ -1878,7 +1878,7 @@ void QWindowsWindow::setWindowState_sys(Qt::WindowState newState)
if (!wasSync) if (!wasSync)
clearFlag(SynchronousGeometryChangeEvent); clearFlag(SynchronousGeometryChangeEvent);
QWindowSystemInterface::handleGeometryChange(window(), r); QWindowSystemInterface::handleGeometryChange(window(), r);
QWindowSystemInterface::flushWindowSystemEvents(); QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
} else if (newState != Qt::WindowMinimized) { } else if (newState != Qt::WindowMinimized) {
// Restore saved state. // Restore saved state.
unsigned newStyle = m_savedStyle ? m_savedStyle : style(); unsigned newStyle = m_savedStyle ? m_savedStyle : style();

View File

@ -2195,8 +2195,11 @@ void QXcbWindow::handleButtonPressEvent(int event_x, int event_y, int root_x, in
const bool isWheel = detail >= 4 && detail <= 7; const bool isWheel = detail >= 4 && detail <= 7;
if (!isWheel && window() != QGuiApplication::focusWindow()) { if (!isWheel && window() != QGuiApplication::focusWindow()) {
QWindow *w = static_cast<QWindowPrivate *>(QObjectPrivate::get(window()))->eventReceiver(); 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(); w->requestActivate();
}
} }
updateNetWmUserTime(timestamp); updateNetWmUserTime(timestamp);

View File

@ -874,8 +874,10 @@ void QDialog::adjustPosition(QWidget* w)
// QTBUG-52735: Manually set the correct target screen since scaling in a // QTBUG-52735: Manually set the correct target screen since scaling in a
// subsequent call to QWindow::resize() may otherwise use the wrong factor // subsequent call to QWindow::resize() may otherwise use the wrong factor
// if the screen changed notification is still in an event queue. // if the screen changed notification is still in an event queue.
if (QWindow *window = windowHandle()) if (scrn >= 0) {
window->setScreen(QGuiApplication::screens().at(scrn)); if (QWindow *window = windowHandle())
window->setScreen(QGuiApplication::screens().at(scrn));
}
move(p); move(p);
} }

View File

@ -376,6 +376,7 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
const QStyleOptionViewItem &option, const QStyleOptionViewItem &option,
const QModelIndex &index) const QModelIndex &index)
{ {
Q_D(QAbstractItemDelegate);
Q_UNUSED(option); Q_UNUSED(option);
if (!event || !view) if (!event || !view)
@ -384,9 +385,10 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
#ifndef QT_NO_TOOLTIP #ifndef QT_NO_TOOLTIP
case QEvent::ToolTip: { case QEvent::ToolTip: {
QHelpEvent *he = static_cast<QHelpEvent*>(event); QHelpEvent *he = static_cast<QHelpEvent*>(event);
QVariant tooltip = index.data(Qt::ToolTipRole); const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp
if (tooltip.canConvert<QString>()) { const QString tooltip = d->textForRole(Qt::ToolTipRole, index.data(Qt::ToolTipRole), option.locale, precision);
QToolTip::showText(he->globalPos(), tooltip.toString(), view); if (!tooltip.isEmpty()) {
QToolTip::showText(he->globalPos(), tooltip, view);
return true; return true;
} }
break;} break;}
@ -398,9 +400,10 @@ bool QAbstractItemDelegate::helpEvent(QHelpEvent *event,
break; } break; }
case QEvent::WhatsThis: { case QEvent::WhatsThis: {
QHelpEvent *he = static_cast<QHelpEvent*>(event); QHelpEvent *he = static_cast<QHelpEvent*>(event);
QVariant whatsthis = index.data(Qt::WhatsThisRole); const int precision = inherits("QItemDelegate") ? 10 : 6; // keep in sync with DBL_DIG in qitemdelegate.cpp
if (whatsthis.canConvert<QString>()) { const QString whatsthis = d->textForRole(Qt::WhatsThisRole, index.data(Qt::WhatsThisRole), option.locale, precision);
QWhatsThis::showText(he->globalPos(), whatsthis.toString(), view); if (!whatsthis.isEmpty()) {
QWhatsThis::showText(he->globalPos(), whatsthis, view);
return true; return true;
} }
break ; } break ; }
@ -543,6 +546,46 @@ bool QAbstractItemDelegatePrivate::tryFixup(QWidget *editor)
return true; 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) void QAbstractItemDelegatePrivate::_q_commitDataAndCloseEditor(QWidget *editor)
{ {
Q_Q(QAbstractItemDelegate); Q_Q(QAbstractItemDelegate);

View File

@ -58,7 +58,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAbstractItemDelegatePrivate : public QObjectPrivate class Q_AUTOTEST_EXPORT QAbstractItemDelegatePrivate : public QObjectPrivate
{ {
Q_DECLARE_PUBLIC(QAbstractItemDelegate) Q_DECLARE_PUBLIC(QAbstractItemDelegate)
public: public:
@ -66,6 +66,7 @@ public:
bool editorEventFilter(QObject *object, QEvent *event); bool editorEventFilter(QObject *object, QEvent *event);
bool tryFixup(QWidget *editor); bool tryFixup(QWidget *editor);
QString textForRole(Qt::ItemDataRole role, const QVariant &value, const QLocale &locale, int precision = 6) const;
void _q_commitDataAndCloseEditor(QWidget *editor); void _q_commitDataAndCloseEditor(QWidget *editor);
}; };

View File

@ -4325,6 +4325,12 @@ const QEditorInfo & QAbstractItemViewPrivate::editorForIndex(const QModelIndex &
return it.value(); 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 QModelIndex QAbstractItemViewPrivate::indexForEditor(QWidget *editor) const
{ {
// do not try to search to avoid slow implicit cast from QModelIndex to QPersistentModelIndex // do not try to search to avoid slow implicit cast from QModelIndex to QPersistentModelIndex

View File

@ -276,10 +276,7 @@ public:
} }
const QEditorInfo &editorForIndex(const QModelIndex &index) const; const QEditorInfo &editorForIndex(const QModelIndex &index) const;
inline bool hasEditor(const QModelIndex &index) const { 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);
}
QModelIndex indexForEditor(QWidget *editor) const; QModelIndex indexForEditor(QWidget *editor) const;
void addEditor(const QModelIndex &index, QWidget *editor, bool isStatic); void addEditor(const QModelIndex &index, QWidget *editor, bool isStatic);

View File

@ -67,6 +67,7 @@
#include <limits.h> #include <limits.h>
// keep in sync with QAbstractItemDelegate::helpEvent()
#ifndef DBL_DIG #ifndef DBL_DIG
# define DBL_DIG 10 # define DBL_DIG 10
#endif #endif
@ -102,7 +103,7 @@ public:
return text; return text;
} }
static QString valueToText(const QVariant &value, const QStyleOptionViewItem &option); QString valueToText(const QVariant &value, const QStyleOptionViewItem &option) const;
QItemEditorFactory *f; QItemEditorFactory *f;
bool clipPainting; bool clipPainting;
@ -332,40 +333,9 @@ void QItemDelegate::setClipping(bool clip)
d->clipPainting = 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; return textForRole(Qt::DisplayRole, value, option.locale, DBL_DIG);
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;
} }
/*! /*!
@ -434,7 +404,7 @@ void QItemDelegate::paint(QPainter *painter,
QRect displayRect; QRect displayRect;
value = index.data(Qt::DisplayRole); value = index.data(Qt::DisplayRole);
if (value.isValid() && !value.isNull()) { if (value.isValid() && !value.isNull()) {
text = QItemDelegatePrivate::valueToText(value, opt); text = d->valueToText(value, opt);
displayRect = textRectangle(painter, d->textLayoutBounds(opt), opt.font, text); 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); return QRect(QPoint(0, 0), option.decorationSize);
case QVariant::String: case QVariant::String:
default: { default: {
QString text = QItemDelegatePrivate::valueToText(value, option); const QString text = d->valueToText(value, option);
value = index.data(Qt::FontRole); value = index.data(Qt::FontRole);
QFont fnt = qvariant_cast<QFont>(value).resolve(option.font); QFont fnt = qvariant_cast<QFont>(value).resolve(option.font);
return textRectangle(0, d->textLayoutBounds(option), fnt, text); } return textRectangle(0, d->textLayoutBounds(option), fnt, text); }

View File

@ -261,41 +261,7 @@ QStyledItemDelegate::~QStyledItemDelegate()
*/ */
QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const QString QStyledItemDelegate::displayText(const QVariant &value, const QLocale& locale) const
{ {
QString text; return d_func()->textForRole(Qt::DisplayRole, value, locale);
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;
} }
/*! /*!

View File

@ -65,8 +65,12 @@
#include "qlistview.h" #include "qlistview.h"
#include <private/qmath_p.h> #include <private/qmath_p.h>
#include <qmath.h> #include <qmath.h>
#include <QtGui/qscreen.h>
#include <QtGui/qwindow.h>
#include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme.h>
#include <qpa/qplatformscreen.h>
#include <private/qguiapplication_p.h> #include <private/qguiapplication_p.h>
#include <private/qhighdpiscaling_p.h>
#include <private/qstylehelper_p.h> #include <private/qstylehelper_p.h>
#include <private/qstyleanimation_p.h> #include <private/qstyleanimation_p.h>
@ -402,6 +406,47 @@ int QWindowsStylePrivate::fixedPixelMetric(QStyle::PixelMetric pm)
return QWindowsStylePrivate::InvalidMetric; 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 \reimp
*/ */
@ -409,7 +454,7 @@ int QWindowsStyle::pixelMetric(PixelMetric pm, const QStyleOption *opt, const QW
{ {
int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget); int ret = QWindowsStylePrivate::pixelMetricFromSystemDp(pm, opt, widget);
if (ret != QWindowsStylePrivate::InvalidMetric) if (ret != QWindowsStylePrivate::InvalidMetric)
return qRound(qreal(ret) / QWindowsStylePrivate::devicePixelRatio(widget)); return qRound(qreal(ret) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
ret = QWindowsStylePrivate::fixedPixelMetric(pm); ret = QWindowsStylePrivate::fixedPixelMetric(pm);
if (ret != QWindowsStylePrivate::InvalidMetric) if (ret != QWindowsStylePrivate::InvalidMetric)

View File

@ -72,6 +72,7 @@ public:
static int fixedPixelMetric(QStyle::PixelMetric pm); static int fixedPixelMetric(QStyle::PixelMetric pm);
static qreal devicePixelRatio(const QWidget *widget = 0) static qreal devicePixelRatio(const QWidget *widget = 0)
{ return widget ? widget->devicePixelRatioF() : QWindowsStylePrivate::appDevicePixelRatio(); } { return widget ? widget->devicePixelRatioF() : QWindowsStylePrivate::appDevicePixelRatio(); }
static qreal nativeMetricScaleFactor(const QWidget *widget = Q_NULLPTR);
bool hasSeenAlt(const QWidget *widget) const; bool hasSeenAlt(const QWidget *widget) const;
bool altDown() const { return alt_down; } bool altDown() const { return alt_down; }
@ -104,3 +105,4 @@ QT_END_NAMESPACE
#endif // QT_NO_STYLE_WINDOWS #endif // QT_NO_STYLE_WINDOWS
#endif //QWINDOWSSTYLE_P_P_H #endif //QWINDOWSSTYLE_P_P_H
;

View File

@ -432,7 +432,7 @@ void QWindowsVistaStyle::drawPrimitive(PrimitiveElement element, const QStyleOpt
XPThemeData themeSize = theme; XPThemeData themeSize = theme;
themeSize.partId = TVP_HOTGLYPH; themeSize.partId = TVP_HOTGLYPH;
themeSize.stateId = GLPS_OPENED; 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())); decoration_size = qRound(qMax(size.width(), size.height()));
} }
int mid_h = option->rect.x() + option->rect.width() / 2; 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, XPThemeData theme(widget, 0, QWindowsXPStylePrivate::ToolBarTheme,
TP_DROPDOWNBUTTON); TP_DROPDOWNBUTTON);
if (theme.isValid()) { if (theme.isValid()) {
const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
if (!size.isEmpty()) { if (!size.isEmpty()) {
mbiw = qRound(size.width()); mbiw = qRound(size.width());
mbih = qRound(size.height()); mbih = qRound(size.height());
@ -1190,8 +1190,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData themeSize = theme; XPThemeData themeSize = theme;
themeSize.partId = MENU_POPUPCHECK; themeSize.partId = MENU_POPUPCHECK;
themeSize.stateId = 0; themeSize.stateId = 0;
const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right())); checkcol = qMax(menuitem->maxIconWidth, qRound(gutterWidth + size.width() + margins.left() + margins.right()));
} }
QRect rect = option->rect; QRect rect = option->rect;
@ -1216,7 +1216,7 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) { if (menuitem->menuItemType == QStyleOptionMenuItem::Separator) {
int yoff = y-2 + h / 2; 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 p1 = QPoint(x + checkcol, yoff);
QPoint p2 = QPoint(x + w + separatorSize, yoff); QPoint p2 = QPoint(x + w + separatorSize, yoff);
stateId = MBI_HOT; stateId = MBI_HOT;
@ -1249,8 +1249,8 @@ void QWindowsVistaStyle::drawControl(ControlElement element, const QStyleOption
XPThemeData themeSize = theme; XPThemeData themeSize = theme;
themeSize.partId = MENU_POPUPCHECK; themeSize.partId = MENU_POPUPCHECK;
themeSize.stateId = 0; themeSize.stateId = 0;
const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()), QRect checkRect(0, 0, qRound(size.width() + margins.left() + margins.right()),
qRound(size.height() + margins.bottom() + margins.top())); qRound(size.height() + margins.bottom() + margins.top()));
checkRect.moveCenter(vCheckRect.center()); checkRect.moveCenter(vCheckRect.center());
@ -1862,8 +1862,8 @@ QSize QWindowsVistaStyle::sizeFromContents(ContentsType type, const QStyleOption
XPThemeData themeSize = theme; XPThemeData themeSize = theme;
themeSize.partId = MENU_POPUPCHECK; themeSize.partId = MENU_POPUPCHECK;
themeSize.stateId = 0; themeSize.stateId = 0;
const QSizeF size = themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QSizeF size = themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
const QMarginsF margins = themeSize.margins() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QMarginsF margins = themeSize.margins() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), sz.height()); minimumHeight = qMax(qRound(size.height() + margins.bottom() + margins.top()), sz.height());
sz.rwidth() += qRound(size.width() + margins.left() + margins.right()); sz.rwidth() += qRound(size.width() + margins.left() + margins.right());
} }
@ -1973,7 +1973,7 @@ QRect QWindowsVistaStyle::subElementRect(SubElement element, const QStyleOption
int arrowWidth = 13; int arrowWidth = 13;
int arrowHeight = 5; int arrowHeight = 5;
if (theme.isValid()) { if (theme.isValid()) {
const QSizeF size = theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget); const QSizeF size = theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget);
if (!size.isEmpty()) { if (!size.isEmpty()) {
arrowWidth = qRound(size.width()); arrowWidth = qRound(size.width());
arrowHeight = qRound(size.height()); arrowHeight = qRound(size.height());
@ -2456,7 +2456,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
QWindowsXPStylePrivate::ButtonTheme, QWindowsXPStylePrivate::ButtonTheme,
BP_COMMANDLINKGLYPH, CMDLGS_NORMAL); BP_COMMANDLINKGLYPH, CMDLGS_NORMAL);
if (theme.isValid()) { if (theme.isValid()) {
const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QIcon linkGlyph; QIcon linkGlyph;
QPixmap pm(size); QPixmap pm(size);
pm.fill(Qt::transparent); pm.fill(Qt::transparent);

View File

@ -489,7 +489,7 @@ const QPixmap *QWindowsXPStylePrivate::tabBody(QWidget *widget)
{ {
if (!tabbody) { if (!tabbody) {
XPThemeData theme(0, 0, QWindowsXPStylePrivate::TabTheme, TABP_BODY); 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()); tabbody = new QPixmap(size.width(), QApplication::desktop()->screenGeometry().height());
QPainter painter(tabbody); QPainter painter(tabbody);
@ -3457,7 +3457,7 @@ int QWindowsXPStyle::pixelMetric(PixelMetric pm, const QStyleOption *option, con
int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget); int res = QWindowsXPStylePrivate::pixelMetricFromSystemDp(pm, option, widget);
if (res != QWindowsStylePrivate::InvalidMetric) if (res != QWindowsStylePrivate::InvalidMetric)
return qRound(qreal(res) / QWindowsStylePrivate::devicePixelRatio(widget)); return qRound(qreal(res) * QWindowsStylePrivate::nativeMetricScaleFactor(widget));
res = 0; res = 0;
switch (pm) { switch (pm) {
@ -3603,9 +3603,10 @@ QRect QWindowsXPStyle::subControlRect(ComplexControl cc, const QStyleOptionCompl
const int height = tb->rect.height(); const int height = tb->rect.height();
const int width = tb->rect.width(); const int width = tb->rect.width();
const int buttonMargin = int(QStyleHelper::dpiScaled(4)); 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; - buttonMargin;
int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) / QWindowsStylePrivate::devicePixelRatio(widget)) int buttonWidth = qRound(qreal(GetSystemMetrics(SM_CXSIZE)) * factor)
- buttonMargin; - buttonMargin;
const int delta = buttonWidth + 2; const int delta = buttonWidth + 2;
int controlTop = option->rect.bottom() - buttonHeight - 2; int controlTop = option->rect.bottom() - buttonHeight - 2;
@ -3975,7 +3976,7 @@ QPixmap QWindowsXPStyle::standardPixmap(StandardPixmap standardPixmap, const QSt
if (widget && widget->isWindow()) { if (widget && widget->isWindow()) {
XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL); XPThemeData theme(widget, 0, QWindowsXPStylePrivate::WindowTheme, WP_SMALLCLOSEBUTTON, CBS_NORMAL);
if (theme.isValid()) { 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); return QIcon(QWindowsStyle::standardPixmap(standardPixmap, option, widget)).pixmap(size);
} }
} }
@ -4009,7 +4010,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_MAXBUTTON, MAXBS_NORMAL); WP_MAXBUTTON, MAXBS_NORMAL);
if (theme.isValid()) { if (theme.isValid()) {
const QSize size = (themeSize.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); const QSize size = (themeSize.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QPixmap pm(size); QPixmap pm(size);
pm.fill(Qt::transparent); pm.fill(Qt::transparent);
QPainter p(&pm); QPainter p(&pm);
@ -4043,7 +4044,7 @@ QIcon QWindowsXPStyle::standardIcon(StandardPixmap standardIcon,
XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme, XPThemeData theme(0, 0, QWindowsXPStylePrivate::WindowTheme,
WP_SMALLCLOSEBUTTON, CBS_NORMAL); WP_SMALLCLOSEBUTTON, CBS_NORMAL);
if (theme.isValid()) { if (theme.isValid()) {
const QSize size = (theme.size() / QWindowsXPStylePrivate::devicePixelRatio(widget)).toSize(); const QSize size = (theme.size() * QWindowsStylePrivate::nativeMetricScaleFactor(widget)).toSize();
QPixmap pm(size); QPixmap pm(size);
pm.fill(Qt::transparent); pm.fill(Qt::transparent);
QPainter p(&pm); QPainter p(&pm);

View File

@ -271,6 +271,7 @@ private slots:
void testOperators() const; void testOperators() const;
void reserve(); void reserve();
void reserveZero();
void reallocAfterCopy_data(); void reallocAfterCopy_data();
void reallocAfterCopy(); void reallocAfterCopy();
void initializeListInt(); void initializeListInt();
@ -2365,13 +2366,34 @@ void tst_QVector::reserve()
{ {
QVector<Foo> a; QVector<Foo> a;
a.resize(2); a.resize(2);
QCOMPARE(fooCtor, 2);
QVector<Foo> b(a); QVector<Foo> b(a);
b.reserve(1); b.reserve(1);
QCOMPARE(b.size(), a.size()); QCOMPARE(b.size(), a.size());
QCOMPARE(fooDtor, 0);
} }
QCOMPARE(fooCtor, fooDtor); 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 // This is a regression test for QTBUG-11763, where memory would be reallocated
// soon after copying a QVector. // soon after copying a QVector.
void tst_QVector::reallocAfterCopy_data() void tst_QVector::reallocAfterCopy_data()

View File

@ -94,6 +94,8 @@ private slots:
void setPixel_data(); void setPixel_data();
void setPixel(); void setPixel();
void defaultColorTable_data();
void defaultColorTable();
void setColorCount(); void setColorCount();
void setColor(); void setColor();
@ -1450,6 +1452,38 @@ void tst_QImage::convertToFormatPreserveText()
QCOMPARE(imgResult2.textKeys(), listResult); 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() void tst_QImage::setColorCount()
{ {
QImage img(0, 0, QImage::Format_Indexed8); QImage img(0, 0, QImage::Format_Indexed8);
@ -3182,8 +3216,8 @@ void tst_QImage::pixel()
QImage monolsb(&a, 1, 1, QImage::Format_MonoLSB); QImage monolsb(&a, 1, 1, QImage::Format_MonoLSB);
QImage indexed(&a, 1, 1, QImage::Format_Indexed8); QImage indexed(&a, 1, 1, QImage::Format_Indexed8);
QCOMPARE(QColor(mono.pixel(0, 0)), QColor(Qt::black)); mono.pixel(0, 0); // Don't crash
QCOMPARE(QColor(monolsb.pixel(0, 0)), QColor(Qt::black)); monolsb.pixel(0, 0); // Don't crash
indexed.pixel(0, 0); // Don't crash indexed.pixel(0, 0); // Don't crash
} }
} }

View File

@ -46,6 +46,7 @@ class tst_QObjectRace: public QObject
private slots: private slots:
void moveToThreadRace(); void moveToThreadRace();
void destroyRace(); void destroyRace();
void disconnectRace();
}; };
class RaceObject : public QObject class RaceObject : public QObject
@ -293,6 +294,180 @@ void tst_QObjectRace::destroyRace()
delete threads[i]; 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) QTEST_MAIN(tst_QObjectRace)
#include "tst_qobjectrace.moc" #include "tst_qobjectrace.moc"

View File

@ -1,6 +1,6 @@
CONFIG += testcase CONFIG += testcase
TARGET = tst_qitemdelegate TARGET = tst_qitemdelegate
QT += widgets testlib QT += widgets widgets-private testlib
SOURCES += tst_qitemdelegate.cpp SOURCES += tst_qitemdelegate.cpp
win32:!wince:!winrt: LIBS += -luser32 win32:!wince:!winrt: LIBS += -luser32

View File

@ -51,6 +51,8 @@
#include <QPlainTextEdit> #include <QPlainTextEdit>
#include <QDialog> #include <QDialog>
#include <QtWidgets/private/qabstractitemdelegate_p.h>
Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint) Q_DECLARE_METATYPE(QAbstractItemDelegate::EndEditHint)
#if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT) #if defined (Q_OS_WIN) && !defined(Q_OS_WINCE) && !defined(Q_OS_WINRT)
@ -216,6 +218,8 @@ private slots:
void task257859_finalizeEdit(); void task257859_finalizeEdit();
void QTBUG4435_keepSelectionOnCheck(); void QTBUG4435_keepSelectionOnCheck();
void QTBUG16469_textForRole();
}; };
@ -1521,6 +1525,64 @@ void tst_QItemDelegate::testLineEditValidation()
QCOMPARE(item->data(Qt::DisplayRole).toString(), QStringLiteral("abc,def")); 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: // ### _not_ covered: