Merge remote-tracking branch 'origin/5.12' into 5.13

Change-Id: Ia3591d7288bac3bf441f27e486d35e2c5c481993
bb10
Qt Forward Merge Bot 2019-03-27 10:28:54 +01:00
commit b176a6a159
7 changed files with 225 additions and 46 deletions

View File

@ -1156,6 +1156,66 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
}
#endif
static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color)
{
Q_ASSERT(color);
Q_ASSERT(context);
CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context);
NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace];
NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace];
[targetNSColorSpace release];
return adjusted;
}
static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4])
{
Q_ASSERT(context);
auto colorSpace = CGBitmapContextGetColorSpace(context);
if (!colorSpace)
return nil;
return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]);
}
static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect)
{
Q_ASSERT(context);
static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97};
static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9};
NSColor *fillColor = qt_colorForContext(context, selected ? white : gray);
[fillColor setFill];
if (state == NSOffState) {
static NSBezierPath *triangle = [[NSBezierPath alloc] init];
[triangle removeAllPoints];
// In off state, a disclosure button is an equilateral triangle
// ('pointing' to the right) with a bound rect that can be described
// as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by
// (2, 4).
[triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)];
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)];
[triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)];
[triangle closePath];
[triangle fill];
} else {
static NSBezierPath *openTriangle = [[NSBezierPath alloc] init];
[openTriangle removeAllPoints];
// In 'on' state, the button is an equilateral triangle (looking down)
// with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect'
// it's translated by (1, 4).
[openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)];
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)];
[openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)];
[openTriangle closePath];
[openTriangle fill];
}
}
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
{
QPainterPath focusRingPath;
@ -3241,8 +3301,15 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
CGContextScaleCTM(cg, 1, -1);
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) {
// When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme,
// under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark'
// code path and is becoming transparent, thus 'invisible' on the white background. To workaround this,
// we draw the disclose triangle manually:
qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect);
} else {
[triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
}
d->restoreNSGraphicsContext(cg);
break; }

View File

@ -83,56 +83,56 @@ void QAppleTestLogger::leaveTestFunction()
testFunctionActivity.leave();
}
typedef QPair<QtMsgType, const char *> IncidentClassification;
static IncidentClassification incidentTypeToClassification(QAbstractTestLogger::IncidentTypes type)
struct MessageData
{
switch (type) {
case QAbstractTestLogger::Pass:
return IncidentClassification(QtInfoMsg, "pass");
case QAbstractTestLogger::XFail:
return IncidentClassification(QtInfoMsg, "xfail");
case QAbstractTestLogger::Fail:
return IncidentClassification(QtCriticalMsg, "fail");
case QAbstractTestLogger::XPass:
return IncidentClassification(QtInfoMsg, "xpass");
case QAbstractTestLogger::BlacklistedPass:
return IncidentClassification(QtWarningMsg, "bpass");
case QAbstractTestLogger::BlacklistedFail:
return IncidentClassification(QtInfoMsg, "bfail");
case QAbstractTestLogger::BlacklistedXPass:
return IncidentClassification(QtWarningMsg, "bxpass");
case QAbstractTestLogger::BlacklistedXFail:
return IncidentClassification(QtInfoMsg, "bxfail");
QtMsgType messageType = QtFatalMsg;
const char *categorySuffix = nullptr;
void generateCategory(QTestCharBuffer *category)
{
if (categorySuffix)
QTest::qt_asprintf(category, "qt.test.%s", categorySuffix);
else
QTest::qt_asprintf(category, "qt.test");
}
return IncidentClassification(QtFatalMsg, nullptr);
}
};
void QAppleTestLogger::addIncident(IncidentTypes type, const char *description,
const char *file, int line)
{
IncidentClassification incidentClassification = incidentTypeToClassification(type);
MessageData messageData = [=]() {
switch (type) {
case QAbstractTestLogger::Pass:
return MessageData{QtInfoMsg, "pass"};
case QAbstractTestLogger::XFail:
return MessageData{QtInfoMsg, "xfail"};
case QAbstractTestLogger::Fail:
return MessageData{QtCriticalMsg, "fail"};
case QAbstractTestLogger::XPass:
return MessageData{QtInfoMsg, "xpass"};
case QAbstractTestLogger::BlacklistedPass:
return MessageData{QtWarningMsg, "bpass"};
case QAbstractTestLogger::BlacklistedFail:
return MessageData{QtInfoMsg, "bfail"};
case QAbstractTestLogger::BlacklistedXPass:
return MessageData{QtWarningMsg, "bxpass"};
case QAbstractTestLogger::BlacklistedXFail:
return MessageData{QtInfoMsg, "bxfail"};
}
Q_UNREACHABLE();
}();
QTestCharBuffer category;
QTest::qt_asprintf(&category, "qt.test.%s", incidentClassification.second);
messageData.generateCategory(&category);
QMessageLogContext context(file, line, /* function = */ nullptr, category.data());
QTestCharBuffer subsystemBuffer;
// It would be nice to have the data tag as part of the subsystem too, but that
// will for some tests results in hundreds of thousands of log objects being
// created, so we limit the subsystem to test functions, which we can hope
// are reasonably limited.
generateTestIdentifier(&subsystemBuffer, TestObject | TestFunction);
QString subsystem = QString::fromLatin1(subsystemBuffer.data());
// We still want the full identifier as part of the message though
QTestCharBuffer testIdentifier;
generateTestIdentifier(&testIdentifier);
QString message = QString::fromLatin1(testIdentifier.data());
QString message = testIdentifier();
if (qstrlen(description))
message += QLatin1Char('\n') % QString::fromLatin1(description);
AppleUnifiedLogger::messageHandler(incidentClassification.first, context, message, subsystem);
AppleUnifiedLogger::messageHandler(messageData.messageType, context, message, subsystem());
}
void QAppleTestLogger::addMessage(QtMsgType type, const QMessageLogContext &context, const QString &message)
@ -140,6 +140,62 @@ void QAppleTestLogger::addMessage(QtMsgType type, const QMessageLogContext &cont
AppleUnifiedLogger::messageHandler(type, context, message);
}
void QAppleTestLogger::addMessage(MessageTypes type, const QString &message, const char *file, int line)
{
MessageData messageData = [=]() {
switch (type) {
case QAbstractTestLogger::Warn:
case QAbstractTestLogger::QWarning:
return MessageData{QtWarningMsg, nullptr};
case QAbstractTestLogger::QDebug:
return MessageData{QtDebugMsg, nullptr};
case QAbstractTestLogger::QSystem:
return MessageData{QtWarningMsg, "system"};
case QAbstractTestLogger::QFatal:
return MessageData{QtFatalMsg, nullptr};
case QAbstractTestLogger::Skip:
return MessageData{QtInfoMsg, "skip"};
case QAbstractTestLogger::Info:
case QAbstractTestLogger::QInfo:
return MessageData{QtInfoMsg, nullptr};
}
Q_UNREACHABLE();
}();
QTestCharBuffer category;
messageData.generateCategory(&category);
QMessageLogContext context(file, line, /* function = */ nullptr, category.data());
QString msg = message;
if (type == Skip) {
if (!message.isNull())
msg.prepend(testIdentifier() + QLatin1Char('\n'));
else
msg = testIdentifier();
}
AppleUnifiedLogger::messageHandler(messageData.messageType, context, msg, subsystem());
}
QString QAppleTestLogger::subsystem() const
{
QTestCharBuffer buffer;
// It would be nice to have the data tag as part of the subsystem too, but that
// will for some tests result in hundreds of thousands of log objects being
// created, so we limit the subsystem to test functions, which we can hope
// are reasonably limited.
generateTestIdentifier(&buffer, TestObject | TestFunction);
return QString::fromLatin1(buffer.data());
}
QString QAppleTestLogger::testIdentifier() const
{
QTestCharBuffer buffer;
generateTestIdentifier(&buffer);
return QString::fromLatin1(buffer.data());
}
#endif // QT_USE_APPLE_UNIFIED_LOGGING
QT_END_NAMESPACE

View File

@ -73,11 +73,14 @@ public:
void addMessage(QtMsgType, const QMessageLogContext &,
const QString &) override;
void addMessage(MessageTypes type, const QString &message,
const char *file = 0, int line = 0) override
{ Q_UNUSED(type); Q_UNUSED(message); Q_UNUSED(file); Q_UNUSED(line); Q_UNREACHABLE(); }
const char *file = 0, int line = 0) override;
void addBenchmarkResult(const QBenchmarkResult &result) override
{ Q_UNUSED(result); }
private:
QString subsystem() const;
QString testIdentifier() const;
};
#endif

View File

@ -31,7 +31,7 @@
#include <QProcess>
#include <QDir>
static QString targetName( BuildType buildMode, const QString& target, const QString& version )
QString TestCompiler::targetName(BuildType buildMode, const QString& target, const QString& version)
{
Q_UNUSED(version);
QString targetName = target;
@ -257,7 +257,8 @@ bool TestCompiler::qmakeProject( const QString &workDir, const QString &proName
return runCommand(qmakeCmd_, QStringList() << "-project" << "-o" << projectFile << "DESTDIR=./");
}
bool TestCompiler::qmake( const QString &workDir, const QString &proName, const QString &buildDir )
bool TestCompiler::qmake(const QString &workDir, const QString &proName, const QString &buildDir,
const QStringList &additionalArguments)
{
QDir D;
D.setCurrent( workDir );
@ -274,7 +275,8 @@ bool TestCompiler::qmake( const QString &workDir, const QString &proName, const
makeFile += "Makefile";
// Now start qmake and generate the makefile
return runCommand(qmakeCmd_, QStringList(qmakeArgs_) << projectFile << "-o" << makeFile);
return runCommand(qmakeCmd_, QStringList(qmakeArgs_) << projectFile << "-o" << makeFile
<< additionalArguments);
}
bool TestCompiler::make( const QString &workPath, const QString &target, bool expectFail )

View File

@ -49,6 +49,8 @@ public:
void resetEnvironment();
void addToEnvironment( QString varAssignment );
static QString targetName(BuildType buildMode, const QString& target, const QString& version);
// executes a make clean in the specified workPath
bool makeClean( const QString &workPath );
// executes a make dist clean in the specified workPath
@ -56,7 +58,8 @@ public:
// executes a qmake -project on the specified workDir
bool qmakeProject( const QString &workDir, const QString &proName );
// executes a qmake on proName in the specified workDir, output goes to buildDir or workDir if it's null
bool qmake( const QString &workDir, const QString &proName, const QString &buildDir = QString() );
bool qmake(const QString &workDir, const QString &proName, const QString &buildDir = QString(),
const QStringList &additionalArguments = QStringList());
// executes a make in the specified workPath, with an optional target (eg. install)
bool make( const QString &workPath, const QString &target = QString(), bool expectFail = false );
// checks if the executable exists in destDir

View File

@ -5,3 +5,8 @@ SOURCES = test_file.cpp \
RESOURCES = test.qrc
TARGET = "simple app"
DESTDIR = "dest dir"
target.path = $$OUT_PWD/dist
INSTALLS += target
!build_pass:msvc:CONFIG(debug, debug|release):message("check for pdb, please")

View File

@ -58,6 +58,7 @@ private slots:
void simple_app();
void simple_app_shadowbuild();
void simple_app_shadowbuild2();
void simple_app_versioned();
void simple_lib();
void simple_dll();
void subdirs();
@ -173,10 +174,15 @@ void tst_qmake::simple_app()
{
QString workDir = base_path + "/testdata/simple_app";
QString destDir = workDir + "/dest dir";
QString installDir = workDir + "/dist";
QVERIFY( test_compiler.qmake( workDir, "simple_app" ));
QVERIFY( test_compiler.qmake( workDir, "simple_app", QString() ));
QVERIFY( test_compiler.make( workDir ));
QVERIFY( test_compiler.exists( destDir, "simple app", Exe, "1.0.0" ));
QVERIFY(test_compiler.make(workDir, "install"));
QVERIFY(test_compiler.exists(installDir, "simple app", Exe, "1.0.0"));
QVERIFY( test_compiler.makeClean( workDir ));
QVERIFY( test_compiler.exists( destDir, "simple app", Exe, "1.0.0" )); // Should still exist after a make clean
QVERIFY( test_compiler.makeDistClean( workDir ));
@ -216,6 +222,43 @@ void tst_qmake::simple_app_shadowbuild2()
QVERIFY( test_compiler.removeMakefile( buildDir ) );
}
void tst_qmake::simple_app_versioned()
{
QString workDir = base_path + "/testdata/simple_app";
QString buildDir = base_path + "/testdata/simple_app_versioned_build";
QString destDir = buildDir + "/dest dir";
QString installDir = buildDir + "/dist";
QString version = "4.5.6";
QVERIFY(test_compiler.qmake(workDir, "simple_app", buildDir, QStringList{ "VERSION=" + version }));
QString qmakeOutput = test_compiler.commandOutput();
QVERIFY(test_compiler.make(buildDir));
QVERIFY(test_compiler.exists(destDir, "simple app", Exe, version));
QString pdbFilePath;
bool checkPdb = qmakeOutput.contains("Project MESSAGE: check for pdb, please");
if (checkPdb) {
QString targetBase = QFileInfo(TestCompiler::targetName(Exe, "simple app", version))
.completeBaseName();
pdbFilePath = destDir + '/' + targetBase + ".pdb";
QVERIFY2(QFile::exists(pdbFilePath), qPrintable(pdbFilePath));
QVERIFY(test_compiler.make(buildDir, "install"));
QString installedPdbFilePath = installDir + '/' + targetBase + ".pdb";
QEXPECT_FAIL("", "QTBUG-74265", Continue);
QVERIFY2(QFile::exists(installedPdbFilePath), qPrintable(installedPdbFilePath));
}
QVERIFY(test_compiler.makeClean(buildDir));
QVERIFY(test_compiler.exists(destDir, "simple app", Exe, version));
QVERIFY(test_compiler.makeDistClean(buildDir));
QVERIFY(!test_compiler.exists(destDir, "simple app", Exe, version));
if (checkPdb) {
QEXPECT_FAIL("", "QTBUG-74265", Continue);
QVERIFY(!QFile::exists(pdbFilePath));
}
QVERIFY(test_compiler.removeMakefile(buildDir));
}
void tst_qmake::simple_dll()
{
QString workDir = base_path + "/testdata/simple_dll";