Merge "Merge remote-tracking branch 'origin/4.11'"

This commit is contained in:
The Qt Project
2020-02-05 11:00:37 +00:00
24 changed files with 364 additions and 271 deletions

View File

@@ -16,6 +16,10 @@ Editing
* Fixed `Visualize Whitespace` for editors without specialized highlighter definition * Fixed `Visualize Whitespace` for editors without specialized highlighter definition
(QTCREATORBUG-23040) (QTCREATORBUG-23040)
### Language Client
* Fixed failure when restarting server (QTCREATORBUG-23497)
### C++ ### C++
* Fixed wrong warnings about C++98 incompatibility with MSVC (QTCREATORBUG-23118) * Fixed wrong warnings about C++98 incompatibility with MSVC (QTCREATORBUG-23118)
@@ -37,6 +41,14 @@ Projects
* Fixed subdirectory structure in project tree (QTCREATORBUG-23372) * Fixed subdirectory structure in project tree (QTCREATORBUG-23372)
### Qbs
* Fixed building Android projects (QTCREATORBUG-23489)
### Generic
* Fixed crash when updating deployment data (QTCREATORBUG-23501)
Debugging Debugging
--------- ---------
@@ -61,6 +73,10 @@ Platforms
* Worked around issue with HiDPI in Qt (QTBUG-80934) * Worked around issue with HiDPI in Qt (QTBUG-80934)
### Remote Linux
* Fixed that terminal setting was ignored (QTCREATORBUG-23470)
### WebAssembly ### WebAssembly
* Fixed missing device in kit (QTCREATORBUG-23360) * Fixed missing device in kit (QTCREATORBUG-23360)

View File

@@ -9,7 +9,7 @@ int main(int argc, char *argv[])
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QQuickView view; QQuickView view;
view.engine->addImportPath("qrc:/qml/imports"); view.engine()->addImportPath("qrc:/qml/imports");
view.setSource(QUrl("qrc:/qml/ProgressBar.ui.qml")); view.setSource(QUrl("qrc:/qml/ProgressBar.ui.qml"));
if (!view.errors().isEmpty()) if (!view.errors().isEmpty())
return -1; return -1;

View File

@@ -181,4 +181,28 @@
at each level. To include the checks from the lower levels automatically, at each level. To include the checks from the lower levels automatically,
select the \uicontrol {Enable lower levels automatically} check box. select the \uicontrol {Enable lower levels automatically} check box.
\section2 Creating Clang-Tidy Configuration Files
Clang-Tidy reads the configuration for each source file from a .clang-tidy
file located in the closest parent directory of the source file. If any
configuration options have a corresponding command-line option, the
command-line option takes precedence. The effective configuration can be
inspected using \c {-dump-config}.
\QC creates the configuration for you based on the checks you select. To
store the checks in file format, you can create a .clang-tidy file, as
follows:
\list 1
\li Select \uicontrol {Edit Checks as String} and copy the contents of
the field.
\li Pipe the output of \c {clang-tidy -dump-config} into a file named
\c {.clang-tidy}. For example:
\c {clang-tidy -checks=-*,bugprone-*,cppcoreguidelines-avoid-* -dump-config > .clang-tidy}
\li Move the .clang-tidy file to the parent directory of the sources.
\endlist
To add more checks using \QC later on, copy the checks from your .clang-tidy
file into the \uicontrol {Edit Checks as String} field, select additional
checks, and copy-paste the contents of the field to the .clang-tidy file.
*/ */

View File

@@ -100,7 +100,7 @@
\skipto QQuickView view; \skipto QQuickView view;
\printuntil view.show() \printuntil view.show()
Where \c {qrc:/qml/imports} is the import path and Where \c {qrc:/qml/imports} is the import path and
\c {qrc:qml/ProgressBar.ui.qml} is the path to and the \c {qrc:/qml/ProgressBar.ui.qml} is the path to and the
name of the main QML file in the Qt Quick UI project. name of the main QML file in the Qt Quick UI project.
\li Select \uicontrol Build > \uicontrol Run to build and run your \li Select \uicontrol Build > \uicontrol Run to build and run your
project. project.

View File

@@ -162,7 +162,7 @@ bool ServerCapabilities::isValid(QStringList *error) const
&& checkOptional<bool>(error, documentHighlightProviderKey) && checkOptional<bool>(error, documentHighlightProviderKey)
&& checkOptional<bool>(error, documentSymbolProviderKey) && checkOptional<bool>(error, documentSymbolProviderKey)
&& checkOptional<bool>(error, workspaceSymbolProviderKey) && checkOptional<bool>(error, workspaceSymbolProviderKey)
&& checkOptional<bool>(error, codeActionProviderKey) && checkOptional<bool, CodeActionOptions>(error, codeActionProviderKey)
&& checkOptional<CodeLensOptions>(error, codeLensProviderKey) && checkOptional<CodeLensOptions>(error, codeLensProviderKey)
&& checkOptional<bool>(error, documentFormattingProviderKey) && checkOptional<bool>(error, documentFormattingProviderKey)
&& checkOptional<bool>(error, documentRangeFormattingProviderKey) && checkOptional<bool>(error, documentRangeFormattingProviderKey)

View File

@@ -226,11 +226,10 @@ bool AndroidBuildApkStep::init()
QString outputDir = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString(); QString outputDir = bc->buildDirectory().pathAppended(Constants::ANDROID_BUILDDIRECTORY).toString();
QString inputFile;
if (node) if (node)
inputFile = node->data(Constants::AndroidDeploySettingsFile).toString(); m_inputFile = node->data(Constants::AndroidDeploySettingsFile).toString();
if (inputFile.isEmpty()) { if (m_inputFile.isEmpty()) {
m_skipBuilding = true; m_skipBuilding = true;
return true; return true;
} }
@@ -242,7 +241,7 @@ bool AndroidBuildApkStep::init()
return false; return false;
} }
QStringList arguments = {"--input", inputFile, QStringList arguments = {"--input", m_inputFile,
"--output", outputDir, "--output", outputDir,
"--android-platform", AndroidManager::buildTargetSDK(target()), "--android-platform", AndroidManager::buildTargetSDK(target()),
"--jdk", AndroidConfigurations::currentConfig().openJDKLocation().toString()}; "--jdk", AndroidConfigurations::currentConfig().openJDKLocation().toString()};
@@ -358,6 +357,8 @@ bool AndroidBuildApkStep::verifyCertificatePassword()
static bool copyFileIfNewer(const QString &sourceFileName, static bool copyFileIfNewer(const QString &sourceFileName,
const QString &destinationFileName) const QString &destinationFileName)
{ {
if (sourceFileName == destinationFileName)
return true;
if (QFile::exists(destinationFileName)) { if (QFile::exists(destinationFileName)) {
QFileInfo destinationFileInfo(destinationFileName); QFileInfo destinationFileInfo(destinationFileName);
QFileInfo sourceFileInfo(sourceFileName); QFileInfo sourceFileInfo(sourceFileName);
@@ -398,48 +399,56 @@ void AndroidBuildApkStep::doRun()
if (!node) if (!node)
return false; return false;
FilePath deploymentSettingsFile = FilePath::fromString(node->data(Android::Constants::AndroidDeploySettingsFile).toString()); bool inputExists = QFile::exists(m_inputFile);
if (deploymentSettingsFile.exists()) if (inputExists && !AndroidManager::isQtCreatorGenerated(FilePath::fromString(m_inputFile)))
return true; // cmake creates this file for us return true; // use the generated file if it was not generated by qtcreator
auto targets = node->data(Android::Constants::AndroidTargets).toStringList(); auto targets = node->data(Android::Constants::AndroidTargets).toStringList();
if (targets.isEmpty()) if (targets.isEmpty())
return true; // qmake does this job for us return inputExists; // qmake does this job for us
QtSupport::BaseQtVersion *version = QtSupport::QtKitAspect::qtVersion(target()->kit());
if (!version)
return false;
QJsonObject deploySettings = Android::AndroidManager::deploymentSettings(target()); QJsonObject deploySettings = Android::AndroidManager::deploymentSettings(target());
QJsonObject architectures; QString applicationBinary;
if (version->qtVersion() < QtSupport::QtVersionNumber(5, 14, 0)) {
// Copy targets to android build folder QTC_ASSERT(androidAbis.size() == 1, return false);
QString applicationBinary = target()->activeRunConfiguration()->buildTargetInfo().targetFilePath.toFileInfo().fileName(); applicationBinary = target()->activeRunConfiguration()->buildTargetInfo().targetFilePath.toString();
for (const auto &abi : androidAbis) { Utils::FilePath androidLibsDir = bc->buildDirectory().pathAppended("android-build/libs").pathAppended(androidAbis.first());
QString targetSuffix = QString{"_%1.so"}.arg(abi);
if (applicationBinary.endsWith(targetSuffix)) {
// Keep only TargetName from "lib[TargetName]_abi.so"
applicationBinary.remove(0, 3).chop(targetSuffix.size());
}
Utils::FilePath androidLibsDir = bc->buildDirectory()
.pathAppended("android-build/libs")
.pathAppended(abi);
for (const auto &target : targets) { for (const auto &target : targets) {
if (target.endsWith(targetSuffix)) { if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString()))
if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString())) return false;
return false; }
if (abi == "x86") { deploySettings["target-architecture"] = androidAbis.first();
architectures[abi] = "i686-linux-android"; } else {
} else if (abi == "x86_64") { applicationBinary = target()->activeRunConfiguration()->buildTargetInfo().targetFilePath.toFileInfo().fileName();
architectures[abi] = "x86_64-linux-android"; QJsonObject architectures;
} else if (abi == "arm64-v8a") {
architectures[abi] = "aarch64-linux-android"; // Copy targets to android build folder
} else { for (const auto &abi : androidAbis) {
architectures[abi] = "arm-linux-androideabi"; QString targetSuffix = QString{"_%1.so"}.arg(abi);
if (applicationBinary.endsWith(targetSuffix)) {
// Keep only TargetName from "lib[TargetName]_abi.so"
applicationBinary.remove(0, 3).chop(targetSuffix.size());
}
Utils::FilePath androidLibsDir = bc->buildDirectory()
.pathAppended("android-build/libs")
.pathAppended(abi);
for (const auto &target : targets) {
if (target.endsWith(targetSuffix)) {
if (!copyFileIfNewer(target, androidLibsDir.pathAppended(QFileInfo{target}.fileName()).toString()))
return false;
architectures[abi] = AndroidManager::archTriplet(abi);
} }
} }
} }
deploySettings["architectures"] = architectures;
} }
deploySettings["application-binary"] = applicationBinary; deploySettings["application-binary"] = applicationBinary;
deploySettings["architectures"] = architectures;
QString extraLibs = node->data(Android::Constants::AndroidExtraLibs).toString(); QString extraLibs = node->data(Android::Constants::AndroidExtraLibs).toString();
if (!extraLibs.isEmpty()) if (!extraLibs.isEmpty())
@@ -458,7 +467,7 @@ void AndroidBuildApkStep::doRun()
qmlRootPath = target()->project()->rootProjectDirectory().toString(); qmlRootPath = target()->project()->rootProjectDirectory().toString();
deploySettings["qml-root-path"] = qmlRootPath; deploySettings["qml-root-path"] = qmlRootPath;
QFile f{deploymentSettingsFile.toString()}; QFile f{m_inputFile};
if (!f.open(QIODevice::WriteOnly)) if (!f.open(QIODevice::WriteOnly))
return false; return false;
f.write(QJsonDocument{deploySettings}.toJson()); f.write(QJsonDocument{deploySettings}.toJson());

View File

@@ -108,6 +108,7 @@ private:
QString m_command; QString m_command;
QString m_argumentsPasswordConcealed; QString m_argumentsPasswordConcealed;
bool m_skipBuilding = false; bool m_skipBuilding = false;
QString m_inputFile;
}; };
namespace Internal { namespace Internal {

View File

@@ -54,17 +54,18 @@
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <utils/synchronousprocess.h> #include <utils/synchronousprocess.h>
#include <QApplication>
#include <QDir> #include <QDir>
#include <QDomDocument>
#include <QFileSystemWatcher> #include <QFileSystemWatcher>
#include <QJsonDocument>
#include <QList> #include <QList>
#include <QLoggingCategory> #include <QLoggingCategory>
#include <QMessageBox>
#include <QProcess> #include <QProcess>
#include <QRegExp> #include <QRegExp>
#include <QMessageBox>
#include <QApplication>
#include <QDomDocument>
#include <QVersionNumber>
#include <QRegularExpression> #include <QRegularExpression>
#include <QVersionNumber>
namespace { namespace {
const QLatin1String AndroidManifestName("AndroidManifest.xml"); const QLatin1String AndroidManifestName("AndroidManifest.xml");
@@ -76,6 +77,7 @@ namespace {
const QString activityRegEx("(?<token>launchable-activity: )(.*?)(name=)'(?<target>.*?)'"); const QString activityRegEx("(?<token>launchable-activity: )(.*?)(name=)'(?<target>.*?)'");
const QString apkVersionRegEx("(?<token>package: )(.*?)(versionCode=)'(?<target>.*?)'"); const QString apkVersionRegEx("(?<token>package: )(.*?)(versionCode=)'(?<target>.*?)'");
const QString versionCodeRegEx("(?<token>versionCode=)(?<version>\\d*)"); const QString versionCodeRegEx("(?<token>versionCode=)(?<version>\\d*)");
const QString qtcSignature("This file is generated by QtCreator to be read by androiddeployqt and should not be modified by hand.");
static Q_LOGGING_CATEGORY(androidManagerLog, "qtc.android.androidManager", QtWarningMsg) static Q_LOGGING_CATEGORY(androidManagerLog, "qtc.android.androidManager", QtWarningMsg)
@@ -266,6 +268,18 @@ QStringList AndroidManager::applicationAbis(const Target *target)
return qt->androidAbis(); return qt->androidAbis();
} }
QString AndroidManager::archTriplet(const QString &abi)
{
if (abi == "x86") {
return {"i686-linux-android"};
} else if (abi == "x86_64") {
return {"x86_64-linux-android"};
} else if (abi == "arm64-v8a") {
return {"aarch64-linux-android"};
}
return {"arm-linux-androideabi"};
}
QJsonObject AndroidManager::deploymentSettings(const Target *target) QJsonObject AndroidManager::deploymentSettings(const Target *target)
{ {
QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit()); QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit());
@@ -276,11 +290,20 @@ QJsonObject AndroidManager::deploymentSettings(const Target *target)
if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_TYPEID) if (!tc || tc->typeId() != Constants::ANDROID_TOOLCHAIN_TYPEID)
return {}; return {};
QJsonObject settings; QJsonObject settings;
settings["_description"] = "This file is generated by QtCreator to be read by androiddeployqt and should not be modified by hand."; settings["_description"] = qtcSignature;
settings["qt"] = qt->prefix().toString(); settings["qt"] = qt->prefix().toString();
settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation().toString(); settings["ndk"] = AndroidConfigurations::currentConfig().ndkLocation().toString();
settings["sdk"] = AndroidConfigurations::currentConfig().sdkLocation().toString(); settings["sdk"] = AndroidConfigurations::currentConfig().sdkLocation().toString();
settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath().pathAppended("sysroot/usr/lib/").toString(); if (qt->qtVersion() < QtSupport::QtVersionNumber(5, 14, 0)) {
const QStringList abis = applicationAbis(target);
QTC_ASSERT(abis.size() == 1, return {});
settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath()
.pathAppended("sysroot/usr/lib/")
.pathAppended(archTriplet(abis.first()))
.pathAppended("libc++_shared.so").toString();
} else {
settings["stdcpp-path"] = AndroidConfigurations::currentConfig().toolchainPath().pathAppended("sysroot/usr/lib/").toString();
}
settings["toolchain-prefix"] = "llvm"; settings["toolchain-prefix"] = "llvm";
settings["tool-prefix"] = "llvm"; settings["tool-prefix"] = "llvm";
settings["useLLVM"] = true; settings["useLLVM"] = true;
@@ -288,6 +311,14 @@ QJsonObject AndroidManager::deploymentSettings(const Target *target)
return settings; return settings;
} }
bool AndroidManager::isQtCreatorGenerated(const FilePath &deploymentFile)
{
QFile f{deploymentFile.toString()};
if (!f.open(QIODevice::ReadOnly))
return false;
return QJsonDocument::fromJson(f.readAll()).object()["_description"].toString() == qtcSignature;
}
Utils::FilePath AndroidManager::dirPath(const ProjectExplorer::Target *target) Utils::FilePath AndroidManager::dirPath(const ProjectExplorer::Target *target)
{ {
if (auto *bc = target->activeBuildConfiguration()) if (auto *bc = target->activeBuildConfiguration())

View File

@@ -96,6 +96,7 @@ public:
static int minimumSDK(const ProjectExplorer::Kit *kit); static int minimumSDK(const ProjectExplorer::Kit *kit);
static QStringList applicationAbis(const ProjectExplorer::Target *target); static QStringList applicationAbis(const ProjectExplorer::Target *target);
static QString archTriplet(const QString &abi);
static Utils::FilePath dirPath(const ProjectExplorer::Target *target); static Utils::FilePath dirPath(const ProjectExplorer::Target *target);
static Utils::FilePath manifestPath(ProjectExplorer::Target *target); static Utils::FilePath manifestPath(ProjectExplorer::Target *target);
@@ -126,6 +127,7 @@ public:
static SdkToolResult runAaptCommand(const QStringList &args, int timeoutS = 30); static SdkToolResult runAaptCommand(const QStringList &args, int timeoutS = 30);
static QJsonObject deploymentSettings(const ProjectExplorer::Target *target); static QJsonObject deploymentSettings(const ProjectExplorer::Target *target);
static bool isQtCreatorGenerated(const Utils::FilePath &deploymentFile);
private: private:
static SdkToolResult runCommand(const Utils::CommandLine &command, static SdkToolResult runCommand(const Utils::CommandLine &command,

View File

@@ -401,48 +401,89 @@ KeilToolchainFactory::KeilToolchainFactory()
setUserCreatable(true); setUserCreatable(true);
} }
// Parse the 'tools.ini' file to fetch a toolchain version.
// Note: We can't use QSettings here!
static QString extractVersion(const QString &toolsFile, const QString &section)
{
QFile f(toolsFile);
if (!f.open(QIODevice::ReadOnly))
return {};
QTextStream in(&f);
enum State { Enter, Lookup, Exit } state = Enter;
while (!in.atEnd()) {
const QString line = in.readLine().trimmed();
// Search for section.
const int firstBracket = line.indexOf('[');
const int lastBracket = line.lastIndexOf(']');
const bool hasSection = (firstBracket == 0 && lastBracket != -1
&& (lastBracket + 1) == line.size());
switch (state) {
case Enter:
if (hasSection) {
const auto content = line.midRef(firstBracket + 1,
lastBracket - firstBracket - 1);
if (content == section)
state = Lookup;
}
break;
case Lookup: {
if (hasSection)
return {}; // Next section found.
const int versionIndex = line.indexOf("VERSION=");
if (versionIndex < 0)
continue;
QString version = line.mid(8);
if (version.startsWith('V'))
version.remove(0, 1);
return version;
}
break;
default:
return {};
}
}
return {};
}
QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown) QList<ToolChain *> KeilToolchainFactory::autoDetect(const QList<ToolChain *> &alreadyKnown)
{ {
#ifdef Q_OS_WIN64 #ifdef Q_OS_WIN64
static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Keil\\Products"; static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\WOW6432Node\\Microsoft\\" \
"Windows\\CurrentVersion\\Uninstall\\Keil µVision4";
#else #else
static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Keil\\Products"; static const char kRegistryNode[] = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\" \
"Windows\\CurrentVersion\\Uninstall\\Keil µVision4";
#endif #endif
struct Entry {
QString productKey;
QString subExePath;
};
// Dictionary for know toolchains.
static const std::array<Entry, 2> knowToolchains = {{
{QString("MDK"), QString("\\ARMCC\\bin\\armcc.exe")},
{QString("C51"), QString("\\BIN\\c51.exe")},
}};
Candidates candidates; Candidates candidates;
QSettings registry(kRegistryNode, QSettings::NativeFormat); QSettings registry(kRegistryNode, QSettings::NativeFormat);
const auto productGroups = registry.childGroups(); const auto productGroups = registry.childGroups();
for (const QString &productKey : productGroups) { for (const QString &productKey : productGroups) {
const Entry entry = Utils::findOrDefault(knowToolchains, if (!productKey.startsWith("App"))
[productKey](const Entry &entry) {
return entry.productKey == productKey; });
if (entry.productKey.isEmpty())
continue; continue;
registry.beginGroup(productKey); registry.beginGroup(productKey);
QString compilerPath = registry.value("Path").toString(); const FilePath productPath(FilePath::fromString(registry.value("ProductDir")
if (!compilerPath.isEmpty()) { .toString()));
// Build full compiler path. // Fetch the toolchain executable path.
compilerPath += entry.subExePath; FilePath compilerPath;
const FilePath fn = FilePath::fromString(compilerPath); if (productPath.endsWith("ARM"))
if (compilerExists(fn)) { compilerPath = productPath.pathAppended("\\ARMCC\\bin\\armcc.exe");
QString version = registry.value("Version").toString(); else if (productPath.endsWith("C51"))
if (version.startsWith('V')) compilerPath = productPath.pathAppended("\\BIN\\c51.exe");
version.remove(0, 1);
candidates.push_back({fn, version}); if (compilerPath.exists()) {
// Fetch the toolchain version.
const QDir rootDir(registry.value("Directory").toString());
const QString toolsFilePath = rootDir.absoluteFilePath("tools.ini");
for (auto index = 1; index <= 2; ++index) {
const QString section = registry.value(
QStringLiteral("Section %1").arg(index)).toString();
const QString version = extractVersion(toolsFilePath, section);
if (!version.isEmpty()) {
candidates.push_back({compilerPath, version});
break;
}
} }
} }
registry.endGroup(); registry.endGroup();

View File

@@ -2286,6 +2286,12 @@ void DebuggerEngine::openDisassemblerView(const Location &location)
void DebuggerEngine::raiseWatchersWindow() void DebuggerEngine::raiseWatchersWindow()
{ {
if (d->m_watchersView && d->m_watchersWindow) { if (d->m_watchersView && d->m_watchersWindow) {
auto currentPerspective = DebuggerMainWindow::currentPerspective();
QTC_ASSERT(currentPerspective, return);
// if a companion engine has taken over - do not raise the watchers
if (currentPerspective->name() != d->m_engine->displayName())
return;
if (auto dock = qobject_cast<QDockWidget *>(d->m_watchersWindow->parentWidget())) { if (auto dock = qobject_cast<QDockWidget *>(d->m_watchersWindow->parentWidget())) {
if (QAction *act = dock->toggleViewAction()) { if (QAction *act = dock->toggleViewAction()) {
if (!act->isChecked()) if (!act->isChecked())

View File

@@ -52,6 +52,8 @@ constexpr char kBitRange[] = "bitRange";
constexpr char kBitWidth[] = "bitWidth"; constexpr char kBitWidth[] = "bitWidth";
constexpr char kDerivedFrom[] = "derivedFrom"; constexpr char kDerivedFrom[] = "derivedFrom";
constexpr char kDescription[] = "description"; constexpr char kDescription[] = "description";
constexpr char kDevice[] = "device";
constexpr char kDisplayName[] = "displayName";
constexpr char kField[] = "field"; constexpr char kField[] = "field";
constexpr char kFields[] = "fields"; constexpr char kFields[] = "fields";
constexpr char kGroupName[] = "groupName"; constexpr char kGroupName[] = "groupName";
@@ -559,135 +561,147 @@ PeripheralRegisterHandler::PeripheralRegisterHandler(DebuggerEngine *engine)
setHeader({tr("Name"), tr("Value"), tr("Access")}); setHeader({tr("Name"), tr("Value"), tr("Access")});
} }
static PeripheralRegisterGroups availablePeripheralRegisterGroups( static void handleField(QXmlStreamReader &in, PeripheralRegister &reg)
const QString &filePath) {
PeripheralRegisterField fld;
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kName) {
fld.name = in.readElementText();
} else if (elementName == kDescription) {
fld.description = in.readElementText();
} else if (elementName == kAccess) {
fld.access = decodeAccess(in.readElementText());
} else if (elementName == kBitRange) {
const QString elementText = in.readElementText();
const int startBracket = elementText.indexOf('[');
const int endBracket = elementText.indexOf(']');
if (startBracket == -1 || endBracket == -1 || (endBracket - startBracket) <= 0)
continue;
const QString range = elementText.mid(startBracket + 1, endBracket - 1);
const QStringList items = range.split(':');
enum { MaxBit, MinBit, BitsCount };
if (items.count() != BitsCount)
continue;
const int from = int(decodeNumeric(items.at(MinBit)));
const int to = int(decodeNumeric(items.at(MaxBit)));
fld.bitOffset = from;
fld.bitWidth = to - from + 1;
} else if (elementName == kBitOffset) {
fld.bitOffset = int(decodeNumeric(in.readElementText()));
} else if (elementName == kBitWidth) {
fld.bitWidth = int(decodeNumeric(in.readElementText()));
} else {
in.skipCurrentElement();
}
}
// Inherit the field access from the register access if the filed
// has not the access rights description.
if (fld.access == PeripheralRegisterAccess::Unknown)
fld.access = reg.access;
reg.fields.push_back(fld);
}
static void handleRegister(QXmlStreamReader &in, PeripheralRegisterGroup &group)
{
PeripheralRegister reg;
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kName) {
reg.name = in.readElementText();
} else if (elementName == kDisplayName) {
reg.displayName = in.readElementText();
} else if (elementName == kDescription) {
reg.description = in.readElementText();
} else if (elementName == kAddressOffset) {
reg.addressOffset = decodeNumeric(in.readElementText());
} else if (elementName == kSize) {
reg.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == kAccess) {
reg.access = decodeAccess(in.readElementText());
} else if (elementName == kResetvalue) {
reg.resetValue = decodeNumeric(in.readElementText());
} else if (elementName == kFields) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kField)
handleField(in, reg);
else
in.skipCurrentElement();
}
} else {
in.skipCurrentElement();
}
}
group.registers.push_back(reg);
}
static void handleGroup(QXmlStreamReader &in, PeripheralRegisterGroups &groups)
{
PeripheralRegisterGroup group;
const auto fromGroupName = in.attributes().value(kDerivedFrom);
if (!fromGroupName.isEmpty()) {
const auto groupEnd = groups.cend();
const auto groupIt = std::find_if(groups.cbegin(), groupEnd,
[fromGroupName](const PeripheralRegisterGroup &group) {
return fromGroupName == group.name;
});
if (groupIt != groupEnd)
group = *groupIt;
}
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kName) {
group.name = in.readElementText();
} else if (elementName == kDescription) {
group.description = in.readElementText();
} else if (elementName == kGroupName) {
group.displayName = in.readElementText();
} else if (elementName == kBaseAddress) {
group.baseAddress = decodeNumeric(in.readElementText());
} else if (elementName == kSize) {
group.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == kAccess) {
group.access = decodeAccess(in.readElementText());
} else if (elementName == kRegisters) {
while (in.readNextStartElement()) {
const auto elementName = in.name();
if (elementName == kRegister)
handleRegister(in, group);
else
in.skipCurrentElement();
}
} else {
in.skipCurrentElement();
}
}
groups.push_back(group);
}
static PeripheralRegisterGroups availablePeripheralRegisterGroups(const QString &filePath)
{ {
QFile f(filePath); QFile f(filePath);
if (!f.open(QIODevice::ReadOnly)) if (!f.open(QIODevice::ReadOnly))
return {}; return {};
QXmlStreamReader in(&f); QXmlStreamReader in(&f);
PeripheralRegisterGroups groups;
PeripheralRegisterGroups foundGroups; while (in.readNextStartElement()) {
const auto elementName = in.name();
while (!in.atEnd()) { if (elementName == kDevice) {
const auto token = in.readNext(); while (in.readNextStartElement()) {
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kPeripherals)) {
break;
} else if (token != QXmlStreamReader::StartElement
|| in.name() != QLatin1String(kPeripheral)) {
continue;
}
PeripheralRegisterGroup group;
const auto fromGroupName = in.attributes().value(
QLatin1String(kDerivedFrom));
const auto foundGroupEnd = foundGroups.cend();
const auto foundGroupIt = std::find_if(
foundGroups.cbegin(), foundGroupEnd,
[fromGroupName](const PeripheralRegisterGroup &foundGroup) {
return fromGroupName == foundGroup.name;
});
if (foundGroupIt != foundGroupEnd)
group = *foundGroupIt;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kPeripheral)) {
foundGroups.push_back(group);
break;
} else if (token == QXmlStreamReader::StartElement) {
const auto elementName = in.name(); const auto elementName = in.name();
if (elementName == QLatin1String(kName)) { if (elementName == kPeripherals) {
group.name = in.readElementText(); while (in.readNextStartElement()) {
} else if (elementName == QLatin1String(kDescription)) { const auto elementName = in.name();
group.description = in.readElementText(); if (elementName == kPeripheral)
} else if (elementName == QLatin1String(kGroupName)) { handleGroup(in, groups);
group.displayName = in.readElementText(); else
} else if (elementName == QLatin1String(kBaseAddress)) { in.skipCurrentElement();
group.baseAddress = decodeNumeric(in.readElementText());
} else if (elementName == QLatin1String(kSize)) {
group.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == QLatin1String(kAccess)) {
group.access = decodeAccess(in.readElementText());
} else if (elementName == QLatin1String(kRegisters)
|| elementName == QLatin1String(kRegister)) {
PeripheralRegister reg;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kRegister)) {
group.registers.push_back(reg);
break;
} else if (token == QXmlStreamReader::StartElement) {
const auto elementName = in.name();
if (elementName == QLatin1String(kRegister)) {
continue;
} else if (elementName == QLatin1String(kName)) {
reg.name = in.readElementText();
} else if (elementName == QLatin1String(kDescription)) {
reg.description = in.readElementText();
} else if (elementName == QLatin1String(kAddressOffset)) {
reg.addressOffset = decodeNumeric(in.readElementText());
} else if (elementName == QLatin1String(kSize)) {
reg.size = int(decodeNumeric(in.readElementText()));
} else if (elementName == QLatin1String(kAccess)) {
reg.access = decodeAccess(in.readElementText());
} else if (elementName == QLatin1String(kResetvalue)) {
reg.resetValue = decodeNumeric(in.readElementText());
} else if (elementName == QLatin1String(kFields)
|| elementName == QLatin1String(kField)) {
PeripheralRegisterField fld;
while (!in.atEnd()) {
const auto token = in.readNext();
if (token == QXmlStreamReader::EndElement
&& in.name() == QLatin1String(kField)) {
reg.fields.push_back(fld);
break;
} else if (token == QXmlStreamReader::StartElement) {
const auto elementName = in.name();
if (elementName == QLatin1String(kField)) {
continue;
} else if (elementName == QLatin1String(kName)) {
fld.name = in.readElementText();
} else if (elementName == QLatin1String(kDescription)) {
fld.description = in.readElementText();
} else if (elementName == QLatin1String(kAccess)) {
fld.access = decodeAccess(in.readElementText());
} else if (elementName == QLatin1String(kBitRange)) {
const QString elementText = in.readElementText();
const int startBracket = elementText.indexOf('[');
const int endBracket = elementText.indexOf(']');
if (startBracket == -1 || endBracket == -1
|| (endBracket - startBracket) <= 0) {
continue;
}
const QString range = elementText.mid(
startBracket + 1, endBracket - 1);
const QStringList items = range.split(':');
enum { MaxBit, MinBit, BitsCount };
if (items.count() != BitsCount)
continue;
const int from = int(decodeNumeric(items.at(MinBit)));
const int to = int(decodeNumeric(items.at(MaxBit)));
fld.bitOffset = from;
fld.bitWidth = to - from + 1;
} else if (elementName == QLatin1String(kBitOffset)) {
fld.bitOffset = int(decodeNumeric(in.readElementText()));
} else if (elementName == QLatin1String(kBitWidth)) {
fld.bitWidth = int(decodeNumeric(in.readElementText()));
} else {
in.skipCurrentElement();
}
}
}
} else {
in.skipCurrentElement();
}
}
} }
} else { } else {
in.skipCurrentElement(); in.skipCurrentElement();
@@ -695,8 +709,7 @@ static PeripheralRegisterGroups availablePeripheralRegisterGroups(
} }
} }
} }
return groups;
return foundGroups;
} }
void PeripheralRegisterHandler::updateRegisterGroups() void PeripheralRegisterHandler::updateRegisterGroups()

View File

@@ -587,10 +587,12 @@ void GenericBuildSystem::updateDeploymentData()
hasDeploymentData = QFileInfo::exists(deploymentFilePath.toString()); hasDeploymentData = QFileInfo::exists(deploymentFilePath.toString());
} }
if (hasDeploymentData) { if (hasDeploymentData) {
DeploymentData deploymentData; if (target) {
deploymentData.addFilesFromDeploymentFile(deploymentFilePath.toString(), DeploymentData deploymentData;
projectDirectory().toString()); deploymentData.addFilesFromDeploymentFile(deploymentFilePath.toString(),
setDeploymentData(deploymentData); projectDirectory().toString());
setDeploymentData(deploymentData);
}
if (m_deployFileWatcher.files() != QStringList(deploymentFilePath.toString())) { if (m_deployFileWatcher.files() != QStringList(deploymentFilePath.toString())) {
m_deployFileWatcher.removeFiles(m_deployFileWatcher.files()); m_deployFileWatcher.removeFiles(m_deployFileWatcher.files());
m_deployFileWatcher.addFile(deploymentFilePath.toString(), m_deployFileWatcher.addFile(deploymentFilePath.toString(),

View File

@@ -913,7 +913,6 @@ bool Client::reset()
m_openedDocument.clear(); m_openedDocument.clear();
m_serverCapabilities = ServerCapabilities(); m_serverCapabilities = ServerCapabilities();
m_dynamicCapabilities.reset(); m_dynamicCapabilities.reset();
m_project = nullptr;
for (const DocumentUri &uri : m_diagnostics.keys()) for (const DocumentUri &uri : m_diagnostics.keys())
removeDiagnostics(uri); removeDiagnostics(uri);
for (TextEditor::TextDocument *document : m_resetAssistProvider.keys()) for (TextEditor::TextDocument *document : m_resetAssistProvider.keys())

View File

@@ -234,6 +234,7 @@ void SessionModel::deleteSessions(const QStringList &sessions)
return; return;
beginResetModel(); beginResetModel();
SessionManager::deleteSessions(sessions); SessionManager::deleteSessions(sessions);
m_sortedSessions = SessionManager::sessions();
endResetModel(); endResetModel();
} }

View File

@@ -179,7 +179,8 @@ void MakeInstallStep::finish(bool success)
if (success) { if (success) {
m_deploymentData = DeploymentData(); m_deploymentData = DeploymentData();
m_deploymentData.setLocalInstallRoot(installRoot()); m_deploymentData.setLocalInstallRoot(installRoot());
QDirIterator dit(installRoot().toString(), QDir::Files, QDirIterator::Subdirectories); QDirIterator dit(installRoot().toString(), QDir::Files | QDir::Hidden,
QDirIterator::Subdirectories);
while (dit.hasNext()) { while (dit.hasNext()) {
dit.next(); dit.next();
const QFileInfo fi = dit.fileInfo(); const QFileInfo fi = dit.fileInfo();

View File

@@ -70,13 +70,6 @@ def placeCursorToLine(editor, line, isRegex=False):
def menuVisibleAtEditor(editor, menuInList): def menuVisibleAtEditor(editor, menuInList):
menuInList[0] = None menuInList[0] = None
try: try:
# Hack for Squish 5.0.1 handling menus of Qt5.2 on Mac (avoids crash) - remove asap
if platform.system() == 'Darwin':
for obj in object.topLevelObjects():
if className(obj) == "QMenu" and obj.visible and widgetContainsPoint(editor, obj.mapToGlobal(QPoint(0, 0))):
menuInList[0] = obj
return True
return False
menu = waitForObject("{type='QMenu' unnamed='1' visible='1'}", 500) menu = waitForObject("{type='QMenu' unnamed='1' visible='1'}", 500)
topLeft = menu.mapToGlobal(QPoint(0, 0)) topLeft = menu.mapToGlobal(QPoint(0, 0))
bottomLeft = menu.mapToGlobal(QPoint(0, menu.height)) bottomLeft = menu.mapToGlobal(QPoint(0, menu.height))

View File

@@ -143,11 +143,7 @@ def invokeContextMenuOnProject(projectName, menuItem):
return return
openItemContextMenu(waitForObject(":Qt Creator_Utils::NavigationTreeView"), openItemContextMenu(waitForObject(":Qt Creator_Utils::NavigationTreeView"),
str(projItem.text).replace("_", "\\_").replace(".", "\\."), 5, 5, 0) str(projItem.text).replace("_", "\\_").replace(".", "\\."), 5, 5, 0)
# Hack for Squish 5.0.1 handling menus of Qt5.2 on Mac (avoids crash) - remove asap activateItem(waitForObjectItem("{name='Project.Menu.Project' type='QMenu' visible='1'}", menuItem))
if platform.system() == 'Darwin':
waitFor("macHackActivateContextMenuItem(menuItem)", 6000)
else:
activateItem(waitForObjectItem("{name='Project.Menu.Project' type='QMenu' visible='1'}", menuItem))
return projItem return projItem
def addAndActivateKit(kit): def addAndActivateKit(kit):

View File

@@ -25,33 +25,6 @@
import urllib2 import urllib2
############ functions not related to issues tracked inside jira ############
def __checkWithoutWidget__(*args):
return className(args[0]) == 'QMenu' and args[0].visible
def __checkWithWidget__(*args):
return (__checkWithoutWidget__(args[0])
and widgetContainsPoint(waitForObject(args[1]), args[0].mapToGlobal(QPoint(0 ,0))))
# hack for activating context menus on Mac because of Squish5/Qt5.2 problems
# param item a string holding the menu item to invoke (just the label)
# param widget an object; if provided there will be an additional check if the menu's top left
# corner is placed on this widget
def macHackActivateContextMenuItem(item, widget=None):
if widget:
func = __checkWithWidget__
else:
func = __checkWithoutWidget__
for obj in object.topLevelObjects():
try:
if func(obj, widget):
activateItem(waitForObjectItem(obj, item))
return True
except:
pass
return False
################ workarounds for issues tracked inside jira ################# ################ workarounds for issues tracked inside jira #################
JIRA_URL='https://bugreports.qt.io/browse' JIRA_URL='https://bugreports.qt.io/browse'

View File

@@ -96,15 +96,11 @@ def renameFile(projectDir, proFile, branch, oldname, newname):
itemWithWildcard = addBranchWildcardToRoot(itemText) itemWithWildcard = addBranchWildcardToRoot(itemText)
waitForObjectItem(treeview, itemWithWildcard, 10000) waitForObjectItem(treeview, itemWithWildcard, 10000)
openItemContextMenu(treeview, itemWithWildcard, 5, 5, 0) openItemContextMenu(treeview, itemWithWildcard, 5, 5, 0)
# hack for Squish5/Qt5.2 problems of handling menus on Mac - remove asap if oldname.lower().endswith(".qrc"):
if platform.system() == 'Darwin': menu = ":Qt Creator.Project.Menu.Folder_QMenu"
waitFor("macHackActivateContextMenuItem('Rename...')", 5000)
else: else:
if oldname.lower().endswith(".qrc"): menu = ":Qt Creator.Project.Menu.File_QMenu"
menu = ":Qt Creator.Project.Menu.Folder_QMenu" activateItem(waitForObjectItem(menu, "Rename..."))
else:
menu = ":Qt Creator.Project.Menu.File_QMenu"
activateItem(waitForObjectItem(menu, "Rename..."))
replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit") replaceEdit = waitForObject(":Qt Creator_Utils::NavigationTreeView::QExpandingLineEdit")
test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0], test.compare(replaceEdit.selectedText, oldname.rsplit(".", 1)[0],
"Only the filename without the extension is selected?") "Only the filename without the extension is selected?")

View File

@@ -75,12 +75,9 @@ def generateMockTasksFile():
def checkOrUncheckMyTasks(): def checkOrUncheckMyTasks():
filterButton = waitForObject(toolButton % 'Filter by categories') filterButton = waitForObject(toolButton % 'Filter by categories')
clickButton(filterButton) clickButton(filterButton)
if platform.system() == 'Darwin': activateItem(waitForObjectItem("{type='QMenu' unnamed='1' visible='1' "
waitFor("macHackActivateContextMenuItem('My Tasks')", 5000) "window=':Qt Creator_Core::Internal::MainWindow'}",
else: "My Tasks"))
activateItem(waitForObjectItem("{type='QMenu' unnamed='1' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}",
"My Tasks"))
def getBuildIssuesTypeCounts(model): def getBuildIssuesTypeCounts(model):
issueTypes = map(lambda x: x.data(Qt.UserRole + 5).toInt(), dumpIndices(model)) issueTypes = map(lambda x: x.data(Qt.UserRole + 5).toInt(), dumpIndices(model))

View File

@@ -38,11 +38,7 @@ def main():
if buttonName: if buttonName:
openContextMenu(waitForObject("{container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack'" openContextMenu(waitForObject("{container=':*Qt Creator.FormEditorStack_Designer::Internal::FormEditorStack'"
"text='PushButton' type='QPushButton' visible='1'}"), 5, 5, 1) "text='PushButton' type='QPushButton' visible='1'}"), 5, 5, 1)
# hack for Squish5/Qt5.2 problems of handling menus on Mac - remove asap activateItem(waitForObjectItem("{type='QMenu' unnamed='1' visible='1'}", "Change objectName..."))
if platform.system() == 'Darwin':
waitFor("macHackActivateContextMenuItem('Change objectName...')", 6000)
else:
activateItem(waitForObjectItem("{type='QMenu' unnamed='1' visible='1'}", "Change objectName..."))
typeLines(waitForObject(":FormEditorStack_qdesigner_internal::PropertyLineEdit"), buttonName) typeLines(waitForObject(":FormEditorStack_qdesigner_internal::PropertyLineEdit"), buttonName)
else: else:
# Verify that everything works without ever changing the name # Verify that everything works without ever changing the name

View File

@@ -45,11 +45,7 @@ def main():
selectFromLocator("mainwindow.ui") selectFromLocator("mainwindow.ui")
openContextMenu(waitForObject(con[0]), 5, 5, 0) openContextMenu(waitForObject(con[0]), 5, 5, 0)
snooze(1) snooze(1)
# hack for Squish 5/Qt5.2 problems of handling menus on Mac - remove asap activateItem(waitForObjectItem("{type='QMenu' unnamed='1' visible='1'}", "Go to slot..."))
if platform.system() == 'Darwin':
waitFor("macHackActivateContextMenuItem('Go to slot...', con[0])", 6000)
else:
activateItem(waitForObjectItem("{type='QMenu' unnamed='1' visible='1'}", "Go to slot..."))
signalWidgetObject = waitForObject(":Select signal.signalList_QTreeView") signalWidgetObject = waitForObject(":Select signal.signalList_QTreeView")
signalName = con[1] + "." + con[2] signalName = con[1] + "." + con[2]
mouseClick(waitForObjectItem(signalWidgetObject, signalName), 5, 5, 0, Qt.LeftButton) mouseClick(waitForObjectItem(signalWidgetObject, signalName), 5, 5, 0, Qt.LeftButton)

View File

@@ -138,7 +138,6 @@ SOURCES += \
clangdocumentprocessors-test.cpp \ clangdocumentprocessors-test.cpp \
clangdocumentprocessor-test.cpp \ clangdocumentprocessor-test.cpp \
clangdocuments-test.cpp \ clangdocuments-test.cpp \
clangdocumentsuspenderresumer-test.cpp \
clangdocument-test.cpp \ clangdocument-test.cpp \
clangfixitoperation-test.cpp \ clangfixitoperation-test.cpp \
clangfollowsymbol-test.cpp \ clangfollowsymbol-test.cpp \
@@ -146,7 +145,6 @@ SOURCES += \
clangjobqueue-test.cpp \ clangjobqueue-test.cpp \
clangjobs-test.cpp \ clangjobs-test.cpp \
clangparsesupportivetranslationunitjob-test.cpp \ clangparsesupportivetranslationunitjob-test.cpp \
clangreferencescollector-test.cpp \
clangrequestannotationsjob-test.cpp \ clangrequestannotationsjob-test.cpp \
clangrequestreferencesjob-test.cpp \ clangrequestreferencesjob-test.cpp \
clangresumedocumentjob-test.cpp \ clangresumedocumentjob-test.cpp \
@@ -177,7 +175,6 @@ SOURCES += \
sqlitetable-test.cpp \ sqlitetable-test.cpp \
sqlstatementbuilder-test.cpp \ sqlstatementbuilder-test.cpp \
token-test.cpp \ token-test.cpp \
tokenprocessor-test.cpp \
translationunitupdater-test.cpp \ translationunitupdater-test.cpp \
unsavedfiles-test.cpp \ unsavedfiles-test.cpp \
unsavedfile-test.cpp \ unsavedfile-test.cpp \
@@ -187,9 +184,11 @@ SOURCES += \
!isEmpty(LIBTOOLING_LIBS) { !isEmpty(LIBTOOLING_LIBS) {
SOURCES += \ SOURCES += \
gtest-llvm-printing.cpp \ gtest-llvm-printing.cpp \
clangdocumentsuspenderresumer-test.cpp \
clangquerygatherer-test.cpp \ clangquerygatherer-test.cpp \
clangqueryprojectfindfilter-test.cpp \ clangqueryprojectfindfilter-test.cpp \
clangquery-test.cpp \ clangquery-test.cpp \
clangreferencescollector-test.cpp \
gtest-clang-printing.cpp \ gtest-clang-printing.cpp \
pchcreator-test.cpp \ pchcreator-test.cpp \
refactoringclientserverinprocess-test.cpp \ refactoringclientserverinprocess-test.cpp \
@@ -202,7 +201,8 @@ SOURCES += \
symbolscollector-test.cpp \ symbolscollector-test.cpp \
testclangtool.cpp \ testclangtool.cpp \
usedmacrocollector-test.cpp \ usedmacrocollector-test.cpp \
builddependencycollector-test.cpp builddependencycollector-test.cpp \
tokenprocessor-test.cpp
} }
!isEmpty(CLANGFORMAT_LIBS) { !isEmpty(CLANGFORMAT_LIBS) {