Merge remote-tracking branch 'origin/7.0'

Change-Id: I809383e6c060701a2751197a8bf16add92bfaf0d
This commit is contained in:
Eike Ziller
2022-02-28 09:21:18 +01:00
43 changed files with 579 additions and 272 deletions

View File

@@ -68,10 +68,14 @@ if (Qt5_VERSION VERSION_LESS 6.0.0)
endif()
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU)
add_compile_options(-Wno-missing-field-initializers)
endif()
endif()
else()
# Common intermediate directory for QML modules which are defined via qt_add_qml_module()
set(QT_QML_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/qml_modules")
# This includes the code that will enable higher compiler warnings level (/W3 for MSVC, -Wall -Wextra for GCC)
# This is controlled by QT_COMPILE_OPTIONS_DISABLE_WARNINGS target property.
include(QtCompilerFlags)
endif()
find_package(Qt5 COMPONENTS LinguistTools QUIET)
find_package(Qt5 COMPONENTS Quick QuickWidgets Designer DesignerComponents Help SerialPort Svg Tools QUIET)

View File

@@ -233,6 +233,7 @@ function(add_qtc_library name)
RUNTIME_OUTPUT_DIRECTORY "${_output_binary_dir}/${_DESTINATION}"
LIBRARY_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_LIBRARY_PATH}"
ARCHIVE_OUTPUT_DIRECTORY "${_output_binary_dir}/${IDE_LIBRARY_ARCHIVE_PATH}"
QT_COMPILE_OPTIONS_DISABLE_WARNINGS OFF
${_arg_PROPERTIES}
)
@@ -485,6 +486,7 @@ function(add_qtc_plugin target_name)
RUNTIME_OUTPUT_DIRECTORY "${_output_binary_dir}/${plugin_dir}"
OUTPUT_NAME "${name}"
QT_SKIP_TRANSLATION "${skip_translation}"
QT_COMPILE_OPTIONS_DISABLE_WARNINGS OFF
${_arg_PROPERTIES}
)
@@ -667,6 +669,7 @@ function(add_qtc_executable name)
CXX_EXTENSIONS OFF
CXX_VISIBILITY_PRESET hidden
VISIBILITY_INLINES_HIDDEN ON
QT_COMPILE_OPTIONS_DISABLE_WARNINGS OFF
${_arg_PROPERTIES}
)
if (NOT _arg_SKIP_PCH)

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2018 The Qt Company Ltd.
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -113,6 +113,10 @@
\li Open files in editors in a running \QC instance and block the
command line until the first editor is closed.
\row
\li -nocrashcheck
\li Disable the startup check for a previously crashed \QC instance.
\row
\li -load <plugin>
\li Enable the specified plugin and all plugins that it depends on.
@@ -122,7 +126,7 @@
\row
\li -load all
\li Enables all plugins.
\li Enable all plugins.
\row
\li -noload <plugin>
@@ -130,11 +134,11 @@
\row
\li -noload all
\li Disables all plugins.
\li Disable all plugins.
\row
\li -profile
\li Output plugin start up and shut down profiling data.
\li Output profiling data about plugin startup and shutdown.
\row
\li -pluginpath <path>
@@ -151,10 +155,28 @@
(for example written by the installer).
\row
\li -temporarycleansettings
\li -temporarycleansettings, -tcs
\li Use clean settings for debug or testing reasons. The settings
will be deleted when \QC exits.
\row
\li -test <plugin>[,testfunction[:testdata]] ...
\li For \QC plugin developers: run the plugin's tests using a
separate settings path by default.
\row
\li -test all
\li For \QC plugin developers: run tests from all plugins.
\row
\li -notest <plugin>
\li For \QC plugin developers: exclude all of the plugin's
tests from the test run.
\row
\li -scenario <scenarioname>
\li For \QC plugin developers: run the specified scenario.
\row
\li -color <color>
\li Core plugin: override the selected UI color.
@@ -171,7 +193,7 @@
\row
\li -notour
\li Welcome plugin: Skip the UI tour on startup.
\li Welcome plugin: skip the UI tour on startup.
\row
\li -debug <pid>
@@ -208,9 +230,13 @@
\row
\li -wincrashevent <event-handle:pid>
\li Debugger plugin: Attach to crashed processes by using the
\li Debugger plugin: attach to crashed processes by using the
specified event handle and process ID.
\row
\li -git-show <git commit hash>
\li Git plugin: show the specified commit hash.
\row
\li -customwizard-verbose
\li ProjectExplorer plugin: display additional information when

View File

@@ -176,7 +176,7 @@
"trDescription": "Creates a C++ header and a source file for a new class that you can add to a C++ project.",
"trDisplayName": "C++ Class",
"trDisplayCategory": "C++",
"icon": "../../global/genericfilewizard.png",
"iconText": "h/cpp",
"enabled": "%{JS: value('Plugins').indexOf('CppEditor') >= 0}",
\endcode
@@ -203,7 +203,13 @@
\li \c icon appears next to the \c trDisplayName in the middle
panel when \c trDisplayCategory is selected. We recommend
that you specify the path relative to the wizard.json file,
but you can also use an absolute path.
but you can also use an absolute path. Omit this value to
use the default icon for the wizard type.
\li \c iconText determines the text overlay for the default
file icon.
\li \c iconKind determines whether the icon is themed.
\li \c image specifies a path to an image (for example a
screenshot) that appears below the \c trDescription.
@@ -281,8 +287,12 @@
"trDisplayName": "Class name:",
"mandatory": true,
"type": "LineEdit",
"data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)+[a-zA-Z_][a-zA-Z_0-9]*|)" }
},
"data": {
"trPlaceholder": "Fully qualified name, including namespaces",
"validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*|)",
"completion": "namespaces"
}
},
...
]
\endcode
@@ -335,11 +345,19 @@
"source": "file.h",
"target": "%{HdrPath}",
"openInEditor": true
"options": [
{ "key": "Cpp:License:FileName", "value": "%{HdrFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
},
{
"source": "file.cpp",
"target": "%{SrcPath}",
"openInEditor": true
"options": [
{ "key": "Cpp:License:FileName", "value": "%{SrcFileName}" },
{ "key": "Cpp:License:ClassName", "value": "%{CN}" }
]
}
]
\endcode
@@ -410,7 +428,11 @@
"trDisplayName": "Class name:",
"mandatory": true,
"type": "LineEdit",
"data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)+[a-zA-Z_][a-zA-Z_0-9]*|)" }
"data": {
"trPlaceholder": "Fully qualified name, including namespaces",
"validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*|)",
"completion": "namespaces"
}
},
...
],
@@ -776,7 +798,11 @@
"trDisplayName": "Class name:",
"mandatory": true,
"type": "LineEdit",
"data": { "validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)+[a-zA-Z_][a-zA-Z_0-9]*|)" }
"data": {
"trPlaceholder": "Fully qualified name, including namespaces",
"validator": "(?:(?:[a-zA-Z_][a-zA-Z_0-9]*::)*[a-zA-Z_][a-zA-Z_0-9]*|)",
"completion": "namespaces"
}
},
{
"name": "BaseEdit",
@@ -787,8 +813,7 @@
{
"trText": "%{BaseCB}",
"trDisabledText": "%{BaseCB}",
"historyId": "EditValues",
"restoreLastHistoryItem": false
"completion": "classes"
}
},
\endcode
@@ -799,6 +824,11 @@
\li \c trDisabledText specifies the text to display in a disabled field.
\li \c completion lists existing \c namespaces for the class name line
edit and existing \c classes for the base class line edit. This
value replaces the history completer that is usually available for
such fields.
\li \c trPlaceholder specifies the placeholder text.
\li \c validator specifies a QRegularExpression to validate the line
@@ -812,7 +842,8 @@
contains a password, which will be masked.
\li \c historyId is a key that specifies the name for a list of items
for the history completer.
for the history completer. This value and \c completion are
mutually exclusive, so do not set both of them at the same time.
\li \c restoreLastHistoryItem is a boolean that specifies that the
last history item is automatically set as the default text in

View File

@@ -37,6 +37,7 @@ Usage:
"""
import os, sys, string
import platform
import subprocess
from xml.sax import saxutils, handler, make_parser

View File

@@ -56,6 +56,8 @@
#include <QUrl>
#include <QVariant>
#include <QSysInfo>
#include <QNetworkProxyFactory>
#include <QApplication>
@@ -410,6 +412,11 @@ QStringList lastSessionArgument()
#ifdef ENABLE_CRASHPAD
bool startCrashpad(const QString &libexecPath, bool crashReportingEnabled)
{
if (QSysInfo::currentCpuArchitecture() == "arm64") {
qDebug() << "The crashpad_handler binary does not work on arm64 properly. So it is disabled for now.";
return false;
}
using namespace crashpad;
// Cache directory that will store crashpad information and minidumps

View File

@@ -454,14 +454,21 @@ FilePath FilePath::fromUrl(const QUrl &url)
return fn;
}
static QString hostEncoded(QString host)
{
host.replace('%', "%25");
host.replace('/', "%2f");
return host;
}
/// \returns a QString for passing on to QString based APIs
QString FilePath::toString() const
{
if (m_scheme.isEmpty())
return m_data;
if (m_data.startsWith('/'))
return m_scheme + "://" + m_host + m_data;
return m_scheme + "://" + m_host + "/./" + m_data;
return m_scheme + "://" + hostEncoded(m_host) + m_data;
return m_scheme + "://" + hostEncoded(m_host) + "/./" + m_data;
}
QUrl FilePath::toUrl() const
@@ -595,7 +602,6 @@ void FilePath::setScheme(const QString &scheme)
void FilePath::setHost(const QString &host)
{
QTC_CHECK(!host.contains('/'));
m_host = host;
}
@@ -943,6 +949,8 @@ void FilePath::setFromString(const QString &filename)
m_data = filename.mid(pos1);
} else {
m_host = filename.mid(pos1, pos2 - pos1);
m_host.replace("%2f", "/");
m_host.replace("%25", "%");
m_data = filename.mid(pos2);
}
if (m_data.startsWith("/./"))

View File

@@ -105,7 +105,6 @@ public:
bool endsWith(const QString &s) const;
bool exists() const;
bool needsDevice() const;
FilePath parentDir() const;
bool isChildOf(const FilePath &s) const;
@@ -191,6 +190,13 @@ public:
qint64 maxSize = -1, qint64 offset = 0) const;
void asyncWriteFileContents(const Continuation<bool> &cont, const QByteArray &data) const;
// Prefer not to use
// Using needsDevice() in "user" code is likely to result in code that
// makes a local/remote distinction which should be avoided in general.
// There are usually other means available. E.g. distinguishing based
// on FilePath::osType().
bool needsDevice() const;
// Deprecated.
[[nodiscard]] static FilePath fromFileInfo(const QFileInfo &info); // Avoid.
[[nodiscard]] QFileInfo toFileInfo() const; // Avoid.
@@ -205,7 +211,7 @@ private:
[[nodiscard]] QString mapToDevicePath() const;
QString m_scheme;
QString m_host;
QString m_host; // May contain raw slashes.
QString m_data;
};

View File

@@ -1410,10 +1410,10 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
setDocumentChangeUpdateThreshold(d->settings.documentUpdateThreshold);
const auto textMarkCreator = [this](const Utils::FilePath &filePath,
const Diagnostic &diag) {
const Diagnostic &diag, bool isProjectFile) {
if (d->isTesting)
emit textMarkCreated(filePath);
return new ClangdTextMark(filePath, diag, this);
return new ClangdTextMark(filePath, diag, isProjectFile, this);
};
const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); };
setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler);
@@ -2652,6 +2652,7 @@ private:
int posForNodeStart(const AstNode &node) const;
int posForNodeEnd(const AstNode &node) const;
void insertResult(const HighlightingResult &result);
void insertResult(const AstNode &node, TextStyle style);
void insertAngleBracketInfo(int searchStart1, int searchEnd1, int searchStart2, int searchEnd2);
void setResultPosFromRange(HighlightingResult &result, const Range &range);
void collectFromNode(const AstNode &node);
@@ -3619,6 +3620,16 @@ void ExtraHighlightingResultsCollector::insertResult(const HighlightingResult &r
}
}
void ExtraHighlightingResultsCollector::insertResult(const AstNode &node, TextStyle style)
{
HighlightingResult result;
result.useTextSyles = true;
result.textStyles.mainStyle = style;
setResultPosFromRange(result, node.range());
insertResult(result);
return;
}
// For matching the "<" and ">" brackets of template declarations, specializations
// and instantiations.
void ExtraHighlightingResultsCollector::insertAngleBracketInfo(int searchStart1, int searchEnd1,
@@ -3673,37 +3684,30 @@ void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
if (node.kind() == "UserDefinedLiteral")
return;
if (node.kind().endsWith("Literal")) {
HighlightingResult result;
result.useTextSyles = true;
const bool isKeyword = node.kind() == "CXXBoolLiteral"
|| node.kind() == "CXXNullPtrLiteral";
const bool isStringLike = !isKeyword && (node.kind().startsWith("String")
|| node.kind().startsWith("Character"));
result.textStyles.mainStyle = isKeyword ? C_KEYWORD : isStringLike ? C_STRING : C_NUMBER;
setResultPosFromRange(result, node.range());
insertResult(result);
const TextStyle style = isKeyword ? C_KEYWORD : isStringLike ? C_STRING : C_NUMBER;
insertResult(node, style);
return;
}
if (node.role() == "type" && node.kind() == "Builtin") {
HighlightingResult result;
result.useTextSyles = true;
result.textStyles.mainStyle = C_PRIMITIVE_TYPE;
setResultPosFromRange(result, node.range());
insertResult(result);
insertResult(node, C_PRIMITIVE_TYPE);
return;
}
if (node.role() == "attribute" && (node.kind() == "Override" || node.kind() == "Final")) {
HighlightingResult result;
result.useTextSyles = true;
result.textStyles.mainStyle = C_KEYWORD;
setResultPosFromRange(result, node.range());
insertResult(result);
insertResult(node, C_KEYWORD);
return;
}
const bool isExpression = node.role() == "expression";
const bool isDeclaration = node.role() == "declaration";
if (isExpression && node.kind() == "Predefined") {
insertResult(node, C_PREPROCESSOR);
return;
}
const bool isDeclaration = node.role() == "declaration";
const int nodeStartPos = posForNodeStart(node);
const int nodeEndPos = posForNodeEnd(node);
const QList<AstNode> children = node.children().value_or(QList<AstNode>());

View File

@@ -385,6 +385,7 @@ ClangBackEnd::DiagnosticContainer convertDiagnostic(const ClangdDiagnostic &src,
ClangdTextMark::ClangdTextMark(const FilePath &filePath,
const Diagnostic &diagnostic,
bool isProjectFile,
const Client *client)
: TextEditor::TextMark(filePath, int(diagnostic.range().start().line() + 1), client->id())
, m_lspDiagnostic(diagnostic)
@@ -399,18 +400,13 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
setPriority(isError ? TextEditor::TextMark::HighPriority
: TextEditor::TextMark::NormalPriority);
setIcon(isError ? Icons::CODEMODEL_ERROR.icon() : Icons::CODEMODEL_WARNING.icon());
if (client->project()) {
if (isProjectFile) {
setLineAnnotation(diagnostic.message());
setColor(isError ? Theme::CodeModel_Error_TextMarkColor
: Theme::CodeModel_Warning_TextMarkColor);
ClangDiagnosticManager::addTask(m_diagnostic);
}
m_clientDeleted = QObject::connect(client, &QObject::destroyed, [this] (){
QTC_ASSERT_STRING("ClangdClient deleted before TextMark");
delete this;
});
// Copy to clipboard action
QVector<QAction *> actions;
QAction *action = new QAction();
@@ -438,11 +434,6 @@ ClangdTextMark::ClangdTextMark(const FilePath &filePath,
setActions(actions);
}
ClangdTextMark::~ClangdTextMark()
{
QObject::disconnect(m_clientDeleted);
}
bool ClangdTextMark::addToolTipContent(QLayout *target) const
{
const auto canApplyFixIt = [c = m_client, diag = m_lspDiagnostic, fp = fileName()] {

View File

@@ -72,8 +72,8 @@ class ClangdTextMark : public TextEditor::TextMark
public:
ClangdTextMark(const ::Utils::FilePath &filePath,
const LanguageServerProtocol::Diagnostic &diagnostic,
bool isProjectFile,
const LanguageClient::Client *client);
~ClangdTextMark();
private:
bool addToolTipContent(QLayout *target) const override;
@@ -81,8 +81,6 @@ private:
const LanguageServerProtocol::Diagnostic m_lspDiagnostic;
const ClangBackEnd::DiagnosticContainer m_diagnostic;
const QPointer<const LanguageClient::Client> m_client;
QMetaObject::Connection m_clientDeleted;
};
} // namespace Internal

View File

@@ -1302,6 +1302,12 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_FIELD} << 0;
QTest::newRow("output arg") << 945 << 20 << 945 << 23
<< QList<int>{C_LOCAL, C_OUTPUT_ARGUMENT} << 0;
QTest::newRow("built-in define 1") << 950 << 21 << 950 << 29
<< QList<int>{C_PREPROCESSOR} << 0;
QTest::newRow("built-in define 2") << 951 << 21 << 951 << 33
<< QList<int>{C_PREPROCESSOR} << 0;
QTest::newRow("built-in define 3") << 952 << 21 << 952 << 40
<< QList<int>{C_PREPROCESSOR} << 0;
}
void ClangdTestHighlighting::test()

View File

@@ -944,3 +944,10 @@ void inputsAndOutputsFromObject(const WithVector &s)
std::vector<int> out;
transform(s.v, out, [] {});
}
void builtinDefines()
{
const auto f1 = __func__;
const auto f2 = __FUNCTION__;
const auto f3 = __PRETTY_FUNCTION__;
}

View File

@@ -120,7 +120,7 @@ BaseEditorDocumentParser::Ptr BaseEditorDocumentParser::get(const QString &fileP
ProjectPartInfo BaseEditorDocumentParser::determineProjectPart(const QString &filePath,
const QString &preferredProjectPartId,
const ProjectPartInfo &currentProjectPartInfo,
const ProjectExplorer::Project *activeProject,
const Utils::FilePath &activeProject,
Utils::Language languagePreference,
bool projectsUpdated)
{

View File

@@ -30,6 +30,8 @@
#include "cppworkingcopy.h"
#include "projectpart.h"
#include <projectexplorer/project.h>
#include <QFutureInterface>
#include <QObject>
#include <QMutex>
@@ -65,14 +67,14 @@ public:
Utils::Language languagePreference,
bool projectsUpdated)
: workingCopy(workingCopy)
, activeProject(activeProject)
, activeProject(activeProject ? activeProject->projectFilePath() : Utils::FilePath())
, languagePreference(languagePreference)
, projectsUpdated(projectsUpdated)
{
}
WorkingCopy workingCopy;
const ProjectExplorer::Project *activeProject = nullptr;
const Utils::FilePath activeProject;
Utils::Language languagePreference = Utils::Language::Cxx;
bool projectsUpdated = false;
};
@@ -104,7 +106,7 @@ protected:
static ProjectPartInfo determineProjectPart(const QString &filePath,
const QString &preferredProjectPartId,
const ProjectPartInfo &currentProjectPartInfo,
const ProjectExplorer::Project *activeProject,
const Utils::FilePath &activeProject,
Utils::Language languagePreference,
bool projectsUpdated);

View File

@@ -46,7 +46,7 @@ public:
ProjectPartPrioritizer(const QList<ProjectPart::ConstPtr> &projectParts,
const QString &preferredProjectPartId,
const ProjectExplorer::Project *activeProject,
const Utils::FilePath &activeProject,
Language languagePreference,
bool areProjectPartsFromDependencies)
: m_preferredProjectPartId(preferredProjectPartId)
@@ -124,7 +124,7 @@ private:
private:
const QString m_preferredProjectPartId;
const ProjectExplorer::Project *m_activeProject = nullptr;
const Utils::FilePath m_activeProject;
Language m_languagePreference = Language::Cxx;
// Results
@@ -134,7 +134,7 @@ private:
ProjectPartInfo ProjectPartChooser::choose(const QString &filePath,
const ProjectPartInfo &currentProjectPartInfo,
const QString &preferredProjectPartId,
const ProjectExplorer::Project *activeProject,
const Utils::FilePath &activeProject,
Language languagePreference,
bool projectsUpdated) const
{

View File

@@ -50,7 +50,7 @@ public:
ProjectPartInfo choose(const QString &filePath,
const ProjectPartInfo &currentProjectPartInfo,
const QString &preferredProjectPartId,
const ProjectExplorer::Project *activeProject,
const Utils::FilePath &activeProject,
Utils::Language languagePreference,
bool projectsUpdated) const;

View File

@@ -60,8 +60,11 @@ public:
const ProjectPartInfo choose()
{
const Project * const project = projectMap.value(activeProject).get();
const Utils::FilePath projectFilePath = project ? project->projectFilePath()
: Utils::FilePath();
return chooser.choose(filePath, currentProjectPartInfo, preferredProjectPartId,
projectMap.value(activeProject).get(),
projectFilePath,
languagePreference, projectsChanged);
}

View File

@@ -57,7 +57,12 @@ QString ProjectPart::projectFileLocation() const
bool ProjectPart::belongsToProject(const ProjectExplorer::Project *project) const
{
return project ? topLevelProject == project->projectFilePath() : !hasProject();
return belongsToProject(project ? project->projectFilePath() : Utils::FilePath());
}
bool ProjectPart::belongsToProject(const Utils::FilePath &project) const
{
return topLevelProject == project;
}
QByteArray ProjectPart::readProjectConfigFile(const QString &projectConfigFile)

View File

@@ -75,6 +75,7 @@ public:
QString projectFileLocation() const;
bool hasProject() const { return !topLevelProject.isEmpty(); }
bool belongsToProject(const ProjectExplorer::Project *project) const;
bool belongsToProject(const Utils::FilePath &project) const;
static QByteArray readProjectConfigFile(const QString &projectConfigFile);

View File

@@ -363,11 +363,11 @@ public:
};
connect(autoDetectButton, &QPushButton::clicked, this,
[this, logView, data, dockerDevice, searchPaths] {
[this, logView, dockerDevice, searchPaths] {
logView->clear();
dockerDevice->updateContainerAccess();
m_kitItemDetector.autoDetect(data.autodetectId(), searchPaths());
m_kitItemDetector.autoDetect(dockerDevice->id().toString(), searchPaths());
if (DockerPlugin::isDaemonRunning().value_or(false) == false)
logView->append(tr("Docker daemon appears to be not running."));
@@ -376,14 +376,14 @@ public:
updateDaemonStateTexts();
});
connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, data] {
connect(undoAutoDetectButton, &QPushButton::clicked, this, [this, logView, device] {
logView->clear();
m_kitItemDetector.undoAutoDetect(data.autodetectId());
m_kitItemDetector.undoAutoDetect(device->id().toString());
});
connect(listAutoDetectedButton, &QPushButton::clicked, this, [this, logView, data] {
connect(listAutoDetectedButton, &QPushButton::clicked, this, [this, logView, device] {
logView->clear();
m_kitItemDetector.listAutoDetected(data.autodetectId());
m_kitItemDetector.listAutoDetected(device->id().toString());
});
using namespace Layouting;
@@ -458,7 +458,7 @@ Tasks DockerDevice::validate() const
// DockerDeviceData
QString DockerDeviceData::dockerId() const
QString DockerDeviceData::repoAndTag() const
{
if (repo == "<none>")
return imageId;
@@ -479,7 +479,7 @@ DockerDevice::DockerDevice(const DockerDeviceData &data)
setDisplayType(tr("Docker"));
setOsType(OsTypeOtherUnix);
setDefaultDisplayName(tr("Docker Image"));;
setDisplayName(tr("Docker Image \"%1\" (%2)").arg(data.dockerId()).arg(data.imageId));
setDisplayName(tr("Docker Image \"%1\" (%2)").arg(data.repoAndTag()).arg(data.imageId));
setAllowEmptyCommand(true);
setOpenTerminal([this](const Environment &env, const FilePath &workingDir) {
@@ -829,7 +829,7 @@ void DockerDevicePrivate::startContainer()
dockerCreate.addArgs({"-v", q->debugDumperPath().toUserOutput() + ':' + dumperPath.path()});
q->setDebugDumperPath(dumperPath);
dockerCreate.addArgs({"--entrypoint", "/bin/sh", m_data.dockerId()});
dockerCreate.addArgs({"--entrypoint", "/bin/sh", m_data.repoAndTag()});
LOG("RUNNING: " << dockerCreate.toUserOutput());
QtcProcess createProcess;
@@ -980,10 +980,20 @@ FilePath DockerDevice::mapToGlobalPath(const FilePath &pathOnDevice) const
QTC_CHECK(handlesFile(pathOnDevice));
return pathOnDevice;
}
FilePath result;
result.setScheme("docker");
result.setHost(d->m_data.dockerId());
result.setPath(pathOnDevice.path());
result.setScheme("docker");
result.setHost(d->m_data.repoAndTag());
// The following would work, but gives no hint on repo and tag
// result.setScheme("docker");
// result.setHost(d->m_data.imageId);
// The following would work, but gives no hint on repo, tag and imageid
// result.setScheme("device");
// result.setHost(id().toString());
return result;
}
@@ -1002,7 +1012,13 @@ QString DockerDevice::mapToDevicePath(const Utils::FilePath &globalPath) const
bool DockerDevice::handlesFile(const FilePath &filePath) const
{
return filePath.scheme() == "docker" && filePath.host() == d->m_data.dockerId();
if (filePath.scheme() == "device" && filePath.host() == id().toString())
return true;
if (filePath.scheme() == "docker" && filePath.host() == d->m_data.imageId)
return true;
if (filePath.scheme() == "docker" && filePath.host() == d->m_data.repo + ':' + d->m_data.tag)
return true;
return false;
}
bool DockerDevice::isExecutableFile(const FilePath &filePath) const
@@ -1385,7 +1401,7 @@ Environment DockerDevice::systemEnvironment() const
void DockerDevice::aboutToBeRemoved() const
{
KitDetector detector(sharedFromThis());
detector.undoAutoDetect(d->m_data.autodetectId());
detector.undoAutoDetect(id().toString());
}
void DockerDevicePrivate::fetchSystemEnviroment()
@@ -1589,7 +1605,7 @@ public:
QTC_ASSERT(item, return {});
auto device = DockerDevice::create(*item);
device->setupId(IDevice::ManuallyAdded, Id::fromString(item->autodetectId()));
device->setupId(IDevice::ManuallyAdded);
device->setType(Constants::DOCKER_DEVICE_TYPE);
device->setMachineType(IDevice::Hardware);

View File

@@ -37,10 +37,8 @@ namespace Internal {
class DockerDeviceData
{
public:
// Used for "docker run" and for host parts of FilePaths
QString dockerId() const;
// Used as autodetection source string
QString autodetectId() const { return "docker:" + dockerId(); }
// Used for "docker run"
QString repoAndTag() const;
QString imageId;
QString repo;

View File

@@ -28,6 +28,7 @@
#include "client.h"
#include <coreplugin/editormanager/documentmodel.h>
#include <projectexplorer/project.h>
#include <texteditor/fontsettings.h>
#include <texteditor/textdocument.h>
#include <texteditor/texteditor.h>
@@ -74,7 +75,7 @@ private:
DiagnosticManager::DiagnosticManager(Client *client)
: m_client(client)
{
m_textMarkCreator = [this](const FilePath &filePath, const Diagnostic &diagnostic) {
m_textMarkCreator = [this](const FilePath &filePath, const Diagnostic &diagnostic, bool /*isProjectFile*/) {
return createTextMark(filePath, diagnostic);
};
}
@@ -125,9 +126,11 @@ void DiagnosticManager::showDiagnostics(const DocumentUri &uri, int version)
QList<QTextEdit::ExtraSelection> extraSelections;
const VersionedDiagnostics &versionedDiagnostics = m_diagnostics.value(uri);
if (versionedDiagnostics.version.value_or(version) == version) {
const bool isProjectFile = m_client->project()
&& m_client->project()->isKnownFile(filePath);
for (const Diagnostic &diagnostic : versionedDiagnostics.diagnostics) {
extraSelections << toDiagnosticsSelections(diagnostic, doc->document());
m_marks[filePath].append(m_textMarkCreator(filePath, diagnostic));
m_marks[filePath].append(m_textMarkCreator(filePath, diagnostic, isProjectFile));
}
}

View File

@@ -43,7 +43,7 @@ namespace LanguageClient {
class Client;
using TextMarkCreator = std::function<TextEditor::TextMark *(const Utils::FilePath &,
const LanguageServerProtocol::Diagnostic &)>;
const LanguageServerProtocol::Diagnostic &, bool)>;
using HideDiagnosticsHandler = std::function<void()>;
class DiagnosticManager

View File

@@ -366,6 +366,15 @@ bool DeviceManager::isLoaded() const
IDevice::ConstPtr DeviceManager::deviceForPath(const FilePath &path)
{
const QList<IDevice::Ptr> devices = instance()->d->deviceList();
if (path.scheme() == "device") {
for (const IDevice::Ptr &dev : devices) {
if (path.host() == dev->id().toString())
return dev;
}
return {};
}
for (const IDevice::Ptr &dev : devices) {
// TODO: ensure handlesFile is thread safe
if (dev->handlesFile(path))

View File

@@ -697,7 +697,7 @@ void GccToolChain::addToEnvironment(Environment &env) const
{
// On Windows gcc invokes cc1plus which is in libexec directory.
// cc1plus depends on libwinpthread-1.dll which is in bin, so bin must be in the PATH.
if (HostOsInfo::isWindowsHost())
if (compilerCommand().osType() == OsTypeWindows)
addCommandPathToEnvironment(compilerCommand(), env);
}
@@ -1229,7 +1229,7 @@ Toolchains GccToolChainFactory::autoDetectToolChain(const ToolChainDescription &
{
Toolchains result;
Environment systemEnvironment = Environment::systemEnvironment();
Environment systemEnvironment = tcd.compilerPath.deviceEnvironment();
GccToolChain::addCommandPathToEnvironment(tcd.compilerPath, systemEnvironment);
const FilePath localCompilerPath = findLocalCompiler(tcd.compilerPath, systemEnvironment);
if (ToolChainManager::isBadToolchain(localCompilerPath))
@@ -1436,7 +1436,7 @@ void GccToolChainConfigWidget::handleCompilerCommandChange()
haveCompiler = fi.isExecutable() && fi.isFile();
}
if (haveCompiler) {
Environment env = Environment::systemEnvironment();
Environment env = path.deviceEnvironment();
GccToolChain::addCommandPathToEnvironment(path, env);
QStringList args = gccPredefinedMacrosOptions(Constants::CXX_LANGUAGE_ID)
+ splitString(m_platformCodeGenFlagsLineEdit->text());

View File

@@ -313,22 +313,20 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
if (tcCxx)
cxxCompilerPath = tcCxx->compilerCommand();
const QFileInfo cFileInfo = cCompilerPath.toFileInfo();
const QFileInfo cxxFileInfo = cxxCompilerPath.toFileInfo();
QString cCompilerName = cFileInfo.fileName();
QString cxxCompilerName = cxxFileInfo.fileName();
QString cCompilerName = cCompilerPath.fileName();
QString cxxCompilerName = cxxCompilerPath.fileName();
const QString cToolchainPrefix = extractToolchainPrefix(&cCompilerName);
const QString cxxToolchainPrefix = extractToolchainPrefix(&cxxCompilerName);
QFileInfo mainFileInfo;
Utils::FilePath mainFilePath;
QString mainCompilerName;
QString mainToolchainPrefix;
if (tcCxx) {
mainFileInfo = cxxFileInfo;
mainFilePath = cxxCompilerPath;
mainCompilerName = cxxCompilerName;
mainToolchainPrefix = cxxToolchainPrefix;
} else {
mainFileInfo = cFileInfo;
mainFilePath = cCompilerPath;
mainCompilerName = cCompilerName;
mainToolchainPrefix = cToolchainPrefix;
}
@@ -353,11 +351,11 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
}
if (tcC && tcCxx && !cCompilerPath.isEmpty() && !cxxCompilerPath.isEmpty()
&& cFileInfo.absolutePath() != cxxFileInfo.absolutePath()) {
&& cCompilerPath.absolutePath() != cxxCompilerPath.absolutePath()) {
Core::MessageManager::writeFlashing(
tr("C and C++ compiler paths differ. C compiler may not work."));
}
data.insert(QLatin1String(CPP_TOOLCHAINPATH), mainFileInfo.absolutePath());
data.insert(QLatin1String(CPP_TOOLCHAINPATH), mainFilePath.absolutePath().toString());
if (auto gcc = dynamic_cast<ProjectExplorer::GccToolChain *>(mainTc)) {
QStringList compilerFlags = gcc->platformCodeGenFlags();
@@ -372,7 +370,7 @@ QVariantMap DefaultPropertyProvider::autoGeneratedProperties(const ProjectExplor
// Reverse engineer the Xcode developer path from the compiler path
const QRegularExpression compilerRe(
QStringLiteral("^(?<developerpath>.*)/Toolchains/(?:.+)\\.xctoolchain/usr/bin$"));
const QRegularExpressionMatch compilerReMatch = compilerRe.match(cxxFileInfo.absolutePath());
const QRegularExpressionMatch compilerReMatch = compilerRe.match(cxxCompilerPath.absolutePath().toString());
if (compilerReMatch.hasMatch()) {
const QString developerPath = compilerReMatch.captured(QStringLiteral("developerpath"));
data.insert(QLatin1String(XCODE_DEVELOPERPATH), developerPath);

View File

@@ -218,8 +218,7 @@ QString QbsProfileManager::profileNameForKit(const ProjectExplorer::Kit *kit)
QString QbsProfileManager::runQbsConfig(QbsConfigOp op, const QString &key, const QVariant &value)
{
Utils::QtcProcess qbsConfig;
QStringList args("config");
QStringList args;
if (QbsSettings::useCreatorSettingsDirForQbs())
args << "--settings-dir" << QbsSettings::qbsSettingsBaseDir();
switch (op) {
@@ -242,10 +241,11 @@ QString QbsProfileManager::runQbsConfig(QbsConfigOp op, const QString &key, cons
break;
}
}
const Utils::FilePath qbsExe = QbsSettings::qbsExecutableFilePath();
if (qbsExe.isEmpty() || !qbsExe.exists())
const Utils::FilePath qbsConfigExe = QbsSettings::qbsConfigFilePath();
if (qbsConfigExe.isEmpty() || !qbsConfigExe.exists())
return {};
qbsConfig.setCommand({qbsExe, args});
Utils::QtcProcess qbsConfig;
qbsConfig.setCommand({qbsConfigExe, args});
qbsConfig.start();
if (!qbsConfig.waitForStarted(3000) || !qbsConfig.waitForFinished(5000)) {
Core::MessageManager::writeFlashing(

View File

@@ -87,6 +87,18 @@ FilePath QbsSettings::qbsExecutableFilePath()
return candidate;
}
FilePath QbsSettings::qbsConfigFilePath()
{
const FilePath qbsExe = qbsExecutableFilePath();
if (!qbsExe.isExecutableFile())
return {};
const FilePath qbsConfig = qbsExe.absolutePath().pathAppended("qbs-config")
.withExecutableSuffix();
if (!qbsConfig.isExecutableFile())
return {};
return qbsConfig;
}
QString QbsSettings::defaultInstallDirTemplate()
{
return instance().m_settings.defaultInstallDirTemplate;

View File

@@ -50,6 +50,7 @@ public:
static QbsSettings &instance();
static Utils::FilePath qbsExecutableFilePath();
static Utils::FilePath qbsConfigFilePath();
static bool hasQbsExecutable();
static QString defaultInstallDirTemplate();
static bool useCreatorSettingsDirForQbs();

View File

@@ -64,7 +64,7 @@ void FileResourcesModel::setModelNodeBackend(const QVariant &modelNodeBackend)
if (backendObjectCasted) {
QmlDesigner::Model *model = backendObjectCasted->qmlObjectNode().modelNode().model();
m_docPath = QDir{QFileInfo{model->fileUrl().toLocalFile()}.absolutePath()};
m_path = QUrl::fromLocalFile(QmlDesigner::DocumentManager::currentResourcePath()
m_path = QUrl::fromLocalFile(QmlDesigner::DocumentManager::currentProjectDirPath()
.toFileInfo().absoluteFilePath());
}

View File

@@ -862,14 +862,8 @@ ModelNode RewriterView::nodeAtTextCursorPositionHelper(const ModelNode &root, in
ModelNode lastNode = root;
int i = 0;
for (const myPair &pair : data) {
ModelNode node = pair.first;
i++;
if (i >= int(data.size())) {
lastNode = node;
break;
}
const int nodeTextOffset = nodeOffset(node);
const int nodeTextLength = m_textModifier->text().indexOf("}", nodeTextOffset) - nodeTextOffset - 1;

View File

@@ -92,7 +92,7 @@ Rectangle {
Text {
id: software_for_ui
x: 15
y: 124
y: 126
width: 300
height: 30
color: "#ffffff"

View File

@@ -2610,7 +2610,7 @@ void TextEditorWidget::keyPressEvent(QKeyEvent *e)
if (ro || !isPrintableText(eventText)) {
QTextCursor::MoveOperation blockSelectionOperation = QTextCursor::NoMove;
if (e->modifiers() & Qt::AltModifier && !Utils::HostOsInfo::isMacHost()) {
if (e->modifiers() == (Qt::AltModifier | Qt::ShiftModifier) && !Utils::HostOsInfo::isMacHost()) {
if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToNextLine))
blockSelectionOperation = QTextCursor::Down;
else if (MultiTextCursor::multiCursorAddEvent(e, QKeySequence::MoveToPreviousLine))

View File

@@ -62,6 +62,7 @@ const char DEBUGGER_ENGINE[] = "EngineType";
const char DEBUGGER_BINARY[] = "Binary";
const char DEVICE_TYPE[] = "PE.Profile.DeviceType";
const char DEVICE_ID[] = "PE.Profile.Device";
const char BUILDDEVICE_ID[] = "PE.Profile.BuildDevice";
const char SYSROOT[] = "PE.Profile.SysRoot";
const char TOOLCHAIN[] = "PE.Profile.ToolChainsV3";
const char MKSPEC[] = "QtPM4.mkSpecInformation";
@@ -90,8 +91,9 @@ QString AddKitOperation::argumentsHelpText() const
" (not compatible with --debugger and --debuggerengine)\n"
" --debuggerengine <ENGINE> debuggerengine of the new kit.\n"
" --debugger <PATH> debugger of the new kit.\n"
" --devicetype <TYPE> device type of the new kit (required).\n"
" --device <ID> device id to use (optional).\n"
" --devicetype <TYPE> (run-)device type of the new kit (required).\n"
" --device <ID> (run-)device id to use (optional).\n"
" --builddevice <ID> build device id to use (optional).\n"
" --sysroot <PATH> sysroot of the new kit.\n"
" --toolchain <ID> tool chain of the new kit (obsolete!).\n"
" --<LANG>toolchain <ID> tool chain for a language.\n"
@@ -180,6 +182,14 @@ bool AddKitOperation::setArguments(const QStringList &args)
continue;
}
if (current == "--builddevice") {
if (next.isNull())
return false;
++i; // skip next;
m_buildDevice = next;
continue;
}
if (current == "--sysroot") {
if (next.isNull())
return false;
@@ -303,7 +313,18 @@ int AddKitOperation::execute() const
#ifdef WITH_TESTS
bool AddKitOperation::test() const
{
AddKitData kitData;
AddKitData baseData;
baseData.m_id ="testId";
baseData.m_displayName = "Test Kit";
baseData.m_icon = "/tmp/icon.png";
baseData.m_debuggerEngine = 1;
baseData.m_debugger = "/usr/bin/gdb-test";
baseData.m_deviceType = "Desktop";
baseData.m_device = "{dev-id}";
baseData.m_qt = "{qt-id}";
baseData.m_mkspec ="unsupported/mkspec";
baseData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue")}};
QVariantMap map = initializeKits();
QVariantMap tcMap = AddToolChainData::initializeToolChains();
@@ -326,22 +347,27 @@ bool AddKitOperation::test() const
const QStringList env = {"TEST=1", "PATH"};
if (map.count() != 3
|| !map.contains(VERSION) || map.value(VERSION).toInt() != 1
|| !map.contains(COUNT) || map.value(COUNT).toInt() != 0
|| !map.contains(DEFAULT) || !map.value(DEFAULT).toString().isEmpty())
if (map.count() != 3)
return false;
if (!map.contains(VERSION))
return false;
if (map.value(VERSION).toInt() != 1)
return false;
if (!map.contains(COUNT))
return false;
if (map.value(COUNT).toInt() != 0)
return false;
if (!map.contains(DEFAULT))
return false;
if (!map.value(DEFAULT).toString().isEmpty())
return false;
QHash<QString, QString> tcs;
tcs.insert("Cxx", "{tcXX-id}");
// Fail if TC is not there:
kitData = {"testId", "Test Kit", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", "{dev-id}", QString(),
tcs, "{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(),
QStringList(),
{{{"PE.Profile.Data/extraData", QVariant("extraValue")}}}};
AddKitData kitData = baseData;
kitData.m_tcs = tcs;
QVariantMap empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (!empty.isEmpty())
@@ -349,21 +375,16 @@ bool AddKitOperation::test() const
// Do not fail if TC is an ABI:
tcs.clear();
tcs.insert("C", "x86-linux-generic-elf-64bit");
kitData = {"testId", "Test Kit", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", "{dev-id}", QString(),
tcs, "{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}};
kitData = baseData;
kitData.m_tcs = tcs;
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (empty.isEmpty())
return false;
// QTCREATORBUG-11983, mach_o was not covered by the first attempt to fix this.
tcs.insert("D", "x86-macos-generic-mach_o-64bit");
kitData = {"testId", "Test Kit", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", "{dev-id}", QString(),
tcs, "{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}}};
kitData = baseData;
kitData.m_tcs = tcs;
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (empty.isEmpty())
return false;
@@ -372,153 +393,288 @@ bool AddKitOperation::test() const
tcs.insert("Cxx", "{tc-id}");
// Fail if Qt is not there:
kitData = {"testId", "Test Kit", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", "{dev-id}", QString(), tcs, "{qtXX-id}",
"unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}}};
kitData = baseData;
kitData.m_qt = "{qtXX-id}";
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (!empty.isEmpty())
return false;
// Fail if dev is not there:
kitData = {"testId", "Test Kit", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", "{devXX-id}", QString(), tcs, "{qt-id}",
"unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}};
kitData = baseData;
kitData.m_device = "{devXX-id}";
empty = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (!empty.isEmpty())
return false;
// Profile 0:
kitData = {"testId", "Test Kit", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", QString(), QString(), tcs, "{qt-id}",
"unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}}};
kitData = baseData;
kitData.m_tcs = tcs;
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (map.count() != 4
|| !map.contains(VERSION) || map.value(VERSION).toInt() != 1
|| !map.contains(COUNT) || map.value(COUNT).toInt() != 1
|| !map.contains(DEFAULT) || map.value(DEFAULT).toString() != "testId"
|| !map.contains("Profile.0"))
if (map.count() != 4)
return false;
if (!map.contains(VERSION))
return false;
if (map.value(VERSION).toInt() != 1)
return false;
if (!map.contains(COUNT))
return false;
if (map.value(COUNT).toInt() != 1)
return false;
if (!map.contains(DEFAULT))
return false;
if (map.value(DEFAULT).toString() != "testId")
return false;
if (!map.contains("Profile.0"))
return false;
QVariantMap profile0 = map.value("Profile.0").toMap();
if (profile0.count() != 6
|| !profile0.contains(ID) || profile0.value(ID).toString() != "testId"
|| !profile0.contains(DISPLAYNAME) || profile0.value(DISPLAYNAME).toString() != "Test Kit"
|| !profile0.contains(ICON) || profile0.value(ICON).toString() != "/tmp/icon.png"
|| !profile0.contains(DATA) || profile0.value(DATA).type() != QVariant::Map
|| !profile0.contains(AUTODETECTED) || profile0.value(AUTODETECTED).toBool() != true
|| !profile0.contains(SDK) || profile0.value(SDK).toBool() != true)
if (profile0.count() != 6)
return false;
if (!profile0.contains(ID))
return false;
if (profile0.value(ID).toString() != "testId")
return false;
if (!profile0.contains(DISPLAYNAME))
return false;
if (profile0.value(DISPLAYNAME).toString() != "Test Kit")
return false;
if (!profile0.contains(ICON))
return false;
if (profile0.value(ICON).toString() != "/tmp/icon.png")
return false;
if (!profile0.contains(DATA))
return false;
if (profile0.value(DATA).type() != QVariant::Map)
return false;
if (!profile0.contains(AUTODETECTED))
return false;
if (profile0.value(AUTODETECTED).toBool() != true)
return false;
if (!profile0.contains(SDK))
return false;
if (profile0.value(SDK).toBool() != true)
return false;
QVariantMap data = profile0.value(DATA).toMap();
if (data.count() != 7
|| !data.contains(DEBUGGER) || data.value(DEBUGGER).type() != QVariant::Map
|| !data.contains(DEVICE_TYPE) || data.value(DEVICE_TYPE).toString() != "Desktop"
|| !data.contains(TOOLCHAIN)
|| !data.contains(QT) || data.value(QT).toString() != "SDK.{qt-id}"
|| !data.contains(MKSPEC) || data.value(MKSPEC).toString() != "unsupported/mkspec"
|| !data.contains("extraData") || data.value("extraData").toString() != "extraValue")
if (data.count() != 7)
return false;
QVariantMap tcOutput = data.value(TOOLCHAIN).toMap();
if (tcOutput.count() != 1
|| !tcOutput.contains("Cxx") || tcOutput.value("Cxx") != "{tc-id}")
if (!data.contains(DEBUGGER))
return false;
if (data.value(DEBUGGER).type() != QVariant::Map)
return false;
if (!data.contains(DEVICE_TYPE))
return false;
if (data.value(DEVICE_TYPE).toString() != "Desktop")
return false;
if (!data.contains(TOOLCHAIN))
return false;
if (!data.contains(QT))
return false;
if (data.value(QT).toString() != "SDK.{qt-id}")
return false;
if (!data.contains(MKSPEC))
return false;
if (data.value(MKSPEC).toString() != "unsupported/mkspec")
return false;
if (!data.contains("extraData"))
return false;
if (data.value("extraData").toString() != "extraValue")
return false;
// Ignore existing ids:
kitData = {"testId", "Test Qt Version X",
"/tmp/icon3.png", QString(), 1, "/usr/bin/gdb-test3", "Desktop",
QString(), QString(), tcs, "{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}}};
QVariantMap tcOutput = data.value(TOOLCHAIN).toMap();
if (tcOutput.count() != 1)
return false;
if (!tcOutput.contains("Cxx"))
return false;
if (tcOutput.value("Cxx") != "{tc-id}")
return false;
// Ignore exist ids:
kitData = baseData;
kitData.m_displayName = "Test Qt Version X";
kitData.m_icon = "/tmp/icon3.png";
kitData.m_debugger = "/usr/bin/gdb-test3";
kitData.m_tcs = tcs;
QVariantMap result = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (!result.isEmpty())
return false;
// Profile 1: Make sure name is unique:
kitData = {"testId2", "Test Kit2", "/tmp/icon2.png", QString(), 1,
"/usr/bin/gdb-test2", "Desktop", "{dev-id}", "/sys/root//", tcs,
"{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}}};
kitData = baseData;
kitData.m_id = "testId2";
kitData.m_displayName = "Test Kit2";
kitData.m_icon = "/tmp/icon2.png";
kitData.m_debugger = "/usr/bin/gdb-test2";
kitData.m_sysRoot = "/sys/root//";
kitData.m_env = env;
kitData.m_tcs = tcs;
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (map.count() != 5
|| !map.contains(VERSION) || map.value(VERSION).toInt() != 1
|| !map.contains(COUNT) || map.value(COUNT).toInt() != 2
|| !map.contains(DEFAULT) || map.value(DEFAULT).toInt() != 0
|| !map.contains("Profile.0")
|| !map.contains("Profile.1"))
if (map.count() != 5)
return false;
if (!map.contains(VERSION) )
return false;
if (map.value(VERSION).toInt() != 1)
return false;
if (!map.contains(COUNT) )
return false;
if (map.value(COUNT).toInt() != 2)
return false;
if (!map.contains(DEFAULT) )
return false;
if (map.value(DEFAULT).toInt() != 0)
return false;
if (!map.contains("Profile.0"))
return false;
if (!map.contains("Profile.1"))
return false;
if (map.value("Profile.0") != profile0)
return false;
QVariantMap profile1 = map.value("Profile.1").toMap();
if (profile1.count() != 6
|| !profile1.contains(ID) || profile1.value(ID).toString() != "testId2"
|| !profile1.contains(DISPLAYNAME) || profile1.value(DISPLAYNAME).toString() != "Test Kit2"
|| !profile1.contains(ICON) || profile1.value(ICON).toString() != "/tmp/icon2.png"
|| !profile1.contains(DATA) || profile1.value(DATA).type() != QVariant::Map
|| !profile1.contains(AUTODETECTED) || profile1.value(AUTODETECTED).toBool() != true
|| !profile1.contains(SDK) || profile1.value(SDK).toBool() != true)
if (profile1.count() != 6)
return false;
if (!profile1.contains(ID) )
return false;
if (profile1.value(ID).toString() != "testId2")
return false;
if (!profile1.contains(DISPLAYNAME) )
return false;
if (profile1.value(DISPLAYNAME).toString() != "Test Kit2")
return false;
if (!profile1.contains(ICON) )
return false;
if (profile1.value(ICON).toString() != "/tmp/icon2.png")
return false;
if (!profile1.contains(DATA) )
return false;
if (profile1.value(DATA).type() != QVariant::Map)
return false;
if (!profile1.contains(AUTODETECTED) )
return false;
if (profile1.value(AUTODETECTED).toBool() != true)
return false;
if (!profile1.contains(SDK) )
return false;
if (profile1.value(SDK).toBool() != true)
return false;
data = profile1.value(DATA).toMap();
if (data.count() != 9
|| !data.contains(DEBUGGER) || data.value(DEBUGGER).type() != QVariant::Map
|| !data.contains(DEVICE_TYPE) || data.value(DEVICE_TYPE).toString() != "Desktop"
|| !data.contains(DEVICE_ID) || data.value(DEVICE_ID).toString() != "{dev-id}"
|| !data.contains(SYSROOT) || data.value(SYSROOT).toString() != "/sys/root//"
|| !data.contains(TOOLCHAIN)
|| !data.contains(QT) || data.value(QT).toString() != "SDK.{qt-id}"
|| !data.contains(MKSPEC) || data.value(MKSPEC).toString() != "unsupported/mkspec"
|| !data.contains(ENV) || data.value(ENV).toStringList() != env
|| !data.contains("extraData") || data.value("extraData").toString() != "extraValue")
if (data.count() != 9)
return false;
if (!data.contains(DEBUGGER) )
return false;
if (data.value(DEBUGGER).type() != QVariant::Map)
return false;
if (!data.contains(DEVICE_TYPE) )
return false;
if (data.value(DEVICE_TYPE).toString() != "Desktop")
return false;
if (!data.contains(DEVICE_ID) )
return false;
if (data.value(DEVICE_ID).toString() != "{dev-id}")
return false;
if (!data.contains(SYSROOT) )
return false;
if (data.value(SYSROOT).toString() != "/sys/root//")
return false;
if (!data.contains(TOOLCHAIN))
return false;
if (!data.contains(QT) )
return false;
if (data.value(QT).toString() != "SDK.{qt-id}")
return false;
if (!data.contains(MKSPEC) )
return false;
if (data.value(MKSPEC).toString() != "unsupported/mkspec")
return false;
if (!data.contains(ENV) )
return false;
if (data.value(ENV).toStringList() != env)
return false;
if (!data.contains("extraData") )
return false;
if (data.value("extraData").toString() != "extraValue")
return false;
tcOutput = data.value(TOOLCHAIN).toMap();
if (tcOutput.count() != 1
|| !tcOutput.contains("Cxx") || tcOutput.value("Cxx") != "{tc-id}")
if (tcOutput.count() != 1)
return false;
if (!tcOutput.contains("Cxx") )
return false;
if (tcOutput.value("Cxx") != "{tc-id}")
return false;
// Profile 2: Test debugger id:
kitData = {"test with debugger Id", "Test debugger Id",
"/tmp/icon2.png", "debugger Id", 0, QString(), "Desktop", QString(), QString(),
tcs, "{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), env,
{KeyValuePair("PE.Profile.Data/extraData", QVariant("extraValue"))}};
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (map.count() != 6
|| !map.contains(VERSION) || map.value(VERSION).toInt() != 1
|| !map.contains(COUNT) || map.value(COUNT).toInt() != 3
|| !map.contains(DEFAULT) || map.value(DEFAULT).toInt() != 0
|| !map.contains("Profile.0")
|| !map.contains("Profile.1")
|| !map.contains("Profile.2"))
return false;
kitData = baseData;
kitData.m_id = "test with debugger Id";
kitData.m_displayName = "Test debugger Id";
kitData.m_icon = "/tmp/icon2.png";
kitData.m_debuggerId = "debugger Id";
kitData.m_env = env;
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
if (map.count() != 6)
return false;
if (!map.contains(VERSION) )
return false;
if (map.value(VERSION).toInt() != 1)
return false;
if (!map.contains(COUNT) )
return false;
if (map.value(COUNT).toInt() != 3)
return false;
if (!map.contains(DEFAULT) )
return false;
if (map.value(DEFAULT).toInt() != 0)
return false;
if (!map.contains("Profile.0"))
return false;
if (!map.contains("Profile.1"))
return false;
if (!map.contains("Profile.2"))
return false;
if (map.value("Profile.0") != profile0)
return false;
if (map.value("Profile.1") != profile1)
return false;
QVariantMap profile2 = map.value("Profile.2").toMap();
if (profile2.count() != 6
|| !profile2.contains(ID) || profile2.value(ID).toString() != "test with debugger Id"
|| !profile2.contains(DISPLAYNAME) || profile2.value(DISPLAYNAME).toString() != "Test debugger Id"
|| !profile2.contains(ICON) || profile2.value(ICON).toString() != "/tmp/icon2.png"
|| !profile2.contains(DATA) || profile2.value(DATA).type() != QVariant::Map
|| !profile2.contains(AUTODETECTED) || profile2.value(AUTODETECTED).toBool() != true
|| !profile2.contains(SDK) || profile2.value(SDK).toBool() != true)
if (profile2.count() != 6)
return false;
if (!profile2.contains(ID) )
return false;
if (profile2.value(ID).toString() != "test with debugger Id")
return false;
if (!profile2.contains(DISPLAYNAME) )
return false;
if (profile2.value(DISPLAYNAME).toString() != "Test debugger Id")
return false;
if (!profile2.contains(ICON) )
return false;
if (profile2.value(ICON).toString() != "/tmp/icon2.png")
return false;
if (!profile2.contains(DATA) )
return false;
if (profile2.value(DATA).type() != QVariant::Map)
return false;
if (!profile2.contains(AUTODETECTED) )
return false;
if (profile2.value(AUTODETECTED).toBool() != true)
return false;
if (!profile2.contains(SDK) )
return false;
if (profile2.value(SDK).toBool() != true)
return false;
data = profile2.value(DATA).toMap();
if (data.count() != 7
|| !data.contains(DEBUGGER) || data.value(DEBUGGER).toString() != "debugger Id")
if (data.count() != 7)
return false;
if (!data.contains(DEBUGGER))
return false;
if (data.value(DEBUGGER).toString() != "debugger Id")
return false;
return true;
@@ -575,6 +731,10 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
std::cerr << "Error: Device " << qPrintable(m_device) << " does not exist." << std::endl;
return QVariantMap();
}
if (!m_buildDevice.isEmpty() && !AddDeviceOperation::exists(devMap, m_buildDevice)) {
std::cerr << "Error: Device " << qPrintable(m_buildDevice) << " does not exist." << std::endl;
return QVariantMap();
}
// Treat a qt that was explicitly set to '' as "no Qt"
if (!qtId.isNull() && qtId.isEmpty())
@@ -621,6 +781,8 @@ QVariantMap AddKitData::addKit(const QVariantMap &map, const QVariantMap &tcMap,
data << KeyValuePair({kit, DATA, DEVICE_TYPE}, QVariant(m_deviceType));
if (!m_device.isNull())
data << KeyValuePair({kit, DATA, DEVICE_ID}, QVariant(m_device));
if (!m_buildDevice.isNull())
data << KeyValuePair({kit, DATA, BUILDDEVICE_ID}, QVariant(m_buildDevice));
if (!m_sysRoot.isNull())
data << KeyValuePair({kit, DATA, SYSROOT}, Utils::FilePath::fromUserInput(m_sysRoot).toVariant());
for (auto i = m_tcs.constBegin(); i != m_tcs.constEnd(); ++i)

View File

@@ -47,6 +47,7 @@ public:
QString m_debugger;
QString m_deviceType;
QString m_device;
QString m_buildDevice;
QString m_sysRoot;
QHash<QString, QString> m_tcs;
QString m_qt;

View File

@@ -116,22 +116,28 @@ bool RmKitOperation::test() const
QHash<QString, QString> tcs;
tcs.insert("Cxx", "{tc-id}");
QVariantMap map =
AddKitData{"testId", "Test Qt Version", "/tmp/icon.png", QString(), 1,
"/usr/bin/gdb-test", "Desktop", QString(), QString(), tcs,
"{qt-id}", "unsupported/mkspec",
QString(), QString(), QString(), QString(), QString(), QStringList(), QStringList(),
{{"PE.Profile.Data/extraData", QVariant("extraValue")}}}
.addKit(AddKitData::initializeKits(), tcMap, qtMap, devMap, {});
AddKitData kitData;
kitData.m_id = "testId";
kitData.m_displayName = "Test Qt Version";
kitData.m_icon = "/tmp/icon.png";
kitData.m_debuggerEngine = 1;
kitData.m_debugger = "/usr/bin/gdb-test";
kitData.m_deviceType = "Desktop";
kitData.m_tcs = tcs;
kitData.m_qt = "{qt-id}";
kitData.m_mkspec = "unsupported/mkspec";
kitData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue")}};
QVariantMap map = kitData.addKit(AddKitData::initializeKits(), tcMap, qtMap, devMap, {});
map = AddKitData{"testId2", "Test Qt Version",
"/tmp/icon2.png", QString(), 1, "/usr/bin/gdb-test2",
"Desktop", QString(), QString(), tcs, "{qt-id}",
"unsupported/mkspec2",
QString(), QString(), QString(), QString(), QString(), QStringList(), QStringList(),
{{"PE.Profile.Data/extraData", QVariant("extraValue2")}}}
.addKit(map, tcMap, qtMap, devMap, {});
kitData.m_id = "testId2";
kitData.m_icon = "/tmp/icon2.png";
kitData.m_icon = "/usr/bin/gdb-test2";
kitData.m_mkspec = "unsupported/mkspec2";
kitData.m_extra = {{"PE.Profile.Data/extraData", QVariant("extraValue2")}};
map = kitData.addKit(map, tcMap, qtMap, devMap, {});
QVariantMap result = rmKit(map, "testId");
if (result.count() != 4

View File

@@ -84,7 +84,7 @@
:Go to slot.OK_QPushButton {text='OK' type='QPushButton' unnamed='1' visible='1' window=':Go to slot_QDialog'}
:Go to slot.Select signal_QGroupBox {name='groupBox' title='Select signal' type='QGroupBox' visible='1' window=':Go to slot_QDialog'}
:Go to slot_QDialog {name='SelectSignalDialog' type='QDialog' visible='1' windowTitle='Go to slot'}
:Help Widget_Help::Internal::HelpWidget {type='Help::Internal::HelpWidget' unnamed='1' visible='1' windowTitle?='Help -*'}
:Help Widget_Help::Internal::HelpWidget {type='Help::Internal::HelpWidget' unnamed='1' visible='1' windowTitle?='Help*'}
:Hits_QLabel {text~='\\\\d+ - \\\\d+ of \\\\d+ Hits' type='QLabel' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:Hits_QResultWidget {aboveWidget=':Hits_QLabel' type='QResultWidget' unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'}
:JsonWizard_ProjectExplorer::JsonFieldPage {type='ProjectExplorer::JsonFieldPage' unnamed='1' visible='1' window=':New_ProjectExplorer::JsonWizard'}

View File

@@ -31,9 +31,9 @@ def openQbsProject(projectPath):
def openQmakeProject(projectPath, targets=Targets.desktopTargetClasses(), fromWelcome=False):
cleanUpUserFiles(projectPath)
if fromWelcome:
wsButtonFrame, wsButtonLabel = getWelcomeScreenMainButton('Open')
wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Open Project...')
if not all((wsButtonFrame, wsButtonLabel)):
test.fatal("Could not find 'Open' button on Welcome Page.")
test.fatal("Could not find 'Open Project...' button on Welcome Page.")
return []
mouseClick(wsButtonLabel)
else:
@@ -83,10 +83,10 @@ def openCmakeProject(projectPath, buildDir):
def __createProjectOrFileSelectType__(category, template, fromWelcome = False, isProject=True):
if fromWelcome:
if not isProject:
test.fatal("'New' on Welcome screen only handles projects nowadays.")
wsButtonFrame, wsButtonLabel = getWelcomeScreenMainButton("New")
test.fatal("'Create Project...' on Welcome screen only handles projects nowadays.")
wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton("Create Project...")
if not all((wsButtonFrame, wsButtonLabel)):
test.fatal("Could not find 'New' button on Welcome Page")
test.fatal("Could not find 'Create Project...' button on Welcome Page")
return []
mouseClick(wsButtonLabel)
elif isProject:

View File

@@ -41,8 +41,9 @@ def __getWelcomeScreenButtonHelper__(buttonLabel, widgetWithQFrames, isUrlButton
return None, None
def getWelcomeScreenSideBarButton(buttonLabel, isUrlButton = False):
sideBar = waitForObject("{type='Welcome::Internal::SideBar' unnamed='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}")
sideBar = waitForObject("{container={type='Welcome::Internal::SideArea' unnamed='1' "
"window=':Qt Creator_Core::Internal::MainWindow'} type='QWidget' "
"unnamed='1'}")
return __getWelcomeScreenButtonHelper__(buttonLabel, sideBar, isUrlButton)
def getWelcomeScreenMainButton(buttonLabel):

View File

@@ -75,13 +75,15 @@ def main():
return
switchToSubMode('Projects')
typePropDet = (("QPushButton", "Get Started Now", "Get Started Now button"),
("QTreeView", "Sessions", "Sessions section"),
typePropDet = (("QTreeView", "Sessions", "Sessions section"),
("SessionModelIndex", ("default", False), "default session listed"),
("QTreeView", "Recent Projects", "Projects section")
)
checkTypeAndProperties(typePropDet)
getStartedF, getStartedL = getWelcomeScreenSideBarButton("Get Started")
test.verify(getStartedF is not None and getStartedL is not None, "'Get Started' button found")
# select "Create Project" and try to create a new project
createNewQtQuickApplication(tempDir(), "SampleApp", fromWelcome = True)
test.verify(checkIfObjectExists("{column='0' container=':Qt Creator_Utils::NavigationTreeView'"

View File

@@ -42,10 +42,10 @@ def handlePackagingMessageBoxes():
def openExample(examplesLineEdit, input, exampleRegex, exampleName):
replaceEditorContent(examplesLineEdit, input)
tableView = waitForObject("{type='QTableView' unnamed='1' visible='1' "
listView = waitForObject("{type='QListView' unnamed='1' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}")
waitFor('findExampleOrTutorial(tableView, exampleRegex) is not None', 3000)
example = findExampleOrTutorial(tableView, exampleRegex, True)
waitFor('findExampleOrTutorial(listView, exampleRegex) is not None', 3000)
example = findExampleOrTutorial(listView, exampleRegex, True)
if test.verify(example is not None, "Verifying: Example (%s) is shown." % exampleName):
mouseClick(example)
handlePackagingMessageBoxes()
@@ -67,7 +67,7 @@ def main():
qchs.extend([os.path.join(p, "qtopengl.qch"), os.path.join(p, "qtwidgets.qch")])
addHelpDocumentation(qchs)
setFixedHelpViewer(HelpViewer.HELPMODE)
wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Get Started Now')
wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Get Started')
if not test.verify(all((wsButtonFrame, wsButtonLabel)),
"Verifying: Qt Creator displays Welcome Page with Getting Started."):
test.fatal("Something's wrong - leaving test.")
@@ -75,7 +75,7 @@ def main():
return
# select "Examples" topic
switchToSubMode('Examples')
expect = (("QTableView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'",
expect = (("QListView", "unnamed='1' visible='1' window=':Qt Creator_Core::Internal::MainWindow'",
"examples list"),
("QLineEdit", "placeholderText='Search in Examples...'", "examples search line edit"),
("QComboBox", "currentText~='.*Qt.*' visible='1'", "Qt version combo box"))
@@ -88,9 +88,9 @@ def main():
combo = waitForObject(search % (expect[2][0], expect[2][1]))
test.log("Using examples from Kit %s." % str(combo.currentText))
replaceEditorContent(examplesLineEdit, "qwerty")
tableView = waitForObject(search % (expect[0][0], expect[0][1]))
waitFor('findExampleOrTutorial(tableView, ".*") is None', 3000)
example = findExampleOrTutorial(tableView, ".*", True)
listView = waitForObject(search % (expect[0][0], expect[0][1]))
waitFor('findExampleOrTutorial(listView, ".*") is None', 3000)
example = findExampleOrTutorial(listView, ".*", True)
test.verify(example is None, "Verifying: No example is shown.")
proFiles = map(lambda p: os.path.join(p, "opengl", "2dpainting", "2dpainting.pro"),

View File

@@ -30,7 +30,7 @@ def main():
startQC()
if not startedWithoutPluginError():
return
wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Get Started Now')
wsButtonFrame, wsButtonLabel = getWelcomeScreenSideBarButton('Get Started')
if not test.verify(all((wsButtonFrame, wsButtonLabel)),
"Verifying: Qt Creator displays Welcome Page with Getting Started."):
test.fatal("Something's wrong - leaving test.")
@@ -44,16 +44,16 @@ def main():
searchTutorials = waitForObject("{type='QLineEdit' placeholderText='Search in Tutorials...'}")
mouseClick(searchTutorials)
replaceEditorContent(searchTutorials, "qwerty")
tableView = waitForObject("{type='QTableView' unnamed='1' visible='1' "
listView = waitForObject("{type='QListView' unnamed='1' visible='1' "
"window=':Qt Creator_Core::Internal::MainWindow'}")
waitFor('findExampleOrTutorial(tableView, ".*") is None', 3000)
tutorial = findExampleOrTutorial(tableView, ".*", True)
waitFor('findExampleOrTutorial(listView, ".*") is None', 3000)
tutorial = findExampleOrTutorial(listView, ".*", True)
test.verify(tutorial is None,
"Verifying: 'Tutorials' topic is opened and nothing is shown.")
bnr = "Help: Building and Running an Example"
replaceEditorContent(searchTutorials, bnr.lower())
waitFor('findExampleOrTutorial(tableView, "%s.*") is not None' % bnr, 3000)
tutorial = findExampleOrTutorial(tableView, "%s.*" % bnr, True)
waitFor('findExampleOrTutorial(listView, "%s.*") is not None' % bnr, 3000)
tutorial = findExampleOrTutorial(listView, "%s.*" % bnr, True)
test.verify(tutorial is not None, "Verifying: Expected Text tutorial is shown.")
# clicking before documentation was updated will open the tutorial in browser
progressBarWait(warn=False)
@@ -67,8 +67,9 @@ def main():
# check a demonstration video link
mouseClick(searchTutorials)
replaceEditorContent(searchTutorials, "embedded device")
waitFor('findExampleOrTutorial(tableView, "Online: Qt for Device Creation.*") is not None', 3000)
tutorial = findExampleOrTutorial(tableView, "Online: Qt for Device Creation.*", True)
embeddedTutorial = "Online: How to install and set up Qt for Device Creation.*"
waitFor('findExampleOrTutorial(listView, embeddedTutorial) is not None', 3000)
tutorial = findExampleOrTutorial(listView, embeddedTutorial, True)
test.verify(tutorial is not None,
"Verifying: Link to the expected demonstration video exists.")
# exit Qt Creator