Merge remote-tracking branch 'origin/4.12'

Conflicts:
	src/plugins/cmakeprojectmanager/fileapiparser.cpp

Change-Id: I39f8c2be859be043f506bef77de9bb5b42d38165
This commit is contained in:
Eike Ziller
2020-06-15 11:30:34 +02:00
13 changed files with 499 additions and 105 deletions

View File

@@ -53,16 +53,20 @@
To remove invalid Qt versions, select \uicontrol {Clean Up}. To remove invalid Qt versions, select \uicontrol {Clean Up}.
You can link to a Qt that you installed using the Qt Maintenance Tool to You can link to a Qt that you installed using the Qt Maintenance Tool to
automatically register the installed Qt versions. The mechanism does not automatically register the installed Qt versions. However, you cannot link
handle Qt versions installed by the system using some other package manager, to Qt versions that were installed by the system using some other package
such as your Linux distribution, brew on \macos, or Chocolatey on Windows, manager, such as your Linux distribution, brew on \macos, or Chocolatey on
nor a self-built Qt. Windows, nor a self-built Qt. In those cases, select \uicontrol {Add} in
the \uicontrol {Qt Versions} tab to add the Qt version manually, as
instructed in \l{Setting Up New Qt Versions}.
To link to a Qt installation: To link to a Qt installation:
\list 1 \list 1
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol Kits > \li Select \uicontrol Tools > \uicontrol Options >
\uicontrol {Qt Versions} > \uicontrol {Link with Qt}. (or \uicontrol {Qt Creator} > \uicontrol Preferences on
\macos) > \uicontrol Kits > \uicontrol {Qt Versions} >
\uicontrol {Link with Qt}.
\image qtcreator-link-with-qt.png "Choose Qt Installation dialog" \image qtcreator-link-with-qt.png "Choose Qt Installation dialog"
\li In the \uicontrol {Qt installation path} field, enter the path to \li In the \uicontrol {Qt installation path} field, enter the path to
the directory where you installed Qt. the directory where you installed Qt.
@@ -72,14 +76,16 @@
\endlist \endlist
To remove the automatically detected Qt versions from the list, select To remove the automatically detected Qt versions from the list, select
\uicontrol {Link with Qt} > \uicontrol {Remove Link}. \uicontrol {Remove Link}.
If a Qt version is still not listed under \uicontrol Auto-detected, select If a Qt version is still not listed in the \uicontrol {Qt Versions} tab
\uicontrol {Add} to add it manually. under \uicontrol Auto-detected, you have to set it up manually, as described
in the following section.
You specify the Qt version to use for each \l{glossary-buildandrun-kit} You specify the Qt version to use for each \l{glossary-buildandrun-kit}
{kit} for building and running your projects {kit} for building and running your projects
in \uicontrol Tools > \uicontrol Options > \uicontrol Kits. in \uicontrol Tools > \uicontrol Options > \uicontrol Kits, as described
in \l{Specifying Kit Settings}.
\section1 Setting Up New Qt Versions \section1 Setting Up New Qt Versions

View File

@@ -559,30 +559,32 @@ class DumperBase():
return 0, size return 0, size
return size, limit return size, limit
def vectorDataHelper(self, addr): def vectorDataHelper(self, vector_data_ptr):
# vector_data_ptr is what is e.g. stored in a QVector's d_ptr.
if self.qtVersion() >= 0x050000: if self.qtVersion() >= 0x050000:
if self.ptrSize() == 4: if self.ptrSize() == 4:
(ref, size, alloc, offset) = self.split('IIIp', addr) (ref, size, alloc, offset) = self.split('IIIp', vector_data_ptr)
else: else:
(ref, size, alloc, pad, offset) = self.split('IIIIp', addr) (ref, size, alloc, pad, offset) = self.split('IIIIp', vector_data_ptr)
alloc = alloc & 0x7ffffff alloc = alloc & 0x7ffffff
data = addr + offset data = vector_data_ptr + offset
else: else:
(ref, alloc, size) = self.split('III', addr) (ref, alloc, size) = self.split('III', vector_data_ptr)
data = addr + 16 data = vector_data_ptr + 16
self.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000) self.check(0 <= size and size <= alloc and alloc <= 1000 * 1000 * 1000)
return data, size, alloc return data, size, alloc
def byteArrayDataHelper(self, addr): def byteArrayDataHelper(self, bytearray_data_ptr):
# bytearray_data_ptr is what is e.g. stored in a QByteArray's d_ptr.
if self.qtVersion() >= 0x050000: if self.qtVersion() >= 0x050000:
# QTypedArray: # QTypedArray:
# - QtPrivate::RefCount ref # - QtPrivate::RefCount ref
# - int size # - int size
# - uint alloc : 31, capacityReserved : 1 # - uint alloc : 31, capacityReserved : 1
# - qptrdiff offset # - qptrdiff offset
(ref, size, alloc, offset) = self.split('IIpp', addr) (ref, size, alloc, offset) = self.split('IIpp', bytearray_data_ptr)
alloc = alloc & 0x7ffffff alloc = alloc & 0x7ffffff
data = addr + offset data = bytearray_data_ptr + offset
if self.ptrSize() == 4: if self.ptrSize() == 4:
data = data & 0xffffffff data = data & 0xffffffff
else: else:
@@ -594,19 +596,19 @@ class DumperBase():
# - [padding] # - [padding]
# - char *data; # - char *data;
if self.ptrSize() == 4: if self.ptrSize() == 4:
(ref, alloc, size, data) = self.split('IIIp', addr) (ref, alloc, size, data) = self.split('IIIp', bytearray_data_ptr)
else: else:
(ref, alloc, size, pad, data) = self.split('IIIIp', addr) (ref, alloc, size, pad, data) = self.split('IIIIp', bytearray_data_ptr)
else: else:
# Data: # Data:
# - QShared count; # - QShared count;
# - QChar *unicode # - QChar *unicode
# - char *ascii # - char *ascii
# - uint len: 30 # - uint len: 30
(dummy, dummy, dummy, size) = self.split('IIIp', addr) (dummy, dummy, dummy, size) = self.split('IIIp', bytearray_data_ptr)
size = self.extractInt(addr + 3 * self.ptrSize()) & 0x3ffffff size = self.extractInt(bytearray_data_ptr + 3 * self.ptrSize()) & 0x3ffffff
alloc = size # pretend. alloc = size # pretend.
data = self.extractPointer(addr + self.ptrSize()) data = self.extractPointer(bytearray_data_ptr + self.ptrSize())
return data, size, alloc return data, size, alloc
# addr is the begin of a QByteArrayData structure # addr is the begin of a QByteArrayData structure
@@ -3852,6 +3854,17 @@ class DumperBase():
return val return val
raise RuntimeError('EXPECTING ADDRESS OR BYTES, GOT %s' % type(datish)) raise RuntimeError('EXPECTING ADDRESS OR BYTES, GOT %s' % type(datish))
def createProxyValue(self, proxy_data, type_name):
tdata = self.TypeData(self)
tdata.name = type_name
tdata.typeId = type_name
tdata.code = TypeCode.Struct
self.registerType(type_name, tdata)
val = self.Value(self)
val.type = self.Type(self, type_name)
val.ldata = proxy_data
return val
def createContainerItem(self, data, innerTypish, container): def createContainerItem(self, data, innerTypish, container):
innerType = self.createType(innerTypish) innerType = self.createType(innerTypish)
name = self.qtNamespace() + '%s<%s>' % (container, innerType.name) name = self.qtNamespace() + '%s<%s>' % (container, innerType.name)

View File

@@ -24,9 +24,10 @@
############################################################################ ############################################################################
import platform import platform
import struct
import re import re
from dumper import Children, SubItem, UnnamedSubItem, toInteger from dumper import Children, SubItem, UnnamedSubItem, toInteger, DumperBase
from utils import DisplayFormat from utils import DisplayFormat, TypeCode
def qdump__QAtomicInt(d, value): def qdump__QAtomicInt(d, value):
@@ -2922,6 +2923,12 @@ def qdumpHelper_QJsonObject(d, data, obj):
def qdump__QJsonValue(d, value): def qdump__QJsonValue(d, value):
(data, dd, t) = value.split('QpI') (data, dd, t) = value.split('QpI')
if d.qtVersion() >= 0x050f00:
value = d.createProxyValue((data, dd, t, False), 'QCborValue_proxy')
d.putItem(value)
return
if t == 0: if t == 0:
d.putType('QJsonValue (Null)') d.putType('QJsonValue (Null)')
d.putValue('Null') d.putValue('Null')
@@ -2953,10 +2960,20 @@ def qdump__QJsonValue(d, value):
def qdump__QJsonArray(d, value): def qdump__QJsonArray(d, value):
if d.qtVersion() >= 0x050f00:
_, container_ptr = value.split('pp')
qdumpHelper_QCbor_array(d, container_ptr, False)
return
qdumpHelper_QJsonArray(d, value['d'].pointer(), value['a'].pointer()) qdumpHelper_QJsonArray(d, value['d'].pointer(), value['a'].pointer())
def qdump__QJsonObject(d, value): def qdump__QJsonObject(d, value):
if d.qtVersion() >= 0x050f00:
_, container_ptr = value.split('pp')
qdumpHelper_QCbor_map(d, container_ptr, False)
return
qdumpHelper_QJsonObject(d, value['d'].pointer(), value['o'].pointer()) qdumpHelper_QJsonObject(d, value['d'].pointer(), value['o'].pointer())
@@ -3022,3 +3039,187 @@ def qdump__qfloat16(d, value):
res = (-1)**sign * (1 + 1. * fraction / 2**10) * 2**(exp - 15) res = (-1)**sign * (1 + 1. * fraction / 2**10) * 2**(exp - 15)
d.putValue(res) d.putValue(res)
d.putPlainChildren(value) d.putPlainChildren(value)
def qdumpHelper_QCbor_string(d, container_ptr, element_index, is_bytes):
# d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB, so be explicit:
offset = 2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8
data_d_ptr, elements_d_ptr = d.split('pp', container_ptr + offset)
elements_data_ptr, elements_size, _ = d.vectorDataHelper(elements_d_ptr)
element_at_n_addr = elements_data_ptr + element_index * 16 # sizeof(QtCbor::Element) == 15
element_value, _, element_flags = d.split('qII', element_at_n_addr)
enc = 'latin1' if is_bytes or (element_flags & 8) else 'utf16'
bytedata, _, _ = d.byteArrayDataHelper(data_d_ptr)
bytedata += element_value
if d.qtVersion() >= 0x060000:
bytedata_len = d.extractInt64(bytedata)
bytedata_data = bytedata + 8
else:
bytedata_len = d.extractInt(bytedata)
bytedata_data = bytedata + 4 # sizeof(QtCbor::ByteData) header part
elided, shown = d.computeLimit(bytedata_len, d.displayStringLimit)
res = d.readMemory(bytedata_data, shown)
d.putValue(res, enc, elided=elided)
def qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, idx, bytedata, is_cbor):
element_at_n_addr = elements_data_ptr + idx * 16 # sizeof(QtCbor::Element) == 15
element_value, element_type, element_flags = d.split('qII', element_at_n_addr)
element_container, _, _ = d.split('pII', element_at_n_addr)
if element_flags & 1: # QtCbor::Element::IsContainer
return d.createProxyValue((-1, element_container, element_type, is_cbor), 'QCborValue_proxy')
if element_flags & 2: # QtCbor::Element::HasByteData
return d.createProxyValue((idx, container_ptr, element_type, is_cbor), 'QCborValue_proxy')
return d.createProxyValue((element_value, 0, element_type, is_cbor), 'QCborValue_proxy')
def qdumpHelper_QCbor_array(d, container_ptr, is_cbor):
if not container_ptr:
d.putItemCount(0)
return
# d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB, so be explicit:
offset = 2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8
data_d_ptr, elements_d_ptr = d.split('pp', container_ptr + offset)
elements_data_ptr, elements_size, _ = d.vectorDataHelper(elements_d_ptr)
d.putItemCount(elements_size)
if d.isExpanded():
bytedata, _, _ = d.byteArrayDataHelper(data_d_ptr)
with Children(d, maxNumChild=1000):
for i in range(elements_size):
d.putSubItem(i, qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, i, bytedata, is_cbor))
def qdump__QCborArray(d, value):
container_ptr = value.extractPointer()
qdumpHelper_QCbor_array(d, container_ptr, True)
def qdumpHelper_QCbor_map(d, container_ptr, is_cbor):
if not container_ptr:
d.putItemCount(0)
return
# d.split('i@{QByteArray::size_type}pp', container_ptr) doesn't work with CDB, so be explicit:
offset = 2 * d.ptrSize() if d.qtVersion() >= 0x060000 else 8
data_d_ptr, elements_d_ptr = d.split('pp', container_ptr + offset)
elements_data_ptr, elements_size, _ = d.vectorDataHelper(elements_d_ptr)
elements_size = int(elements_size / 2)
d.putItemCount(elements_size)
if d.isExpanded():
bytedata, _, _ = d.byteArrayDataHelper(data_d_ptr)
with Children(d, maxNumChild=1000):
for i in range(elements_size):
key = qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, 2 * i, bytedata, is_cbor)
val = qdumpHelper_QCborArray_valueAt(d, container_ptr, elements_data_ptr, 2 * i + 1, bytedata, is_cbor)
d.putPairItem(i, (key, val), 'key', 'value')
def qdump__QCborMap(d, value):
container_ptr = value.extractPointer()
qdumpHelper_QCbor_map(d, container_ptr, True)
def qdump__QCborValue(d, value):
item_data, container_ptr, item_type = value.split('qpi')
d.putItem(d.createProxyValue((item_data, container_ptr, item_type, True), 'QCborValue_proxy'))
def qdump__QCborValue_proxy(d, value):
item_data, container_ptr, item_type, is_cbor = value.data()
def typename(key, is_cbor):
if is_cbor:
return {
'invalid' : 'QCborValue (Invalid)',
'int' : 'QCborValue (Integer)',
'false' : 'QCborValue (False)',
'true' : 'QCborValue (True)',
'null' : 'QCborValue (Null)',
'undefined' : 'QCborValue (Undefined)',
'double' : 'QCborValue (Double)',
'bytes' : 'QCborValue (ByteArray)',
'string' : 'QCborValue (String)',
'map' : 'QCborValue (Map)',
'array' : 'QCborValue (Array)'
}.get(key, 'QCborValue (Unknown)')
else:
return {
'invalid' : 'QJsonValue (Invalid)',
'int' : 'QJsonValue (Number)',
'false' : 'QJsonValue (Bool)',
'true' : 'QJsonValue (Bool)',
'null' : 'QJsonValue (Null)',
'undefined' : 'QJsonValue (Undefined)',
'double' : 'QJsonValue (Number)',
'bytes' : 'QJsonValue (ByteArray)',
'string' : 'QJsonValue (String)',
'map' : 'QJsonValue (Object)',
'array' : 'QJsonValue (Array)'
}.get(key, 'QJsonValue (Unknown)')
if item_type == 0xffffffffffffffff:
d.putType(typename('invalid', is_cbor))
d.putValue('Invalid')
elif item_type == 0x00:
d.putType(typename('int', is_cbor))
d.putValue(item_data)
elif item_type == 0x100 + 20:
d.putType(typename('false', is_cbor))
d.putValue('False')
elif item_type == 0x100 + 21:
d.putType(typename('true', is_cbor))
d.putValue('True')
elif item_type == 0x100 + 22:
d.putType(typename('null', is_cbor))
d.putValue('Null')
elif item_type == 0x100 + 23:
d.putType(typename('undefined', is_cbor))
d.putValue('Undefined')
elif item_type == 0x202:
val = struct.unpack('d', struct.pack('q', item_data))
d.putType(typename('double', is_cbor))
d.putValue('%f' % val)
elif item_type == 0x40:
d.putType(typename('bytes', is_cbor))
qdumpHelper_QCbor_string(d, container_ptr, item_data, True)
elif item_type == 0x60:
d.putType(typename('string', is_cbor))
qdumpHelper_QCbor_string(d, container_ptr, item_data, False)
elif item_type == 0x80:
d.putType(typename('array', is_cbor))
qdumpHelper_QCbor_array(d, container_ptr, is_cbor)
elif item_type == 0xa0:
d.putType(typename('map', is_cbor))
qdumpHelper_QCbor_map(d, container_ptr, is_cbor)
elif item_type == 0x10000:
d.putType('QCborValue (DateTime)')
d.putValue('DateTime')
elif item_type == 0x10020:
d.putType('QCborValue (Url)')
d.putValue('Url')
elif item_type == 0x10023:
d.putType('QCborValue (RegularExpression)')
d.putValue('RegularExpression')
elif item_type == 0x10025:
d.putType('QCborValue (Uuid)')
d.putValue('Uuid')
else:
d.putType('QCborValue (Unknown)')
d.putValue(item_data)

View File

@@ -576,6 +576,8 @@ AST *Parser::parse(int startToken)
if (yytoken != -1) { if (yytoken != -1) {
const QLatin1String s(spell[yytoken]); const QLatin1String s(spell[yytoken]);
message = QString::fromLatin1("Unexpected token `%1'").arg(s); message = QString::fromLatin1("Unexpected token `%1'").arg(s);
if (yytoken == 0) // do not freeze on unexpected end of file
return nullptr;
} }
for (; _tos; --_tos) { for (; _tos; --_tos) {

View File

@@ -166,6 +166,8 @@ AST *Parser::parse(int startToken)
if (yytoken != -1) { if (yytoken != -1) {
const QLatin1String s(spell[yytoken]); const QLatin1String s(spell[yytoken]);
message = QString::fromLatin1("Unexpected token `%1'").arg(s); message = QString::fromLatin1("Unexpected token `%1'").arg(s);
if (yytoken == 0) // do not freeze on unexpected end of file
return nullptr;
} }
for (; _tos; --_tos) { for (; _tos; --_tos) {

View File

@@ -877,12 +877,13 @@ int Lexer::scanString(ScanStringMode mode)
// in case we just parsed a \r, we need to reset this flag to get things working // in case we just parsed a \r, we need to reset this flag to get things working
// correctly in the loop below and afterwards // correctly in the loop below and afterwards
_skipLinefeed = false; _skipLinefeed = false;
bool first = true;
if (_engine) { if (_engine) {
while (_codePtr <= _endPtr) { while (_codePtr <= _endPtr) {
if (isLineTerminator()) { if (isLineTerminator()) {
if ((quote == QLatin1Char('`') || qmlMode())) { if ((quote == QLatin1Char('`') || qmlMode())) {
--_currentLineNumber; if (first)
--_currentLineNumber;
break; break;
} }
_errorCode = IllegalCharacter; _errorCode = IllegalCharacter;
@@ -910,6 +911,7 @@ int Lexer::scanString(ScanStringMode mode)
// don't use scanChar() here, that would transform \r sequences and the midRef() call would create the wrong result // don't use scanChar() here, that would transform \r sequences and the midRef() call would create the wrong result
_char = *_codePtr++; _char = *_codePtr++;
++_currentColumnNumber; ++_currentColumnNumber;
first = false;
} }
} }

View File

@@ -88,11 +88,9 @@ QTextCursor selectAt(QTextCursor textCursor, int line, int column, uint length)
if (column < 1) if (column < 1)
column = 1; column = 1;
textCursor.setPosition(0); const int anchorPosition = positionInText(textCursor.document(), line, column + length);
textCursor.movePosition(QTextCursor::NextBlock, QTextCursor::MoveAnchor, line - 1); textCursor.setPosition(anchorPosition);
textCursor.movePosition(QTextCursor::NextCharacter,QTextCursor::MoveAnchor, column + length - 1 ); textCursor.setPosition(anchorPosition - length, QTextCursor::KeepAnchor);
textCursor.movePosition(QTextCursor::PreviousCharacter,QTextCursor::KeepAnchor, length);
return textCursor; return textCursor;
} }

View File

@@ -788,16 +788,16 @@ void AndroidSettingsWidget::downloadOpenSslRepo(const bool silent)
qCDebug(androidsettingswidget) << "Cloning OpenSSL repo: " << gitCloneCommand.toUserOutput(); qCDebug(androidsettingswidget) << "Cloning OpenSSL repo: " << gitCloneCommand.toUserOutput();
QDir openSslDir(openSslPath.toString()); QDir openSslDir(openSslPath.toString());
if (openSslDir.exists()) { const bool isEmptyDir = openSslDir.isEmpty(QDir::AllEntries | QDir::NoDotAndDotDot
auto userInput = QMessageBox::information(this, openSslCloneTitle, | QDir::Hidden | QDir::System);
tr("The selected download path (%1) for OpenSSL already exists. " if (openSslDir.exists() && !isEmptyDir) {
"Remove and overwrite its content?") QMessageBox::information(
.arg(QDir::toNativeSeparators(openSslPath.toString())), this,
QMessageBox::Yes | QMessageBox::No); openSslCloneTitle,
if (userInput == QMessageBox::Yes) tr("The selected download path (%1) for OpenSSL already exists and the directory is "
openSslDir.removeRecursively(); "not empty. Select a different path or make sure it is an empty directory.")
else .arg(QDir::toNativeSeparators(openSslPath.toString())));
return; return;
} }
QProgressDialog *openSslProgressDialog QProgressDialog *openSslProgressDialog

View File

@@ -258,39 +258,52 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
extractBacktraceInformation(t.backtraceGraph, sourceDir, id.backtrace, 500)); extractBacktraceInformation(t.backtraceGraph, sourceDir, id.backtrace, 500));
} }
// Is this a terminal application? if (ct.targetType == ExecutableType) {
Utils::FilePaths librarySeachPaths; Utils::FilePaths librarySeachPaths;
if (ct.targetType == ExecutableType && t.link && t.link.value().language == "CXX") { // Is this a GUI application?
ct.linksToQtGui = Utils::contains(t.link.value().fragments,
[](const FragmentInfo &f) {
return f.role == "libraries"
&& (f.fragment.contains("QtGui")
|| f.fragment.contains("Qt5Gui")
|| f.fragment.contains("Qt6Gui"));
});
// Extract library directories for executables:
for (const FragmentInfo &f : t.link.value().fragments) { for (const FragmentInfo &f : t.link.value().fragments) {
FilePath tmp; if (f.role == "flags") // ignore all flags fragments
// Some projects abuse linking to libraries to pass random flags to the linker! continue;
if (f.role != "flags"
&& !(f.fragment.startsWith("-") || f.fragment.contains(" -"))) {
tmp = FilePath::fromString(currentBuildDir.absoluteFilePath(
QDir::fromNativeSeparators(f.fragment)));
}
if (f.role == "libraries") { // CMake sometimes mixes several shell-escaped pieces into one fragment. Disentangle that again:
tmp = tmp.parentDir(); const QStringList parts = QtcProcess::splitArgs(f.fragment);
for (const QString part : parts) {
// Some projects abuse linking to libraries to pass random flags to the linker, so ignore
// flags mixed into a fragment
if (part.startsWith("-"))
continue;
if (f.fragment.contains("QtGui") || f.fragment.contains("Qt5Gui") FilePath tmp = FilePath::fromString(
|| f.fragment.contains("Qt6Gui")) currentBuildDir.absoluteFilePath(QDir::fromNativeSeparators(part)));
ct.linksToQtGui = true;
}
if (!tmp.isEmpty()) { if (f.role == "libraries")
librarySeachPaths.append(tmp); tmp = tmp.parentDir();
// Libraries often have their import libs in ../lib and the
// actual dll files in ../bin on windows. Qt is one example of that.
if (tmp.fileName() == "lib" && HostOsInfo::isWindowsHost()) {
const FilePath path = tmp.parentDir().pathAppended("bin");
librarySeachPaths.append(path); if (!tmp.isEmpty()
&& tmp.isDir()) { // f.role is libraryPath or frameworkPath
librarySeachPaths.append(tmp);
// Libraries often have their import libs in ../lib and the
// actual dll files in ../bin on windows. Qt is one example of that.
if (tmp.fileName() == "lib" && HostOsInfo::isWindowsHost()) {
const FilePath path = tmp.parentDir().pathAppended("bin");
if (path.isDir())
librarySeachPaths.append(path);
}
} }
} }
} }
ct.libraryDirectories = filteredUnique(librarySeachPaths);
} }
ct.libraryDirectories = filteredUnique(librarySeachPaths);
return ct; return ct;
}); });
@@ -566,6 +579,8 @@ std::pair<std::unique_ptr<CMakeProjectNode>, QSet<FilePath>> generateRootProject
= findOrDefault(data.codemodel.projects, equal(&FileApiDetails::Project::parent, -1)); = findOrDefault(data.codemodel.projects, equal(&FileApiDetails::Project::parent, -1));
if (!topLevelProject.name.isEmpty()) if (!topLevelProject.name.isEmpty())
result.first->setDisplayName(topLevelProject.name); result.first->setDisplayName(topLevelProject.name);
else
result.first->setDisplayName(sourceDirectory.fileName());
QHash<FilePath, ProjectNode *> cmakeListsNodes = addCMakeLists(result.first.get(), QHash<FilePath, ProjectNode *> cmakeListsNodes = addCMakeLists(result.first.get(),
std::move(data.cmakeListNodes)); std::move(data.cmakeListNodes));

View File

@@ -310,7 +310,7 @@ static std::vector<Project> extractProjects(const QJsonArray &projects, QString
project.directories = indexList(obj.value("directoryIndexes")); project.directories = indexList(obj.value("directoryIndexes"));
project.targets = indexList(obj.value("targetIndexes")); project.targets = indexList(obj.value("targetIndexes"));
if (project.name.isEmpty() || project.directories.empty()) { if (project.directories.empty()) {
qCDebug(cmakeFileApi) << "Invalid project skipped!"; qCDebug(cmakeFileApi) << "Invalid project skipped!";
errorMessage = QCoreApplication::translate( errorMessage = QCoreApplication::translate(
"CMakeProjectManager::Internal", "CMakeProjectManager::Internal",

View File

@@ -63,24 +63,26 @@ namespace Internal {
static const int KIT_VERSION = 5; // Bumps up whenever details in Kit creation change static const int KIT_VERSION = 5; // Bumps up whenever details in Kit creation change
static QString packagePathFromSettings(const QString &settingsKey, const QString &defaultPath = {}) static QString packagePathFromSettings(const QString &settingsKey,
QSettings::Scope scope = QSettings::UserScope,
const QString &defaultPath = {})
{ {
QSettings *s = Core::ICore::settings(); QSettings *s = Core::ICore::settings(scope);
s->beginGroup(Constants::SETTINGS_GROUP); s->beginGroup(Constants::SETTINGS_GROUP);
const QString path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) const QString path = s->value(QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX)
+ settingsKey, defaultPath).toString(); + settingsKey, defaultPath).toString();
s->endGroup(); s->endGroup();
return path; return Utils::FilePath::fromFileInfo(path).toString();
} }
McuPackage::McuPackage(const QString &label, const QString &defaultPath, McuPackage::McuPackage(const QString &label, const QString &defaultPath,
const QString &detectionPath, const QString &settingsKey) const QString &detectionPath, const QString &settingsKey)
: m_label(label) : m_label(label)
, m_defaultPath(defaultPath) , m_defaultPath(packagePathFromSettings(settingsKey, QSettings::SystemScope, defaultPath))
, m_detectionPath(detectionPath) , m_detectionPath(detectionPath)
, m_settingsKey(settingsKey) , m_settingsKey(settingsKey)
{ {
m_path = packagePathFromSettings(settingsKey, defaultPath); m_path = packagePathFromSettings(settingsKey, QSettings::UserScope, m_defaultPath);
} }
QString McuPackage::path() const QString McuPackage::path() const
@@ -105,6 +107,12 @@ QWidget *McuPackage::widget()
m_widget = new QWidget; m_widget = new QWidget;
m_fileChooser = new Utils::PathChooser; m_fileChooser = new Utils::PathChooser;
m_fileChooser->lineEdit()->setButtonIcon(Utils::FancyLineEdit::Right,
Utils::Icons::RESET.icon());
m_fileChooser->lineEdit()->setButtonVisible(Utils::FancyLineEdit::Right, true);
connect(m_fileChooser->lineEdit(), &Utils::FancyLineEdit::rightButtonClicked, [&](){
m_fileChooser->setPath(m_defaultPath);
});
auto layout = new QGridLayout(m_widget); auto layout = new QGridLayout(m_widget);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
@@ -169,11 +177,8 @@ void McuPackage::writeToSettings() const
{ {
const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' + const QString key = QLatin1String(Constants::SETTINGS_GROUP) + '/' +
QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey; QLatin1String(Constants::SETTINGS_KEY_PACKAGE_PREFIX) + m_settingsKey;
const QSettings *iS = Core::ICore::settings(QSettings::SystemScope);
QSettings *uS = Core::ICore::settings(); QSettings *uS = Core::ICore::settings();
if (m_path == m_defaultPath || ( if (m_path == m_defaultPath)
iS->contains(key) &&
m_path == Utils::FilePath::fromUserInput(iS->value(key).toString()).toString()))
uS->remove(key); uS->remove(key);
else else
uS->setValue(key, m_path); uS->setValue(key, m_path);
@@ -213,6 +218,8 @@ void McuPackage::updateStatus()
break; break;
} }
m_infoLabel->setText(statusText); m_infoLabel->setText(statusText);
m_fileChooser->lineEdit()->button(Utils::FancyLineEdit::Right)->setEnabled(
m_path != m_defaultPath);
} }
McuToolChainPackage::McuToolChainPackage(const QString &label, const QString &defaultPath, McuToolChainPackage::McuToolChainPackage(const QString &label, const QString &defaultPath,
@@ -465,7 +472,8 @@ void McuSupportOptions::setQulDir(const Utils::FilePath &dir)
Utils::FilePath McuSupportOptions::qulDirFromSettings() Utils::FilePath McuSupportOptions::qulDirFromSettings()
{ {
return Utils::FilePath::fromUserInput( return Utils::FilePath::fromUserInput(
packagePathFromSettings(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK)); packagePathFromSettings(Constants::SETTINGS_KEY_PACKAGE_QT_FOR_MCUS_SDK,
QSettings::UserScope));
} }
static Utils::FilePath jomExecutablePath() static Utils::FilePath jomExecutablePath()

View File

@@ -641,7 +641,10 @@ bool GenericProposalWidget::eventFilter(QObject *o, QEvent *e)
case Qt::Key_End: case Qt::Key_End:
case Qt::Key_Backspace: case Qt::Key_Backspace:
// We want these navigation keys to work in the editor. // We want these navigation keys to work in the editor.
break; QApplication::sendEvent(const_cast<QWidget *>(d->m_underlyingWidget), e);
if (isVisible())
d->m_assistant->notifyChange();
return true;
default: default:
// Only forward keys that insert text and refine the completion. // Only forward keys that insert text and refine the completion.

View File

@@ -7183,6 +7183,127 @@ void tst_Dumpers::dumper_data()
+ Check("p", "<5 items>", "@QGraphicsPolygonItem"); + Check("p", "<5 items>", "@QGraphicsPolygonItem");
QTest::newRow("QCbor")
<< Data("#include <QString>\n"
"#if QT_VERSION >= 0x050c00\n"
"#include <QCborArray>\n"
"#include <QCborMap>\n"
"#include <QCborValue>\n"
"#include <QVariantMap>\n"
"#endif\n",
"#if QT_VERSION >= 0x050c00\n"
"QCborMap ob0;\n"
"QCborMap ob = QCborMap::fromVariantMap({\n"
" {\"a\", 1},\n"
" {\"bb\", 2},\n"
" {\"ccc\", \"hallo\"},\n"
" {\"s\", \"ssss\"}\n"
"});\n"
"ob.insert(QLatin1String(\"d\"), QCborMap::fromVariantMap({{\"ddd\", 1234}}));\n"
"\n"
"QCborValue a0;\n"
"QCborValue a1(1);\n"
"QCborValue a2(\"asd\");\n"
"QCborValue a3(QString::fromUtf8(\"cöder\"));\n"
"QCborValue a4(1.4);\n"
"QCborValue a5(true);\n"
"QCborValue a6(QByteArray(\"cder\"));\n"
"\n"
"QCborArray aa;\n"
"QCborArray a;\n"
"a.append(a1);\n"
"a.append(a2);\n"
"a.append(a3);\n"
"a.append(a4);\n"
"a.append(a5);\n"
"a.append(a0);\n"
"a.append(ob);\n"
"\n"
"QCborArray b;\n"
"b.append(QCborValue(1));\n"
"b.append(a);\n"
"b.append(QCborValue(2));\n"
"\n"
"QCborArray c;\n"
"for (unsigned int i = 0; i < 32; ++i) {\n"
" c.append(QCborValue(qint64(1u << i) - 1));\n"
" c.append(QCborValue(qint64(1u << i)));\n"
" c.append(QCborValue(qint64(1u << i) + 1));\n"
"}\n"
"for (unsigned int i = 0; i < 32; ++i) {\n"
" c.append(QCborValue(-qint64(1u << i) + 1));\n"
" c.append(QCborValue(-qint64(1u << i)));\n"
" c.append(QCborValue(-qint64(1u << i) - 1));\n"
"}"
"unused(&b, &a, &aa);\n"
"#endif\n",
"")
+ Cxx11Profile()
+ CoreProfile()
+ QtVersion(0x50f00)
+ MsvcVersion(1900)
+ Check("a0", "Undefined", "QCborValue (Undefined)")
+ Check("a1", "1", "QCborValue (Integer)")
+ Check("a2", "\"asd\"", "QCborValue (String)")
+ Check("a3", "\"cöder\"", "QCborValue (String)")
+ Check("a4", "1.400000", "QCborValue (Double)")
+ Check("a5", "True", "QCborValue (True)")
+ Check("a6", "\"cder\"", "QCborValue (ByteArray)")
+ Check("aa", "<0 items>", "@QCborArray")
+ Check("a", "<7 items>", "@QCborArray")
+ Check("a.0", "[0]", "1", "QCborValue (Integer)")
+ Check("a.1", "[1]", "\"asd\"", "QCborValue (String)")
+ Check("a.2", "[2]", "\"cöder\"", "QCborValue (String)")
+ Check("a.3", "[3]", "1.400000", "QCborValue (Double)")
+ Check("a.4", "[4]", "True", "QCborValue (True)")
+ Check("a.5", "[5]", "Undefined", "QCborValue (Undefined)")
+ Check("a.6", "[6]", "<5 items>", "QCborValue (Map)")
+ Check("a.6.0", "[0] \"a\"", "1", "")
+ Check("a.6.1", "[1] \"bb\"", "2", "")
+ Check("a.6.2", "[2] \"ccc\"", "\"hallo\"", "")
+ Check("a.6.3", "[3] \"s\"", "\"ssss\"", "")
+ Check("a.6.4", "[4] \"d\"", "<1 items>", "")
+ Check("b", "b", "<3 items>" , "@QCborArray")
+ Check("b.0", "[0]", "1", "QCborValue (Integer)")
+ Check("b.1", "[1]", "<7 items>", "QCborValue (Array)")
+ Check("b.1.0", "[0]", "1", "QCborValue (Integer)")
+ Check("b.1.1", "[1]", "\"asd\"", "QCborValue (String)")
+ Check("b.1.2", "[2]", "\"cöder\"", "QCborValue (String)")
+ Check("b.1.3", "[3]", "1.400000", "QCborValue (Double)")
+ Check("b.1.4", "[4]", "True", "QCborValue (True)")
+ Check("b.1.5", "[5]", "Undefined", "QCborValue (Undefined)")
+ Check("b.1.6", "[6]", "<5 items>", "QCborValue (Map)")
+ Check("b.2", "[2]", "2", "QCborValue (Integer)")
+ Check("c", "c", "<192 items>", "@QCborArray")
+ Check("c.0", "[0]", "0", "QCborValue (Integer)")
+ Check("c.1", "[1]", "1", "QCborValue (Integer)")
+ Check("c.78", "[78]", "67108863", "QCborValue (Integer)")
+ Check("c.79", "[79]", "67108864", "QCborValue (Integer)")
+ Check("c.94", "[94]", "2147483648", "QCborValue (Integer)")
+ Check("c.95", "[95]", "2147483649", "QCborValue (Integer)")
+ Check("c.96", "[96]", "0", "QCborValue (Integer)")
+ Check("c.97", "[97]", "-1", "QCborValue (Integer)")
+ Check("c.174", "[174]", "-67108863", "QCborValue (Integer)")
+ Check("c.175", "[175]", "-67108864", "QCborValue (Integer)")
+ Check("ob0", "ob0", "<0 items>", "@QCborMap")
+ Check("ob", "ob", "<5 items>", "@QCborMap")
+ Check("ob.0", "[0] \"a\"", "1", "")
+ Check("ob.0.key", "key", "\"a\"", "QCborValue (String)")
+ Check("ob.0.value", "value", "1", "QCborValue (Integer)")
+ Check("ob.1", "[1] \"bb\"", "2", "")
+ Check("ob.2", "[2] \"ccc\"", "\"hallo\"", "")
+ Check("ob.3", "[3] \"s\"", "\"ssss\"", "")
+ Check("ob.4", "[4] \"d\"", "<1 items>", "")
;
const QtVersion jsonv1{0, 0x50e00};
const QtVersion jsonv2{0x50e00};
QTest::newRow("QJson") QTest::newRow("QJson")
<< Data("#include <QString>\n" << Data("#include <QString>\n"
"#if QT_VERSION >= 0x050000\n" "#if QT_VERSION >= 0x050000\n"
@@ -7193,6 +7314,7 @@ void tst_Dumpers::dumper_data()
"#endif\n", "#endif\n",
"#if QT_VERSION >= 0x050000\n" "#if QT_VERSION >= 0x050000\n"
"QJsonObject ob0;\n"
"QJsonObject ob = QJsonObject::fromVariantMap({\n" "QJsonObject ob = QJsonObject::fromVariantMap({\n"
" {\"a\", 1},\n" " {\"a\", 1},\n"
" {\"bb\", 2},\n" " {\"bb\", 2},\n"
@@ -7201,6 +7323,7 @@ void tst_Dumpers::dumper_data()
"});\n" "});\n"
"ob.insert(QLatin1String(\"d\"), QJsonObject::fromVariantMap({{\"ddd\", 1234}}));\n" "ob.insert(QLatin1String(\"d\"), QJsonObject::fromVariantMap({{\"ddd\", 1234}}));\n"
"\n" "\n"
"QJsonArray aa;\n"
"QJsonArray a;\n" "QJsonArray a;\n"
"a.append(QJsonValue(1));\n" "a.append(QJsonValue(1));\n"
"a.append(QJsonValue(\"asd\"));\n" "a.append(QJsonValue(\"asd\"));\n"
@@ -7225,7 +7348,7 @@ void tst_Dumpers::dumper_data()
" c.append(QJsonValue(-qint64(1u << i)));\n" " c.append(QJsonValue(-qint64(1u << i)));\n"
" c.append(QJsonValue(-qint64(1u << i) - 1));\n" " c.append(QJsonValue(-qint64(1u << i) - 1));\n"
"}" "}"
"unused(&ob,&b,&a);\n" "unused(&ob, &b, &a, &aa);\n"
"#endif\n", "#endif\n",
"") "")
@@ -7235,45 +7358,66 @@ void tst_Dumpers::dumper_data()
+ QtVersion(0x50000) + QtVersion(0x50000)
+ MsvcVersion(1900) + MsvcVersion(1900)
+ Check("aa", "<0 items>", "@QJsonArray")
+ Check("a", "<6 items>", "@QJsonArray") + Check("a", "<6 items>", "@QJsonArray")
+ Check("a.0", "[0]", "1", "QJsonValue (Number)") + Check("a.0", "[0]", "1", "QJsonValue (Number)")
+ Check("a.1", "[1]", "\"asd\"", "QJsonValue (String)") + Check("a.1", "[1]", "\"asd\"", "QJsonValue (String)")
+ Check("a.2", "[2]", "\"cdfer\"", "QJsonValue (String)") + Check("a.2", "[2]", "\"cdfer\"", "QJsonValue (String)")
+ Check("a.3", "[3]", "1.4", "QJsonValue (Number)") + Check("a.3", "[3]", "1.4", "QJsonValue (Number)") % jsonv1
+ Check("a.4", "[4]", "true", "QJsonValue (Bool)") + Check("a.3", "[3]", "1.400000", "QJsonValue (Number)") % jsonv2
+ Check("a.4", "[4]", "true", "QJsonValue (Bool)") % jsonv1
+ Check("a.4", "[4]", "True", "QJsonValue (Bool)") % jsonv2
+ Check("a.5", "[5]", "<5 items>", "QJsonValue (Object)") + Check("a.5", "[5]", "<5 items>", "QJsonValue (Object)")
+ Check("a.5.0", "\"a\"", "1", "QJsonValue (Number)") + Check("a.5.0", "\"a\"", "1", "QJsonValue (Number)") % jsonv1
+ Check("a.5.1", "\"bb\"", "2", "QJsonValue (Number)") + Check("a.5.0", "[0] \"a\"", "1", "" ) % jsonv2
+ Check("a.5.2", "\"ccc\"", "\"hallo\"", "QJsonValue (String)") + Check("a.5.1", "\"bb\"", "2", "QJsonValue (Number)") % jsonv1
+ Check("a.5.3", "\"d\"", "<1 items>", "QJsonValue (Object)") + Check("a.5.1", "[1] \"bb\"", "2", "" ) % jsonv2
+ Check("a.5.4", "\"s\"", "\"ssss\"", "QJsonValue (String)") + Check("a.5.2", "\"ccc\"", "\"hallo\"", "QJsonValue (String)") % jsonv1
+ Check("a.5.2", "[2] \"ccc\"","\"hallo\"", "" ) % jsonv2
+ Check("a.5.3", "\"d\"", "<1 items>", "QJsonValue (Object)") % jsonv1
+ Check("a.5.3", "[3] \"d\"", "<1 items>", "" ) % jsonv2
+ Check("a.5.4", "\"s\"", "\"ssss\"", "QJsonValue (String)") % jsonv1
+ Check("a.5.4", "[4] \"s\"", "\"ssss\"", "" ) % jsonv2
+ Check("b", "b", "<3 items>" , "@QJsonArray") + Check("b", "b", "<3 items>" , "@QJsonArray")
+ Check("b.0", "[0]", "1", "QJsonValue (Number)") + Check("b.0", "[0]", "1", "QJsonValue (Number)")
+ Check("b.1", "[1]", "<6 items>", "QJsonValue (Array)") + Check("b.1", "[1]", "<6 items>", "QJsonValue (Array)")
+ Check("b.1.0", "[0]", "1", "QJsonValue (Number)") + Check("b.1.0", "[0]", "1", "QJsonValue (Number)") % jsonv2
+ Check("b.1.1", "[1]", "\"asd\"", "QJsonValue (String)") + Check("b.1.1", "[1]", "\"asd\"", "QJsonValue (String)") % jsonv2
+ Check("b.1.2", "[2]", "\"cdfer\"", "QJsonValue (String)") + Check("b.1.2", "[2]", "\"cdfer\"", "QJsonValue (String)") % jsonv2
+ Check("b.1.3", "[3]", "1.4", "QJsonValue (Number)") + Check("b.1.3", "[3]", "1.4", "QJsonValue (Number)") % jsonv1
+ Check("b.1.4", "[4]", "true", "QJsonValue (Bool)") + Check("b.1.3", "[3]", "1.400000", "QJsonValue (Number)") % jsonv2
+ Check("b.1.5", "[5]", "<5 items>", "QJsonValue (Object)") + Check("b.1.4", "[4]", "true", "QJsonValue (Bool)") % jsonv1
+ Check("b.2", "[2]", "2", "QJsonValue (Number)") + Check("b.1.5", "[5]", "<5 items>", "QJsonValue (Object)") % jsonv2
+ Check("b.2", "[2]", "2", "QJsonValue (Number)") % jsonv2
+ Check("c", "c", "<192 items>", "@QJsonArray") + Check("c", "c", "<192 items>", "@QJsonArray")
+ Check("c.0", "[0]", "0.0", "QJsonValue (Number)") + Check("c.0", "[0]", "0.0", "QJsonValue (Number)") % jsonv1
+ Check("c.0", "[0]", "0", "QJsonValue (Number)") % jsonv2
+ Check("c.1", "[1]", "1", "QJsonValue (Number)") + Check("c.1", "[1]", "1", "QJsonValue (Number)")
+ Check("c.78", "[78]", "67108863", "QJsonValue (Number)") + Check("c.78", "[78]", "67108863", "QJsonValue (Number)")
+ Check("c.79", "[79]", "67108864.0", "QJsonValue (Number)") + Check("c.79", "[79]", "67108864.0", "QJsonValue (Number)") % jsonv1
+ Check("c.94", "[94]", "2147483648.0", "QJsonValue (Number)") + Check("c.79", "[79]", "67108864", " QJsonValue (Number)") % jsonv2
+ Check("c.95", "[95]", "2147483649.0", "QJsonValue (Number)") + Check("c.94", "[94]", "2147483648.0", "QJsonValue (Number)") % jsonv1
+ Check("c.96", "[96]", "0.0", "QJsonValue (Number)") + Check("c.94", "[94]", "2147483648", "QJsonValue (Number)") % jsonv2
+ Check("c.95", "[95]", "2147483649.0", "QJsonValue (Number)") % jsonv1
+ Check("c.95", "[95]", "2147483649", "QJsonValue (Number)") % jsonv2
+ Check("c.96", "[96]", "0.0", "QJsonValue (Number)") % jsonv1
+ Check("c.96", "[96]", "0", "QJsonValue (Number)") % jsonv2
+ Check("c.97", "[97]", "-1", "QJsonValue (Number)") + Check("c.97", "[97]", "-1", "QJsonValue (Number)")
+ Check("c.174", "[174]", "-67108863", "QJsonValue (Number)") + Check("c.174", "[174]", "-67108863", "QJsonValue (Number)")
+ Check("c.175", "[175]", "-67108864.0", "QJsonValue (Number)") + Check("c.175", "[175]", "-67108864.0", "QJsonValue (Number)") % jsonv1
+ Check("c.175", "[175]", "-67108864", "QJsonValue (Number)") % jsonv2
+ Check("ob0", "ob0", "<0 items>", "@QJsonObject")
+ Check("ob", "ob", "<5 items>", "@QJsonObject") + Check("ob", "ob", "<5 items>", "@QJsonObject")
+ Check("ob.0", "\"a\"", "1", "QJsonValue (Number)") + Check("ob.0", "\"a\"", "1", "QJsonValue (Number)") % jsonv1
+ Check("ob.1", "\"bb\"", "2", "QJsonValue (Number)") + Check("ob.0", "[0] \"a\"", "1", "" ) % jsonv2
+ Check("ob.2", "\"ccc\"", "\"hallo\"", "QJsonValue (String)") + Check("ob.1", "\"bb\"", "2", "QJsonValue (Number)") % jsonv1
+ Check("ob.3", "\"d\"", "<1 items>", "QJsonValue (Object)") + Check("ob.1", "[1] \"bb\"", "2", "" ) % jsonv2
+ Check("ob.4", "\"s\"", "\"ssss\"", "QJsonValue (String)"); + Check("ob.2", "\"ccc\"", "\"hallo\"", "QJsonValue (String)") % jsonv1
+ Check("ob.2", "[2] \"ccc\"", "\"hallo\"", "" ) % jsonv2
+ Check("ob.3", "\"d\"", "<1 items>", "QJsonValue (Object)") % jsonv1
+ Check("ob.3", "[3] \"d\"", "<1 items>", "" ) % jsonv2
+ Check("ob.4", "\"s\"", "\"ssss\"", "QJsonValue (String)") % jsonv1
+ Check("ob.4", "[4] \"s\"", "\"ssss\"", "" ) % jsonv2;
QTest::newRow("Q&qstring_literal_temp,V4") QTest::newRow("Q&qstring_literal_temp,V4")