Merge 5.14 into 5.14.2

Change-Id: Ib4b26bad47a850cde6253fb3422aae34b2cf622b
This commit is contained in:
Kari Oikarinen 2020-03-10 09:43:16 +02:00
commit d6d902a990
36 changed files with 300 additions and 158 deletions

View File

@ -50,9 +50,13 @@
#include "printview.h" #include "printview.h"
#ifndef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB)
# include <QtPrintSupport/qtprintsupportglobal.h>
# if QT_CONFIG(printer)
# include <QPrinter> # include <QPrinter>
# endif # endif
#endif
PrintView::PrintView() PrintView::PrintView()
{ {
@ -62,9 +66,11 @@ PrintView::PrintView()
void PrintView::print(QPrinter *printer) void PrintView::print(QPrinter *printer)
{ {
#ifndef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
resize(printer->width(), printer->height()); resize(printer->width(), printer->height());
render(printer); render(printer);
#else
Q_UNUSED(printer)
#endif #endif
} }

View File

@ -638,7 +638,7 @@ QString encode_pos(int row, int col)
void SpreadSheet::print() void SpreadSheet::print()
{ {
#if QT_CONFIG(printpreviewdialog) #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
QPrinter printer(QPrinter::ScreenResolution); QPrinter printer(QPrinter::ScreenResolution);
QPrintPreviewDialog dlg(&printer); QPrintPreviewDialog dlg(&printer);
PrintView view; PrintView view;

View File

@ -197,7 +197,7 @@ void TextEdit::setupFileActions()
a->setPriority(QAction::LowPriority); a->setPriority(QAction::LowPriority);
menu->addSeparator(); menu->addSeparator();
#ifndef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png")); const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png"));
a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint); a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint);
a->setPriority(QAction::LowPriority); a->setPriority(QAction::LowPriority);
@ -559,7 +559,7 @@ void TextEdit::filePrint()
void TextEdit::filePrintPreview() void TextEdit::filePrintPreview()
{ {
#if QT_CONFIG(printpreviewdialog) #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
QPrinter printer(QPrinter::HighResolution); QPrinter printer(QPrinter::HighResolution);
QPrintPreviewDialog preview(&printer, this); QPrintPreviewDialog preview(&printer, this);
connect(&preview, &QPrintPreviewDialog::paintRequested, this, &TextEdit::printPreview); connect(&preview, &QPrintPreviewDialog::paintRequested, this, &TextEdit::printPreview);
@ -569,17 +569,17 @@ void TextEdit::filePrintPreview()
void TextEdit::printPreview(QPrinter *printer) void TextEdit::printPreview(QPrinter *printer)
{ {
#ifdef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
Q_UNUSED(printer);
#else
textEdit->print(printer); textEdit->print(printer);
#else
Q_UNUSED(printer)
#endif #endif
} }
void TextEdit::filePrintPdf() void TextEdit::filePrintPdf()
{ {
#ifndef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
//! [0] //! [0]
QFileDialog fileDialog(this, tr("Export PDF")); QFileDialog fileDialog(this, tr("Export PDF"));
fileDialog.setAcceptMode(QFileDialog::AcceptSave); fileDialog.setAcceptMode(QFileDialog::AcceptSave);

View File

@ -1,6 +1,8 @@
TEMPLATE = app TEMPLATE = app
TARGET = notepad TARGET = notepad
QT += widgets
qtHaveModule(printsupport): QT += printsupport qtHaveModule(printsupport): QT += printsupport
requires(qtConfig(fontdialog)) requires(qtConfig(fontdialog))

View File

@ -70,6 +70,7 @@
#if defined(QT_PRINTSUPPORT_LIB) #if defined(QT_PRINTSUPPORT_LIB)
# include <QtPrintSupport/qtprintsupportglobal.h> # include <QtPrintSupport/qtprintsupportglobal.h>
# if QT_CONFIG(printdialog) # if QT_CONFIG(printdialog)
# include <QPrintDialog> # include <QPrintDialog>
# endif # endif

View File

@ -53,9 +53,13 @@
#include <QMainWindow> #include <QMainWindow>
#include <QImage> #include <QImage>
#ifndef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB)
# include <QtPrintSupport/qtprintsupportglobal.h>
# if QT_CONFIG(printer)
# include <QPrinter> # include <QPrinter>
# endif # endif
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QAction; class QAction;
@ -100,7 +104,7 @@ private:
QScrollArea *scrollArea; QScrollArea *scrollArea;
double scaleFactor = 1; double scaleFactor = 1;
#ifndef QT_NO_PRINTER #if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
QPrinter printer; QPrinter printer;
#endif #endif

View File

@ -1949,8 +1949,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
example.) example.)
If you are working with large amounts of filtering and have to invoke If you are working with large amounts of filtering and have to invoke
invalidateFilter() repeatedly, using reset() may be more efficient, invalidateFilter() repeatedly, using beginResetModel() / endResetModel() may
depending on the implementation of your model. However, reset() returns the be more efficient, depending on the implementation of your model. However,
beginResetModel() / endResetModel() returns the
proxy model to its original state, losing selection information, and will proxy model to its original state, losing selection information, and will
cause the proxy model to be repopulated. cause the proxy model to be repopulated.

View File

@ -589,7 +589,8 @@ QMetaTypeComparatorRegistry;
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int> typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
QMetaTypeDebugStreamRegistry; QMetaTypeDebugStreamRegistry;
Q_STATIC_ASSERT(std::is_pod<QMetaTypeInterface>::value); Q_STATIC_ASSERT(std::is_trivial<QMetaTypeInterface>::value);
Q_STATIC_ASSERT(std::is_standard_layout<QMetaTypeInterface>::value);
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes) Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)

View File

@ -389,17 +389,12 @@ QObject *QFactoryLoader::instance(int index) const
QMutexLocker lock(&d->mutex); QMutexLocker lock(&d->mutex);
if (index < d->libraryList.size()) { if (index < d->libraryList.size()) {
QLibraryPrivate *library = d->libraryList.at(index); QLibraryPrivate *library = d->libraryList.at(index);
if (library->instance || library->loadPlugin()) { if (QObject *obj = library->pluginInstance()) {
if (!library->inst)
library->inst = library->instance();
QObject *obj = library->inst.data();
if (obj) {
if (!obj->parent()) if (!obj->parent())
obj->moveToThread(QCoreApplicationPrivate::mainThread()); obj->moveToThread(QCoreApplicationPrivate::mainThread());
return obj; return obj;
} }
} return nullptr;
return 0;
} }
index -= d->libraryList.size(); index -= d->libraryList.size();
lock.unlock(); lock.unlock();

View File

@ -407,7 +407,7 @@ inline void QLibraryStore::cleanup()
QLibraryPrivate *lib = it.value(); QLibraryPrivate *lib = it.value();
if (lib->libraryRefCount.loadRelaxed() == 1) { if (lib->libraryRefCount.loadRelaxed() == 1) {
if (lib->libraryUnloadCount.loadRelaxed() > 0) { if (lib->libraryUnloadCount.loadRelaxed() > 0) {
Q_ASSERT(lib->pHnd); Q_ASSERT(lib->pHnd.loadRelaxed());
lib->libraryUnloadCount.storeRelaxed(1); lib->libraryUnloadCount.storeRelaxed(1);
#ifdef __GLIBC__ #ifdef __GLIBC__
// glibc has a bug in unloading from global destructors // glibc has a bug in unloading from global destructors
@ -498,8 +498,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
} }
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints) QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
: pHnd(0), fileName(canonicalFileName), fullVersion(version), instance(0), : fileName(canonicalFileName), fullVersion(version), pluginState(MightBeAPlugin)
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
{ {
loadHintsInt.storeRelaxed(loadHints); loadHintsInt.storeRelaxed(loadHints);
if (canonicalFileName.isEmpty()) if (canonicalFileName.isEmpty())
@ -519,7 +518,7 @@ QLibraryPrivate::~QLibraryPrivate()
void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh) void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
{ {
// if the library is already loaded, we can't change the load hints // if the library is already loaded, we can't change the load hints
if (pHnd) if (pHnd.loadRelaxed())
return; return;
loadHintsInt.storeRelaxed(lh); loadHintsInt.storeRelaxed(lh);
@ -527,7 +526,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
QFunctionPointer QLibraryPrivate::resolve(const char *symbol) QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
{ {
if (!pHnd) if (!pHnd.loadRelaxed())
return 0; return 0;
return resolve_sys(symbol); return resolve_sys(symbol);
} }
@ -539,9 +538,36 @@ void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
mergeLoadHints(lh); mergeLoadHints(lh);
} }
QObject *QLibraryPrivate::pluginInstance()
{
// first, check if the instance is cached and hasn't been deleted
QObject *obj = (QMutexLocker(&mutex), inst.data());
if (obj)
return obj;
// We need to call the plugin's factory function. Is that cached?
// skip increasing the reference count (why? -Thiago)
QtPluginInstanceFunction factory = instanceFactory.loadAcquire();
if (!factory)
factory = loadPlugin();
if (!factory)
return nullptr;
obj = factory();
// cache again
QMutexLocker locker(&mutex);
if (inst)
obj = inst;
else
inst = obj;
return obj;
}
bool QLibraryPrivate::load() bool QLibraryPrivate::load()
{ {
if (pHnd) { if (pHnd.loadRelaxed()) {
libraryUnloadCount.ref(); libraryUnloadCount.ref();
return true; return true;
} }
@ -550,7 +576,9 @@ bool QLibraryPrivate::load()
Q_TRACE(QLibraryPrivate_load_entry, fileName); Q_TRACE(QLibraryPrivate_load_entry, fileName);
mutex.lock();
bool ret = load_sys(); bool ret = load_sys();
mutex.unlock();
if (qt_debug_component()) { if (qt_debug_component()) {
if (ret) { if (ret) {
qDebug() << "loaded library" << fileName; qDebug() << "loaded library" << fileName;
@ -573,9 +601,10 @@ bool QLibraryPrivate::load()
bool QLibraryPrivate::unload(UnloadFlag flag) bool QLibraryPrivate::unload(UnloadFlag flag)
{ {
if (!pHnd) if (!pHnd.loadRelaxed())
return false; return false;
if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
QMutexLocker locker(&mutex);
delete inst.data(); delete inst.data();
if (flag == NoUnloadSys || unload_sys()) { if (flag == NoUnloadSys || unload_sys()) {
if (qt_debug_component()) if (qt_debug_component())
@ -584,12 +613,13 @@ bool QLibraryPrivate::unload(UnloadFlag flag)
//when the library is unloaded, we release the reference on it so that 'this' //when the library is unloaded, we release the reference on it so that 'this'
//can get deleted //can get deleted
libraryRefCount.deref(); libraryRefCount.deref();
pHnd = 0; pHnd.storeRelaxed(nullptr);
instance = 0; instanceFactory.storeRelaxed(nullptr);
return true;
} }
} }
return (pHnd == 0); return false;
} }
void QLibraryPrivate::release() void QLibraryPrivate::release()
@ -597,22 +627,23 @@ void QLibraryPrivate::release()
QLibraryStore::releaseLibrary(this); QLibraryStore::releaseLibrary(this);
} }
bool QLibraryPrivate::loadPlugin() QtPluginInstanceFunction QLibraryPrivate::loadPlugin()
{ {
if (instance) { if (auto ptr = instanceFactory.loadAcquire()) {
libraryUnloadCount.ref(); libraryUnloadCount.ref();
return true; return ptr;
} }
if (pluginState == IsNotAPlugin) if (pluginState == IsNotAPlugin)
return false; return nullptr;
if (load()) { if (load()) {
instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance"); auto ptr = reinterpret_cast<QtPluginInstanceFunction>(resolve("qt_plugin_instance"));
return instance; instanceFactory.storeRelease(ptr); // two threads may store the same value
return ptr;
} }
if (qt_debug_component()) if (qt_debug_component())
qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString; qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
pluginState = IsNotAPlugin; pluginState = IsNotAPlugin;
return false; return nullptr;
} }
/*! /*!
@ -719,6 +750,7 @@ bool QLibraryPrivate::isPlugin()
void QLibraryPrivate::updatePluginState() void QLibraryPrivate::updatePluginState()
{ {
QMutexLocker locker(&mutex);
errorString.clear(); errorString.clear();
if (pluginState != MightBeAPlugin) if (pluginState != MightBeAPlugin)
return; return;
@ -739,7 +771,7 @@ void QLibraryPrivate::updatePluginState()
} }
#endif #endif
if (!pHnd) { if (!pHnd.loadRelaxed()) {
// scan for the plugin metadata without loading // scan for the plugin metadata without loading
success = findPatternUnloaded(fileName, this); success = findPatternUnloaded(fileName, this);
} else { } else {
@ -803,7 +835,7 @@ bool QLibrary::load()
if (!d) if (!d)
return false; return false;
if (did_load) if (did_load)
return d->pHnd; return d->pHnd.loadRelaxed();
did_load = true; did_load = true;
return d->load(); return d->load();
} }
@ -839,7 +871,7 @@ bool QLibrary::unload()
*/ */
bool QLibrary::isLoaded() const bool QLibrary::isLoaded() const
{ {
return d && d->pHnd; return d && d->pHnd.loadRelaxed();
} }
@ -950,8 +982,10 @@ void QLibrary::setFileName(const QString &fileName)
QString QLibrary::fileName() const QString QLibrary::fileName() const
{ {
if (d) if (d) {
QMutexLocker locker(&d->mutex);
return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName; return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
}
return QString(); return QString();
} }
@ -1092,7 +1126,12 @@ QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &versi
*/ */
QString QLibrary::errorString() const QString QLibrary::errorString() const
{ {
return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString; QString str;
if (d) {
QMutexLocker locker(&d->mutex);
str = d->errorString;
}
return str.isEmpty() ? tr("Unknown error") : str;
} }
/*! /*!

View File

@ -54,10 +54,10 @@
#include <QtCore/private/qglobal_p.h> #include <QtCore/private/qglobal_p.h>
#include "QtCore/qlibrary.h" #include "QtCore/qlibrary.h"
#include "QtCore/qmutex.h"
#include "QtCore/qpointer.h" #include "QtCore/qpointer.h"
#include "QtCore/qstringlist.h" #include "QtCore/qstringlist.h"
#include "QtCore/qplugin.h" #include "QtCore/qplugin.h"
#include "QtCore/qsharedpointer.h"
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
# include "QtCore/qt_windows.h" # include "QtCore/qt_windows.h"
#endif #endif
@ -72,21 +72,18 @@ class QLibraryStore;
class QLibraryPrivate class QLibraryPrivate
{ {
public: public:
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
HINSTANCE using Handle = HINSTANCE;
#else #else
void * using Handle = void *;
#endif #endif
pHnd;
enum UnloadFlag { UnloadSys, NoUnloadSys }; enum UnloadFlag { UnloadSys, NoUnloadSys };
QString fileName, qualifiedFileName; const QString fileName;
QString fullVersion; const QString fullVersion;
bool load(); bool load();
bool loadPlugin(); // loads and resolves instance QtPluginInstanceFunction loadPlugin(); // loads and resolves instance
bool unload(UnloadFlag flag = UnloadSys); bool unload(UnloadFlag flag = UnloadSys);
void release(); void release();
QFunctionPointer resolve(const char *); QFunctionPointer resolve(const char *);
@ -94,17 +91,22 @@ public:
QLibrary::LoadHints loadHints() const QLibrary::LoadHints loadHints() const
{ return QLibrary::LoadHints(loadHintsInt.loadRelaxed()); } { return QLibrary::LoadHints(loadHintsInt.loadRelaxed()); }
void setLoadHints(QLibrary::LoadHints lh); void setLoadHints(QLibrary::LoadHints lh);
QObject *pluginInstance();
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(), static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
QLibrary::LoadHints loadHints = nullptr); QLibrary::LoadHints loadHints = nullptr);
static QStringList suffixes_sys(const QString &fullVersion); static QStringList suffixes_sys(const QString &fullVersion);
static QStringList prefixes_sys(); static QStringList prefixes_sys();
QPointer<QObject> inst; QAtomicPointer<std::remove_pointer<QtPluginInstanceFunction>::type> instanceFactory;
QtPluginInstanceFunction instance; QAtomicPointer<std::remove_pointer<Handle>::type> pHnd;
QJsonObject metaData;
// the mutex protects the fields below
QMutex mutex;
QPointer<QObject> inst; // used by QFactoryLoader
QJsonObject metaData;
QString errorString; QString errorString;
QString qualifiedFileName;
void updatePluginState(); void updatePluginState();
bool isPlugin(); bool isPlugin();

View File

@ -214,8 +214,9 @@ bool QLibraryPrivate::load_sys()
#endif #endif
bool retry = true; bool retry = true;
for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) { Handle hnd = nullptr;
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) { for (int prefix = 0; retry && !hnd && prefix < prefixes.size(); prefix++) {
for (int suffix = 0; retry && !hnd && suffix < suffixes.size(); suffix++) {
if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix))) if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
continue; continue;
if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/'))) if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/')))
@ -232,7 +233,7 @@ bool QLibraryPrivate::load_sys()
attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix); attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
} }
pHnd = dlopen(QFile::encodeName(attempt), dlFlags); hnd = dlopen(QFile::encodeName(attempt), dlFlags);
#ifdef Q_OS_ANDROID #ifdef Q_OS_ANDROID
if (!pHnd) { if (!pHnd) {
auto attemptFromBundle = attempt; auto attemptFromBundle = attempt;
@ -248,7 +249,7 @@ bool QLibraryPrivate::load_sys()
} }
#endif #endif
if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) { if (!hnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
// We only want to continue if dlopen failed due to that the shared library did not exist. // We only want to continue if dlopen failed due to that the shared library did not exist.
// However, we are only able to apply this check for absolute filenames (since they are // However, we are only able to apply this check for absolute filenames (since they are
// not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...) // not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...)
@ -259,7 +260,7 @@ bool QLibraryPrivate::load_sys()
} }
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
if (!pHnd) { if (!hnd) {
QByteArray utf8Bundle = fileName.toUtf8(); QByteArray utf8Bundle = fileName.toUtf8();
QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true); QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true);
QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl); QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl);
@ -268,23 +269,24 @@ bool QLibraryPrivate::load_sys()
char executableFile[FILENAME_MAX]; char executableFile[FILENAME_MAX];
CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX); CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX);
attempt = QString::fromUtf8(executableFile); attempt = QString::fromUtf8(executableFile);
pHnd = dlopen(QFile::encodeName(attempt), dlFlags); hnd = dlopen(QFile::encodeName(attempt), dlFlags);
} }
} }
#endif #endif
if (!pHnd) { if (!hnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror()); errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror());
} }
if (pHnd) { if (hnd) {
qualifiedFileName = attempt; qualifiedFileName = attempt;
errorString.clear(); errorString.clear();
} }
return (pHnd != 0); pHnd.storeRelaxed(hnd);
return (hnd != nullptr);
} }
bool QLibraryPrivate::unload_sys() bool QLibraryPrivate::unload_sys()
{ {
if (dlclose(pHnd)) { if (dlclose(pHnd.loadAcquire())) {
#if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in #if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in
char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance
if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative" if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative"
@ -316,13 +318,7 @@ Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symb
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol) QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
{ {
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol)); QFunctionPointer address = QFunctionPointer(dlsym(pHnd.loadAcquire(), symbol));
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
QString::fromLatin1(symbol), fileName, qdlerror());
} else {
errorString.clear();
}
return address; return address;
} }

View File

@ -95,26 +95,27 @@ bool QLibraryPrivate::load_sys()
attempts.prepend(QDir::rootPath() + fileName); attempts.prepend(QDir::rootPath() + fileName);
#endif #endif
Handle hnd = nullptr;
for (const QString &attempt : qAsConst(attempts)) { for (const QString &attempt : qAsConst(attempts)) {
#ifndef Q_OS_WINRT #ifndef Q_OS_WINRT
pHnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16())); hnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
#else // Q_OS_WINRT #else // Q_OS_WINRT
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt)); QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
pHnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0); hnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
if (pHnd) if (hnd)
qualifiedFileName = attempt; qualifiedFileName = attempt;
#endif // !Q_OS_WINRT #endif // !Q_OS_WINRT
// If we have a handle or the last error is something other than "unable // If we have a handle or the last error is something other than "unable
// to find the module", then bail out // to find the module", then bail out
if (pHnd || ::GetLastError() != ERROR_MOD_NOT_FOUND) if (hnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
break; break;
} }
#ifndef Q_OS_WINRT #ifndef Q_OS_WINRT
SetErrorMode(oldmode); SetErrorMode(oldmode);
#endif #endif
if (!pHnd) { if (!hnd) {
errorString = QLibrary::tr("Cannot load library %1: %2").arg( errorString = QLibrary::tr("Cannot load library %1: %2").arg(
QDir::toNativeSeparators(fileName), qt_error_string()); QDir::toNativeSeparators(fileName), qt_error_string());
} else { } else {
@ -123,7 +124,7 @@ bool QLibraryPrivate::load_sys()
#ifndef Q_OS_WINRT #ifndef Q_OS_WINRT
wchar_t buffer[MAX_PATH]; wchar_t buffer[MAX_PATH];
::GetModuleFileName(pHnd, buffer, MAX_PATH); ::GetModuleFileName(hnd, buffer, MAX_PATH);
QString moduleFileName = QString::fromWCharArray(buffer); QString moduleFileName = QString::fromWCharArray(buffer);
moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\'))); moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
@ -138,19 +139,20 @@ bool QLibraryPrivate::load_sys()
HMODULE hmod; HMODULE hmod;
bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN | bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN |
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
reinterpret_cast<const wchar_t *>(pHnd), reinterpret_cast<const wchar_t *>(hnd),
&hmod); &hmod);
Q_ASSERT(!ok || hmod == pHnd); Q_ASSERT(!ok || hmod == hnd);
Q_UNUSED(ok); Q_UNUSED(ok);
} }
#endif // !Q_OS_WINRT #endif // !Q_OS_WINRT
} }
return (pHnd != 0); pHnd.storeRelaxed(hnd);
return (pHnd != nullptr);
} }
bool QLibraryPrivate::unload_sys() bool QLibraryPrivate::unload_sys()
{ {
if (!FreeLibrary(pHnd)) { if (!FreeLibrary(pHnd.loadAcquire())) {
errorString = QLibrary::tr("Cannot unload library %1: %2").arg( errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
QDir::toNativeSeparators(fileName), qt_error_string()); QDir::toNativeSeparators(fileName), qt_error_string());
return false; return false;
@ -161,13 +163,7 @@ bool QLibraryPrivate::unload_sys()
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol) QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
{ {
FARPROC address = GetProcAddress(pHnd, symbol); FARPROC address = GetProcAddress(pHnd.loadAcquire(), symbol);
if (!address) {
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
QString::fromLatin1(symbol), QDir::toNativeSeparators(fileName), qt_error_string());
} else {
errorString.clear();
}
return QFunctionPointer(address); return QFunctionPointer(address);
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -196,9 +196,7 @@ QObject *QPluginLoader::instance()
{ {
if (!isLoaded() && !load()) if (!isLoaded() && !load())
return 0; return 0;
if (!d->inst && d->instance) return d->pluginInstance();
d->inst = d->instance();
return d->inst.data();
} }
/*! /*!
@ -233,7 +231,7 @@ bool QPluginLoader::load()
if (!d || d->fileName.isEmpty()) if (!d || d->fileName.isEmpty())
return false; return false;
if (did_load) if (did_load)
return d->pHnd && d->instance; return d->pHnd && d->instanceFactory.loadAcquire();
if (!d->isPlugin()) if (!d->isPlugin())
return false; return false;
did_load = true; did_load = true;
@ -275,7 +273,7 @@ bool QPluginLoader::unload()
*/ */
bool QPluginLoader::isLoaded() const bool QPluginLoader::isLoaded() const
{ {
return d && d->pHnd && d->instance; return d && d->pHnd && d->instanceFactory.loadRelaxed();
} }
#if defined(QT_SHARED) #if defined(QT_SHARED)

View File

@ -115,7 +115,8 @@ struct ByteData
QStringView asStringView() const{ return QStringView(utf16(), len / 2); } QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); } QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
}; };
Q_STATIC_ASSERT(std::is_pod<ByteData>::value); Q_STATIC_ASSERT(std::is_trivial<ByteData>::value);
Q_STATIC_ASSERT(std::is_standard_layout<ByteData>::value);
} // namespace QtCbor } // namespace QtCbor
Q_DECLARE_TYPEINFO(QtCbor::Element, Q_PRIMITIVE_TYPE); Q_DECLARE_TYPEINFO(QtCbor::Element, Q_PRIMITIVE_TYPE);

View File

@ -1666,7 +1666,7 @@ void QWindow::setGeometry(const QRect &rect)
if (newScreen && isTopLevel()) if (newScreen && isTopLevel())
nativeRect = QHighDpi::toNativePixels(rect, newScreen); nativeRect = QHighDpi::toNativePixels(rect, newScreen);
else else
nativeRect = QHighDpi::toNativePixels(rect, this); nativeRect = QHighDpi::toNativeLocalPosition(rect, newScreen);
d->platformWindow->setGeometry(nativeRect); d->platformWindow->setGeometry(nativeRect);
} else { } else {
d->geometry = rect; d->geometry = rect;
@ -1717,8 +1717,12 @@ QScreen *QWindowPrivate::screenForGeometry(const QRect &newGeometry) const
QRect QWindow::geometry() const QRect QWindow::geometry() const
{ {
Q_D(const QWindow); Q_D(const QWindow);
if (d->platformWindow) if (d->platformWindow) {
return QHighDpi::fromNativePixels(d->platformWindow->geometry(), this); const auto nativeGeometry = d->platformWindow->geometry();
return isTopLevel()
? QHighDpi::fromNativePixels(nativeGeometry, this)
: QHighDpi::fromNativeLocalPosition(nativeGeometry, this);
}
return d->geometry; return d->geometry;
} }

View File

@ -296,14 +296,21 @@ QWindowSystemInterfacePrivate::GeometryChangeEvent::GeometryChangeEvent(QWindow
, window(window) , window(window)
, newGeometry(newGeometry) , newGeometry(newGeometry)
{ {
if (const QPlatformWindow *pw = window->handle()) if (const QPlatformWindow *pw = window->handle()) {
requestedGeometry = QHighDpi::fromNativePixels(pw->QPlatformWindow::geometry(), window); const auto nativeGeometry = pw->QPlatformWindow::geometry();
requestedGeometry = window->isTopLevel()
? QHighDpi::fromNativePixels(nativeGeometry, window)
: QHighDpi::fromNativeLocalPosition(nativeGeometry, window);
}
} }
QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect) QT_DEFINE_QPA_EVENT_HANDLER(void, handleGeometryChange, QWindow *window, const QRect &newRect)
{ {
Q_ASSERT(window); Q_ASSERT(window);
QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, QHighDpi::fromNativePixels(newRect, window)); const auto newRectDi = window->isTopLevel()
? QHighDpi::fromNativePixels(newRect, window)
: QHighDpi::fromNativeLocalPosition(newRect, window);
auto e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(window, newRectDi);
if (window->handle()) { if (window->handle()) {
// Persist the new geometry so that QWindow::geometry() can be queried in the resize event // Persist the new geometry so that QWindow::geometry() can be queried in the resize event
window->handle()->QPlatformWindow::setGeometry(newRect); window->handle()->QPlatformWindow::setGeometry(newRect);

View File

@ -577,7 +577,10 @@ void QTextMarkdownImporter::insertBlock()
QTextBlockFormat blockFormat; QTextBlockFormat blockFormat;
if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) { if (!m_listStack.isEmpty() && !m_needsInsertList && m_listItem) {
QTextList *list = m_listStack.top(); QTextList *list = m_listStack.top();
if (list)
blockFormat = list->item(list->count() - 1).blockFormat(); blockFormat = list->item(list->count() - 1).blockFormat();
else
qWarning() << "attempted to insert into a list that no longer exists";
} }
if (m_blockQuoteDepth) { if (m_blockQuoteDepth) {
blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth); blockFormat.setProperty(QTextFormat::BlockQuoteLevel, m_blockQuoteDepth);
@ -607,7 +610,7 @@ void QTextMarkdownImporter::insertBlock()
} }
if (m_needsInsertList) { if (m_needsInsertList) {
m_listStack.push(m_cursor->createList(m_listFormat)); m_listStack.push(m_cursor->createList(m_listFormat));
} else if (!m_listStack.isEmpty() && m_listItem) { } else if (!m_listStack.isEmpty() && m_listItem && m_listStack.top()) {
m_listStack.top()->add(m_cursor->block()); m_listStack.top()->add(m_cursor->block());
} }
m_needsInsertList = false; m_needsInsertList = false;

View File

@ -56,6 +56,7 @@
#include <QtGui/qpalette.h> #include <QtGui/qpalette.h>
#include <QtGui/qtextdocument.h> #include <QtGui/qtextdocument.h>
#include <QtGui/qtextlist.h> #include <QtGui/qtextlist.h>
#include <QtCore/qpointer.h>
#include <QtCore/qstack.h> #include <QtCore/qstack.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -113,7 +114,7 @@ private:
#endif #endif
QString m_blockCodeLanguage; QString m_blockCodeLanguage;
QVector<int> m_nonEmptyTableCells; // in the current row QVector<int> m_nonEmptyTableCells; // in the current row
QStack<QTextList *> m_listStack; QStack<QPointer<QTextList>> m_listStack;
QStack<QTextCharFormat> m_spanFormatStack; QStack<QTextCharFormat> m_spanFormatStack;
QFont m_monoFont; QFont m_monoFont;
QPalette m_palette; QPalette m_palette;

View File

@ -46,7 +46,11 @@
#include <QSocketNotifier> #include <QSocketNotifier>
#include <QLoggingCategory> #include <QLoggingCategory>
#ifdef Q_OS_FREEBSD
#include <dev/evdev/input.h>
#else
#include <linux/input.h> #include <linux/input.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -334,7 +334,9 @@ QPlatformWindow *QWindowsIntegration::createPlatformWindow(QWindow *window) cons
QWindowsWindowData requested; QWindowsWindowData requested;
requested.flags = window->flags(); requested.flags = window->flags();
requested.geometry = QHighDpi::toNativePixels(window->geometry(), window); requested.geometry = window->isTopLevel()
? QHighDpi::toNativePixels(window->geometry(), window)
: QHighDpi::toNativeLocalPosition(window->geometry(), window);
// Apply custom margins (see QWindowsWindow::setCustomMargins())). // Apply custom margins (see QWindowsWindow::setCustomMargins())).
const QVariant customMarginsV = window->property("_q_windowsCustomMargins"); const QVariant customMarginsV = window->property("_q_windowsCustomMargins");
if (customMarginsV.isValid()) if (customMarginsV.isValid())

View File

@ -122,6 +122,7 @@ static const char *xcb_atomnames = {
"_NET_WM_STATE_MODAL\0" "_NET_WM_STATE_MODAL\0"
"_NET_WM_STATE_STAYS_ON_TOP\0" "_NET_WM_STATE_STAYS_ON_TOP\0"
"_NET_WM_STATE_DEMANDS_ATTENTION\0" "_NET_WM_STATE_DEMANDS_ATTENTION\0"
"_NET_WM_STATE_HIDDEN\0"
"_NET_WM_USER_TIME\0" "_NET_WM_USER_TIME\0"
"_NET_WM_USER_TIME_WINDOW\0" "_NET_WM_USER_TIME_WINDOW\0"

View File

@ -123,6 +123,7 @@ public:
_NET_WM_STATE_MODAL, _NET_WM_STATE_MODAL,
_NET_WM_STATE_STAYS_ON_TOP, _NET_WM_STATE_STAYS_ON_TOP,
_NET_WM_STATE_DEMANDS_ATTENTION, _NET_WM_STATE_DEMANDS_ATTENTION,
_NET_WM_STATE_HIDDEN,
_NET_WM_USER_TIME, _NET_WM_USER_TIME,
_NET_WM_USER_TIME_WINDOW, _NET_WM_USER_TIME_WINDOW,

View File

@ -276,7 +276,9 @@ void QXcbWindow::create()
QXcbScreen *currentScreen = xcbScreen(); QXcbScreen *currentScreen = xcbScreen();
QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen(); QXcbScreen *platformScreen = parent() ? parentScreen() : initialScreen();
QRect rect = QHighDpi::toNativePixels(window()->geometry(), platformScreen); QRect rect = parent()
? QHighDpi::toNativeLocalPosition(window()->geometry(), platformScreen)
: QHighDpi::toNativePixels(window()->geometry(), platformScreen);
if (type == Qt::Desktop) { if (type == Qt::Desktop) {
m_window = platformScreen->root(); m_window = platformScreen->root();
@ -905,6 +907,8 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
result |= NetWmStateStaysOnTop; result |= NetWmStateStaysOnTop;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
result |= NetWmStateDemandsAttention; result |= NetWmStateDemandsAttention;
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
result |= NetWmStateHidden;
} else { } else {
qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window); qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
} }
@ -1076,6 +1080,9 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
states |= NetWmStateBelow; states |= NetWmStateBelow;
} }
if (window()->windowStates() & Qt::WindowMinimized)
states |= NetWmStateHidden;
if (window()->windowStates() & Qt::WindowFullScreen) if (window()->windowStates() & Qt::WindowFullScreen)
states |= NetWmStateFullScreen; states |= NetWmStateFullScreen;
@ -1109,6 +1116,8 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW))) if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW)); atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
if (states & NetWmStateHidden && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_HIDDEN));
if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN))) if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ))) if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
@ -2217,10 +2226,16 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
|| (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized)); || (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
} }
} }
if (m_minimized)
newState = Qt::WindowMinimized;
const NetWmStates states = netWmStates(); const NetWmStates states = netWmStates();
// _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would
// not be visible on the screen if its desktop/viewport were active and its coordinates were
// within the screen bounds. The canonical example is that minimized windows should be in
// the _NET_WM_STATE_HIDDEN state.
if (m_minimized && (!connection()->wmSupport()->isSupportedByWM(NetWmStateHidden)
|| states.testFlag(NetWmStateHidden)))
newState = Qt::WindowMinimized;
if (states & NetWmStateFullScreen) if (states & NetWmStateFullScreen)
newState |= Qt::WindowFullScreen; newState |= Qt::WindowFullScreen;
if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))

View File

@ -68,7 +68,8 @@ public:
NetWmStateMaximizedVert = 0x10, NetWmStateMaximizedVert = 0x10,
NetWmStateModal = 0x20, NetWmStateModal = 0x20,
NetWmStateStaysOnTop = 0x40, NetWmStateStaysOnTop = 0x40,
NetWmStateDemandsAttention = 0x80 NetWmStateDemandsAttention = 0x80,
NetWmStateHidden = 0x100
}; };
Q_DECLARE_FLAGS(NetWmStates, NetWmState) Q_DECLARE_FLAGS(NetWmStates, NetWmState)

View File

@ -546,12 +546,19 @@ void WriteInitialization::acceptUI(DomUI *node)
m_output << m_option.indent << language::endFunctionDefinition("setupUi"); m_output << m_option.indent << language::endFunctionDefinition("setupUi");
if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) { if (!m_mainFormUsedInRetranslateUi) {
if (language::language() == Language::Cpp) {
// Mark varName as unused to avoid compiler warnings. // Mark varName as unused to avoid compiler warnings.
m_refreshInitialization += m_indent; m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("(void)"); m_refreshInitialization += QLatin1String("(void)");
m_refreshInitialization += varName ; m_refreshInitialization += varName ;
m_refreshInitialization += language::eol; m_refreshInitialization += language::eol;
} else if (language::language() == Language::Python) {
// output a 'pass' to have an empty function
m_refreshInitialization += m_indent;
m_refreshInitialization += QLatin1String("pass");
m_refreshInitialization += language::eol;
}
} }
m_output << m_option.indent m_output << m_option.indent

View File

@ -62,6 +62,7 @@
#include <qshareddata.h> #include <qshareddata.h>
#include <qdebug.h> #include <qdebug.h>
#include <stdio.h> #include <stdio.h>
#include <limits>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -4866,7 +4867,7 @@ void QDomElement::setAttribute(const QString& name, float value)
if (!impl) if (!impl)
return; return;
QString x; QString x;
x.setNum(value); x.setNum(value, 'g', 8);
IMPL->setAttribute(name, x); IMPL->setAttribute(name, x);
} }
@ -4880,7 +4881,7 @@ void QDomElement::setAttribute(const QString& name, double value)
if (!impl) if (!impl)
return; return;
QString x; QString x;
x.setNum(value); x.setNum(value, 'g', 17);
IMPL->setAttribute(name, x); IMPL->setAttribute(name, x);
} }
@ -5049,7 +5050,7 @@ void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, doub
if (!impl) if (!impl)
return; return;
QString x; QString x;
x.setNum(value); x.setNum(value, 'g', 17);
IMPL->setAttributeNS(nsURI, qName, x); IMPL->setAttributeNS(nsURI, qName, x);
} }

View File

@ -573,12 +573,32 @@ void tst_QDeadlineTimer::stdchrono()
QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero()); QCOMPARE(deadline.remainingTimeAsDuration(), nanoseconds::zero());
/*
Call QTest::qSleep, and return true if the time actually slept is
within \a deviationPercent percent of the requested sleep time.
Otherwise, return false, in which case the test should to abort.
*/
auto sleepHelper = [](int ms, int deviationPercent = 10) -> bool {
auto before = steady_clock::now();
QTest::qSleep(ms);
auto after = steady_clock::now();
auto diff = duration_cast<milliseconds>(after - before).count();
bool inRange = qAbs(diff - ms) < ms * deviationPercent/100.0;
if (!inRange)
qWarning() << "sleeping" << diff << "instead of" << ms << inRange;
return inRange;
};
auto steady_before = steady_clock::now(); auto steady_before = steady_clock::now();
auto system_before = system_clock::now(); auto system_before = system_clock::now();
QTest::qSleep(minResolution); if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto now = QDeadlineTimer::current(timerType); auto now = QDeadlineTimer::current(timerType);
QTest::qSleep(minResolution); auto steady_reference = steady_clock::now();
auto system_reference = system_clock::now();
if (!sleepHelper(minResolution))
QSKIP("Slept too long");
auto sampling_start = steady_clock::now(); auto sampling_start = steady_clock::now();
auto steady_deadline = now.deadline<steady_clock>(); auto steady_deadline = now.deadline<steady_clock>();
@ -599,35 +619,33 @@ void tst_QDeadlineTimer::stdchrono()
} }
{ {
auto diff = duration_cast<milliseconds>(steady_after - steady_deadline); auto reference = duration_cast<milliseconds>(steady_after - steady_reference).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); auto diff = duration_cast<milliseconds>(steady_after - steady_deadline).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_after(steady_after, timerType); QDeadlineTimer dt_after(steady_after, timerType);
QVERIFY2(now < dt_after, QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(steady_deadline - steady_before); reference = duration_cast<milliseconds>(steady_reference - steady_before).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff)));
QDeadlineTimer dt_before(steady_before, timerType); QDeadlineTimer dt_before(steady_before, timerType);
QVERIFY2(now > dt_before, QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());
} }
{ {
auto diff = duration_cast<milliseconds>(system_after - system_deadline); auto reference = duration_cast<milliseconds>(system_after - system_reference).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); auto diff = duration_cast<milliseconds>(system_after - system_deadline).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_after(system_after, timerType);
QDeadlineTimer dt_after(system_after, timerType);
QVERIFY2(now < dt_after, QVERIFY2(now < dt_after,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1()); "; after = " + QLocale().toString(dt_after.deadlineNSecs())).toLatin1());
diff = duration_cast<milliseconds>(system_deadline - system_before); reference = duration_cast<milliseconds>(system_reference - system_before).count();
QVERIFY2(diff.count() > minResolution/2, QByteArray::number(qint64(diff.count()))); diff = duration_cast<milliseconds>(steady_deadline - steady_before).count();
QVERIFY2(diff.count() < 3*minResolution/2, QByteArray::number(qint64(diff.count()))); QVERIFY2(diff > reference * 0.9 && diff < reference*1.1, QByteArray::number(qint64(diff))); QDeadlineTimer dt_before(system_before, timerType);
QDeadlineTimer dt_before(system_before, timerType);
QVERIFY2(now > dt_before, QVERIFY2(now > dt_before,
("now = " + QLocale().toString(now.deadlineNSecs()) + ("now = " + QLocale().toString(now.deadlineNSecs()) +
"; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1()); "; before = " + QLocale().toString(dt_before.deadlineNSecs())).toLatin1());

View File

@ -1,3 +0,0 @@
[elapsed]
macos
windows-10

View File

@ -368,7 +368,7 @@ void tst_QLibrary::errorString_data()
QTest::newRow("bad load()") << (int)Load << QString("nosuchlib") << false << QString("Cannot load library nosuchlib: .*"); QTest::newRow("bad load()") << (int)Load << QString("nosuchlib") << false << QString("Cannot load library nosuchlib: .*");
QTest::newRow("call errorString() on QLibrary with no d-pointer (crashtest)") << (int)(Load | DontSetFileName) << QString() << false << QString("Unknown error"); QTest::newRow("call errorString() on QLibrary with no d-pointer (crashtest)") << (int)(Load | DontSetFileName) << QString() << false << QString("Unknown error");
QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Cannot resolve symbol \"nosuchsymbol\" in \\S+: .*"); QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Unknown error");
QTest::newRow("good resolve") << (int)Resolve << appDir + "/mylib" << true << QString("Unknown error"); QTest::newRow("good resolve") << (int)Resolve << appDir + "/mylib" << true << QString("Unknown error");
#ifdef Q_OS_WIN #ifdef Q_OS_WIN

View File

@ -0,0 +1,5 @@
<t><EFBFBD>
* <20>
<09>
* <20>

View File

@ -0,0 +1 @@
| --:| <?`?><?|`

View File

@ -5,5 +5,7 @@ SOURCES += tst_qtextmarkdownimporter.cpp
TESTDATA += \ TESTDATA += \
data/thematicBreaks.md \ data/thematicBreaks.md \
data/headingBulletsContinuations.md \ data/headingBulletsContinuations.md \
data/fuzz20450.md \
data/fuzz20580.md \
DEFINES += SRCDIR=\\\"$$PWD\\\" DEFINES += SRCDIR=\\\"$$PWD\\\"

View File

@ -57,6 +57,8 @@ private slots:
void lists(); void lists();
void avoidBlankLineAtBeginning_data(); void avoidBlankLineAtBeginning_data();
void avoidBlankLineAtBeginning(); void avoidBlankLineAtBeginning();
void pathological_data();
void pathological();
}; };
void tst_QTextMarkdownImporter::headingBulletsContinuations() void tst_QTextMarkdownImporter::headingBulletsContinuations()
@ -256,5 +258,27 @@ void tst_QTextMarkdownImporter::avoidBlankLineAtBeginning() // QTBUG-81060
QCOMPARE(i, expectedNumberOfParagraphs); QCOMPARE(i, expectedNumberOfParagraphs);
} }
void tst_QTextMarkdownImporter::pathological_data()
{
QTest::addColumn<QString>("warning");
QTest::newRow("fuzz20450") << "attempted to insert into a list that no longer exists";
QTest::newRow("fuzz20580") << "";
}
void tst_QTextMarkdownImporter::pathological() // avoid crashing on crazy input
{
QFETCH(QString, warning);
QString filename = QLatin1String("data/") + QTest::currentDataTag() + QLatin1String(".md");
QFile f(QFINDTESTDATA(filename));
QVERIFY(f.open(QFile::ReadOnly));
#ifdef QT_NO_DEBUG
Q_UNUSED(warning)
#else
if (!warning.isEmpty())
QTest::ignoreMessage(QtWarningMsg, warning.toLatin1());
#endif
QTextDocument().setMarkdown(f.readAll());
}
QTEST_MAIN(tst_QTextMarkdownImporter) QTEST_MAIN(tst_QTextMarkdownImporter)
#include "tst_qtextmarkdownimporter.moc" #include "tst_qtextmarkdownimporter.moc"

View File

@ -2,7 +2,3 @@
# QTBUG-66345 # QTBUG-66345
opensuse-42.3 opensuse-42.3
ubuntu-16.04 ubuntu-16.04
[setWindowState]
ubuntu-18.04
rhel-7.6

View File

@ -38,6 +38,7 @@
#include <QtTest/QtTest> #include <QtTest/QtTest>
#include <QtXml> #include <QtXml>
#include <QVariant> #include <QVariant>
#include <cmath>
QT_FORWARD_DECLARE_CLASS(QDomDocument) QT_FORWARD_DECLARE_CLASS(QDomDocument)
QT_FORWARD_DECLARE_CLASS(QDomNode) QT_FORWARD_DECLARE_CLASS(QDomNode)
@ -408,7 +409,9 @@ void tst_QDom::setGetAttributes()
const int intVal = std::numeric_limits<int>::min(); const int intVal = std::numeric_limits<int>::min();
const uint uintVal = std::numeric_limits<uint>::max(); const uint uintVal = std::numeric_limits<uint>::max();
const float floatVal = 0.1234f; const float floatVal = 0.1234f;
const double doubleVal = 0.1234; const double doubleVal1 = 1./6.;
const double doubleVal2 = std::nextafter(doubleVal1, 1.);
const double doubleVal3 = std::nextafter(doubleVal2, 1.);
rootNode.setAttribute("qstringVal", qstringVal); rootNode.setAttribute("qstringVal", qstringVal);
rootNode.setAttribute("qlonglongVal", qlonglongVal); rootNode.setAttribute("qlonglongVal", qlonglongVal);
@ -416,7 +419,9 @@ void tst_QDom::setGetAttributes()
rootNode.setAttribute("intVal", intVal); rootNode.setAttribute("intVal", intVal);
rootNode.setAttribute("uintVal", uintVal); rootNode.setAttribute("uintVal", uintVal);
rootNode.setAttribute("floatVal", floatVal); rootNode.setAttribute("floatVal", floatVal);
rootNode.setAttribute("doubleVal", doubleVal); rootNode.setAttribute("doubleVal1", doubleVal1);
rootNode.setAttribute("doubleVal2", doubleVal2);
rootNode.setAttribute("doubleVal3", doubleVal3);
QDomElement nsNode = doc.createElement("NS"); QDomElement nsNode = doc.createElement("NS");
rootNode.appendChild(nsNode); rootNode.appendChild(nsNode);
@ -426,7 +431,9 @@ void tst_QDom::setGetAttributes()
nsNode.setAttributeNS("namespace", "intVal", intVal); nsNode.setAttributeNS("namespace", "intVal", intVal);
nsNode.setAttributeNS("namespace", "uintVal", uintVal); nsNode.setAttributeNS("namespace", "uintVal", uintVal);
nsNode.setAttributeNS("namespace", "floatVal", floatVal); // not available atm nsNode.setAttributeNS("namespace", "floatVal", floatVal); // not available atm
nsNode.setAttributeNS("namespace", "doubleVal", doubleVal); nsNode.setAttributeNS("namespace", "doubleVal1", doubleVal1);
nsNode.setAttributeNS("namespace", "doubleVal2", doubleVal2);
nsNode.setAttributeNS("namespace", "doubleVal3", doubleVal3);
bool bOk; bool bOk;
QCOMPARE(rootNode.attribute("qstringVal"), qstringVal); QCOMPARE(rootNode.attribute("qstringVal"), qstringVal);
@ -440,8 +447,10 @@ void tst_QDom::setGetAttributes()
QVERIFY(bOk); QVERIFY(bOk);
QCOMPARE(rootNode.attribute("floatVal").toFloat(&bOk), floatVal); QCOMPARE(rootNode.attribute("floatVal").toFloat(&bOk), floatVal);
QVERIFY(bOk); QVERIFY(bOk);
QCOMPARE(rootNode.attribute("doubleVal").toDouble(&bOk), doubleVal);
QVERIFY(bOk); QVERIFY(rootNode.attribute("doubleVal1").toDouble(&bOk) == doubleVal1 && bOk);
QVERIFY(rootNode.attribute("doubleVal2").toDouble(&bOk) == doubleVal2 && bOk);
QVERIFY(rootNode.attribute("doubleVal3").toDouble(&bOk) == doubleVal3 && bOk);
QCOMPARE(nsNode.attributeNS("namespace", "qstringVal"), qstringVal); QCOMPARE(nsNode.attributeNS("namespace", "qstringVal"), qstringVal);
QCOMPARE(nsNode.attributeNS("namespace", "qlonglongVal").toLongLong(&bOk), qlonglongVal); QCOMPARE(nsNode.attributeNS("namespace", "qlonglongVal").toLongLong(&bOk), qlonglongVal);
@ -454,8 +463,9 @@ void tst_QDom::setGetAttributes()
QVERIFY(bOk); QVERIFY(bOk);
QCOMPARE(nsNode.attributeNS("namespace", "floatVal").toFloat(&bOk), floatVal); QCOMPARE(nsNode.attributeNS("namespace", "floatVal").toFloat(&bOk), floatVal);
QVERIFY(bOk); QVERIFY(bOk);
QCOMPARE(nsNode.attributeNS("namespace", "doubleVal").toDouble(&bOk), doubleVal); QVERIFY(nsNode.attributeNS("namespace", "doubleVal1").toDouble(&bOk) == doubleVal1 && bOk);
QVERIFY(bOk); QVERIFY(nsNode.attributeNS("namespace", "doubleVal2").toDouble(&bOk) == doubleVal2 && bOk);
QVERIFY(nsNode.attributeNS("namespace", "doubleVal3").toDouble(&bOk) == doubleVal3 && bOk);
QLocale::setDefault(oldLocale); QLocale::setDefault(oldLocale);
} }