diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-03-31 01:00:13 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-03-31 01:00:13 +0200 |
commit | ffb2c2ac6c3ba40acbe13a39899a72049585b427 (patch) | |
tree | dbee14e6d1641e02ea1fd5fc67ce001ab12776ef | |
parent | 6d0044f1dcffebc29dccd9d37d90f8abdb941a88 (diff) | |
parent | dbdd5f0ffbce52c8b789ed09f1aa3f1da6c02e23 (diff) |
Merge remote-tracking branch 'origin/5.11' into dev
Change-Id: I33b47095efdfe0ba698c6a88ca41ec911f432208
23 files changed, 440 insertions, 245 deletions
diff --git a/examples/widgets/itemviews/frozencolumn/main.cpp b/examples/widgets/itemviews/frozencolumn/main.cpp index 5a4d3e0f42..6f2b4a8d71 100644 --- a/examples/widgets/itemviews/frozencolumn/main.cpp +++ b/examples/widgets/itemviews/frozencolumn/main.cpp @@ -51,6 +51,7 @@ #include <QApplication> #include <QStandardItemModel> #include <QFile> +#include <QTextStream> #include "freezetablewidget.h" @@ -63,14 +64,16 @@ int main(int argc, char* argv[]) QFile file(":/grades.txt"); if (file.open(QFile::ReadOnly)) { - QString line = file.readLine(200); + QTextStream stream(&file); + + QString line = stream.readLine(); QStringList list = line.simplified().split(','); model->setHorizontalHeaderLabels(list); int row = 0; QStandardItem *newItem = 0; - while (file.canReadLine()) { - line = file.readLine(200); + while (!stream.atEnd()) { + line = stream.readLine(); if (!line.startsWith('#') && line.contains(',')) { list = line.simplified().split(','); for (int col = 0; col < list.length(); ++col){ diff --git a/mkspecs/features/exclusive_builds.prf b/mkspecs/features/exclusive_builds.prf index b477cff162..2d7f0e1ab6 100644 --- a/mkspecs/features/exclusive_builds.prf +++ b/mkspecs/features/exclusive_builds.prf @@ -38,5 +38,5 @@ defineTest(addExclusiveBuilds) { } # Default directories to process -QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR -QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR +QMAKE_DIR_REPLACE = OBJECTS_DIR MOC_DIR RCC_DIR PRECOMPILED_DIR QGLTF_DIR DESTDIR TRACEGEN_DIR QMLCACHE_DIR +QMAKE_DIR_REPLACE_SANE += QGLTF_DIR TRACEGEN_DIR QMLCACHE_DIR diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf index a2fa1be481..021036e4f9 100644 --- a/mkspecs/features/qt_build_config.prf +++ b/mkspecs/features/qt_build_config.prf @@ -26,6 +26,7 @@ MOC_DIR = .moc RCC_DIR = .rcc UI_DIR = .uic TRACEGEN_DIR = .tracegen +QMLCACHE_DIR = .qmlcache intel_icl { # ICL 14.0 has a bug that makes it not find #includes in dirs starting with . MOC_DIR = tmp/moc diff --git a/qmake/library/ioutils.cpp b/qmake/library/ioutils.cpp index cb4aa5e74d..fd84dff59d 100644 --- a/qmake/library/ioutils.cpp +++ b/qmake/library/ioutils.cpp @@ -60,7 +60,7 @@ IoUtils::FileType IoUtils::fileType(const QString &fileName) struct ::stat st; if (::stat(fileName.toLocal8Bit().constData(), &st)) return FileNotFound; - return S_ISDIR(st.st_mode) ? FileIsDir : FileIsRegular; + return S_ISDIR(st.st_mode) ? FileIsDir : S_ISREG(st.st_mode) ? FileIsRegular : FileNotFound; #endif } @@ -258,9 +258,8 @@ bool IoUtils::touchFile(const QString &targetFileName, const QString &referenceF # endif return true; } -#endif -#ifdef Q_OS_UNIX +#if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX) bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target) { const QByteArray localSymlinkPath = QFile::encodeName(symlinkPath); @@ -295,4 +294,6 @@ bool IoUtils::readLinkTarget(const QString &symlinkPath, QString *target) } #endif +#endif // PROEVALUATOR_FULL + QT_END_NAMESPACE diff --git a/qmake/library/ioutils.h b/qmake/library/ioutils.h index ad379404f3..32bf675f62 100644 --- a/qmake/library/ioutils.h +++ b/qmake/library/ioutils.h @@ -29,6 +29,8 @@ #ifndef IOUTILS_H #define IOUTILS_H +#include "qmake_global.h" + #include <qstring.h> QT_BEGIN_NAMESPACE @@ -39,7 +41,7 @@ namespace QMakeInternal { This class provides replacement functionality for QFileInfo, QFile & QDir, as these are abysmally slow. */ -class IoUtils { +class QMAKE_EXPORT IoUtils { public: enum FileType { FileNotFound = 0, @@ -64,9 +66,9 @@ public: #endif #if defined(PROEVALUATOR_FULL) static bool touchFile(const QString &targetFileName, const QString &referenceFileName, QString *errorString); -#endif -#ifdef Q_OS_UNIX +# if defined(QT_BUILD_QMAKE) && defined(Q_OS_UNIX) static bool readLinkTarget(const QString &symlinkPath, QString *target); +# endif #endif }; diff --git a/qmake/library/qmakebuiltins.cpp b/qmake/library/qmakebuiltins.cpp index 0a83b9b930..c1d446263e 100644 --- a/qmake/library/qmakebuiltins.cpp +++ b/qmake/library/qmakebuiltins.cpp @@ -443,15 +443,18 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::parseJsonInto(const QByteArray &json QMakeEvaluator::VisitReturn QMakeEvaluator::writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, - bool exe, const QString &contents) + QMakeVfs::VfsFlags flags, const QString &contents) { + int oldId = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly); + int id = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsCreate); QString errStr; - if (!m_vfs->writeFile(fn, mode, exe, contents, &errStr)) { + if (!m_vfs->writeFile(id, mode, flags, contents, &errStr)) { evalError(fL1S("Cannot write %1file %2: %3") .arg(ctx, QDir::toNativeSeparators(fn), errStr)); return ReturnFalse; } - m_parser->discardFileFromCache(fn); + if (oldId) + m_parser->discardFileFromCache(oldId); return ReturnTrue; } @@ -1343,7 +1346,8 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } QString fn = resolvePath(args.at(0).toQString(m_tmp1)); - int pro = m_parser->idForFileName(fn); + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); + int pro = m_vfs->idForFileName(fn, flags | QMakeVfs::VfsAccessedOnly); if (!pro) return ReturnFalse; ProValueMap &vmap = m_valuemapStack.first(); @@ -1416,7 +1420,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( VisitReturn ret = ReturnFalse; QString contents = args.join(statics.field_sep); ProFile *pro = m_parser->parsedProBlock(QStringRef(&contents), - m_current.pro->fileName(), m_current.line); + 0, m_current.pro->fileName(), m_current.line); if (m_cumulative || pro->isOk()) { m_locationStack.push(m_current); visitProBlock(pro, pro->tokPtr()); @@ -1784,7 +1788,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( return ReturnFalse; } QIODevice::OpenMode mode = QIODevice::Truncate; - bool exe = false; + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); QString contents; if (args.count() >= 2) { const ProStringList &vals = values(args.at(1).toKey()); @@ -1796,7 +1800,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( if (opt == QLatin1String("append")) { mode = QIODevice::Append; } else if (opt == QLatin1String("exe")) { - exe = true; + flags |= QMakeVfs::VfsExecutable; } else { evalError(fL1S("write_file(): invalid flag %1.").arg(opt.toQString(m_tmp3))); return ReturnFalse; @@ -1806,7 +1810,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( } QString path = resolvePath(args.at(0).toQString(m_tmp1)); path.detach(); // make sure to not leak m_tmp1 into the map of written files. - return writeFile(QString(), path, mode, exe, contents); + return writeFile(QString(), path, mode, flags, contents); } case T_TOUCH: { if (args.count() != 2) { @@ -1960,6 +1964,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( varstr += QLatin1Char('\n'); } QString fn; + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); if (target == TargetSuper) { if (m_superfile.isEmpty()) { m_superfile = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.super")); @@ -1983,12 +1988,12 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateBuiltinConditional( fn = m_stashfile; if (fn.isEmpty()) fn = QDir::cleanPath(m_outputDir + QLatin1String("/.qmake.stash")); - if (!m_vfs->exists(fn)) { + if (!m_vfs->exists(fn, flags)) { printf("Info: creating stash file %s\n", qPrintable(QDir::toNativeSeparators(fn))); valuesRef(ProKey("_QMAKE_STASH_")) << ProString(fn); } } - return writeFile(fL1S("cache "), fn, QIODevice::Append, false, varstr); + return writeFile(fL1S("cache "), fn, QIODevice::Append, flags, varstr); } case T_RELOAD_PROPERTIES: #ifdef QT_BUILD_QMAKE diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp index 6e6c72de59..7112b57c11 100644 --- a/qmake/library/qmakeevaluator.cpp +++ b/qmake/library/qmakeevaluator.cpp @@ -1104,6 +1104,7 @@ void QMakeEvaluator::loadDefaults() bool QMakeEvaluator::prepareProject(const QString &inDir) { + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); QString superdir; if (m_option->do_cache) { QString conffile; @@ -1114,7 +1115,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) superdir = m_outputDir; forever { QString superfile = superdir + QLatin1String("/.qmake.super"); - if (m_vfs->exists(superfile)) { + if (m_vfs->exists(superfile, flags)) { m_superfile = QDir::cleanPath(superfile); break; } @@ -1129,10 +1130,10 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) QString dir = m_outputDir; forever { conffile = sdir + QLatin1String("/.qmake.conf"); - if (!m_vfs->exists(conffile)) + if (!m_vfs->exists(conffile, flags)) conffile.clear(); cachefile = dir + QLatin1String("/.qmake.cache"); - if (!m_vfs->exists(cachefile)) + if (!m_vfs->exists(cachefile, flags)) cachefile.clear(); if (!conffile.isEmpty() || !cachefile.isEmpty()) { if (dir != sdir) @@ -1160,7 +1161,7 @@ bool QMakeEvaluator::prepareProject(const QString &inDir) QString dir = m_outputDir; forever { QString stashfile = dir + QLatin1String("/.qmake.stash"); - if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile)) { + if (dir == (!superdir.isEmpty() ? superdir : m_buildRoot) || m_vfs->exists(stashfile, flags)) { m_stashfile = QDir::cleanPath(stashfile); break; } @@ -1259,7 +1260,7 @@ bool QMakeEvaluator::loadSpec() goto cool; } } - evalError(fL1S("Could not find qmake configuration file %1.").arg(qmakespec)); + evalError(fL1S("Could not find qmake spec '%1'.").arg(qmakespec)); return false; } cool: @@ -1285,7 +1286,8 @@ bool QMakeEvaluator::loadSpec() m_cachefile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) return false; } - if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile)) { + QMakeVfs::VfsFlags flags = (m_cumulative ? QMakeVfs::VfsCumulative : QMakeVfs::VfsExact); + if (!m_stashfile.isEmpty() && m_vfs->exists(m_stashfile, flags)) { valuesRef(ProKey("_QMAKE_STASH_")) << ProString(m_stashfile); if (evaluateFile( m_stashfile, QMakeHandler::EvalConfigFile, LoadProOnly) != ReturnTrue) @@ -1308,7 +1310,7 @@ void QMakeEvaluator::setupProject() void QMakeEvaluator::evaluateCommand(const QString &cmds, const QString &where) { if (!cmds.isEmpty()) { - ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), where, -1); + ProFile *pro = m_parser->parsedProBlock(QStringRef(&cmds), 0, where, -1); if (pro->isOk()) { m_locationStack.push(m_current); visitProBlock(pro, pro->tokPtr()); @@ -1812,7 +1814,7 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateConditional( const QStringRef &cond, const QString &where, int line) { VisitReturn ret = ReturnFalse; - ProFile *pro = m_parser->parsedProBlock(cond, where, line, QMakeParser::TestGrammar); + ProFile *pro = m_parser->parsedProBlock(cond, 0, where, line, QMakeParser::TestGrammar); if (pro->isOk()) { m_locationStack.push(m_current); ret = visitProBlock(pro, pro->tokPtr()); @@ -1980,23 +1982,34 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile( // needs to be determined. Failed lookups are represented via non-null empty strings. QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)]; if (fnp->isNull()) { - int start_root = 0; - const QStringList &paths = m_featureRoots->paths; - if (!currFn.isEmpty()) { - QStringRef currPath = IoUtils::pathName(currFn); - for (int root = 0; root < paths.size(); ++root) - if (currPath == paths.at(root)) { - start_root = root + 1; - break; - } - } - for (int root = start_root; root < paths.size(); ++root) { - QString fname = paths.at(root) + fn; - if (IoUtils::exists(fname)) { - fn = fname; +#ifdef QMAKE_OVERRIDE_PRFS + { + QString ovrfn(QLatin1String(":/qmake/override_features/") + fn); + if (QFileInfo::exists(ovrfn)) { + fn = ovrfn; goto cool; } } +#endif + { + int start_root = 0; + const QStringList &paths = m_featureRoots->paths; + if (!currFn.isEmpty()) { + QStringRef currPath = IoUtils::pathName(currFn); + for (int root = 0; root < paths.size(); ++root) + if (currPath == paths.at(root)) { + start_root = root + 1; + break; + } + } + for (int root = start_root; root < paths.size(); ++root) { + QString fname = paths.at(root) + fn; + if (IoUtils::exists(fname)) { + fn = fname; + goto cool; + } + } + } #ifdef QMAKE_BUILTIN_PRFS fn.prepend(QLatin1String(":/qmake/features/")); if (QFileInfo::exists(fn)) diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h index 7318664d46..1f0255e55a 100644 --- a/qmake/library/qmakeevaluator.h +++ b/qmake/library/qmakeevaluator.h @@ -34,6 +34,7 @@ #endif #include "qmakeparser.h" +#include "qmakevfs.h" #include "ioutils.h" #include <qlist.h> @@ -237,7 +238,7 @@ public: VisitReturn parseJsonInto(const QByteArray &json, const QString &into, ProValueMap *value); VisitReturn writeFile(const QString &ctx, const QString &fn, QIODevice::OpenMode mode, - bool exe, const QString &contents); + QMakeVfs::VfsFlags flags, const QString &contents); #if QT_CONFIG(process) void runProcess(QProcess *proc, const QString &command) const; #endif diff --git a/qmake/library/qmakeglobals.cpp b/qmake/library/qmakeglobals.cpp index d733d479cf..452b44c045 100644 --- a/qmake/library/qmakeglobals.cpp +++ b/qmake/library/qmakeglobals.cpp @@ -327,6 +327,13 @@ bool QMakeGlobals::initProperties() QT_PCLOSE(proc); } #endif + parseProperties(data, properties); + return true; +} +#endif + +void QMakeGlobals::parseProperties(const QByteArray &data, QHash<ProKey, ProString> &properties) +{ const auto lines = data.split('\n'); for (QByteArray line : lines) { int off = line.indexOf(':'); @@ -337,47 +344,50 @@ bool QMakeGlobals::initProperties() QString name = QString::fromLatin1(line.left(off)); ProString value = ProString(QDir::fromNativeSeparators( QString::fromLocal8Bit(line.mid(off + 1)))); + if (value.isNull()) + value = ProString(""); // Make sure it is not null, to discern from missing keys properties.insert(ProKey(name), value); if (name.startsWith(QLatin1String("QT_"))) { - bool plain = !name.contains(QLatin1Char('/')); - if (!plain) { - if (!name.endsWith(QLatin1String("/get"))) + enum { PropPut, PropRaw, PropGet } variant; + if (name.contains(QLatin1Char('/'))) { + if (name.endsWith(QLatin1String("/raw"))) + variant = PropRaw; + else if (name.endsWith(QLatin1String("/get"))) + variant = PropGet; + else // Nothing falls back on /src or /dev. continue; name.chop(4); + } else { + variant = PropPut; } if (name.startsWith(QLatin1String("QT_INSTALL_"))) { - if (plain) { - properties.insert(ProKey(name + QLatin1String("/raw")), value); - properties.insert(ProKey(name + QLatin1String("/get")), value); - } - properties.insert(ProKey(name + QLatin1String("/src")), value); - if (name == QLatin1String("QT_INSTALL_PREFIX") - || name == QLatin1String("QT_INSTALL_DATA") - || name == QLatin1String("QT_INSTALL_BINS")) { - name.replace(3, 7, QLatin1String("HOST")); - if (plain) { - properties.insert(ProKey(name), value); - properties.insert(ProKey(name + QLatin1String("/get")), value); + if (variant < PropRaw) { + if (name == QLatin1String("QT_INSTALL_PREFIX") + || name == QLatin1String("QT_INSTALL_DATA") + || name == QLatin1String("QT_INSTALL_LIBS") + || name == QLatin1String("QT_INSTALL_BINS")) { + // Qt4 fallback + QString hname = name; + hname.replace(3, 7, QLatin1String("HOST")); + properties.insert(ProKey(hname), value); + properties.insert(ProKey(hname + QLatin1String("/get")), value); + properties.insert(ProKey(hname + QLatin1String("/src")), value); } - properties.insert(ProKey(name + QLatin1String("/src")), value); + properties.insert(ProKey(name + QLatin1String("/raw")), value); } - } else if (name.startsWith(QLatin1String("QT_HOST_"))) { - if (plain) + if (variant <= PropRaw) + properties.insert(ProKey(name + QLatin1String("/dev")), value); + } else if (!name.startsWith(QLatin1String("QT_HOST_"))) { + continue; + } + if (variant != PropRaw) { + if (variant < PropGet) properties.insert(ProKey(name + QLatin1String("/get")), value); properties.insert(ProKey(name + QLatin1String("/src")), value); } } } - return true; } -#else -void QMakeGlobals::setProperties(const QHash<QString, QString> &props) -{ - QHash<QString, QString>::ConstIterator it = props.constBegin(), eit = props.constEnd(); - for (; it != eit; ++it) - properties.insert(ProKey(it.key()), ProString(it.value())); -} -#endif #endif // QT_BUILD_QMAKE QT_END_NAMESPACE diff --git a/qmake/library/qmakeglobals.h b/qmake/library/qmakeglobals.h index 000f685b73..6c00b1f3af 100644 --- a/qmake/library/qmakeglobals.h +++ b/qmake/library/qmakeglobals.h @@ -131,10 +131,10 @@ public: void reloadProperties() { property->reload(); } ProString propertyValue(const ProKey &name) const { return property->value(name); } #else + static void parseProperties(const QByteArray &data, QHash<ProKey, ProString> &props); # ifdef PROEVALUATOR_INIT_PROPS bool initProperties(); # else - void setProperties(const QHash<QString, QString> &props); void setProperties(const QHash<ProKey, ProString> &props) { properties = props; } # endif ProString propertyValue(const ProKey &name) const { return properties.value(name); } diff --git a/qmake/library/qmakeparser.cpp b/qmake/library/qmakeparser.cpp index b5d89c1ba6..37608c7a15 100644 --- a/qmake/library/qmakeparser.cpp +++ b/qmake/library/qmakeparser.cpp @@ -52,12 +52,22 @@ ProFileCache::~ProFileCache() ent.pro->deref(); } -void ProFileCache::discardFile(const QString &fileName) +void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs) +{ + int eid = vfs->idForFileName(fileName, QMakeVfs::VfsExact | QMakeVfs::VfsAccessedOnly); + if (eid) + discardFile(eid); + int cid = vfs->idForFileName(fileName, QMakeVfs::VfsCumulative | QMakeVfs::VfsAccessedOnly); + if (cid && cid != eid) + discardFile(cid); +} + +void ProFileCache::discardFile(int id) { #ifdef PROPARSER_THREAD_SAFE QMutexLocker lck(&mutex); #endif - QHash<QString, Entry>::Iterator it = parsed_files.find(fileName); + auto it = parsed_files.find(id); if (it != parsed_files.end()) { #ifdef PROPARSER_THREAD_SAFE if (it->locker) { @@ -77,16 +87,16 @@ void ProFileCache::discardFile(const QString &fileName) } } -void ProFileCache::discardFiles(const QString &prefix) +void ProFileCache::discardFiles(const QString &prefix, QMakeVfs *vfs) { #ifdef PROPARSER_THREAD_SAFE QMutexLocker lck(&mutex); #endif - QHash<QString, Entry>::Iterator - it = parsed_files.begin(), - end = parsed_files.end(); - while (it != end) - if (it.key().startsWith(prefix)) { + auto it = parsed_files.begin(), end = parsed_files.end(); + while (it != end) { + // Note: this is empty for virtual files from other VFSes. + QString fn = vfs->fileNameForId(it.key()); + if (fn.startsWith(prefix)) { #ifdef PROPARSER_THREAD_SAFE if (it->locker) { if (!it->locker->done) { @@ -105,6 +115,7 @@ void ProFileCache::discardFiles(const QString &prefix) } else { ++it; } + } } ////////// Parser /////////// @@ -167,12 +178,15 @@ QMakeParser::QMakeParser(ProFileCache *cache, QMakeVfs *vfs, QMakeParserHandler ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) { ProFile *pro; + QMakeVfs::VfsFlags vfsFlags = ((flags & ParseCumulative) ? QMakeVfs::VfsCumulative + : QMakeVfs::VfsExact); + int id = m_vfs->idForFileName(fileName, vfsFlags); if ((flags & ParseUseCache) && m_cache) { ProFileCache::Entry *ent; #ifdef PROPARSER_THREAD_SAFE QMutexLocker locker(&m_cache->mutex); #endif - QHash<QString, ProFileCache::Entry>::Iterator it = m_cache->parsed_files.find(fileName); + auto it = m_cache->parsed_files.find(id); if (it != m_cache->parsed_files.end()) { ent = &*it; #ifdef PROPARSER_THREAD_SAFE @@ -190,18 +204,18 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) if ((pro = ent->pro)) pro->ref(); } else { - ent = &m_cache->parsed_files[fileName]; + ent = &m_cache->parsed_files[id]; #ifdef PROPARSER_THREAD_SAFE ent->locker = new ProFileCache::Entry::Locker; locker.unlock(); #endif - pro = new ProFile(idForFileName(fileName), fileName); - if (!read(pro, flags)) { - delete pro; - pro = 0; - } else { + QString contents; + if (readFile(id, flags, &contents)) { + pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar); pro->itemsRef()->squeeze(); pro->ref(); + } else { + pro = 0; } ent->pro = pro; #ifdef PROPARSER_THREAD_SAFE @@ -216,51 +230,39 @@ ProFile *QMakeParser::parsedProFile(const QString &fileName, ParseFlags flags) #endif } } else { - pro = new ProFile(idForFileName(fileName), fileName); - if (!read(pro, flags)) { - delete pro; + QString contents; + if (readFile(id, flags, &contents)) + pro = parsedProBlock(QStringRef(&contents), id, fileName, 1, FullGrammar); + else pro = 0; - } } return pro; } ProFile *QMakeParser::parsedProBlock( - const QStringRef &contents, const QString &name, int line, SubGrammar grammar) + const QStringRef &contents, int id, const QString &name, int line, SubGrammar grammar) { - ProFile *pro = new ProFile(0, name); + ProFile *pro = new ProFile(id, name); read(pro, contents, line, grammar); return pro; } -int QMakeParser::idForFileName(const QString &fileName) -{ -#ifdef PROPARSER_THREAD_SAFE - QMutexLocker lck(&fileIdMutex); -#endif - int &place = fileIdMap[fileName]; - if (!place) - place = ++fileIdCounter; - return place; -} - -void QMakeParser::discardFileFromCache(const QString &fileName) +void QMakeParser::discardFileFromCache(int id) { if (m_cache) - m_cache->discardFile(fileName); + m_cache->discardFile(id); } -bool QMakeParser::read(ProFile *pro, ParseFlags flags) +bool QMakeParser::readFile(int id, ParseFlags flags, QString *contents) { - QString content; QString errStr; - if (!m_vfs->readFile(pro->fileName(), &content, &errStr)) { - if (m_handler && ((flags & ParseReportMissing) || m_vfs->exists(pro->fileName()))) + QMakeVfs::ReadResult result = m_vfs->readFile(id, contents, &errStr); + if (result != QMakeVfs::ReadOk) { + if (m_handler && ((flags & ParseReportMissing) || result != QMakeVfs::ReadNotFound)) m_handler->message(QMakeParserHandler::ParserIoError, - fL1S("Cannot read %1: %2").arg(pro->fileName(), errStr)); + fL1S("Cannot read %1: %2").arg(m_vfs->fileNameForId(id), errStr)); return false; } - read(pro, QStringRef(&content), 1, FullGrammar); return true; } diff --git a/qmake/library/qmakeparser.h b/qmake/library/qmakeparser.h index a29e9c227d..3ae30dcf74 100644 --- a/qmake/library/qmakeparser.h +++ b/qmake/library/qmakeparser.h @@ -30,6 +30,7 @@ #define QMAKEPARSER_H #include "qmake_global.h" +#include "qmakevfs.h" #include "proitems.h" #include <qhash.h> @@ -78,7 +79,12 @@ public: enum ParseFlag { ParseDefault = 0, ParseUseCache = 1, - ParseReportMissing = 4 + ParseReportMissing = 4, +#ifdef PROEVALUATOR_DUAL_VFS + ParseCumulative = 8 +#else + ParseCumulative = 0 +#endif }; Q_DECLARE_FLAGS(ParseFlags, ParseFlag) @@ -87,12 +93,10 @@ public: enum SubGrammar { FullGrammar, TestGrammar, ValueGrammar }; // fileName is expected to be absolute and cleanPath()ed. ProFile *parsedProFile(const QString &fileName, ParseFlags flags = ParseDefault); - ProFile *parsedProBlock(const QStringRef &contents, const QString &name, int line = 0, + ProFile *parsedProBlock(const QStringRef &contents, int id, const QString &name, int line = 0, SubGrammar grammar = FullGrammar); - int idForFileName(const QString &fileName); - - void discardFileFromCache(const QString &fileName); + void discardFileFromCache(int id); #ifdef PROPARSER_DEBUG static QString formatProBlock(const QString &block); @@ -131,7 +135,7 @@ private: ushort terminator; // '}' if replace function call is braced, ':' if test function }; - bool read(ProFile *pro, ParseFlags flags); + bool readFile(int id, QMakeParser::ParseFlags flags, QString *contents); void read(ProFile *pro, const QStringRef &content, int line, SubGrammar grammar); ALWAYS_INLINE void putTok(ushort *&tokPtr, ushort tok); @@ -182,12 +186,6 @@ private: QString m_tmp; // Temporary for efficient toQString - QHash<QString, int> fileIdMap; -#ifdef PROEVALUATOR_THREAD_SAFE - QMutex fileIdMutex; -#endif - int fileIdCounter = 0; - ProFileCache *m_cache; QMakeParserHandler *m_handler; QMakeVfs *m_vfs; @@ -206,8 +204,9 @@ public: ProFileCache() {} ~ProFileCache(); - void discardFile(const QString &fileName); - void discardFiles(const QString &prefix); + void discardFile(int id); + void discardFile(const QString &fileName, QMakeVfs *vfs); + void discardFiles(const QString &prefix, QMakeVfs *vfs); private: struct Entry { @@ -223,7 +222,7 @@ private: #endif }; - QHash<QString, Entry> parsed_files; + QHash<int, Entry> parsed_files; #ifdef PROPARSER_THREAD_SAFE QMutex mutex; #endif diff --git a/qmake/library/qmakevfs.cpp b/qmake/library/qmakevfs.cpp index 5aa9ec9299..2239a2beec 100644 --- a/qmake/library/qmakevfs.cpp +++ b/qmake/library/qmakevfs.cpp @@ -35,6 +35,10 @@ using namespace QMakeInternal; #include <qfile.h> #include <qfileinfo.h> +#ifndef QT_NO_TEXTCODEC +#include <qtextcodec.h> +#endif + #define fL1S(s) QString::fromLatin1(s) QT_BEGIN_NAMESPACE @@ -45,34 +49,107 @@ QMakeVfs::QMakeVfs() , m_magicExisting(fL1S("existing")) #endif { +#ifndef QT_NO_TEXTCODEC + m_textCodec = 0; +#endif +} + +#ifdef PROPARSER_THREAD_SAFE +QMutex QMakeVfs::s_mutex; +#endif +QAtomicInt QMakeVfs::s_fileIdCounter; +QHash<QString, int> QMakeVfs::s_fileIdMap; +QHash<int, QString> QMakeVfs::s_idFileMap; + +int QMakeVfs::idForFileName(const QString &fn, VfsFlags flags) +{ +#ifdef PROEVALUATOR_DUAL_VFS + { +# ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&m_vmutex); +# endif + int idx = (flags & VfsCumulative) ? 1 : 0; + if (flags & VfsCreate) { + int &id = m_virtualFileIdMap[idx][fn]; + if (!id) { + id = ++s_fileIdCounter; + m_virtualIdFileMap[id] = fn; + } + return id; + } + int id = m_virtualFileIdMap[idx].value(fn); + if (id || (flags & VfsCreatedOnly)) + return id; + } +#endif + if (!(flags & VfsAccessedOnly)) { +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&s_mutex); +#endif + int &id = s_fileIdMap[fn]; + if (!id) { + id = ++s_fileIdCounter; + s_idFileMap[id] = fn; + } + return id; + } + return s_fileIdMap.value(fn); +} + +QString QMakeVfs::fileNameForId(int id) +{ +#ifdef PROEVALUATOR_DUAL_VFS + { +# ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&m_vmutex); +# endif + const QString &fn = m_virtualIdFileMap.value(id); + if (!fn.isEmpty()) + return fn; + } +#endif +#ifdef PROPARSER_THREAD_SAFE + QMutexLocker locker(&s_mutex); +#endif + return s_idFileMap.value(id); +} + +void QMakeVfs::clearIds() +{ +#ifdef PROEVALUATOR_THREAD_SAFE + QMutexLocker locker(&s_mutex); +#endif + s_fileIdCounter = 0; + s_fileIdMap.clear(); + s_idFileMap.clear(); } -bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, +bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QString *cont = &m_files[fn]; + QString *cont = &m_files[id]; + Q_UNUSED(flags) if (mode & QIODevice::Append) *cont += contents; else *cont = contents; Q_UNUSED(errStr) - Q_UNUSED(exe) return true; #else - QFileInfo qfi(fn); + QFileInfo qfi(fileNameForId(id)); if (!QDir::current().mkpath(qfi.path())) { *errStr = fL1S("Cannot create parent directory"); return false; } QByteArray bytes = contents.toLocal8Bit(); - QFile cfile(fn); + QFile cfile(qfi.filePath()); if (!(mode & QIODevice::Append) && cfile.open(QIODevice::ReadOnly | QIODevice::Text)) { if (cfile.readAll() == bytes) { - if (exe) { + if (flags & VfsExecutable) { cfile.setPermissions(cfile.permissions() | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); } else { @@ -93,70 +170,78 @@ bool QMakeVfs::writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, *errStr = cfile.errorString(); return false; } - if (exe) + if (flags & VfsExecutable) cfile.setPermissions(cfile.permissions() | QFile::ExeUser | QFile::ExeGroup | QFile::ExeOther); return true; #endif } -bool QMakeVfs::readFile(const QString &fn, QString *contents, QString *errStr) +QMakeVfs::ReadResult QMakeVfs::readFile(int id, QString *contents, QString *errStr) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); + auto it = m_files.constFind(id); if (it != m_files.constEnd()) { if (it->constData() == m_magicMissing.constData()) { *errStr = fL1S("No such file or directory"); - return false; + return ReadNotFound; } if (it->constData() != m_magicExisting.constData()) { *contents = *it; - return true; + return ReadOk; } } #endif - QFile file(fn); + QFile file(fileNameForId(id)); if (!file.open(QIODevice::ReadOnly)) { + if (!file.exists()) { #ifndef PROEVALUATOR_FULL - if (!IoUtils::exists(fn)) { - m_files[fn] = m_magicMissing; - *errStr = fL1S("No such file or directory"); - } else + m_files[id] = m_magicMissing; #endif - *errStr = file.errorString(); - return false; + *errStr = fL1S("No such file or directory"); + return ReadNotFound; + } + *errStr = file.errorString(); + return ReadOtherError; } #ifndef PROEVALUATOR_FULL - m_files[fn] = m_magicExisting; + m_files[id] = m_magicExisting; #endif QByteArray bcont = file.readAll(); if (bcont.startsWith("\xef\xbb\xbf")) { // UTF-8 BOM will cause subtle errors *errStr = fL1S("Unexpected UTF-8 BOM"); - return false; + return ReadOtherError; } - *contents = QString::fromLocal8Bit(bcont); - return true; + *contents = +#ifndef QT_NO_TEXTCODEC + m_textCodec ? m_textCodec->toUnicode(bcont) : +#endif + QString::fromLocal8Bit(bcont); + return ReadOk; } -bool QMakeVfs::exists(const QString &fn) +bool QMakeVfs::exists(const QString &fn, VfsFlags flags) { #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QHash<QString, QString>::ConstIterator it = m_files.constFind(fn); + int id = idForFileName(fn, flags); + auto it = m_files.constFind(id); if (it != m_files.constEnd()) return it->constData() != m_magicMissing.constData(); +#else + Q_UNUSED(flags) #endif - bool ex = IoUtils::exists(fn); + bool ex = IoUtils::fileType(fn) == IoUtils::FileIsRegular; #ifndef PROEVALUATOR_FULL - m_files[fn] = ex ? m_magicExisting : m_magicMissing; + m_files[id] = ex ? m_magicExisting : m_magicMissing; #endif return ex; } @@ -168,7 +253,7 @@ void QMakeVfs::invalidateCache() # ifdef PROEVALUATOR_THREAD_SAFE QMutexLocker locker(&m_mutex); # endif - QHash<QString, QString>::Iterator it = m_files.begin(), eit = m_files.end(); + auto it = m_files.begin(), eit = m_files.end(); while (it != eit) { if (it->constData() == m_magicMissing.constData() ||it->constData() == m_magicExisting.constData()) @@ -188,4 +273,11 @@ void QMakeVfs::invalidateContents() } #endif +#ifndef QT_NO_TEXTCODEC +void QMakeVfs::setTextCodec(const QTextCodec *textCodec) +{ + m_textCodec = textCodec; +} +#endif + QT_END_NAMESPACE diff --git a/qmake/library/qmakevfs.h b/qmake/library/qmakevfs.h index 8677ba08c1..1217225471 100644 --- a/qmake/library/qmakevfs.h +++ b/qmake/library/qmakevfs.h @@ -31,12 +31,20 @@ #include "qmake_global.h" -# include <qiodevice.h> -#ifndef PROEVALUATOR_FULL -# include <qhash.h> -# include <qstring.h> -# ifdef PROEVALUATOR_THREAD_SAFE -# include <qmutex.h> +#include <qiodevice.h> +#include <qhash.h> +#include <qstring.h> +#ifdef PROEVALUATOR_THREAD_SAFE +# include <qmutex.h> +#endif + +#ifndef QT_NO_TEXTCODEC +QT_FORWARD_DECLARE_CLASS(QTextCodec) +#endif + +#ifdef PROEVALUATOR_DUAL_VFS +# ifndef PROEVALUATOR_CUMULATIVE +# error PROEVALUATOR_DUAL_VFS requires PROEVALUATOR_CUMULATIVE # endif #endif @@ -45,28 +53,85 @@ QT_BEGIN_NAMESPACE class QMAKE_EXPORT QMakeVfs { public: + enum ReadResult { + ReadOk, + ReadNotFound, + ReadOtherError + }; + + enum VfsFlag { + VfsExecutable = 1, + VfsExact = 0, +#ifdef PROEVALUATOR_DUAL_VFS + VfsCumulative = 2, + VfsCreate = 4, + VfsCreatedOnly = 8, +#else + VfsCumulative = 0, + VfsCreate = 0, + VfsCreatedOnly = 0, +#endif + VfsAccessedOnly = 16 + }; + Q_DECLARE_FLAGS(VfsFlags, VfsFlag) + QMakeVfs(); - bool writeFile(const QString &fn, QIODevice::OpenMode mode, bool exe, const QString &contents, QString *errStr); - bool readFile(const QString &fn, QString *contents, QString *errStr); - bool exists(const QString &fn); + int idForFileName(const QString &fn, VfsFlags flags); + QString fileNameForId(int id); + static void clearIds(); + bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr); + ReadResult readFile(int id, QString *contents, QString *errStr); + bool exists(const QString &fn, QMakeVfs::VfsFlags flags); #ifndef PROEVALUATOR_FULL void invalidateCache(); void invalidateContents(); #endif +#ifndef QT_NO_TEXTCODEC + void setTextCodec(const QTextCodec *textCodec); +#endif + private: +#ifdef PROEVALUATOR_THREAD_SAFE + static QMutex s_mutex; +#endif + static QAtomicInt s_fileIdCounter; + // Qt Creator's ProFile cache is a singleton to maximize its cross-project + // effectiveness (shared prf files from QtVersions). + // For this to actually work, real files need a global mapping. + // This is fine, because the namespace of real files is indeed global. + static QHash<QString, int> s_fileIdMap; + static QHash<int, QString> s_idFileMap; +#ifdef PROEVALUATOR_DUAL_VFS +# ifdef PROEVALUATOR_THREAD_SAFE + // The simple way to avoid recursing m_mutex. + QMutex m_vmutex; +# endif + // Virtual files are bound to the project context they were created in, + // so their ids need to be local as well. + // We violate that rule in lupdate (which has a non-dual VFS), but that + // does not matter, because it has only one project context anyway. + QHash<QString, int> m_virtualFileIdMap[2]; // Exact and cumulative + QHash<int, QString> m_virtualIdFileMap; // Only one map, as ids are unique across realms. +#endif + #ifndef PROEVALUATOR_FULL # ifdef PROEVALUATOR_THREAD_SAFE QMutex m_mutex; # endif - QHash<QString, QString> m_files; + QHash<int, QString> m_files; QString m_magicMissing; QString m_magicExisting; #endif +#ifndef QT_NO_TEXTCODEC + const QTextCodec *m_textCodec; +#endif }; +Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeVfs::VfsFlags) + QT_END_NAMESPACE #endif // QMAKEVFS_H diff --git a/qmake/project.cpp b/qmake/project.cpp index e8509ad096..e6bdb04bfb 100644 --- a/qmake/project.cpp +++ b/qmake/project.cpp @@ -123,7 +123,7 @@ QStringList QMakeProject::expand(const ProKey &func, const QList<ProStringList> ProString QMakeProject::expand(const QString &expr, const QString &where, int line) { ProString ret; - ProFile *pro = m_parser->parsedProBlock(QStringRef(&expr), where, line, + ProFile *pro = m_parser->parsedProBlock(QStringRef(&expr), 0, where, line, QMakeParser::ValueGrammar); if (pro->isOk()) { m_current.pro = pro; diff --git a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp index a17e541df3..d163129d54 100644 --- a/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp +++ b/src/corelib/doc/snippets/code/src_corelib_tools_qbytearray.cpp @@ -395,10 +395,10 @@ QByteArray ba = QByteArray::number(12.3456, 'E', 3); //! [43] static const char mydata[] = { - 0x00, 0x00, 0x03, 0x84, 0x78, 0x9c, 0x3b, 0x76, - 0xec, 0x18, 0xc3, 0x31, 0x0a, 0xf1, 0xcc, 0x99, + '\x00', '\x00', '\x03', '\x84', '\x78', '\x9c', '\x3b', '\x76', + '\xec', '\x18', '\xc3', '\x31', '\x0a', '\xf1', '\xcc', '\x99', ... - 0x6d, 0x5b + '\x6d', '\x5b' }; QByteArray data = QByteArray::fromRawData(mydata, sizeof(mydata)); diff --git a/src/corelib/thread/qsemaphore.cpp b/src/corelib/thread/qsemaphore.cpp index 6c4a211222..9a5505bd1e 100644 --- a/src/corelib/thread/qsemaphore.cpp +++ b/src/corelib/thread/qsemaphore.cpp @@ -120,12 +120,12 @@ using namespace QtFutex; If the system has the ability to wake up a precise number of threads, has Linux's FUTEX_WAKE_OP functionality, and is 64-bit, instead of using a - single bit indicating a contended semaphore, we'll store the total number - of waiters in the high word. Additionally, all multi-token waiters will be - waiting on that high word. So when releasing n tokens on those systems, we - tell the kernel to wake up n single-token threads and all of the - multi-token ones. Which threads get woken up is unspecified, but it's - likely single-token threads will get woken up first. + single bit indicating a contended semaphore, we'll store the number of + tokens *plus* total number of waiters in the high word. Additionally, all + multi-token waiters will be waiting on that high word. So when releasing n + tokens on those systems, we tell the kernel to wake up n single-token + threads and all of the multi-token ones. Which threads get woken up is + unspecified, but it's likely single-token threads will get woken up first. */ #if defined(FUTEX_OP) && QT_POINTER_SIZE > 4 @@ -231,10 +231,14 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp { // Try to acquire without waiting (we still loop because the testAndSet // call can fail). + quintptr nn = unsigned(n); + if (futexHasWaiterCount) + nn |= quint64(nn) << 32; // token count replicated in high word + quintptr curValue = u.loadAcquire(); while (futexAvailCounter(curValue) >= n) { // try to acquire - quintptr newValue = curValue - n; + quintptr newValue = curValue - nn; if (u.testAndSetOrdered(curValue, newValue, curValue)) return true; // succeeded! } @@ -242,7 +246,6 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp return false; // we need to wait - quintptr valueToSubtract = unsigned(n); quintptr oneWaiter = quintptr(Q_UINT64_C(1) << 32); // zero on 32-bit if (futexHasWaiterCount) { // increase the waiter count @@ -250,14 +253,15 @@ template <bool IsTimed> bool futexSemaphoreTryAcquire(QBasicAtomicInteger<quintp // We don't use the fetched value from above so futexWait() fails if // it changed after the testAndSetOrdered above. + if ((quint64(curValue) >> 32) == 0x7fffffff) + return false; // overflow! curValue += oneWaiter; - // Also adjust valueToSubtract to subtract oneWaiter when we succeed in - // acquiring. - valueToSubtract += oneWaiter; + // Also adjust nn to subtract oneWaiter when we succeed in acquiring. + nn += oneWaiter; } - if (futexSemaphoreTryAcquire_loop<IsTimed>(u, curValue, valueToSubtract, timeout)) + if (futexSemaphoreTryAcquire_loop<IsTimed>(u, curValue, nn, timeout)) return true; if (futexHasWaiterCount) { @@ -345,7 +349,10 @@ void QSemaphore::release(int n) Q_ASSERT_X(n >= 0, "QSemaphore::release", "parameter 'n' must be non-negative"); if (futexAvailable()) { - quintptr prevValue = u.fetchAndAddRelease(n); + quintptr nn = unsigned(n); + if (futexHasWaiterCount) + nn |= quint64(nn) << 32; // token count replicated in high word + quintptr prevValue = u.fetchAndAddRelease(nn); if (futexNeedsWake(prevValue)) { #ifdef FUTEX_OP if (!futexHasWaiterCount) { diff --git a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm index 25ff69d877..98b753eff9 100644 --- a/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm +++ b/src/platformsupport/fontdatabases/mac/qfontengine_coretext.mm @@ -824,7 +824,7 @@ void QCoreTextFontEngine::getUnscaledGlyph(glyph_t glyph, QPainterPath *path, gl QFixed QCoreTextFontEngine::emSquareSize() const { - return QFixed::QFixed(int(CTFontGetUnitsPerEm(ctfont))); + return QFixed(int(CTFontGetUnitsPerEm(ctfont))); } QFontEngine *QCoreTextFontEngine::cloneWithSize(qreal pixelSize) const diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 9fff4b5e42..9872b6b4e0 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1161,23 +1161,19 @@ void QWindowsWindow::fireExpose(const QRegion ®ion, bool force) QWindowSystemInterface::handleExposeEvent(window(), region); } -static inline QWindow *findTransientChild(const QWindow *parent) -{ - foreach (QWindow *w, QGuiApplication::topLevelWindows()) - if (w->transientParent() == parent) - return w; - return 0; -} - void QWindowsWindow::destroyWindow() { qCDebug(lcQpaWindows) << __FUNCTION__ << this << window() << m_data.hwnd; if (m_data.hwnd) { // Stop event dispatching before Window is destroyed. setFlag(WithinDestroy); // Clear any transient child relationships as Windows will otherwise destroy them (QTBUG-35499, QTBUG-36666) - if (QWindow *transientChild = findTransientChild(window())) - if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(transientChild)) - tw->updateTransientParent(); + const auto tlw = QGuiApplication::topLevelWindows(); + for (QWindow *w : tlw) { + if (w->transientParent() == window()) { + if (QWindowsWindow *tw = QWindowsWindow::windowsWindowOf(w)) + tw->updateTransientParent(); + } + } QWindowsContext *context = QWindowsContext::instance(); if (context->windowUnderMouse() == window()) context->clearWindowUnderMouse(); diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp index 92d3c5c171..4c7d095ca3 100644 --- a/src/tools/rcc/rcc.cpp +++ b/src/tools/rcc/rcc.cpp @@ -504,38 +504,8 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, if (QDir::isRelativePath(absFileName)) absFileName.prepend(currentPath); QFileInfo file(absFileName); - if (!file.exists()) { - m_failedResources.push_back(absFileName); - const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n") - .arg(fname, fileName); - m_errorDevice->write(msg.toUtf8()); - if (ignoreErrors) - continue; - else - return false; - } else if (file.isFile()) { - const bool arc = - addFile(alias, - RCCFileInfo(alias.section(slash, -1), - file, - language, - country, - RCCFileInfo::NoFlags, - compressLevel, - compressThreshold) - ); - if (!arc) - m_failedResources.push_back(absFileName); - } else { - QDir dir; - if (file.isDir()) { - dir.setPath(file.filePath()); - } else { - dir.setPath(file.path()); - dir.setNameFilters(QStringList(file.fileName())); - if (alias.endsWith(file.fileName())) - alias = alias.left(alias.length()-file.fileName().length()); - } + if (file.isDir()) { + QDir dir(file.filePath()); if (!alias.endsWith(slash)) alias += slash; QDirIterator it(dir, QDirIterator::FollowSymlinks|QDirIterator::Subdirectories); @@ -557,6 +527,33 @@ bool RCCResourceLibrary::interpretResourceFile(QIODevice *inputDevice, m_failedResources.push_back(child.fileName()); } } + } else if (file.isFile()) { + const bool arc = + addFile(alias, + RCCFileInfo(alias.section(slash, -1), + file, + language, + country, + RCCFileInfo::NoFlags, + compressLevel, + compressThreshold) + ); + if (!arc) + m_failedResources.push_back(absFileName); + } else if (file.exists()) { + m_failedResources.push_back(absFileName); + const QString msg = QString::fromLatin1("RCC: Error in '%1': Entry '%2' is neither a file nor a directory\n") + .arg(fname, fileName); + m_errorDevice->write(msg.toUtf8()); + return false; + } else { + m_failedResources.push_back(absFileName); + const QString msg = QString::fromLatin1("RCC: Error in '%1': Cannot find file '%2'\n") + .arg(fname, fileName); + m_errorDevice->write(msg.toUtf8()); + if (ignoreErrors) + continue; + return false; } } break; diff --git a/tests/auto/tools/qmakelib/evaltest.cpp b/tests/auto/tools/qmakelib/evaltest.cpp index abb7a1a964..aeedf4ae32 100644 --- a/tests/auto/tools/qmakelib/evaltest.cpp +++ b/tests/auto/tools/qmakelib/evaltest.cpp @@ -2375,11 +2375,7 @@ void tst_qmakelib::addTestFunctions(const QString &qindir) QTest::newRow("include(): fail") << "include(include/nope.pri): OK = 1" << "OK = UNDEF" -#ifdef Q_OS_WIN - << "Cannot read " + m_indir + "/include/nope.pri: The system cannot find the file specified." -#else << "Cannot read " + m_indir + "/include/nope.pri: No such file or directory" -#endif << true; QTest::newRow("include(): silent fail") @@ -2873,12 +2869,12 @@ void tst_qmakelib::proEval() globals.environment = m_env; globals.setProperties(m_prop); globals.setDirectories(m_indir, m_outdir); - ProFile *outPro = parser.parsedProBlock(QStringRef(&out), "out", 1, QMakeParser::FullGrammar); + ProFile *outPro = parser.parsedProBlock(QStringRef(&out), 0, "out", 1, QMakeParser::FullGrammar); if (!outPro->isOk()) { qWarning("Expected output is malformed"); verified = false; } - ProFile *pro = parser.parsedProBlock(QStringRef(&in), infile, 1, QMakeParser::FullGrammar); + ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, infile, 1, QMakeParser::FullGrammar); QMakeEvaluator visitor(&globals, &parser, &vfs, &handler); visitor.setOutputDir(m_outdir); #ifdef Q_OS_WIN diff --git a/tests/auto/tools/qmakelib/parsertest.cpp b/tests/auto/tools/qmakelib/parsertest.cpp index 70f1be5fc3..f736bf38bf 100644 --- a/tests/auto/tools/qmakelib/parsertest.cpp +++ b/tests/auto/tools/qmakelib/parsertest.cpp @@ -2031,7 +2031,7 @@ void tst_qmakelib::proParser() handler.setExpectedMessages(msgs.split('\n', QString::SkipEmptyParts)); QMakeVfs vfs; QMakeParser parser(0, &vfs, &handler); - ProFile *pro = parser.parsedProBlock(QStringRef(&in), "in", 1, QMakeParser::FullGrammar); + ProFile *pro = parser.parsedProBlock(QStringRef(&in), 0, "in", 1, QMakeParser::FullGrammar); if (handler.printedMessages()) { qWarning("Got unexpected message(s)"); verified = false; diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index 8287b9ebdd..4cd2fef2dc 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -281,7 +281,7 @@ void tst_QGraphicsProxyWidget::initTestCase() // This will be called after every test function. void tst_QGraphicsProxyWidget::cleanup() { - QVERIFY(QApplication::topLevelWidgets().isEmpty()); + QTRY_VERIFY(QApplication::topLevelWidgets().isEmpty()); } void tst_QGraphicsProxyWidget::qgraphicsproxywidget_data() @@ -2575,6 +2575,22 @@ void tst_QGraphicsProxyWidget::changingCursor_basic() } #endif +static bool findViewAndTipLabel(const QWidget *view) +{ + bool foundView = false; + bool foundTipLabel = false; + const QWidgetList &topLevels = QApplication::topLevelWidgets(); + for (const QWidget *widget : topLevels) { + if (widget == view) + foundView = true; + if (widget->inherits("QTipLabel")) + foundTipLabel = true; + if (foundView && foundTipLabel) + return true; + } + return false; +} + void tst_QGraphicsProxyWidget::tooltip_basic() { QString toolTip = "Qt rocks!"; @@ -2627,18 +2643,7 @@ void tst_QGraphicsProxyWidget::tooltip_basic() QHelpEvent helpEvent(QEvent::ToolTip, view.mapFromScene(proxy->boundingRect().center()), view.viewport()->mapToGlobal(view.mapFromScene(proxy->boundingRect().center()))); QApplication::sendEvent(view.viewport(), &helpEvent); - QTest::qWait(350); - - bool foundView = false; - bool foundTipLabel = false; - foreach (QWidget *widget, QApplication::topLevelWidgets()) { - if (widget == &view) - foundView = true; - if (widget->inherits("QTipLabel")) - foundTipLabel = true; - } - QVERIFY(foundView); - QVERIFY(foundTipLabel); + QTRY_VERIFY(findViewAndTipLabel(&view)); } } |