Merge remote-tracking branch 'origin/7.0'

Conflicts:
	cmake/QtCreatorIDEBranding.cmake
	qbs/modules/qtc/qtc.qbs
	qtcreator_ide_branding.pri

Change-Id: I1ce9876150239751a1187bc0c4b8fc5fef1ab40d
This commit is contained in:
Eike Ziller
2022-03-14 14:02:14 +01:00
26 changed files with 186 additions and 121 deletions

View File

@@ -52,7 +52,7 @@ Prerequisites:
* CMake
* Ninja (recommended)
The installed toolchains have to match the one Qt was compiled with.
The used toolchain has to be compatible with the one Qt was compiled with.
### Linux and macOS

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 23 KiB

View File

@@ -43,6 +43,10 @@
You can also view and modify other types of text files.
To open the search dialog in \uicontrol {Text Editor}, go to
\uicontrol Edit > \uicontrol {Find/Replace} > \uicontrol {Find/Replace}.
You can also select \key Ctrl + \key {F}.
You can use a subset of the functions available in the
\l{Writing Code}{Edit mode}:

View File

@@ -29,18 +29,21 @@
#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
#endif
#include <QCoreApplication>
#include <QDebug>
#include <QFile>
#include <QJsonDocument>
#include <QJsonObject>
#include <QCoreApplication>
#include <QTimer>
#include <QScopedPointer>
#include <QDebug>
#include <QTextStream>
#include <QTimer>
namespace Import3D
{
void import3D(const QString &sourceAsset, const QString &outDir, int exitId, const QString &options)
void import3D(const QString &sourceAsset, const QString &outDir, const QString &options)
{
QString errorStr;
#ifdef IMPORT_QUICK3D_ASSETS
QScopedPointer importer {new QSSGAssetImportManager};
@@ -48,32 +51,35 @@ void import3D(const QString &sourceAsset, const QString &outDir, int exitId, con
QJsonDocument optDoc = QJsonDocument::fromJson(options.toUtf8(), &error);
if (!optDoc.isNull() && optDoc.isObject()) {
QString errorStr;
QJsonObject optObj = optDoc.object();
if (importer->importFile(sourceAsset, outDir, optObj.toVariantMap(), &errorStr)
!= QSSGAssetImportManager::ImportState::Success) {
qWarning() << __FUNCTION__ << "Failed to import 3D asset"
<< sourceAsset << "with error:" << errorStr;
} else {
// Allow little time for file operations to finish
QTimer::singleShot(2000, nullptr, [exitId]() {
qApp->exit(exitId);
});
return;
}
} else {
qWarning() << __FUNCTION__ << "Failed to parse import options:" << error.errorString();
errorStr = QObject::tr("Failed to parse import options: %1").arg(error.errorString());
}
#else
errorStr = QObject::tr("QtQuick3D is not available.");
Q_UNUSED(sourceAsset)
Q_UNUSED(outDir)
Q_UNUSED(exitId)
Q_UNUSED(options)
qWarning() << __FUNCTION__ << "Failed to parse import options, Quick3DAssetImport not available";
#endif
QTimer::singleShot(0, nullptr, [exitId]() {
// Negative exitId means import failure
qApp->exit(-exitId);
if (!errorStr.isEmpty()) {
qWarning() << __FUNCTION__ << "Failed to import asset:" << errorStr << outDir;
// Write the error into a file in outDir to pass it to creator side
QString errorFileName = outDir + "/__error.log";
QFile file(errorFileName);
if (file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
QTextStream out(&file);
out << errorStr;
file.close();
}
}
// Allow little time for file operations to finish
QTimer::singleShot(2000, nullptr, []() {
qApp->exit(0);
});
}

View File

@@ -29,5 +29,5 @@
namespace Import3D
{
void import3D(const QString &sourceAsset, const QString &outDir, int id, const QString &options);
void import3D(const QString &sourceAsset, const QString &outDir, const QString &options);
};

View File

@@ -228,10 +228,9 @@ int internalMain(QGuiApplication *application)
if (application->arguments().at(1) == "--import3dAsset") {
QString sourceAsset = application->arguments().at(2);
QString outDir = application->arguments().at(3);
int exitId = application->arguments().at(4).toInt();
QString options = application->arguments().at(5);
QString options = application->arguments().at(4);
Import3D::import3D(sourceAsset, outDir, exitId, options);
Import3D::import3D(sourceAsset, outDir, options);
return application->exec();
}

View File

@@ -101,6 +101,9 @@ ScrollView {
height: DialogValues.presetItemHeight
onClicked: delegate.GridView.view.currentIndex = index
onDoubleClicked: {
BackendApi.accept()
}
background: Rectangle {
id: delegateBackground

View File

@@ -379,6 +379,8 @@ GenerateCompilationDbResult generateCompilationDB(const CppEditor::ProjectInfo::
{
QTC_ASSERT(!baseDir.isEmpty(), return GenerateCompilationDbResult(QString(),
QCoreApplication::translate("ClangUtils", "Could not retrieve build directory.")));
QTC_ASSERT(projectInfo, return GenerateCompilationDbResult(QString(),
"Could not retrieve project info."));
QTC_CHECK(baseDir.ensureWritableDir());
QFile compileCommandsFile(baseDir.toString() + "/compile_commands.json");
const bool fileOpened = compileCommandsFile.open(QIODevice::WriteOnly | QIODevice::Truncate);

View File

@@ -128,7 +128,12 @@ mergeTools(std::vector<std::unique_ptr<CMakeTool>> &sdkTools,
std::unique_ptr<CMakeTool> userTool = std::move(userTools[0]);
userTools.erase(std::begin(userTools));
int userToolIndex = Utils::indexOf(result, Utils::equal(&CMakeTool::id, userTool->id()));
int userToolIndex = Utils::indexOf(result, [&userTool](const std::unique_ptr<CMakeTool> &tool) {
// Id should be sufficient, but we have older "mis-registered" docker based items.
// Make sure that these don't override better new values from the sdk by
// also checking the actual executable.
return userTool->id() == tool->id() && userTool->cmakeExecutable() == tool->cmakeExecutable();
});
if (userToolIndex >= 0) {
// Replace the sdk tool with the user tool, so any user changes do not get lost
result[userToolIndex] = std::move(userTool);

View File

@@ -189,6 +189,14 @@ QRect ManhattanStyle::subElementRect(SubElement element, const QStyleOption *opt
QRect ManhattanStyle::subControlRect(ComplexControl control, const QStyleOptionComplex *option,
SubControl subControl, const QWidget *widget) const
{
#if QT_VERSION < QT_VERSION_CHECK(6, 2, 5)
// Workaround for QTBUG-101581, can be removed when building with Qt 6.2.5 or higher
if (control == CC_ScrollBar) {
const auto scrollbar = qstyleoption_cast<const QStyleOptionSlider *>(option);
if (scrollbar && qint64(scrollbar->maximum) - scrollbar->minimum > INT_MAX)
return QRect(); // breaks the scrollbar, but avoids the crash
}
#endif
return QProxyStyle::subControlRect(control, option, subControl, widget);
}

View File

@@ -345,12 +345,12 @@ public:
searchDirsComboBox->addItem(tr("Search in PATH"));
searchDirsComboBox->addItem(tr("Search in Selected Directories"));
auto searchDirsLineEdit = new QLineEdit;
searchDirsLineEdit->setText("/usr/bin;/opt");
auto searchDirsLineEdit = new FancyLineEdit;
searchDirsLineEdit->setToolTip(
tr("Select the paths in the docker image that should be scanned for kit entries."));
searchDirsLineEdit->setHistoryCompleter("DockerMounts", true);
auto searchPaths = [this, searchDirsComboBox, searchDirsLineEdit, dockerDevice] {
auto searchPaths = [searchDirsComboBox, searchDirsLineEdit, dockerDevice] {
FilePaths paths;
if (searchDirsComboBox->currentIndex() == 0) {
paths = dockerDevice->systemEnvironment().path();
@@ -418,8 +418,10 @@ public:
}.attachTo(this);
searchDirsLineEdit->setVisible(false);
auto updateDirectoriesLineEdit = [this, searchDirsLineEdit](int index) {
auto updateDirectoriesLineEdit = [searchDirsLineEdit](int index) {
searchDirsLineEdit->setVisible(index == 1);
if (index == 1)
searchDirsLineEdit->setFocus();
};
QObject::connect(searchDirsComboBox, qOverload<int>(&QComboBox::activated),
this, updateDirectoriesLineEdit);

View File

@@ -419,7 +419,7 @@ void LayoutInGridLayout::fillEmptyCells()
newItemNode.setVariantProperty("y", yPos);
newItemNode.setVariantProperty("width", 14);
newItemNode.setVariantProperty("height", 14);
newItemNode.setId(m_selectionContext.view()->generateNewId("spacer"));
newItemNode.setId(m_selectionContext.view()->model()->generateNewId("spacer"));
}
m_layoutedNodes.append(m_spacerNodes);
}

View File

@@ -241,7 +241,7 @@ void BackendModel::addNewBackend()
if (!model->hasImport(import))
model->changeImports({import}, {});
QString propertyName = m_connectionView->generateNewId(typeName);
QString propertyName = m_connectionView->model()->generateNewId(typeName);
NodeMetaInfo metaInfo = model->metaInfo(typeName.toUtf8());

View File

@@ -141,7 +141,7 @@ QString NodeListView::setNodeId(int internalId, const QString &id)
{
ModelNode node = modelNodeForInternalId(internalId);
if (node.isValid()) {
QString newId = generateNewId(id);
QString newId = model()->generateNewId(id);
node.setIdWithRefactoring(newId);
return newId;
}

View File

@@ -142,9 +142,10 @@ void ItemLibraryAssetImporter::addInfo(const QString &infoMsg, const QString &sr
emit infoReported(infoMsg, srcPath);
}
void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus,
int importId)
{
Q_UNUSED(exitStatus)
Q_UNUSED(exitCode)
++m_qmlImportFinishedCount;
@@ -154,9 +155,32 @@ void ItemLibraryAssetImporter::importProcessFinished(int exitCode, QProcess::Exi
return !entry || entry->state() == QProcess::NotRunning;
}));
if (m_parseData.contains(-exitCode)) {
const ParseData pd = m_parseData.take(-exitCode);
addError(tr("Asset import process failed for: \"%1\".").arg(pd.sourceInfo.absoluteFilePath()));
if (m_parseData.contains(importId)) {
const ParseData &pd = m_parseData[importId];
QString errStr;
if (exitStatus == QProcess::ExitStatus::CrashExit) {
errStr = tr("Import process crashed.");
} else {
bool unknownFail = !pd.outDir.exists() || pd.outDir.isEmpty();
if (!unknownFail) {
QFile errorLog(pd.outDir.filePath("__error.log"));
if (errorLog.exists()) {
if (errorLog.open(QIODevice::ReadOnly))
errStr = QString::fromUtf8(errorLog.readAll());
else
unknownFail = true;
}
}
if (unknownFail)
errStr = tr("Import failed for unknown reason.");
}
if (!errStr.isEmpty()) {
addError(tr("Asset import process failed: \"%1\".")
.arg(pd.sourceInfo.absoluteFilePath()));
addError(errStr);
m_parseData.remove(importId);
}
}
if (m_qmlImportFinishedCount == m_qmlPuppetCount) {
@@ -565,15 +589,14 @@ bool ItemLibraryAssetImporter::startImportProcess(const ParseData &pd)
QJsonDocument optDoc(pd.options);
puppetArgs << "--import3dAsset" << pd.sourceInfo.absoluteFilePath()
<< pd.outDir.absolutePath() << QString::number(pd.importId)
<< QString::fromUtf8(optDoc.toJson());
<< pd.outDir.absolutePath() << QString::fromUtf8(optDoc.toJson());
QProcessUniquePointer process = puppetCreator.createPuppetProcess(
"custom",
{},
[&] {},
[&](int exitCode, QProcess::ExitStatus exitStatus) {
importProcessFinished(exitCode, exitStatus);
importProcessFinished(exitCode, exitStatus, pd.importId);
},
puppetArgs);

View File

@@ -74,7 +74,7 @@ signals:
void importFinished();
private slots:
void importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
void importProcessFinished(int exitCode, QProcess::ExitStatus exitStatus, int importId);
void iconProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
private:
@@ -125,7 +125,7 @@ private:
std::vector<QProcessUniquePointer> m_qmlPuppetProcesses;
int m_qmlPuppetCount = 0;
int m_qmlImportFinishedCount = 0;
int m_importIdCounter = 1000000; // Use ids in range unlikely to clash with any normal process exit codes
int m_importIdCounter = 0;
QHash<int, ParseData> m_parseData;
QString m_progressTitle;
QList<Import> m_requiredImports;

View File

@@ -910,8 +910,8 @@ ModelNode NavigatorTreeModel::handleItemLibraryShaderDrop(const QString &shaderP
// Rename the node based on shader source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"shader"));
newModelNode.setIdWithoutRefactoring(
m_view->model()->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");
@@ -956,9 +956,9 @@ ModelNode NavigatorTreeModel::handleItemLibrarySoundDrop(const QString &soundPat
// Rename the node based on source
QFileInfo fi(relPath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(),
"soundEffect"));
}
newModelNode.setIdWithoutRefactoring(
m_view->model()->generateNewId(fi.baseName(), "soundEffect"));
}
return newModelNode;
}
@@ -1073,7 +1073,8 @@ ModelNode NavigatorTreeModel::createTextureNode(const NodeAbstractProperty &targ
// Rename the node based on source image
QFileInfo fi(imagePath);
newModelNode.setIdWithoutRefactoring(m_view->generateNewId(fi.baseName(), "textureImage"));
newModelNode.setIdWithoutRefactoring(
m_view->model()->generateNewId(fi.baseName(), "textureImage"));
return newModelNode;
}
return {};

View File

@@ -131,7 +131,7 @@ void AddTabDesignerAction::addNewTab()
tabViewModelNode.majorVersion(),
tabViewModelNode.minorVersion(),
propertyList);
newTabModelNode.setIdWithRefactoring(newTabModelNode.view()->generateNewId(tabName));
newTabModelNode.setIdWithRefactoring(newTabModelNode.model()->generateNewId(tabName));
tabViewModelNode.defaultNodeAbstractProperty().reparentHere(newTabModelNode);
}
}

View File

@@ -136,8 +136,6 @@ public:
ModelNode modelNodeForId(const QString &id);
bool hasId(const QString &id) const;
QString generateNewId(const QString &prefixName) const;
QString generateNewId(const QString &prefixName, const QString &fallbackPrefix) const;
ModelNode modelNodeForInternalId(qint32 internalId) const;
bool hasModelNodeForInternalId(qint32 internalId) const;

View File

@@ -124,6 +124,11 @@ public:
void clearMetaInfoCache();
bool hasId(const QString &id) const;
QString generateNewId(const QString &prefixName) const;
QString generateNewId(const QString &prefixName, const QString &fallbackPrefix) const;
protected:
Model();

View File

@@ -42,7 +42,6 @@
#include <utils/qtcassert.h>
#include <utils/algorithm.h>
#include <QRegularExpression>
#include <QWidget>
#include <QtGui/qimage.h>
@@ -517,52 +516,7 @@ ModelNode AbstractView::modelNodeForId(const QString &id)
bool AbstractView::hasId(const QString &id) const
{
return model()->d->hasId(id);
}
QString firstCharToLower(const QString &string)
{
QString resultString = string;
if (!resultString.isEmpty())
resultString[0] = resultString.at(0).toLower();
return resultString;
}
QString AbstractView::generateNewId(const QString &prefixName, const QString &fallbackPrefix) const
{
// First try just the prefixName without number as postfix, then continue with 2 and further
// as postfix until id does not already exist.
// Properties of the root node are not allowed for ids, because they are available in the
// complete context without qualification.
int counter = 0;
QString newBaseId = QString(QStringLiteral("%1")).arg(firstCharToLower(prefixName));
newBaseId.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9_]")));
if (!newBaseId.isEmpty()) {
QChar firstChar = newBaseId.at(0);
if (firstChar.isDigit())
newBaseId.prepend('_');
} else {
newBaseId = fallbackPrefix;
}
QString newId = newBaseId;
while (!ModelNode::isValidId(newId) || hasId(newId) || rootModelNode().hasProperty(newId.toUtf8())) {
++counter;
newId = QString(QStringLiteral("%1%2")).arg(firstCharToLower(newBaseId)).arg(counter);
}
return newId;
}
QString AbstractView::generateNewId(const QString &prefixName) const
{
return generateNewId(prefixName, QStringLiteral("element"));
return model()->hasId(id);
}
ModelNode AbstractView::modelNodeForInternalId(qint32 internalId) const

View File

@@ -67,6 +67,8 @@
#include <utils/algorithm.h>
#include <QRegularExpression>
/*!
\defgroup CoreModel
*/
@@ -1444,6 +1446,57 @@ bool Model::hasImport(const Import &import, bool ignoreAlias, bool allowHigherVe
return false;
}
bool Model::hasId(const QString &id) const
{
return d->hasId(id);
}
static QString firstCharToLower(const QString &string)
{
QString resultString = string;
if (!resultString.isEmpty())
resultString[0] = resultString.at(0).toLower();
return resultString;
}
QString Model::generateNewId(const QString &prefixName, const QString &fallbackPrefix) const
{
// First try just the prefixName without number as postfix, then continue with 2 and further
// as postfix until id does not already exist.
// Properties of the root node are not allowed for ids, because they are available in the
// complete context without qualification.
int counter = 0;
QString newBaseId = QString(QStringLiteral("%1")).arg(firstCharToLower(prefixName));
newBaseId.remove(QRegularExpression(QStringLiteral("[^a-zA-Z0-9_]")));
if (!newBaseId.isEmpty()) {
QChar firstChar = newBaseId.at(0);
if (firstChar.isDigit())
newBaseId.prepend('_');
} else {
newBaseId = fallbackPrefix;
}
QString newId = newBaseId;
while (!ModelNode::isValidId(newId) || hasId(newId)
|| d->rootNode()->hasProperty(newId.toUtf8())) {
++counter;
newId = QString(QStringLiteral("%1%2")).arg(firstCharToLower(newBaseId)).arg(counter);
}
return newId;
}
QString Model::generateNewId(const QString &prefixName) const
{
return generateNewId(prefixName, QStringLiteral("element"));
}
bool Model::isImportPossible(const Import &import, bool ignoreAlias, bool allowHigherVersion) const
{
if (imports().contains(import))

View File

@@ -25,7 +25,6 @@
#include "modelnode.h"
#include <abstractproperty.h>
#include <abstractview.h>
#include <model.h>
#include <nodemetainfo.h>
#include "internalnode_p.h"
@@ -144,7 +143,7 @@ QString ModelNode::id() const
QString ModelNode::validId()
{
if (id().isEmpty())
setIdWithRefactoring(view()->generateNewId(simplifiedTypeName()));
setIdWithRefactoring(model()->generateNewId(simplifiedTypeName()));
return id();
}
@@ -270,7 +269,8 @@ void ModelNode::setIdWithoutRefactoring(const QString &id)
if (id == m_internalNode->id())
return;
if (view()->hasId(id))
if (model()->hasId(id))
throw InvalidIdException(__LINE__, __FUNCTION__, __FILE__, id.toUtf8(), InvalidIdException::DuplicateId);
m_model.data()->d->changeNodeId(internalNode(), id);

View File

@@ -117,7 +117,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromImage(AbstractView *view, const QS
parentproperty.reparentHere(newQmlItemNode);
QFileInfo fi(relativeImageName);
newQmlItemNode.setId(view->generateNewId(fi.baseName(), "image"));
newQmlItemNode.setId(view->model()->generateNewId(fi.baseName(), "image"));
newQmlItemNode.modelNode().variantProperty("fillMode").setEnumeration("Image.PreserveAspectFit");
@@ -168,7 +168,7 @@ QmlItemNode QmlItemNode::createQmlItemNodeFromFont(AbstractView *view,
metaInfo.minorVersion(), propertyPairList));
parentproperty.reparentHere(newQmlItemNode);
newQmlItemNode.setId(view->generateNewId("text", "text"));
newQmlItemNode.setId(view->model()->generateNewId("text", "text"));
Q_ASSERT(newQmlItemNode.isValid());
};

View File

@@ -335,7 +335,7 @@ QmlObjectNode QmlVisualNode::createQmlObjectNode(AbstractView *view,
if (!newQmlObjectNode.isValid())
return;
newQmlObjectNode.setId(view->generateNewId(itemLibraryEntry.name()));
newQmlObjectNode.setId(view->model()->generateNewId(itemLibraryEntry.name()));
for (const auto &propertyBindingEntry : propertyBindingList)
newQmlObjectNode.modelNode().bindingProperty(propertyBindingEntry.first).setExpression(propertyBindingEntry.second);

View File

@@ -21,20 +21,22 @@ extend_qtc_plugin(QmlPreview
tests/qmlpreviewplugin_test.cpp tests/qmlpreviewplugin_test.h
)
# check if Qt version have_qml_debug_translation_protocol
# will be introduced in Qt 6.2, but there are users
# who needs it in older but special built Qt versions aswell
string(REGEX MATCH "^[0-9]*" QT_VERSION_MAJOR ${Qt5_VERSION})
get_target_property(qmldebugprivate_include_directories
Qt${QT_VERSION_MAJOR}::QmlPrivate
INTERFACE_INCLUDE_DIRECTORIES
)
find_file(have_qml_debug_translation_protocol
NAMES private/qqmldebugtranslationprotocol_p.h
PATHS ${qmldebugprivate_include_directories}
)
extend_qtc_plugin(QmlPreview
CONDITION have_qml_debug_translation_protocol
PUBLIC_DEPENDS Qt5::QmlPrivate
PUBLIC_DEFINES "FOUND_QML_DEBUG_TRANSLATION_PROTOCOL"
)
if(TARGET Qt${QT_VERSION_MAJOR}::QmlPrivate)
# check if Qt version have_qml_debug_translation_protocol
# will be introduced in Qt 6.2, but there are users
# who needs it in older but special built Qt versions aswell
string(REGEX MATCH "^[0-9]*" QT_VERSION_MAJOR ${Qt5_VERSION})
get_target_property(qmldebugprivate_include_directories
Qt${QT_VERSION_MAJOR}::QmlPrivate
INTERFACE_INCLUDE_DIRECTORIES
)
find_file(have_qml_debug_translation_protocol
NAMES private/qqmldebugtranslationprotocol_p.h
PATHS ${qmldebugprivate_include_directories}
)
extend_qtc_plugin(QmlPreview
CONDITION have_qml_debug_translation_protocol
PUBLIC_DEPENDS Qt5::QmlPrivate
PUBLIC_DEFINES "FOUND_QML_DEBUG_TRANSLATION_PROTOCOL"
)
endif()