diff --git a/doc/qtdesignstudio/examples/doc/images/loginui1-button.png b/doc/qtdesignstudio/examples/doc/images/loginui1-button.png index 2f15db64fdd..6284072c56e 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/loginui1-button.png and b/doc/qtdesignstudio/examples/doc/images/loginui1-button.png differ diff --git a/doc/qtdesignstudio/examples/doc/images/loginui1-entry-field-styled.jpg b/doc/qtdesignstudio/examples/doc/images/loginui1-entry-field-styled.jpg index ef441b60a67..87f24920059 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/loginui1-entry-field-styled.jpg and b/doc/qtdesignstudio/examples/doc/images/loginui1-entry-field-styled.jpg differ diff --git a/doc/qtdesignstudio/examples/doc/images/loginui3-login-state.jpg b/doc/qtdesignstudio/examples/doc/images/loginui3-login-state.jpg index ab76d81007c..9df56bc1a67 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/loginui3-login-state.jpg and b/doc/qtdesignstudio/examples/doc/images/loginui3-login-state.jpg differ diff --git a/doc/qtdesignstudio/examples/doc/images/loginui3-states.jpg b/doc/qtdesignstudio/examples/doc/images/loginui3-states.jpg index b7192194ec6..9dac6b081a8 100644 Binary files a/doc/qtdesignstudio/examples/doc/images/loginui3-states.jpg and b/doc/qtdesignstudio/examples/doc/images/loginui3-states.jpg differ diff --git a/doc/qtdesignstudio/examples/doc/loginui3.qdoc b/doc/qtdesignstudio/examples/doc/loginui3.qdoc index 9ececf18349..c42d1dcfb95 100644 --- a/doc/qtdesignstudio/examples/doc/loginui3.qdoc +++ b/doc/qtdesignstudio/examples/doc/loginui3.qdoc @@ -102,7 +102,8 @@ components in \uicontrol {Form Editor}, depending on the current page: \list 1 - \li In the \l States view, select \uicontrol {Create New State}. + \li In the \l States view, select \inlineimage icons/plus.png + . \li Enter \e login as the state name. \image loginui3-login-state.jpg "States view" \li Select \e repeatPassword in \uicontrol Navigator to display its diff --git a/doc/qtdesignstudio/examples/doc/loginui4.qdoc b/doc/qtdesignstudio/examples/doc/loginui4.qdoc index 6a43e55b009..b58701c02ee 100644 --- a/doc/qtdesignstudio/examples/doc/loginui4.qdoc +++ b/doc/qtdesignstudio/examples/doc/loginui4.qdoc @@ -267,10 +267,10 @@ in \uicontrol Timeline: \list 1 - \li In \uicontrol States, select \uicontrol {Create New State} twice to - add two states called \e login and \e createAccount. You don't - need to make any property changes this time because you'll bind the - states to property animations. + \li In \uicontrol States, select \inlineimage icons/plus.png + twice to add two states called \e login and \e createAccount. You + don't need to make any property changes this time because you'll + bind the states to property animations. \li In \uicontrol States, select \inlineimage icons/action-icon.png for \e login to open the \uicontrol Actions menu, and then select \uicontrol {Set as Default} to determine that the \e login diff --git a/doc/qtdesignstudio/images/qmldesigner-borderimage-states.png b/doc/qtdesignstudio/images/qmldesigner-borderimage-states.png index 5d1ebaf1ad9..9c0d159c328 100644 Binary files a/doc/qtdesignstudio/images/qmldesigner-borderimage-states.png and b/doc/qtdesignstudio/images/qmldesigner-borderimage-states.png differ diff --git a/doc/qtdesignstudio/images/qmldesigner-borderimage-type.png b/doc/qtdesignstudio/images/qmldesigner-borderimage-type.png index 840708f202a..f0f4519b765 100644 Binary files a/doc/qtdesignstudio/images/qmldesigner-borderimage-type.png and b/doc/qtdesignstudio/images/qmldesigner-borderimage-type.png differ diff --git a/doc/qtdesignstudio/images/qmldesigner-screen-design.png b/doc/qtdesignstudio/images/qmldesigner-screen-design.png index 79da601126c..4ef84082d51 100644 Binary files a/doc/qtdesignstudio/images/qmldesigner-screen-design.png and b/doc/qtdesignstudio/images/qmldesigner-screen-design.png differ diff --git a/doc/qtdesignstudio/images/qmldesigner-states-when-condition.png b/doc/qtdesignstudio/images/qmldesigner-states-when-condition.png index ddd080c315b..f506c3e9548 100644 Binary files a/doc/qtdesignstudio/images/qmldesigner-states-when-condition.png and b/doc/qtdesignstudio/images/qmldesigner-states-when-condition.png differ diff --git a/doc/qtdesignstudio/images/qmldesigner-states.png b/doc/qtdesignstudio/images/qmldesigner-states.png index e73fb441f16..2b6e2794e13 100644 Binary files a/doc/qtdesignstudio/images/qmldesigner-states.png and b/doc/qtdesignstudio/images/qmldesigner-states.png differ diff --git a/doc/qtdesignstudio/images/qmldesigner-transitions.png b/doc/qtdesignstudio/images/qmldesigner-transitions.png index 005178481ea..9c91383878f 100644 Binary files a/doc/qtdesignstudio/images/qmldesigner-transitions.png and b/doc/qtdesignstudio/images/qmldesigner-transitions.png differ diff --git a/doc/qtdesignstudio/images/studio-design-mode-states-timeline.png b/doc/qtdesignstudio/images/studio-design-mode-states-timeline.png index d229e39ead9..2579687674e 100644 Binary files a/doc/qtdesignstudio/images/studio-design-mode-states-timeline.png and b/doc/qtdesignstudio/images/studio-design-mode-states-timeline.png differ diff --git a/doc/qtdesignstudio/images/studio-dial.png b/doc/qtdesignstudio/images/studio-dial.png index 79c4237ccb0..3d7b75fa89d 100644 Binary files a/doc/qtdesignstudio/images/studio-dial.png and b/doc/qtdesignstudio/images/studio-dial.png differ diff --git a/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc b/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc index 7aacb6a655f..2a6b36695df 100644 --- a/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc +++ b/doc/qtdesignstudio/src/components/qtquick-buttons.qdoc @@ -234,7 +234,7 @@ \section1 Using States to Change Component Property Values \list 1 - \li In the \l States view, select \uicontrol {Create New State} + \li In the \l States view, select \inlineimage icons/plus.png twice to create two new states. \image qmldesigner-borderimage-states.png "Active and inactive states" \li Select \uicontrol State1. diff --git a/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc b/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc index 021f4cddaab..d5894641dbb 100644 --- a/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc +++ b/doc/qtdesignstudio/src/views/qtquick-states-view.qdoc @@ -38,19 +38,10 @@ To open the \uicontrol States view, select \uicontrol View > \uicontrol Views > \uicontrol States. - To collapse or expand the \uicontrol States view, select: - - \list - \li Select \uicontrol View > \uicontrol Views > - \uicontrol {Toggle States}. - \li Press \key {Ctr+Alt+S} on Windows or \key {Cmd+Option+S} on \macOS. - \li Right-click the view and select \uicontrol Collapse or - \uicontrol Expand. - \endlist - Initially, \uicontrol States displays a \e {base state} that shows the selected \l{glossary-component}{component} in its initial state. To add - states, select \uicontrol {Create New State}. + states, select \inlineimage icons/plus.png + in the \uicontrol States view. For more information, watch the following video: diff --git a/doc/qtdesignstudio/src/views/qtquick-states.qdoc b/doc/qtdesignstudio/src/views/qtquick-states.qdoc index cc3652ab31e..13f4f8aa95d 100644 --- a/doc/qtdesignstudio/src/views/qtquick-states.qdoc +++ b/doc/qtdesignstudio/src/views/qtquick-states.qdoc @@ -36,7 +36,8 @@ \title Adding States You can define states for components and component instances in the - \l States view by selecting \uicontrol {Create New State}. + \l States view by selecting \inlineimage icons/plus.png + . \image qmldesigner-transitions.png "States view" @@ -181,7 +182,7 @@ \inlineimage icons/eye_open.png icon in \l Navigator to hide components on the canvas that are not part of a view. - \li In \uicontrol States, select \uicontrol {Create New State} to create + \li In \uicontrol States, select the \uicontrol + symbol to create a new state and give it a name. For example, \c Normal. \li In \l Properties (2), deselect the \uicontrol Visibility check box or set \uicontrol Opacity to 0 for each component that diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleEmitterGizmo.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleEmitterGizmo.qml index a06a38a2024..9b19bf35261 100644 --- a/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleEmitterGizmo.qml +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/qt6/ParticleEmitterGizmo.qml @@ -27,6 +27,9 @@ import QtQuick import QtQuick3D import QtQuick3D.Particles3D +// Note: This gizmo is also used to visualize Attractor3D in addition to ParticleEmitter3D, +// as the two are very similar. + Node { id: root @@ -41,6 +44,7 @@ Node { property bool globalShow: false property bool canBeVisible: activeScene === scene && targetNode && !hidden && !systemHidden property bool partOfActiveSystem: root.targetNode && root.targetNode.system === activeParticleSystem + property bool isEmitter: targetNode && targetNode instanceof ParticleEmitter3D opacity: 0.15 @@ -120,7 +124,10 @@ Node { DefaultMaterial { id: defaultMaterial - diffuseColor: root.selected ? "#FF0000" : partOfActiveSystem ? "#FFFF00" : "#AAAAAA" + diffuseColor: root.selected ? "#FF0000" + : root.partOfActiveSystem + ? root.isEmitter ? "#FFFF00" : "#0000FF" + : "#AAAAAA" lighting: DefaultMaterial.NoLighting cullMode: Material.NoCulling } diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index 1b1788e4acf..3b774c3f4a6 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -51,6 +51,7 @@ #include #include #include +#include #endif #include @@ -477,11 +478,15 @@ QQuick3DNode *GeneralHelper::createParticleEmitterGizmoModel(QQuick3DNode *emitt QQuick3DMaterial *material) const { #ifdef QUICK3D_PARTICLES_MODULE - auto e = qobject_cast(emitter); - if (!e || qobject_cast(e) || !material) + if (qobject_cast(emitter) || !material) return nullptr; - auto shape = qobject_cast(e->shape()); + QQuick3DParticleModelShape *shape = nullptr; + if (auto e = qobject_cast(emitter)) + shape = qobject_cast(e->shape()); + else if (auto a = qobject_cast(emitter)) + shape = qobject_cast(a->shape()); + if (shape && shape->delegate()) { if (auto model = qobject_cast( shape->delegate()->create(shape->delegate()->creationContext()))) { diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp index d496aff3889..a6e7e259e28 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/nodeinstanceserver.cpp @@ -1576,6 +1576,9 @@ void NodeInstanceServer::setupState(qint32 stateInstanceId) void NodeInstanceServer::registerFonts(const QUrl &resourceUrl) const { + if (!resourceUrl.isValid()) + return; + // Autoregister all fonts found inside the project QDirIterator it {QFileInfo(resourceUrl.toLocalFile()).absoluteFilePath(), {"*.ttf", "*.otf"}, QDir::Files, QDirIterator::Subdirectories}; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp index 0d6c069faec..acc7894a963 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/qt5informationnodeinstanceserver.cpp @@ -113,6 +113,7 @@ #include #include #include +#include #include #endif @@ -775,7 +776,8 @@ void Qt5InformationNodeInstanceServer::handleNode3DDestroyed(QObject *obj) } else if (qobject_cast(obj)) { QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleSystemGizmo", Q_ARG(QVariant, objectToVariant(obj))); - } else if (qobject_cast(obj) + } else if ((qobject_cast(obj) + || qobject_cast(obj)) && !qobject_cast(obj)) { QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleEmitterGizmo", Q_ARG(QVariant, objectToVariant(obj))); @@ -887,7 +889,8 @@ void Qt5InformationNodeInstanceServer::resolveSceneRoots() QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleSystemGizmoScene", Q_ARG(QVariant, objectToVariant(newRoot)), Q_ARG(QVariant, objectToVariant(node))); - } else if (qobject_cast(node) + } else if ((qobject_cast(node) + || qobject_cast(node)) && !qobject_cast(node)) { QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleEmitterGizmoScene", Q_ARG(QVariant, objectToVariant(newRoot)), @@ -1469,7 +1472,8 @@ void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos( lights[find3DSceneRoot(instance)] << instance.internalObject(); } else if (instance.isSubclassOf("QQuick3DParticleSystem")) { particleSystems[find3DSceneRoot(instance)] << instance.internalObject(); - } else if (instance.isSubclassOf("QQuick3DParticleEmitter") + } else if ((instance.isSubclassOf("QQuick3DParticleEmitter") + || instance.isSubclassOf("QQuick3DParticleAttractor")) && !instance.isSubclassOf("QQuick3DParticleTrailEmitter")) { particleEmitters[find3DSceneRoot(instance)] << instance.internalObject(); } @@ -2016,7 +2020,7 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm #ifdef QUICK3D_PARTICLES_MODULE || qobject_cast(object) || qobject_cast(object) - + || qobject_cast(object) #endif ) { return true; diff --git a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml index 5ac4d0fc6eb..8173457f73b 100644 --- a/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml +++ b/share/qtcreator/qmldesigner/itemLibraryQmlSources/Assets.qml @@ -39,7 +39,12 @@ Item { property string contextFilePath: "" property var contextDir: undefined property bool isDirContextMenu: false - property var dropExtFiles: [] // array of supported externally dropped files + + // Array of supported externally dropped files that are imported as-is + property var dropSimpleExtFiles: [] + + // Array of supported externally dropped files that trigger custom import process + property var dropComplexExtFiles: [] function clearSearchFilter() { @@ -48,18 +53,23 @@ Item { function updateDropExtFiles(drag) { - root.dropExtFiles = [] + root.dropSimpleExtFiles = [] + root.dropComplexExtFiles = [] + var simpleSuffixes = rootView.supportedAssetSuffixes(false); + var complexSuffixes = rootView.supportedAssetSuffixes(true); for (const u of drag.urls) { var url = u.toString(); if (url.startsWith("file:///")) // remove file scheme (happens on Windows) url = url.substr(8) - var ext = url.slice(url.lastIndexOf('.') + 1).toLowerCase() - if (rootView.supportedDropSuffixes().includes('*.' + ext)) - root.dropExtFiles.push(url) + var ext = '*.' + url.slice(url.lastIndexOf('.') + 1).toLowerCase() + if (simpleSuffixes.includes(ext)) + root.dropSimpleExtFiles.push(url) + else if (complexSuffixes.includes(ext)) + root.dropComplexExtFiles.push(url) } - drag.accepted = root.dropExtFiles.length > 0 + drag.accepted = root.dropSimpleExtFiles.length > 0 || root.dropComplexExtFiles.length > 0 } DropArea { // handles external drop on empty area of the view (goes to root folder) @@ -73,13 +83,14 @@ Item { } onDropped: { - rootView.handleExtFilesDrop(root.dropExtFiles, assetsModel.rootDir().dirPath) + rootView.handleExtFilesDrop(root.dropSimpleExtFiles, root.dropComplexExtFiles, + assetsModel.rootDir().dirPath) } Canvas { // marker for the drop area id: dropCanvas anchors.fill: parent - visible: dropArea.containsDrag + visible: dropArea.containsDrag && root.dropSimpleExtFiles.length > 0 onWidthChanged: dropCanvas.requestPaint() onHeightChanged: dropCanvas.requestPaint() @@ -458,50 +469,62 @@ Item { visible: assetsModel.isEmpty && searchBox.isEmpty() clip: true - Column { - id: colNoAssets + DropArea { // handles external drop (goes into default folder based on suffix) + anchors.fill: parent - spacing: 20 - x: 20 - width: root.width - 2 * x - anchors.verticalCenter: parent.verticalCenter - - Text { - text: qsTr("Looks like you don't have any assets yet.") - color: StudioTheme.Values.themeTextColor - font.pixelSize: 18 - width: colNoAssets.width - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap + onEntered: (drag)=> { + root.updateDropExtFiles(drag) } - Image { - source: "image://qmldesigner_assets/browse" - anchors.horizontalCenter: parent.horizontalCenter - scale: maBrowse.containsMouse ? 1.2 : 1 - Behavior on scale { - NumberAnimation { - duration: 300 - easing.type: Easing.OutQuad + onDropped: { + rootView.handleExtFilesDrop(root.dropSimpleExtFiles, root.dropComplexExtFiles) + } + + Column { + id: colNoAssets + + spacing: 20 + x: 20 + width: root.width - 2 * x + anchors.verticalCenter: parent.verticalCenter + + Text { + text: qsTr("Looks like you don't have any assets yet.") + color: StudioTheme.Values.themeTextColor + font.pixelSize: 18 + width: colNoAssets.width + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap + } + + Image { + source: "image://qmldesigner_assets/browse" + anchors.horizontalCenter: parent.horizontalCenter + scale: maBrowse.containsMouse ? 1.2 : 1 + Behavior on scale { + NumberAnimation { + duration: 300 + easing.type: Easing.OutQuad + } + } + + MouseArea { + id: maBrowse + anchors.fill: parent + hoverEnabled: true + onClicked: rootView.handleAddAsset(); } } - MouseArea { - id: maBrowse - anchors.fill: parent - hoverEnabled: true - onClicked: rootView.handleAddAsset(); + Text { + text: qsTr("Drag-and-drop your assets here or click the '+' button to browse assets from the file system.") + color: StudioTheme.Values.themeTextColor + font.pixelSize: 18 + width: colNoAssets.width + horizontalAlignment: Text.AlignHCenter + wrapMode: Text.WordWrap } } - - Text { - text: qsTr("Drag-and-drop your assets here or click the '+' button to browse assets from the file system.") - color: StudioTheme.Values.themeTextColor - font.pixelSize: 18 - width: colNoAssets.width - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.WordWrap - } } } @@ -546,7 +569,7 @@ Item { onDropEnter: (drag)=> { root.updateDropExtFiles(drag) - section.highlight = drag.accepted + section.highlight = drag.accepted && root.dropSimpleExtFiles.length > 0 } onDropExit: { @@ -555,7 +578,9 @@ Item { onDrop: { section.highlight = false - rootView.handleExtFilesDrop(root.dropExtFiles, dirPath) + rootView.handleExtFilesDrop(root.dropSimpleExtFiles, + root.dropComplexExtFiles, + dirPath) } onShowContextMenu: { diff --git a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml index ef2cbdf62f7..142aaa5c838 100644 --- a/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml +++ b/share/qtcreator/qmldesigner/statesEditorQmlSources/StatesList.qml @@ -161,7 +161,7 @@ FocusScope { Text { text: "+" anchors.centerIn: parent - anchors.verticalCenterOffset: -5 + anchors.verticalCenterOffset: -16 font.pixelSize: parent.height * .5 color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1) } diff --git a/src/libs/ssh/sshconnection.cpp b/src/libs/ssh/sshconnection.cpp index 2e07e12bbad..b1f03d58a0d 100644 --- a/src/libs/ssh/sshconnection.cpp +++ b/src/libs/ssh/sshconnection.cpp @@ -479,7 +479,8 @@ bool checkParameters(const QSsh::SshConnectionParameters ¶ms) void printSetupHelp() { - qInfo() << "In order to run this test properly it requires some setup (example for fedora):\n" + qInfo() << "\n\n" + "In order to run this test properly it requires some setup (example for fedora):\n" "1. Run a server on the host to connect to:\n" " systemctl start sshd\n" "2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n" diff --git a/src/plugins/coreplugin/find/searchresultwindow.cpp b/src/plugins/coreplugin/find/searchresultwindow.cpp index d5582ffd111..94739a2edba 100644 --- a/src/plugins/coreplugin/find/searchresultwindow.cpp +++ b/src/plugins/coreplugin/find/searchresultwindow.cpp @@ -111,6 +111,7 @@ namespace Internal { void popupRequested(bool focus); void handleExpandCollapseToolButton(bool checked); void updateFilterButton(); + QList toolBarWidgets(); SearchResultWindow *q; QList m_searchResultWidgets; @@ -120,9 +121,9 @@ namespace Internal { QAction *m_expandCollapseAction; static const bool m_initiallyExpand; QWidget *m_spacer; - QLabel *m_historyLabel; + QLabel *m_historyLabel = nullptr; QWidget *m_spacer2; - QComboBox *m_recentSearchesBox; + QComboBox *m_recentSearchesBox = nullptr; QStackedWidget *m_widget; QList m_searchResults; int m_currentIndex; @@ -139,20 +140,13 @@ namespace Internal { m_expandCollapseButton(nullptr), m_expandCollapseAction(new QAction(tr("Expand All"), window)), m_spacer(new QWidget), - m_historyLabel(new QLabel(tr("History:"))), m_spacer2(new QWidget), - m_recentSearchesBox(new QComboBox), m_widget(new QStackedWidget), m_currentIndex(0), m_tabWidth(8) { m_spacer->setMinimumWidth(30); m_spacer2->setMinimumWidth(5); - m_recentSearchesBox->setProperty("drawleftborder", true); - m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); - m_recentSearchesBox->addItem(tr("New Search")); - connect(m_recentSearchesBox, QOverload::of(&QComboBox::activated), - this, &SearchResultWindowPrivate::setCurrentIndexWithFocus); m_widget->setWindowTitle(q->displayName()); @@ -194,6 +188,7 @@ namespace Internal { void SearchResultWindowPrivate::setCurrentIndex(int index, bool focus) { + QTC_ASSERT(m_recentSearchesBox, return ); if (isSearchVisible()) m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(false); m_currentIndex = index; @@ -217,6 +212,7 @@ namespace Internal { void SearchResultWindowPrivate::moveWidgetToTop() { + QTC_ASSERT(m_recentSearchesBox, return ); auto widget = qobject_cast(sender()); QTC_ASSERT(widget, return); const int index = m_searchResultWidgets.indexOf(widget); @@ -458,8 +454,7 @@ QWidget *SearchResultWindow::outputWidget(QWidget *) */ QList SearchResultWindow::toolBarWidgets() const { - return {d->m_expandCollapseButton, d->m_filterButton, d->m_newSearchButton, d->m_spacer, - d->m_historyLabel, d->m_spacer2, d->m_recentSearchesBox}; + return d->toolBarWidgets(); } /*! @@ -497,16 +492,19 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label, PreserveCaseMode preserveCaseMode, const QString &cfgGroup) { - if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) { - if (d->m_currentIndex >= d->m_recentSearchesBox->count() - 1) { - // temporarily set the index to the last but one existing - d->m_currentIndex = d->m_recentSearchesBox->count() - 2; + if (QTC_GUARD(d->m_recentSearchesBox)) { + if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) { + if (d->m_currentIndex >= d->m_recentSearchesBox->count() - 1) { + // temporarily set the index to the last but one existing + d->m_currentIndex = d->m_recentSearchesBox->count() - 2; + } + d->m_searchResultWidgets.last()->notifyVisibilityChanged(false); + // widget first, because that might send interesting signals to SearchResult + delete d->m_searchResultWidgets.takeLast(); + delete d->m_searchResults.takeLast(); + d->m_recentSearchesBox->removeItem(d->m_recentSearchesBox->count() - 1); } - d->m_searchResultWidgets.last()->notifyVisibilityChanged(false); - // widget first, because that might send interesting signals to SearchResult - delete d->m_searchResultWidgets.takeLast(); - delete d->m_searchResults.takeLast(); - d->m_recentSearchesBox->removeItem(d->m_recentSearchesBox->count()-1); + d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm)); } auto widget = new SearchResultWidget; connect(widget, &SearchResultWidget::filterInvalidated, this, [this, widget] { @@ -532,7 +530,6 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label, widget->setInfo(label, toolTip, searchTerm); auto result = new SearchResult(widget); d->m_searchResults.prepend(result); - d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm)); if (d->m_currentIndex > 0) ++d->m_currentIndex; // so setCurrentIndex still knows about the right "currentIndex" and its widget d->setCurrentIndexWithFocus(1); @@ -544,8 +541,10 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label, */ void SearchResultWindow::clearContents() { - for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i) - d->m_recentSearchesBox->removeItem(i); + if (QTC_GUARD(d->m_recentSearchesBox)) { + for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i) + d->m_recentSearchesBox->removeItem(i); + } foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets) widget->notifyVisibilityChanged(false); qDeleteAll(d->m_searchResultWidgets); @@ -642,6 +641,29 @@ void SearchResultWindowPrivate::updateFilterButton() && m_searchResultWidgets.at(visibleSearchIndex())->hasFilter()); } +QList SearchResultWindowPrivate::toolBarWidgets() +{ + if (!m_historyLabel) + m_historyLabel = new QLabel(tr("History:")); + if (!m_recentSearchesBox) { + m_recentSearchesBox = new QComboBox; + m_recentSearchesBox->setProperty("drawleftborder", true); + m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents); + m_recentSearchesBox->addItem(tr("New Search")); + connect(m_recentSearchesBox, + QOverload::of(&QComboBox::activated), + this, + &SearchResultWindowPrivate::setCurrentIndexWithFocus); + } + return {m_expandCollapseButton, + m_filterButton, + m_newSearchButton, + m_spacer, + m_historyLabel, + m_spacer2, + m_recentSearchesBox}; +} + /*! \internal */ diff --git a/src/plugins/docker/dockerdevice.cpp b/src/plugins/docker/dockerdevice.cpp index 8b01467e27a..f76e2517efa 100644 --- a/src/plugins/docker/dockerdevice.cpp +++ b/src/plugins/docker/dockerdevice.cpp @@ -684,7 +684,7 @@ Toolchains KitDetectorPrivate::autoDetectToolChains() emit q->logOutput('\n' + tr("Searching toolchains...")); for (ToolChainFactory *factory : factories) { emit q->logOutput(tr("Searching toolchains of type %1").arg(factory->displayName())); - const ToolchainDetector detector(alreadyKnown, m_device); + const ToolchainDetector detector(alreadyKnown, m_device, m_searchPaths); const Toolchains newToolChains = factory->autoDetect(detector); for (ToolChain *toolChain : newToolChains) { emit q->logOutput(tr("Found \"%1\"").arg(toolChain->compilerCommand().toUserOutput())); @@ -1495,6 +1495,12 @@ QByteArray DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) cons QTC_ASSERT(m_shell && m_shell->isRunning(), return {}); QMutexLocker l(&m_shellMutex); m_shell->readAllStandardOutput(); // clean possible left-overs + const QByteArray oldError = m_shell->readAllStandardError(); // clean possible left-overs + if (!oldError.isEmpty()) { + LOG("Unexpected old stderr: " << oldError); + QTC_CHECK(false); + } + const QByteArray markerWithNewLine("___QC_DOCKER_" + randomHex() + "_OUTPUT_MARKER___\n"); m_shell->write(cmd.toUserOutput().toUtf8() + "\necho -n \"" + markerWithNewLine + "\"\n"); QByteArray output; @@ -1506,6 +1512,11 @@ QByteArray DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) cons LOG("Run command in shell:" << cmd.toUserOutput() << "output size:" << output.size()); if (QTC_GUARD(output.endsWith(markerWithNewLine))) output.chop(markerWithNewLine.size()); + const QByteArray currentError = m_shell->readAllStandardError(); + if (!currentError.isEmpty()) { + LOG("Unexpected current stderr: " << currentError); + QTC_CHECK(false); + } return output; } diff --git a/src/plugins/mcusupport/mcupackage.cpp b/src/plugins/mcusupport/mcupackage.cpp index cd4d0f0661b..87199414480 100644 --- a/src/plugins/mcusupport/mcupackage.cpp +++ b/src/plugins/mcusupport/mcupackage.cpp @@ -365,7 +365,7 @@ static ToolChain *iarToolChain(const FilePath &path, Id language) == BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID; }); if (iarFactory) { - Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {})); + Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}, {})); if (detected.isEmpty()) detected = iarFactory->detectForImport({path, language}); for (auto tc : detected) { diff --git a/src/plugins/projectexplorer/gcctoolchain.cpp b/src/plugins/projectexplorer/gcctoolchain.cpp index f7313eaad14..0f0173d9839 100644 --- a/src/plugins/projectexplorer/gcctoolchain.cpp +++ b/src/plugins/projectexplorer/gcctoolchain.cpp @@ -1090,10 +1090,11 @@ Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd) return {}; } -static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device, +static FilePaths findCompilerCandidates(const ToolchainDetector &detector, const QString &compilerName, bool detectVariants) { + const IDevice::ConstPtr device = detector.device; const QFileInfo fi(compilerName); if (device.isNull() && fi.isAbsolute() && fi.isFile()) return {FilePath::fromString(compilerName)}; @@ -1119,7 +1120,9 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device, if (!device.isNull()) { // FIXME: Merge with block below - FilePaths searchPaths = device->systemEnvironment().path(); + FilePaths searchPaths = detector.searchPaths; + if (searchPaths.isEmpty()) + searchPaths = device->systemEnvironment().path(); for (const FilePath &deviceDir : qAsConst(searchPaths)) { static const QRegularExpression regexp(binaryRegexp); const auto callBack = [&compilerPaths, compilerName](const FilePath &candidate) { @@ -1135,16 +1138,19 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device, } } else { // The normal, local host case. - FilePaths searchPaths = Environment::systemEnvironment().path(); - searchPaths << gnuSearchPathsFromRegistry(); - searchPaths << atmelSearchPathsFromRegistry(); - searchPaths << renesasRl78SearchPathsFromRegistry(); - if (HostOsInfo::isAnyUnixHost()) { - FilePath ccachePath = "/usr/lib/ccache/bin"; - if (!ccachePath.exists()) - ccachePath = "/usr/lib/ccache"; - if (ccachePath.exists() && !searchPaths.contains(ccachePath)) - searchPaths << ccachePath; + FilePaths searchPaths = detector.searchPaths; + if (searchPaths.isEmpty()) { + searchPaths = Environment::systemEnvironment().path(); + searchPaths << gnuSearchPathsFromRegistry(); + searchPaths << atmelSearchPathsFromRegistry(); + searchPaths << renesasRl78SearchPathsFromRegistry(); + if (HostOsInfo::isAnyUnixHost()) { + FilePath ccachePath = "/usr/lib/ccache/bin"; + if (!ccachePath.exists()) + ccachePath = "/usr/lib/ccache"; + if (ccachePath.exists() && !searchPaths.contains(ccachePath)) + searchPaths << ccachePath; + } } for (const FilePath &dir : qAsConst(searchPaths)) { static const QRegularExpression regexp(binaryRegexp); @@ -1173,7 +1179,7 @@ Toolchains GccToolChainFactory::autoDetectToolchains( const ToolchainChecker &checker) const { const FilePaths compilerPaths = - findCompilerCandidates(detector.device, compilerName, detectVariants == DetectVariants::Yes); + findCompilerCandidates(detector, compilerName, detectVariants == DetectVariants::Yes); Toolchains existingCandidates = filtered(detector.alreadyKnown, [language](const ToolChain *tc) { return tc->language() == language; }); Toolchains result; @@ -1748,7 +1754,7 @@ Toolchains ClangToolChainFactory::autoDetect(const ToolchainDetector &detector) const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix(); tcs.append(autoDetectToolchains(clang.toString(), DetectVariants::No, Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID, - ToolchainDetector(known, detector.device))); + ToolchainDetector(known, detector.device, detector.searchPaths))); } return tcs; diff --git a/src/plugins/projectexplorer/toolchain.cpp b/src/plugins/projectexplorer/toolchain.cpp index 2572d25443a..bf3412cfe64 100644 --- a/src/plugins/projectexplorer/toolchain.cpp +++ b/src/plugins/projectexplorer/toolchain.cpp @@ -673,8 +673,10 @@ void ToolChainFactory::setUserCreatable(bool userCreatable) m_userCreatable = userCreatable; } -ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device) - : alreadyKnown(alreadyKnown), device(device) +ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown, + const IDevice::ConstPtr &device, + const FilePaths &searchPaths) + : alreadyKnown(alreadyKnown), device(device), searchPaths(searchPaths) {} BadToolchain::BadToolchain(const Utils::FilePath &filePath) diff --git a/src/plugins/projectexplorer/toolchain.h b/src/plugins/projectexplorer/toolchain.h index acaeabd3572..133b9d39e36 100644 --- a/src/plugins/projectexplorer/toolchain.h +++ b/src/plugins/projectexplorer/toolchain.h @@ -250,13 +250,16 @@ public: class PROJECTEXPLORER_EXPORT ToolchainDetector { public: - ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device); + ToolchainDetector(const Toolchains &alreadyKnown, + const IDevice::ConstPtr &device, + const Utils::FilePaths &searchPaths); bool isBadToolchain(const Utils::FilePath &toolchain) const; void addBadToolchain(const Utils::FilePath &toolchain) const; const Toolchains alreadyKnown; const IDevice::ConstPtr device; + const Utils::FilePaths searchPaths; // If empty use device path and/or magic. }; class PROJECTEXPLORER_EXPORT ToolChainFactory diff --git a/src/plugins/projectexplorer/toolchainoptionspage.cpp b/src/plugins/projectexplorer/toolchainoptionspage.cpp index 642629191ca..1690c29e69d 100644 --- a/src/plugins/projectexplorer/toolchainoptionspage.cpp +++ b/src/plugins/projectexplorer/toolchainoptionspage.cpp @@ -412,7 +412,7 @@ void ToolChainOptionsWidget::redetectToolchains() QSet toDelete; ToolChainManager::resetBadToolchains(); for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) { - const ToolchainDetector detector(knownTcs, {}); // FIXME: Pass device. + const ToolchainDetector detector(knownTcs, {}, {}); // FIXME: Pass device and search paths for (ToolChain * const tc : f->autoDetect(detector)) { if (knownTcs.contains(tc) || toDelete.contains(tc)) continue; diff --git a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp index 628b4f2772e..4db892b391e 100644 --- a/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp +++ b/src/plugins/projectexplorer/toolchainsettingsaccessor.cpp @@ -205,7 +205,7 @@ Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const = Utils::filtered(userFileTcs, &ToolChain::isAutoDetected); // FIXME: Use real device? const Toolchains autodetectedTcs = - autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {})); + autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {}, {})); // merge tool chains and register those that we need to keep: const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs); diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp index b68128099b5..34be8ab46d9 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.cpp @@ -213,34 +213,38 @@ void AssetsLibraryWidget::handleAddAsset() addResources({}); } -void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &filesPaths, const QString &targetDirPath) +void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &simpleFilesPaths, + const QStringList &complexFilesPaths, + const QString &targetDirPath) { - QStringList assetPaths; - QStringList otherPaths; // as of now 3D models, and 3D Studio presentations - std::tie(assetPaths, otherPaths) = Utils::partition(filesPaths, [](const QString &path) { - QString suffix = "*." + path.split('.').last().toLower(); - return AssetsLibraryModel::supportedSuffixes().contains(suffix); - }); - - AddFilesResult result = ModelNodeOperations::addFilesToProject(assetPaths, targetDirPath); - if (result == AddFilesResult::Failed) { - Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"), - tr("Could not add %1 to project.") - .arg(filesPaths.join(' '))); + if (!simpleFilesPaths.isEmpty()) { + if (targetDirPath.isEmpty()) { + addResources(simpleFilesPaths); + } else { + AddFilesResult result = ModelNodeOperations::addFilesToProject(simpleFilesPaths, + targetDirPath); + if (result == AddFilesResult::Failed) { + Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"), + tr("Could not add %1 to project.") + .arg(simpleFilesPaths.join(' '))); + } + } } - if (!otherPaths.empty()) - addResources(otherPaths); + if (!complexFilesPaths.empty()) + addResources(complexFilesPaths); } -QSet AssetsLibraryWidget::supportedDropSuffixes() +QSet AssetsLibraryWidget::supportedAssetSuffixes(bool complex) { const QList handlers = QmlDesignerPlugin::instance()->viewManager() .designerActionManager().addResourceHandler(); QSet suffixes; - for (const AddResourceHandler &handler : handlers) - suffixes.insert(handler.filter); + for (const AddResourceHandler &handler : handlers) { + if (AssetsLibraryModel::supportedSuffixes().contains(handler.filter) != complex) + suffixes.insert(handler.filter); + } return suffixes; } diff --git a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h index 7d3f48ef4dc..abf91c3a8ce 100644 --- a/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h +++ b/src/plugins/qmldesigner/components/assetslibrary/assetslibrarywidget.h @@ -80,8 +80,10 @@ public: Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos); Q_INVOKABLE void handleAddAsset(); Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText); - Q_INVOKABLE void handleExtFilesDrop(const QStringList &filesPaths, const QString &targetDirPath); - Q_INVOKABLE QSet supportedDropSuffixes(); + Q_INVOKABLE void handleExtFilesDrop(const QStringList &simpleFilesPaths, + const QStringList &complexFilesPaths, + const QString &targetDirPath = {}); + Q_INVOKABLE QSet supportedAssetSuffixes(bool complex); signals: void itemActivated(const QString &itemName); diff --git a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp index f664d793d80..2b473e574bd 100644 --- a/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp +++ b/src/plugins/qmldesigner/components/edit3d/edit3dview.cpp @@ -360,9 +360,9 @@ void Edit3DView::createEdit3DActions() m_showParticleEmitterAction = new Edit3DAction( QmlDesigner::Constants::EDIT3D_EDIT_SHOW_PARTICLE_EMITTER, View3DActionCommand::ShowParticleEmitter, - QCoreApplication::translate("ShowParticleEmitterAction", "Always Show Particle Emitters"), + QCoreApplication::translate("ShowParticleEmitterAction", "Always Show Particle Emitters And Attractors"), QKeySequence(Qt::Key_M), true, false, {}, {}, nullptr, - QCoreApplication::translate("ShowParticleEmitterAction", "Toggle between always showing the particle emitter visualization and only showing it when the emitter is selected.")); + QCoreApplication::translate("ShowParticleEmitterAction", "Toggle between always showing the particle emitter and attractor visualizations and only showing them when the emitter or attractor is selected.")); SelectionContextOperation resetTrigger = [this](const SelectionContext &) { m_particlesPlayAction->action()->setEnabled(particlemode); diff --git a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h index 48ecd4119f6..bc3ca88d810 100644 --- a/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h +++ b/src/plugins/qmldesigner/designercore/include/nodeinstanceview.h @@ -170,6 +170,8 @@ private: // functions NodeInstance loadNode(const ModelNode &node); + void clearErrors(); + void removeAllInstanceNodeRelationships(); void removeRecursiveChildRelationship(const ModelNode &removedNode); diff --git a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp index 547d7ad8a60..a6061234320 100644 --- a/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp +++ b/src/plugins/qmldesigner/designercore/instances/nodeinstanceview.cpp @@ -326,10 +326,17 @@ void NodeInstanceView::endPuppetTransaction() } } + +void NodeInstanceView::clearErrors() +{ + for (NodeInstance &instance : instances()) { + instance.setError({}); + } +} + void NodeInstanceView::restartProcess() { - if (rootNodeInstance().isValid()) - rootNodeInstance().setError({}); + clearErrors(); emitInstanceErrorChange({}); emitDocumentMessage({}, {}); @@ -556,10 +563,11 @@ void NodeInstanceView::nodeReparented(const ModelNode &node, const NodeAbstractP m_nodeInstanceServer->reparentInstances( createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent)); - // Reset puppet when particle emitter is reparented to work around issue in + // Reset puppet when particle emitter/affector is reparented to work around issue in // autodetecting the particle system it belongs to. QTBUG-101157 - if (node.isSubclassOf("QtQuick.Particles3D.ParticleEmitter3D") - && node.property("system").toBindingProperty().expression().isEmpty()) { + if ((node.isSubclassOf("QtQuick.Particles3D.ParticleEmitter3D") + || node.isSubclassOf("QtQuick.Particles3D.Affector3D")) + && node.property("system").toBindingProperty().expression().isEmpty()) { resetPuppet(); } } @@ -957,6 +965,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand() } } + clearErrors(); + nodeList = filterNodesForSkipItems(nodeList); QList variantPropertyList; diff --git a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp index 84278234d48..1497c5da22c 100644 --- a/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp +++ b/src/plugins/qmldesigner/designercore/metainfo/nodemetainfo.cpp @@ -767,12 +767,16 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i const ObjectValue *objectValue = getObjectValue(); if (objectValue) { const CppComponentValue *qmlValue = value_cast(objectValue); + if (qmlValue) { if (m_majorVersion == -1 && m_minorVersion == -1) { m_majorVersion = qmlValue->componentVersion().majorVersion(); m_minorVersion = qmlValue->componentVersion().minorVersion(); - m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8(); - } else if (m_majorVersion == qmlValue->componentVersion().majorVersion() && m_minorVersion == qmlValue->componentVersion().minorVersion()) { + m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + + qmlValue->className().toUtf8(); + + } else if (m_majorVersion == qmlValue->componentVersion().majorVersion() + && m_minorVersion == qmlValue->componentVersion().minorVersion()) { m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8(); } else { return; @@ -780,10 +784,16 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i } else { m_isFileComponent = true; const Imports *imports = context()->imports(document()); - ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data()); - if (importInfo.isValid() && importInfo.type() == ImportType::Library) { - m_majorVersion = importInfo.version().majorVersion(); - m_minorVersion = importInfo.version().minorVersion(); + const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data()); + if (importInfo.isValid()) { + if (importInfo.type() == ImportType::Library) { + m_majorVersion = importInfo.version().majorVersion(); + m_minorVersion = importInfo.version().minorVersion(); + } + bool prepandName = (importInfo.type() == ImportType::Library || importInfo.type() == ImportType::Directory) + && !m_qualfiedTypeName.contains('.'); + if (prepandName) + m_qualfiedTypeName.prepend(importInfo.name().toUtf8() + '.'); } } m_objectValue = objectValue; diff --git a/src/plugins/qmldesigner/settingspage.cpp b/src/plugins/qmldesigner/settingspage.cpp index 23e0a948067..1af226ae49f 100644 --- a/src/plugins/qmldesigner/settingspage.cpp +++ b/src/plugins/qmldesigner/settingspage.cpp @@ -260,7 +260,9 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings) #else const auto showDebugSettings = settings.value(DesignerSettingsKey::SHOW_DEBUG_SETTINGS).toBool(); #endif - m_ui.debugGroupBox->setVisible(!standaloneMode || showDebugSettings); + const bool showAdvancedFeatures = !standaloneMode || showDebugSettings; + m_ui.emulationGroupBox->setVisible(showAdvancedFeatures); + m_ui.debugGroupBox->setVisible(showAdvancedFeatures); m_ui.featureTimelineEditorCheckBox->setVisible(standaloneMode); } diff --git a/src/plugins/remotelinux/filesystemaccess_test.cpp b/src/plugins/remotelinux/filesystemaccess_test.cpp index 1cf68a056c7..58680b6a859 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.cpp +++ b/src/plugins/remotelinux/filesystemaccess_test.cpp @@ -95,7 +95,11 @@ void FileSystemAccessTest::initTestCase() QVERIFY(!newDev.isNull()); devMgr->addDevice(newDev); } + if (filePath.exists()) // Do initial cleanup after possible leftovers from previously failed test + QVERIFY(filePath.removeRecursively()); + QVERIFY(!filePath.exists()); QVERIFY(filePath.createDir()); + QVERIFY(filePath.exists()); } void FileSystemAccessTest::cleanupTestCase() @@ -106,7 +110,43 @@ void FileSystemAccessTest::cleanupTestCase() QVERIFY(baseFilePath().removeRecursively()); } -void FileSystemAccessTest::testDirStatuses() +void FileSystemAccessTest::testCreateRemoteFile_data() +{ + QTest::addColumn("data"); + + QTest::newRow("Spaces") << QByteArray("Line with spaces"); + QTest::newRow("Newlines") << QByteArray("Some \n\n newlines \n"); + QTest::newRow("Carriage return") << QByteArray("Line with carriage \r return"); + QTest::newRow("Tab") << QByteArray("Line with \t tab"); + QTest::newRow("Apostrophe") << QByteArray("Line with apostrophe's character"); + QTest::newRow("Quotation marks") << QByteArray("Line with \"quotation marks\""); + QTest::newRow("Backslash 1") << QByteArray("Line with \\ backslash"); + QTest::newRow("Backslash 2") << QByteArray("Line with \\\" backslash"); + QTest::newRow("Command output") << QByteArray("The date is: $(date +%D)"); + + const int charSize = sizeof(char) * 0x100; + QByteArray charString(charSize, Qt::Uninitialized); + char *data = charString.data(); + for (int c = 0; c < charSize; ++c) + data[c] = c; + QTest::newRow("All Characters") << charString; +} + +void FileSystemAccessTest::testCreateRemoteFile() +{ + QFETCH(QByteArray, data); + + const FilePath testFilePath = baseFilePath() / "test_file"; + + QVERIFY(!testFilePath.exists()); + QVERIFY(testFilePath.writeFileContents(data)); + QVERIFY(testFilePath.exists()); + QCOMPARE(testFilePath.fileContents(), data); + QVERIFY(testFilePath.removeFile()); + QVERIFY(!testFilePath.exists()); +} + +void FileSystemAccessTest::testDirStatus() { FilePath filePath = baseFilePath(); QVERIFY(filePath.exists()); @@ -142,7 +182,7 @@ void FileSystemAccessTest::testBytesAvailable() void FileSystemAccessTest::testFileActions() { - FilePath testFilePath = createFile("test"); + const FilePath testFilePath = createFile("test"); QVERIFY(testFilePath.exists()); QVERIFY(testFilePath.isFile()); @@ -153,15 +193,17 @@ void FileSystemAccessTest::testFileActions() QVERIFY(testFilePath.isReadableFile()); QVERIFY(testFilePath.isExecutableFile()); - QByteArray content("Test"); + const QByteArray content("Test"); testFilePath.writeFileContents(content); - // ToDo: remove ".contains", make fileContents exact equal content - QVERIFY(testFilePath.fileContents().contains(content)); + QCOMPARE(testFilePath.fileContents(), content); - QVERIFY(testFilePath.renameFile(baseFilePath() / "test1")); + const FilePath newTestFilePath = baseFilePath() / "test1"; // It is Ok that FilePath doesn't change itself after rename. - FilePath newTestFilePath = baseFilePath() / "test1"; + // FilePath::renameFile() is a const method! + QVERIFY(testFilePath.renameFile(newTestFilePath)); + QVERIFY(!testFilePath.exists()); QVERIFY(newTestFilePath.exists()); + QCOMPARE(newTestFilePath.fileContents(), content); QVERIFY(!testFilePath.removeFile()); QVERIFY(newTestFilePath.exists()); QVERIFY(newTestFilePath.removeFile()); diff --git a/src/plugins/remotelinux/filesystemaccess_test.h b/src/plugins/remotelinux/filesystemaccess_test.h index 7dacd1ae936..c0a2d9aefb1 100644 --- a/src/plugins/remotelinux/filesystemaccess_test.h +++ b/src/plugins/remotelinux/filesystemaccess_test.h @@ -45,12 +45,15 @@ class FileSystemAccessTest : public QObject private slots: void initTestCase(); - void cleanupTestCase(); - void testDirStatuses(); + void testCreateRemoteFile_data(); + void testCreateRemoteFile(); + void testDirStatus(); void testBytesAvailable(); void testFileActions(); + void cleanupTestCase(); + private: TestLinuxDeviceFactory m_testLinuxDeviceFactory; bool m_skippedAtWhole = false; diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index a69a35c1787..122dbd2f0b3 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -232,11 +232,14 @@ public: bool runInShell(const CommandLine &cmd, const QByteArray &data = {}) { QTC_ASSERT(m_shell, return false); - const QByteArray prefix = !data.isEmpty() ? QByteArray("echo " + data + " | ") - : QByteArray(""); + QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs - m_shell->readAllStandardOutput(); // clean possible left-overs - m_shell->write(prefix + cmd.toUserOutput().toUtf8() + "\necho $?\n"); + const QByteArray prefix = !data.isEmpty() + ? QByteArray("echo '" + data.toBase64() + "' | base64 -d | ") : QByteArray(""); + const QByteArray suffix = QByteArray(" > /dev/null 2>&1\necho $?\n"); + const QByteArray command = prefix + cmd.toUserOutput().toUtf8() + suffix; + + m_shell->write(command); DEBUG("RUN1 " << cmd.toUserOutput()); m_shell->waitForReadyRead(); const QByteArray output = m_shell->readAllStandardOutput(); @@ -244,18 +247,19 @@ public: bool ok = false; const int result = output.toInt(&ok); LOG("Run command in shell:" << cmd.toUserOutput() << "result: " << output << " ==>" << result); - return ok && result == 0; + QTC_ASSERT(ok, return false); + return !result; } QByteArray outputForRunInShell(const QString &cmd) { QTC_ASSERT(m_shell, return {}); + QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs static int val = 0; const QByteArray delim = QString::number(++val, 16).toUtf8(); DEBUG("RUN2 " << cmd); - m_shell->readAllStandardOutput(); // clean possible left-overs const QByteArray marker = "___QTC___" + delim + "_OUTPUT_MARKER___"; DEBUG(" CMD: " << cmd.toUtf8() + "\necho " + marker + "\n"); m_shell->write(cmd.toUtf8() + "\necho " + marker + "\n"); @@ -342,11 +346,9 @@ LinuxDevice::LinuxDevice() proc->start(); }); - if (Utils::HostOsInfo::isAnyUnixHost()) { - addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) { - device->openTerminal(Environment(), FilePath()); - }}); - } + addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) { + device->openTerminal(Environment(), FilePath()); + }}); } LinuxDevice::~LinuxDevice() @@ -734,9 +736,6 @@ QByteArray LinuxDevice::fileContents(const FilePath &filePath, qint64 limit, qin bool LinuxDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const { QTC_ASSERT(handlesFile(filePath), return {}); - -// This following would be the generic Unix solution. -// But it doesn't pass input. FIXME: Why? return d->runInShell({"dd", {"of=" + filePath.path()}}, data); } diff --git a/src/plugins/webassembly/webassemblytoolchain.cpp b/src/plugins/webassembly/webassemblytoolchain.cpp index bebf2866fb9..bb3420253c2 100644 --- a/src/plugins/webassembly/webassemblytoolchain.cpp +++ b/src/plugins/webassembly/webassemblytoolchain.cpp @@ -158,7 +158,7 @@ void WebAssemblyToolChain::registerToolChains() }; // Create new toolchains and register them - ToolchainDetector detector({}, {}); + ToolchainDetector detector({}, {}, {}); const Toolchains toolchains = doAutoDetect(detector); for (auto toolChain : toolchains) ToolChainManager::registerToolChain(toolChain); diff --git a/tests/system/objects.map b/tests/system/objects.map index 074fc19ae7e..aa80ec7c2d0 100644 --- a/tests/system/objects.map +++ b/tests/system/objects.map @@ -21,7 +21,7 @@ :Add Bookmark.treeView_QTreeView {name='treeView' type='QTreeView' visible='1' window=':Add Bookmark_BookmarkDialog'} :Add Bookmark_BookmarkDialog {name='BookmarkDialog' type='BookmarkDialog' visible='1' windowTitle='Add Bookmark'} :Add to Version Control.No_QPushButton {text='No' type='QPushButton' unnamed='1' visible='1' window=':Add to Version Control_QMessageBox'} -:Add to Version Control_QMessageBox {text~='Add the file.*to version control (.*)?' type='QMessageBox' unnamed='1' visible='1'} +:Add to Version Control_QMessageBox {type='QMessageBox' unnamed='1' visible='1' windowTitle='Add to Version Control'} :Analyzer Toolbar.AnalyzerManagerToolBox_QComboBox {container=':DebugModeWidget.Toolbar_QDockWidget' name='PerspectiveChooser' type='QComboBox' visible='1'} :Analyzer Toolbar.Clear_QToolButton {container=':DebugModeWidget.Toolbar_QDockWidget' toolTip='Discard data' type='QToolButton' unnamed='1' visible='1'} :Analyzer Toolbar.Elapsed:_QLabel {container=':DebugModeWidget.Toolbar_QDockWidget' text~='Elapsed: \\\\d+.\\\\d s' type='QLabel' unnamed='1' visible='1'} diff --git a/tests/system/shared/debugger.py b/tests/system/shared/debugger.py index 39b184146e4..586867fd5c8 100644 --- a/tests/system/shared/debugger.py +++ b/tests/system/shared/debugger.py @@ -42,7 +42,8 @@ def handleDebuggerWarnings(config, isMsvcBuild=False): clickButton(waitForObject("{text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':Dialog_Debugger::Internal::SymbolPathsDialog'}", 10000)) except LookupError: pass # No warning. Fine. - if "Release" in config and (isMsvcBuild or platform.system() == "Linux"): + isReleaseConfig = "Release" in config and not "with Debug Information" in config + if isReleaseConfig and (isMsvcBuild or platform.system() == "Linux"): msgBox = "{type='QMessageBox' unnamed='1' visible='1' windowTitle='Warning'}" message = waitForObject("{name='qt_msgbox_label' type='QLabel' visible='1' window=%s}" % msgBox) messageText = str(message.text) diff --git a/tests/system/suite_CSUP/tst_CSUP01/test.py b/tests/system/suite_CSUP/tst_CSUP01/test.py index 20316f39775..50f31d1da34 100644 --- a/tests/system/suite_CSUP/tst_CSUP01/test.py +++ b/tests/system/suite_CSUP/tst_CSUP01/test.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2022 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. @@ -53,7 +53,7 @@ def main(): checkCodeModelSettings(useClang) changeAutocompleteToManual(False) # Step 2: Open .cpp file in Edit mode. - if not openDocument("SampleApp.Sources.main\\.cpp"): + if not openDocument("SampleApp.SampleApp.Source Files.main\\.cpp"): test.fatal("Could not open main.cpp") invokeMenuItem("File", "Exit") return diff --git a/tests/system/suite_CSUP/tst_CSUP02/test.py b/tests/system/suite_CSUP/tst_CSUP02/test.py index ba8fce83c13..2a39c0dc8f8 100644 --- a/tests/system/suite_CSUP/tst_CSUP02/test.py +++ b/tests/system/suite_CSUP/tst_CSUP02/test.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 The Qt Company Ltd. +# Copyright (C) 2022 The Qt Company Ltd. # Contact: https://www.qt.io/licensing/ # # This file is part of Qt Creator. @@ -43,7 +43,7 @@ def main(): createNewQtQuickApplication(tempDir(), "SampleApp") checkCodeModelSettings(useClang) # Step 2: Open .cpp file in Edit mode. - if not openDocument("SampleApp.Sources.main\\.cpp"): + if not openDocument("SampleApp.SampleApp.Source Files.main\\.cpp"): test.fatal("Could not open main.cpp") invokeMenuItem("File", "Exit") return diff --git a/tests/system/suite_HELP/tst_HELP04/test.py b/tests/system/suite_HELP/tst_HELP04/test.py index e78afa46b3f..63d2a284328 100644 --- a/tests/system/suite_HELP/tst_HELP04/test.py +++ b/tests/system/suite_HELP/tst_HELP04/test.py @@ -1,6 +1,6 @@ ############################################################################ # -# Copyright (C) 2016 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,9 +26,9 @@ source("../../shared/qtcreator.py") # test search in help mode and advanced search -searchKeywordDictionary = { "abundance":True, "deplmint":False, "QODBC":True, "bldx":False } -urlDictionary = { "abundance":"qthelp://com.trolltech.qt.487/qdoc/gettingstarted-develop.html", - "QODBC":"qthelp://com.trolltech.qt.487/qdoc/sql-driver.html" } +searchKeywordDictionary = { "compass":True, "deplmint":False, "QODBC":True, "bldx":False } +urlDictionary = {"compass":"qthelp://org.qt-project.qtdoc.5141/qtdoc/mobiledevelopment.html", + "QODBC":"qthelp://org.qt-project.qtsql.5141/qtsql/sql-driver.html" } def __getSelectedText__(): @@ -69,8 +69,9 @@ def main(): startQC() if not startedWithoutPluginError(): return - if qt4Available: - addHelpDocumentation([os.path.join(qt4Path, "doc", "qch", "qt.qch")]) + docFiles = ["qtdoc.qch", "qtsql.qch"] + docFiles = [os.path.join(Qt5Path.docsPath(Targets.DESKTOP_5_14_1_DEFAULT), file) for file in docFiles] + addHelpDocumentation(docFiles) # switch to help mode switchViewTo(ViewConstants.HELP) # verify that search widget is accessible @@ -87,9 +88,6 @@ def main(): test.verify(waitFor("noMatch in " "str(resultWidget.plainText)", 2000), "Verifying if search did not match anything.") - # workaround for "endless waiting cursor" - mouseClick(waitForObject("{column='0' container=':Qt Creator_QHelpContentWidget' " - "text='Qt Reference Documentation' type='QModelIndex'}")) # try to search keyword from list searchLineEdit = getChildByClass(waitForObject("{type='QHelpSearchQueryWidget' unnamed='1' visible='1' " "window=':Qt Creator_Core::Internal::MainWindow'}"), diff --git a/tests/system/suite_QMLS/shared/qmls.py b/tests/system/suite_QMLS/shared/qmls.py index 564e2f3884e..5ebcd1d76c7 100644 --- a/tests/system/suite_QMLS/shared/qmls.py +++ b/tests/system/suite_QMLS/shared/qmls.py @@ -32,7 +32,7 @@ def startQtCreatorWithNewAppAtQMLEditor(projectDir, projectName, line = None): # create qt quick application createNewQtQuickApplication(projectDir, projectName) # open qml file - qmlFile = projectName + ".Resources.qml\.qrc./.main\\.qml" + qmlFile = "%s.%s.qml\.qrc./.main\\.qml" % (projectName, projectName) if not openDocument(qmlFile): test.fatal("Could not open %s" % qmlFile) invokeMenuItem("File", "Exit") diff --git a/tests/system/suite_QMLS/tst_QMLS04/test.py b/tests/system/suite_QMLS/tst_QMLS04/test.py index b6336700c43..dd60b40a100 100644 --- a/tests/system/suite_QMLS/tst_QMLS04/test.py +++ b/tests/system/suite_QMLS/tst_QMLS04/test.py @@ -59,7 +59,7 @@ def main(): test.passes("Refactoring was properly applied in source file") else: test.fail("Refactoring of Text to MyComponent failed in source file. Content of editor:\n%s" % codeText) - myCompTE = "SampleApp.Resources.qml\\.qrc./.MyComponent\\.qml" + myCompTE = "SampleApp.SampleApp.qml\\.qrc./.MyComponent\\.qml" # there should be new QML file generated with name "MyComponent.qml" try: waitForObjectItem(":Qt Creator_Utils::NavigationTreeView", myCompTE, 5000) diff --git a/tests/system/suite_debugger/tst_cli_output_console/test.py b/tests/system/suite_debugger/tst_cli_output_console/test.py index 3f996241af1..be89db5a853 100644 --- a/tests/system/suite_debugger/tst_cli_output_console/test.py +++ b/tests/system/suite_debugger/tst_cli_output_console/test.py @@ -50,9 +50,10 @@ def main(): 'Waiter();']) # Rely on code completion for closing bracket invokeMenuItem("File", "Save All") - openDocument(project + "." + project + "\\.pro") - proEditor = waitForObject(":Qt Creator_TextEditor::TextEditorWidget") - test.verify("CONFIG += c++11 console" in str(proEditor.plainText), + openDocument(project + ".CMakeLists\\.txt") + projectFileEditor = waitForObject(":Qt Creator_TextEditor::TextEditorWidget") + projectFileContent = str(projectFileEditor.plainText) + test.verify("Widgets" not in projectFileContent and "MACOSX_BUNDLE" not in projectFileContent, "Verifying that program is configured with console") availableConfigs = iterateBuildConfigs() @@ -88,7 +89,7 @@ def main(): test.log("Debugging application") isMsvc = isMsvcConfig(kit) - invokeMenuItem("Debug", "Start Debugging", "Start debugging of startup project") + invokeMenuItem("Debug", "Start Debugging", "Start Debugging of Startup Project") handleDebuggerWarnings(config, isMsvc) ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton") outputWindow = waitForObject(":Qt Creator_Core::OutputWindow") diff --git a/tests/system/suite_editors/tst_qml_indent/test.py b/tests/system/suite_editors/tst_qml_indent/test.py index a81e3d558d6..a7659b7e560 100644 --- a/tests/system/suite_editors/tst_qml_indent/test.py +++ b/tests/system/suite_editors/tst_qml_indent/test.py @@ -37,7 +37,7 @@ def main(): invokeMenuItem("File", "Exit") def prepareQmlFile(): - if not openDocument("untitled.Resources.qml\.qrc./.main\\.qml"): + if not openDocument("untitled.untitled.qml\\.qrc./.main\\.qml"): test.fatal("Could not open main.qml") return None editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")