Merge remote-tracking branch 'origin/5.0'

Conflicts:
	qbs/modules/qtc/qtc.qbs
	src/plugins/android/androidconfigurations.cpp

Change-Id: If8dc2cdf131811e08ca147c6f58dbb3ed3bf7227
This commit is contained in:
Eike Ziller
2021-08-26 11:09:08 +02:00
114 changed files with 1832 additions and 633 deletions

View File

@@ -43,8 +43,9 @@ enum class LanguageVersion : unsigned char {
CXX11,
CXX14,
CXX17,
CXX2a,
LatestCxx = CXX2a,
CXX20,
CXX2b,
LatestCxx = CXX2b,
};
enum class LanguageExtension : unsigned char {

View File

@@ -391,7 +391,7 @@ void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDi
if (d->m_progressParser)
d->m_progressParser->parseProgress(text);
if (!(d->m_flags & SuppressStdErr))
appendError(text);
emit appendError(text);
if (d->m_progressiveOutput)
emit stdErrText(text);
});
@@ -403,7 +403,7 @@ void ShellCommand::runSynchronous(QtcProcess &process, const FilePath &workingDi
if (d->m_progressParser)
d->m_progressParser->parseProgress(text);
if (d->m_flags & ShowStdOut)
append(text);
emit append(text);
if (d->m_progressiveOutput) {
emit stdOutText(text);
d->m_hadOutput = true;

View File

@@ -417,7 +417,9 @@ public:
DStoolTipBackground,
DStoolTipOutline,
DStoolTipText
DStoolTipText,
DSUnimportedModuleColor
};
enum Gradient {

View File

@@ -47,7 +47,13 @@ QUrl urlFromLocalSocket()
{
QUrl serverUrl;
serverUrl.setScheme(urlSocketScheme());
TemporaryFile file("qtcreator-freesocket");
TemporaryFile file("qtc-socket");
// see "man unix" for unix socket file name size limitations
if (file.fileName().size() > 104) {
qWarning().nospace()
<< "Socket file name \"" << file.fileName()
<< "\" is larger than 104 characters, which will not work on Darwin/macOS/Linux!";
}
if (file.open())
serverUrl.setPath(file.fileName());
return serverUrl;

View File

@@ -333,7 +333,7 @@ QString AndroidAvdManager::waitForAvd(const QString &avdName,
// 60 rounds of 2s sleeping, two minutes for the avd to start
QString serialNumber;
for (int i = 0; i < 60; ++i) {
if (cancelChecker())
if (cancelChecker && cancelChecker())
return QString();
serialNumber = findAvd(avdName);
if (!serialNumber.isEmpty())
@@ -365,7 +365,7 @@ bool AndroidAvdManager::waitForBooted(const QString &serialNumber,
{
// found a serial number, now wait until it's done booting...
for (int i = 0; i < 60; ++i) {
if (cancelChecker())
if (cancelChecker && cancelChecker())
return false;
if (isAvdBooted(serialNumber)) {
return true;

View File

@@ -176,7 +176,8 @@ AndroidBuildApkWidget::AndroidBuildApkWidget(AndroidBuildApkStep *step)
QWidget *AndroidBuildApkWidget::createApplicationGroup()
{
const int minApiSupported = AndroidManager::apiLevelRange().first;
QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(m_step->target()->kit());
const int minApiSupported = AndroidManager::defaultMinimumSDK(qt);
QStringList targets = AndroidConfig::apiLevelNamesFor(AndroidConfigurations::sdkManager()->
filteredSdkPlatforms(minApiSupported));
targets.removeDuplicates();

View File

@@ -778,12 +778,12 @@ bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
QString AndroidConfig::bestNdkPlatformMatch(int target, const BaseQtVersion *qtVersion) const
{
target = std::max(AndroidManager::apiLevelRange().first, target);
target = std::max(AndroidManager::defaultMinimumSDK(qtVersion), target);
foreach (int apiLevel, availableNdkPlatforms(qtVersion)) {
if (apiLevel <= target)
return QString::fromLatin1("android-%1").arg(apiLevel);
}
return QString("android-%1").arg(AndroidManager::apiLevelRange().first);
return QString("android-%1").arg(AndroidManager::defaultMinimumSDK(qtVersion));
}
FilePath AndroidConfig::sdkLocation() const
@@ -1291,10 +1291,7 @@ void AndroidConfigurations::updateAutomaticKitList()
Id deviceTypeId = DeviceTypeKitAspect::deviceTypeId(k);
if (k->isAutoDetected() && !k->isSdkProvided()
&& deviceTypeId == Constants::ANDROID_DEVICE_TYPE) {
if (!QtKitAspect::qtVersion(k))
KitManager::deregisterKit(k); // Remove autoDetected kits without Qt.
else
return true;
return true;
}
return false;
});
@@ -1327,6 +1324,7 @@ void AndroidConfigurations::updateAutomaticKitList()
&& tc->isValid()
&& tc->typeId() == Constants::ANDROID_TOOLCHAIN_TYPEID;
});
QList<Kit *> unhandledKits = existingKits;
for (ToolChain *tc : toolchains) {
if (tc->language() != ProjectExplorer::Constants::CXX_LANGUAGE_ID)
continue;
@@ -1381,12 +1379,18 @@ void AndroidConfigurations::updateAutomaticKitList()
k->setValueSilently(Constants::ANDROID_KIT_SDK, currentConfig().sdkLocation().toString());
};
if (existingKit)
if (existingKit) {
initializeKit(existingKit); // Update the existing kit with new data.
else
unhandledKits.removeOne(existingKit);
} else {
KitManager::registerKit(initializeKit);
}
}
}
// cleanup any mess that might have existed before, by removing all Android kits that
// existed before, but weren't re-used
for (Kit *k : unhandledKits)
KitManager::deregisterKit(k);
}
bool AndroidConfigurations::force32bitEmulator()

View File

@@ -399,9 +399,14 @@ void AndroidManager::setDeviceApiLevel(Target *target, int level)
target->setNamedSettings(ApiLevelKey, level);
}
QPair<int, int> AndroidManager::apiLevelRange()
int AndroidManager::defaultMinimumSDK(const QtSupport::BaseQtVersion *qtVersion)
{
return qMakePair(16, 29);
if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber{6, 0})
return 23;
else if (qtVersion && qtVersion->qtVersion() >= QtSupport::QtVersionNumber{5, 13})
return 21;
else
return 16;
}
QString AndroidManager::androidNameForApiLevel(int x)

View File

@@ -31,6 +31,7 @@
#include <QObject>
#include <QVersionNumber>
#include <qtsupport/baseqtversion.h>
#include <projectexplorer/abi.h>
QT_BEGIN_NAMESPACE
@@ -87,6 +88,7 @@ public:
static int minimumSDK(const ProjectExplorer::Target *target);
static int minimumSDK(const ProjectExplorer::Kit *kit);
static int defaultMinimumSDK(const QtSupport::BaseQtVersion *qtVersion);
static QStringList applicationAbis(const ProjectExplorer::Target *target);
static QString archTriplet(const QString &abi);
@@ -100,7 +102,6 @@ public:
static QString devicePreferredAbi(const QStringList &deviceAbis, const QStringList &appAbis);
static ProjectExplorer::Abi androidAbi2Abi(const QString &androidAbi);
static QPair<int, int> apiLevelRange();
static QString androidNameForApiLevel(int x);
static void installQASIPackage(ProjectExplorer::Target *target, const Utils::FilePath &packagePath);

View File

@@ -720,18 +720,21 @@ void AndroidManifestEditorWidget::updateInfoBar()
void AndroidManifestEditorWidget::updateSdkVersions()
{
QPair<int, int> apiLevels = AndroidManager::apiLevelRange();
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
m_androidMinSdkVersion->addItem(tr("API %1: %2")
.arg(i)
.arg(AndroidManager::androidNameForApiLevel(i)),
i);
static const QPair<int, int> sdkPair = qMakePair(16, 31);
int minSdk = sdkPair.first;
const int targetSdk = sdkPair.second;
const Target *target = androidTarget(m_textEditorWidget->textDocument()->filePath());
if (target) {
const QtSupport::BaseQtVersion *qt = QtSupport::QtKitAspect::qtVersion(target->kit());
minSdk = AndroidManager::defaultMinimumSDK(qt);
}
for (int i = apiLevels.first; i < apiLevels.second + 1; ++i)
m_androidTargetSdkVersion->addItem(tr("API %1: %2")
.arg(i)
.arg(AndroidManager::androidNameForApiLevel(i)),
i);
for (int i = minSdk; i <= targetSdk; ++i) {
const QString apiStr = tr("API %1: %2").arg(i)
.arg(AndroidManager::androidNameForApiLevel(i));
m_androidMinSdkVersion->addItem(apiStr, i);
m_androidTargetSdkVersion->addItem(apiStr, i);
}
}
void AndroidManifestEditorWidget::updateInfoBar(const QString &errorMessage, int line, int column)

View File

@@ -191,12 +191,14 @@ static bool isChildOf(const FilePath &path, const QStringList &prefixes)
QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
const FilePath &sourceDirectory,
const FilePath &buildDirectory)
const FilePath &buildDirectory,
bool haveLibrariesRelativeToBuildDirectory)
{
QDir sourceDir(sourceDirectory.toString());
const QList<CMakeBuildTarget> result = transform<QList>(input.targetDetails,
[&sourceDir, &sourceDirectory, &buildDirectory](const TargetDetails &t) {
[&sourceDir, &sourceDirectory, &buildDirectory,
&haveLibrariesRelativeToBuildDirectory](const TargetDetails &t) {
const FilePath currentBuildDir = buildDirectory.absoluteFilePath(t.buildDir);
CMakeBuildTarget ct;
@@ -271,7 +273,8 @@ QList<CMakeBuildTarget> generateBuildTargets(const PreprocessedData &input,
if (part.startsWith("-"))
continue;
FilePath tmp = currentBuildDir.absoluteFilePath(FilePath::fromUserInput(part));
const FilePath buildDir = haveLibrariesRelativeToBuildDirectory ? buildDirectory : currentBuildDir;
FilePath tmp = buildDir.absoluteFilePath(FilePath::fromUserInput(part));
if (f.role == "libraries")
tmp = tmp.parentDir();
@@ -707,7 +710,12 @@ FileApiQtcData extractData(FileApiData &input,
return {};
}
result.buildTargets = generateBuildTargets(data, sourceDirectory, buildDirectory);
// Ninja generator from CMake version 3.20.5 has libraries relative to build directory
const bool haveLibrariesRelativeToBuildDirectory =
input.replyFile.generator.startsWith("Ninja")
&& input.replyFile.cmakeVersion >= QVersionNumber(3, 20, 5);
result.buildTargets = generateBuildTargets(data, sourceDirectory, buildDirectory, haveLibrariesRelativeToBuildDirectory);
result.cmakeFiles = std::move(data.cmakeFiles);
result.projectParts = generateRawProjectParts(data, sourceDirectory);

View File

@@ -147,6 +147,13 @@ static ReplyFileContents readReplyFile(const FilePath &filePath, QString &errorM
result.generator = generator.value("name").toString();
result.isMultiConfig = generator.value("multiConfig").toBool();
}
const QJsonObject version = cmakeObject.value("version").toObject();
{
int major = version.value("major").toInt();
int minor = version.value("minor").toInt();
int patch = version.value("patch").toInt();
result.cmakeVersion = QVersionNumber(major, minor, patch);
}
}
}

View File

@@ -39,6 +39,7 @@
#include <QFutureInterface>
#include <QString>
#include <QVector>
#include <QVersionNumber>
#include <vector>
@@ -65,6 +66,7 @@ public:
QString cmakeRoot;
QVector<ReplyObject> replies;
QVersionNumber cmakeVersion;
Utils::FilePath jsonFile(const QString &kind, const Utils::FilePath &replyDir) const;
};

View File

@@ -164,7 +164,8 @@ QStringList CppcheckTool::additionalArguments(const CppTools::ProjectPart &part)
break;
case Version::CXX98:
case Version::CXX17:
case Version::CXX2a:
case Version::CXX20:
case Version::CXX2b:
result.push_back("--language=c++");
break;
case Version::None:

View File

@@ -92,15 +92,15 @@ public:
filePaths << absoluteFilePath;
}
// Update Code Model
QVERIFY(parseFiles(filePaths));
// Open Editor
const QString fileName = temporaryDir.path() + QLatin1String("/file1.h");
CppEditor *editor;
QVERIFY(openCppEditor(fileName, &editor));
closeEditorAtEndOfTestCase(editor);
// Update Code Model
QVERIFY(parseFiles(filePaths));
// Test model
CppIncludeHierarchyModel model;
model.buildHierarchy(editor->document()->filePath().toString());

View File

@@ -472,7 +472,10 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX17:
option = "/std:c++17";
break;
case LanguageVersion::CXX2a:
case LanguageVersion::CXX20:
option = "/std:c++20";
break;
case LanguageVersion::CXX2b:
option = "/std:c++latest";
break;
}
@@ -517,8 +520,11 @@ void CompilerOptionsBuilder::addLanguageVersionAndExtensions()
case LanguageVersion::CXX17:
option = (gnuExtensions ? QLatin1String("-std=gnu++17") : QLatin1String("-std=c++17"));
break;
case LanguageVersion::CXX2a:
option = (gnuExtensions ? QLatin1String("-std=gnu++2a") : QLatin1String("-std=c++2a"));
case LanguageVersion::CXX20:
option = (gnuExtensions ? QLatin1String("-std=gnu++20") : QLatin1String("-std=c++20"));
break;
case LanguageVersion::CXX2b:
option = (gnuExtensions ? QLatin1String("-std=gnu++2b") : QLatin1String("-std=c++2b"));
break;
case LanguageVersion::None:
break;
@@ -868,6 +874,14 @@ void CompilerOptionsBuilder::evaluateCompilerFlags()
theOption[0] = '-';
}
// Clang-cl (as of Clang 12) frontend doesn't know about -std:c++20
// but the clang front end knows about -std=c++20
// https://github.com/llvm/llvm-project/blob/release/12.x/clang/lib/Driver/ToolChains/Clang.cpp#L5855
if (toolChain == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID ||
toolChain == ProjectExplorer::Constants::CLANG_CL_TOOLCHAIN_TYPEID) {
theOption.replace("-std:c++20", "-clang:-std=c++20");
}
m_compilerFlags.flags.append(theOption);
}

View File

@@ -123,7 +123,8 @@ QString Utils::toString(::Utils::LanguageVersion languageVersion)
CASE_LANGUAGEVERSION(CXX11);
CASE_LANGUAGEVERSION(CXX14);
CASE_LANGUAGEVERSION(CXX17);
CASE_LANGUAGEVERSION(CXX2a);
CASE_LANGUAGEVERSION(CXX20);
CASE_LANGUAGEVERSION(CXX2b);
// no default to get a compiler warning if anything is added
}
#undef CASE_LANGUAGEVERSION

View File

@@ -235,7 +235,7 @@ QVariant FlatModel::data(const QModelIndex &index, int role) const
}
case Qt::DecorationRole: {
if (!folderNode)
return Core::FileIconProvider::icon(node->filePath());
return node->asFileNode()->icon();
if (!project)
return folderNode->icon();
static QIcon warnIcon = Utils::Icons::WARNING.icon();

View File

@@ -44,6 +44,7 @@
#include <utils/pointeralgorithm.h>
#include <utils/qtcassert.h>
#include <utils/stringutils.h>
#include <utils/utilsicons.h>
#include <QDir>
#include <QFileInfo>
@@ -252,6 +253,35 @@ bool Node::isEnabled() const
return parent ? parent->isEnabled() : true;
}
QIcon FileNode::icon() const
{
if (hasError())
return Utils::Icons::WARNING.icon();
if (m_icon.isNull())
m_icon = Core::FileIconProvider::icon(filePath());
return m_icon;
}
void FileNode::setIcon(const QIcon icon)
{
m_icon = icon;
}
bool FileNode::hasError() const
{
return m_hasError;
}
void FileNode::setHasError(bool error)
{
m_hasError = error;
}
void FileNode::setHasError(bool error) const
{
m_hasError = error;
}
/*!
Returns \c true if the file is automatically generated by a compile step.
*/

View File

@@ -218,8 +218,17 @@ public:
bool supportsAction(ProjectAction action, const Node *node) const override;
QString displayName() const override;
bool hasError() const;
void setHasError(const bool error);
void setHasError(const bool error) const;
QIcon icon() const;
void setIcon(const QIcon icon);
private:
FileType m_fileType;
mutable QIcon m_icon;
mutable bool m_hasError = false;
};
// Documentation inside.

View File

@@ -10,6 +10,7 @@ add_qtc_plugin(QmlDesigner
DEFINES
DESIGNER_CORE_LIBRARY
IDE_LIBRARY_BASENAME=\"${IDE_LIBRARY_BASE_PATH}\"
SHARE_QML_PATH="${CMAKE_CURRENT_SOURCE_DIR}/../../../share/qtcreator/qmldesigner"
PUBLIC_INCLUDES
"${CMAKE_CURRENT_LIST_DIR}"
"${CMAKE_CURRENT_LIST_DIR}/designercore/include"

View File

@@ -48,6 +48,24 @@ static QString styleConfigFileName(const QString &qmlFileName)
ChangeStyleWidgetAction::ChangeStyleWidgetAction(QObject *parent) : QWidgetAction(parent)
{
// The Default style was renamed to Basic in Qt 6. In Qt 6, "Default"
// will result in a platform-specific style being chosen.
items = {
{"Basic", "Basic", {}},
{"Default", "Default", {}},
{"Fusion", "Fusion", {}},
{"Imagine", "Imagine", {}},
{"Material Light", "Material", "Light"},
{"Material Dark", "Material", "Dark"},
{"Universal Light", "Universal", "Light"},
{"Universal Dark", "Universal", "Dark"},
{"Universal System", "Universal", "System"}
};
if (Utils::HostOsInfo::isMacHost())
items.append({"macOS", "macOS", {}});
if (Utils::HostOsInfo::isWindowsHost())
items.append({"Windows", "Windows", {}});
}
void ChangeStyleWidgetAction::handleModelUpdate(const QString &style)
@@ -55,6 +73,48 @@ void ChangeStyleWidgetAction::handleModelUpdate(const QString &style)
emit modelUpdated(style);
}
const QList<StyleWidgetEntry> ChangeStyleWidgetAction::styleItems() const
{
return items;
}
void ChangeStyleWidgetAction::changeStyle(const QString &style)
{
if (style.isEmpty())
return;
const Utils::FilePath configFileName = Utils::FilePath::fromString(styleConfigFileName(qmlFileName));
if (configFileName.exists()) {
QSettings infiFile(configFileName.toString(), QSettings::IniFormat);
int contains = -1;
for (const auto &item : qAsConst(items)) {
if (item.displayName == style) {
contains = items.indexOf(item);
break;
}
}
if (contains >= 0) {
const QString styleName = items.at(contains).styleName;
const QString styleTheme = items.at(contains).styleTheme;
infiFile.setValue("Controls/Style", styleName);
if (!styleTheme.isEmpty())
infiFile.setValue((styleName + "/Theme"), styleTheme);
}
else {
infiFile.setValue("Controls/Style", style);
}
if (view)
view->resetPuppet();
}
}
const char enabledTooltip[] = QT_TRANSLATE_NOOP("ChangeStyleWidgetAction",
"Change style for Qt Quick Controls 2.");
const char disbledTooltip[] = QT_TRANSLATE_NOOP("ChangeStyleWidgetAction",
@@ -64,18 +124,10 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
{
auto comboBox = new QComboBox(parent);
comboBox->setToolTip(tr(enabledTooltip));
// The Default style was renamed to Basic in Qt 6. In Qt 6, "Default"
// will result in a platform-specific style being chosen.
comboBox->addItem("Basic");
comboBox->addItem("Default");
comboBox->addItem("Fusion");
comboBox->addItem("Imagine");
if (Utils::HostOsInfo::isMacHost())
comboBox->addItem("macOS");
comboBox->addItem("Material");
comboBox->addItem("Universal");
if (Utils::HostOsInfo::isWindowsHost())
comboBox->addItem("Windows");
for (const auto &item : qAsConst(items))
comboBox->addItem(item.displayName);
comboBox->setEditable(true);
comboBox->setCurrentIndex(0);
@@ -97,23 +149,8 @@ QWidget *ChangeStyleWidgetAction::createWidget(QWidget *parent)
}
});
connect(comboBox,
&QComboBox::textActivated,
this,
[this](const QString &style) {
if (style.isEmpty())
return;
const Utils::FilePath configFileName = Utils::FilePath::fromString(styleConfigFileName(qmlFileName));
if (configFileName.exists()) {
QSettings infiFile(configFileName.toString(), QSettings::IniFormat);
infiFile.setValue("Controls/Style", style);
if (view)
view->resetPuppet();
}
});
connect(comboBox, &QComboBox::textActivated,
this, &ChangeStyleWidgetAction::changeStyle);
return comboBox;
}
@@ -135,11 +172,27 @@ void ChangeStyleAction::currentContextChanged(const SelectionContext &selectionC
if (Utils::FilePath::fromString(confFileName).exists()) {
QSettings infiFile(confFileName, QSettings::IniFormat);
m_action->handleModelUpdate(infiFile.value("Controls/Style", "Basic").toString());
const QString styleName = infiFile.value("Controls/Style", "Basic").toString();
const QString styleTheme = infiFile.value(styleName + "/Theme", "").toString();
const auto items = m_action->styleItems();
QString comboBoxEntry = styleName;
for (const auto &item : items) {
if (item.styleName == styleName) {
if (!styleTheme.isEmpty() && (item.styleTheme == styleTheme)) {
comboBoxEntry.append(" ");
comboBoxEntry.append(styleTheme);
break;
}
}
}
m_action->handleModelUpdate(comboBoxEntry);
} else {
m_action->handleModelUpdate("");
}
}
}

View File

@@ -38,6 +38,24 @@ namespace QmlDesigner {
class AbstractView;
struct StyleWidgetEntry {
QString displayName;
QString styleName;
QString styleTheme;
bool operator==(const StyleWidgetEntry &entry) const {
if (displayName != entry.displayName)
return false;
if (styleName != entry.styleName)
return false;
if (styleTheme != entry.styleTheme)
return false;
return true;
};
};
class ChangeStyleWidgetAction : public QWidgetAction
{
Q_OBJECT
@@ -46,6 +64,11 @@ public:
explicit ChangeStyleWidgetAction(QObject *parent = nullptr);
void handleModelUpdate(const QString &style);
const QList<StyleWidgetEntry> styleItems() const;
public slots:
void changeStyle(const QString &style);
protected:
QWidget *createWidget(QWidget *parent) override;
@@ -55,6 +78,8 @@ signals:
public:
QString qmlFileName;
QPointer<AbstractView> view;
QList<StyleWidgetEntry> items;
};
class ChangeStyleAction : public ActionInterface

View File

@@ -128,7 +128,7 @@ QString Theme::replaceCssColors(const QString &input)
void Theme::setupTheme(QQmlEngine *engine)
{
static const int typeIndex = qmlRegisterSingletonType<Theme>(
"QtQuickDesignerTheme", 1, 0, "Theme", [](QQmlEngine *engine, QJSEngine *) {
"QtQuickDesignerTheme", 1, 0, "Theme", [](QQmlEngine *, QJSEngine *) {
return new Theme(Utils::creatorTheme(), nullptr);
});
Q_UNUSED(typeIndex)

View File

@@ -79,6 +79,10 @@ namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
@@ -376,6 +380,10 @@ void ItemLibraryWidget::handleTabChanged(int index)
QString ItemLibraryWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/itemLibraryQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/itemLibraryQmlSources").toString();
}

View File

@@ -46,6 +46,10 @@
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/icore.h>
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <projectexplorer/projectnodes.h>
#include <utils/algorithm.h>
#include <utils/icon.h>
#include <utils/utilsicons.h>
@@ -169,6 +173,29 @@ void NavigatorView::modelAttached(Model *model)
}
}
});
clearExplorerWarnings();
}
void NavigatorView::clearExplorerWarnings()
{
QList<ModelNode> allNodes;
addNodeAndSubModelNodesToList(rootModelNode(), allNodes);
for (ModelNode node : allNodes) {
if (node.metaInfo().isFileComponent()) {
const ProjectExplorer::FileNode *fnode = fileNodeForModelNode(node);
if (fnode)
fnode->setHasError(false);
}
}
}
void NavigatorView::addNodeAndSubModelNodesToList(const ModelNode &node, QList<ModelNode> &nodes)
{
nodes.append(node);
for (ModelNode subNode : node.allSubModelNodes()) {
addNodeAndSubModelNodesToList(subNode, nodes);
}
}
void NavigatorView::modelAboutToBeDetached(Model *model)
@@ -342,8 +369,10 @@ void NavigatorView::auxiliaryDataChanged(const ModelNode &modelNode,
void NavigatorView::instanceErrorChanged(const QVector<ModelNode> &errorNodeList)
{
for (const ModelNode &modelNode : errorNodeList)
for (const ModelNode &modelNode : errorNodeList) {
m_currentModelInterface->notifyDataChanged(modelNode);
propagateInstanceErrorToExplorer(modelNode);
}
}
void NavigatorView::nodeOrderChanged(const NodeListProperty &listProperty)
@@ -374,6 +403,52 @@ QAbstractItemModel *NavigatorView::currentModel() const
return treeWidget()->model();
}
const ProjectExplorer::FileNode *NavigatorView::fileNodeForModelNode(const ModelNode &node) const
{
QString filename = node.metaInfo().componentFileName();
Utils::FilePath filePath = Utils::FilePath::fromString(filename);
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(
filePath);
if (!currentProject) {
filePath = Utils::FilePath::fromString(node.model()->fileUrl().toLocalFile());
/* If the component does not belong to the project then we can fallback to the current file */
currentProject = ProjectExplorer::SessionManager::projectForFile(filePath);
}
if (!currentProject)
return nullptr;
return currentProject->nodeForFilePath(filePath)->asFileNode();
}
const ProjectExplorer::FileNode *NavigatorView::fileNodeForIndex(const QModelIndex &index) const
{
if (index.isValid() && currentModel()->data(index, Qt::UserRole).isValid()) {
ModelNode node = modelNodeForIndex(index);
if (node.metaInfo().isFileComponent()) {
return fileNodeForModelNode(node);
}
}
return nullptr;
}
void NavigatorView::propagateInstanceErrorToExplorer(const ModelNode &modelNode) {
QModelIndex index = indexForModelNode(modelNode);;
do {
const ProjectExplorer::FileNode *fnode = fileNodeForIndex(index);
if (fnode) {
fnode->setHasError(true);
return;
}
else {
index = index.parent();
}
} while (index.isValid());
}
void NavigatorView::leftButtonClicked()
{
if (selectedModelNodes().count() > 1)

View File

@@ -28,6 +28,7 @@
#include "navigatormodelinterface.h"
#include <abstractview.h>
#include <projectexplorer/projectnodes.h>
#include <QPointer>
#include <QHash>
@@ -108,6 +109,7 @@ private:
void changeToComponent(const QModelIndex &index);
QModelIndex indexForModelNode(const ModelNode &modelNode) const;
QAbstractItemModel *currentModel() const;
void propagateInstanceErrorToExplorer(const ModelNode &modelNode);
void leftButtonClicked();
void rightButtonClicked();
@@ -123,6 +125,10 @@ protected: //functions
void expandAncestors(const QModelIndex &index);
void reparentAndCatch(NodeAbstractProperty property, const ModelNode &modelNode);
void setupWidget();
void addNodeAndSubModelNodesToList(const ModelNode &node, QList<ModelNode> &nodes);
void clearExplorerWarnings();
const ProjectExplorer::FileNode *fileNodeForModelNode(const ModelNode &node) const;
const ProjectExplorer::FileNode *fileNodeForIndex(const QModelIndex &index) const;
private:
bool m_blockSelectionChangedSignal;

View File

@@ -47,8 +47,9 @@
#include <QApplication>
#include <QDir>
#include <QFileInfo>
#include <QVector3D>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
#include <QLoggingCategory>
@@ -343,6 +344,18 @@ void PropertyEditorQmlBackend::setValue(const QmlObjectNode & , const PropertyNa
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
} else if (value.type() == QVariant::Vector4D) {
const char *suffix[4] = {"_x", "_y", "_z", "_w"};
auto vecValue = value.value<QVector4D>();
for (int i = 0; i < 4; ++i) {
PropertyName subPropName(name.size() + 2, '\0');
subPropName.replace(0, name.size(), name);
subPropName.replace(name.size(), 2, suffix[i]);
auto propertyValue = qobject_cast<PropertyEditorValue *>(
variantToQObject(m_backendValuesPropertyMap.value(QString::fromUtf8(subPropName))));
if (propertyValue)
propertyValue->setValue(QVariant(vecValue[i]));
}
} else {
PropertyName propertyName = name;
propertyName.replace('.', '_');
@@ -532,6 +545,10 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
QString PropertyEditorQmlBackend::propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}

View File

@@ -227,14 +227,21 @@ void PropertyEditorView::changeValue(const QString &name)
removePropertyFromModel(propertyName);
} else {
// QVector*D(0, 0, 0) detects as null variant though it is valid value
if (castedValue.isValid() && (!castedValue.isNull()
|| castedValue.type() == QVariant::Vector2D
|| castedValue.type() == QVariant::Vector3D)) {
if (castedValue.isValid()
&& (!castedValue.isNull() || castedValue.type() == QVariant::Vector2D
|| castedValue.type() == QVariant::Vector3D
|| castedValue.type() == QVariant::Vector4D)) {
commitVariantValueToModel(propertyName, castedValue);
}
}
}
static bool isTrueFalseLiteral(const QString &expression)
{
return (expression.compare("false", Qt::CaseInsensitive) == 0)
|| (expression.compare("true", Qt::CaseInsensitive) == 0);
}
void PropertyEditorView::changeExpression(const QString &propertyName)
{
PropertyName name = propertyName.toUtf8();
@@ -267,9 +274,8 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
return;
}
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "bool") {
if (value->expression().compare(QLatin1String("false"), Qt::CaseInsensitive) == 0
|| value->expression().compare(QLatin1String("true"), Qt::CaseInsensitive) == 0) {
if (value->expression().compare(QLatin1String("true"), Qt::CaseInsensitive) == 0)
if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
qmlObjectNode->setVariantProperty(name, true);
else
qmlObjectNode->setVariantProperty(name, false);
@@ -289,6 +295,19 @@ void PropertyEditorView::changeExpression(const QString &propertyName)
qmlObjectNode->setVariantProperty(name, realValue);
return;
}
} else if (qmlObjectNode->modelNode().metaInfo().propertyTypeName(name) == "QVariant") {
bool ok;
qreal realValue = value->expression().toDouble(&ok);
if (ok) {
qmlObjectNode->setVariantProperty(name, realValue);
return;
} else if (isTrueFalseLiteral(value->expression())) {
if (value->expression().compare("true", Qt::CaseInsensitive) == 0)
qmlObjectNode->setVariantProperty(name, true);
else
qmlObjectNode->setVariantProperty(name, false);
return;
}
}
}

View File

@@ -894,7 +894,8 @@ QmlItemNode QmlAnchorBindingProxy::targetIdToNode(const QString &id) const
QString QmlAnchorBindingProxy::idForNode(const QmlItemNode &qmlItemNode) const
{
QTC_ASSERT(qmlItemNode.modelNode().isValid(), return {});
if (!qmlItemNode.modelNode().isValid())
return {};
if (!qmlItemNode.isValid())
return qmlItemNode.id();

View File

@@ -58,6 +58,10 @@ namespace QmlDesigner {
static QString propertyEditorResourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/propertyEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/propertyEditorQmlSources").toString();
}
@@ -122,6 +126,10 @@ StatesEditorWidget::~StatesEditorWidget() = default;
QString StatesEditorWidget::qmlSourcesPath()
{
#ifdef SHARE_QML_PATH
if (qEnvironmentVariableIsSet("LOAD_QML_FROM_SOURCE"))
return QLatin1String(SHARE_QML_PATH) + "/statesEditorQmlSources";
#endif
return Core::ICore::resourcePath("qmldesigner/statesEditorQmlSources").toString();
}

View File

@@ -32,8 +32,9 @@
#include <QDebug>
#include <QPainter>
#include <QVector3D>
#include <QVector2D>
#include <QVector3D>
#include <QVector4D>
QT_BEGIN_NAMESPACE
void qt_blurImage(QPainter *painter, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0);
@@ -352,6 +353,28 @@ QVariant NodeInstance::property(const PropertyName &name) const
break;
}
return QVariant(subValue);
} else if (varValue.type() == QVariant::Vector4D) {
auto value = varValue.value<QVector4D>();
char subProp = name.right(1)[0];
float subValue = 0.f;
switch (subProp) {
case 'x':
subValue = value.x();
break;
case 'y':
subValue = value.y();
break;
case 'z':
subValue = value.z();
break;
case 'w':
subValue = value.w();
break;
default:
subValue = 0.f;
break;
}
return QVariant(subValue);
}
}
}
@@ -443,6 +466,24 @@ void NodeInstance::setProperty(const PropertyName &name, const QVariant &value)
update = true;
}
newValueVar = newValue;
} else if (oldValue.type() == QVariant::Vector4D) {
QVector4D newValue;
if (oldValue.type() == QVariant::Vector4D)
newValue = oldValue.value<QVector4D>();
if (name.endsWith(".x")) {
newValue.setX(value.toFloat());
update = true;
} else if (name.endsWith(".y")) {
newValue.setY(value.toFloat());
update = true;
} else if (name.endsWith(".z")) {
newValue.setZ(value.toFloat());
update = true;
} else if (name.endsWith(".w")) {
newValue.setW(value.toFloat());
update = true;
}
newValueVar = newValue;
}
if (update) {
d->propertyValues.insert(parentPropName, newValueVar);

View File

@@ -349,15 +349,35 @@ private:
static inline bool isValueType(const TypeName &type)
{
static const PropertyTypeList objectValuesList({"QFont", "QPoint", "QPointF",
"QSize", "QSizeF", "QVector3D", "QVector2D", "vector2d", "vector3d", "font"});
static const PropertyTypeList objectValuesList({"QFont",
"QPoint",
"QPointF",
"QSize",
"QSizeF",
"QVector2D",
"QVector3D",
"QVector4D",
"vector2d",
"vector3d",
"vector4d",
"font"});
return objectValuesList.contains(type);
}
static inline bool isValueType(const QString &type)
{
static const QStringList objectValuesList({"QFont", "QPoint", "QPointF",
"QSize", "QSizeF", "QVector3D", "QVector2D", "vector2d", "vector3d", "font"});
static const QStringList objectValuesList({"QFont",
"QPoint",
"QPointF",
"QSize",
"QSizeF",
"QVector2D",
"QVector3D",
"QVector4D",
"vector2d",
"vector3d",
"vector4d",
"font"});
return objectValuesList.contains(type);
}
@@ -1091,6 +1111,9 @@ QVariant::Type NodeMetaInfoPrivate::variantTypeId(const PropertyName &propertyNa
if (typeName == "vector3d")
return QVariant::Vector3D;
if (typeName == "vector4d")
return QVariant::Vector4D;
return QVariant::nameToType(typeName.data());
}

View File

@@ -27,6 +27,7 @@
#include <QVariant>
#include <QColor>
#include <QVector4D>
#include <QVector3D>
#include <QVector2D>
@@ -169,6 +170,14 @@ QString QmlTextGenerator::toQml(const AbstractProperty &property, int indentDept
auto vec = value.value<QVector3D>();
return QStringLiteral("Qt.vector3d(%1, %2, %3)").arg(vec.x()).arg(vec.y()).arg(vec.z());
}
case QMetaType::QVector4D: {
auto vec = value.value<QVector4D>();
return QStringLiteral("Qt.vector4d(%1, %2, %3, %4)")
.arg(vec.x())
.arg(vec.y())
.arg(vec.z())
.arg(vec.w());
}
default:
return QStringLiteral("\"%1\"").arg(escape(stringValue));
}

View File

@@ -83,7 +83,7 @@ bool AddPropertyRewriteAction::execute(QmlRefactoring &refactoring, ModelNodePos
const int nodeLocation = positionStore.nodeOffset(m_property.parentModelNode());
bool result = false;
if (m_property.isDefaultProperty()) {
if (m_propertyType != QmlRefactoring::ScriptBinding && m_property.isDefaultProperty()) {
result = refactoring.addToObjectMemberList(nodeLocation, m_valueText);
if (!result) {
@@ -187,7 +187,7 @@ bool ChangePropertyRewriteAction::execute(QmlRefactoring &refactoring, ModelNode
}
bool result = false;
if (m_property.isDefaultProperty()) {
if (m_propertyType != QmlRefactoring::ScriptBinding && m_property.isDefaultProperty()) {
result = refactoring.addToObjectMemberList(nodeLocation, m_valueText);
if (!result) {

View File

@@ -824,10 +824,9 @@ void TextToModelMerger::setupImports(const Document::Ptr &doc,
differenceHandler.modelMissesImport(newImport);
} else {
QString importUri = toString(import->importUri);
if (version.isEmpty()) {
version = getHighestPossibleImport(importUri);
if (version.isEmpty())
m_hasVersionlessImport = true;
}
const Import newImport = Import::createLibraryImport(importUri,
version,
as,

View File

@@ -42,3 +42,7 @@ BUILD_PUPPET_IN_CREATOR_BINPATH = $$(BUILD_PUPPET_IN_CREATOR_BINPATH)
DEFINES += SEARCH_PUPPET_IN_CREATOR_BINPATH
message("Search puppet in qtcreator bin path!")
}
SHARE_QML_PATH = "$${PWD}/../../../share/qtcreator/qmldesigner"
DEFINES += SHARE_QML_PATH=\\\"$${SHARE_QML_PATH}\\\"

View File

@@ -235,6 +235,13 @@ Rectangle {
id: doNotShowCheckBox
text: qsTr("Do not show this again")
padding: 0
spacing: 12
contentItem: Text {
text: doNotShowCheckBox.text
color: "#ffffff"
leftPadding: doNotShowCheckBox.indicator.width + doNotShowCheckBox.spacing
}
}
CheckBox {
@@ -242,8 +249,15 @@ Rectangle {
text: qsTr("Enable Usage Statistics")
checked: usageStatisticModel.usageStatisticEnabled
padding: 0
spacing: 12
onCheckedChanged: usageStatisticModel.setTelemetryEnabled(usageStatisticCheckBox.checked)
contentItem: Text {
text: usageStatisticCheckBox.text
color: "#ffffff"
leftPadding: usageStatisticCheckBox.indicator.width + usageStatisticCheckBox.spacing
}
}
}

View File

@@ -14,6 +14,7 @@ endif()
if (QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP)
return()
endif()
option(QT_CREATOR_SKIP_PACKAGE_MANAGER_SETUP "Skip Qt Creator's package manager auto-setup" OFF)
#
# conan
@@ -27,6 +28,7 @@ foreach(file conanfile.txt conanfile.py)
endforeach()
if (conanfile_txt AND NOT QT_CREATOR_SKIP_CONAN_SETUP)
option(QT_CREATOR_SKIP_CONAN_SETUP "Skip Qt Creator's conan package manager auto-setup" OFF)
# Get conan from Qt SDK
set(qt_creator_ini "${CMAKE_CURRENT_LIST_DIR}/../QtProject/QtCreator.ini")
@@ -108,6 +110,8 @@ unset(conanfile_txt)
#
if (EXISTS "${CMAKE_SOURCE_DIR}/vcpkg.json" AND NOT QT_CREATOR_SKIP_VCPKG_SETUP)
option(QT_CREATOR_SKIP_VCPKG_SETUP "Skip Qt Creator's vcpkg package manager auto-setup" OFF)
find_program(vcpkg_program vcpkg)
if (NOT vcpkg_program)
return()