Merge remote-tracking branch 'origin/qds-1.50' into qds-1.59

Change-Id: I45983a470a275f7eb173ed4ce34a2350e23cc625
This commit is contained in:
Tim Jenssen
2020-04-24 13:47:50 +02:00
68 changed files with 5733 additions and 4891 deletions

View File

@@ -229,7 +229,11 @@ function(set_public_includes target includes)
if (NOT IS_ABSOLUTE ${inc_dir})
set(inc_dir "${CMAKE_CURRENT_SOURCE_DIR}/${inc_dir}")
endif()
target_include_directories(${target} PUBLIC $<BUILD_INTERFACE:${inc_dir}>)
file(RELATIVE_PATH include_dir_relative_path ${PROJECT_SOURCE_DIR} ${inc_dir})
target_include_directories(${target} PUBLIC
$<BUILD_INTERFACE:${inc_dir}>
$<INSTALL_INTERFACE:include/${include_dir_relative_path}>
)
endforeach()
endfunction()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -64,7 +64,7 @@
The \uicontrol {Qt Quick Application} wizards for a particular platform add
the import statements automatically. You can remove import statements in
\uicontrol {QML Imports}
\uicontrol {QML Imports}.
\uicontrol {Assets} displays the images and other files that you copy
to the project folder (to the same subfolder as the QML files).
@@ -85,6 +85,8 @@
\li Add states to apply sets of changes to the properties of one or
several components in the \uicontrol States view (6). For more
information, see \l{Adding States}.
\li Animate component properties in the \uicontrol Timeline view (7).
For more information, see \l{Creating Animations}.
\endlist
\section1 Using Basic QML Types

View File

@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Creator documentation.
@@ -52,17 +52,9 @@
{here}.
\if defined(qtcreator)
\section1 Enabling the Timeline Editor
The \uicontrol Timeline view is not visible in \QC by default. To enable
it, select \uicontrol Tools > \uicontrol Options > \uicontrol {Qt Quick} >
\uicontrol {Qt Quick Designer} > \uicontrol {Enable Timeline editor}.
Select \uicontrol {Restart Now} to restart \QC with the \uicontrol Timeline
view visible.
To be able to create timelines, you also need the \l {Qt Quick Timeline}
module, which is delivered with Qt 5.14, and later. For more
information about adding the module to an older Qt version, see
add-on module, which you can install with Qt 5.14, and later. For more
information about adding the module to an older Qt version, see
\l{Adding Qt Quick Timeline Module to Qt Installations}.
\endif
@@ -77,9 +69,7 @@
\list 1
\li In the \uicontrol Navigator, select the item to animate.
\li Select the \uicontrol Timeline tab to open the \uicontrol Timeline
view.
\li Select the \inlineimage plus.png
\li In the \uicontrol Timeline view, select the \inlineimage plus.png
(\uicontrol {Add Timeline (A)}) button, or press \key {A} to
specify settings for the timeline and running the animation
in the \uicontrol {Timeline Settings} dialog.
@@ -144,7 +134,7 @@
\section1 Managing Keyframes
To animate components in the \uicontrol Timeline view, move to a frame
on the timeline and specify changes in the values of a property. \QDS
on the timeline and specify changes in the values of a property. \QC
automatically adds keyframes between two keyframes, and sets their values
evenly to create an appearance of movement or transformation.
@@ -160,7 +150,8 @@
\li Select the \uicontrol {To Start (Home)}, \uicontrol {Previous (,)},
or \uicontrol {Next (.)} buttons (3), or use the keyboard shortcuts
to move to the first, previous, or next frame on the timeline.
\li Enter the number of a frame in the field (4) to move to that frame.
\li Enter the number of a frame in the current keyframe field (4) to
move to that frame.
\li Select the \uicontrol Previous and \uicontrol Next buttons next to
a property name on the timeline (5) to move to the previous or next
keyframe for that property.
@@ -231,13 +222,11 @@
You can view the animation on the canvas by moving the playhead along the
timeline.
\if defined(qtdesignstudio)
To preview the animation, select the \uicontrol {Play (Space)}
button or press \key Space. To preview the whole UI, select the
\inlineimage live_preview.png
(\uicontrol {Show Live Preview}) button on the canvas toolbar
or press \key {Alt+P}.
\endif
\section1 Editing Easing Curves
@@ -247,7 +236,7 @@
timeline are \e linear, which means that they move from the beginning to
the end at a constant speed. You can use the \uicontrol {Easing Curve Editor}
to edit the easing curve between two keyframes. You can also use the more
advanced \uicontrol {Curve Editor (C)} to edit the curves for the whole
advanced \uicontrol {Animation Curve Editor} to edit the curves for the whole
animation.
\section2 Attaching Easing Curves to Keyframes
@@ -306,23 +295,24 @@
\section1 Editing Animation Curves
In the curve editor, you can view and modify the whole animation curve. You
In the animation curve editor, you can view and modify the whole animation
curve. You
can insert keyframes to the curve and drag them and the point handlers to
modify the curve. You can modify the appearance of the curve in the style
editor.
You can also edit easing curves that you added with the easing curve editor.
\image studio-curve-editor.png "Curve Editor"
\image studio-curve-editor.png "Animation Curve Editor"
To edit animation curves:
\list 1
\li In the \uicontrol Timeline view, insert at least one keyframe.
\li Select \inlineimage curveGraphIcon.png
(\uicontrol {Curve Editor (C)} on the toolbar or press \key C
to open the curve editor.
\li Right-click in the curve editor, and select
(\uicontrol {Animation Curve Editor}) on the toolbar or press \key C
to open the animation curve editor.
\li Right-click in the animation curve editor, and select
\uicontrol {Insert Keyframe} to add a keyframe.
\li Select keyframes to display the easing curves attached to them.
To select multiple keyframes, press and hold \key Ctrl.

View File

@@ -8,8 +8,6 @@ headerdirs =
sourcedirs = ../src \
../examples/doc \
../../qtcreator/src
# The image folders also need to added by packaging scripts, so inform your
# local release team about any changes you make.
imagedirs = ../images \
../examples/doc/images \
../../qtcreator/images \
@@ -23,6 +21,7 @@ imagedirs = ../images \
../../../src/plugins/help/images \
../../../src/plugins/projectexplorer/images \
../../../src/plugins/qmldesigner/components/componentcore/images \
../../../src/plugins/qmldesigner/components/edit3d/images \
../../../src/plugins/qmldesigner/components/formeditor \
../../../src/plugins/qmldesigner/components/navigator \
../../../src/plugins/qmldesigner/components/timelineeditor/images \

View File

@@ -67,23 +67,7 @@ source_include_patterns = [
r"^doc/.*$", # include everything under doc/
r"^.*\.pri$", # .pri files in all directories that are looked into
r"^.*\.h$", # .h files in all directories that are looked into
r"^.*\.hpp$", # .hpp files in all directories that are looked into
# qtdesignstudio docs are build against dev package, so we need to include some image directories
r"^share/qtcreator/qml/qmlpuppet/mockfiles/images/.*$",
r"^share/qtcreator/qmldesigner/propertyEditorQmlSources/imports/HelperWidgets/images/.*$",
r"^src/libs/qmleditorwidgets/images/.*$",
r"^src/libs/utils/images/.*$",
r"^src/plugins/debugger/images/.*$",
r"^src/plugins/diffeditor/images/.*$",
r"^src/plugins/help/images/.*$",
r"^src/plugins/projectexplorer/images/.*$",
r"^src/plugins/qmldesigner/components/componentcore/images/.*$",
r"^src/plugins/qmldesigner/components/timelineeditor/images/.*$",
r"^src/plugins/qmldesigner/qmlpreviewplugin/images/.*$",
r"^src/plugins/texteditor/images/.*$",
# also some single files
r"^src/plugins/qmldesigner/components/formeditor/.*\.png$",
r"^src/plugins/qmldesigner/components/navigator/.*\.png$"
r"^.*\.hpp$" # .hpp files in all directories that are looked into
]
build_include_patterns = [

View File

@@ -800,7 +800,10 @@ def qdump__std____1__shared_ptr(d, value):
def qdump__std__unique_ptr(d, value):
p = d.extractPointer(value)
if value.type.size() == d.ptrSize():
p = d.extractPointer(value)
else:
_, p = value.split("pp"); # For custom deleters.
if p == 0:
d.putValue("(null)")
d.putNumChild(0)

View File

@@ -121,7 +121,7 @@ View3D {
pick(mouse);
if (pickObj) {
axisHelperView.editCameraCtrl.focusObject(axisHelperView.selectedNode,
pickObj.cameraRotation, false);
pickObj.cameraRotation, false, false);
} else {
mouse.accepted = false;
}

View File

@@ -87,14 +87,15 @@ Item {
}
function focusObject(targetObject, rotation, updateZoom)
function focusObject(targetObject, rotation, updateZoom, closeUp)
{
if (!camera)
return;
camera.eulerRotation = rotation;
var newLookAtAndZoom = _generalHelper.focusObjectToCamera(
camera, _defaultCameraLookAtDistance, targetObject, view3d, _zoomFactor, updateZoom);
camera, _defaultCameraLookAtDistance, targetObject, view3d, _zoomFactor,
updateZoom, closeUp);
_lookAtPoint = newLookAtAndZoom.toVector3d();
_zoomFactor = newLookAtAndZoom.w;
storeCameraState(0);

View File

@@ -146,7 +146,7 @@ Item {
if (editView) {
var targetNode = selectionBoxes.length > 0
? selectionBoxes[0].model : null;
cameraControl.focusObject(targetNode, editView.camera.eulerRotation, true);
cameraControl.focusObject(targetNode, editView.camera.eulerRotation, true, false);
}
}

View File

@@ -42,7 +42,7 @@ Item {
function fitAndHideBox() : bool
{
cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true);
cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true, true);
if (cameraControl._zoomFactor < 0.1) {
view3D.importScene.scale = view3D.importScene.scale.times(10);
return false;

View File

@@ -148,7 +148,7 @@ float GeneralHelper::zoomCamera(QQuick3DCamera *camera, float distance, float de
// Return value contains new lookAt point (xyz) and zoom factor (w)
QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
float oldZoom, bool updateZoom)
float oldZoom, bool updateZoom, bool closeUp)
{
if (!camera)
return QVector4D(0.f, 0.f, 0.f, 1.f);
@@ -200,7 +200,9 @@ QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defau
camera->setPosition(lookAt + newLookVector);
float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / 900.), 100.f) : oldZoom;
qreal divisor = closeUp ? 900. : 725.;
float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / divisor), 100.f) : oldZoom;
float cameraZoomFactor = zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false);
return QVector4D(lookAt, cameraZoomFactor);

View File

@@ -66,8 +66,9 @@ public:
float defaultLookAtDistance, const QVector3D &lookAt,
float zoomFactor, bool relative);
Q_INVOKABLE QVector4D focusObjectToCamera(QQuick3DCamera *camera, float defaultLookAtDistance,
QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
float oldZoom, bool updateZoom = true);
QQuick3DNode *targetObject, QQuick3DViewport *viewPort,
float oldZoom, bool updateZoom = true,
bool closeUp = false);
Q_INVOKABLE void delayedPropertySet(QObject *obj, int delay, const QString &property,
const QVariant& value);
Q_INVOKABLE QQuick3DNode *resolvePick(QQuick3DNode *pickNode);

View File

@@ -47,6 +47,8 @@ Item {
width: itemLibraryIconWidth // to be set in Qml context
height: itemLibraryIconHeight // to be set in Qml context
source: itemLibraryIconPath // to be set by model
cache: false // Allow thumbnail to be dynamically updated
}
Text {

View File

@@ -51,6 +51,8 @@ Rectangle {
property real __actionIndicatorWidth: StudioTheme.Values.squareComponentWidth
property real __actionIndicatorHeight: StudioTheme.Values.height
property string typeFilter: "QtQuick3D.Material"
color: "transparent"
border.color: StudioTheme.Values.themeControlOutline
border.width: StudioTheme.Values.border
@@ -69,7 +71,7 @@ Rectangle {
validator: RegExpValidator { regExp: /(^[a-z_]\w*|^[A-Z]\w*\.{1}([a-z_]\w*\.?)+)/ }
actionIndicatorVisible: false
typeFilter: "QtQuick3D.Material"
typeFilter: editableListView.typeFilter
editText: modelData
initialModelData: modelData

View File

@@ -68,9 +68,12 @@ Section {
text: qsTr("Font")
}
FontComboBox {
id: fontComboBox
backendValue: fontSection.fontFamily
Layout.fillWidth: true
width: 160
property string familyName: backendValue.value
onFamilyNameChanged: print(styleNamesForFamily(familyName))
}
Label {
@@ -151,6 +154,7 @@ Section {
italic: fontSection.italicStyle
underline: fontSection.underlineStyle
strikeout: fontSection.strikeoutStyle
enabled: !styleComboBox.styleSet
}
Label {
@@ -175,6 +179,21 @@ Section {
backendValue: getBackendValue("weight")
model: ["Normal", "Light", "ExtraLight", "Thin", "Medium", "DemiBold", "Bold", "ExtraBold", "Black"]
scope: "Font"
enabled: !styleComboBox.styleSet
}
Label {
text: qsTr("Style name")
toolTip: qsTr("Sets the font's style.")
}
ComboBox {
id: styleComboBox
property bool styleSet: backendValue.isInModel
Layout.fillWidth: true
backendValue: getBackendValue("styleName")
model: styleNamesForFamily(fontComboBox.familyName)
useString: true
}
Label {

View File

@@ -73,8 +73,12 @@ bool ComponentVersion::isValid() const
QString ComponentVersion::toString() const
{
return QString::fromLatin1("%1.%2").arg(QString::number(_major),
QString::number(_minor));
QByteArray temp;
QByteArray result;
result += temp.setNum(_major);
result += '.';
result += temp.setNum(_minor);
return QString::fromLatin1(result);
}
void ComponentVersion::addToHash(QCryptographicHash &hash) const

View File

@@ -7,6 +7,7 @@ add_qtc_library(QmlJS
parser/qmljsast.cpp parser/qmljsast_p.h
parser/qmljsastfwd_p.h
parser/qmljsastvisitor.cpp parser/qmljsastvisitor_p.h
parser/qmljsdiagnosticmessage_p.h
parser/qmljsengine_p.cpp parser/qmljsengine_p.h
parser/qmljsglobal_p.h
parser/qmljsgrammar.cpp parser/qmljsgrammar_p.h

View File

@@ -872,6 +872,7 @@ int Lexer::scanString(ScanStringMode mode)
{
QChar quote = (mode == TemplateContinuation) ? QChar(TemplateHead) : QChar(mode);
bool multilineStringLiteral = false;
bool escaped = false;
const QChar *startCode = _codePtr - 1;
// in case we just parsed a \r, we need to reset this flag to get things working
@@ -880,6 +881,12 @@ int Lexer::scanString(ScanStringMode mode)
if (_engine) {
while (_codePtr <= _endPtr) {
if (escaped) { // former char started an escape sequence
escaped = false;
_char = *_codePtr++;
++_currentColumnNumber;
continue;
}
if (isLineTerminator()) {
if ((quote == QLatin1Char('`') || qmlMode()))
break;
@@ -887,7 +894,10 @@ int Lexer::scanString(ScanStringMode mode)
_errorMessage = QCoreApplication::translate("QmlParser", "Stray newline in string literal");
return T_ERROR;
} else if (_char == QLatin1Char('\\')) {
break;
if (mode != DoubleQuote && mode != SingleQuote)
break;
else // otherwise we need to handle an escape sequence
escaped = true;
} else if (_char == '$' && quote == QLatin1Char('`')) {
break;
} else if (_char == quote) {

View File

@@ -395,6 +395,8 @@ const Value *CppComponentValue::valueForCppName(const QString &typeName) const
return valueOwner()->realValue();
} else if (typeName == QLatin1String("QFont")) {
return valueOwner()->qmlFontObject();
} else if (typeName == QLatin1String("QPalette")) {
return valueOwner()->qmlPaletteObject();
} else if (typeName == QLatin1String("QPoint")
|| typeName == QLatin1String("QPointF")
|| typeName == QLatin1String("QVector2D")) {

View File

@@ -95,6 +95,7 @@ public:
ObjectValue *_mathObject;
ObjectValue *_qtObject;
ObjectValue *_qmlFontObject;
ObjectValue *_qmlPaletteObject;
ObjectValue *_qmlPointObject;
ObjectValue *_qmlSizeObject;
ObjectValue *_qmlRectObject;
@@ -496,6 +497,28 @@ SharedValueOwner::SharedValueOwner(SharedValueOwnerKind kind)
_qmlFontObject->setMember(QLatin1String("kerning"), booleanValue());
_qmlFontObject->setMember(QLatin1String("preferShaping"), booleanValue());
_qmlPaletteObject = newObject(/* prototype = */ nullptr);
_qmlPaletteObject->setClassName(QLatin1String("palette"));
_qmlPaletteObject->setMember(QLatin1String("alternateBase"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("base"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("brightText"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("button"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("buttonText"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("dark"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("highlight"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("highlightedText"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("light"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("link"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("linkVisited"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("mid"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("midlight"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("shadow"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("text"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("toolTipBase"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("toolTipText"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("window"), colorValue());
_qmlPaletteObject->setMember(QLatin1String("windowText"), colorValue());
_qmlPointObject = newObject(/*prototype =*/ nullptr);
_qmlPointObject->setClassName(QLatin1String("Point"));
_qmlPointObject->setMember(QLatin1String("x"), numberValue());
@@ -896,6 +919,11 @@ const ObjectValue *ValueOwner::qmlFontObject()
return _shared->_qmlFontObject;
}
const ObjectValue *ValueOwner::qmlPaletteObject()
{
return _shared->_qmlPaletteObject;
}
const ObjectValue *ValueOwner::qmlPointObject()
{
return _shared->_qmlPointObject;

View File

@@ -82,6 +82,7 @@ public:
// QML objects
const ObjectValue *qmlFontObject();
const ObjectValue *qmlPaletteObject();
const ObjectValue *qmlPointObject();
const ObjectValue *qmlSizeObject();
const ObjectValue *qmlRectObject();

View File

@@ -160,7 +160,7 @@ static const CommandDescription commandDescriptions[] = {
{"assign","Assigns a value to a variable in current symbol group.",
"[-t token] [-h] <iname=value>\n"
"-h Data are hex-encoded, binary data\n"
"-u Data are hex-encoded, UTF16 data"
"-e iname is an hex-encoded expression to be evaluated "
},
{"threads","Lists threads in GDBMI format.","[-t token]"},
{"registers","Lists registers in GDBMI format","[-t token]"},
@@ -819,57 +819,77 @@ extern "C" HRESULT CALLBACK assign(CIDebugClient *client, PCSTR argsIn)
ExtensionCommandContext exc(client);
std::string errorMessage;
bool success = false;
bool encoded = false;
bool evaluateExpression = false;
int token = 0;
do {
StringList tokens = commandTokens<StringList>(argsIn, &token);
if (tokens.empty()) {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
break;
}
StringList tokens = commandTokens<StringList>(argsIn, &token);
while (!tokens.empty()) {
if (tokens.front() == "-h") {
encoded = true;
tokens.pop_front();
continue;
}
if (tokens.empty()) {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
break;
if (tokens.front() == "-e") {
evaluateExpression = true;
tokens.pop_front();
continue;
}
break;
};
// Parse 'assign locals.x=5'
const std::string::size_type equalsPos = tokens.front().find('=');
if (equalsPos == std::string::npos) {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
break;
}
const std::string iname = tokens.front().substr(0, equalsPos);
const std::string value = tokens.front().substr(equalsPos + 1, tokens.front().size() - equalsPos - 1);
// get the symbolgroup
int currentFrame = ExtensionContext::instance().symbolGroupFrame();
if (currentFrame < 0) {
CIDebugControl *control = ExtensionCommandContext::instance()->control();
DEBUG_STACK_FRAME frame;
if (FAILED(control->GetStackTrace(0, 0, 0, &frame, 1, NULL))) {
errorMessage = "No current frame.";
break;
// Parse 'assign locals.x=5'
const std::string::size_type equalsPos = tokens.empty() ? std::string::npos
: tokens.front().find('=');
if (equalsPos == std::string::npos) {
errorMessage = singleLineUsage(commandDescriptions[CmdAssign]);
} else {
std::string iname = tokens.front().substr(0, equalsPos);
const std::string value = tokens.front().substr(equalsPos + 1,
tokens.front().size() - equalsPos - 1);
SymbolGroup *symGroup = nullptr;
if (evaluateExpression) {
WatchesSymbolGroup *watchesSymGroup
= ExtensionContext::instance().watchesSymbolGroup(exc.symbols(), &errorMessage);
std::string tempAssignIname = "watch.tmpassign";
if (watchesSymGroup) {
if (watchesSymGroup->addWatch(exc.symbols(),
tempAssignIname,
stringFromHex(iname),
&errorMessage)) {
iname = tempAssignIname;
symGroup = watchesSymGroup;
}
}
} else {
// get the symbolgroup
int currentFrame = ExtensionContext::instance().symbolGroupFrame();
if (currentFrame < 0) {
CIDebugControl *control = ExtensionCommandContext::instance()->control();
DEBUG_STACK_FRAME frame;
if (FAILED(control->GetStackTrace(0, 0, 0, &frame, 1, NULL)))
errorMessage = "No current frame.";
else
currentFrame = frame.FrameNumber;
}
if (currentFrame >= 0) {
symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(),
exc.threadId(),
currentFrame,
&errorMessage);
}
currentFrame = frame.FrameNumber;
}
SymbolGroup *symGroup = ExtensionContext::instance().symbolGroup(exc.symbols(), exc.threadId(), currentFrame, &errorMessage);
if (!symGroup)
break;
success = symGroup->assign(iname, encoded ? stringFromHex(value) : value,
SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()),
&errorMessage);
} while (false);
if (symGroup
&& symGroup->assign(iname,
encoded ? stringFromHex(value) : value,
SymbolGroupValueContext(exc.dataSpaces(), exc.symbols()),
&errorMessage)) {
ExtensionContext::instance().report('R', token, 0, "assign", "Ok");
return S_OK;
}
}
if (success)
ExtensionContext::instance().report('R', token, 0, "assign", "Ok");
else
ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str());
ExtensionContext::instance().report('N', token, 0, "assign", errorMessage.c_str());
return S_OK;
}

View File

@@ -698,6 +698,7 @@ void ClangTool::startTool(ClangTool::FileSelection fileSelection,
connect(m_runWorker, &ClangToolRunWorker::started, this, &ClangTool::onStarted);
connect(m_runWorker, &ClangToolRunWorker::runnerFinished,
this, &ClangTool::updateForCurrentState);
connect(m_runControl, &RunControl::destroyed, [this](){ m_runWorker = nullptr; });
// More init and UI update
m_diagnosticFilterModel->setProject(project);
@@ -1038,6 +1039,8 @@ void ClangTool::onRunControlStopped()
void ClangTool::update()
{
updateForInitialState();
if (!m_runWorker)
return;
updateForCurrentState();
}

View File

@@ -33,10 +33,12 @@
#include <app/app_version.h>
#include <coreplugin/icore.h>
#include <coreplugin/variablechooser.h>
#include <projectexplorer/task.h>
#include <projectexplorer/toolchain.h>
#include <projectexplorer/kit.h>
#include <projectexplorer/kitinformation.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/projectexplorersettings.h>
#include <projectexplorer/task.h>
#include <projectexplorer/toolchain.h>
#include <qtsupport/baseqtversion.h>
#include <qtsupport/qtkitinformation.h>
#include <projectexplorer/projectexplorerconstants.h>
@@ -643,6 +645,21 @@ QVariant CMakeGeneratorKitAspect::defaultValue(const Kit *k) const
return g.matches("NMake Makefiles", extraGenerator)
|| g.matches("NMake Makefiles JOM", extraGenerator);
});
if (ProjectExplorerPlugin::projectExplorerSettings().useJom) {
it = std::find_if(known.constBegin(),
known.constEnd(),
[extraGenerator](const CMakeTool::Generator &g) {
return g.matches("NMake Makefiles JOM", extraGenerator);
});
}
if (it == known.constEnd()) {
it = std::find_if(known.constBegin(),
known.constEnd(),
[extraGenerator](const CMakeTool::Generator &g) {
return g.matches("NMake Makefiles", extraGenerator);
});
}
}
} else {
// Unix-oid OSes:
@@ -770,6 +787,16 @@ KitAspectWidget *CMakeGeneratorKitAspect::createConfigWidget(Kit *k) const
return new CMakeGeneratorKitAspectWidget(k, this);
}
void CMakeGeneratorKitAspect::addToEnvironment(const Kit *k, Utils::Environment &env) const
{
GeneratorInfo info = generatorInfo(k);
if (info.generator == "NMake Makefiles JOM") {
if (env.searchInPath("jom.exe").exists())
return;
env.appendOrSetPath(QCoreApplication::applicationDirPath());
}
}
// --------------------------------------------------------------------
// CMakeConfigurationKitAspect:
// --------------------------------------------------------------------

View File

@@ -83,6 +83,7 @@ public:
void upgrade(ProjectExplorer::Kit *k) final;
ItemList toUserOutput(const ProjectExplorer::Kit *k) const final;
ProjectExplorer::KitAspectWidget *createConfigWidget(ProjectExplorer::Kit *k) const final;
void addToEnvironment(const ProjectExplorer::Kit *k, Utils::Environment &env) const final;
private:
QVariant defaultValue(const ProjectExplorer::Kit *k) const;

View File

@@ -170,7 +170,7 @@ static FilePath jsonObjectFilename(const QJsonObject &object)
const QString workingDir = QDir::fromNativeSeparators(object["directory"].toString());
FilePath fileName = FilePath::fromString(QDir::fromNativeSeparators(object["file"].toString()));
if (fileName.toFileInfo().isRelative())
fileName = FilePath::fromString(workingDir + "/" + fileName.toString()).canonicalPath();
fileName = FilePath::fromString(QDir::cleanPath(workingDir + "/" + fileName.toString()));
return fileName;
}

View File

@@ -929,8 +929,15 @@ void CdbEngine::assignValueInDebugger(WatchItem *w, const QString &expr, const Q
qWarning("Internal error: assignValueInDebugger: Invalid state or no stack frame.");
return;
}
runCommand({m_extensionCommandPrefix + "assign -h " + w->iname + '=' + toHex(value.toString()),
NoFlags});
if (m_pythonVersion > 0x030000 && w->isWatcher()) {
runCommand({m_extensionCommandPrefix + "assign -h -e " + toHex(w->expression()) + '='
+ toHex(value.toString()),
NoFlags});
} else {
runCommand({m_extensionCommandPrefix + "assign -h " + w->iname + '=' + toHex(value.toString()),
NoFlags});
}
// Update all locals in case we change a union or something pointed to
// that affects other variables, too.
updateLocals();

View File

@@ -500,8 +500,13 @@ void QmakeBuildSystem::startAsyncTimer(QmakeProFile::AsyncUpdateDelay delay)
void QmakeBuildSystem::incrementPendingEvaluateFutures()
{
if (m_pendingEvaluateFuturesCount == 0)
m_guard = guardParsingRun();
if (m_pendingEvaluateFuturesCount == 0) {
// The guard actually might already guard the project if this
// here is the re-start of a previously aborted parse due to e.g.
// changing build directories while parsing.
if (!m_guard.guardsProject())
m_guard = guardParsingRun();
}
++m_pendingEvaluateFuturesCount;
m_asyncUpdateFutureInterface.setProgressRange(m_asyncUpdateFutureInterface.progressMinimum(),
m_asyncUpdateFutureInterface.progressMaximum() + 1);

View File

@@ -144,6 +144,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX ../../../share/qtcreator/qml/qmlpuppet/interfaces
PUBLIC_INCLUDES ../../../share/qtcreator/qml/qmlpuppet/interfaces
SOURCES
nodeinstanceserverinterface.cpp
commondefines.h
@@ -202,6 +203,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/formeditor
PUBLIC_INCLUDES components/formeditor
SOURCES
abstractcustomtool.cpp abstractcustomtool.h
abstractformeditortool.cpp abstractformeditortool.h
@@ -243,6 +245,7 @@ extend_qtc_plugin(QmlDesigner
snapper.cpp snapper.h
snappinglinecreator.cpp snappinglinecreator.h
toolbox.cpp toolbox.h
transitiontool.cpp transitiontool.h
)
extend_qtc_plugin(QmlDesigner
@@ -257,6 +260,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX components/integration
PUBLIC_INCLUDES components/integration
SOURCES
componentaction.cpp componentaction.h
componentview.cpp componentview.h
@@ -470,6 +474,7 @@ extend_qtc_plugin(QmlDesigner
extend_qtc_plugin(QmlDesigner
SOURCES_PREFIX designercore
PUBLIC_INCLUDES designercore
SOURCES
metainfo/itemlibraryinfo.cpp
metainfo/metainfo.cpp

View File

@@ -41,6 +41,7 @@ const char anchorsCategory[] = "Anchors";
const char positionCategory[] = "Position";
const char layoutCategory[] = "Layout";
const char flowCategory[] = "Flow";
const char flowEffectCategory[] = "FlowEffect";
const char flowConnectionCategory[] = "FlowConnection";
const char stackedContainerCategory[] = "StackedContainer";
const char genericToolBarCategory[] = "GenericToolBar";
@@ -57,6 +58,7 @@ const char anchorsFillCommandId[] = "AnchorsFill";
const char anchorsResetCommandId[] = "AnchorsReset";
const char removePositionerCommandId[] = "RemovePositioner";
const char createFlowActionAreaCommandId[] = "CreateFlowActionArea";
const char setFlowStartCommandId[] = "SetFlowStart";
const char layoutRowPositionerCommandId[] = "LayoutRowPositioner";
const char layoutColumnPositionerCommandId[] = "LayoutColumnPositioner";
const char layoutGridPositionerCommandId[] = "LayoutGridPositioner";
@@ -85,6 +87,7 @@ const char anchorsCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextM
const char positionCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Position");
const char layoutCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Layout");
const char flowCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Flow");
const char flowEffectCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Flow Effects");
const char stackedContainerCategoryDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Stacked Container");
const char cutSelectionDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Cut");
@@ -124,6 +127,7 @@ const char layoutGridPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerCon
const char layoutFlowPositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Position in Flow");
const char removePositionerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Remove Positioner");
const char createFlowActionAreaDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Create Flow Action");
const char setFlowStartDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Set Flow Start");
const char removeLayoutDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Remove Layout");
const char addItemToStackedContainerDisplayName[] = QT_TRANSLATE_NOOP("QmlDesignerContextMenu", "Add Item");

View File

@@ -346,6 +346,12 @@ bool isFlowItem(const SelectionContext &context)
&& QmlFlowItemNode::isValidQmlFlowItemNode(context.currentSingleSelectedNode());
}
bool isFlowTarget(const SelectionContext &context)
{
return context.singleNodeIsSelected()
&& QmlFlowTargetNode::isFlowEditorTarget(context.currentSingleSelectedNode());
}
bool isFlowTransitionItem(const SelectionContext &context)
{
return context.singleNodeIsSelected()
@@ -362,9 +368,9 @@ bool isFlowActionItemItem(const SelectionContext &context)
|| QmlVisualNode::isFlowWildcard(selectedNode));
}
bool isFlowItemOrTransition(const SelectionContext &context)
bool isFlowTargetOrTransition(const SelectionContext &context)
{
return isFlowItem(context) || isFlowTransitionItem(context);
return isFlowTarget(context) || isFlowTransitionItem(context);
}
class FlowActionConnectAction : public ActionGroup
@@ -853,15 +859,24 @@ void DesignerActionManager::createDefaultDesignerActions()
priorityLayoutCategory,
&layoutOptionVisible));
//isFlowTransitionItem
addDesignerAction(new ActionGroup(
flowCategoryDisplayName,
flowCategory,
priorityFlowCategory,
&isFlowItemOrTransition,
&isFlowTargetOrTransition,
&flowOptionVisible));
auto effectMenu = new ActionGroup(
flowEffectCategoryDisplayName,
flowEffectCategory,
priorityFlowCategory,
&isFlowTransitionItem,
&flowOptionVisible);
effectMenu->setCategory(flowCategory);
addDesignerAction(effectMenu);
addDesignerAction(new ModelNodeFormEditorAction(
createFlowActionAreaCommandId,
createFlowActionAreaDisplayName,
@@ -874,6 +889,17 @@ void DesignerActionManager::createDefaultDesignerActions()
&isFlowItem,
&flowOptionVisible));
addDesignerAction(new ModelNodeContextMenuAction(
setFlowStartCommandId,
setFlowStartDisplayName,
{},
flowCategory,
priorityFirst,
{},
&setFlowStartItem,
&isFlowItem,
&flowOptionVisible));
addDesignerAction(new FlowActionConnectAction(
flowConnectionCategoryDisplayName,
flowConnectionCategory,
@@ -1175,7 +1201,7 @@ void DesignerActionManager::addTransitionEffectAction(const TypeName &typeName)
QByteArray(ComponentCoreConstants::flowAssignEffectCommandId) + typeName,
QLatin1String(ComponentCoreConstants::flowAssignEffectDisplayName) + typeName,
{},
ComponentCoreConstants::flowCategory,
ComponentCoreConstants::flowEffectCategory,
{},
typeName == "None" ? 100 : 140,
[typeName](const SelectionContext &context)

View File

@@ -132,16 +132,22 @@ public:
bool isVisible(const SelectionContext &m_selectionState) const override { return m_visibility(m_selectionState); }
bool isEnabled(const SelectionContext &m_selectionState) const override { return m_enabled(m_selectionState); }
QByteArray category() const override { return QByteArray(); }
QByteArray category() const override { return m_category; }
QByteArray menuId() const override { return m_menuId; }
int priority() const override { return m_priority; }
Type type() const override { return ContextMenu; }
void setCategory(const QByteArray &catageoryId)
{
m_category = catageoryId;
}
private:
const QByteArray m_menuId;
const int m_priority;
SelectionContextPredicate m_enabled;
SelectionContextPredicate m_visibility;
QByteArray m_category;
};
class SeperatorDesignerAction : public AbstractAction

View File

@@ -311,8 +311,10 @@ void resetSize(const SelectionContext &selectionState)
selectionState.view()->executeInTransaction("DesignerActionManager|resetSize",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
itemNode.removeProperty("width");
itemNode.removeProperty("height");
if (itemNode.isValid()) {
itemNode.removeProperty("width");
itemNode.removeProperty("height");
}
}
});
}
@@ -325,8 +327,10 @@ void resetPosition(const SelectionContext &selectionState)
selectionState.view()->executeInTransaction("DesignerActionManager|resetPosition",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
itemNode.removeProperty("x");
itemNode.removeProperty("y");
if (itemNode.isValid()) {
itemNode.removeProperty("x");
itemNode.removeProperty("y");
}
}
});
}
@@ -348,7 +352,8 @@ void resetZ(const SelectionContext &selectionState)
selectionState.view()->executeInTransaction("DesignerActionManager|resetZ",[selectionState](){
foreach (ModelNode node, selectionState.selectedModelNodes()) {
QmlItemNode itemNode(node);
itemNode.removeProperty("z");
if (itemNode.isValid())
itemNode.removeProperty("z");
}
});
}
@@ -1095,7 +1100,24 @@ void addFlowEffect(const SelectionContext &selectionContext, const TypeName &typ
container.nodeProperty("effect").reparentHere(effectNode);
view->setSelectedModelNode(effectNode);
}
});
});
}
void setFlowStartItem(const SelectionContext &selectionContext)
{
AbstractView *view = selectionContext.view();
QTC_ASSERT(view && selectionContext.hasSingleSelectedModelNode(), return);
ModelNode node = selectionContext.currentSingleSelectedNode();
QTC_ASSERT(node.isValid(), return);
QTC_ASSERT(node.metaInfo().isValid(), return);
QmlFlowItemNode flowItem(node);
QTC_ASSERT(flowItem.isValid(), return);
QTC_ASSERT(flowItem.flowView().isValid(), return);
view->executeInTransaction("DesignerActionManager:setFlowStartItem",
[&flowItem](){
flowItem.flowView().setStartFlowItem(flowItem);
});
}
} // namespace Mode

View File

@@ -77,6 +77,7 @@ bool addFontToProject(const QStringList &fileNames, const QString &directory);
void createFlowActionArea(const SelectionContext &selectionContext);
void addTransition(const SelectionContext &selectionState);
void addFlowEffect(const SelectionContext &selectionState, const TypeName &typeName);
void setFlowStartItem(const SelectionContext &selectionContext);
} // namespace ModelNodeOperationso
} //QmlDesigner

View File

@@ -179,6 +179,17 @@ void Edit3DView::importsChanged(const QList<Import> &addedImports,
checkImports();
}
void Edit3DView::customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
Q_UNUSED(view)
Q_UNUSED(nodeList)
Q_UNUSED(data)
if (identifier == "asset_import_update")
resetPuppet();
}
void Edit3DView::sendInputEvent(QInputEvent *e) const
{
if (nodeInstanceView())
@@ -301,14 +312,16 @@ QVector<Edit3DAction *> Edit3DView::rightActions() const
void Edit3DView::addQuick3DImport()
{
const QList<Import> imports = model()->possibleImports();
for (const auto &import : imports) {
if (import.url() == "QtQuick3D") {
model()->changeImports({import}, {});
if (model()) {
const QList<Import> imports = model()->possibleImports();
for (const auto &import : imports) {
if (import.url() == "QtQuick3D") {
model()->changeImports({import}, {});
// Subcomponent manager update needed to make item library entries appear
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
return;
// Subcomponent manager update needed to make item library entries appear
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
return;
}
}
}
Core::AsynchronousMessageBox::warning(tr("Failed to Add Import"),

View File

@@ -58,6 +58,7 @@ public:
void modelAttached(Model *model) override;
void modelAboutToBeDetached(Model *model) override;
void importsChanged(const QList<Import> &addedImports, const QList<Import> &removedImports) override;
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void sendInputEvent(QInputEvent *e) const;
void edit3DViewResized(const QSize &size) const;

View File

@@ -106,12 +106,11 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
// Onboarding label contains instructions for new users how to get 3D content into the project
m_onboardingLabel = new QLabel(this);
QString labelText =
"No 3D import here yet!<br><br>"
"To create a 3D View you need to add the QtQuick3D import to your file.<br>"
"You can add the import via the QML Imports tab of the Library view, or alternatively click"
" <a href=\"#add_import\"><span style=\"text-decoration:none;color:%1\">here</span></a> "
"to add it straight away.<br><br>"
"If you want to import 3D assets from another tool, click on the \"Add New Assets...\" button in the Assets tab of the Library view.";
tr("Your file does not import Qt Quick 3D.<br><br>"
"To create a 3D view, add the QtQuick3D import to your file in the QML Imports tab of the Library view. Or click"
" <a href=\"#add_import\"><span style=\"text-decoration:none;color:%1\">here</span></a> "
"here to add it immediately.<br><br>"
"To import 3D assets from another tool, click on the \"Add New Assets...\" button in the Assets tab of the Library view.");
m_onboardingLabel->setText(labelText.arg(Utils::creatorTheme()->color(Utils::Theme::TextColorLink).name()));
m_onboardingLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
connect(m_onboardingLabel, &QLabel::linkActivated, this, &Edit3DWidget::linkActivated);

View File

@@ -36,7 +36,8 @@ SOURCES += formeditoritem.cpp \
contentnoteditableindicator.cpp \
backgroundaction.cpp \
formeditortoolbutton.cpp \
formeditorannotationicon.cpp
formeditorannotationicon.cpp \
transitiontool.cpp
HEADERS += formeditorscene.h \
formeditorwidget.h \
@@ -75,6 +76,7 @@ HEADERS += formeditorscene.h \
contentnoteditableindicator.h \
backgroundaction.h \
formeditortoolbutton.h \
formeditorannotationicon.h
formeditorannotationicon.h \
transitiontool.h
RESOURCES += formeditor.qrc

View File

@@ -0,0 +1,438 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "transitiontool.h"
#include <formeditorscene.h>
#include <formeditorview.h>
#include <formeditorwidget.h>
#include <itemutilfunctions.h>
#include <formeditoritem.h>
#include <layeritem.h>
#include <resizehandleitem.h>
#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>
#include <nodemetainfo.h>
#include <qmlitemnode.h>
#include <qmldesignerplugin.h>
#include <abstractaction.h>
#include <designeractionmanager.h>
#include <variantproperty.h>
#include <rewritingexception.h>
#include <rewritertransaction.h>
#include <coreplugin/icore.h>
#include <utils/qtcassert.h>
#include <QApplication>
#include <QGraphicsSceneMouseEvent>
#include <QAction>
#include <QMessageBox>
#include <QPair>
#include <QGraphicsSceneMouseEvent>
namespace QmlDesigner {
static bool isTransitionSource(const ModelNode &node)
{
return QmlFlowTargetNode::isFlowEditorTarget(node);
}
static bool isTransitionTarget(const QmlItemNode &node)
{
return QmlFlowTargetNode::isFlowEditorTarget(node)
&& !node.isFlowActionArea()
&& !node.isFlowWildcard();
}
class TransitionToolAction : public AbstractAction
{
public:
TransitionToolAction(const QString &name) : AbstractAction(name) {}
QByteArray category() const override
{
return QByteArray();
}
QByteArray menuId() const override
{
return "TransitionTool";
}
int priority() const override
{
return CustomActionsPriority;
}
Type type() const override
{
return ContextMenuAction;
}
protected:
bool isVisible(const SelectionContext &selectionContext) const override
{
if (selectionContext.scenePosition().isNull())
return false;
if (selectionContext.singleNodeIsSelected())
return isTransitionSource(selectionContext.currentSingleSelectedNode());
return false;
}
bool isEnabled(const SelectionContext &selectionContext) const override
{
return isVisible(selectionContext);
}
};
class TransitionCustomAction : public TransitionToolAction
{
public:
TransitionCustomAction(const QString &name) : TransitionToolAction(name) {}
QByteArray category() const override
{
return ComponentCoreConstants::flowCategory;
}
SelectionContext selectionContext() const
{
return AbstractAction::selectionContext();
}
};
static QRectF paintedBoundingRect(FormEditorItem *item)
{
QRectF boundingRect = item->qmlItemNode().instanceBoundingRect();
if (boundingRect.width() < 4)
boundingRect = item->boundingRect();
return boundingRect;
}
static QPointF centerPoint(FormEditorItem *item)
{
QRectF boundingRect = paintedBoundingRect(item);
return QPointF(item->scenePos().x() + boundingRect.width() / 2,
item->scenePos().y() + boundingRect.height() / 2);
}
void static setToBoundingRect(QGraphicsRectItem *rect, FormEditorItem *item)
{
QPolygonF boundingRectInSceneSpace(item->mapToScene(paintedBoundingRect(item)));
rect->setRect(boundingRectInSceneSpace.boundingRect());
}
TransitionTool::TransitionTool()
: QObject(), AbstractCustomTool()
{
TransitionToolAction *transitionToolAction = new TransitionToolAction(tr("Add Transition"));
QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(transitionToolAction);
connect(transitionToolAction->action(), &QAction::triggered,
this, &TransitionTool::activateTool);
TransitionCustomAction *removeAction = new TransitionCustomAction(tr("Remove Transitions"));
QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(removeAction);
connect(removeAction->action(), &QAction::triggered,
this, [removeAction](){
SelectionContext context = removeAction->selectionContext();
QmlFlowTargetNode node = QmlFlowTargetNode(context.currentSingleSelectedNode());
context.view()->executeInTransaction("Remove Transitions", [&node](){
if (node.isValid())
node.removeTransitions();
});
});
TransitionCustomAction *removeAllTransitionsAction = new TransitionCustomAction(tr("Remove All Transitions"));
QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(removeAllTransitionsAction);
connect(removeAllTransitionsAction->action(), &QAction::triggered,
this, [removeAllTransitionsAction](){
if (QMessageBox::question(Core::ICore::dialogParent(),
tr("Remove All Transitions"),
tr("Do you really want to remove all transitions?"),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
return;
SelectionContext context = removeAllTransitionsAction->selectionContext();
QmlFlowTargetNode node = QmlFlowTargetNode(context.currentSingleSelectedNode());
context.view()->executeInTransaction("Remove All Transitions", [&node](){
if (node.isValid() && node.flowView().isValid())
node.flowView().removeAllTransitions();
});
});
TransitionCustomAction *removeDanglingTransitionAction = new TransitionCustomAction(tr("Remove Dangling Transitions"));
QmlDesignerPlugin::instance()->designerActionManager().addDesignerAction(removeDanglingTransitionAction);
connect(removeDanglingTransitionAction->action(), &QAction::triggered,
this, [removeDanglingTransitionAction](){
SelectionContext context = removeDanglingTransitionAction->selectionContext();
QmlFlowTargetNode node = QmlFlowTargetNode(context.currentSingleSelectedNode());
context.view()->executeInTransaction("Remove Dangling Transitions", [&node](){
if (node.isValid() && node.flowView().isValid())
node.flowView().removeDanglingTransitions();
});
});
}
TransitionTool::~TransitionTool()
{
}
void TransitionTool::clear()
{
m_lineItem.reset(nullptr);
m_rectangleItem1.reset(nullptr);
m_rectangleItem2.reset(nullptr);
AbstractFormEditorTool::clear();
}
void TransitionTool::mousePressEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event)
{
if (m_block)
return;
if (event->button() != Qt::LeftButton)
return;
AbstractFormEditorTool::mousePressEvent(itemList, event);
TransitionTool::mouseMoveEvent(itemList, event);
}
void TransitionTool::mouseMoveEvent(const QList<QGraphicsItem*> & itemList,
QGraphicsSceneMouseEvent * event)
{
if (!m_lineItem)
return;
QTC_ASSERT(currentFormEditorItem(), return);
const QPointF pos = centerPoint(m_formEditorItem);
lineItem()->setLine(pos.x(),
pos.y(),
event->scenePos().x(),
event->scenePos().y());
FormEditorItem *formEditorItem = nearestFormEditorItem(event->scenePos(), itemList);
if (formEditorItem
&& formEditorItem->qmlItemNode().isValid()
&& isTransitionTarget(formEditorItem->qmlItemNode().modelNode())) {
rectangleItem2()->setVisible(true);
setToBoundingRect(rectangleItem2(), formEditorItem);
} else {
rectangleItem2()->setVisible(false);
}
}
void TransitionTool::hoverMoveEvent(const QList<QGraphicsItem*> & itemList,
QGraphicsSceneMouseEvent *event)
{
mouseMoveEvent(itemList, event);
}
void TransitionTool::keyPressEvent(QKeyEvent * /*keyEvent*/)
{
}
void TransitionTool::keyReleaseEvent(QKeyEvent * /*keyEvent*/)
{
view()->changeToSelectionTool();
}
void TransitionTool::dragLeaveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGraphicsSceneDragDropEvent * /*event*/)
{
}
void TransitionTool::dragMoveEvent(const QList<QGraphicsItem*> &/*itemList*/, QGraphicsSceneDragDropEvent * /*event*/)
{
}
void TransitionTool::mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event)
{
if (m_block)
return;
if (event->button() == Qt::LeftButton) {
FormEditorItem *formEditorItem = nearestFormEditorItem(event->scenePos(), itemList);
if (formEditorItem
&& QmlFlowTargetNode(formEditorItem->qmlItemNode().modelNode()).isValid())
createTransition(m_formEditorItem, formEditorItem);
}
view()->changeToSelectionTool();
}
void TransitionTool::mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList, QGraphicsSceneMouseEvent *event)
{
AbstractFormEditorTool::mouseDoubleClickEvent(itemList, event);
}
void TransitionTool::itemsAboutToRemoved(const QList<FormEditorItem*> &)
{
view()->changeCurrentToolTo(this);
}
void TransitionTool::selectedItemsChanged(const QList<FormEditorItem*> &itemList)
{
if (!itemList.isEmpty()) {
createItems();
m_formEditorItem = itemList.first();
setToBoundingRect(rectangleItem1(), m_formEditorItem);
}
}
void TransitionTool::instancesCompleted(const QList<FormEditorItem*> & /*itemList*/)
{
}
void TransitionTool::instancesParentChanged(const QList<FormEditorItem *> & /*itemList*/)
{
}
void TransitionTool::instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > & /*propertyList*/)
{
}
void TransitionTool::formEditorItemsChanged(const QList<FormEditorItem*> & /*itemList*/)
{
}
int TransitionTool::wantHandleItem(const ModelNode &modelNode) const
{
if (isTransitionSource(modelNode))
return 10;
return 0;
}
QString TransitionTool::name() const
{
return tr("Transition Tool");
}
void TransitionTool::activateTool()
{
view()->changeToCustomTool();
}
void TransitionTool::unblock()
{
m_block = false;
}
QGraphicsLineItem *TransitionTool::lineItem()
{
return m_lineItem.get();
}
QGraphicsRectItem *TransitionTool::rectangleItem1()
{
return m_rectangleItem1.get();
}
QGraphicsRectItem *TransitionTool::rectangleItem2()
{
return m_rectangleItem2.get();
}
FormEditorItem *TransitionTool::currentFormEditorItem() const
{
if (scene()->items().contains(m_formEditorItem))
return m_formEditorItem;
return nullptr;
}
void TransitionTool::createItems() {
m_block = true;
QTimer::singleShot(200, this, [this](){ unblock(); });
if (!lineItem())
m_lineItem.reset(new QGraphicsLineItem(scene()->manipulatorLayerItem()));
if (!rectangleItem1())
m_rectangleItem1.reset(new QGraphicsRectItem(scene()->manipulatorLayerItem()));
if (!rectangleItem2())
m_rectangleItem2.reset(new QGraphicsRectItem(scene()->manipulatorLayerItem()));
m_rectangleItem2->setVisible(false);
QPen pen;
pen.setColor(QColor(Qt::lightGray));
pen.setStyle(Qt::DashLine);
pen.setWidth(0);
m_lineItem->setPen(pen);
pen.setColor(QColor(108, 141, 221));
pen.setStyle(Qt::SolidLine);
pen.setWidth(4);
pen.setCosmetic(true);
m_rectangleItem1->setPen(pen);
m_rectangleItem2->setPen(pen);
}
void TransitionTool::createTransition(FormEditorItem *source, FormEditorItem *target)
{
QmlFlowTargetNode sourceNode(source->qmlItemNode().modelNode());
QmlFlowTargetNode targetNode(target->qmlItemNode().modelNode());
if (sourceNode.isValid() && targetNode.isValid()
&& sourceNode != targetNode
&& !targetNode.isFlowActionArea()
&& !targetNode.isFlowWildcard()) {
view()->executeInTransaction("create transition", [&sourceNode, targetNode](){
sourceNode.assignTargetItem(targetNode);
});
} else {
qWarning() << Q_FUNC_INFO << "nodes invalid";
}
}
}

View File

@@ -0,0 +1,98 @@
/****************************************************************************
**
** Copyright (C) 2020 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#pragma once
#include "abstractcustomtool.h"
#include "selectionindicator.h"
#include <QGraphicsLineItem>
#include <QHash>
#include <QPointer>
#include <memory>
namespace QmlDesigner {
class TransitionTool : public QObject, public AbstractCustomTool
{
Q_OBJECT
public:
TransitionTool();
~TransitionTool();
void mousePressEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event) override;
void mouseMoveEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event) override;
void mouseReleaseEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event) override;
void mouseDoubleClickEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event) override;
void hoverMoveEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneMouseEvent *event) override;
void keyPressEvent(QKeyEvent *event) override;
void keyReleaseEvent(QKeyEvent *keyEvent) override;
void dragLeaveEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneDragDropEvent * event) override;
void dragMoveEvent(const QList<QGraphicsItem*> &itemList,
QGraphicsSceneDragDropEvent * event) override;
void itemsAboutToRemoved(const QList<FormEditorItem*> &itemList) override;
void selectedItemsChanged(const QList<FormEditorItem*> &itemList) override;
void instancesCompleted(const QList<FormEditorItem*> &itemList) override;
void instancesParentChanged(const QList<FormEditorItem *> &itemList) override;
void instancePropertyChange(const QList<QPair<ModelNode, PropertyName> > &propertyList) override;
void clear() override;
void formEditorItemsChanged(const QList<FormEditorItem*> &itemList) override;
int wantHandleItem(const ModelNode &modelNode) const override;
QString name() const override;
void activateTool();
void unblock();
QGraphicsLineItem *lineItem();
QGraphicsRectItem *rectangleItem1();
QGraphicsRectItem *rectangleItem2();
private:
FormEditorItem *currentFormEditorItem() const;
void createItems();
void createTransition(FormEditorItem *item1, FormEditorItem *item2);
FormEditorItem* m_formEditorItem;
std::unique_ptr<QGraphicsLineItem> m_lineItem;
std::unique_ptr<QGraphicsRectItem> m_rectangleItem1;
std::unique_ptr<QGraphicsRectItem> m_rectangleItem2;
bool m_block = true;
};
} //QmlDesigner

View File

@@ -81,14 +81,16 @@ void ImportManagerView::modelAboutToBeDetached(Model *model)
void ImportManagerView::importsChanged(const QList<Import> &/*addedImports*/, const QList<Import> &/*removedImports*/)
{
if (m_importsWidget)
if (m_importsWidget) {
m_importsWidget->setImports(model()->imports());
// setImports recreates labels, so we need to update used imports, as it is not guaranteed
// usedImportsChanged notification will come after this.
m_importsWidget->setUsedImports(model()->usedImports());
}
}
void ImportManagerView::possibleImportsChanged(const QList<Import> &/*possibleImports*/)
{
QmlDesignerPlugin::instance()->currentDesignDocument()->updateSubcomponentManager();
if (m_importsWidget)
m_importsWidget->setPossibleImports(model()->possibleImports());
}

View File

@@ -32,6 +32,9 @@
#include "utils/outputformatter.h"
#include "theme.h"
#include <projectexplorer/project.h>
#include <projectexplorer/session.h>
#include <QtCore/qfileinfo.h>
#include <QtCore/qdir.h>
#include <QtCore/qloggingcategory.h>
@@ -97,6 +100,20 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
QStringList importPaths;
auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
if (doc) {
Model *model = doc->currentModel();
if (model)
importPaths = model->importPaths();
}
QString targetDir = defaulTargetDirectory;
ProjectExplorer::Project *currentProject = ProjectExplorer::SessionManager::projectForFile(doc->fileName());
if (currentProject)
targetDir = currentProject->projectDirectory().toString();
// Import is always done under known folder. The order of preference for folder is:
// 1) An existing QUICK_3D_ASSETS_FOLDER under DEFAULT_ASSET_IMPORT_FOLDER project import path
// 2) An existing QUICK_3D_ASSETS_FOLDER under any project import path
@@ -105,19 +122,11 @@ ItemLibraryAssetImportDialog::ItemLibraryAssetImportDialog(const QStringList &im
// 5) New QUICK_3D_ASSETS_FOLDER under new DEFAULT_ASSET_IMPORT_FOLDER under project
const QString defaultAssetFolder = QLatin1String(Constants::DEFAULT_ASSET_IMPORT_FOLDER);
const QString quick3DFolder = QLatin1String(Constants::QUICK_3D_ASSETS_FOLDER);
QString candidatePath = defaulTargetDirectory + defaultAssetFolder + quick3DFolder;
QString candidatePath = targetDir + defaultAssetFolder + quick3DFolder;
int candidatePriority = 5;
QStringList importPaths;
auto doc = QmlDesignerPlugin::instance()->currentDesignDocument();
if (doc) {
Model *model = doc->currentModel();
if (model)
importPaths = model->importPaths();
}
for (auto importPath : qAsConst(importPaths)) {
if (importPath.startsWith(defaulTargetDirectory)) {
if (importPath.startsWith(targetDir)) {
const bool isDefaultFolder = importPath.endsWith(defaultAssetFolder);
const QString assetFolder = importPath + quick3DFolder;
const bool exists = QFileInfo(assetFolder).exists();

View File

@@ -280,7 +280,16 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar
return;
}
QString originalAssetName = assetName;
if (targetDir.exists(assetName)) {
// If we have a file system with case insensitive filenames, assetName may be
// different from the existing name. Modify assetName to ensure exact match to
// the overwritten old asset capitalization
const QStringList assetDirs = targetDir.entryList({assetName}, QDir::Dirs);
if (assetDirs.size() == 1) {
assetName = assetDirs[0];
targetDirPath = targetDir.filePath(assetName);
}
if (!confirmAssetOverwrite(assetName)) {
addWarning(tr("Skipped import of existing asset: \"%1\"").arg(assetName));
return;
@@ -306,6 +315,16 @@ void ItemLibraryAssetImporter::parseQuick3DAsset(const QString &file, const QVar
return;
}
// The importer is reset after every import to avoid issues with it caching various things
m_quick3DAssetImporter.reset(new QSSGAssetImportManager);
if (originalAssetName != assetName) {
// Fix the generated qml file name
const QString assetQml = originalAssetName + ".qml";
if (outDir.exists(assetQml))
outDir.rename(assetQml, assetName + ".qml");
}
QHash<QString, QString> assetFiles;
const int outDirPathSize = outDir.path().size();
auto insertAsset = [&](const QString &filePath) {
@@ -512,18 +531,24 @@ void ItemLibraryAssetImporter::finalizeQuick3DImport()
addInfo(progressTitle);
notifyProgress(0, progressTitle);
// There is an inbuilt delay before rewriter change actually updates the data model,
// so we need to wait for a moment to allow the change to take effect.
// First we have to wait a while to ensure qmljs detects new files and updates its
// internal model. Then we make a non-change to the document to trigger qmljs snapshot
// update. There is an inbuilt delay before rewriter change actually updates the data
// model, so we need to wait for another moment to allow the change to take effect.
// Otherwise subsequent subcomponent manager update won't detect new imports properly.
QTimer *timer = new QTimer(parent());
static int counter;
counter = 0;
timer->callOnTimeout([this, timer, progressTitle, model]() {
timer->callOnTimeout([this, timer, progressTitle, model, doc]() {
if (!isCancelled()) {
notifyProgress(++counter * 10, progressTitle);
if (counter >= 10) {
// Trigger underlying qmljs snapshot update by making a non-change to the doc
notifyProgress(++counter * 5, progressTitle);
if (counter == 10) {
model->rewriterView()->textModifier()->replace(0, 0, {});
} else if (counter == 19) {
doc->updateSubcomponentManager();
} else if (counter >= 20) {
if (!m_overwrittenImports.isEmpty())
model->rewriterView()->emitCustomNotification("asset_import_update");
timer->stop();
notifyFinished();
}

View File

@@ -238,11 +238,6 @@ QMimeData *ItemLibraryModel::getMimeData(const ItemLibraryEntry &itemLibraryEntr
return mimeData;
}
QList<ItemLibrarySection *> ItemLibraryModel::sections() const
{
return m_sections;
}
void ItemLibraryModel::clearSections()
{
qDeleteAll(m_sections);

View File

@@ -58,17 +58,8 @@ public:
QMimeData *getMimeData(const ItemLibraryEntry &itemLibraryEntry);
QList<ItemLibrarySection*> sections() const;
void clearSections();
static void registerQmlTypes();
int visibleSectionCount() const;
QList<ItemLibrarySection*> visibleSections() const;
ItemLibrarySection *sectionByName(const QString &sectionName);
void setSearchText(const QString &searchText);
void setExpanded(bool, const QString &section);
@@ -80,13 +71,15 @@ signals:
void searchTextChanged();
private: // functions
ItemLibrarySection *sectionByName(const QString &sectionName);
void updateVisibility(bool *changed);
void addRoleNames();
void sortSections();
void clearSections();
private: // variables
QList<ItemLibrarySection*> m_sections;
QList<QPointer<ItemLibrarySection>> m_sections;
QHash<int, QByteArray> m_roleNames;
QString m_searchText;

View File

@@ -101,13 +101,15 @@ ItemLibraryWidget::ItemLibraryWidget(QWidget *parent) :
m_itemViewQuickWidget->engine()->addImportPath(propertyEditorResourcesPath() + "/imports");
m_itemLibraryModel = new ItemLibraryModel(this);
QQmlContext *rootContext = m_itemViewQuickWidget->rootContext();
rootContext->setContextProperty(QStringLiteral("itemLibraryModel"), m_itemLibraryModel.data());
rootContext->setContextProperty(QStringLiteral("itemLibraryIconWidth"), m_itemIconSize.width());
rootContext->setContextProperty(QStringLiteral("itemLibraryIconHeight"), m_itemIconSize.height());
rootContext->setContextProperty(QStringLiteral("rootView"), this);
m_itemViewQuickWidget->rootContext()->setContextProperty(QStringLiteral("highlightColor"), Utils::StyleHelper::notTooBrightHighlightColor());
m_itemViewQuickWidget->rootContext()->setContextProperties(
QVector<QQmlContext::PropertyPair>{
{"itemLibraryModel", QVariant::fromValue(m_itemLibraryModel.data())},
{"itemLibraryIconWidth", m_itemIconSize.width()},
{"itemLibraryIconHeight", m_itemIconSize.height()},
{"rootView", QVariant::fromValue(this)},
{"highlightColor", Utils::StyleHelper::notTooBrightHighlightColor()}
}
);
/* create Resources view and its model */
m_resourcesFileSystemModel = new CustomFileSystemModel(this);

View File

@@ -43,6 +43,7 @@ public:
virtual void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) = 0;
virtual void notifyIconsChanged() = 0;
virtual void setFilter(bool showObjects) = 0;
virtual void resetModel() = 0;
};

View File

@@ -695,6 +695,11 @@ void NavigatorTreeModel::notifyModelNodesMoved(const QList<ModelNode> &modelNode
emit layoutChanged(indexes);
}
void NavigatorTreeModel::notifyIconsChanged()
{
emit dataChanged(index(0, 0), index(rowCount(), 0), {Qt::DecorationRole});
}
void NavigatorTreeModel::setFilter(bool showOnlyVisibleItems)
{
m_showOnlyVisibleItems = showOnlyVisibleItems;

View File

@@ -87,6 +87,7 @@ public:
void notifyModelNodesRemoved(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesInserted(const QList<ModelNode> &modelNodes) override;
void notifyModelNodesMoved(const QList<ModelNode> &modelNodes) override;
void notifyIconsChanged() override;
void setFilter(bool showOnlyVisibleItems) override;
void resetModel() override;

View File

@@ -147,6 +147,17 @@ void NavigatorView::bindingPropertiesChanged(const QList<BindingProperty> & prop
}
}
void NavigatorView::customNotification(const AbstractView *view, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
Q_UNUSED(view)
Q_UNUSED(nodeList)
Q_UNUSED(data)
if (identifier == "asset_import_update")
m_currentModelInterface->notifyIconsChanged();
}
void NavigatorView::handleChangedExport(const ModelNode &modelNode, bool exported)
{
const ModelNode rootNode = rootModelNode();
@@ -431,7 +442,7 @@ void NavigatorView::updateItemSelection()
// make sure selected nodes a visible
foreach (const QModelIndex &selectedIndex, itemSelection.indexes()) {
if (selectedIndex.column() == 0)
expandRecursively(selectedIndex);
expandAncestors(selectedIndex);
}
}
@@ -455,9 +466,9 @@ bool NavigatorView::blockSelectionChangedSignal(bool block)
return oldValue;
}
void NavigatorView::expandRecursively(const QModelIndex &index)
void NavigatorView::expandAncestors(const QModelIndex &index)
{
QModelIndex currentIndex = index;
QModelIndex currentIndex = index.parent();
while (currentIndex.isValid()) {
if (!treeWidget()->isExpanded(currentIndex))
treeWidget()->expand(currentIndex);

View File

@@ -84,6 +84,8 @@ public:
void bindingPropertiesChanged(const QList<BindingProperty> &propertyList, PropertyChangeFlags) override;
void customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data) override;
void handleChangedExport(const ModelNode &modelNode, bool exported);
bool isNodeInvisible(const ModelNode &modelNode) const;
@@ -108,7 +110,7 @@ protected: //functions
QTreeView *treeWidget() const;
NavigatorTreeModel *treeModel();
bool blockSelectionChangedSignal(bool block);
void expandRecursively(const QModelIndex &index);
void expandAncestors(const QModelIndex &index);
void reparentAndCatch(NodeAbstractProperty property, const ModelNode &modelNode);
void setupWidget();

View File

@@ -379,9 +379,12 @@ void PropertyEditorQmlBackend::setup(const QmlObjectNode &qmlObjectNode, const Q
// anchors
m_backendAnchorBinding.setup(qmlObjectNode.modelNode());
context()->setContextProperty(QLatin1String("anchorBackend"), &m_backendAnchorBinding);
context()->setContextProperty(QLatin1String("transaction"), m_propertyEditorTransaction.data());
context()->setContextProperties(
QVector<QQmlContext::PropertyPair>{
{{"anchorBackend"}, QVariant::fromValue(&m_backendAnchorBinding)},
{{"transaction"}, QVariant::fromValue(m_propertyEditorTransaction.data())}
}
);
qCInfo(propertyEditorBenchmark) << "anchors:" << time.elapsed();
@@ -457,9 +460,13 @@ void PropertyEditorQmlBackend::initialSetup(const TypeName &typeName, const QUrl
QObject::connect(valueObject, &PropertyEditorValue::valueChanged, &backendValuesPropertyMap(), &DesignerPropertyMap::valueChanged);
m_backendValuesPropertyMap.insert(QLatin1String("id"), QVariant::fromValue(valueObject));
context()->setContextProperty(QLatin1String("anchorBackend"), &m_backendAnchorBinding);
context()->setContextProperty(QLatin1String("modelNodeBackend"), &m_backendModelNode);
context()->setContextProperty(QLatin1String("transaction"), m_propertyEditorTransaction.data());
context()->setContextProperties(
QVector<QQmlContext::PropertyPair>{
{{"anchorBackend"}, QVariant::fromValue(&m_backendAnchorBinding)},
{{"modelNodeBackend"}, QVariant::fromValue(&m_backendModelNode)},
{{"transaction"}, QVariant::fromValue(m_propertyEditorTransaction.data())}
}
);
contextObject()->setSpecificsUrl(qmlSpecificsFile);

View File

@@ -102,9 +102,12 @@ StatesEditorWidget::StatesEditorWidget(StatesEditorView *statesEditorView, State
setResizeMode(QQuickWidget::SizeRootObjectToView);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
rootContext()->setContextProperty(QStringLiteral("statesEditorModel"), statesEditorModel);
rootContext()->setContextProperty(QLatin1String("canAddNewStates"), true);
rootContext()->setContextProperties(
QVector<QQmlContext::PropertyPair>{
{{"statesEditorModel"}, QVariant::fromValue(statesEditorModel)},
{{"canAddNewStates"}, true}
}
);
Theme::setupTheme(engine());

View File

@@ -85,10 +85,25 @@ bool ChangeImportsVisitor::remove(QmlJS::AST::UiProgram *ast, const Import &impo
bool ChangeImportsVisitor::equals(QmlJS::AST::UiImport *ast, const Import &import)
{
bool equal = false;
if (import.isLibraryImport())
return toString(ast->importUri) == import.url();
equal = toString(ast->importUri) == import.url();
else if (import.isFileImport())
return ast->fileName == import.file();
else
return false;
equal = ast->fileName == import.file();
if (equal) {
equal = (!ast->version || (ast->version->minorVersion == 0 && ast->version->majorVersion == 0))
&& import.version().isEmpty();
if (!equal && ast->version) {
const QStringList versions = import.version().split('.');
if (versions.size() >= 1 && versions[0].toInt() == ast->version->majorVersion) {
if (versions.size() >= 2)
equal = versions[1].toInt() == ast->version->minorVersion;
else
equal = ast->version->minorVersion == 0;
}
}
}
return equal;
}

View File

@@ -182,8 +182,13 @@ public:
const QList<ModelNode> wildcards() const;
const QList<ModelNode> decicions() const;
QList<ModelNode> transitionsForTarget(const ModelNode &modelNode);
QList<ModelNode> transitionsForSource(const ModelNode &modelNode);
void removeDanglingTransitions();
void removeAllTransitions();
void setStartFlowItem(const QmlFlowItemNode &flowItem);
ModelNode createTransition();
protected:
QList<ModelNode> transitionsForProperty(const PropertyName &propertyName, const ModelNode &modelNode);
};

View File

@@ -650,7 +650,7 @@ PropertyName NodeMetaInfoPrivate::defaultPropertyName() const
static inline TypeName stringIdentifier( const TypeName &type, int maj, int min)
{
return type + QString::number(maj).toLatin1() + '_' + QString::number(min).toLatin1();
return type + QByteArray::number(maj) + '_' + QByteArray::number(min);
}
NodeMetaInfoPrivate::Pointer NodeMetaInfoPrivate::create(Model *model, const TypeName &type, int major, int minor)

View File

@@ -420,8 +420,7 @@ void SubComponentManager::parseQuick3DAssetDir(const QString &assetPath)
itemLibraryEntry.addHints(hints);
}
if (!model()->metaInfo().itemLibraryInfo()->containsEntry(itemLibraryEntry))
model()->metaInfo().itemLibraryInfo()->addEntries({itemLibraryEntry});
model()->metaInfo().itemLibraryInfo()->addEntries({itemLibraryEntry}, true);
}
}
}

View File

@@ -664,9 +664,7 @@ QList<QmlFlowItemNode> QmlFlowViewNode::flowItems() const
ModelNode QmlFlowViewNode::addTransition(const QmlFlowTargetNode &from, const QmlFlowTargetNode &to)
{
ModelNode transition = view()->createModelNode("FlowView.FlowTransition", 1, 0);
nodeListProperty("flowTransitions").reparentHere(transition);
ModelNode transition = createTransition();
QmlFlowTargetNode f = from;
QmlFlowTargetNode t = to;
@@ -684,8 +682,6 @@ const QList<ModelNode> QmlFlowViewNode::transitions() const
return modelNode().nodeListProperty("flowTransitions").toModelNodeList();
return {};
}
const QList<ModelNode> QmlFlowViewNode::wildcards() const
@@ -706,13 +702,12 @@ const QList<ModelNode> QmlFlowViewNode::decicions() const
QList<ModelNode> QmlFlowViewNode::transitionsForTarget(const ModelNode &modelNode)
{
QList<ModelNode> list;
for (const ModelNode &transition : transitions()) {
if (transition.hasBindingProperty("to")
&& transition.bindingProperty("to").resolveToModelNode() == modelNode)
list.append(transition);
}
return list;
return transitionsForProperty("to", modelNode);
}
QList<ModelNode> QmlFlowViewNode::transitionsForSource(const ModelNode &modelNode)
{
return transitionsForProperty("from", modelNode);
}
void QmlFlowViewNode::removeDanglingTransitions()
@@ -830,4 +825,41 @@ void QmlFlowViewNode::removeAllTransitions()
removeProperty("flowTransitions");
}
void QmlFlowViewNode::setStartFlowItem(const QmlFlowItemNode &flowItem)
{
QTC_ASSERT(flowItem.isValid(), return);
QmlFlowItemNode item = flowItem;
ModelNode transition;
for (const ModelNode &node : transitionsForSource(modelNode()))
transition = node;
if (!transition.isValid())
transition = createTransition();
transition.bindingProperty("from").setExpression(modelNode().validId());
transition.bindingProperty("to").setExpression(item.validId());
}
ModelNode QmlFlowViewNode::createTransition()
{
ModelNode transition = view()->createModelNode("FlowView.FlowTransition", 1, 0);
nodeListProperty("flowTransitions").reparentHere(transition);
return transition;
}
QList<ModelNode> QmlFlowViewNode::transitionsForProperty(const PropertyName &propertyName,
const ModelNode &modelNode)
{
QList<ModelNode> list;
for (const ModelNode &transition : transitions()) {
if (transition.hasBindingProperty(propertyName)
&& transition.bindingProperty(propertyName).resolveToModelNode() == modelNode)
list.append(transition);
}
return list;
}
} //QmlDesigner

View File

@@ -381,11 +381,21 @@ void QmlObjectNode::destroy()
timeline.destroyKeyframesForTarget(subNode);
}
if (QmlFlowActionAreaNode::isValidQmlFlowActionAreaNode(modelNode()))
QmlFlowActionAreaNode(modelNode()).destroyTarget();
bool wasFlowEditorTarget = false;
if (QmlFlowTargetNode::isFlowEditorTarget(modelNode())) {
QmlFlowTargetNode(modelNode()).destroyTargets();
wasFlowEditorTarget = true;
}
removeStateOperationsForChildren(modelNode());
BindingProperty::deleteAllReferencesTo(modelNode());
QmlFlowViewNode root(view()->rootModelNode());
modelNode().destroy();
if (wasFlowEditorTarget && root.isValid())
root.removeDanglingTransitions();
}
void QmlObjectNode::ensureAliasExport()

View File

@@ -84,6 +84,7 @@ void DesignerSettings::fromSettings(QSettings *settings)
);
restoreValue(settings, DesignerSettingsKey::SIMPLE_COLOR_PALETTE_CONTENT, QStringList());
restoreValue(settings, DesignerSettingsKey::ALWAYS_DESIGN_MODE, true);
restoreValue(settings, DesignerSettingsKey::DISABLE_ITEM_LIBRARY_UPDATE_TIMER, true);
settings->endGroup();
settings->endGroup();

View File

@@ -38,6 +38,7 @@
#include <sourcetool/sourcetool.h>
#include <colortool/colortool.h>
#include <annotationeditor/annotationtool.h>
#include <formeditor/transitiontool.h>
#include <texttool/texttool.h>
#include <timelineeditor/timelineview.h>
#include <pathtool/pathtool.h>
@@ -247,6 +248,7 @@ bool QmlDesignerPlugin::delayedInitialize()
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::AnnotationTool);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::TextTool);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::PathTool);
d->viewManager.registerFormEditorToolTakingOwnership(new QmlDesigner::TransitionTool);
return true;
}

View File

@@ -530,6 +530,8 @@ Project {
"formeditor/toolbox.h",
"formeditor/formeditortoolbutton.cpp",
"formeditor/formeditortoolbutton.h",
"formeditor/transitiontool.cpp",
"formeditor/transitiontool.h",
"importmanager/importlabel.cpp",
"importmanager/importlabel.h",
"importmanager/importmanagercombobox.cpp",

View File

@@ -791,7 +791,7 @@ void QmlJSEditorWidget::findLinkAt(const QTextCursor &cursor,
const QString relative = QString::fromLatin1("%1/%2").arg(
semanticInfo.document->path(),
text);
if (semanticInfo.snapshot.document(relative)) {
if (QFileInfo::exists(relative)) {
link.targetFileName = relative;
processLinkCallback(link);
return;

View File

@@ -2034,6 +2034,9 @@ FilePaths BaseQtVersionPrivate::qtCorePaths()
else if (file.endsWith(".dll")
|| file.endsWith(QString::fromLatin1(".so.") + versionString)
|| file.endsWith(".so")
#if defined(Q_OS_OPENBSD)
|| file.contains(QRegularExpression("\\.so\\.[0-9]+\\.[0-9]+$")) // QTCREATORBUG-23818
#endif
|| file.endsWith(QLatin1Char('.') + versionString + ".dylib"))
dynamicLibs.append(FilePath::fromFileInfo(info));
}

View File

@@ -107,6 +107,7 @@
#include <QPropertyAnimation>
#include <QDrag>
#include <QSequentialAnimationGroup>
#include <QScreen>
#include <QScrollBar>
#include <QShortcut>
#include <QStyle>
@@ -1199,7 +1200,11 @@ void TextEditorWidgetPrivate::print(QPrinter *printer)
QAbstractTextDocumentLayout *layout = doc->documentLayout();
layout->setPaintDevice(p.device());
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
int dpiy = p.device()->logicalDpiY();
#else
int dpiy = qRound(QGuiApplication::primaryScreen()->logicalDotsPerInchY());
#endif
int margin = int((2/2.54)*dpiy); // 2 cm margins
QTextFrameFormat fmt = doc->rootFrame()->frameFormat();

View File

@@ -4706,14 +4706,19 @@ void tst_Dumpers::dumper_data()
QTest::newRow("StdUniquePtr")
<< Data("#include <memory>\n"
"#include <string>\n" + fooData,
"#include <string>\n" + fooData +
"static Foo *alloc_foo() { return new Foo; }\n"
"static void free_foo(Foo *f) { delete f; }\n",
"std::unique_ptr<int> p0;\n\n"
"std::unique_ptr<int> p1(new int(32));\n\n"
"std::unique_ptr<Foo> p2(new Foo);\n\n"
"std::unique_ptr<std::string> p3(new std::string(\"ABC\"));",
"std::unique_ptr<std::string> p3(new std::string(\"ABC\"));\n"
"&p0, &p1, &p2, &p3")
"std::unique_ptr<Foo, void(*)(Foo*)> p4{alloc_foo(), free_foo};",
"&p0, &p1, &p2, &p3, &p4")
+ CoreProfile()
+ Cxx11Profile()
@@ -4722,7 +4727,8 @@ void tst_Dumpers::dumper_data()
+ Check("p0", "(null)", "std::unique_ptr<int, std::default_delete<int> >")
+ Check("p1", "32", "std::unique_ptr<int, std::default_delete<int> >")
+ Check("p2", Pointer(), "std::unique_ptr<Foo, std::default_delete<Foo> >")
+ Check("p3", "\"ABC\"", "std::unique_ptr<std::string, std::default_delete<std::string> >");
+ Check("p3", "\"ABC\"", "std::unique_ptr<std::string, std::default_delete<std::string> >")
+ Check("p4.b", "2", "int");
QTest::newRow("StdOnce")