Merge remote-tracking branch 'origin/7.0'
Conflicts: src/plugins/webassembly/webassemblytoolchain.cpp Change-Id: Ia75c783e3ecab1f97de2b5c73a0979c49da82009
Before Width: | Height: | Size: 33 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 45 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 35 KiB |
@@ -102,7 +102,8 @@
|
|||||||
components in \uicontrol {Form Editor}, depending on the current page:
|
components in \uicontrol {Form Editor}, depending on the current page:
|
||||||
|
|
||||||
\list 1
|
\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.
|
\li Enter \e login as the state name.
|
||||||
\image loginui3-login-state.jpg "States view"
|
\image loginui3-login-state.jpg "States view"
|
||||||
\li Select \e repeatPassword in \uicontrol Navigator to display its
|
\li Select \e repeatPassword in \uicontrol Navigator to display its
|
||||||
|
@@ -267,10 +267,10 @@
|
|||||||
in \uicontrol Timeline:
|
in \uicontrol Timeline:
|
||||||
|
|
||||||
\list 1
|
\list 1
|
||||||
\li In \uicontrol States, select \uicontrol {Create New State} twice to
|
\li In \uicontrol States, select \inlineimage icons/plus.png
|
||||||
add two states called \e login and \e createAccount. You don't
|
twice to add two states called \e login and \e createAccount. You
|
||||||
need to make any property changes this time because you'll bind the
|
don't need to make any property changes this time because you'll
|
||||||
states to property animations.
|
bind the states to property animations.
|
||||||
\li In \uicontrol States, select \inlineimage icons/action-icon.png
|
\li In \uicontrol States, select \inlineimage icons/action-icon.png
|
||||||
for \e login to open the \uicontrol Actions menu, and then
|
for \e login to open the \uicontrol Actions menu, and then
|
||||||
select \uicontrol {Set as Default} to determine that the \e login
|
select \uicontrol {Set as Default} to determine that the \e login
|
||||||
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 14 KiB |
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 39 KiB After Width: | Height: | Size: 38 KiB |
@@ -234,7 +234,7 @@
|
|||||||
\section1 Using States to Change Component Property Values
|
\section1 Using States to Change Component Property Values
|
||||||
|
|
||||||
\list 1
|
\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.
|
twice to create two new states.
|
||||||
\image qmldesigner-borderimage-states.png "Active and inactive states"
|
\image qmldesigner-borderimage-states.png "Active and inactive states"
|
||||||
\li Select \uicontrol State1.
|
\li Select \uicontrol State1.
|
||||||
|
@@ -38,19 +38,10 @@
|
|||||||
To open the \uicontrol States view, select \uicontrol View >
|
To open the \uicontrol States view, select \uicontrol View >
|
||||||
\uicontrol Views > \uicontrol States.
|
\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
|
Initially, \uicontrol States displays a \e {base state} that shows the
|
||||||
selected \l{glossary-component}{component} in its initial state. To add
|
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:
|
For more information, watch the following video:
|
||||||
|
|
||||||
|
@@ -36,7 +36,8 @@
|
|||||||
\title Adding States
|
\title Adding States
|
||||||
|
|
||||||
You can define states for components and component instances in the
|
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"
|
\image qmldesigner-transitions.png "States view"
|
||||||
|
|
||||||
@@ -181,7 +182,7 @@
|
|||||||
\inlineimage icons/eye_open.png
|
\inlineimage icons/eye_open.png
|
||||||
icon in \l Navigator to hide components on the canvas that are
|
icon in \l Navigator to hide components on the canvas that are
|
||||||
not part of a view.
|
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.
|
a new state and give it a name. For example, \c Normal.
|
||||||
\li In \l Properties (2), deselect the \uicontrol Visibility
|
\li In \l Properties (2), deselect the \uicontrol Visibility
|
||||||
check box or set \uicontrol Opacity to 0 for each component that
|
check box or set \uicontrol Opacity to 0 for each component that
|
||||||
|
@@ -27,6 +27,9 @@ import QtQuick
|
|||||||
import QtQuick3D
|
import QtQuick3D
|
||||||
import QtQuick3D.Particles3D
|
import QtQuick3D.Particles3D
|
||||||
|
|
||||||
|
// Note: This gizmo is also used to visualize Attractor3D in addition to ParticleEmitter3D,
|
||||||
|
// as the two are very similar.
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
id: root
|
id: root
|
||||||
|
|
||||||
@@ -41,6 +44,7 @@ Node {
|
|||||||
property bool globalShow: false
|
property bool globalShow: false
|
||||||
property bool canBeVisible: activeScene === scene && targetNode && !hidden && !systemHidden
|
property bool canBeVisible: activeScene === scene && targetNode && !hidden && !systemHidden
|
||||||
property bool partOfActiveSystem: root.targetNode && root.targetNode.system === activeParticleSystem
|
property bool partOfActiveSystem: root.targetNode && root.targetNode.system === activeParticleSystem
|
||||||
|
property bool isEmitter: targetNode && targetNode instanceof ParticleEmitter3D
|
||||||
|
|
||||||
opacity: 0.15
|
opacity: 0.15
|
||||||
|
|
||||||
@@ -120,7 +124,10 @@ Node {
|
|||||||
|
|
||||||
DefaultMaterial {
|
DefaultMaterial {
|
||||||
id: defaultMaterial
|
id: defaultMaterial
|
||||||
diffuseColor: root.selected ? "#FF0000" : partOfActiveSystem ? "#FFFF00" : "#AAAAAA"
|
diffuseColor: root.selected ? "#FF0000"
|
||||||
|
: root.partOfActiveSystem
|
||||||
|
? root.isEmitter ? "#FFFF00" : "#0000FF"
|
||||||
|
: "#AAAAAA"
|
||||||
lighting: DefaultMaterial.NoLighting
|
lighting: DefaultMaterial.NoLighting
|
||||||
cullMode: Material.NoCulling
|
cullMode: Material.NoCulling
|
||||||
}
|
}
|
||||||
|
@@ -51,6 +51,7 @@
|
|||||||
#include <QtQuick3DParticles/private/qquick3dparticlemodelshape_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticlemodelshape_p.h>
|
||||||
#include <QtQuick3DParticles/private/qquick3dparticleemitter_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticleemitter_p.h>
|
||||||
#include <QtQuick3DParticles/private/qquick3dparticletrailemitter_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticletrailemitter_p.h>
|
||||||
|
#include <QtQuick3DParticles/private/qquick3dparticleattractor_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
@@ -477,11 +478,15 @@ QQuick3DNode *GeneralHelper::createParticleEmitterGizmoModel(QQuick3DNode *emitt
|
|||||||
QQuick3DMaterial *material) const
|
QQuick3DMaterial *material) const
|
||||||
{
|
{
|
||||||
#ifdef QUICK3D_PARTICLES_MODULE
|
#ifdef QUICK3D_PARTICLES_MODULE
|
||||||
auto e = qobject_cast<QQuick3DParticleEmitter *>(emitter);
|
if (qobject_cast<QQuick3DParticleTrailEmitter *>(emitter) || !material)
|
||||||
if (!e || qobject_cast<QQuick3DParticleTrailEmitter *>(e) || !material)
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
auto shape = qobject_cast<QQuick3DParticleModelShape *>(e->shape());
|
QQuick3DParticleModelShape *shape = nullptr;
|
||||||
|
if (auto e = qobject_cast<QQuick3DParticleEmitter *>(emitter))
|
||||||
|
shape = qobject_cast<QQuick3DParticleModelShape *>(e->shape());
|
||||||
|
else if (auto a = qobject_cast<QQuick3DParticleAttractor *>(emitter))
|
||||||
|
shape = qobject_cast<QQuick3DParticleModelShape *>(a->shape());
|
||||||
|
|
||||||
if (shape && shape->delegate()) {
|
if (shape && shape->delegate()) {
|
||||||
if (auto model = qobject_cast<QQuick3DModel *>(
|
if (auto model = qobject_cast<QQuick3DModel *>(
|
||||||
shape->delegate()->create(shape->delegate()->creationContext()))) {
|
shape->delegate()->create(shape->delegate()->creationContext()))) {
|
||||||
|
@@ -1576,6 +1576,9 @@ void NodeInstanceServer::setupState(qint32 stateInstanceId)
|
|||||||
|
|
||||||
void NodeInstanceServer::registerFonts(const QUrl &resourceUrl) const
|
void NodeInstanceServer::registerFonts(const QUrl &resourceUrl) const
|
||||||
{
|
{
|
||||||
|
if (!resourceUrl.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
// Autoregister all fonts found inside the project
|
// Autoregister all fonts found inside the project
|
||||||
QDirIterator it {QFileInfo(resourceUrl.toLocalFile()).absoluteFilePath(),
|
QDirIterator it {QFileInfo(resourceUrl.toLocalFile()).absoluteFilePath(),
|
||||||
{"*.ttf", "*.otf"}, QDir::Files, QDirIterator::Subdirectories};
|
{"*.ttf", "*.otf"}, QDir::Files, QDirIterator::Subdirectories};
|
||||||
|
@@ -113,6 +113,7 @@
|
|||||||
#include <QtQuick3DParticles/private/qquick3dparticle_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticle_p.h>
|
||||||
#include <QtQuick3DParticles/private/qquick3dparticleaffector_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticleaffector_p.h>
|
||||||
#include <QtQuick3DParticles/private/qquick3dparticleemitter_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticleemitter_p.h>
|
||||||
|
#include <QtQuick3DParticles/private/qquick3dparticleattractor_p.h>
|
||||||
#include <QtQuick3DParticles/private/qquick3dparticletrailemitter_p.h>
|
#include <QtQuick3DParticles/private/qquick3dparticletrailemitter_p.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -775,7 +776,8 @@ void Qt5InformationNodeInstanceServer::handleNode3DDestroyed(QObject *obj)
|
|||||||
} else if (qobject_cast<QQuick3DParticleSystem *>(obj)) {
|
} else if (qobject_cast<QQuick3DParticleSystem *>(obj)) {
|
||||||
QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleSystemGizmo",
|
QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleSystemGizmo",
|
||||||
Q_ARG(QVariant, objectToVariant(obj)));
|
Q_ARG(QVariant, objectToVariant(obj)));
|
||||||
} else if (qobject_cast<QQuick3DParticleEmitter *>(obj)
|
} else if ((qobject_cast<QQuick3DParticleEmitter *>(obj)
|
||||||
|
|| qobject_cast<QQuick3DParticleAttractor *>(obj))
|
||||||
&& !qobject_cast<QQuick3DParticleTrailEmitter *>(obj)) {
|
&& !qobject_cast<QQuick3DParticleTrailEmitter *>(obj)) {
|
||||||
QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleEmitterGizmo",
|
QMetaObject::invokeMethod(m_editView3DData.rootItem, "releaseParticleEmitterGizmo",
|
||||||
Q_ARG(QVariant, objectToVariant(obj)));
|
Q_ARG(QVariant, objectToVariant(obj)));
|
||||||
@@ -887,7 +889,8 @@ void Qt5InformationNodeInstanceServer::resolveSceneRoots()
|
|||||||
QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleSystemGizmoScene",
|
QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleSystemGizmoScene",
|
||||||
Q_ARG(QVariant, objectToVariant(newRoot)),
|
Q_ARG(QVariant, objectToVariant(newRoot)),
|
||||||
Q_ARG(QVariant, objectToVariant(node)));
|
Q_ARG(QVariant, objectToVariant(node)));
|
||||||
} else if (qobject_cast<QQuick3DParticleEmitter *>(node)
|
} else if ((qobject_cast<QQuick3DParticleEmitter *>(node)
|
||||||
|
|| qobject_cast<QQuick3DParticleAttractor *>(node))
|
||||||
&& !qobject_cast<QQuick3DParticleTrailEmitter *>(node)) {
|
&& !qobject_cast<QQuick3DParticleTrailEmitter *>(node)) {
|
||||||
QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleEmitterGizmoScene",
|
QMetaObject::invokeMethod(m_editView3DData.rootItem, "updateParticleEmitterGizmoScene",
|
||||||
Q_ARG(QVariant, objectToVariant(newRoot)),
|
Q_ARG(QVariant, objectToVariant(newRoot)),
|
||||||
@@ -1469,7 +1472,8 @@ void Qt5InformationNodeInstanceServer::createCameraAndLightGizmos(
|
|||||||
lights[find3DSceneRoot(instance)] << instance.internalObject();
|
lights[find3DSceneRoot(instance)] << instance.internalObject();
|
||||||
} else if (instance.isSubclassOf("QQuick3DParticleSystem")) {
|
} else if (instance.isSubclassOf("QQuick3DParticleSystem")) {
|
||||||
particleSystems[find3DSceneRoot(instance)] << instance.internalObject();
|
particleSystems[find3DSceneRoot(instance)] << instance.internalObject();
|
||||||
} else if (instance.isSubclassOf("QQuick3DParticleEmitter")
|
} else if ((instance.isSubclassOf("QQuick3DParticleEmitter")
|
||||||
|
|| instance.isSubclassOf("QQuick3DParticleAttractor"))
|
||||||
&& !instance.isSubclassOf("QQuick3DParticleTrailEmitter")) {
|
&& !instance.isSubclassOf("QQuick3DParticleTrailEmitter")) {
|
||||||
particleEmitters[find3DSceneRoot(instance)] << instance.internalObject();
|
particleEmitters[find3DSceneRoot(instance)] << instance.internalObject();
|
||||||
}
|
}
|
||||||
@@ -2016,7 +2020,7 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
|
|||||||
#ifdef QUICK3D_PARTICLES_MODULE
|
#ifdef QUICK3D_PARTICLES_MODULE
|
||||||
|| qobject_cast<QQuick3DParticleSystem *>(object)
|
|| qobject_cast<QQuick3DParticleSystem *>(object)
|
||||||
|| qobject_cast<QQuick3DParticleEmitter *>(object)
|
|| qobject_cast<QQuick3DParticleEmitter *>(object)
|
||||||
|
|| qobject_cast<QQuick3DParticleAttractor *>(object)
|
||||||
#endif
|
#endif
|
||||||
) {
|
) {
|
||||||
return true;
|
return true;
|
||||||
|
@@ -39,7 +39,12 @@ Item {
|
|||||||
property string contextFilePath: ""
|
property string contextFilePath: ""
|
||||||
property var contextDir: undefined
|
property var contextDir: undefined
|
||||||
property bool isDirContextMenu: false
|
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()
|
function clearSearchFilter()
|
||||||
{
|
{
|
||||||
@@ -48,18 +53,23 @@ Item {
|
|||||||
|
|
||||||
function updateDropExtFiles(drag)
|
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) {
|
for (const u of drag.urls) {
|
||||||
var url = u.toString();
|
var url = u.toString();
|
||||||
if (url.startsWith("file:///")) // remove file scheme (happens on Windows)
|
if (url.startsWith("file:///")) // remove file scheme (happens on Windows)
|
||||||
url = url.substr(8)
|
url = url.substr(8)
|
||||||
|
|
||||||
var ext = url.slice(url.lastIndexOf('.') + 1).toLowerCase()
|
var ext = '*.' + url.slice(url.lastIndexOf('.') + 1).toLowerCase()
|
||||||
if (rootView.supportedDropSuffixes().includes('*.' + ext))
|
if (simpleSuffixes.includes(ext))
|
||||||
root.dropExtFiles.push(url)
|
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)
|
DropArea { // handles external drop on empty area of the view (goes to root folder)
|
||||||
@@ -73,13 +83,14 @@ Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onDropped: {
|
onDropped: {
|
||||||
rootView.handleExtFilesDrop(root.dropExtFiles, assetsModel.rootDir().dirPath)
|
rootView.handleExtFilesDrop(root.dropSimpleExtFiles, root.dropComplexExtFiles,
|
||||||
|
assetsModel.rootDir().dirPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas { // marker for the drop area
|
Canvas { // marker for the drop area
|
||||||
id: dropCanvas
|
id: dropCanvas
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
visible: dropArea.containsDrag
|
visible: dropArea.containsDrag && root.dropSimpleExtFiles.length > 0
|
||||||
|
|
||||||
onWidthChanged: dropCanvas.requestPaint()
|
onWidthChanged: dropCanvas.requestPaint()
|
||||||
onHeightChanged: dropCanvas.requestPaint()
|
onHeightChanged: dropCanvas.requestPaint()
|
||||||
@@ -458,50 +469,62 @@ Item {
|
|||||||
visible: assetsModel.isEmpty && searchBox.isEmpty()
|
visible: assetsModel.isEmpty && searchBox.isEmpty()
|
||||||
clip: true
|
clip: true
|
||||||
|
|
||||||
Column {
|
DropArea { // handles external drop (goes into default folder based on suffix)
|
||||||
id: colNoAssets
|
anchors.fill: parent
|
||||||
|
|
||||||
spacing: 20
|
onEntered: (drag)=> {
|
||||||
x: 20
|
root.updateDropExtFiles(drag)
|
||||||
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 {
|
onDropped: {
|
||||||
source: "image://qmldesigner_assets/browse"
|
rootView.handleExtFilesDrop(root.dropSimpleExtFiles, root.dropComplexExtFiles)
|
||||||
anchors.horizontalCenter: parent.horizontalCenter
|
}
|
||||||
scale: maBrowse.containsMouse ? 1.2 : 1
|
|
||||||
Behavior on scale {
|
Column {
|
||||||
NumberAnimation {
|
id: colNoAssets
|
||||||
duration: 300
|
|
||||||
easing.type: Easing.OutQuad
|
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 {
|
Text {
|
||||||
id: maBrowse
|
text: qsTr("Drag-and-drop your assets here or click the '+' button to browse assets from the file system.")
|
||||||
anchors.fill: parent
|
color: StudioTheme.Values.themeTextColor
|
||||||
hoverEnabled: true
|
font.pixelSize: 18
|
||||||
onClicked: rootView.handleAddAsset();
|
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)=> {
|
onDropEnter: (drag)=> {
|
||||||
root.updateDropExtFiles(drag)
|
root.updateDropExtFiles(drag)
|
||||||
section.highlight = drag.accepted
|
section.highlight = drag.accepted && root.dropSimpleExtFiles.length > 0
|
||||||
}
|
}
|
||||||
|
|
||||||
onDropExit: {
|
onDropExit: {
|
||||||
@@ -555,7 +578,9 @@ Item {
|
|||||||
|
|
||||||
onDrop: {
|
onDrop: {
|
||||||
section.highlight = false
|
section.highlight = false
|
||||||
rootView.handleExtFilesDrop(root.dropExtFiles, dirPath)
|
rootView.handleExtFilesDrop(root.dropSimpleExtFiles,
|
||||||
|
root.dropComplexExtFiles,
|
||||||
|
dirPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
onShowContextMenu: {
|
onShowContextMenu: {
|
||||||
|
@@ -161,7 +161,7 @@ FocusScope {
|
|||||||
Text {
|
Text {
|
||||||
text: "+"
|
text: "+"
|
||||||
anchors.centerIn: parent
|
anchors.centerIn: parent
|
||||||
anchors.verticalCenterOffset: -5
|
anchors.verticalCenterOffset: -16
|
||||||
font.pixelSize: parent.height * .5
|
font.pixelSize: parent.height * .5
|
||||||
color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1)
|
color: Qt.lighter(StudioTheme.Values.themeControlBackgroundInteraction, addState.containsMouse ? 1.5 : 1)
|
||||||
}
|
}
|
||||||
|
@@ -479,7 +479,8 @@ bool checkParameters(const QSsh::SshConnectionParameters ¶ms)
|
|||||||
|
|
||||||
void printSetupHelp()
|
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"
|
"1. Run a server on the host to connect to:\n"
|
||||||
" systemctl start sshd\n"
|
" systemctl start sshd\n"
|
||||||
"2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n"
|
"2. Create your own ssh key (needed only once). For fedora it needs ecdsa type:\n"
|
||||||
|
@@ -111,6 +111,7 @@ namespace Internal {
|
|||||||
void popupRequested(bool focus);
|
void popupRequested(bool focus);
|
||||||
void handleExpandCollapseToolButton(bool checked);
|
void handleExpandCollapseToolButton(bool checked);
|
||||||
void updateFilterButton();
|
void updateFilterButton();
|
||||||
|
QList<QWidget *> toolBarWidgets();
|
||||||
|
|
||||||
SearchResultWindow *q;
|
SearchResultWindow *q;
|
||||||
QList<Internal::SearchResultWidget *> m_searchResultWidgets;
|
QList<Internal::SearchResultWidget *> m_searchResultWidgets;
|
||||||
@@ -120,9 +121,9 @@ namespace Internal {
|
|||||||
QAction *m_expandCollapseAction;
|
QAction *m_expandCollapseAction;
|
||||||
static const bool m_initiallyExpand;
|
static const bool m_initiallyExpand;
|
||||||
QWidget *m_spacer;
|
QWidget *m_spacer;
|
||||||
QLabel *m_historyLabel;
|
QLabel *m_historyLabel = nullptr;
|
||||||
QWidget *m_spacer2;
|
QWidget *m_spacer2;
|
||||||
QComboBox *m_recentSearchesBox;
|
QComboBox *m_recentSearchesBox = nullptr;
|
||||||
QStackedWidget *m_widget;
|
QStackedWidget *m_widget;
|
||||||
QList<SearchResult *> m_searchResults;
|
QList<SearchResult *> m_searchResults;
|
||||||
int m_currentIndex;
|
int m_currentIndex;
|
||||||
@@ -139,20 +140,13 @@ namespace Internal {
|
|||||||
m_expandCollapseButton(nullptr),
|
m_expandCollapseButton(nullptr),
|
||||||
m_expandCollapseAction(new QAction(tr("Expand All"), window)),
|
m_expandCollapseAction(new QAction(tr("Expand All"), window)),
|
||||||
m_spacer(new QWidget),
|
m_spacer(new QWidget),
|
||||||
m_historyLabel(new QLabel(tr("History:"))),
|
|
||||||
m_spacer2(new QWidget),
|
m_spacer2(new QWidget),
|
||||||
m_recentSearchesBox(new QComboBox),
|
|
||||||
m_widget(new QStackedWidget),
|
m_widget(new QStackedWidget),
|
||||||
m_currentIndex(0),
|
m_currentIndex(0),
|
||||||
m_tabWidth(8)
|
m_tabWidth(8)
|
||||||
{
|
{
|
||||||
m_spacer->setMinimumWidth(30);
|
m_spacer->setMinimumWidth(30);
|
||||||
m_spacer2->setMinimumWidth(5);
|
m_spacer2->setMinimumWidth(5);
|
||||||
m_recentSearchesBox->setProperty("drawleftborder", true);
|
|
||||||
m_recentSearchesBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
||||||
m_recentSearchesBox->addItem(tr("New Search"));
|
|
||||||
connect(m_recentSearchesBox, QOverload<int>::of(&QComboBox::activated),
|
|
||||||
this, &SearchResultWindowPrivate::setCurrentIndexWithFocus);
|
|
||||||
|
|
||||||
m_widget->setWindowTitle(q->displayName());
|
m_widget->setWindowTitle(q->displayName());
|
||||||
|
|
||||||
@@ -194,6 +188,7 @@ namespace Internal {
|
|||||||
|
|
||||||
void SearchResultWindowPrivate::setCurrentIndex(int index, bool focus)
|
void SearchResultWindowPrivate::setCurrentIndex(int index, bool focus)
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(m_recentSearchesBox, return );
|
||||||
if (isSearchVisible())
|
if (isSearchVisible())
|
||||||
m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(false);
|
m_searchResultWidgets.at(visibleSearchIndex())->notifyVisibilityChanged(false);
|
||||||
m_currentIndex = index;
|
m_currentIndex = index;
|
||||||
@@ -217,6 +212,7 @@ namespace Internal {
|
|||||||
|
|
||||||
void SearchResultWindowPrivate::moveWidgetToTop()
|
void SearchResultWindowPrivate::moveWidgetToTop()
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(m_recentSearchesBox, return );
|
||||||
auto widget = qobject_cast<SearchResultWidget *>(sender());
|
auto widget = qobject_cast<SearchResultWidget *>(sender());
|
||||||
QTC_ASSERT(widget, return);
|
QTC_ASSERT(widget, return);
|
||||||
const int index = m_searchResultWidgets.indexOf(widget);
|
const int index = m_searchResultWidgets.indexOf(widget);
|
||||||
@@ -458,8 +454,7 @@ QWidget *SearchResultWindow::outputWidget(QWidget *)
|
|||||||
*/
|
*/
|
||||||
QList<QWidget*> SearchResultWindow::toolBarWidgets() const
|
QList<QWidget*> SearchResultWindow::toolBarWidgets() const
|
||||||
{
|
{
|
||||||
return {d->m_expandCollapseButton, d->m_filterButton, d->m_newSearchButton, d->m_spacer,
|
return d->toolBarWidgets();
|
||||||
d->m_historyLabel, d->m_spacer2, d->m_recentSearchesBox};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -497,16 +492,19 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label,
|
|||||||
PreserveCaseMode preserveCaseMode,
|
PreserveCaseMode preserveCaseMode,
|
||||||
const QString &cfgGroup)
|
const QString &cfgGroup)
|
||||||
{
|
{
|
||||||
if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) {
|
if (QTC_GUARD(d->m_recentSearchesBox)) {
|
||||||
if (d->m_currentIndex >= d->m_recentSearchesBox->count() - 1) {
|
if (d->m_searchResults.size() >= MAX_SEARCH_HISTORY) {
|
||||||
// temporarily set the index to the last but one existing
|
if (d->m_currentIndex >= d->m_recentSearchesBox->count() - 1) {
|
||||||
d->m_currentIndex = d->m_recentSearchesBox->count() - 2;
|
// 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);
|
d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm));
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
auto widget = new SearchResultWidget;
|
auto widget = new SearchResultWidget;
|
||||||
connect(widget, &SearchResultWidget::filterInvalidated, this, [this, widget] {
|
connect(widget, &SearchResultWidget::filterInvalidated, this, [this, widget] {
|
||||||
@@ -532,7 +530,6 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label,
|
|||||||
widget->setInfo(label, toolTip, searchTerm);
|
widget->setInfo(label, toolTip, searchTerm);
|
||||||
auto result = new SearchResult(widget);
|
auto result = new SearchResult(widget);
|
||||||
d->m_searchResults.prepend(result);
|
d->m_searchResults.prepend(result);
|
||||||
d->m_recentSearchesBox->insertItem(1, tr("%1 %2").arg(label, searchTerm));
|
|
||||||
if (d->m_currentIndex > 0)
|
if (d->m_currentIndex > 0)
|
||||||
++d->m_currentIndex; // so setCurrentIndex still knows about the right "currentIndex" and its widget
|
++d->m_currentIndex; // so setCurrentIndex still knows about the right "currentIndex" and its widget
|
||||||
d->setCurrentIndexWithFocus(1);
|
d->setCurrentIndexWithFocus(1);
|
||||||
@@ -544,8 +541,10 @@ SearchResult *SearchResultWindow::startNewSearch(const QString &label,
|
|||||||
*/
|
*/
|
||||||
void SearchResultWindow::clearContents()
|
void SearchResultWindow::clearContents()
|
||||||
{
|
{
|
||||||
for (int i = d->m_recentSearchesBox->count() - 1; i > 0 /* don't want i==0 */; --i)
|
if (QTC_GUARD(d->m_recentSearchesBox)) {
|
||||||
d->m_recentSearchesBox->removeItem(i);
|
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)
|
foreach (Internal::SearchResultWidget *widget, d->m_searchResultWidgets)
|
||||||
widget->notifyVisibilityChanged(false);
|
widget->notifyVisibilityChanged(false);
|
||||||
qDeleteAll(d->m_searchResultWidgets);
|
qDeleteAll(d->m_searchResultWidgets);
|
||||||
@@ -642,6 +641,29 @@ void SearchResultWindowPrivate::updateFilterButton()
|
|||||||
&& m_searchResultWidgets.at(visibleSearchIndex())->hasFilter());
|
&& m_searchResultWidgets.at(visibleSearchIndex())->hasFilter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QWidget *> 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<int>::of(&QComboBox::activated),
|
||||||
|
this,
|
||||||
|
&SearchResultWindowPrivate::setCurrentIndexWithFocus);
|
||||||
|
}
|
||||||
|
return {m_expandCollapseButton,
|
||||||
|
m_filterButton,
|
||||||
|
m_newSearchButton,
|
||||||
|
m_spacer,
|
||||||
|
m_historyLabel,
|
||||||
|
m_spacer2,
|
||||||
|
m_recentSearchesBox};
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
@@ -684,7 +684,7 @@ Toolchains KitDetectorPrivate::autoDetectToolChains()
|
|||||||
emit q->logOutput('\n' + tr("Searching toolchains..."));
|
emit q->logOutput('\n' + tr("Searching toolchains..."));
|
||||||
for (ToolChainFactory *factory : factories) {
|
for (ToolChainFactory *factory : factories) {
|
||||||
emit q->logOutput(tr("Searching toolchains of type %1").arg(factory->displayName()));
|
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);
|
const Toolchains newToolChains = factory->autoDetect(detector);
|
||||||
for (ToolChain *toolChain : newToolChains) {
|
for (ToolChain *toolChain : newToolChains) {
|
||||||
emit q->logOutput(tr("Found \"%1\"").arg(toolChain->compilerCommand().toUserOutput()));
|
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 {});
|
QTC_ASSERT(m_shell && m_shell->isRunning(), return {});
|
||||||
QMutexLocker l(&m_shellMutex);
|
QMutexLocker l(&m_shellMutex);
|
||||||
m_shell->readAllStandardOutput(); // clean possible left-overs
|
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");
|
const QByteArray markerWithNewLine("___QC_DOCKER_" + randomHex() + "_OUTPUT_MARKER___\n");
|
||||||
m_shell->write(cmd.toUserOutput().toUtf8() + "\necho -n \"" + markerWithNewLine + "\"\n");
|
m_shell->write(cmd.toUserOutput().toUtf8() + "\necho -n \"" + markerWithNewLine + "\"\n");
|
||||||
QByteArray output;
|
QByteArray output;
|
||||||
@@ -1506,6 +1512,11 @@ QByteArray DockerDevicePrivate::outputForRunInShell(const CommandLine &cmd) cons
|
|||||||
LOG("Run command in shell:" << cmd.toUserOutput() << "output size:" << output.size());
|
LOG("Run command in shell:" << cmd.toUserOutput() << "output size:" << output.size());
|
||||||
if (QTC_GUARD(output.endsWith(markerWithNewLine)))
|
if (QTC_GUARD(output.endsWith(markerWithNewLine)))
|
||||||
output.chop(markerWithNewLine.size());
|
output.chop(markerWithNewLine.size());
|
||||||
|
const QByteArray currentError = m_shell->readAllStandardError();
|
||||||
|
if (!currentError.isEmpty()) {
|
||||||
|
LOG("Unexpected current stderr: " << currentError);
|
||||||
|
QTC_CHECK(false);
|
||||||
|
}
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -365,7 +365,7 @@ static ToolChain *iarToolChain(const FilePath &path, Id language)
|
|||||||
== BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
|
== BareMetal::Constants::IAREW_TOOLCHAIN_TYPEID;
|
||||||
});
|
});
|
||||||
if (iarFactory) {
|
if (iarFactory) {
|
||||||
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}));
|
Toolchains detected = iarFactory->autoDetect(ToolchainDetector({}, {}, {}));
|
||||||
if (detected.isEmpty())
|
if (detected.isEmpty())
|
||||||
detected = iarFactory->detectForImport({path, language});
|
detected = iarFactory->detectForImport({path, language});
|
||||||
for (auto tc : detected) {
|
for (auto tc : detected) {
|
||||||
|
@@ -1090,10 +1090,11 @@ Toolchains GccToolChainFactory::detectForImport(const ToolChainDescription &tcd)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
static FilePaths findCompilerCandidates(const ToolchainDetector &detector,
|
||||||
const QString &compilerName,
|
const QString &compilerName,
|
||||||
bool detectVariants)
|
bool detectVariants)
|
||||||
{
|
{
|
||||||
|
const IDevice::ConstPtr device = detector.device;
|
||||||
const QFileInfo fi(compilerName);
|
const QFileInfo fi(compilerName);
|
||||||
if (device.isNull() && fi.isAbsolute() && fi.isFile())
|
if (device.isNull() && fi.isAbsolute() && fi.isFile())
|
||||||
return {FilePath::fromString(compilerName)};
|
return {FilePath::fromString(compilerName)};
|
||||||
@@ -1119,7 +1120,9 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
|||||||
|
|
||||||
if (!device.isNull()) {
|
if (!device.isNull()) {
|
||||||
// FIXME: Merge with block below
|
// 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)) {
|
for (const FilePath &deviceDir : qAsConst(searchPaths)) {
|
||||||
static const QRegularExpression regexp(binaryRegexp);
|
static const QRegularExpression regexp(binaryRegexp);
|
||||||
const auto callBack = [&compilerPaths, compilerName](const FilePath &candidate) {
|
const auto callBack = [&compilerPaths, compilerName](const FilePath &candidate) {
|
||||||
@@ -1135,16 +1138,19 @@ static FilePaths findCompilerCandidates(const IDevice::ConstPtr &device,
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// The normal, local host case.
|
// The normal, local host case.
|
||||||
FilePaths searchPaths = Environment::systemEnvironment().path();
|
FilePaths searchPaths = detector.searchPaths;
|
||||||
searchPaths << gnuSearchPathsFromRegistry();
|
if (searchPaths.isEmpty()) {
|
||||||
searchPaths << atmelSearchPathsFromRegistry();
|
searchPaths = Environment::systemEnvironment().path();
|
||||||
searchPaths << renesasRl78SearchPathsFromRegistry();
|
searchPaths << gnuSearchPathsFromRegistry();
|
||||||
if (HostOsInfo::isAnyUnixHost()) {
|
searchPaths << atmelSearchPathsFromRegistry();
|
||||||
FilePath ccachePath = "/usr/lib/ccache/bin";
|
searchPaths << renesasRl78SearchPathsFromRegistry();
|
||||||
if (!ccachePath.exists())
|
if (HostOsInfo::isAnyUnixHost()) {
|
||||||
ccachePath = "/usr/lib/ccache";
|
FilePath ccachePath = "/usr/lib/ccache/bin";
|
||||||
if (ccachePath.exists() && !searchPaths.contains(ccachePath))
|
if (!ccachePath.exists())
|
||||||
searchPaths << ccachePath;
|
ccachePath = "/usr/lib/ccache";
|
||||||
|
if (ccachePath.exists() && !searchPaths.contains(ccachePath))
|
||||||
|
searchPaths << ccachePath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (const FilePath &dir : qAsConst(searchPaths)) {
|
for (const FilePath &dir : qAsConst(searchPaths)) {
|
||||||
static const QRegularExpression regexp(binaryRegexp);
|
static const QRegularExpression regexp(binaryRegexp);
|
||||||
@@ -1173,7 +1179,7 @@ Toolchains GccToolChainFactory::autoDetectToolchains(
|
|||||||
const ToolchainChecker &checker) const
|
const ToolchainChecker &checker) const
|
||||||
{
|
{
|
||||||
const FilePaths compilerPaths =
|
const FilePaths compilerPaths =
|
||||||
findCompilerCandidates(detector.device, compilerName, detectVariants == DetectVariants::Yes);
|
findCompilerCandidates(detector, compilerName, detectVariants == DetectVariants::Yes);
|
||||||
Toolchains existingCandidates = filtered(detector.alreadyKnown,
|
Toolchains existingCandidates = filtered(detector.alreadyKnown,
|
||||||
[language](const ToolChain *tc) { return tc->language() == language; });
|
[language](const ToolChain *tc) { return tc->language() == language; });
|
||||||
Toolchains result;
|
Toolchains result;
|
||||||
@@ -1748,7 +1754,7 @@ Toolchains ClangToolChainFactory::autoDetect(const ToolchainDetector &detector)
|
|||||||
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix();
|
const FilePath clang = compilerPath.parentDir().pathAppended("clang").withExecutableSuffix();
|
||||||
tcs.append(autoDetectToolchains(clang.toString(), DetectVariants::No,
|
tcs.append(autoDetectToolchains(clang.toString(), DetectVariants::No,
|
||||||
Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID,
|
Constants::C_LANGUAGE_ID, Constants::CLANG_TOOLCHAIN_TYPEID,
|
||||||
ToolchainDetector(known, detector.device)));
|
ToolchainDetector(known, detector.device, detector.searchPaths)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return tcs;
|
return tcs;
|
||||||
|
@@ -673,8 +673,10 @@ void ToolChainFactory::setUserCreatable(bool userCreatable)
|
|||||||
m_userCreatable = userCreatable;
|
m_userCreatable = userCreatable;
|
||||||
}
|
}
|
||||||
|
|
||||||
ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown, const IDevice::ConstPtr &device)
|
ToolchainDetector::ToolchainDetector(const Toolchains &alreadyKnown,
|
||||||
: alreadyKnown(alreadyKnown), device(device)
|
const IDevice::ConstPtr &device,
|
||||||
|
const FilePaths &searchPaths)
|
||||||
|
: alreadyKnown(alreadyKnown), device(device), searchPaths(searchPaths)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
BadToolchain::BadToolchain(const Utils::FilePath &filePath)
|
BadToolchain::BadToolchain(const Utils::FilePath &filePath)
|
||||||
|
@@ -250,13 +250,16 @@ public:
|
|||||||
class PROJECTEXPLORER_EXPORT ToolchainDetector
|
class PROJECTEXPLORER_EXPORT ToolchainDetector
|
||||||
{
|
{
|
||||||
public:
|
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;
|
bool isBadToolchain(const Utils::FilePath &toolchain) const;
|
||||||
void addBadToolchain(const Utils::FilePath &toolchain) const;
|
void addBadToolchain(const Utils::FilePath &toolchain) const;
|
||||||
|
|
||||||
const Toolchains alreadyKnown;
|
const Toolchains alreadyKnown;
|
||||||
const IDevice::ConstPtr device;
|
const IDevice::ConstPtr device;
|
||||||
|
const Utils::FilePaths searchPaths; // If empty use device path and/or magic.
|
||||||
};
|
};
|
||||||
|
|
||||||
class PROJECTEXPLORER_EXPORT ToolChainFactory
|
class PROJECTEXPLORER_EXPORT ToolChainFactory
|
||||||
|
@@ -412,7 +412,7 @@ void ToolChainOptionsWidget::redetectToolchains()
|
|||||||
QSet<ToolChain *> toDelete;
|
QSet<ToolChain *> toDelete;
|
||||||
ToolChainManager::resetBadToolchains();
|
ToolChainManager::resetBadToolchains();
|
||||||
for (ToolChainFactory *f : ToolChainFactory::allToolChainFactories()) {
|
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)) {
|
for (ToolChain * const tc : f->autoDetect(detector)) {
|
||||||
if (knownTcs.contains(tc) || toDelete.contains(tc))
|
if (knownTcs.contains(tc) || toDelete.contains(tc))
|
||||||
continue;
|
continue;
|
||||||
|
@@ -205,7 +205,7 @@ Toolchains ToolChainSettingsAccessor::restoreToolChains(QWidget *parent) const
|
|||||||
= Utils::filtered(userFileTcs, &ToolChain::isAutoDetected);
|
= Utils::filtered(userFileTcs, &ToolChain::isAutoDetected);
|
||||||
// FIXME: Use real device?
|
// FIXME: Use real device?
|
||||||
const Toolchains autodetectedTcs =
|
const Toolchains autodetectedTcs =
|
||||||
autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {}));
|
autoDetectToolChains(ToolchainDetector(autodetectedUserFileTcs, {}, {}));
|
||||||
|
|
||||||
// merge tool chains and register those that we need to keep:
|
// merge tool chains and register those that we need to keep:
|
||||||
const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs);
|
const ToolChainOperations ops = mergeToolChainLists(systemFileTcs, userFileTcs, autodetectedTcs);
|
||||||
|
@@ -213,34 +213,38 @@ void AssetsLibraryWidget::handleAddAsset()
|
|||||||
addResources({});
|
addResources({});
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &filesPaths, const QString &targetDirPath)
|
void AssetsLibraryWidget::handleExtFilesDrop(const QStringList &simpleFilesPaths,
|
||||||
|
const QStringList &complexFilesPaths,
|
||||||
|
const QString &targetDirPath)
|
||||||
{
|
{
|
||||||
QStringList assetPaths;
|
if (!simpleFilesPaths.isEmpty()) {
|
||||||
QStringList otherPaths; // as of now 3D models, and 3D Studio presentations
|
if (targetDirPath.isEmpty()) {
|
||||||
std::tie(assetPaths, otherPaths) = Utils::partition(filesPaths, [](const QString &path) {
|
addResources(simpleFilesPaths);
|
||||||
QString suffix = "*." + path.split('.').last().toLower();
|
} else {
|
||||||
return AssetsLibraryModel::supportedSuffixes().contains(suffix);
|
AddFilesResult result = ModelNodeOperations::addFilesToProject(simpleFilesPaths,
|
||||||
});
|
targetDirPath);
|
||||||
|
if (result == AddFilesResult::Failed) {
|
||||||
AddFilesResult result = ModelNodeOperations::addFilesToProject(assetPaths, targetDirPath);
|
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
||||||
if (result == AddFilesResult::Failed) {
|
tr("Could not add %1 to project.")
|
||||||
Core::AsynchronousMessageBox::warning(tr("Failed to Add Files"),
|
.arg(simpleFilesPaths.join(' ')));
|
||||||
tr("Could not add %1 to project.")
|
}
|
||||||
.arg(filesPaths.join(' ')));
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!otherPaths.empty())
|
if (!complexFilesPaths.empty())
|
||||||
addResources(otherPaths);
|
addResources(complexFilesPaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
QSet<QString> AssetsLibraryWidget::supportedDropSuffixes()
|
QSet<QString> AssetsLibraryWidget::supportedAssetSuffixes(bool complex)
|
||||||
{
|
{
|
||||||
const QList<AddResourceHandler> handlers = QmlDesignerPlugin::instance()->viewManager()
|
const QList<AddResourceHandler> handlers = QmlDesignerPlugin::instance()->viewManager()
|
||||||
.designerActionManager().addResourceHandler();
|
.designerActionManager().addResourceHandler();
|
||||||
|
|
||||||
QSet<QString> suffixes;
|
QSet<QString> suffixes;
|
||||||
for (const AddResourceHandler &handler : handlers)
|
for (const AddResourceHandler &handler : handlers) {
|
||||||
suffixes.insert(handler.filter);
|
if (AssetsLibraryModel::supportedSuffixes().contains(handler.filter) != complex)
|
||||||
|
suffixes.insert(handler.filter);
|
||||||
|
}
|
||||||
|
|
||||||
return suffixes;
|
return suffixes;
|
||||||
}
|
}
|
||||||
|
@@ -80,8 +80,10 @@ public:
|
|||||||
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
|
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
|
||||||
Q_INVOKABLE void handleAddAsset();
|
Q_INVOKABLE void handleAddAsset();
|
||||||
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
Q_INVOKABLE void handleSearchfilterChanged(const QString &filterText);
|
||||||
Q_INVOKABLE void handleExtFilesDrop(const QStringList &filesPaths, const QString &targetDirPath);
|
Q_INVOKABLE void handleExtFilesDrop(const QStringList &simpleFilesPaths,
|
||||||
Q_INVOKABLE QSet<QString> supportedDropSuffixes();
|
const QStringList &complexFilesPaths,
|
||||||
|
const QString &targetDirPath = {});
|
||||||
|
Q_INVOKABLE QSet<QString> supportedAssetSuffixes(bool complex);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void itemActivated(const QString &itemName);
|
void itemActivated(const QString &itemName);
|
||||||
|
@@ -360,9 +360,9 @@ void Edit3DView::createEdit3DActions()
|
|||||||
|
|
||||||
m_showParticleEmitterAction = new Edit3DAction(
|
m_showParticleEmitterAction = new Edit3DAction(
|
||||||
QmlDesigner::Constants::EDIT3D_EDIT_SHOW_PARTICLE_EMITTER, View3DActionCommand::ShowParticleEmitter,
|
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,
|
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 &) {
|
SelectionContextOperation resetTrigger = [this](const SelectionContext &) {
|
||||||
m_particlesPlayAction->action()->setEnabled(particlemode);
|
m_particlesPlayAction->action()->setEnabled(particlemode);
|
||||||
|
@@ -170,6 +170,8 @@ private: // functions
|
|||||||
|
|
||||||
NodeInstance loadNode(const ModelNode &node);
|
NodeInstance loadNode(const ModelNode &node);
|
||||||
|
|
||||||
|
void clearErrors();
|
||||||
|
|
||||||
void removeAllInstanceNodeRelationships();
|
void removeAllInstanceNodeRelationships();
|
||||||
|
|
||||||
void removeRecursiveChildRelationship(const ModelNode &removedNode);
|
void removeRecursiveChildRelationship(const ModelNode &removedNode);
|
||||||
|
@@ -326,10 +326,17 @@ void NodeInstanceView::endPuppetTransaction()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NodeInstanceView::clearErrors()
|
||||||
|
{
|
||||||
|
for (NodeInstance &instance : instances()) {
|
||||||
|
instance.setError({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodeInstanceView::restartProcess()
|
void NodeInstanceView::restartProcess()
|
||||||
{
|
{
|
||||||
if (rootNodeInstance().isValid())
|
clearErrors();
|
||||||
rootNodeInstance().setError({});
|
|
||||||
emitInstanceErrorChange({});
|
emitInstanceErrorChange({});
|
||||||
emitDocumentMessage({}, {});
|
emitDocumentMessage({}, {});
|
||||||
|
|
||||||
@@ -556,10 +563,11 @@ void NodeInstanceView::nodeReparented(const ModelNode &node, const NodeAbstractP
|
|||||||
m_nodeInstanceServer->reparentInstances(
|
m_nodeInstanceServer->reparentInstances(
|
||||||
createReparentInstancesCommand(node, newPropertyParent, oldPropertyParent));
|
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
|
// autodetecting the particle system it belongs to. QTBUG-101157
|
||||||
if (node.isSubclassOf("QtQuick.Particles3D.ParticleEmitter3D")
|
if ((node.isSubclassOf("QtQuick.Particles3D.ParticleEmitter3D")
|
||||||
&& node.property("system").toBindingProperty().expression().isEmpty()) {
|
|| node.isSubclassOf("QtQuick.Particles3D.Affector3D"))
|
||||||
|
&& node.property("system").toBindingProperty().expression().isEmpty()) {
|
||||||
resetPuppet();
|
resetPuppet();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -957,6 +965,8 @@ CreateSceneCommand NodeInstanceView::createCreateSceneCommand()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clearErrors();
|
||||||
|
|
||||||
nodeList = filterNodesForSkipItems(nodeList);
|
nodeList = filterNodesForSkipItems(nodeList);
|
||||||
|
|
||||||
QList<VariantProperty> variantPropertyList;
|
QList<VariantProperty> variantPropertyList;
|
||||||
|
@@ -767,12 +767,16 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
|
|||||||
const ObjectValue *objectValue = getObjectValue();
|
const ObjectValue *objectValue = getObjectValue();
|
||||||
if (objectValue) {
|
if (objectValue) {
|
||||||
const CppComponentValue *qmlValue = value_cast<CppComponentValue>(objectValue);
|
const CppComponentValue *qmlValue = value_cast<CppComponentValue>(objectValue);
|
||||||
|
|
||||||
if (qmlValue) {
|
if (qmlValue) {
|
||||||
if (m_majorVersion == -1 && m_minorVersion == -1) {
|
if (m_majorVersion == -1 && m_minorVersion == -1) {
|
||||||
m_majorVersion = qmlValue->componentVersion().majorVersion();
|
m_majorVersion = qmlValue->componentVersion().majorVersion();
|
||||||
m_minorVersion = qmlValue->componentVersion().minorVersion();
|
m_minorVersion = qmlValue->componentVersion().minorVersion();
|
||||||
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8();
|
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.'
|
||||||
} else if (m_majorVersion == qmlValue->componentVersion().majorVersion() && m_minorVersion == qmlValue->componentVersion().minorVersion()) {
|
+ qmlValue->className().toUtf8();
|
||||||
|
|
||||||
|
} else if (m_majorVersion == qmlValue->componentVersion().majorVersion()
|
||||||
|
&& m_minorVersion == qmlValue->componentVersion().minorVersion()) {
|
||||||
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8();
|
m_qualfiedTypeName = qmlValue->moduleName().toUtf8() + '.' + qmlValue->className().toUtf8();
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
@@ -780,10 +784,16 @@ NodeMetaInfoPrivate::NodeMetaInfoPrivate(Model *model, TypeName type, int maj, i
|
|||||||
} else {
|
} else {
|
||||||
m_isFileComponent = true;
|
m_isFileComponent = true;
|
||||||
const Imports *imports = context()->imports(document());
|
const Imports *imports = context()->imports(document());
|
||||||
ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
|
const ImportInfo importInfo = imports->info(lookupNameComponent().constLast(), context().data());
|
||||||
if (importInfo.isValid() && importInfo.type() == ImportType::Library) {
|
if (importInfo.isValid()) {
|
||||||
m_majorVersion = importInfo.version().majorVersion();
|
if (importInfo.type() == ImportType::Library) {
|
||||||
m_minorVersion = importInfo.version().minorVersion();
|
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;
|
m_objectValue = objectValue;
|
||||||
|
@@ -260,7 +260,9 @@ void SettingsPageWidget::setSettings(const DesignerSettings &settings)
|
|||||||
#else
|
#else
|
||||||
const auto showDebugSettings = settings.value(DesignerSettingsKey::SHOW_DEBUG_SETTINGS).toBool();
|
const auto showDebugSettings = settings.value(DesignerSettingsKey::SHOW_DEBUG_SETTINGS).toBool();
|
||||||
#endif
|
#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);
|
m_ui.featureTimelineEditorCheckBox->setVisible(standaloneMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -95,7 +95,11 @@ void FileSystemAccessTest::initTestCase()
|
|||||||
QVERIFY(!newDev.isNull());
|
QVERIFY(!newDev.isNull());
|
||||||
devMgr->addDevice(newDev);
|
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.createDir());
|
||||||
|
QVERIFY(filePath.exists());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemAccessTest::cleanupTestCase()
|
void FileSystemAccessTest::cleanupTestCase()
|
||||||
@@ -106,7 +110,43 @@ void FileSystemAccessTest::cleanupTestCase()
|
|||||||
QVERIFY(baseFilePath().removeRecursively());
|
QVERIFY(baseFilePath().removeRecursively());
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileSystemAccessTest::testDirStatuses()
|
void FileSystemAccessTest::testCreateRemoteFile_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QByteArray>("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();
|
FilePath filePath = baseFilePath();
|
||||||
QVERIFY(filePath.exists());
|
QVERIFY(filePath.exists());
|
||||||
@@ -142,7 +182,7 @@ void FileSystemAccessTest::testBytesAvailable()
|
|||||||
|
|
||||||
void FileSystemAccessTest::testFileActions()
|
void FileSystemAccessTest::testFileActions()
|
||||||
{
|
{
|
||||||
FilePath testFilePath = createFile("test");
|
const FilePath testFilePath = createFile("test");
|
||||||
QVERIFY(testFilePath.exists());
|
QVERIFY(testFilePath.exists());
|
||||||
QVERIFY(testFilePath.isFile());
|
QVERIFY(testFilePath.isFile());
|
||||||
|
|
||||||
@@ -153,15 +193,17 @@ void FileSystemAccessTest::testFileActions()
|
|||||||
QVERIFY(testFilePath.isReadableFile());
|
QVERIFY(testFilePath.isReadableFile());
|
||||||
QVERIFY(testFilePath.isExecutableFile());
|
QVERIFY(testFilePath.isExecutableFile());
|
||||||
|
|
||||||
QByteArray content("Test");
|
const QByteArray content("Test");
|
||||||
testFilePath.writeFileContents(content);
|
testFilePath.writeFileContents(content);
|
||||||
// ToDo: remove ".contains", make fileContents exact equal content
|
QCOMPARE(testFilePath.fileContents(), content);
|
||||||
QVERIFY(testFilePath.fileContents().contains(content));
|
|
||||||
|
|
||||||
QVERIFY(testFilePath.renameFile(baseFilePath() / "test1"));
|
const FilePath newTestFilePath = baseFilePath() / "test1";
|
||||||
// It is Ok that FilePath doesn't change itself after rename.
|
// 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());
|
QVERIFY(newTestFilePath.exists());
|
||||||
|
QCOMPARE(newTestFilePath.fileContents(), content);
|
||||||
QVERIFY(!testFilePath.removeFile());
|
QVERIFY(!testFilePath.removeFile());
|
||||||
QVERIFY(newTestFilePath.exists());
|
QVERIFY(newTestFilePath.exists());
|
||||||
QVERIFY(newTestFilePath.removeFile());
|
QVERIFY(newTestFilePath.removeFile());
|
||||||
|
@@ -45,12 +45,15 @@ class FileSystemAccessTest : public QObject
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
void cleanupTestCase();
|
|
||||||
|
|
||||||
void testDirStatuses();
|
void testCreateRemoteFile_data();
|
||||||
|
void testCreateRemoteFile();
|
||||||
|
void testDirStatus();
|
||||||
void testBytesAvailable();
|
void testBytesAvailable();
|
||||||
void testFileActions();
|
void testFileActions();
|
||||||
|
|
||||||
|
void cleanupTestCase();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TestLinuxDeviceFactory m_testLinuxDeviceFactory;
|
TestLinuxDeviceFactory m_testLinuxDeviceFactory;
|
||||||
bool m_skippedAtWhole = false;
|
bool m_skippedAtWhole = false;
|
||||||
|
@@ -232,11 +232,14 @@ public:
|
|||||||
bool runInShell(const CommandLine &cmd, const QByteArray &data = {})
|
bool runInShell(const CommandLine &cmd, const QByteArray &data = {})
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_shell, return false);
|
QTC_ASSERT(m_shell, return false);
|
||||||
const QByteArray prefix = !data.isEmpty() ? QByteArray("echo " + data + " | ")
|
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
||||||
: QByteArray("");
|
|
||||||
|
|
||||||
m_shell->readAllStandardOutput(); // clean possible left-overs
|
const QByteArray prefix = !data.isEmpty()
|
||||||
m_shell->write(prefix + cmd.toUserOutput().toUtf8() + "\necho $?\n");
|
? 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());
|
DEBUG("RUN1 " << cmd.toUserOutput());
|
||||||
m_shell->waitForReadyRead();
|
m_shell->waitForReadyRead();
|
||||||
const QByteArray output = m_shell->readAllStandardOutput();
|
const QByteArray output = m_shell->readAllStandardOutput();
|
||||||
@@ -244,18 +247,19 @@ public:
|
|||||||
bool ok = false;
|
bool ok = false;
|
||||||
const int result = output.toInt(&ok);
|
const int result = output.toInt(&ok);
|
||||||
LOG("Run command in shell:" << cmd.toUserOutput() << "result: " << output << " ==>" << result);
|
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)
|
QByteArray outputForRunInShell(const QString &cmd)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(m_shell, return {});
|
QTC_ASSERT(m_shell, return {});
|
||||||
|
QTC_CHECK(m_shell->readAllStandardOutput().isNull()); // clean possible left-overs
|
||||||
|
|
||||||
static int val = 0;
|
static int val = 0;
|
||||||
const QByteArray delim = QString::number(++val, 16).toUtf8();
|
const QByteArray delim = QString::number(++val, 16).toUtf8();
|
||||||
|
|
||||||
DEBUG("RUN2 " << cmd);
|
DEBUG("RUN2 " << cmd);
|
||||||
m_shell->readAllStandardOutput(); // clean possible left-overs
|
|
||||||
const QByteArray marker = "___QTC___" + delim + "_OUTPUT_MARKER___";
|
const QByteArray marker = "___QTC___" + delim + "_OUTPUT_MARKER___";
|
||||||
DEBUG(" CMD: " << cmd.toUtf8() + "\necho " + marker + "\n");
|
DEBUG(" CMD: " << cmd.toUtf8() + "\necho " + marker + "\n");
|
||||||
m_shell->write(cmd.toUtf8() + "\necho " + marker + "\n");
|
m_shell->write(cmd.toUtf8() + "\necho " + marker + "\n");
|
||||||
@@ -342,11 +346,9 @@ LinuxDevice::LinuxDevice()
|
|||||||
proc->start();
|
proc->start();
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Utils::HostOsInfo::isAnyUnixHost()) {
|
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
|
||||||
addDeviceAction({tr("Open Remote Shell"), [](const IDevice::Ptr &device, QWidget *) {
|
device->openTerminal(Environment(), FilePath());
|
||||||
device->openTerminal(Environment(), FilePath());
|
}});
|
||||||
}});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LinuxDevice::~LinuxDevice()
|
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
|
bool LinuxDevice::writeFileContents(const FilePath &filePath, const QByteArray &data) const
|
||||||
{
|
{
|
||||||
QTC_ASSERT(handlesFile(filePath), return {});
|
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);
|
return d->runInShell({"dd", {"of=" + filePath.path()}}, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -158,7 +158,7 @@ void WebAssemblyToolChain::registerToolChains()
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create new toolchains and register them
|
// Create new toolchains and register them
|
||||||
ToolchainDetector detector({}, {});
|
ToolchainDetector detector({}, {}, {});
|
||||||
const Toolchains toolchains = doAutoDetect(detector);
|
const Toolchains toolchains = doAutoDetect(detector);
|
||||||
for (auto toolChain : toolchains)
|
for (auto toolChain : toolchains)
|
||||||
ToolChainManager::registerToolChain(toolChain);
|
ToolChainManager::registerToolChain(toolChain);
|
||||||
|
@@ -21,7 +21,7 @@
|
|||||||
:Add Bookmark.treeView_QTreeView {name='treeView' type='QTreeView' visible='1' window=':Add Bookmark_BookmarkDialog'}
|
: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 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.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.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.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'}
|
:Analyzer Toolbar.Elapsed:_QLabel {container=':DebugModeWidget.Toolbar_QDockWidget' text~='Elapsed: \\\\d+.\\\\d s' type='QLabel' unnamed='1' visible='1'}
|
||||||
|
@@ -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))
|
clickButton(waitForObject("{text='Cancel' type='QPushButton' unnamed='1' visible='1' window=':Dialog_Debugger::Internal::SymbolPathsDialog'}", 10000))
|
||||||
except LookupError:
|
except LookupError:
|
||||||
pass # No warning. Fine.
|
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'}"
|
msgBox = "{type='QMessageBox' unnamed='1' visible='1' windowTitle='Warning'}"
|
||||||
message = waitForObject("{name='qt_msgbox_label' type='QLabel' visible='1' window=%s}" % msgBox)
|
message = waitForObject("{name='qt_msgbox_label' type='QLabel' visible='1' window=%s}" % msgBox)
|
||||||
messageText = str(message.text)
|
messageText = str(message.text)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016 The Qt Company Ltd.
|
# Copyright (C) 2022 The Qt Company Ltd.
|
||||||
# Contact: https://www.qt.io/licensing/
|
# Contact: https://www.qt.io/licensing/
|
||||||
#
|
#
|
||||||
# This file is part of Qt Creator.
|
# This file is part of Qt Creator.
|
||||||
@@ -53,7 +53,7 @@ def main():
|
|||||||
checkCodeModelSettings(useClang)
|
checkCodeModelSettings(useClang)
|
||||||
changeAutocompleteToManual(False)
|
changeAutocompleteToManual(False)
|
||||||
# Step 2: Open .cpp file in Edit mode.
|
# 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")
|
test.fatal("Could not open main.cpp")
|
||||||
invokeMenuItem("File", "Exit")
|
invokeMenuItem("File", "Exit")
|
||||||
return
|
return
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016 The Qt Company Ltd.
|
# Copyright (C) 2022 The Qt Company Ltd.
|
||||||
# Contact: https://www.qt.io/licensing/
|
# Contact: https://www.qt.io/licensing/
|
||||||
#
|
#
|
||||||
# This file is part of Qt Creator.
|
# This file is part of Qt Creator.
|
||||||
@@ -43,7 +43,7 @@ def main():
|
|||||||
createNewQtQuickApplication(tempDir(), "SampleApp")
|
createNewQtQuickApplication(tempDir(), "SampleApp")
|
||||||
checkCodeModelSettings(useClang)
|
checkCodeModelSettings(useClang)
|
||||||
# Step 2: Open .cpp file in Edit mode.
|
# 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")
|
test.fatal("Could not open main.cpp")
|
||||||
invokeMenuItem("File", "Exit")
|
invokeMenuItem("File", "Exit")
|
||||||
return
|
return
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
############################################################################
|
############################################################################
|
||||||
#
|
#
|
||||||
# Copyright (C) 2016 The Qt Company Ltd.
|
# Copyright (C) 2022 The Qt Company Ltd.
|
||||||
# Contact: https://www.qt.io/licensing/
|
# Contact: https://www.qt.io/licensing/
|
||||||
#
|
#
|
||||||
# This file is part of Qt Creator.
|
# This file is part of Qt Creator.
|
||||||
@@ -26,9 +26,9 @@
|
|||||||
source("../../shared/qtcreator.py")
|
source("../../shared/qtcreator.py")
|
||||||
|
|
||||||
# test search in help mode and advanced search
|
# test search in help mode and advanced search
|
||||||
searchKeywordDictionary = { "abundance":True, "deplmint":False, "QODBC":True, "bldx":False }
|
searchKeywordDictionary = { "compass":True, "deplmint":False, "QODBC":True, "bldx":False }
|
||||||
urlDictionary = { "abundance":"qthelp://com.trolltech.qt.487/qdoc/gettingstarted-develop.html",
|
urlDictionary = {"compass":"qthelp://org.qt-project.qtdoc.5141/qtdoc/mobiledevelopment.html",
|
||||||
"QODBC":"qthelp://com.trolltech.qt.487/qdoc/sql-driver.html" }
|
"QODBC":"qthelp://org.qt-project.qtsql.5141/qtsql/sql-driver.html" }
|
||||||
|
|
||||||
|
|
||||||
def __getSelectedText__():
|
def __getSelectedText__():
|
||||||
@@ -69,8 +69,9 @@ def main():
|
|||||||
startQC()
|
startQC()
|
||||||
if not startedWithoutPluginError():
|
if not startedWithoutPluginError():
|
||||||
return
|
return
|
||||||
if qt4Available:
|
docFiles = ["qtdoc.qch", "qtsql.qch"]
|
||||||
addHelpDocumentation([os.path.join(qt4Path, "doc", "qch", "qt.qch")])
|
docFiles = [os.path.join(Qt5Path.docsPath(Targets.DESKTOP_5_14_1_DEFAULT), file) for file in docFiles]
|
||||||
|
addHelpDocumentation(docFiles)
|
||||||
# switch to help mode
|
# switch to help mode
|
||||||
switchViewTo(ViewConstants.HELP)
|
switchViewTo(ViewConstants.HELP)
|
||||||
# verify that search widget is accessible
|
# verify that search widget is accessible
|
||||||
@@ -87,9 +88,6 @@ def main():
|
|||||||
test.verify(waitFor("noMatch in "
|
test.verify(waitFor("noMatch in "
|
||||||
"str(resultWidget.plainText)", 2000),
|
"str(resultWidget.plainText)", 2000),
|
||||||
"Verifying if search did not match anything.")
|
"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
|
# try to search keyword from list
|
||||||
searchLineEdit = getChildByClass(waitForObject("{type='QHelpSearchQueryWidget' unnamed='1' visible='1' "
|
searchLineEdit = getChildByClass(waitForObject("{type='QHelpSearchQueryWidget' unnamed='1' visible='1' "
|
||||||
"window=':Qt Creator_Core::Internal::MainWindow'}"),
|
"window=':Qt Creator_Core::Internal::MainWindow'}"),
|
||||||
|
@@ -32,7 +32,7 @@ def startQtCreatorWithNewAppAtQMLEditor(projectDir, projectName, line = None):
|
|||||||
# create qt quick application
|
# create qt quick application
|
||||||
createNewQtQuickApplication(projectDir, projectName)
|
createNewQtQuickApplication(projectDir, projectName)
|
||||||
# open qml file
|
# open qml file
|
||||||
qmlFile = projectName + ".Resources.qml\.qrc./.main\\.qml"
|
qmlFile = "%s.%s.qml\.qrc./.main\\.qml" % (projectName, projectName)
|
||||||
if not openDocument(qmlFile):
|
if not openDocument(qmlFile):
|
||||||
test.fatal("Could not open %s" % qmlFile)
|
test.fatal("Could not open %s" % qmlFile)
|
||||||
invokeMenuItem("File", "Exit")
|
invokeMenuItem("File", "Exit")
|
||||||
|
@@ -59,7 +59,7 @@ def main():
|
|||||||
test.passes("Refactoring was properly applied in source file")
|
test.passes("Refactoring was properly applied in source file")
|
||||||
else:
|
else:
|
||||||
test.fail("Refactoring of Text to MyComponent failed in source file. Content of editor:\n%s" % codeText)
|
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"
|
# there should be new QML file generated with name "MyComponent.qml"
|
||||||
try:
|
try:
|
||||||
waitForObjectItem(":Qt Creator_Utils::NavigationTreeView", myCompTE, 5000)
|
waitForObjectItem(":Qt Creator_Utils::NavigationTreeView", myCompTE, 5000)
|
||||||
|
@@ -50,9 +50,10 @@ def main():
|
|||||||
'Waiter();'])
|
'Waiter();'])
|
||||||
# Rely on code completion for closing bracket
|
# Rely on code completion for closing bracket
|
||||||
invokeMenuItem("File", "Save All")
|
invokeMenuItem("File", "Save All")
|
||||||
openDocument(project + "." + project + "\\.pro")
|
openDocument(project + ".CMakeLists\\.txt")
|
||||||
proEditor = waitForObject(":Qt Creator_TextEditor::TextEditorWidget")
|
projectFileEditor = waitForObject(":Qt Creator_TextEditor::TextEditorWidget")
|
||||||
test.verify("CONFIG += c++11 console" in str(proEditor.plainText),
|
projectFileContent = str(projectFileEditor.plainText)
|
||||||
|
test.verify("Widgets" not in projectFileContent and "MACOSX_BUNDLE" not in projectFileContent,
|
||||||
"Verifying that program is configured with console")
|
"Verifying that program is configured with console")
|
||||||
|
|
||||||
availableConfigs = iterateBuildConfigs()
|
availableConfigs = iterateBuildConfigs()
|
||||||
@@ -88,7 +89,7 @@ def main():
|
|||||||
|
|
||||||
test.log("Debugging application")
|
test.log("Debugging application")
|
||||||
isMsvc = isMsvcConfig(kit)
|
isMsvc = isMsvcConfig(kit)
|
||||||
invokeMenuItem("Debug", "Start Debugging", "Start debugging of startup project")
|
invokeMenuItem("Debug", "Start Debugging", "Start Debugging of Startup Project")
|
||||||
handleDebuggerWarnings(config, isMsvc)
|
handleDebuggerWarnings(config, isMsvc)
|
||||||
ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton")
|
ensureChecked(":Qt Creator_AppOutput_Core::Internal::OutputPaneToggleButton")
|
||||||
outputWindow = waitForObject(":Qt Creator_Core::OutputWindow")
|
outputWindow = waitForObject(":Qt Creator_Core::OutputWindow")
|
||||||
|
@@ -37,7 +37,7 @@ def main():
|
|||||||
invokeMenuItem("File", "Exit")
|
invokeMenuItem("File", "Exit")
|
||||||
|
|
||||||
def prepareQmlFile():
|
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")
|
test.fatal("Could not open main.qml")
|
||||||
return None
|
return None
|
||||||
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
editor = waitForObject(":Qt Creator_QmlJSEditor::QmlJSTextEditorWidget")
|
||||||
|