Merge remote-tracking branch 'origin/7.0'

Conflicts:
	cmake/QtCreatorIDEBranding.cmake
	qbs/modules/qtc/qtc.qbs
	qtcreator_ide_branding.pri
	src/plugins/docker/dockerdevice.cpp
	src/plugins/mcusupport/mcupackage.cpp
	src/plugins/mcusupport/mcupackage.h
	src/plugins/mcusupport/mcusupportoptions.cpp
	src/plugins/mcusupport/mcusupportoptions.h
	src/plugins/mcusupport/mcusupportoptionspage.cpp
	src/plugins/mcusupport/mcusupportsdk.cpp
	src/plugins/mcusupport/mcusupportsdk.h

Change-Id: I8c8f5953a21729ba9178dbc44ed613eed131a0c8
This commit is contained in:
Eike Ziller
2022-02-16 10:44:23 +01:00
123 changed files with 1627 additions and 455 deletions

View File

@@ -1782,8 +1782,7 @@ void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Loca
}
qCDebug(clangdLog) << "document count is" << refData->fileData.size();
if (refData->replacementData || q->versionNumber() < QVersionNumber(13)
|| !refData->categorize) {
if (refData->replacementData || !refData->categorize) {
qCDebug(clangdLog) << "skipping AST retrieval";
reportAllSearchResultsAndFinish(*refData);
return;
@@ -1953,11 +1952,6 @@ void ClangdClient::followSymbol(TextDocument *document,
};
symbolSupport().findLinkAt(document, adjustedCursor, std::move(gotoDefCallback), true);
if (versionNumber() < QVersionNumber(12)) {
d->followSymbolData->cursorNode.emplace(AstNode());
return;
}
const auto astHandler = [this, id = d->followSymbolData->id]
(const AstNode &ast, const MessageId &) {
qCDebug(clangdLog) << "received ast response for cursor";
@@ -2747,6 +2741,11 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
const QList<AstNode> path = getAstPath(ast, range);
if (path.size() < 2)
return false;
if (token.type == "property"
&& (path.rbegin()->kind() == "MemberInitializer"
|| path.rbegin()->kind() == "CXXConstruct")) {
return false;
}
for (auto it = path.rbegin() + 1; it != path.rend(); ++it) {
if (it->kind() == "Call" || it->kind() == "CXXConstruct"
|| it->kind() == "MemberInitializer") {
@@ -2859,7 +2858,6 @@ static void semanticHighlighter(QFutureInterface<HighlightingResult> &future,
styles.mainStyle = C_FIELD;
} else if (token.type == "enum") {
styles.mainStyle = C_TYPE;
styles.mixinStyles.push_back(C_ENUMERATION);
} else if (token.type == "enumMember") {
styles.mainStyle = C_ENUMERATION;
} else if (token.type == "parameter") {
@@ -3640,9 +3638,11 @@ void ExtraHighlightingResultsCollector::collectFromNode(const AstNode &node)
if (node.kind().endsWith("Literal")) {
HighlightingResult result;
result.useTextSyles = true;
const bool isStringLike = node.kind().startsWith("String")
|| node.kind().startsWith("Character");
result.textStyles.mainStyle = isStringLike ? C_STRING : C_NUMBER;
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);
return;

View File

@@ -260,7 +260,7 @@ void ClangFollowSymbol::switchDeclDef(const CppEditor::CursorInEditor &data,
{
ClangdClient * const client
= ClangModelManagerSupport::instance()->clientForFile(data.filePath());
if (client && client->isFullyIndexed() && client->versionNumber() >= QVersionNumber(13)) {
if (client && client->isFullyIndexed()) {
client->switchDeclDef(data.textDocument(), data.cursor(), data.editorWidget(),
std::move(processLinkCallback));
return;

View File

@@ -179,7 +179,6 @@ ClangdTestFindReferences::ClangdTestFindReferences()
{
setProjectFileName("find-usages.pro");
setSourceFileNames({"defs.h", "main.cpp"});
setMinimumVersion(13);
}
void ClangdTestFindReferences::initTestCase()
@@ -322,7 +321,6 @@ ClangdTestFollowSymbol::ClangdTestFollowSymbol()
{
setProjectFileName("follow-symbol.pro");
setSourceFileNames({"main.cpp", "header.h"});
setMinimumVersion(12);
}
void ClangdTestFollowSymbol::test_data()
@@ -409,7 +407,6 @@ ClangdTestLocalReferences::ClangdTestLocalReferences()
{
setProjectFileName("local-references.pro");
setSourceFileNames({"references.cpp"});
setMinimumVersion(13);
}
// We currently only support local variables, but if and when clangd implements
@@ -525,7 +522,6 @@ ClangdTestTooltips::ClangdTestTooltips()
{
setProjectFileName("tooltips.pro");
setSourceFileNames({"tooltips.cpp"});
setMinimumVersion(13);
}
void ClangdTestTooltips::test_data()
@@ -668,7 +664,6 @@ ClangdTestHighlighting::ClangdTestHighlighting()
{
setProjectFileName("highlighting.pro");
setSourceFileNames({"highlighting.cpp"});
setMinimumVersion(13);
}
void ClangdTestHighlighting::initTestCase()
@@ -744,11 +739,11 @@ void ClangdTestHighlighting::test_data()
QTest::newRow("static member function call") << 114 << 15 << 114 << 27
<< QList<int>{C_FUNCTION} << 0;
QTest::newRow("enum declaration") << 118 << 6 << 118 << 17
<< QList<int>{C_TYPE, C_ENUMERATION, C_DECLARATION} << 0;
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
QTest::newRow("enumerator declaration") << 120 << 5 << 120 << 15
<< QList<int>{C_ENUMERATION, C_DECLARATION} << 0;
QTest::newRow("enum in variable declaration") << 125 << 5 << 125 << 16
<< QList<int>{C_TYPE, C_ENUMERATION} << 0;
<< QList<int>{C_TYPE} << 0;
QTest::newRow("enum variable declaration") << 125 << 17 << 125 << 28
<< QList<int>{C_LOCAL, C_DECLARATION} << 0;
QTest::newRow("enum variable reference") << 127 << 5 << 127 << 16 << QList<int>{C_LOCAL} << 0;
@@ -966,7 +961,7 @@ void ClangdTestHighlighting::test_data()
<< 310 << 29 << 310 << 38
<< QList<int>{C_FIELD} << 0;
QTest::newRow("enum declaration with underlying type") << 316 << 6 << 316 << 21
<< QList<int>{C_TYPE, C_ENUMERATION, C_DECLARATION} << 0;
<< QList<int>{C_TYPE, C_DECLARATION} << 0;
QTest::newRow("type in static_cast") << 328 << 23 << 328 << 33
<< QList<int>{C_TYPE} << 0;
QTest::newRow("opening angle bracket in static_cast") << 328 << 16 << 328 << 17
@@ -1293,6 +1288,13 @@ void ClangdTestHighlighting::test_data()
<< QList<int>{C_LOCAL} << 0;
QTest::newRow("const operator()") << 903 << 5 << 903 << 7
<< QList<int>{C_LOCAL} << 0;
QTest::newRow("member initialization: member (user-defined type)") << 911 << 14 << 911 << 18
<< QList<int>{C_FIELD} << 0;
QTest::newRow("member initialization: member (built-in type)") << 911 << 23 << 911 << 27
<< QList<int>{C_FIELD} << 0;
QTest::newRow("keywords: true") << 920 << 15 << 920 << 19 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("keywords: false") << 921 << 15 << 921 << 20 << QList<int>{C_KEYWORD} << 0;
QTest::newRow("keywords: nullptr") << 922 << 15 << 922 << 22 << QList<int>{C_KEYWORD} << 0;
}
void ClangdTestHighlighting::test()
@@ -2015,9 +2017,10 @@ void ClangdTestExternalChanges::test()
header.close();
ClangdClient * const oldClient = client();
QVERIFY(oldClient);
QVERIFY(!waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
&ClangModelManagerSupport::createdClient, timeOutInMs()));
waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
&ClangModelManagerSupport::createdClient, timeOutInMs());
QCOMPARE(client(), oldClient);
QCOMPARE(client(), ClangModelManagerSupport::instance()->clientForProject(project()));
const TextDocument * const curDoc = document("main.cpp");
QVERIFY(curDoc);
QVERIFY(curDoc->marks().isEmpty());

View File

@@ -902,3 +902,22 @@ void callOperators()
Callable2 c2;
c2();
}
namespace std { template<typename T> struct atomic { atomic(int) {} }; }
void constructorMemberInitialization()
{
struct S {
S(): m_m1(1), m_m2(0) {}
std::atomic<int> m_m1;
int m_m2;
};
}
void keywords()
{
bool b1 = true;
bool b2 = false;
void *p = nullptr;
}

View File

@@ -428,6 +428,13 @@ static QIcon interruptIcon(bool toolBarStyle)
return toolBarStyle ? iconToolBar : icon;
}
static bool hideAnalyzeMenu()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
.toBool();
}
QAction *addAction(const QObject *parent, QMenu *menu, const QString &display, bool on,
const std::function<void()> &onTriggered)
{
@@ -775,7 +782,8 @@ DebuggerPluginPrivate::DebuggerPluginPrivate(const QStringList &arguments)
ActionContainer *menubar = ActionManager::actionContainer(MENU_BAR);
ActionContainer *mtools = ActionManager::actionContainer(M_TOOLS);
menubar->addMenu(mtools, m_menu);
if (!hideAnalyzeMenu())
menubar->addMenu(mtools, m_menu);
m_menu->addSeparator(G_ANALYZER_TOOLS);
m_menu->addSeparator(G_ANALYZER_REMOTE_TOOLS);

View File

@@ -156,7 +156,8 @@ void OutputCollector::newConnectionAvailable()
void OutputCollector::bytesAvailable()
{
#ifdef Q_OS_WIN
emit byteDelivery(m_socket->readAll());
if (m_socket)
emit byteDelivery(m_socket->readAll());
#else
size_t nbytes = 0;
if (::ioctl(m_serverFd, FIONREAD, (char *) &nbytes) < 0)

View File

@@ -34,7 +34,6 @@ const char ACTION_ID[] = "Docker.Action";
const char MENU_ID[] = "Docker.Menu";
const char DOCKER_DEVICE_TYPE[] = "DockerDeviceType";
const char DOCKER_RUN_FLAGS[] = "DockerRunFlags";
const char DOCKER_BUILDHOST_BUILDSTEP_ID[] = "Docker.BuildStep.BuildHost";

View File

@@ -123,8 +123,6 @@ void DockerDeviceProcess::start()
DockerDevice::ConstPtr dockerDevice = qSharedPointerCast<const DockerDevice>(device());
QTC_ASSERT(dockerDevice, return);
const QStringList dockerRunFlags = extraData(Constants::DOCKER_RUN_FLAGS).toStringList();
connect(this, &DeviceProcess::readyReadStandardOutput, this, [this] {
MessageManager::writeSilently(QString::fromLocal8Bit(readAllStandardError()));
});

View File

@@ -105,6 +105,10 @@ Client::Client(BaseClientInterface *clientInterface)
connect(clientInterface, &BaseClientInterface::messageReceived, this, &Client::handleMessage);
connect(clientInterface, &BaseClientInterface::error, this, &Client::setError);
connect(clientInterface, &BaseClientInterface::finished, this, &Client::finished);
connect(Core::EditorManager::instance(),
&Core::EditorManager::documentClosed,
this,
&Client::documentClosed);
m_tokenSupport.setTokenTypesMap(SemanticTokens::defaultTokenTypesMap());
m_tokenSupport.setTokenModifiersMap(SemanticTokens::defaultTokenModifiersMap());
@@ -308,13 +312,11 @@ void Client::initialize()
initRequest.setResponseCallback([this](const InitializeRequest::Response &initResponse){
initializeCallback(initResponse);
});
// directly send data otherwise the state check would fail;
if (Utils::optional<ResponseHandler> responseHandler = initRequest.responseHandler())
m_responseHandlers[responseHandler->id] = responseHandler->callback;
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage,
name(),
initRequest.toBaseMessage());
// directly send message otherwise the state check of sendContent would fail
sendMessage(initRequest.toBaseMessage());
m_clientInterface->sendMessage(initRequest.toBaseMessage());
m_state = InitializeRequested;
}
@@ -427,9 +429,7 @@ void Client::sendContent(const IContent &content, SendDocUpdates sendUpdates)
QString error;
if (!QTC_GUARD(content.isValid(&error)))
Core::MessageManager::writeFlashing(error);
const BaseMessage message = content.toBaseMessage();
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
m_clientInterface->sendMessage(message);
sendMessage(content.toBaseMessage());
}
void Client::cancelRequest(const MessageId &id)
@@ -632,6 +632,12 @@ void Client::deactivateDocument(TextEditor::TextDocument *document)
}
}
void Client::documentClosed(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
closeDocument(textDocument);
}
bool Client::documentOpen(const TextEditor::TextDocument *document) const
{
return m_openedDocument.contains(const_cast<TextEditor::TextDocument *>(document));
@@ -1486,6 +1492,12 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams &params)
}
}
void Client::sendMessage(const BaseMessage &message)
{
LanguageClientManager::logBaseMessage(LspLogMessage::ClientMessage, name(), message);
m_clientInterface->sendMessage(message);
}
bool Client::documentUpdatePostponed(const Utils::FilePath &fileName) const
{
return Utils::contains(m_documentsToUpdate, [fileName](const auto &elem) {
@@ -1602,8 +1614,8 @@ void Client::shutDownCallback(const ShutdownRequest::Response &shutdownResponse)
qDebug() << error;
return;
}
// directly send data otherwise the state check would fail;
m_clientInterface->sendMessage(ExitNotification().toBaseMessage());
// directly send message otherwise the state check of sendContent would fail
sendMessage(ExitNotification().toBaseMessage());
qCDebug(LOGLSPCLIENT) << "language server " << m_displayName << " shutdown";
m_state = Shutdown;
}

View File

@@ -227,6 +227,7 @@ protected:
virtual void handleDiagnostics(const LanguageServerProtocol::PublishDiagnosticsParams &params);
private:
void sendMessage(const LanguageServerProtocol::BaseMessage &message);
void handleResponse(const LanguageServerProtocol::MessageId &id, const QByteArray &content,
QTextCodec *codec);
void handleMethod(const QString &method, const LanguageServerProtocol::MessageId &id,
@@ -252,6 +253,7 @@ private:
void requestDocumentHighlightsNow(TextEditor::TextEditorWidget *widget);
LanguageServerProtocol::SemanticRequestTypes supportedSemanticRequests(TextEditor::TextDocument *document) const;
void handleSemanticTokens(const LanguageServerProtocol::SemanticTokens &tokens);
void documentClosed(Core::IDocument *document);
virtual void handleDocumentClosed(TextEditor::TextDocument *) {}
virtual void handleDocumentOpened(TextEditor::TextDocument *) {}

View File

@@ -542,11 +542,8 @@ void LanguageClientManager::documentOpened(Core::IDocument *document)
void LanguageClientManager::documentClosed(Core::IDocument *document)
{
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document)) {
for (Client *client : qAsConst(m_clients))
client->closeDocument(textDocument);
if (auto textDocument = qobject_cast<TextEditor::TextDocument *>(document))
m_clientForDocument.remove(textDocument);
}
}
void LanguageClientManager::documentContentsSaved(Core::IDocument *document)

View File

@@ -7,7 +7,7 @@ add_qtc_plugin(McuSupport
mcusupport_global.h
mcusupportconstants.h
mcusupportdevice.cpp mcusupportdevice.h
mcusupportoptions.cpp mcusupportoptions.h
mcusupportoptions.cpp mcusupportoptions.h mcuabstractpackage.h
mcusupportoptionspage.cpp mcusupportoptionspage.h
mcupackage.cpp mcupackage.h
mcusupportplugin.cpp mcusupportplugin.h
@@ -15,4 +15,7 @@ add_qtc_plugin(McuSupport
mcusupportrunconfiguration.cpp mcusupportrunconfiguration.h
mcusupportversiondetection.cpp mcusupportversiondetection.h
mcusupportcmakemapper.cpp mcusupportcmakemapper.h
mcutargetdescription.h
)
add_subdirectory(test)

View File

@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QObject>
namespace Utils {
class FilePath;
} // namespace Utils
namespace McuSupport::Internal {
class McuAbstractPackage : public QObject
{
Q_OBJECT
public:
enum class Status {
EmptyPath,
InvalidPath,
ValidPathInvalidPackage,
ValidPackageMismatchedVersion,
ValidPackage
};
virtual Utils::FilePath basePath() const = 0;
virtual Utils::FilePath path() const = 0;
virtual QString label() const = 0;
virtual Utils::FilePath defaultPath() const = 0;
virtual QString detectionPath() const = 0;
virtual QString statusText() const = 0;
virtual void updateStatus() = 0;
virtual Status status() const = 0;
virtual bool validStatus() const = 0;
virtual const QString &environmentVariableName() const = 0;
virtual void setAddToPath(bool) = 0;
virtual bool addToPath() const = 0;
virtual void writeGeneralSettings() const = 0;
virtual bool writeToSettings() const = 0;
virtual void setRelativePathModifier(const QString &) = 0;
virtual void setVersions(const QStringList &) = 0;
virtual bool automaticKitCreationEnabled() const = 0;
virtual void setAutomaticKitCreationEnabled(const bool enabled) = 0;
virtual QWidget *widget() = 0;
signals:
void changed();
void statusChanged();
}; // class McuAbstractPackage
} // namespace McuSupport::Internal

View File

@@ -38,8 +38,7 @@
using namespace Utils;
namespace McuSupport {
namespace Internal {
namespace McuSupport::Internal {
static bool automaticKitCreationFromSettings(QSettings::Scope scope = QSettings::UserScope)
{
@@ -144,8 +143,7 @@ McuPackage::Status McuPackage::status() const
bool McuPackage::validStatus() const
{
return m_status == McuPackage::ValidPackage
|| m_status == McuPackage::ValidPackageMismatchedVersion;
return m_status == Status::ValidPackage || m_status == Status::ValidPackageMismatchedVersion;
}
const QString &McuPackage::environmentVariableName() const
@@ -221,11 +219,11 @@ void McuPackage::updateStatus()
const bool validVersion = m_detectedVersion.isEmpty() || m_versions.isEmpty()
|| m_versions.contains(m_detectedVersion);
m_status = validPath
? (validPackage ? (validVersion ? ValidPackage : ValidPackageMismatchedVersion)
: ValidPathInvalidPackage)
: m_path.isEmpty() ? EmptyPath
: InvalidPath;
m_status = validPath ? (validPackage ? (validVersion ? Status::ValidPackage
: Status::ValidPackageMismatchedVersion)
: Status::ValidPathInvalidPackage)
: m_path.isEmpty() ? Status::EmptyPath
: Status::InvalidPath;
emit statusChanged();
}
@@ -233,10 +231,10 @@ void McuPackage::updateStatus()
void McuPackage::updateStatusUi()
{
switch (m_status) {
case ValidPackage:
case Status::ValidPackage:
m_infoLabel->setType(InfoLabel::Ok);
break;
case ValidPackageMismatchedVersion:
case Status::ValidPackageMismatchedVersion:
m_infoLabel->setType(InfoLabel::Warning);
break;
default:
@@ -261,7 +259,7 @@ QString McuPackage::statusText() const
QString response;
switch (m_status) {
case ValidPackage:
case Status::ValidPackage:
response = m_detectionPath.isEmpty()
? (m_detectedVersion.isEmpty()
? tr("Path %1 exists.").arg(displayPackagePath)
@@ -270,23 +268,22 @@ QString McuPackage::statusText() const
: tr("Path %1 is valid, %2 was found.")
.arg(displayPackagePath, displayDetectedPath);
break;
case ValidPackageMismatchedVersion: {
const QString versionWarning
= m_versions.size() == 1
? tr("but only version %1 is supported").arg(m_versions.first())
: tr("but only versions %1 are supported").arg(displayVersions);
case Status::ValidPackageMismatchedVersion: {
const QString versionWarning = m_versions.size() == 1 ?
tr("but only version %1 is supported").arg(m_versions.first()) :
tr("but only versions %1 are supported").arg(displayVersions);
response = tr("Path %1 is valid, %2 was found, %3.")
.arg(displayPackagePath, displayDetectedPath, versionWarning);
break;
}
case ValidPathInvalidPackage:
case Status::ValidPathInvalidPackage:
response = tr("Path %1 exists, but does not contain %2.")
.arg(displayPackagePath, displayRequiredPath);
break;
case InvalidPath:
case Status::InvalidPath:
response = tr("Path %1 does not exist.").arg(displayPackagePath);
break;
case EmptyPath:
case Status::EmptyPath:
response = m_detectionPath.isEmpty()
? tr("Path is empty.")
: tr("Path is empty, %1 not found.").arg(displayRequiredPath);
@@ -316,5 +313,4 @@ bool McuToolChainPackage::isDesktopToolchain() const
return m_type == Type::MSVC || m_type == Type::GCC;
}
} // namespace Internal
} // namespace McuSupport
} // namespace McuSupport::Internal

View File

@@ -25,6 +25,7 @@
#pragma once
#include "mcuabstractpackage.h"
#include "mcusupportversiondetection.h"
#include <utils/filepath.h>
@@ -46,19 +47,11 @@ class InfoLabel;
namespace McuSupport {
namespace Internal {
class McuPackage : public QObject
class McuPackage : public McuAbstractPackage
{
Q_OBJECT
public:
enum Status {
EmptyPath,
InvalidPath,
ValidPathInvalidPackage,
ValidPackageMismatchedVersion,
ValidPackage
};
McuPackage(const QString &label,
const Utils::FilePath &defaultPath,
const QString &detectionPath,
@@ -66,31 +59,32 @@ public:
const QString &envVarName = {},
const QString &downloadUrl = {},
const McuPackageVersionDetector *versionDetector = nullptr);
virtual ~McuPackage() = default;
~McuPackage() override = default;
Utils::FilePath basePath() const;
Utils::FilePath path() const;
QString label() const;
Utils::FilePath defaultPath() const;
QString detectionPath() const;
QString statusText() const;
void updateStatus();
Utils::FilePath basePath() const override;
Utils::FilePath path() const override;
QString label() const override;
Utils::FilePath defaultPath() const override;
QString detectionPath() const override;
QString statusText() const override;
void updateStatus() override;
Status status() const;
bool validStatus() const;
void setAddToPath(bool addToPath);
bool addToPath() const;
void writeGeneralSettings() const;
bool writeToSettings() const;
void setRelativePathModifier(const QString &path);
void setVersions(const QStringList &versions);
Status status() const override;
bool validStatus() const override;
void setAddToPath(bool addToPath) override;
bool addToPath() const override;
void writeGeneralSettings() const override;
bool writeToSettings() const override;
void setRelativePathModifier(const QString &path) override;
void setVersions(const QStringList &versions) override;
bool automaticKitCreationEnabled() const;
void setAutomaticKitCreationEnabled(const bool enabled);
//TODO(piotr.mucko): Why every package knows about automatic kit creation. This should be outside of this class.
bool automaticKitCreationEnabled() const override;
void setAutomaticKitCreationEnabled(const bool enabled) override;
QWidget *widget();
QWidget *widget() override;
const QString &environmentVariableName() const;
const QString &environmentVariableName() const override;
signals:
void changed();
@@ -119,7 +113,7 @@ private:
bool m_addToPath = false;
bool m_automaticKitCreation = true;
Status m_status = InvalidPath;
Status m_status = Status::InvalidPath;
};
class McuToolChainPackage : public McuPackage

View File

@@ -15,6 +15,7 @@ QtcPlugin {
Depends { name: "QtSupport" }
files: [
"mcuabstractpackage.h",
"mcupackage.cpp",
"mcupackage.h",
"mcusupport.qrc",
@@ -36,6 +37,7 @@ QtcPlugin {
"mcusupportversiondetection.h",
"mcusupportcmakemapper.h",
"mcusupportcmakemapper.cpp",
"mcutargetdescription.h",
"mcukitinformation.cpp",
"mcukitinformation.h"
]

View File

@@ -66,6 +66,8 @@
#include <QVBoxLayout>
#include <QVariant>
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using namespace ProjectExplorer;
using namespace Utils;
@@ -81,22 +83,6 @@ static bool kitNeedsQtVersion()
return !HostOsInfo::isWindowsHost();
}
static void remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
{
using namespace CMakeProjectManager;
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
// First filter out all Qul2.x CMake vars
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
[&](const auto &configItem) {
return !cmakeVarNames.contains(configItem.key);
});
// Then append them with new values
config.append(cmakeVars);
CMakeConfigurationKitAspect::setConfiguration(kit, config);
}
static ToolChain *msvcToolChain(Id language)
{
ToolChain *toolChain = ToolChainManager::toolChain([language](const ToolChain *t) {
@@ -275,7 +261,7 @@ QVariant McuToolChainPackage::debuggerId() const
McuTarget::McuTarget(const QVersionNumber &qulVersion,
const Platform &platform,
OS os,
const QVector<McuPackage *> &packages,
const QVector<McuAbstractPackage *> &packages,
const McuToolChainPackage *toolChainPackage,
int colorDepth)
: m_qulVersion(qulVersion)
@@ -286,7 +272,7 @@ McuTarget::McuTarget(const QVersionNumber &qulVersion,
, m_colorDepth(colorDepth)
{}
const QVector<McuPackage *> &McuTarget::packages() const
const QVector<McuAbstractPackage *> &McuTarget::packages() const
{
return m_packages;
}
@@ -308,7 +294,7 @@ const McuTarget::Platform &McuTarget::platform() const
bool McuTarget::isValid() const
{
return Utils::allOf(packages(), [](McuPackage *package) {
return Utils::allOf(packages(), [](McuAbstractPackage *package) {
package->updateStatus();
return package->validStatus();
});
@@ -318,18 +304,20 @@ void McuTarget::printPackageProblems() const
{
for (auto package : packages()) {
package->updateStatus();
if (!package->validStatus())
if (!package->validStatus()) {
printMessage(tr("Error creating kit for target %1, package %2: %3")
.arg(McuSupportOptions::kitName(this),
package->label(),
package->statusText()),
true);
if (package->status() == McuPackage::ValidPackageMismatchedVersion)
}
if (package->status() == McuAbstractPackage::Status::ValidPackageMismatchedVersion) {
printMessage(tr("Warning creating kit for target %1, package %2: %3")
.arg(McuSupportOptions::kitName(this),
package->label(),
package->statusText()),
false);
}
}
}
@@ -356,7 +344,7 @@ McuSupportOptions::McuSupportOptions(QObject *parent)
, qtForMCUsSdkPackage(Sdk::createQtForMCUsPackage())
{
connect(qtForMCUsSdkPackage,
&McuPackage::changed,
&McuAbstractPackage::changed,
this,
&McuSupportOptions::populatePackagesAndTargets);
}
@@ -425,7 +413,7 @@ void McuSupportOptions::setQulDir(const FilePath &dir)
if (qtForMCUsSdkPackage->validStatus())
Sdk::targetsAndPackages(dir, &sdkRepository);
for (const auto &package : qAsConst(sdkRepository.packages))
connect(package, &McuPackage::changed, this, &McuSupportOptions::changed);
connect(package, &McuAbstractPackage::changed, this, &McuSupportOptions::changed);
emit changed();
}
@@ -469,6 +457,22 @@ static void setKitProperties(const QString &kitName,
k->setIrrelevantAspects(irrelevant);
}
void McuSupportOptions::remapQul2xCmakeVars(Kit *kit, const EnvironmentItems &envItems)
{
const auto cmakeVars = mapEnvVarsToQul2xCmakeVars(envItems);
const auto cmakeVarNames = Utils::transform(cmakeVars, &CMakeConfigItem::key);
// First filter out all Qul2.x CMake vars
auto config = Utils::filtered(CMakeConfigurationKitAspect::configuration(kit),
[&](const auto &configItem) {
return !cmakeVarNames.contains(configItem.key);
});
// Then append them with new values
config.append(cmakeVars);
CMakeConfigurationKitAspect::setConfiguration(kit, config);
}
static void setKitToolchains(Kit *k, const McuToolChainPackage *tcPackage)
{
switch (tcPackage->type()) {
@@ -541,9 +545,9 @@ static bool expectsCmakeVars(const McuTarget *mcuTarget)
return mcuTarget->qulVersion() >= QVersionNumber{2, 0};
}
static void setKitEnvironment(Kit *k,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
void McuSupportOptions::setKitEnvironment(Kit *k,
const McuTarget *mcuTarget,
const McuAbstractPackage *qtForMCUsSdkPackage)
{
EnvironmentItems changes;
QStringList pathAdditions;
@@ -555,7 +559,7 @@ static void setKitEnvironment(Kit *k,
&& !CMakeProjectManager::CMakeToolManager::defaultCMakeTool()->hasFileApi())
pathAdditions.append(qtForMCUsSdkPackage->path().pathAppended("bin").toUserOutput());
auto processPackage = [&pathAdditions, &changes](const McuPackage *package) {
auto processPackage = [&pathAdditions, &changes](const McuAbstractPackage *package) {
if (package->addToPath())
pathAdditions.append(package->path().toUserOutput());
if (!package->environmentVariableName().isEmpty())
@@ -578,7 +582,7 @@ static void setKitEnvironment(Kit *k,
// Hack, this problem should be solved in lower layer
if (expectsCmakeVars(mcuTarget)) {
remapQul2xCmakeVars(k, changes);
McuSupportOptions::remapQul2xCmakeVars(k, changes);
}
EnvironmentKitAspect::setEnvironmentChanges(k, changes);
@@ -586,11 +590,11 @@ static void setKitEnvironment(Kit *k,
static void setKitDependencies(Kit *k,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
NameValueItems dependencies;
auto processPackage = [&dependencies](const McuPackage *package) {
auto processPackage = [&dependencies](const McuAbstractPackage *package) {
if (!package->environmentVariableName().isEmpty())
dependencies.append({package->environmentVariableName(),
QDir::toNativeSeparators(package->detectionPath())});
@@ -606,7 +610,7 @@ static void setKitDependencies(Kit *k,
k->setIrrelevantAspects(irrelevant);
}
static void updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
void McuSupportOptions::updateKitEnvironment(Kit *k, const McuTarget *mcuTarget)
{
EnvironmentItems changes = EnvironmentKitAspect::environmentChanges(k);
for (auto package : mcuTarget->packages()) {
@@ -741,7 +745,7 @@ QList<Kit *> McuSupportOptions::existingKits(const McuTarget *mcuTarget)
}
QList<Kit *> McuSupportOptions::matchingKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
@@ -749,7 +753,7 @@ QList<Kit *> McuSupportOptions::matchingKits(const McuTarget *mcuTarget,
}
QList<Kit *> McuSupportOptions::upgradeableKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
return Utils::filtered(existingKits(mcuTarget), [mcuTarget, qtForMCUsSdkPackage](Kit *kit) {
return !kitUpToDate(kit, mcuTarget, qtForMCUsSdkPackage);
@@ -761,10 +765,9 @@ QList<Kit *> McuSupportOptions::kitsWithMismatchedDependencies(const McuTarget *
return Utils::filtered(existingKits(mcuTarget), [mcuTarget](Kit *kit) {
const auto environment = Utils::NameValueDictionary(
Utils::NameValueItem::toStringList(EnvironmentKitAspect::environmentChanges(kit)));
return Utils::anyOf(mcuTarget->packages(), [&environment](const McuPackage *package) {
return !package->environmentVariableName().isEmpty()
&& environment.value(package->environmentVariableName())
!= package->path().toUserOutput();
return Utils::anyOf(mcuTarget->packages(), [&environment](const McuAbstractPackage *package) {
return !package->environmentVariableName().isEmpty() &&
environment.value(package->environmentVariableName()) != package->path().toUserOutput();
});
});
}
@@ -783,7 +786,7 @@ void McuSupportOptions::removeOutdatedKits()
KitManager::deregisterKit(kit);
}
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk)
Kit *McuSupportOptions::newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk)
{
const auto init = [mcuTarget, qtForMCUsSdk](Kit *k) {
KitGuard kitGuard(k);
@@ -831,7 +834,7 @@ static FilePath kitDependencyPath(const Kit *kit, const QString &variableName)
bool McuSupportOptions::kitUpToDate(const Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage)
const McuAbstractPackage *qtForMCUsSdkPackage)
{
return kitQulVersion(kit) == mcuTarget->qulVersion()
&& kitDependencyPath(kit, qtForMCUsSdkPackage->environmentVariableName()).toUserOutput()
@@ -873,22 +876,22 @@ void McuSupportOptions::createAutomaticKits()
qtForMCUsPackage->updateStatus();
if (!qtForMCUsPackage->validStatus()) {
switch (qtForMCUsPackage->status()) {
case McuPackage::ValidPathInvalidPackage: {
const QString displayPath
= FilePath::fromString(qtForMCUsPackage->detectionPath()).toUserOutput();
case McuAbstractPackage::Status::ValidPathInvalidPackage: {
const QString displayPath = FilePath::fromString(qtForMCUsPackage->detectionPath())
.toUserOutput();
printMessage(tr("Path %1 exists, but does not contain %2.")
.arg(qtForMCUsPackage->path().toUserOutput(), displayPath),
true);
break;
}
case McuPackage::InvalidPath: {
case McuAbstractPackage::Status::InvalidPath: {
printMessage(tr("Path %1 does not exist. Add the path in Tools > Options > "
"Devices > MCU.")
.arg(qtForMCUsPackage->path().toUserOutput()),
true);
break;
}
case McuPackage::EmptyPath: {
case McuAbstractPackage::Status::EmptyPath: {
printMessage(tr("Missing %1. Add the path in Tools > Options > Devices > MCU.")
.arg(qtForMCUsPackage->detectionPath()),
true);
@@ -984,7 +987,7 @@ void McuSupportOptions::upgradeKits(UpgradeOption upgradeOption)
void McuSupportOptions::upgradeKitInPlace(ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdk)
const McuAbstractPackage *qtForMCUsSdk)
{
setKitProperties(kitName(mcuTarget), kit, mcuTarget, qtForMCUsSdk->path());
setKitEnvironment(kit, mcuTarget, qtForMCUsSdk);
@@ -1000,7 +1003,7 @@ void McuSupportOptions::fixKitsDependencies()
Sdk::targetsAndPackages(dir, &repo);
for (const auto &target : qAsConst(repo.mcuTargets)) {
if (target->isValid()) {
for (auto kit : kitsWithMismatchedDependencies(target)) {
for (auto* kit : kitsWithMismatchedDependencies(target)) {
updateKitEnvironment(kit, target);
}
}

View File

@@ -1,7 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2021
** The Qt Company Ltd.
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
@@ -26,8 +25,7 @@
#pragma once
#include "mcusupport_global.h"
#include <utils/environmentfwd.h>
#include <QObject>
#include <QVector>
#include <QVersionNumber>
@@ -48,7 +46,7 @@ class ToolChain;
namespace McuSupport {
namespace Internal {
class McuPackage;
class McuAbstractPackage;
class McuToolChainPackage;
void printMessage(const QString &message, bool important);
@@ -72,12 +70,12 @@ public:
McuTarget(const QVersionNumber &qulVersion,
const Platform &platform,
OS os,
const QVector<McuPackage *> &packages,
const QVector<McuAbstractPackage *> &packages,
const McuToolChainPackage *toolChainPackage,
int colorDepth = UnspecifiedColorDepth);
const QVersionNumber &qulVersion() const;
const QVector<McuPackage *> &packages() const;
const QVector<McuAbstractPackage *> &packages() const;
const McuToolChainPackage *toolChainPackage() const;
const Platform &platform() const;
OS os() const;
@@ -89,15 +87,15 @@ private:
const QVersionNumber m_qulVersion;
const Platform m_platform;
const OS m_os;
const QVector<McuPackage *> m_packages;
const QVector<McuAbstractPackage *> m_packages;
const McuToolChainPackage *m_toolChainPackage;
const int m_colorDepth;
};
}; // class McuTarget
class McuSdkRepository
{
public:
QVector<McuPackage *> packages;
QVector<McuAbstractPackage *> packages;
QVector<McuTarget *> mcuTargets;
void deletePackagesAndTargets();
@@ -110,32 +108,34 @@ class McuSupportOptions : public QObject
public:
enum UpgradeOption { Ignore, Keep, Replace };
McuSupportOptions(QObject *parent = nullptr);
explicit McuSupportOptions(QObject *parent = nullptr);
~McuSupportOptions() override;
McuPackage *qtForMCUsSdkPackage = nullptr;
McuAbstractPackage *qtForMCUsSdkPackage = nullptr;
McuSdkRepository sdkRepository;
void setQulDir(const Utils::FilePath &dir);
static void setKitEnvironment(ProjectExplorer::Kit *, const McuTarget *, const McuAbstractPackage *);
static void updateKitEnvironment(ProjectExplorer::Kit *, const McuTarget *);
static void remapQul2xCmakeVars(ProjectExplorer::Kit *, const Utils::EnvironmentItems &);
static Utils::FilePath qulDirFromSettings();
static QString kitName(const McuTarget *mcuTarget);
static QList<ProjectExplorer::Kit *> existingKits(const McuTarget *mcuTarget);
static QList<ProjectExplorer::Kit *> matchingKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage);
static QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage);
const McuAbstractPackage *qtForMCUsSdkPackage);
static QList<ProjectExplorer::Kit *> upgradeableKits(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdkPackage);
static QList<ProjectExplorer::Kit *> kitsWithMismatchedDependencies(const McuTarget *mcuTarget);
static QList<ProjectExplorer::Kit *> outdatedKits();
static void removeOutdatedKits();
static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuPackage *qtForMCUsSdk);
static ProjectExplorer::Kit *newKit(const McuTarget *mcuTarget, const McuAbstractPackage *qtForMCUsSdk);
static void createAutomaticKits();
static UpgradeOption askForKitUpgrades();
static void upgradeKits(UpgradeOption upgradeOption);
static void upgradeKitInPlace(ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdk);
const McuAbstractPackage *qtForMCUsSdk);
static void fixKitsDependencies();
void checkUpgradeableKits();
static void fixExistingKits();
@@ -148,7 +148,7 @@ public:
static QVersionNumber kitQulVersion(const ProjectExplorer::Kit *kit);
static bool kitUpToDate(const ProjectExplorer::Kit *kit,
const McuTarget *mcuTarget,
const McuPackage *qtForMCUsSdkPackage);
const McuAbstractPackage *qtForMCUsSdkPackage);
private:
void deletePackagesAndTargets();

View File

@@ -121,10 +121,8 @@ McuSupportOptionsWidget::McuSupportOptionsWidget()
&QComboBox::currentTextChanged,
this,
&McuSupportOptionsWidget::showMcuTargetPackages);
connect(m_options.qtForMCUsSdkPackage,
&McuPackage::changed,
this,
&McuSupportOptionsWidget::populateMcuTargetsComboBox);
connect(m_options.qtForMCUsSdkPackage, &McuAbstractPackage::changed,
this, &McuSupportOptionsWidget::populateMcuTargetsComboBox);
}
{

View File

@@ -31,6 +31,10 @@
#include "mcusupportoptionspage.h"
#include "mcusupportrunconfiguration.h"
#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND)
#include "test/unittest.h"
#endif
#include <coreplugin/coreconstants.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
@@ -59,14 +63,9 @@ public:
{Constants::RUNCONFIGURATION}};
McuSupportOptionsPage optionsPage;
McuDependenciesKitAspect environmentPathsKitAspect;
};
}; // class McuSupportPluginPrivate
static McuSupportPluginPrivate *dd = nullptr;
McuSupportPlugin::McuSupportPlugin()
{
setObjectName("McuSupportPlugin");
}
static McuSupportPluginPrivate* dd{nullptr};
McuSupportPlugin::~McuSupportPlugin()
{
@@ -79,6 +78,7 @@ bool McuSupportPlugin::initialize(const QStringList &arguments, QString *errorSt
Q_UNUSED(arguments)
Q_UNUSED(errorString)
setObjectName("McuSupportPlugin");
dd = new McuSupportPluginPrivate;
McuSupportOptions::registerQchFiles();
@@ -147,5 +147,14 @@ void McuSupportPlugin::askUserAboutMcuSupportKitsUpgrade()
ICore::infoBar()->addInfo(info);
}
QVector<QObject *> McuSupportPlugin::createTestObjects() const
{
QVector<QObject *> tests;
#if defined(WITH_TESTS) && defined(GOOGLE_TEST_IS_FOUND)
tests << new Test::McuSupportTest;
#endif
return tests;
}
} // namespace Internal
} // namespace McuSupport

View File

@@ -29,23 +29,25 @@
#include <extensionsystem/iplugin.h>
namespace McuSupport {
namespace Internal {
namespace McuSupport::Internal {
class McuSupportPlugin : public ExtensionSystem::IPlugin
class McuSupportPlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QtCreatorPlugin" FILE "McuSupport.json")
public:
McuSupportPlugin();
~McuSupportPlugin() override;
~McuSupportPlugin() final;
bool initialize(const QStringList &arguments, QString *errorString) final;
void extensionsInitialized() final;
bool initialize(const QStringList &arguments, QString *errorString) override;
void extensionsInitialized() override;
static void askUserAboutMcuSupportKitsSetup();
static void askUserAboutMcuSupportKitsUpgrade();
};
} // namespace Internal
} // namespace McuSupport
private:
QVector<QObject *> createTestObjects() const final;
}; // class McuSupportPlugin
} // namespace McuSupport::Internal

View File

@@ -28,6 +28,7 @@
#include "mcusupportconstants.h"
#include "mcusupportoptions.h"
#include "mcusupportversiondetection.h"
#include "mcutargetdescription.h"
#include <baremetal/baremetalconstants.h>
#include <coreplugin/icore.h>
@@ -330,40 +331,6 @@ static McuPackage *createRenesasProgrammerPackage()
envVar);
return result;
}
struct McuTargetDescription
{
enum class TargetType { MCU, Desktop };
QString qulVersion;
QString compatVersion;
struct
{
QString id;
QString name;
QString vendor;
QVector<int> colorDepths;
TargetType type;
} platform;
struct
{
QString id;
QStringList versions;
} toolchain;
struct
{
QString name;
QString defaultPath;
QString envVar;
QStringList versions;
} boardSdk;
struct
{
QString envVar;
QString boardSdkSubDir;
} freeRTOS;
};
static McuPackageVersionDetector *generatePackageVersionDetector(QString envVar)
{
if (envVar.startsWith("EVK"))
@@ -463,9 +430,9 @@ struct McuTargetFactory
return createTargetsImpl(description);
}
QVector<McuPackage *> getMcuPackages() const
QVector<McuAbstractPackage *> getMcuPackages() const
{
QVector<McuPackage *> packages;
QVector<McuAbstractPackage *> packages;
for (auto *package : qAsConst(boardSdkPkgs))
packages.append(package);
for (auto *package : qAsConst(freeRTOSPkgs))
@@ -483,7 +450,7 @@ protected:
tcPkg = createUnsupportedToolChainPackage();
for (auto os : {McuTarget::OS::BareMetal, McuTarget::OS::FreeRTOS}) {
for (int colorDepth : desc.platform.colorDepths) {
QVector<McuPackage *> required3rdPartyPkgs = {tcPkg};
QVector<McuAbstractPackage *> required3rdPartyPkgs = {tcPkg};
if (vendorPkgs.contains(desc.platform.vendor))
required3rdPartyPkgs.push_back(vendorPkgs.value(desc.platform.vendor));
@@ -566,7 +533,7 @@ protected:
} else
tcPkg = createUnsupportedToolChainPackage();
for (int colorDepth : desc.platform.colorDepths) {
QVector<McuPackage *> required3rdPartyPkgs;
QVector<McuAbstractPackage *> required3rdPartyPkgs;
// Desktop toolchains don't need any additional settings
if (tcPkg && !tcPkg->isDesktopToolchain()
&& tcPkg->type() != McuToolChainPackage::Type::Unsupported)
@@ -620,10 +587,10 @@ private:
QHash<QString, McuPackage *> boardSdkPkgs;
QHash<QString, McuPackage *> freeRTOSPkgs;
};
}; // struct McuTargetFactory
static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
QVector<McuPackage *> *packages)
QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &descriptions,
QVector<McuAbstractPackage *> *packages)
{
const QHash<QString, McuToolChainPackage *> tcPkgs = {
{{"armgcc"}, createArmGccPackage()},
@@ -652,8 +619,10 @@ static QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescrip
}
packages->append(
Utils::transform<QVector<McuPackage *>>(tcPkgs.values(),
[&](McuToolChainPackage *tcPkg) { return tcPkg; }));
Utils::transform<QVector<McuAbstractPackage *>>(tcPkgs.values(),
[&](McuToolChainPackage *tcPkg) {
return tcPkg;
}));
for (auto *package : vendorPkgs)
packages->append(package);
packages->append(targetFactory.getMcuPackages());
@@ -755,7 +724,7 @@ static McuTargetDescription parseDescriptionJsonV2x(const QString &qulVersion,
return description;
}
static McuTargetDescription parseDescriptionJson(const QByteArray &data)
McuTargetDescription parseDescriptionJson(const QByteArray &data)
{
const QJsonDocument document = QJsonDocument::fromJson(data);
const QJsonObject target = document.object();

View File

@@ -33,18 +33,26 @@
namespace McuSupport {
namespace Internal {
#define MAX_COMPATIBILITY_VERSION 1
constexpr int MAX_COMPATIBILITY_VERSION {1};
class McuSdkRepository;
class McuAbstractPackage;
class McuPackage;
class McuTarget;
namespace Sdk {
struct McuTargetDescription;
McuPackage *createQtForMCUsPackage();
bool checkDeprecatedSdkError(const Utils::FilePath &qulDir, QString &message);
void targetsAndPackages(const Utils::FilePath &qulDir, McuSdkRepository *repo);
McuTargetDescription parseDescriptionJson(const QByteArray &);
QVector<McuTarget *> targetsFromDescriptions(const QList<McuTargetDescription> &, QVector<McuAbstractPackage *> *);
Utils::FilePath kitsPath(const Utils::FilePath &dir);
Utils::FilePath packagePathFromSettings(const QString &settingsKey,

View File

@@ -0,0 +1,67 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include <QString>
#include <QStringList>
#include <QVector>
namespace McuSupport::Internal::Sdk {
struct McuTargetDescription
{
enum class TargetType { MCU, Desktop };
QString qulVersion;
QString compatVersion;
struct
{
QString id;
QString name;
QString vendor;
QVector<int> colorDepths;
TargetType type;
} platform;
struct
{
QString id;
QStringList versions;
} toolchain;
struct
{
QString name;
QString defaultPath;
QString envVar;
QStringList versions;
} boardSdk;
struct
{
QString envVar;
QString boardSdkSubDir;
} freeRTOS;
};
} // namespace McuSupport::Internal::Sdk

View File

@@ -0,0 +1,13 @@
find_package(Googletest MODULE)
if(TARGET Googletest)
message("Googletest target is present")
extend_qtc_plugin(McuSupport
CONDITION WITH_TESTS
DEPENDS Googletest
SOURCES
unittest.h unittest.cpp packagemock.h
)
else()
message("Googletest target is missing")
endif()

View File

@@ -0,0 +1,93 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
constexpr auto nxp_1064_json = R"({
"boardSdk": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "QUL_BOARD_SDK_DIR",
"description": "Board SDK for MIMXRT1064-EVK",
"id": "NXP_SDK_DIR",
"optional": false,
"type": "path"
}
],
"envVar": "EVK_MIMXRT1064_SDK_PATH",
"versions": ["2.10.0"]
},
"compatVersion": "1",
"freeRTOS": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "FREERTOS_DIR",
"defaultValue": "$QUL_BOARD_SDK_DIR/rtos/freertos/freertos_kernel",
"description": "FreeRTOS SDK for MIMXRT1064-EVK",
"id": "NXP_FREERTOS_DIR",
"optional": false,
"type": "path"
}
],
"envVar": "IMXRT1064_FREERTOS_DIR"
},
"platform": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "Qul_ROOT",
"description": "Qt for MCUs SDK",
"id": "Qul_DIR",
"optional": false,
"type": "path"
},
{
"cmakeOptionName": "MCUXPRESSO_IDE_PATH",
"defaultValue": {
"unix": "/usr/local/mcuxpressoide/",
"windows": "$ROOT/nxp/MCUXpressoIDE*"
}
}
],
"colorDepths": [16],
"environmentEntries": [],
"id": "MIMXRT1064-EVK-FREERTOS",
"pathEntries": [],
"vendor": "NXP"
},
"qulVersion": "2.0.0",
"toolchain": {
"cmakeCacheEntries": [
{
"cmakeOptionName": "QUL_TARGET_TOOLCHAIN_DIR",
"description": "IAR ARM Compiler",
"id": "IAR_DIR",
"optional": false,
"type": "path"
}
],
"id": "iar",
"versions": ["8.50.9"]
}
})";

View File

@@ -0,0 +1,63 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "mcuabstractpackage.h"
#include <utils/filepath.h>
#include <gmock/gmock.h>
namespace McuSupport::Internal {
class PackageMock : public McuAbstractPackage
{
public:
MOCK_METHOD(Utils::FilePath, basePath, (), (const));
MOCK_METHOD(Utils::FilePath, path, (), (const));
MOCK_METHOD(QString, label, (), (const));
MOCK_METHOD(Utils::FilePath, defaultPath, (), (const));
MOCK_METHOD(QString, detectionPath, (), (const));
MOCK_METHOD(QString, statusText, (), (const));
MOCK_METHOD(void, updateStatus, ());
MOCK_METHOD(Status, status, (), (const));
MOCK_METHOD(bool, validStatus, (), (const));
MOCK_METHOD(void, setDownloadUrl, (const QString &) );
MOCK_METHOD(void, setEnvironmentVariableName, (const QString &) );
MOCK_METHOD(const QString&, environmentVariableName, (), (const));
MOCK_METHOD(void, setAddToPath, (bool) );
MOCK_METHOD(bool, addToPath, (), (const));
MOCK_METHOD(void, writeGeneralSettings, (), (const));
MOCK_METHOD(bool, writeToSettings, (), (const));
MOCK_METHOD(void, setRelativePathModifier, (const QString &) );
MOCK_METHOD(void, setVersions, (const QStringList &) );
MOCK_METHOD(bool, automaticKitCreationEnabled, (), (const));
MOCK_METHOD(void, setAutomaticKitCreationEnabled, (const bool enabled));
MOCK_METHOD(QWidget *, widget, ());
}; // class PackageMock
} // namespace McuSupport::Internal

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "mcutargetdescription.h"
#include "nxp_1064_json.h"
#include "unittest.h"
#include "utils/filepath.h"
#include <cmakeprojectmanager/cmakeconfigitem.h>
#include <cmakeprojectmanager/cmakekitinformation.h>
#include <gmock/gmock.h>
#include <QJsonArray>
#include <QJsonDocument>
namespace McuSupport::Internal::Test {
using CMakeProjectManager::CMakeConfigItem;
using CMakeProjectManager::CMakeConfigurationKitAspect;
using ProjectExplorer::EnvironmentKitAspect;
using ProjectExplorer::KitManager;
using testing::Return;
using testing::ReturnRef;
using Utils::FilePath;
void McuSupportTest::initTestCase()
{
EXPECT_CALL(freeRtosPackage, environmentVariableName()).WillRepeatedly(ReturnRef(freeRtosEnvVar));
EXPECT_CALL(freeRtosPackage, validStatus()).WillRepeatedly(Return(true));
EXPECT_CALL(freeRtosPackage, path())
.WillRepeatedly(Return(FilePath::fromString(defaultfreeRtosPath)));
}
void McuSupportTest::test_parseBasicInfoFromJson()
{
const auto description = Sdk::parseDescriptionJson(nxp_1064_json);
QVERIFY(not description.freeRTOS.envVar.isEmpty());
QVERIFY(description.freeRTOS.boardSdkSubDir.isEmpty());
}
void McuSupportTest::test_addNewKit()
{
auto &kitManager{*KitManager::instance()};
QSignalSpy kitAddedSpy(&kitManager, &KitManager::kitAdded);
auto *newKit{McuSupportOptions::newKit(&mcuTarget, &freeRtosPackage)};
QVERIFY(newKit != nullptr);
QCOMPARE(kitAddedSpy.count(), 1);
QList<QVariant> arguments = kitAddedSpy.takeFirst();
auto *createdKit = qvariant_cast<Kit *>(arguments.at(0));
QVERIFY(createdKit != nullptr);
QCOMPARE(createdKit, newKit);
auto cmakeAspect{CMakeConfigurationKitAspect{}};
QVERIFY(createdKit->hasValue(cmakeAspect.id()));
QVERIFY(createdKit->value(cmakeAspect.id(), freeRtosCmakeVar).isValid());
}
void McuSupportTest::test_addFreeRtosCmakeVarToKit()
{
McuSupportOptions::updateKitEnvironment(&kit, &mcuTarget);
QVERIFY(kit.hasValue(EnvironmentKitAspect::id()));
QVERIFY(kit.isValid());
QVERIFY(not kit.allKeys().empty());
const auto &cmakeConfig{CMakeConfigurationKitAspect::configuration(&kit)};
QCOMPARE(cmakeConfig.size(), 1);
CMakeConfigItem expectedCmakeVar{freeRtosCmakeVar.toLocal8Bit(),
defaultfreeRtosPath.toLocal8Bit()};
QVERIFY(cmakeConfig.contains(expectedCmakeVar));
}
} // namespace McuSupport::Internal::Test

View File

@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "mcusupportoptions.h"
#include "mcusupportplugin.h"
#include "mcusupportsdk.h"
#include "mcupackage.h"
#include "packagemock.h"
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <utils/filepath.h>
#include <utils/fileutils.h>
#include <QObject>
#include <QSignalSpy>
#include <QTest>
namespace McuSupport::Internal::Test {
using ProjectExplorer::Kit;
class McuSupportTest : public QObject
{
Q_OBJECT
private slots:
void initTestCase();
void test_addFreeRtosCmakeVarToKit();
void test_addNewKit();
void test_parseBasicInfoFromJson();
private:
QVersionNumber currentQulVersion{2, 0};
const QString id{"target_id"};
const QString name{"target_name"};
const QString vendor{"target_vendor"};
const QString freeRtosEnvVar{"EVK_MIMXRT1170_FREERTOS_PATH"};
const QString freeRtosCmakeVar{"FREERTOS_DIR"};
const QString defaultfreeRtosPath{"/opt/freertos/default"};
PackageMock freeRtosPackage;
Kit kit;
McuToolChainPackage toolchainPackage{{}, {}, {}, {}, {}};
const McuTarget::Platform platform{id, name, vendor};
McuTarget mcuTarget{currentQulVersion,
platform,
McuTarget::OS::FreeRTOS,
{&freeRtosPackage},
&toolchainPackage};
}; // class McuSupportTest
} // namespace McuSupport::Internal::Test

View File

@@ -1110,6 +1110,10 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
<< ("*-*-*-*-" + compilerName
+ "-[1-9]*"); // "x86_64-pc-linux-gnu-gcc-7.4.1"
}
nameFilters = transform(nameFilters,
[os = device ? device->osType() : HostOsInfo::hostOs()](const QString &baseName) {
return OsSpecificAspects::withExecutableSuffix(os, baseName);
});
FilePaths compilerPaths;
@@ -1145,9 +1149,6 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
for (const FilePath &dir : qAsConst(searchPaths)) {
static const QRegularExpression regexp(binaryRegexp);
QDir binDir(dir.toString());
nameFilters = transform(nameFilters, [](const QString &baseName) {
return HostOsInfo::withExecutableSuffix(baseName);
});
const QStringList fileNames = binDir.entryList(nameFilters,
QDir::Files | QDir::Executable);
for (const QString &fileName : fileNames) {

View File

@@ -166,8 +166,8 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
QPair<FilePath, int> position = parseFileName(match.captured(1));
const FilePath filePath = absoluteFilePath(position.first);
LinkSpecs linkSpecs;
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
if (!m_lastTask.isNull() && line.contains("note: ")) {
addLinkSpecForAbsoluteFilePath(linkSpecs, filePath, position.second, match, 1);
const int offset = std::accumulate(m_lastTask.details.cbegin(),
m_lastTask.details.cend(), 0,
[](int total, const QString &line) { return total + line.length() + 1;});
@@ -181,6 +181,7 @@ MsvcParser::Result MsvcParser::processCompileLine(const QString &line)
m_lastTask = CompileTask(taskType(match.captured(2)),
match.captured(3) + match.captured(4).trimmed(), // description
filePath, position.second);
m_linkSpecs << linkSpecs;
m_lines = 1;
}
return {Status::InProgress, linkSpecs};

View File

@@ -314,6 +314,16 @@ static const RunConfiguration *runConfigForNode(const Target *target, const Proj
return target->activeRunConfiguration();
}
static bool hideBuildMenu()
{
return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_BUILD, false).toBool();
}
static bool hideDebugMenu()
{
return Core::ICore::settings()->value(Constants::SETTINGS_MENU_HIDE_DEBUG, false).toBool();
}
static bool canOpenTerminalWithRunEnv(const Project *project, const ProjectNode *node)
{
if (!project)
@@ -938,14 +948,17 @@ bool ProjectExplorerPlugin::initialize(const QStringList &arguments, QString *er
// build menu
ActionContainer *mbuild =
ActionManager::createMenu(Constants::M_BUILDPROJECT);
mbuild->menu()->setTitle(tr("&Build"));
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
if (!hideBuildMenu())
menubar->addMenu(mbuild, Core::Constants::G_VIEW);
// debug menu
ActionContainer *mdebug =
ActionManager::createMenu(Constants::M_DEBUG);
mdebug->menu()->setTitle(tr("&Debug"));
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
if (!hideDebugMenu())
menubar->addMenu(mdebug, Core::Constants::G_VIEW);
ActionContainer *mstartdebugging =
ActionManager::createMenu(Constants::M_DEBUG_STARTDEBUGGING);

View File

@@ -235,6 +235,9 @@ const char ADD_FILES_DIALOG_FILTER_HISTORY_KEY[] = "ProjectExplorer.AddFilesFilt
const char PROJECT_ROOT_PATH_KEY[] = "ProjectExplorer.Project.RootPath";
const char STARTUPSESSION_KEY[] = "ProjectExplorer/SessionToRestore";
const char LASTSESSION_KEY[] = "ProjectExplorer/StartupSession";
const char SETTINGS_MENU_HIDE_BUILD[] = "Menu/HideBuild";
const char SETTINGS_MENU_HIDE_DEBUG[] = "Menu/HideDebug";
const char SETTINGS_MENU_HIDE_ANALYZE[] = "Menu/HideAnalyze";
// UI texts
PROJECTEXPLORER_EXPORT QString msgAutoDetected();

View File

@@ -144,6 +144,9 @@ bool AssetsLibraryModel::renameFolder(const QString &folderPath, const QString &
return true;
dir.cdUp();
saveExpandedState(loadExpandedState(folderPath), dir.absoluteFilePath(newName));
return dir.rename(oldName, newName);
}
@@ -341,8 +344,14 @@ void AssetsLibraryModel::setRootPath(const QString &path)
beginResetModel();
m_assetsDir = new AssetsLibraryDir(path, 0, true, this);
bool noAssets = parseDirRecursive(m_assetsDir, 1);
setIsEmpty(noAssets);
bool isEmpty = parseDirRecursive(m_assetsDir, 1);
setIsEmpty(isEmpty);
bool noAssets = m_searchText.isEmpty() && isEmpty;
// noAssets: the model has no asset files (project has no assets added)
// isEmpty: the model has no asset files (assets could exist but are filtered out)
m_assetsDir->setDirVisible(!noAssets); // if there are no assets, hide all empty asset folders
endResetModel();
}

View File

@@ -59,6 +59,8 @@ public:
void setRootPath(const QString &path);
void setSearchText(const QString &searchText);
bool isEmpty() const;
static const QStringList &supportedImageSuffixes();
static const QStringList &supportedFragmentShaderSuffixes();
static const QStringList &supportedShaderSuffixes();
@@ -93,7 +95,6 @@ signals:
private:
const QSet<QString> &supportedSuffixes() const;
bool isEmpty() const;
void setIsEmpty(bool empty);
SynchronousImageCache &m_fontImageCache;

View File

@@ -201,10 +201,11 @@ QList<QToolButton *> AssetsLibraryWidget::createToolBarWidgets()
void AssetsLibraryWidget::handleSearchfilterChanged(const QString &filterText)
{
if (filterText != m_filterText) {
m_filterText = filterText;
updateSearch();
}
if (filterText == m_filterText || (m_assetsModel->isEmpty() && filterText.contains(m_filterText)))
return;
m_filterText = filterText;
updateSearch();
}
void AssetsLibraryWidget::handleAddAsset()

View File

@@ -389,7 +389,7 @@ void ItemLibraryAssetImporter::postParseQuick3DAsset(const ParseData &pd)
if (braceIdx != -1) {
int nlIdx = content.lastIndexOf('\n', braceIdx);
QByteArray rootItem = content.mid(nlIdx, braceIdx - nlIdx).trimmed();
if (rootItem == "Node") { // a 3D object
if (rootItem == "Node" || rootItem == "Model") { // a 3D object
// create hints file with proper hints
QFile file(outDir.path() + '/' + fi.baseName() + ".hints");
file.open(QIODevice::WriteOnly | QIODevice::Text);

View File

@@ -68,6 +68,11 @@ QString ItemLibraryItem::requiredImport() const
return m_itemLibraryEntry.requiredImport();
}
QString ItemLibraryItem::componentSource() const
{
return m_itemLibraryEntry.customComponentSource();
}
bool ItemLibraryItem::setVisible(bool isVisible)
{
if (isVisible != m_isVisible) {

View File

@@ -45,6 +45,7 @@ class ItemLibraryItem: public QObject
Q_PROPERTY(QString componentPath READ componentPath FINAL)
Q_PROPERTY(bool itemUsable READ isUsable FINAL)
Q_PROPERTY(QString itemRequiredImport READ requiredImport FINAL)
Q_PROPERTY(QString itemComponentSource READ componentSource FINAL)
public:
ItemLibraryItem(const ItemLibraryEntry &itemLibraryEntry, bool isImported, QObject *parent);
@@ -55,6 +56,7 @@ public:
QString itemLibraryIconPath() const;
QString componentPath() const;
QString requiredImport() const;
QString componentSource() const;
bool setVisible(bool isVisible);
bool isVisible() const;

View File

@@ -32,6 +32,7 @@
#include <designeractionmanager.h>
#include <designermcumanager.h>
#include <documentmanager.h>
#include <itemlibraryimageprovider.h>
#include <itemlibraryinfo.h>
#include <itemlibrarymodel.h>
@@ -269,6 +270,11 @@ void ItemLibraryWidget::handleAddImport(int index)
updateSearch();
}
void ItemLibraryWidget::goIntoComponent(const QString &source)
{
DocumentManager::goIntoComponent(source);
}
void ItemLibraryWidget::delayedUpdateModel()
{
static bool disableTimer = DesignerSettings::getValue(DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER).toBool();

View File

@@ -95,6 +95,7 @@ public:
Q_INVOKABLE void addImportForItem(const QString &importUrl);
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
Q_INVOKABLE void handleAddImport(int index);
Q_INVOKABLE void goIntoComponent(const QString &source);
signals:
void itemActivated(const QString &itemName);

View File

@@ -34,35 +34,64 @@ ChooseFromPropertyListFilter::ChooseFromPropertyListFilter(const NodeMetaInfo &i
const NodeMetaInfo &parentInfo,
bool breakOnFirst)
{
TypeName typeName = insertInfo.typeName();
TypeName superClass = insertInfo.directSuperClass().typeName();
TypeName nodePackage = insertInfo.typeName().replace(insertInfo.simplifiedTypeName(), "");
TypeName targetPackage = parentInfo.typeName().replace(parentInfo.simplifiedTypeName(), "");
if (!nodePackage.contains(targetPackage))
return;
// TODO: Metainfo based matching system (QDS-6240)
// Common base types cause too many rarely valid matches, so they are ignored
const QSet<TypeName> ignoredTypes {"<cpp>.QObject",
"<cpp>.QQuickItem",
"<cpp>.QQuick3DObject",
"QtQuick.Item",
"QtQuick3D.Object3D",
"QtQuick3D.Node",
"QtQuick3D.Particles3D.ParticleSystem3D"};
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
for (const PropertyName &name : targetNodeNameList) {
if (!name.contains('.')) {
TypeName propType = parentInfo.propertyTypeName(name).replace("<cpp>.", targetPackage);
// Skip properties that are not sub classes of anything
if (propType.contains('.')
&& !ignoredTypes.contains(propType)
&& (typeName == propType || propType == superClass)
&& parentInfo.propertyIsWritable(propType)) {
propertyList.append(QString::fromLatin1(name));
if (breakOnFirst)
break;
// Fall back to a hardcoded list of supported cases:
// Texture
// -> DefaultMaterial
// -> PrincipledMaterial
// -> SpriteParticle3D
// -> TextureInput
// -> SceneEnvironment
// Effect
// -> SceneEnvironment
// Shader, Command, Buffer
// -> Pass
// InstanceListEntry
// -> InstanceList
// Pass
// -> Effect
const TypeName textureType = "QtQuick3D.Texture";
if (insertInfo.isSubclassOf(textureType)) {
const TypeName textureTypeCpp = "<cpp>.QQuick3DTexture";
if (parentInfo.isSubclassOf("QtQuick3D.DefaultMaterial")
|| parentInfo.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
// All texture properties are valid targets
const PropertyNameList targetNodeNameList = parentInfo.propertyNames();
for (const PropertyName &name : targetNodeNameList) {
TypeName propType = parentInfo.propertyTypeName(name);
if (propType == textureType || propType == textureTypeCpp) {
propertyList.append(QString::fromLatin1(name));
if (breakOnFirst)
return;
}
}
} else if (parentInfo.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
propertyList.append("sprite");
} else if (parentInfo.isSubclassOf("QtQuick3D.TextureInput")) {
propertyList.append("texture");
} else if (parentInfo.isSubclassOf("QtQuick3D.SceneEnvironment")) {
propertyList.append("lightProbe");
}
} else if (insertInfo.isSubclassOf("QtQuick3D.Effect")) {
if (parentInfo.isSubclassOf("QtQuick3D.SceneEnvironment"))
propertyList.append("effects");
} else if (insertInfo.isSubclassOf("QtQuick3D.Shader")) {
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
propertyList.append("shaders");
} else if (insertInfo.isSubclassOf("QtQuick3D.Command")) {
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
propertyList.append("commands");
} else if (insertInfo.isSubclassOf("QtQuick3D.Buffer")) {
if (parentInfo.isSubclassOf("QtQuick3D.Pass"))
propertyList.append("output");
} else if (insertInfo.isSubclassOf("QtQuick3D.InstanceListEntry")) {
if (parentInfo.isSubclassOf("QtQuick3D.InstanceList"))
propertyList.append("instances");
} else if (insertInfo.isSubclassOf("QtQuick3D.Pass")) {
if (parentInfo.isSubclassOf("QtQuick3D.Effect"))
propertyList.append("passes");
}
}
@@ -110,14 +139,6 @@ TypeName ChooseFromPropertyListDialog::selectedProperty() const
ChooseFromPropertyListDialog *ChooseFromPropertyListDialog::createIfNeeded(
const ModelNode &targetNode, const ModelNode &newNode, QWidget *parent)
{
TypeName typeName = newNode.type();
// Component matches cases where you don't want to insert a plain component,
// such as layer.effect. Also, default property is often a Component (typically 'delegate'),
// and inserting into such property will silently overwrite implicit component, if any.
if (typeName == "QtQml.Component")
return nullptr;
const NodeMetaInfo info = newNode.metaInfo();
const NodeMetaInfo targetInfo = targetNode.metaInfo();
ChooseFromPropertyListFilter *filter = new ChooseFromPropertyListFilter(info, targetInfo);

View File

@@ -581,21 +581,29 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
addImport(import);
}
bool moveNodesAfter = true;
m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] {
for (const QString &assetPath : assetsPaths) {
auto assetTypeAndData = AssetsLibraryWidget::getAssetTypeAndData(assetPath);
QString assetType = assetTypeAndData.first;
QString assetData = QString::fromUtf8(assetTypeAndData.second);
if (assetType == "application/vnd.bauhaus.libraryresource.image")
currNode = handleItemLibraryImageDrop(assetPath, targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.font")
currNode = handleItemLibraryFontDrop(assetData, targetProperty, rowModelIndex); // assetData is fontFamily
else if (assetType == "application/vnd.bauhaus.libraryresource.shader")
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f", targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.sound")
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty, rowModelIndex);
else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d")
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty, rowModelIndex);
if (assetType == "application/vnd.bauhaus.libraryresource.image") {
currNode = handleItemLibraryImageDrop(assetPath, targetProperty,
rowModelIndex, moveNodesAfter);
} else if (assetType == "application/vnd.bauhaus.libraryresource.font") {
currNode = handleItemLibraryFontDrop(assetData, // assetData is fontFamily
targetProperty, rowModelIndex);
} else if (assetType == "application/vnd.bauhaus.libraryresource.shader") {
currNode = handleItemLibraryShaderDrop(assetPath, assetData == "f",
targetProperty, rowModelIndex,
moveNodesAfter);
} else if (assetType == "application/vnd.bauhaus.libraryresource.sound") {
currNode = handleItemLibrarySoundDrop(assetPath, targetProperty,
rowModelIndex);
} else if (assetType == "application/vnd.bauhaus.libraryresource.texture3d") {
currNode = handleItemLibraryTexture3dDrop(assetPath, targetProperty,
rowModelIndex, moveNodesAfter);
}
if (currNode.isValid())
addedNodes.append(currNode);
@@ -603,7 +611,8 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
});
if (!addedNodes.isEmpty()) {
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
if (moveNodesAfter)
moveNodesInteractive(targetProperty, addedNodes, rowNumber);
m_view->setSelectedModelNodes(addedNodes);
}
}
@@ -682,21 +691,22 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
dialog->exec();
if (soloProperty || dialog->result() == QDialog::Accepted) {
TypeName selectedProp = dialog->selectedProperty();
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
if ((newModelNode.isSubclassOf("QtQuick3D.Shader") || newModelNode.isSubclassOf("QtQuick3D.Command"))
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) {
NodeAbstractProperty parentProp = targetProperty.parentProperty();
if (parentProp.isValid()) {
targetProperty = parentProp;
ModelNode targetModel = targetProperty.parentModelNode();
targetRowNumber = rowCount(indexForModelNode(targetModel));
// Move node to new parent within the same transaction as we don't
// want undo to place the node under invalid parent
moveNodesInteractive(targetProperty, {newQmlObjectNode}, targetRowNumber, false);
moveNodesAfter = false;
}
// Pass and TextureInput can't have children, so we have to move nodes under parent
if (((newModelNode.isSubclassOf("QtQuick3D.Shader")
|| newModelNode.isSubclassOf("QtQuick3D.Command")
|| newModelNode.isSubclassOf("QtQuick3D.Buffer"))
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass"))
|| (newModelNode.isSubclassOf("QtQuick3D.Texture")
&& targetProperty.parentModelNode().isSubclassOf("QtQuick3D.TextureInput"))) {
if (moveNodeToParent(targetProperty, newQmlObjectNode)) {
targetProperty = targetProperty.parentProperty();
moveNodesAfter = false;
}
}
if (targetNode.metaInfo().propertyIsListProperty(selectedProp)) {
BindingProperty listProp = targetNode.bindingProperty(selectedProp);
listProp.addModelNodeToArray(newModelNode);
validContainer = true;
} else {
@@ -778,7 +788,8 @@ void NavigatorTreeModel::handleItemLibraryItemDrop(const QMimeData *mimeData, in
ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePath,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{
QTC_ASSERT(m_view, return {});
@@ -788,7 +799,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryImageDrop(const QString &imagePat
ModelNode newModelNode;
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode)) {
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePathRelative, newModelNode, outMoveNodesAfter)) {
if (targetNode.isSubclassOf("QtQuick.Image") || targetNode.isSubclassOf("QtQuick.BorderImage")) {
// if dropping an image on an existing image, set the source
targetNode.variantProperty("source").setValue(imagePathRelative);
@@ -846,9 +857,23 @@ void NavigatorTreeModel::addImport(const QString &importName)
}
}
bool QmlDesigner::NavigatorTreeModel::moveNodeToParent(const NodeAbstractProperty &targetProperty,
const ModelNode &node)
{
NodeAbstractProperty parentProp = targetProperty.parentProperty();
if (parentProp.isValid()) {
ModelNode targetModel = parentProp.parentModelNode();
int targetRowNumber = rowCount(indexForModelNode(targetModel));
moveNodesInteractive(parentProp, {node}, targetRowNumber, false);
return true;
}
return false;
}
ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{
QTC_ASSERT(m_view, return {});
@@ -863,29 +888,37 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
: "Shader.Vertex");
targetNode.variantProperty("shader").setValue(relPath);
} else {
// create a new Shader
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryShaderDrop", [&] {
// create a new Shader
ItemLibraryEntry itemLibraryEntry;
itemLibraryEntry.setName("Shader");
itemLibraryEntry.setType("QtQuick3D.Shader", 1, 0);
// set shader properties
PropertyName prop = "shader";
QString type = "QByteArray";
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
prop = "stage";
type = "enum";
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
itemLibraryEntry.addProperty(prop, type, val);
// set shader properties
PropertyName prop = "shader";
QString type = "QByteArray";
QVariant val = relPath;
itemLibraryEntry.addProperty(prop, type, val);
prop = "stage";
type = "enum";
val = isFragShader ? "Shader.Fragment" : "Shader.Vertex";
itemLibraryEntry.addProperty(prop, type, val);
// create a texture
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
targetProperty, false);
// create a texture
newModelNode = QmlItemNode::createQmlObjectNode(m_view, itemLibraryEntry, {},
targetProperty, false);
// Rename the node based on shader source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
// Rename the node based on shader source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
// Passes can't have children, so move shader node under parent
if (targetProperty.parentModelNode().isSubclassOf("QtQuick3D.Pass")) {
BindingProperty listProp = targetNode.bindingProperty("shaders");
listProp.addModelNodeToArray(newModelNode);
outMoveNodesAfter = !moveNodeToParent(targetProperty, newModelNode);
}
});
}
return newModelNode;
@@ -932,7 +965,8 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3DPath,
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex)
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter)
{
QTC_ASSERT(m_view, return {});
@@ -947,7 +981,7 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
ModelNode newModelNode;
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode)) {
if (!dropAsImage3dTexture(targetNode, targetProperty, imagePath, newModelNode, outMoveNodesAfter)) {
m_view->executeInTransaction("NavigatorTreeModel::handleItemLibraryTexture3dDrop", [&] {
// create a standalone Texture3D at drop location
newModelNode = createTextureNode(targetProperty, imagePath);
@@ -962,8 +996,23 @@ ModelNode NavigatorTreeModel::handleItemLibraryTexture3dDrop(const QString &tex3
bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
const NodeAbstractProperty &targetProp,
const QString &imagePath,
ModelNode &newNode)
ModelNode &newNode,
bool &outMoveNodesAfter)
{
auto bindToProperty = [&](const PropertyName &propName, bool sibling) {
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
newNode = createTextureNode(targetProp, imagePath);
if (newNode.isValid()) {
targetNode.bindingProperty(propName).setExpression(newNode.validId());
// If dropping an image on e.g. TextureInput, create a texture on the same level as
// target, as the target doesn't support Texture children (QTBUG-86219)
if (sibling)
outMoveNodesAfter = !moveNodeToParent(targetProp, newNode);
}
});
};
if (targetNode.isSubclassOf("QtQuick3D.DefaultMaterial")
|| targetNode.isSubclassOf("QtQuick3D.PrincipledMaterial")) {
// if dropping an image on a material, create a texture instead of image
@@ -986,16 +1035,13 @@ bool NavigatorTreeModel::dropAsImage3dTexture(const ModelNode &targetNode,
delete dialog;
return true;
} else if (targetNode.isSubclassOf("QtQuick3D.TextureInput")) {
// If dropping an image on a TextureInput, create a texture on the same level as
// TextureInput, as the TextureInput doesn't support Texture children (QTBUG-86219)
m_view->executeInTransaction("NavigatorTreeModel::dropAsImage3dTexture", [&] {
NodeAbstractProperty parentProp = targetProp.parentProperty();
newNode = createTextureNode(parentProp, imagePath);
if (newNode.isValid()) {
// Automatically set the texture to texture property
targetNode.bindingProperty("texture").setExpression(newNode.validId());
}
});
bindToProperty("texture", true);
return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.Particles3D.SpriteParticle3D")) {
bindToProperty("sprite", false);
return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.SceneEnvironment")) {
bindToProperty("lightProbe", false);
return newNode.isValid();
} else if (targetNode.isSubclassOf("QtQuick3D.Texture")) {
// if dropping an image on an existing texture, set the source

View File

@@ -115,21 +115,24 @@ private:
void handleInternalDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
void handleItemLibraryItemDrop(const QMimeData *mimeData, int rowNumber, const QModelIndex &dropModelIndex);
ModelNode handleItemLibraryImageDrop(const QString &imagePath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
ModelNode handleItemLibraryFontDrop(const QString &fontFamily, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryShaderDrop(const QString &shaderPath, bool isFragShader,
NodeAbstractProperty targetProperty, const QModelIndex &rowModelIndex);
NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex,
bool &outMoveNodesAfter);
ModelNode handleItemLibrarySoundDrop(const QString &soundPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
ModelNode handleItemLibraryTexture3dDrop(const QString &tex3DPath, NodeAbstractProperty targetProperty,
const QModelIndex &rowModelIndex);
const QModelIndex &rowModelIndex, bool &outMoveNodesAfter);
bool dropAsImage3dTexture(const ModelNode &targetNode, const NodeAbstractProperty &targetProp,
const QString &imagePath, ModelNode &newNode);
const QString &imagePath, ModelNode &newNode, bool &outMoveNodesAfter);
ModelNode createTextureNode(const NodeAbstractProperty &targetProp, const QString &imagePath);
QList<QPersistentModelIndex> nodesToPersistentIndex(const QList<ModelNode> &modelNodes);
void addImport(const QString &importName);
QList<ModelNode> filteredList(const NodeListProperty &property, bool filter, bool reverseOrder) const;
bool moveNodeToParent(const NodeAbstractProperty &targetProperty, const ModelNode &newModelNode);
QPointer<NavigatorView> m_view;
mutable QHash<ModelNode, QModelIndex> m_nodeIndexHash;

View File

@@ -108,14 +108,19 @@ static inline void applyProperties(ModelNode &node, const QHash<PropertyName, QV
}
}
static void openFileComponent(const ModelNode &modelNode)
static void openFileComponentForFile(const QString &fileName)
{
QmlDesignerPlugin::instance()->viewManager().nextFileIsCalledInternally();
Core::EditorManager::openEditor(FilePath::fromString(modelNode.metaInfo().componentFileName()),
Core::EditorManager::openEditor(FilePath::fromString(fileName),
Utils::Id(),
Core::EditorManager::DoNotMakeVisible);
}
static void openFileComponent(const ModelNode &modelNode)
{
openFileComponentForFile(modelNode.metaInfo().componentFileName());
}
static void openFileComponentForDelegate(const ModelNode &modelNode)
{
openFileComponent(modelNode.nodeProperty("delegate").modelNode());
@@ -305,6 +310,11 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
return false;
}
void DocumentManager::goIntoComponent(const QString &fileName)
{
openFileComponentForFile(fileName);
}
bool DocumentManager::createFile(const QString &filePath, const QString &contents)
{
Utils::TextFileFormat textFileFormat;

View File

@@ -52,6 +52,7 @@ public:
void removeEditors(const QList<Core::IEditor *> &editors);
static bool goIntoComponent(const ModelNode &modelNode);
static void goIntoComponent(const QString &fileName);
static bool createFile(const QString &filePath, const QString &contents);
static void addFileToVersionControl(const QString &directoryPath, const QString &newFilePath);

View File

@@ -146,7 +146,7 @@ void FileDownloader::start()
QNetworkRequest::UserVerifiedRedirectPolicy);
QNetworkReply *reply = Utils::NetworkAccessManager::instance()->get(request);
QNetworkReply::connect(reply, &QNetworkReply::readyRead, [this, reply]() {
QNetworkReply::connect(reply, &QNetworkReply::readyRead, this, [this, reply]() {
m_tempFile.write(reply->readAll());
});
@@ -165,7 +165,7 @@ void FileDownloader::start()
emit reply->redirectAllowed();
});
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error()) {
m_tempFile.remove();
qDebug() << Q_FUNC_INFO << m_url << reply->errorString();
@@ -246,7 +246,7 @@ void FileDownloader::probeUrl()
emit reply->redirectAllowed();
});
QNetworkReply::connect(reply, &QNetworkReply::finished, [this, reply]() {
QNetworkReply::connect(reply, &QNetworkReply::finished, this, [this, reply]() {
if (reply->error())
return;
@@ -259,6 +259,7 @@ void FileDownloader::probeUrl()
QNetworkReply::connect(reply,
&QNetworkReply::errorOccurred,
this,
[this, reply](QNetworkReply::NetworkError code) {
// QNetworkReply::HostNotFoundError
// QNetworkReply::ContentNotFoundError
@@ -282,7 +283,7 @@ FileExtractor::FileExtractor(QObject *parent)
m_timer.setInterval(100);
m_timer.setSingleShot(false);
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, [this]() {
QObject::connect(this, &FileExtractor::targetFolderExistsChanged, this, [this]() {
if (targetFolderExists()) {
m_birthTime = QFileInfo(m_targetPath.toString() + "/" + m_archiveName).birthTime();
} else
@@ -389,33 +390,34 @@ void FileExtractor::extract()
qint64 bytesBefore = QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
qint64 compressedSize = QFileInfo(m_sourceFile.toString()).size();
QTimer::connect(&m_timer, &QTimer::timeout, [this, bytesBefore, targetFolder, compressedSize]() {
static QHash<QString, int> hash;
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
QTimer::connect(
&m_timer, &QTimer::timeout, this, [this, bytesBefore, targetFolder, compressedSize]() {
static QHash<QString, int> hash;
QDirIterator it(targetFolder, {"*.*"}, QDir::Files, QDirIterator::Subdirectories);
int count = 0;
while (it.hasNext()) {
if (!hash.contains(it.fileName())) {
m_currentFile = it.fileName();
hash.insert(m_currentFile, 0);
emit currentFileChanged();
int count = 0;
while (it.hasNext()) {
if (!hash.contains(it.fileName())) {
m_currentFile = it.fileName();
hash.insert(m_currentFile, 0);
emit currentFileChanged();
}
it.next();
count++;
}
it.next();
count++;
}
qint64 currentSize = bytesBefore
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
qint64 currentSize = bytesBefore
- QStorageInfo(m_targetPath.toFileInfo().dir()).bytesAvailable();
// We can not get the uncompressed size of the archive yet, that is why we use an
// approximation. We assume a 50% compression rate.
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
emit progressChanged();
// We can not get the uncompressed size of the archive yet, that is why we use an
// approximation. We assume a 50% compression rate.
m_progress = std::min(100ll, currentSize * 100 / compressedSize * 2);
emit progressChanged();
m_size = QString::number(currentSize);
m_count = QString::number(count);
emit sizeChanged();
});
m_size = QString::number(currentSize);
m_count = QString::number(count);
emit sizeChanged();
});
QObject::connect(archive, &Utils::Archive::outputReceived, this, [this](const QString &output) {
m_detailedText += output;

View File

@@ -43,6 +43,7 @@
#include <projectexplorer/jsonwizard/jsonwizardfactory.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorerconstants.h>
#include <projectexplorer/projectmanager.h>
#include <qmlprojectmanager/qmlproject.h>
@@ -59,18 +60,21 @@
#include <QAbstractListModel>
#include <QApplication>
#include <QCheckBox>
#include <QDesktopServices>
#include <QFileInfo>
#include <QFontDatabase>
#include <QGroupBox>
#include <QPointer>
#include <QShortcut>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickView>
#include <QQuickWidget>
#include <QSettings>
#include <QShortcut>
#include <QTimer>
#include <QVBoxLayout>
#include <algorithm>
#include <memory>
@@ -758,11 +762,109 @@ WelcomeMode::WelcomeMode()
[](const QString &path) { return QFileInfo::exists(path); }));
}
static bool hideBuildMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD, false)
.toBool();
}
static bool hideDebugMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG, false)
.toBool();
}
static bool hideAnalyzeMenuSetting()
{
return Core::ICore::settings()
->value(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE, false)
.toBool();
}
void setSettingIfDifferent(const QString &key, bool value, bool &dirty)
{
QSettings *s = Core::ICore::settings();
if (s->value(key, false).toBool() != value) {
dirty = false;
s->setValue(key, value);
}
}
WelcomeMode::~WelcomeMode()
{
delete m_modeWidget;
}
StudioSettingsPage::StudioSettingsPage()
: m_buildCheckBox(new QCheckBox(tr("Build")))
, m_debugCheckBox(new QCheckBox(tr("Debug")))
, m_analyzeCheckBox(new QCheckBox(tr("Analyze")))
{
const QString toolTip = tr(
"Hide top-level menus with advanced functionality to simplify the UI. <b>Build</b> is "
"generally not required in the context of Qt Design Studio.<b>Debug</b> and <b>Analyze</b>"
"are only required for debugging and profiling.");
QVBoxLayout *boxLayout = new QVBoxLayout(this);
setLayout(boxLayout);
auto groupBox = new QGroupBox(tr("Hide Menu"));
groupBox->setToolTip(toolTip);
boxLayout->addWidget(groupBox);
boxLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Expanding));
auto verticalLayout = new QVBoxLayout();
groupBox->setLayout(verticalLayout);
m_buildCheckBox->setToolTip(toolTip);
m_debugCheckBox->setToolTip(toolTip);
m_analyzeCheckBox->setToolTip(toolTip);
verticalLayout->addWidget(m_buildCheckBox);
verticalLayout->addWidget(m_debugCheckBox);
verticalLayout->addWidget(m_analyzeCheckBox);
verticalLayout->addSpacerItem(
new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum));
m_buildCheckBox->setChecked(hideBuildMenuSetting());
m_debugCheckBox->setChecked(hideDebugMenuSetting());
m_analyzeCheckBox->setChecked(hideAnalyzeMenuSetting());
}
void StudioSettingsPage::apply()
{
bool dirty = false;
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_BUILD,
m_buildCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_DEBUG,
m_debugCheckBox->isChecked(),
dirty);
setSettingIfDifferent(ProjectExplorer::Constants::SETTINGS_MENU_HIDE_ANALYZE,
m_analyzeCheckBox->isChecked(),
dirty);
if (dirty) {
const QString restartText = tr("The menu visibility change will take effect after restart.");
Core::RestartDialog restartDialog(Core::ICore::dialogParent(), restartText);
restartDialog.exec();
}
}
StudioWelcomeSettingsPage::StudioWelcomeSettingsPage()
{
setId("Z.StudioWelcome.Settings");
setDisplayName(tr("Qt Design Studio Configuration"));
setCategory(Core::Constants::SETTINGS_CATEGORY_CORE);
setWidgetCreator([] { return new StudioSettingsPage; });
}
} // namespace Internal
} // namespace StudioWelcome

View File

@@ -26,12 +26,36 @@
#pragma once
#include <extensionsystem/iplugin.h>
#include <coreplugin/dialogs/ioptionspage.h>
#include <QTimer>
QT_FORWARD_DECLARE_CLASS(QCheckBox)
namespace StudioWelcome {
namespace Internal {
class StudioSettingsPage : public Core::IOptionsPageWidget
{
public:
void apply() final;
StudioSettingsPage();
private:
QCheckBox *m_buildCheckBox;
QCheckBox *m_debugCheckBox;
QCheckBox *m_analyzeCheckBox;
};
class StudioWelcomeSettingsPage : public Core::IOptionsPage
{
Q_OBJECT
public:
StudioWelcomeSettingsPage();
};
class StudioWelcomePlugin final : public ExtensionSystem::IPlugin
{
Q_OBJECT
@@ -55,6 +79,7 @@ public:
private:
class WelcomeMode *m_welcomeMode = nullptr;
QTimer m_removeSplashTimer;
StudioWelcomeSettingsPage m_settingsPage;
int m_removeSplashRemainingTime = 0;
};

View File

@@ -70,8 +70,7 @@ void WizardFactories::filter()
{
QList<JsonWizardFactory *> acceptedFactories = Utils::filtered(m_factories, [&](auto *wizard) {
return wizard->isAvailable(m_platform)
&& wizard->kind() == JsonWizardFactory::ProjectWizard
&& wizard->requiredFeatures().contains("QtStudio");
&& wizard->kind() == JsonWizardFactory::ProjectWizard;
});
m_factories = acceptedFactories;

View File

@@ -26,6 +26,7 @@
#pragma once
#include "texteditor_global.h"
#include "blockrange.h"
#include "formatter.h"
#include "indenter.h"
@@ -49,7 +50,6 @@ QT_END_NAMESPACE
namespace TextEditor {
class BlockRange;
class CompletionAssistProvider;
class ExtraEncodingSettings;
class FontSettings;