Merge remote-tracking branch 'origin/5.6' into 5.7
Conflicts: src/plugins/platforms/eglfs/qeglfshooks.cpp Change-Id: I483f0dbd876943b184803f0fe65a0c686ad75db2bb10
commit
28628a5d5e
|
|
@ -1,6 +1 @@
|
|||
mingw {
|
||||
TMPPATH = $$(INCLUDE)
|
||||
QMAKE_INCDIR_POST += $$split(TMPPATH, $$QMAKE_DIRLIST_SEP)
|
||||
TMPPATH = $$(LIB)
|
||||
QMAKE_LIBDIR_POST += $$split(TMPPATH, $$QMAKE_DIRLIST_SEP)
|
||||
}
|
||||
# This file exists only to detach the tests from the surroundings.
|
||||
|
|
|
|||
|
|
@ -290,7 +290,8 @@ contains(TEMPLATE, .*app) {
|
|||
autoplugs =
|
||||
for (qtmod, qt_module_deps) {
|
||||
for (ptype, QT.$${qtmod}.plugin_types) {
|
||||
isEmpty(QTPLUGIN.$$ptype) {
|
||||
nptype = $$replace(ptype, [-/], _)
|
||||
isEmpty(QTPLUGIN.$$nptype) {
|
||||
for (plug, QT_PLUGINS) {
|
||||
equals(QT_PLUGIN.$${plug}.TYPE, $$ptype) {
|
||||
for (dep, QT_PLUGIN.$${plug}.EXTENDS) {
|
||||
|
|
@ -303,7 +304,7 @@ contains(TEMPLATE, .*app) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
plug = $$eval(QTPLUGIN.$$ptype)
|
||||
plug = $$eval(QTPLUGIN.$$nptype)
|
||||
!equals(plug, -): \
|
||||
autoplugs += $$plug
|
||||
}
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri
|
|||
else: \
|
||||
module_config =
|
||||
!isEmpty(MODULE_PLUGIN_TYPES): \
|
||||
module_plugtypes = "QT.$${MODULE_ID}.plugin_types = $$replace(MODULE_PLUGIN_TYPES, /.*$, )"
|
||||
module_plugtypes = "QT.$${MODULE_ID}.plugin_types = $$replace(MODULE_PLUGIN_TYPES, /[^.]+\\.[^.]+$, )"
|
||||
else: \
|
||||
module_plugtypes =
|
||||
!isEmpty(MODULE_MASTER_HEADER): \
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@
|
|||
|
||||
\section1 Event Types
|
||||
|
||||
Most events types have special classes, notably QResizeEvent,
|
||||
Most event types have special classes, notably QResizeEvent,
|
||||
QPaintEvent, QMouseEvent, QKeyEvent, and QCloseEvent. Each class
|
||||
subclasses QEvent and adds event-specific functions. For example,
|
||||
QResizeEvent adds \l{QResizeEvent::}{size()} and
|
||||
|
|
|
|||
|
|
@ -293,8 +293,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
|
|||
\note To speed up performance, QFileInfo caches information about
|
||||
the file.
|
||||
|
||||
To speed up performance, QFileInfo caches information about the
|
||||
file. Because files can be changed by other users or programs, or
|
||||
Because files can be changed by other users or programs, or
|
||||
even by other parts of the same program, there is a function that
|
||||
refreshes the file information: refresh(). If you want to switch
|
||||
off a QFileInfo's caching and force it to access the file system
|
||||
|
|
|
|||
|
|
@ -282,7 +282,7 @@ QFileSystemEntry QFileSystemEngine::canonicalName(const QFileSystemEntry &entry,
|
|||
if (ret) {
|
||||
data.knownFlagsMask |= QFileSystemMetaData::ExistsAttribute;
|
||||
data.entryFlags |= QFileSystemMetaData::ExistsAttribute;
|
||||
QString canonicalPath = QDir::cleanPath(QString::fromLocal8Bit(ret));
|
||||
QString canonicalPath = QDir::cleanPath(QFile::decodeName(ret));
|
||||
free(ret);
|
||||
return QFileSystemEntry(canonicalPath);
|
||||
} else if (errno == ENOENT) { // file doesn't exist
|
||||
|
|
|
|||
|
|
@ -433,11 +433,11 @@ qint64 QFSFileEnginePrivate::nativeWrite(const char *data, qint64 len)
|
|||
|
||||
// Writing on Windows fails with ERROR_NO_SYSTEM_RESOURCES when
|
||||
// the chunks are too large, so we limit the block size to 32MB.
|
||||
const DWORD blockSize = DWORD(qMin(bytesToWrite, qint64(32 * 1024 * 1024)));
|
||||
qint64 totalWritten = 0;
|
||||
do {
|
||||
const DWORD currentBlockSize = DWORD(qMin(bytesToWrite, qint64(32 * 1024 * 1024)));
|
||||
DWORD bytesWritten;
|
||||
if (!WriteFile(fileHandle, data + totalWritten, blockSize, &bytesWritten, NULL)) {
|
||||
if (!WriteFile(fileHandle, data + totalWritten, currentBlockSize, &bytesWritten, NULL)) {
|
||||
if (totalWritten == 0) {
|
||||
// Note: Only return error if the first WriteFile failed.
|
||||
q->setError(QFile::WriteError, qt_error_string());
|
||||
|
|
|
|||
|
|
@ -417,7 +417,9 @@ QString QSettingsPrivate::variantToString(const QVariant &v)
|
|||
case QVariant::Double:
|
||||
case QVariant::KeySequence: {
|
||||
result = v.toString();
|
||||
if (result.startsWith(QLatin1Char('@')))
|
||||
if (result.contains(QChar::Null))
|
||||
result = QLatin1String("@String(") + result + QLatin1Char(')');
|
||||
else if (result.startsWith(QLatin1Char('@')))
|
||||
result.prepend(QLatin1Char('@'));
|
||||
break;
|
||||
}
|
||||
|
|
@ -477,6 +479,8 @@ QVariant QSettingsPrivate::stringToVariant(const QString &s)
|
|||
if (s.endsWith(QLatin1Char(')'))) {
|
||||
if (s.startsWith(QLatin1String("@ByteArray("))) {
|
||||
return QVariant(s.midRef(11, s.size() - 12).toLatin1());
|
||||
} else if (s.startsWith(QLatin1String("@String("))) {
|
||||
return QVariant(s.midRef(8, s.size() - 9).toString());
|
||||
} else if (s.startsWith(QLatin1String("@Variant("))
|
||||
|| s.startsWith(QLatin1String("@DateTime("))) {
|
||||
#ifndef QT_NO_DATASTREAM
|
||||
|
|
|
|||
|
|
@ -214,7 +214,14 @@ static QCFType<CFPropertyListRef> macValue(const QVariant &value)
|
|||
case QVariant::String:
|
||||
string_case:
|
||||
default:
|
||||
result = QCFString::toCFStringRef(QSettingsPrivate::variantToString(value));
|
||||
QString string = QSettingsPrivate::variantToString(value);
|
||||
if (string.contains(QChar::Null)) {
|
||||
QByteArray ba = string.toUtf8();
|
||||
result = CFDataCreate(kCFAllocatorDefault, reinterpret_cast<const UInt8 *>(ba.data()),
|
||||
CFIndex(ba.size()));
|
||||
} else {
|
||||
result = QCFString::toCFStringRef(string);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
|
@ -267,8 +274,17 @@ static QVariant qtValue(CFPropertyListRef cfvalue)
|
|||
return (bool)CFBooleanGetValue(static_cast<CFBooleanRef>(cfvalue));
|
||||
} else if (typeId == CFDataGetTypeID()) {
|
||||
CFDataRef cfdata = static_cast<CFDataRef>(cfvalue);
|
||||
return QByteArray(reinterpret_cast<const char *>(CFDataGetBytePtr(cfdata)),
|
||||
QByteArray byteArray = QByteArray(reinterpret_cast<const char *>(CFDataGetBytePtr(cfdata)),
|
||||
CFDataGetLength(cfdata));
|
||||
|
||||
// Fast-path for QByteArray, so that we don't have to go
|
||||
// though the expensive and lossy conversion via UTF-8.
|
||||
if (!byteArray.startsWith('@'))
|
||||
return byteArray;
|
||||
|
||||
const QString str = QString::fromUtf8(byteArray.constData(), byteArray.size());
|
||||
return QSettingsPrivate::stringToVariant(str);
|
||||
|
||||
} else if (typeId == CFDictionaryGetTypeID()) {
|
||||
CFDictionaryRef cfdict = static_cast<CFDictionaryRef>(cfvalue);
|
||||
CFTypeID arrayTypeId = CFArrayGetTypeID();
|
||||
|
|
|
|||
|
|
@ -675,15 +675,6 @@ void QWinSettingsPrivate::remove(const QString &uKey)
|
|||
}
|
||||
}
|
||||
|
||||
static bool stringContainsNullChar(const QString &s)
|
||||
{
|
||||
for (int i = 0; i < s.length(); ++i) {
|
||||
if (s.at(i).unicode() == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
|
||||
{
|
||||
if (writeHandle() == 0) {
|
||||
|
|
@ -712,7 +703,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
|
|||
QStringList l = variantListToStringList(value.toList());
|
||||
QStringList::const_iterator it = l.constBegin();
|
||||
for (; it != l.constEnd(); ++it) {
|
||||
if ((*it).length() == 0 || stringContainsNullChar(*it)) {
|
||||
if ((*it).length() == 0 || it->contains(QChar::Null)) {
|
||||
type = REG_BINARY;
|
||||
break;
|
||||
}
|
||||
|
|
@ -756,7 +747,7 @@ void QWinSettingsPrivate::set(const QString &uKey, const QVariant &value)
|
|||
// If the string does not contain '\0', we can use REG_SZ, the native registry
|
||||
// string type. Otherwise we use REG_BINARY.
|
||||
QString s = variantToString(value);
|
||||
type = stringContainsNullChar(s) ? REG_BINARY : REG_SZ;
|
||||
type = s.contains(QChar::Null) ? REG_BINARY : REG_SZ;
|
||||
if (type == REG_BINARY) {
|
||||
regValueBuff = QByteArray((const char*)s.utf16(), s.length() * 2);
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ void QWinRTSettingsPrivate::set(const QString &uKey, const QVariant &value)
|
|||
QStringList::const_iterator it = l.constBegin();
|
||||
bool containsNull = false;
|
||||
for (; it != l.constEnd(); ++it) {
|
||||
if ((*it).length() == 0 || it->indexOf(QChar::Null) != -1) {
|
||||
if ((*it).length() == 0 || it->contains(QChar::Null)) {
|
||||
// We can only store as binary
|
||||
containsNull = true;
|
||||
break;
|
||||
|
|
@ -445,7 +445,7 @@ void QWinRTSettingsPrivate::set(const QString &uKey, const QVariant &value)
|
|||
break;
|
||||
default: {
|
||||
const QString s = variantToString(value);
|
||||
if (s.indexOf(QChar::Null) != -1) {
|
||||
if (s.contains(QChar::Null)) {
|
||||
hr = valueStatics->CreateUInt8Array(s.length() * 2, (BYTE*) s.utf16(), &val);
|
||||
} else {
|
||||
HStringReference ref((const wchar_t*)s.utf16(), s.size());
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@
|
|||
dealing with URLs and strings:
|
||||
|
||||
\list
|
||||
\li When creating an QString to contain a URL from a QByteArray or a
|
||||
\li When creating a QString to contain a URL from a QByteArray or a
|
||||
char*, always use QString::fromUtf8().
|
||||
\endlist
|
||||
*/
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -9,8 +9,8 @@ Those arrays in qurltlds_p.h are derived from the Public
|
|||
Suffix List ([2]), which was originally provided by
|
||||
Jo Hermans <jo.hermans@gmail.com>.
|
||||
|
||||
The file qurltlds_p.h was last generated Wednesday,
|
||||
February 11th 14:36 2015.
|
||||
The file qurltlds_p.h was last generated Thursday,
|
||||
October 20th 8:40 2016.
|
||||
|
||||
----
|
||||
[1] list: http://mxr.mozilla.org/mozilla-central/source/netwerk/dns/effective_tld_names.dat?raw=1
|
||||
|
|
|
|||
|
|
@ -260,8 +260,7 @@ QJsonDocument QJsonDocument::fromBinaryData(const QByteArray &data, DataValidati
|
|||
Creates a QJsonDocument from the QVariant \a variant.
|
||||
|
||||
If the \a variant contains any other type than a QVariantMap,
|
||||
QVariantList or QStringList, the returned document
|
||||
document is invalid.
|
||||
QVariantList or QStringList, the returned document is invalid.
|
||||
|
||||
\sa toVariant()
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -1004,7 +1004,7 @@ bool QCoreApplication::notifyInternal2(QObject *receiver, QEvent *event)
|
|||
approaches are listed below:
|
||||
\list 1
|
||||
\li Reimplementing \l {QWidget::}{paintEvent()}, \l {QWidget::}{mousePressEvent()} and so
|
||||
on. This is the commonest, easiest, and least powerful way.
|
||||
on. This is the most common, easiest, and least powerful way.
|
||||
|
||||
\li Reimplementing this function. This is very powerful, providing
|
||||
complete control; but only one subclass can be active at a time.
|
||||
|
|
|
|||
|
|
@ -88,8 +88,8 @@ public:
|
|||
void unlock()
|
||||
{
|
||||
if (locked) {
|
||||
if (mtx1) mtx1->unlock();
|
||||
if (mtx2) mtx2->unlock();
|
||||
if (mtx1) mtx1->unlock();
|
||||
locked = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ public:
|
|||
// mtx1 is already locked, mtx2 not... do we need to unlock and relock?
|
||||
if (mtx1 == mtx2)
|
||||
return false;
|
||||
if (mtx1 < mtx2) {
|
||||
if (std::less<QMutex *>()(mtx1, mtx2)) {
|
||||
mtx2->lock();
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -548,7 +548,7 @@ QT_BEGIN_NAMESPACE
|
|||
\inmodule QtCore
|
||||
\reentrant
|
||||
|
||||
\brief The QRegularExpressionMatch class provides the results of a matching
|
||||
\brief The QRegularExpressionMatch class provides the results of matching
|
||||
a QRegularExpression against a string.
|
||||
|
||||
\since 5.0
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ QDBusServer::~QDBusServer()
|
|||
QDBusConnectionManager::instance()->removeConnection(name);
|
||||
d->serverConnectionNames.clear();
|
||||
}
|
||||
d->serverObject = nullptr;
|
||||
d->serverObject = Q_NULLPTR;
|
||||
d->ref.store(0);
|
||||
d->deleteLater();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -911,12 +911,12 @@ static bool convert_indexed8_to_RGB16_inplace(QImageData *data, Qt::ImageConvers
|
|||
const int dest_pad = (dst_bytes_per_line >> 1) - width;
|
||||
|
||||
quint16 colorTableRGB16[256];
|
||||
if (data->colortable.isEmpty()) {
|
||||
const int tableSize = data->colortable.size();
|
||||
if (tableSize == 0) {
|
||||
for (int i = 0; i < 256; ++i)
|
||||
colorTableRGB16[i] = qConvertRgb32To16(qRgb(i, i, i));
|
||||
} else {
|
||||
// 1) convert the existing colors to RGB16
|
||||
const int tableSize = data->colortable.size();
|
||||
for (int i = 0; i < tableSize; ++i)
|
||||
colorTableRGB16[i] = qConvertRgb32To16(data->colortable.at(i));
|
||||
data->colortable = QVector<QRgb>();
|
||||
|
|
|
|||
|
|
@ -425,8 +425,9 @@ void QClipboard::setPixmap(const QPixmap &pixmap, Mode mode)
|
|||
/*!
|
||||
\fn QMimeData *QClipboard::mimeData(Mode mode) const
|
||||
|
||||
Returns a reference to a QMimeData representation of the current
|
||||
clipboard data.
|
||||
Returns a pointer to a QMimeData representation of the current
|
||||
clipboard data (can be NULL if the given \a mode is not
|
||||
supported by the platform).
|
||||
|
||||
The \a mode argument is used to control which part of the system
|
||||
clipboard is used. If \a mode is QClipboard::Clipboard, the
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include <QtCore/qatomic.h>
|
||||
#include <QtCore/QDebug>
|
||||
#include <QOpenGLContext>
|
||||
#include <QtGui/qguiapplication.h>
|
||||
|
||||
#ifdef major
|
||||
#undef major
|
||||
|
|
@ -763,10 +764,13 @@ Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format)
|
|||
void QSurfaceFormat::setDefaultFormat(const QSurfaceFormat &format)
|
||||
{
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLContext *globalContext = QOpenGLContext::globalShareContext();
|
||||
if (globalContext && globalContext->isValid()) {
|
||||
qWarning("Warning: Setting a new default format with a different version or profile after "
|
||||
"the global shared context is created may cause issues with context sharing.");
|
||||
if (qApp) {
|
||||
QOpenGLContext *globalContext = QOpenGLContext::globalShareContext();
|
||||
if (globalContext && globalContext->isValid()) {
|
||||
qWarning("Warning: Setting a new default format with a different version or profile "
|
||||
"after the global shared context is created may cause issues with context "
|
||||
"sharing.");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
*qt_default_surface_format() = format;
|
||||
|
|
|
|||
|
|
@ -1925,7 +1925,7 @@ int QPdfEnginePrivate::writeCompressed(const char *src, int len)
|
|||
}
|
||||
|
||||
int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height, int depth,
|
||||
int maskObject, int softMaskObject, bool dct)
|
||||
int maskObject, int softMaskObject, bool dct, bool isMono)
|
||||
{
|
||||
int image = addXrefEntry(-1);
|
||||
xprintf("<<\n"
|
||||
|
|
@ -1935,8 +1935,13 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
|
|||
"/Height %d\n", width, height);
|
||||
|
||||
if (depth == 1) {
|
||||
xprintf("/ImageMask true\n"
|
||||
"/Decode [1 0]\n");
|
||||
if (!isMono) {
|
||||
xprintf("/ImageMask true\n"
|
||||
"/Decode [1 0]\n");
|
||||
} else {
|
||||
xprintf("/BitsPerComponent 1\n"
|
||||
"/ColorSpace /DeviceGray\n");
|
||||
}
|
||||
} else {
|
||||
xprintf("/BitsPerComponent 8\n"
|
||||
"/ColorSpace %s\n", (depth == 32) ? "/DeviceRGB" : "/DeviceGray");
|
||||
|
|
@ -2454,7 +2459,7 @@ int QPdfEnginePrivate::addImage(const QImage &img, bool *bitmap, qint64 serial_n
|
|||
memcpy(rawdata, image.constScanLine(y), bytesPerLine);
|
||||
rawdata += bytesPerLine;
|
||||
}
|
||||
object = writeImage(data, w, h, d, 0, 0);
|
||||
object = writeImage(data, w, h, d, 0, 0, false, is_monochrome(img.colorTable()));
|
||||
} else {
|
||||
QByteArray softMaskData;
|
||||
bool dct = false;
|
||||
|
|
|
|||
|
|
@ -295,7 +295,7 @@ private:
|
|||
int streampos;
|
||||
|
||||
int writeImage(const QByteArray &data, int width, int height, int depth,
|
||||
int maskObject, int softMaskObject, bool dct = false);
|
||||
int maskObject, int softMaskObject, bool dct = false, bool isMono = false);
|
||||
void writePage();
|
||||
|
||||
int addXrefEntry(int object, bool printostr = true);
|
||||
|
|
|
|||
|
|
@ -746,8 +746,9 @@ static ColorData parseColorValue(QCss::Value v)
|
|||
QVector<QCss::Value> colorDigits;
|
||||
if (!p.parseExpr(&colorDigits))
|
||||
return ColorData();
|
||||
const int tokenCount = colorDigits.count();
|
||||
|
||||
for (int i = 0; i < qMin(colorDigits.count(), 7); i += 2) {
|
||||
for (int i = 0; i < qMin(tokenCount, 7); i += 2) {
|
||||
if (colorDigits.at(i).type == Value::Percentage) {
|
||||
colorDigits[i].variant = colorDigits.at(i).variant.toReal() * (255. / 100.);
|
||||
colorDigits[i].type = Value::Number;
|
||||
|
|
@ -756,11 +757,15 @@ static ColorData parseColorValue(QCss::Value v)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
if (tokenCount < 5)
|
||||
return ColorData();
|
||||
|
||||
int v1 = colorDigits.at(0).variant.toInt();
|
||||
int v2 = colorDigits.at(2).variant.toInt();
|
||||
int v3 = colorDigits.at(4).variant.toInt();
|
||||
int alpha = 255;
|
||||
if (colorDigits.count() >= 7) {
|
||||
if (tokenCount >= 7) {
|
||||
int alphaValue = colorDigits.at(6).variant.toInt();
|
||||
if (rgba && alphaValue <= 1)
|
||||
alpha = colorDigits.at(6).variant.toReal() * 255.;
|
||||
|
|
|
|||
|
|
@ -244,7 +244,8 @@ QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager* const manage
|
|||
|
||||
QNetworkReplyHttpImpl::~QNetworkReplyHttpImpl()
|
||||
{
|
||||
// Most work is done in private destructor
|
||||
// This will do nothing if the request was already finished or aborted
|
||||
emit abortHttpRequest();
|
||||
}
|
||||
|
||||
void QNetworkReplyHttpImpl::close()
|
||||
|
|
@ -442,9 +443,6 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
|
|||
|
||||
QNetworkReplyHttpImplPrivate::~QNetworkReplyHttpImplPrivate()
|
||||
{
|
||||
Q_Q(QNetworkReplyHttpImpl);
|
||||
// This will do nothing if the request was already finished or aborted
|
||||
emit q->abortHttpRequest();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -498,10 +498,12 @@ void QNativeSocketEngine::close()
|
|||
ComPtr<IAsyncAction> action;
|
||||
hr = socket3->CancelIOAsync(&action);
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
hr = QWinRTFunctions::await(action);
|
||||
hr = QWinRTFunctions::await(action, QWinRTFunctions::YieldThread, 5000);
|
||||
// If there is no pending IO (no read established before) the function will fail with
|
||||
// "function was called at an unexpected time" which is fine.
|
||||
if (hr != E_ILLEGAL_METHOD_CALL)
|
||||
// Timeout is fine as well. The result will be the socket being hard reset instead of
|
||||
// being closed gracefully
|
||||
if (hr != E_ILLEGAL_METHOD_CALL && hr != ERROR_TIMEOUT)
|
||||
Q_ASSERT_SUCCEEDED(hr);
|
||||
return S_OK;
|
||||
});
|
||||
|
|
|
|||
|
|
@ -461,9 +461,9 @@ QVariant QAndroidPlatformTheme::themeHint(ThemeHint hint) const
|
|||
case StyleNames:
|
||||
if (qEnvironmentVariableIntValue("QT_USE_ANDROID_NATIVE_STYLE")
|
||||
&& m_androidStyleData) {
|
||||
return QStringList("android");
|
||||
return QStringList(QLatin1String("android"));
|
||||
}
|
||||
return QStringList("fusion");
|
||||
return QStringList(QLatin1String("fusion"));
|
||||
|
||||
case MouseDoubleClickDistance:
|
||||
{
|
||||
|
|
|
|||
|
|
@ -352,6 +352,7 @@ public: // for QNSView
|
|||
// This object is tracked by QCocoaWindowPointer,
|
||||
// preventing the use of dangling pointers.
|
||||
QObject sentinel;
|
||||
bool m_hasWindowFilePath;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -384,6 +384,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw)
|
|||
, m_topContentBorderThickness(0)
|
||||
, m_bottomContentBorderThickness(0)
|
||||
, m_normalGeometry(QRect(0,0,-1,-1))
|
||||
, m_hasWindowFilePath(false)
|
||||
{
|
||||
qCDebug(lcQpaCocoaWindow) << "QCocoaWindow::QCocoaWindow" << window();
|
||||
|
||||
|
|
@ -950,6 +951,7 @@ void QCocoaWindow::setWindowFilePath(const QString &filePath)
|
|||
|
||||
QFileInfo fi(filePath);
|
||||
[m_nsWindow setRepresentedFilename: fi.exists() ? QCFString::toNSString(filePath) : @""];
|
||||
m_hasWindowFilePath = fi.exists();
|
||||
}
|
||||
|
||||
void QCocoaWindow::setWindowIcon(const QIcon &icon)
|
||||
|
|
|
|||
|
|
@ -57,7 +57,8 @@
|
|||
- (void)windowWillMove:(NSNotification *)notification;
|
||||
- (BOOL)windowShouldClose:(NSNotification *)notification;
|
||||
- (BOOL)windowShouldZoom:(NSWindow *)window toFrame:(NSRect)newFrame;
|
||||
|
||||
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu;
|
||||
- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard;
|
||||
@end
|
||||
|
||||
QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSWindowDelegate);
|
||||
|
|
|
|||
|
|
@ -115,4 +115,19 @@
|
|||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
Q_UNUSED(menu);
|
||||
return m_cocoaWindow && m_cocoaWindow->m_hasWindowFilePath;
|
||||
}
|
||||
|
||||
- (BOOL)window:(NSWindow *)window shouldDragDocumentWithEvent:(NSEvent *)event from:(NSPoint)dragImageLocation withPasteboard:(NSPasteboard *)pasteboard
|
||||
{
|
||||
Q_UNUSED(window);
|
||||
Q_UNUSED(event);
|
||||
Q_UNUSED(dragImageLocation);
|
||||
Q_UNUSED(pasteboard);
|
||||
return m_cocoaWindow && m_cocoaWindow->m_hasWindowFilePath;
|
||||
}
|
||||
@end
|
||||
|
|
|
|||
|
|
@ -66,7 +66,8 @@ private:
|
|||
|
||||
Q_GLOBAL_STATIC(DeviceIntegration, deviceIntegration)
|
||||
|
||||
DeviceIntegration::DeviceIntegration() : m_integration(0)
|
||||
DeviceIntegration::DeviceIntegration()
|
||||
: m_integration(nullptr)
|
||||
{
|
||||
QStringList pluginKeys = QEGLDeviceIntegrationFactory::keys();
|
||||
if (!pluginKeys.isEmpty()) {
|
||||
|
|
|
|||
|
|
@ -116,6 +116,7 @@ Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
|
|||
#define XCB_GE_GENERIC 35
|
||||
#endif
|
||||
|
||||
#if defined(XCB_USE_XINPUT2)
|
||||
// Starting from the xcb version 1.9.3 struct xcb_ge_event_t has changed:
|
||||
// - "pad0" became "extension"
|
||||
// - "pad1" and "pad" became "pad0"
|
||||
|
|
@ -133,6 +134,7 @@ static inline bool isXIEvent(xcb_generic_event_t *event, int opCode)
|
|||
qt_xcb_ge_event_t *e = (qt_xcb_ge_event_t *)event;
|
||||
return e->extension == opCode;
|
||||
}
|
||||
#endif // XCB_USE_XINPUT2
|
||||
|
||||
#ifdef XCB_USE_XLIB
|
||||
static const char * const xcbConnectionErrors[] = {
|
||||
|
|
|
|||
|
|
@ -1685,9 +1685,11 @@ void QXcbWindow::requestActivateWindow()
|
|||
m_deferredActivation = false;
|
||||
|
||||
updateNetWmUserTime(connection()->time());
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
|
||||
if (window()->isTopLevel()
|
||||
&& !(window()->flags() & Qt::X11BypassWindowManagerHint)
|
||||
&& (!focusWindow || !window()->isAncestorOf(focusWindow))
|
||||
&& connection()->wmSupport()->isSupportedByWM(atom(QXcbAtom::_NET_ACTIVE_WINDOW))) {
|
||||
xcb_client_message_event_t event;
|
||||
|
||||
|
|
@ -1698,7 +1700,6 @@ void QXcbWindow::requestActivateWindow()
|
|||
event.type = atom(QXcbAtom::_NET_ACTIVE_WINDOW);
|
||||
event.data.data32[0] = 1;
|
||||
event.data.data32[1] = connection()->time();
|
||||
QWindow *focusWindow = QGuiApplication::focusWindow();
|
||||
event.data.data32[2] = focusWindow ? focusWindow->winId() : XCB_NONE;
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
|
|
|||
|
|
@ -5237,6 +5237,8 @@ static QPixmap cachedPixmapFromXPM(const char * const *xpm)
|
|||
return result;
|
||||
}
|
||||
|
||||
static inline QPixmap titleBarMenuCachedPixmapFromXPM() { return cachedPixmapFromXPM(qt_menu_xpm); }
|
||||
|
||||
#ifndef QT_NO_IMAGEFORMAT_PNG
|
||||
static inline QString clearText16IconPath()
|
||||
{
|
||||
|
|
@ -5581,7 +5583,7 @@ QPixmap QCommonStyle::standardPixmap(StandardPixmap sp, const QStyleOption *opti
|
|||
#ifndef QT_NO_IMAGEFORMAT_XPM
|
||||
switch (sp) {
|
||||
case SP_TitleBarMenuButton:
|
||||
return cachedPixmapFromXPM(qt_menu_xpm);
|
||||
return titleBarMenuCachedPixmapFromXPM();
|
||||
case SP_TitleBarShadeButton:
|
||||
return cachedPixmapFromXPM(qt_shade_xpm);
|
||||
case SP_TitleBarUnshadeButton:
|
||||
|
|
@ -6121,6 +6123,12 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption
|
|||
case SP_MediaVolumeMuted:
|
||||
icon.addFile(QLatin1String(":/qt-project.org/styles/commonstyle/images/media-volume-muted-16.png"), QSize(16, 16));
|
||||
break;
|
||||
case SP_TitleBarMenuButton:
|
||||
# ifndef QT_NO_IMAGEFORMAT_XPM
|
||||
icon.addPixmap(titleBarMenuCachedPixmapFromXPM());
|
||||
# endif
|
||||
icon.addFile(QLatin1String(":/qt-project.org/qmessagebox/images/qtlogo-64.png"));
|
||||
break;
|
||||
#endif // QT_NO_IMAGEFORMAT_PNG
|
||||
default:
|
||||
icon.addPixmap(proxy()->standardPixmap(standardIcon, option, widget));
|
||||
|
|
|
|||
|
|
@ -4263,10 +4263,6 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
|
|||
bool verticalTabs = ttd == kThemeTabWest || ttd == kThemeTabEast;
|
||||
bool selected = (myTab.state & QStyle::State_Selected);
|
||||
|
||||
if (selected && !myTab.documentMode
|
||||
&& (!usingYosemiteOrLater || myTab.state & State_Active))
|
||||
myTab.palette.setColor(QPalette::WindowText, Qt::white);
|
||||
|
||||
// Check to see if we use have the same as the system font
|
||||
// (QComboMenuItem is internal and should never be seen by the
|
||||
// outside world, unless they read the source, in which case, it's
|
||||
|
|
|
|||
|
|
@ -176,7 +176,12 @@ void QTabBarPrivate::initBasicStyleOption(QStyleOptionTab *option, int tabIndex)
|
|||
|
||||
if (tab.textColor.isValid())
|
||||
option->palette.setColor(q->foregroundRole(), tab.textColor);
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
else if (isCurrent && !documentMode
|
||||
&& (QSysInfo::MacintoshVersion < QSysInfo::MV_10_10 || q->isActiveWindow())) {
|
||||
option->palette.setColor(QPalette::WindowText, Qt::white);
|
||||
}
|
||||
#endif
|
||||
option->icon = tab.icon;
|
||||
option->iconSize = q->iconSize(); // Will get the default value then.
|
||||
|
||||
|
|
|
|||
|
|
@ -765,6 +765,19 @@ void tst_QFileInfo::canonicalFilePath()
|
|||
QDir::current().rmdir(linkTarget);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_DARWIN
|
||||
{
|
||||
// Check if canonicalFilePath's result is in Composed normalization form.
|
||||
QString path = QString::fromLatin1("caf\xe9");
|
||||
QDir dir(QDir::tempPath());
|
||||
dir.mkdir(path);
|
||||
QString canonical = QFileInfo(dir.filePath(path)).canonicalFilePath();
|
||||
QString roundtrip = QFile::decodeName(QFile::encodeName(canonical));
|
||||
QCOMPARE(canonical, roundtrip);
|
||||
dir.rmdir(path);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void tst_QFileInfo::fileName_data()
|
||||
|
|
|
|||
|
|
@ -158,6 +158,8 @@ private slots:
|
|||
void testByteArray();
|
||||
void iniCodec();
|
||||
void bom();
|
||||
void embeddedZeroByte_data();
|
||||
void embeddedZeroByte();
|
||||
|
||||
private:
|
||||
void cleanupTestFiles();
|
||||
|
|
@ -627,7 +629,6 @@ void tst_QSettings::testByteArray_data()
|
|||
#ifndef QT_NO_COMPRESS
|
||||
QTest::newRow("compressed") << qCompress(bytes);
|
||||
#endif
|
||||
QTest::newRow("with \\0") << bytes + '\0' + bytes;
|
||||
}
|
||||
|
||||
void tst_QSettings::testByteArray()
|
||||
|
|
@ -678,6 +679,53 @@ void tst_QSettings::bom()
|
|||
QVERIFY(allkeys.contains("section2/foo2"));
|
||||
}
|
||||
|
||||
void tst_QSettings::embeddedZeroByte_data()
|
||||
{
|
||||
QTest::addColumn<QVariant>("value");
|
||||
|
||||
QByteArray bytes("hello\0world", 11);
|
||||
|
||||
QTest::newRow("bytearray\\0") << QVariant(bytes);
|
||||
QTest::newRow("string\\0") << QVariant(QString::fromLatin1(bytes.data(), bytes.size()));
|
||||
|
||||
bytes = QByteArray("@String(");
|
||||
|
||||
QTest::newRow("@bytearray") << QVariant(bytes);
|
||||
QTest::newRow("@string") << QVariant(QString(bytes));
|
||||
|
||||
bytes = QByteArray("@String(\0test", 13);
|
||||
|
||||
QTest::newRow("@bytearray\\0") << QVariant(bytes);
|
||||
QTest::newRow("@string\\0") << QVariant(QString::fromLatin1(bytes.data(), bytes.size()));
|
||||
}
|
||||
|
||||
void tst_QSettings::embeddedZeroByte()
|
||||
{
|
||||
QFETCH(QVariant, value);
|
||||
{
|
||||
QSettings settings("QtProject", "tst_qsettings");
|
||||
settings.setValue(QTest::currentDataTag(), value);
|
||||
}
|
||||
{
|
||||
QSettings settings("QtProject", "tst_qsettings");
|
||||
QVariant outValue = settings.value(QTest::currentDataTag());
|
||||
|
||||
switch (value.type()) {
|
||||
case QVariant::ByteArray:
|
||||
QCOMPARE(outValue.toByteArray(), value.toByteArray());
|
||||
break;
|
||||
case QVariant::String:
|
||||
QCOMPARE(outValue.toString(), value.toString());
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
}
|
||||
|
||||
if (value.toByteArray().contains(QChar::Null))
|
||||
QVERIFY(outValue.toByteArray().contains(QChar::Null));
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QSettings::testErrorHandling_data()
|
||||
{
|
||||
QTest::addColumn<int>("filePerms"); // -1 means file should not exist
|
||||
|
|
|
|||
|
|
@ -782,6 +782,24 @@ void tst_QWindow::isActive()
|
|||
// child has focus
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
// test focus back to parent and then back to child (QTBUG-39362)
|
||||
// also verify the cumulative FocusOut and FocusIn counts
|
||||
// activate parent
|
||||
window.requestActivate();
|
||||
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
|
||||
QVERIFY(window.isActive());
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(child.received(QEvent::FocusOut), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 2);
|
||||
|
||||
// activate child again
|
||||
child.requestActivate();
|
||||
QTRY_COMPARE(QGuiApplication::focusWindow(), &child);
|
||||
QVERIFY(child.isActive());
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(window.received(QEvent::FocusOut), 2);
|
||||
QTRY_COMPARE(child.received(QEvent::FocusIn), 2);
|
||||
|
||||
Window dialog;
|
||||
dialog.setTransientParent(&window);
|
||||
dialog.setGeometry(QRect(m_availableTopLeft + QPoint(110, 100), m_testWindowSize));
|
||||
|
|
@ -806,7 +824,7 @@ void tst_QWindow::isActive()
|
|||
QTRY_COMPARE(QGuiApplication::focusWindow(), &window);
|
||||
QCoreApplication::processEvents();
|
||||
QTRY_COMPARE(dialog.received(QEvent::FocusOut), 1);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 2);
|
||||
QTRY_COMPARE(window.received(QEvent::FocusIn), 3);
|
||||
|
||||
QVERIFY(window.isActive());
|
||||
|
||||
|
|
|
|||
|
|
@ -842,6 +842,7 @@ void tst_QCssParser::colorValue_data()
|
|||
QTest::newRow("hsla") << "color: hsva(10, 20, 30, 40)" << QColor::fromHsv(10, 20, 30, 40);
|
||||
QTest::newRow("invalid1") << "color: rgb(why, does, it, always, rain, on, me)" << QColor();
|
||||
QTest::newRow("invalid2") << "color: rgba(i, meant, norway)" << QColor();
|
||||
QTest::newRow("invalid3") << "color: rgb(21)" << QColor();
|
||||
QTest::newRow("role") << "color: palette(base)" << qApp->palette().color(QPalette::Base);
|
||||
QTest::newRow("role2") << "color: palette( window-text ) " << qApp->palette().color(QPalette::WindowText);
|
||||
QTest::newRow("transparent") << "color: transparent" << QColor(Qt::transparent);
|
||||
|
|
|
|||
|
|
@ -188,16 +188,16 @@ void tst_QNetworkCookieJar::setCookiesFromUrl_data()
|
|||
result += cookie;
|
||||
QTest::newRow("effective-tld1-accepted") << preset << cookie << "http://something.co.uk" << result << true;
|
||||
|
||||
// 2. anything .mz is an effective TLD ('*.mz'), but 'teledata.mz' is an exception
|
||||
// 2. anything .ck is an effective TLD ('*.ck'), but 'www.ck' is an exception
|
||||
result.clear();
|
||||
preset.clear();
|
||||
cookie.setDomain(".farmacia.mz");
|
||||
QTest::newRow("effective-tld2-denied") << preset << cookie << "http://farmacia.mz" << result << false;
|
||||
QTest::newRow("effective-tld2-denied2") << preset << cookie << "http://www.farmacia.mz" << result << false;
|
||||
QTest::newRow("effective-tld2-denied3") << preset << cookie << "http://www.anything.farmacia.mz" << result << false;
|
||||
cookie.setDomain(".teledata.mz");
|
||||
cookie.setDomain(".foo.ck");
|
||||
QTest::newRow("effective-tld2-denied") << preset << cookie << "http://foo.ck" << result << false;
|
||||
QTest::newRow("effective-tld2-denied2") << preset << cookie << "http://www.foo.ck" << result << false;
|
||||
QTest::newRow("effective-tld2-denied3") << preset << cookie << "http://www.anything.foo.ck" << result << false;
|
||||
cookie.setDomain(".www.ck");
|
||||
result += cookie;
|
||||
QTest::newRow("effective-tld2-accepted") << preset << cookie << "http://www.teledata.mz" << result << true;
|
||||
QTest::newRow("effective-tld2-accepted") << preset << cookie << "http://www.www.ck" << result << true;
|
||||
|
||||
result.clear();
|
||||
preset.clear();
|
||||
|
|
|
|||
|
|
@ -324,7 +324,7 @@ void tst_QAction::enabledVisibleInteraction()
|
|||
|
||||
void tst_QAction::task200823_tooltip()
|
||||
{
|
||||
QAction *action = new QAction("foo", 0);
|
||||
const QScopedPointer<QAction> action(new QAction("foo", Q_NULLPTR));
|
||||
QString shortcut("ctrl+o");
|
||||
action->setShortcut(shortcut);
|
||||
|
||||
|
|
@ -338,8 +338,8 @@ void tst_QAction::task200823_tooltip()
|
|||
void tst_QAction::task229128TriggeredSignalWithoutActiongroup()
|
||||
{
|
||||
// test without a group
|
||||
QAction *actionWithoutGroup = new QAction("Test", qApp);
|
||||
QSignalSpy spyWithoutGroup(actionWithoutGroup, SIGNAL(triggered(bool)));
|
||||
const QScopedPointer<QAction> actionWithoutGroup(new QAction("Test", Q_NULLPTR));
|
||||
QSignalSpy spyWithoutGroup(actionWithoutGroup.data(), SIGNAL(triggered(bool)));
|
||||
QCOMPARE(spyWithoutGroup.count(), 0);
|
||||
actionWithoutGroup->trigger();
|
||||
// signal should be emitted
|
||||
|
|
|
|||
|
|
@ -2197,8 +2197,8 @@ void tst_QApplication::noQuitOnHide()
|
|||
{
|
||||
int argc = 0;
|
||||
QApplication app(argc, 0);
|
||||
QWidget *window1 = new NoQuitOnHideWidget;
|
||||
window1->show();
|
||||
NoQuitOnHideWidget window1;
|
||||
window1.show();
|
||||
QCOMPARE(app.exec(), 1);
|
||||
}
|
||||
|
||||
|
|
@ -2232,12 +2232,12 @@ void tst_QApplication::abortQuitOnShow()
|
|||
{
|
||||
int argc = 0;
|
||||
QApplication app(argc, 0);
|
||||
QWidget *window1 = new ShowCloseShowWidget(false);
|
||||
window1->show();
|
||||
ShowCloseShowWidget window1(false);
|
||||
window1.show();
|
||||
QCOMPARE(app.exec(), 0);
|
||||
|
||||
QWidget *window2 = new ShowCloseShowWidget(true);
|
||||
window2->show();
|
||||
ShowCloseShowWidget window2(true);
|
||||
window2.show();
|
||||
QCOMPARE(app.exec(), 1);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -390,7 +390,8 @@ void tst_QFormLayout::setFormStyle()
|
|||
QCOMPARE(layout.rowWrapPolicy(), QFormLayout::DontWrapRows);
|
||||
#endif
|
||||
|
||||
widget.setStyle(QStyleFactory::create("windows"));
|
||||
const QScopedPointer<QStyle> windowsStyle(QStyleFactory::create("windows"));
|
||||
widget.setStyle(windowsStyle.data());
|
||||
|
||||
QCOMPARE(layout.labelAlignment(), Qt::AlignLeft);
|
||||
QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
|
||||
|
|
@ -401,14 +402,16 @@ void tst_QFormLayout::setFormStyle()
|
|||
this test is cross platform.. so create dummy styles that
|
||||
return all the right stylehints.
|
||||
*/
|
||||
widget.setStyle(new DummyMacStyle());
|
||||
DummyMacStyle macStyle;
|
||||
widget.setStyle(&macStyle);
|
||||
|
||||
QCOMPARE(layout.labelAlignment(), Qt::AlignRight);
|
||||
QVERIFY(layout.formAlignment() == (Qt::AlignHCenter | Qt::AlignTop));
|
||||
QCOMPARE(layout.fieldGrowthPolicy(), QFormLayout::FieldsStayAtSizeHint);
|
||||
QCOMPARE(layout.rowWrapPolicy(), QFormLayout::DontWrapRows);
|
||||
|
||||
widget.setStyle(new DummyQtopiaStyle());
|
||||
DummyQtopiaStyle qtopiaStyle;
|
||||
widget.setStyle(&qtopiaStyle);
|
||||
|
||||
QCOMPARE(layout.labelAlignment(), Qt::AlignRight);
|
||||
QVERIFY(layout.formAlignment() == (Qt::AlignLeft | Qt::AlignTop));
|
||||
|
|
@ -886,7 +889,7 @@ void tst_QFormLayout::takeAt()
|
|||
QCOMPARE(layout->count(), 7);
|
||||
|
||||
for (int i = 6; i >= 0; --i) {
|
||||
layout->takeAt(0);
|
||||
delete layout->takeAt(0);
|
||||
QCOMPARE(layout->count(), i);
|
||||
}
|
||||
}
|
||||
|
|
@ -978,7 +981,7 @@ void tst_QFormLayout::replaceWidget()
|
|||
QFormLayout::ItemRole role;
|
||||
|
||||
// replace editor
|
||||
layout->replaceWidget(edit1, edit3);
|
||||
delete layout->replaceWidget(edit1, edit3);
|
||||
edit1->hide(); // Not strictly needed for the test, but for normal usage it is.
|
||||
QCOMPARE(layout->indexOf(edit1), -1);
|
||||
QCOMPARE(layout->indexOf(edit3), editIndex);
|
||||
|
|
@ -989,7 +992,7 @@ void tst_QFormLayout::replaceWidget()
|
|||
QCOMPARE(rownum, 0);
|
||||
QCOMPARE(role, QFormLayout::FieldRole);
|
||||
|
||||
layout->replaceWidget(label1, label2);
|
||||
delete layout->replaceWidget(label1, label2);
|
||||
label1->hide();
|
||||
QCOMPARE(layout->indexOf(label1), -1);
|
||||
QCOMPARE(layout->indexOf(label2), labelIndex);
|
||||
|
|
|
|||
Loading…
Reference in New Issue