Merge remote-tracking branch 'origin/6.0'

Change-Id: Ia7fc255ee8680e6beac5d4d878f446fe40873183
This commit is contained in:
Eike Ziller
2021-11-08 09:46:57 +01:00
130 changed files with 1693 additions and 173 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@@ -138,10 +138,6 @@
edit the value for the \uicontrol {Do not index files greater than}
check box. To index all files, deselect the check box.
\li To use clangd instead of the built-in code model for features such as
\e {Find References to Symbol}, check the \uicontrol {Use clangd} checkbox.
\note This is an experimental feature, which might not work reliably yet.
\li The \uicontrol {Diagnostic Configuration} field shows the Clang
checks to perform. Click the value of the field to open the
\uicontrol {Diagnostic Configurations} dialog, where you can
@@ -151,6 +147,51 @@
\endlist
\section1 Configuring clangd
You can use the experimental clangd support instead of libclang to receive
exact and complete results for services such as finding references,
following symbols under cursor, and using the locator, even for complex
constructs that the built-in code model cannot handle correctly. These
improvements are based on clangd's \e index. When you \l{Opening Projects}
{open a project}, clangd scans the source files to generate the index. For
large projects, this can take a while, but the index is persistent and
re-scanning is incremental, so nothing is lost by closing and re-starting
\QC.
Because clangd considers only the on-disk state of included header files
when parsing a source file, you need to save changes in header files to
have them considered elsewhere for completion, diagnostics, and so on.
Partly for this reason, files that are changed by refactoring actions are
saved automatically. To disable this feature, select \uicontrol Tools >
\uicontrol Options > \uicontrol Environment > \uicontrol System >
\uicontrol {Auto-save files after refactoring}.
The document outline in the \l{Viewing Defined Types and Symbols}
{Outline} view is backed by clangd's document symbol support, which
makes the results more reliable than before.
To use clangd for the current project instead of the built-in code model or
Clang:
\list 1
\li Select \uicontrol Tools > \uicontrol Options > \uicontrol C++ >
\uicontrol Clang > \uicontrol {Use clangd (EXPERIMENTAL)}.
\image qtcreator-options-clangd.png "clangd options"
\li In \uicontrol {Path to executable}, enter the path to clangd
version 13, or later.
\li For more accurate results during global symbol searches, select
\uicontrol {Enable background indexing}. However, this increases the
CPU load the first time you open the project.
\li Select \uicontrol {Insert header files on completion} to allow
clangd to insert header files as part of symbol completion.
\li By default, clangd attempts to use all unused cores. You can set a
fixed number of cores to use in \uicontrol {Worker thread count}.
\li In \uicontrol {Document update threshold}, specify the amount of
time \QC waits before sending document changes to the server.
If the document changes again while waiting, this timeout is reset.
\endlist
\section1 Clang Checks
In addition to using the built-in checks, you can select \uicontrol Copy to

View File

@@ -116,7 +116,8 @@
\section1 Advanced Search
To search through projects, files on a file system or currently open files:
To search through projects, files on a file system, files in all project
directories, or currently open files:
\list 1
@@ -136,6 +137,9 @@
\li \uicontrol {Current Project} searches from the project you
are currently editing.
\li \uicontrol {Files in All Project Directories} searches from
all project directories.
\li \uicontrol {Files in File System} recursively searches from
the selected directory.
@@ -206,6 +210,9 @@
To clear the search results, select the \inlineimage clean_pane_small.png
(\uicontrol Clear) button.
To expand and collapse the search results, select the
\uicontrol {Expand All} button.
To start a new search, select the \inlineimage qtcreator-new-search-icon.png
(\uicontrol {New Search}) button.

View File

@@ -38,6 +38,9 @@
\uicontrol Design mode:
\image qtcreator-filesystem-view-design.png "File System view in the Design mode"
\else
\image qtcreator-filesystem-view.png "File System view in the sidebar"
\endif
To move to the root directory of the file system, select \uicontrol Computer
in the menu (1). Select \uicontrol Home to move to the user's home
@@ -89,14 +92,19 @@
\li Collapse all open folders.
\endlist
\section1 File System View in Sidebar
\endif
\section1 File System View Toolbar
\if defined(qtdesignstudio)
In the \uicontrol Edit and \uicontrol Debug mode, the
\uicontrol {File System} view is displayed in the \l{Working with Sidebars}
{sidebar}. It has a toolbar with additional options:
{sidebar}. It has a toolbar with additional options.
\image qtcreator-filesystem-view.png "File System view in the sidebar"
\else
The toolbar in the \uicontrol {File System} view contains additional
options.
\endif
To manage view contents, select \inlineimage filtericon.png
(\uicontrol Options):

View File

@@ -45,6 +45,9 @@
\uicontrol Design mode:
\image qtcreator-projects-view-design.png "Projects view in the Design mode"
\else
\image qtcreator-projects-view-edit.png "Projects view in the sidebar"
\endif
You can use the project tree in the following ways:
@@ -97,23 +100,29 @@
\li Expand or collapse the tree view to show or hide all files and
folders.
\li Close all files in a project.
\li Close projects. By default, all files in the project are also
\li Close the selected project or all projects except the selected
one. By default, all files in the projects are also
closed. To keep them open, deselect the \uicontrol Tools >
\uicontrol Options > \uicontrol {Build & Run} > \uicontrol General
> \uicontrol {Close source files along with project} check box.
\endlist
For managing files and directories, the same functions are available as in
the \l {File System} view.
the \l {File System} view. To view a project in it, select
\uicontrol {Show in File System View}.
\section1 Projects View in Sidebar
\endif
\section1 Projects View Toolbar
\if defined(qtdesignstudio)
In the \uicontrol Edit and \uicontrol Debug mode, the \uicontrol Projects
view is displayed in the \l{Working with Sidebars}{sidebar}. It has a
toolbar with additional options:
toolbar with additional options.
\image qtcreator-projects-view-edit.png "Projects view in the sidebar"
\else
The toolbar in the \uicontrol Projects view contains additional options.
\endif
To filter view contents, select \inlineimage filtericon.png
(\uicontrol {Filter Tree}):
@@ -141,9 +150,7 @@
(currently qmake and Qbs). The faithful display of the project structure
allows to specify exactly where a new file should be placed in the build
system.
\endif
\if defined(qtcreator)
If the project is under version control, information from the version
control system might be displayed in brackets after the project name.
This is currently implemented for Git (the branch name or a tag is

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -200,12 +200,7 @@
To create an arc with an outline, select the \uicontrol {Full outline}
check box. The \uicontrol {Outline width} field sets the width of
the arc outline, including the stroke. The \uicontrol {Outline start}
and \uicontrol {Outline end} fields set the width of the start and
end points of the outline separately. The width of the outline between
them is calculated automatically. You can adjust the inner and outer
curves of the outline in the \uicontrol {Inner radius} and
\uicontrol {Outer radius} fields.
the arc outline, including the stroke.
The \uicontrol {Round outline}, \uicontrol {Round start}, and
\uicontrol {Round end} properties specify whether the end points of the

View File

@@ -33,9 +33,18 @@ namespace QmlDesigner {
View3DActionCommand::View3DActionCommand(Type type, bool enable)
: m_type(type)
, m_enabled(enable)
, m_position(0)
{
}
View3DActionCommand::View3DActionCommand(int pos)
: m_type(ParticlesSeek)
, m_enabled(true)
, m_position(pos)
{
}
bool View3DActionCommand::isEnabled() const
{
return m_enabled;
@@ -46,10 +55,16 @@ View3DActionCommand::Type View3DActionCommand::type() const
return m_type;
}
int View3DActionCommand::position() const
{
return m_position;
}
QDataStream &operator<<(QDataStream &out, const View3DActionCommand &command)
{
out << qint32(command.isEnabled());
out << qint32(command.type());
out << qint32(command.position());
return out;
}
@@ -58,10 +73,13 @@ QDataStream &operator>>(QDataStream &in, View3DActionCommand &command)
{
qint32 enabled;
qint32 type;
qint32 pos;
in >> enabled;
in >> type;
in >> pos;
command.m_enabled = bool(enabled);
command.m_type = View3DActionCommand::Type(type);
command.m_position = pos;
return in;
}

View File

@@ -44,18 +44,34 @@ public:
CameraToggle,
OrientationToggle,
EditLightToggle,
ShowGrid
ShowGrid,
Edit3DParticleModeToggle,
ParticlesPlay,
ParticlesRestart,
ParticlesSeek,
};
explicit View3DActionCommand(Type type, bool enable);
View3DActionCommand() = default;
bool isEnabled() const;
Type type() const;
int position() const;
private:
Type m_type = Empty;
bool m_enabled = false;
int m_position = 0;
protected:
View3DActionCommand(int pos);
};
class View3DSeekActionCommand : public View3DActionCommand
{
public:
View3DSeekActionCommand(int pos) : View3DActionCommand(pos) {}
};
QDataStream &operator<<(QDataStream &out, const View3DActionCommand &command);

View File

@@ -0,0 +1,81 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "animationdriver.h"
#include "private/qabstractanimation_p.h"
AnimationDriver::AnimationDriver(QObject *parent)
: QAnimationDriver(parent)
{
setProperty("allowNegativeDelta", true);
install();
connect(this, SIGNAL(started()), this, SLOT(startTimer()));
connect(this, SIGNAL(stopped()), this, SLOT(stopTimer()));
}
AnimationDriver::~AnimationDriver()
{
}
void AnimationDriver::timerEvent(QTimerEvent *e)
{
Q_ASSERT(e->timerId() == m_timer.timerId());
Q_UNUSED(e);
quint32 old = elapsed();
// Provide same time for all users
if (m_seekerEnabled) {
m_seekerElapsed += (m_seekerPos * 100) / 30;
if (m_seekerElapsed + m_elapsed < -100) // -100 to allow small negative value
m_seekerElapsed = -m_elapsed - 100;
} else {
m_elapsed = QAnimationDriver::elapsed();
}
m_delta = elapsed() - old;
advance();
Q_EMIT advanced();
}
void AnimationDriver::startTimer()
{
m_timer.start(m_interval, Qt::PreciseTimer, this);
}
void AnimationDriver::stopTimer()
{
m_timer.stop();
}
void AnimationDriver::setSeekerPosition(int position)
{
if (!m_seekerEnabled)
return;
if (!m_timer.isActive())
restart();
m_seekerPos = position;
}

View File

@@ -0,0 +1,88 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <qabstractanimation.h>
#include <QtCore/qbasictimer.h>
#include <QtCore/qmath.h>
class AnimationDriver : public QAnimationDriver
{
Q_OBJECT
public:
AnimationDriver(QObject *parent = nullptr);
~AnimationDriver();
void timerEvent(QTimerEvent *e) override;
void setInterval(int interval)
{
m_interval = qBound(1, interval, 60);
}
int interval() const
{
return m_interval;
}
void reset()
{
stop();
stopTimer();
}
void restart()
{
start();
startTimer();
}
qint64 elapsed() const override
{
return m_elapsed + m_seekerElapsed;
}
void setSeekerPosition(int position);
void setSeekerEnabled(bool enable)
{
m_seekerEnabled = enable;
}
bool isSeekerEnabled() const
{
return m_seekerEnabled;
}
bool isAnimating() const
{
return (!m_seekerEnabled && m_timer.isActive()) || (m_seekerEnabled && m_delta && m_seekerPos);
}
Q_SIGNALS:
void advanced();
private:
Q_SLOT void startTimer();
Q_SLOT void stopTimer();
QBasicTimer m_timer;
int m_interval = 16;
int m_seekerPos = 0;
bool m_seekerEnabled = false;
qint64 m_elapsed = 0;
qint64 m_seekerElapsed = 0;
qint64 m_delta = 0;
};

View File

@@ -44,6 +44,8 @@ HEADERS += $$PWD/qt5nodeinstanceserver.h \
$$PWD/qt3dpresentationnodeinstance.h \
$$PWD/quick3dnodeinstance.h \
$$PWD/quick3dtexturenodeinstance.h \
$$PWD/viewconfig.h \
$$PWD/animationdriver.h
SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
@@ -74,4 +76,6 @@ SOURCES += $$PWD/qt5nodeinstanceserver.cpp \
$$PWD/layoutnodeinstance.cpp \
$$PWD/qt3dpresentationnodeinstance.cpp \
$$PWD/quick3dnodeinstance.cpp \
$$PWD/quick3dtexturenodeinstance.cpp
$$PWD/quick3dtexturenodeinstance.cpp \
$$PWD/viewconfig.cpp \
$$PWD/animationdriver.cpp

View File

@@ -332,6 +332,7 @@ void NodeInstanceServer::createScene(const CreateSceneCommand &command)
registerFonts(command.resourceUrl);
setTranslationLanguage(command.language);
if (!ViewConfig::isParticleViewMode())
Internal::QmlPrivateGate::stopUnifiedTimer();
setupScene(command);
@@ -783,6 +784,15 @@ QList<QQmlContext *> NodeInstanceServer::allSubContextsForObject(QObject *object
return contextList;
}
QList<QObject *> NodeInstanceServer::allSubObjectsForObject(QObject *object)
{
QList<QObject *> subChildren;
if (object)
subChildren = object->findChildren<QObject *>();
return subChildren;
}
void NodeInstanceServer::removeAllInstanceRelationships()
{
for (ServerNodeInstance &instance : m_objectInstanceHash) {
@@ -1563,4 +1573,39 @@ bool NodeInstanceServer::isInformationServer() const
return false;
}
static QString baseProperty(const QString &property)
{
int index = property.indexOf('.');
if (index > 0)
return property.left(index);
return property;
}
void NodeInstanceServer::addAnimation(QQuickAbstractAnimation *animation)
{
if (!m_animations.contains(animation)) {
m_animations.push_back(animation);
QQuickPropertyAnimation *panim = qobject_cast<QQuickPropertyAnimation *>(animation);
if (panim) {
QObject *target = panim->target();
QString property = panim->property();
QVariant value = target->property(qPrintable(baseProperty(property)));
m_defaultValues.push_back(value);
} else {
m_defaultValues.push_back({});
}
}
}
QVector<QQuickAbstractAnimation *> NodeInstanceServer::animations() const
{
return m_animations;
}
QVariant NodeInstanceServer::animationDefaultValue(int index) const
{
return m_defaultValues.at(index);
}
} // namespace QmlDesigner

View File

@@ -43,6 +43,20 @@
#include <nodeinstanceserverinterface.h>
#include "servernodeinstance.h"
#include "debugoutputcommand.h"
#include "viewconfig.h"
#include <private/qabstractanimation_p.h>
#include <private/qobject_p.h>
#include <private/qquickbehavior_p.h>
#include <private/qquicktext_p.h>
#include <private/qquicktextinput_p.h>
#include <private/qquicktextedit_p.h>
#include <private/qquicktransition_p.h>
#include <private/qquickloader_p.h>
#include <private/qquickanimation_p.h>
#include <private/qqmlmetatype_p.h>
#include <private/qqmltimer_p.h>
namespace QtHelpers {
template <class T>
@@ -217,6 +231,9 @@ public:
virtual QImage grabItem(QQuickItem *item) = 0;
virtual bool isInformationServer() const;
void addAnimation(QQuickAbstractAnimation *animation);
QVector<QQuickAbstractAnimation *> animations() const;
QVariant animationDefaultValue(int index) const;
public slots:
void refreshLocalFileProperty(const QString &path);
@@ -291,7 +308,8 @@ protected:
void setupDefaultDummyData();
QList<ServerNodeInstance> setupInstances(const CreateSceneCommand &command);
QList<QQmlContext *> allSubContextsForObject(QObject *object);
QList<QQmlContext*> allSubContextsForObject(QObject *object);
static QList<QObject*> allSubObjectsForObject(QObject *object);
virtual void resizeCanvasToRootItem() = 0;
void setupState(qint32 stateInstanceId);
@@ -322,6 +340,8 @@ private:
std::unique_ptr<MultiLanguage::Link> multilanguageLink;
int m_needsExtraRenderCount = 0;
int m_extraRenderCurrentPass = 0;
QVector<QQuickAbstractAnimation *> m_animations;
QVector<QVariant> m_defaultValues;
};
}

View File

@@ -87,6 +87,7 @@
#include <QQmlEngine>
#include <QtGui/qevent.h>
#include <QtGui/qguiapplication.h>
#include <QProcessEnvironment>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QtQuick/private/qquickrendercontrol_p.h>
@@ -103,10 +104,6 @@
#endif
#endif
#ifdef QUICK3D_PARTICLES_MODULE
#include <QtQuick3DParticles/private/qquick3dparticlesystem_p.h>
#endif
#ifdef IMPORT_QUICK3D_ASSETS
#include <QtQuick3DAssetImport/private/qssgassetimportmanager_p.h>
#endif
@@ -216,7 +213,7 @@ void Qt5InformationNodeInstanceServer::createAuxiliaryQuickView(const QUrl &url,
void Qt5InformationNodeInstanceServer::updateLockedAndHiddenStates(const QSet<ServerNodeInstance> &instances)
{
if (!isQuick3DMode())
if (!ViewConfig::isQuick3DMode())
return;
// We only want to update the topmost parents in the set
@@ -406,9 +403,83 @@ void Qt5InformationNodeInstanceServer::createEditView3D()
#endif
}
#ifdef QUICK3D_PARTICLES_MODULE
void Qt5InformationNodeInstanceServer::resetParticleSystem()
{
if (!m_targetParticleSystem)
return;
m_targetParticleSystem->reset();
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 2)
m_targetParticleSystem->setEditorTime(0);
#endif
if (m_particleAnimationDriver)
m_particleAnimationDriver->reset();
}
void Qt5InformationNodeInstanceServer::handleParticleSystemSelected(QQuick3DParticleSystem* targetParticleSystem)
{
if (!m_particleAnimationDriver)
return;
m_particleAnimationDriver->reset();
// stop the previously selected from animating
resetParticleSystem();
m_targetParticleSystem = targetParticleSystem;
resetParticleSystem();
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 2)
QObject::disconnect(m_particleAnimationConnection);
m_particleAnimationConnection = connect(m_particleAnimationDriver, &AnimationDriver::advanced, [this] () {
if (m_targetParticleSystem)
m_targetParticleSystem->setEditorTime(m_particleAnimationDriver->elapsed());
});
#endif
if (m_particleAnimationPlaying && m_targetParticleSystem->visible())
m_particleAnimationDriver->restart();
QObject::connect(m_targetParticleSystem, &QQuick3DNode::visibleChanged, [this] () {
if (m_particleAnimationPlaying && m_targetParticleSystem->visible()) {
m_particleAnimationDriver->restart();
} else {
m_particleAnimationDriver->reset();
resetParticleSystem();
}
});
const auto anim = animations();
for (auto a : anim)
a->restart();
}
static QString baseProperty(const QString &property)
{
int index = property.indexOf('.');
if (index > 0)
return property.left(index);
return property;
}
void Qt5InformationNodeInstanceServer::handleParticleSystemDeselected()
{
m_targetParticleSystem = nullptr;
const auto anim = animations();
int i = 0;
for (auto a : anim) {
a->stop();
QQuickPropertyAnimation *panim = qobject_cast<QQuickPropertyAnimation *>(a);
if (panim)
panim->target()->setProperty(qPrintable(baseProperty(panim->property())), animationDefaultValue(i));
i++;
}
}
#endif
// The selection has changed in the edit view 3D. Empty list indicates selection is cleared.
void Qt5InformationNodeInstanceServer::handleSelectionChanged(const QVariant &objs)
{
#ifdef QUICK3D_PARTICLES_MODULE
resetParticleSystem();
#endif
QList<ServerNodeInstance> instanceList;
const QVariantList varObjs = objs.value<QVariantList>();
for (const auto &object : varObjs) {
@@ -829,6 +900,12 @@ void Qt5InformationNodeInstanceServer::doRender3DEditView()
m_render3DEditViewTimer.start(0);
--m_need3DEditViewRender;
}
#ifdef QUICK3D_PARTICLES_MODULE
if (ViewConfig::isParticleViewMode()
&& m_particleAnimationDriver && m_particleAnimationDriver->isAnimating()) {
m_need3DEditViewRender++;
}
#endif
#ifdef FPS_COUNTER
// Force constant rendering for accurate fps count
if (!m_render3DEditViewTimer.isActive())
@@ -1084,6 +1161,12 @@ Qt5InformationNodeInstanceServer::Qt5InformationNodeInstanceServer(NodeInstanceC
_fpsTimer->start();
}
#endif
#ifdef QUICK3D_PARTICLES_MODULE
if (ViewConfig::isParticleViewMode()) {
m_particleAnimationDriver = new AnimationDriver(this);
m_particleAnimationDriver->setInterval(17);
}
#endif
}
Qt5InformationNodeInstanceServer::~Qt5InformationNodeInstanceServer()
@@ -1205,7 +1288,7 @@ QList<ServerNodeInstance> Qt5InformationNodeInstanceServer::createInstances(
void Qt5InformationNodeInstanceServer::initializeAuxiliaryViews()
{
#ifdef QUICK3D_MODULE
if (isQuick3DMode())
if (ViewConfig::isQuick3DMode())
createEditView3D();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
createAuxiliaryQuickView(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml"),
@@ -1665,7 +1748,7 @@ void Qt5InformationNodeInstanceServer::createScene(const CreateSceneCommand &com
sendChildrenChangedCommand(instanceList);
nodeInstanceClient()->componentCompleted(createComponentCompletedCommand(instanceList));
if (isQuick3DMode()) {
if (ViewConfig::isQuick3DMode()) {
setup3DEditView(instanceList, command.edit3dToolStates);
updateRotationBlocks(command.auxiliaryChanges);
}
@@ -1735,7 +1818,9 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
{
if (!m_editView3DSetupDone)
return;
#ifdef QUICK3D_PARTICLES_MODULE
resetParticleSystem();
#endif
m_lastSelectionChangeCommand = command;
if (m_selectionChangeTimer.isActive()) {
// If selection was recently changed by puppet, hold updating the selection for a bit to
@@ -1762,13 +1847,17 @@ void Qt5InformationNodeInstanceServer::changeSelection(const ChangeSelectionComm
if (firstSceneRoot && sceneRoot == firstSceneRoot && instance.isSubclassOf("QQuick3DNode"))
object = instance.internalObject();
#ifdef QUICK3D_PARTICLES_MODULE
auto particlesystem = qobject_cast<QQuick3DParticleSystem *>(instance.internalObject());
if (particlesystem)
handleParticleSystemSelected(particlesystem);
else
handleParticleSystemDeselected();
#endif
auto isSelectableAsRoot = [&]() -> bool {
#ifdef QUICK3D_MODULE
if (qobject_cast<QQuick3DModel *>(object)
|| qobject_cast<QQuick3DCamera *>(object)
#ifdef QUICK3D_PARTICLES_MODULE
|| qobject_cast<QQuick3DParticleSystem *>(object)
#endif
|| qobject_cast<QQuick3DAbstractLight *>(object)) {
return true;
}
@@ -1900,6 +1989,33 @@ void Qt5InformationNodeInstanceServer::view3DAction(const View3DActionCommand &c
case View3DActionCommand::ShowGrid:
updatedState.insert("showGrid", command.isEnabled());
break;
#ifdef QUICK3D_PARTICLES_MODULE
case View3DActionCommand::Edit3DParticleModeToggle:
updatedState.insert("enableParticleViewMode", command.isEnabled());
break;
case View3DActionCommand::ParticlesPlay:
m_particleAnimationPlaying = command.isEnabled();
if (m_particleAnimationPlaying) {
m_particleAnimationDriver->reset();
m_particleAnimationDriver->restart();
m_particleAnimationDriver->setSeekerEnabled(false);
m_particleAnimationDriver->setSeekerPosition(0);
} else {
m_particleAnimationDriver->reset();
m_particleAnimationDriver->setSeekerEnabled(true);
}
break;
case View3DActionCommand::ParticlesRestart:
resetParticleSystem();
m_particleAnimationPlaying = true;
m_particleAnimationDriver->restart();
m_particleAnimationDriver->setSeekerEnabled(false);
m_particleAnimationDriver->setSeekerPosition(0);
break;
case View3DActionCommand::ParticlesSeek:
m_particleAnimationDriver->setSeekerPosition(static_cast<const View3DSeekActionCommand &>(command).position());
break;
#endif
default:
break;
}
@@ -1977,7 +2093,7 @@ void Qt5InformationNodeInstanceServer::handleInstanceLocked(const ServerNodeInst
bool enable, bool checkAncestors)
{
#ifdef QUICK3D_MODULE
if (!isQuick3DMode())
if (!ViewConfig::isQuick3DMode())
return;
bool edit3dLocked = enable;
@@ -2015,7 +2131,7 @@ void Qt5InformationNodeInstanceServer::handleInstanceHidden(const ServerNodeInst
bool enable, bool checkAncestors)
{
#ifdef QUICK3D_MODULE
if (!isQuick3DMode())
if (!ViewConfig::isQuick3DMode())
return;
bool edit3dHidden = enable;

View File

@@ -32,8 +32,14 @@
#include "requestmodelnodepreviewimagecommand.h"
#include "propertybindingcontainer.h"
#include "propertyabstractcontainer.h"
#include "animationdriver.h"
#ifdef QUICK3D_PARTICLES_MODULE
#include <QtQuick3DParticles/private/qquick3dparticlesystem_p.h>
#endif
#include <QTimer>
#include <QElapsedTimer>
#include <QVariant>
#include <QPointer>
#include <QImage>
@@ -140,6 +146,11 @@ private:
void removeRotationBlocks(const QVector<qint32> &instanceIds);
void createAuxiliaryQuickView(const QUrl &url, RenderViewData &viewData);
#ifdef QUICK3D_PARTICLES_MODULE
void handleParticleSystemSelected(QQuick3DParticleSystem* targetParticleSystem);
void resetParticleSystem();
void handleParticleSystemDeselected();
#endif
RenderViewData m_editView3DData;
RenderViewData m_modelNode3DImageViewData;
@@ -161,6 +172,12 @@ private:
QTimer m_render3DEditViewTimer;
QTimer m_renderModelNodeImageViewTimer;
QTimer m_inputEventTimer;
#ifdef QUICK3D_PARTICLES_MODULE
bool m_particleAnimationPlaying = true;
AnimationDriver *m_particleAnimationDriver = nullptr;
QMetaObject::Connection m_particleAnimationConnection;
QQuick3DParticleSystem* m_targetParticleSystem = nullptr;
#endif
QObjectList m_changedNodes;
QList<PropertyName> m_changedProperties;
ChangeSelectionCommand m_lastSelectionChangeCommand;

View File

@@ -82,6 +82,7 @@ Qt5NodeInstanceClientProxy::Qt5NodeInstanceClientProxy(QObject *parent) :
setNodeInstanceServer(std::make_unique<Qt5PreviewNodeInstanceServer>(this));
initializeSocket();
} else if (QCoreApplication::arguments().at(2) == QLatin1String("editormode")) {
ViewConfig::enableParticleView(true);
setNodeInstanceServer(std::make_unique<Qt5InformationNodeInstanceServer>(this));
initializeSocket();
} else if (QCoreApplication::arguments().at(2) == QLatin1String("rendermode")) {

View File

@@ -60,6 +60,7 @@ namespace QmlDesigner {
Qt5NodeInstanceServer::Qt5NodeInstanceServer(NodeInstanceClientInterface *nodeInstanceClient)
: NodeInstanceServer(nodeInstanceClient)
{
if (!ViewConfig::isParticleViewMode())
DesignerSupport::activateDesignerMode();
}

View File

@@ -0,0 +1,45 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "viewconfig.h"
#include <QtGlobal>
bool ViewConfig::isQuick3DMode()
{
static bool mode3D = qEnvironmentVariableIsSet("QMLDESIGNER_QUICK3D_MODE");
return mode3D;
}
static bool particleViewEnabled = false;
void ViewConfig::enableParticleView(bool enable)
{
particleViewEnabled = enable;
}
bool ViewConfig::isParticleViewMode()
{
static bool particleviewmode = !qEnvironmentVariableIsSet("QT_QUICK3D_DISABLE_PARTICLE_SYSTEMS");
return particleviewmode && particleViewEnabled;
}

View File

@@ -0,0 +1,34 @@
/****************************************************************************
**
** Copyright (C) 2021 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
class ViewConfig
{
public:
static bool isQuick3DMode();
static void enableParticleView(bool enable);
static bool isParticleViewMode();
};

View File

@@ -34,6 +34,7 @@
#include <QQuickItem>
#include <QQmlComponent>
#include <QFileInfo>
#include <QProcessEnvironment>
#include <private/qabstractfileengine_p.h>
#include <private/qfsfileengine_p.h>
@@ -47,6 +48,19 @@
#include <private/qqmldata_p.h>
#include <private/qqmlcomponentattached_p.h>
#include <private/qabstractanimation_p.h>
#include <private/qobject_p.h>
#include <private/qquickbehavior_p.h>
#include <private/qquicktext_p.h>
#include <private/qquicktextinput_p.h>
#include <private/qquicktextedit_p.h>
#include <private/qquicktransition_p.h>
#include <private/qquickloader_p.h>
#include <private/qquickanimation_p.h>
#include <private/qqmlmetatype_p.h>
#include <private/qqmltimer_p.h>
namespace QmlDesigner {
namespace Internal {
@@ -382,8 +396,15 @@ void doComponentCompleteRecursive(QObject *object, NodeInstanceServer *nodeInsta
static_cast<QQmlParserStatus *>(item)->componentComplete();
} else {
QQmlParserStatus *qmlParserStatus = dynamic_cast<QQmlParserStatus *>(object);
if (qmlParserStatus)
if (qmlParserStatus) {
qmlParserStatus->componentComplete();
auto *anim = dynamic_cast<QQuickAbstractAnimation *>(object);
if (anim && ViewConfig::isParticleViewMode()) {
nodeInstanceServer->addAnimation(anim);
anim->setEnableUserControl();
anim->stop();
}
}
}
}
}

View File

@@ -116,7 +116,7 @@ Item {
text: qsTr("Remove Module")
visible: itemsView.currentCategory === null
height: visible ? implicitHeight : 0
enabled: itemsView.importToRemove !== ""
enabled: itemsView.importToRemove !== "" && !rootView.subCompEditMode
onTriggered: rootView.removeImport(itemsView.importToRemove)
}

View File

@@ -93,8 +93,10 @@ Item {
anchors.topMargin: 1
width: 24
height: 24
color: mouseArea.containsMouse ? StudioTheme.Values.themeControlBackgroundHover
color: mouseArea.containsMouse && enabled
? StudioTheme.Values.themeControlBackgroundHover
: StudioTheme.Values.themeControlBackground
enabled: index !== 0 || !rootView.subCompEditMode
Label { // + sign
text: StudioTheme.Constants.plus

View File

@@ -162,10 +162,17 @@ QtObject {
readonly property string visibilityOff: "\u009D" // visibilityOff2
readonly property string visibilityOn: "\u009E"
readonly property string wildcard: "\u009F"
readonly property string zoomAll: "\u00A0"
readonly property string zoomIn: "\u00A1"
readonly property string zoomOut: "\u00A2"
readonly property string zoomSelection: "\u00A3"
readonly property string wizardsAutomotive: "\u00A0"
readonly property string wizardsDesktop: "\u00A1"
readonly property string wizardsGeneric: "\u00A2"
readonly property string wizardsMcuEmpty: "\u00A3"
readonly property string wizardsMcuGraph: "\u00A4"
readonly property string wizardsMobile: "\u00A5"
readonly property string wizardsUnknown: "\u00A6"
readonly property string zoomAll: "\u00A7"
readonly property string zoomIn: "\u00A8"
readonly property string zoomOut: "\u00A9"
readonly property string zoomSelection: "\u00AA"
readonly property font iconFont: Qt.font({
"family": controlIcons.name,

View File

@@ -47,5 +47,17 @@ QDebug operator<<(QDebug debug, const DiagnosticContainer &container)
return debug;
}
QDebug operator<<(QDebug debug, const QVector<DiagnosticContainer> &containers)
{
debug.nospace() << "{";
for (int i = 0; i < containers.size(); i++) {
debug.nospace() << containers[i];
if (i < containers.size() - 1)
debug.nospace() << ", ";
}
debug.nospace() << "}";
return debug;
}
} // namespace ClangBackEnd

View File

@@ -123,5 +123,8 @@ public:
};
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const DiagnosticContainer &container);
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QVector<DiagnosticContainer> &container);
} // namespace ClangBackEnd

View File

@@ -39,5 +39,17 @@ QDebug operator<<(QDebug debug, const FixItContainer &container)
return debug;
}
QDebug operator<<(QDebug debug, const QVector<FixItContainer> &containers)
{
debug.nospace() << "{";
for (int i = 0; i < containers.size(); i++) {
debug.nospace() << containers[i];
if (i < containers.size() - 1)
debug.nospace() << ", ";
}
debug.nospace() << "}";
return debug;
}
} // namespace ClangBackEnd

View File

@@ -69,5 +69,6 @@ public:
};
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const FixItContainer &container);
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QVector<FixItContainer> &container);
} // namespace ClangBackEnd

View File

@@ -39,4 +39,16 @@ QDebug operator<<(QDebug debug, const SourceRangeContainer &container)
return debug;
}
QDebug operator<<(QDebug debug, const QVector<SourceRangeContainer> &containers)
{
debug.nospace() << "{";
for (int i = 0; i < containers.size(); i++) {
debug.nospace() << containers[i];
if (i < containers.size() - 1)
debug.nospace() << ", ";
}
debug.nospace() << "}";
return debug;
}
} // namespace ClangBackEnd

View File

@@ -85,5 +85,6 @@ public:
};
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const SourceRangeContainer &container);
CLANGSUPPORT_EXPORT QDebug operator<<(QDebug debug, const QVector<SourceRangeContainer> &container);
} // namespace ClangBackEnd

View File

@@ -1275,6 +1275,9 @@ static bool isIntegerValue(const Value *value)
static bool strictCompareConstant(const Value *lhs, const Value *rhs)
{
// attached properties and working at runtime cases may be undefined at evaluation time
if (lhs->asUndefinedValue() || rhs->asUndefinedValue())
return false;
if (lhs->asUnknownValue() || rhs->asUnknownValue())
return false;
if (lhs->asFunctionValue() || rhs->asFunctionValue()) // function evaluation not implemented
@@ -1283,12 +1286,11 @@ static bool strictCompareConstant(const Value *lhs, const Value *rhs)
return false;
if (lhs->asBooleanValue() && !rhs->asBooleanValue())
return true;
// attached properties and working at runtime cases may be undefined at evaluation time
if (lhs->asNumberValue() && (!rhs->asNumberValue() && !rhs->asUndefinedValue()))
if (lhs->asNumberValue() && !rhs->asNumberValue())
return true;
if (lhs->asStringValue() && !rhs->asStringValue())
return true;
if (lhs->asObjectValue() && (!rhs->asObjectValue() || !rhs->asNullValue() || !rhs->asUndefinedValue()))
if (lhs->asObjectValue() && (!rhs->asObjectValue() || !rhs->asNullValue()))
return true;
return false;
}

View File

@@ -30,7 +30,6 @@
#include "qtcassert.h"
#include <QCoreApplication>
#include <QElapsedTimer>
#include <QLocalSocket>
#include <QMutexLocker>
@@ -542,14 +541,11 @@ bool CallerHandle::isCalledFromLaunchersThread() const
bool LauncherHandle::waitForSignal(int msecs, CallerHandle::SignalType newSignal)
{
QTC_ASSERT(!isCalledFromLaunchersThread(), return false);
QElapsedTimer timer;
timer.start();
QDeadlineTimer deadline(msecs);
while (true) {
const int remainingMsecs = msecs - timer.elapsed();
if (remainingMsecs <= 0)
if (deadline.hasExpired())
break;
const bool timedOut = !doWaitForSignal(qMax(remainingMsecs, 0), newSignal);
if (timedOut)
if (!doWaitForSignal(deadline, newSignal))
break;
m_awaitingShouldContinue = true; // TODO: make it recursive?
const QList<CallerHandle::SignalType> flushedSignals = m_callerHandle->flushFor(newSignal);
@@ -563,14 +559,12 @@ bool LauncherHandle::waitForSignal(int msecs, CallerHandle::SignalType newSignal
return true;
if (wasCanceled)
return true; // or false? is false only in case of timeout?
if (timer.hasExpired(msecs))
break;
}
return false;
}
// Called from caller's thread exclusively.
bool LauncherHandle::doWaitForSignal(int msecs, CallerHandle::SignalType newSignal)
bool LauncherHandle::doWaitForSignal(QDeadlineTimer deadline, CallerHandle::SignalType newSignal)
{
QMutexLocker locker(&m_mutex);
QTC_ASSERT(isCalledFromCallersThread(), return false);
@@ -585,7 +579,7 @@ bool LauncherHandle::doWaitForSignal(int msecs, CallerHandle::SignalType newSign
return true;
m_waitingFor = newSignal;
const bool ret = m_waitCondition.wait(&m_mutex, msecs);
const bool ret = m_waitCondition.wait(&m_mutex, deadline);
m_waitingFor = CallerHandle::SignalType::NoSignal;
return ret;
}

View File

@@ -28,6 +28,7 @@
#include "launcherpackets.h"
#include "processutils.h"
#include <QDeadlineTimer>
#include <QHash>
#include <QMutex>
#include <QObject>
@@ -213,7 +214,7 @@ public:
private:
// Called from caller's thread exclusively.
bool doWaitForSignal(int msecs, CallerHandle::SignalType newSignal);
bool doWaitForSignal(QDeadlineTimer deadline, CallerHandle::SignalType newSignal);
// Called from launcher's thread exclusively. Call me with mutex locked.
void wakeUpIfWaitingFor(CallerHandle::SignalType newSignal);

View File

@@ -294,7 +294,7 @@ static QTextLine currentTextLine(const QTextCursor &cursor)
return layout->lineForTextPosition(relativePos);
}
bool multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey)
bool MultiTextCursor::multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey)
{
uint searchkey = (e->modifiers() | e->key())
& ~(Qt::KeypadModifier

View File

@@ -27,6 +27,7 @@
#include "utils_global.h"
#include <QKeySequence>
#include <QTextCursor>
QT_BEGIN_NAMESPACE
@@ -99,6 +100,8 @@ public:
const_iterator constBegin() const { return m_cursors.constBegin(); }
const_iterator constEnd() const { return m_cursors.constEnd(); }
static bool multiCursorAddEvent(QKeyEvent *e, QKeySequence::StandardKey matchKey);
private:
QList<QTextCursor> m_cursors;
};

View File

@@ -847,7 +847,7 @@ bool AndroidConfig::isValidNdk(const QString &ndkLocation) const
return false;
const QVersionNumber version = ndkVersion(ndkPath);
if (ndkVersion(ndkPath).isNull())
if (version.isNull())
return false;
const FilePath ndkPlatformsDir = ndkPath.pathAppended("platforms");

View File

@@ -81,12 +81,12 @@ using namespace Android::Internal;
namespace Android {
const QLatin1String AndroidManifestName("AndroidManifest.xml");
const QLatin1String AndroidDeviceSn("AndroidDeviceSerialNumber");
const QLatin1String AndroidDeviceAbis("AndroidDeviceAbis");
const QLatin1String ApiLevelKey("AndroidVersion.ApiLevel");
const char qtcSignature[] = "This file is generated by QtCreator to be read by androiddeployqt "
"and should not be modified by hand.";
const char AndroidManifestName[] = "AndroidManifest.xml";
const char AndroidDeviceSn[] = "AndroidDeviceSerialNumber";
const char AndroidDeviceAbis[] = "AndroidDeviceAbis";
const char ApiLevelKey[] = "AndroidVersion.ApiLevel";
const char qtcSignature[] = "This file is generated by QtCreator to be read by "
"androiddeployqt and should not be modified by hand.";
static Q_LOGGING_CATEGORY(androidManagerLog, "qtc.android.androidManager", QtWarningMsg)
@@ -132,7 +132,8 @@ QString AndroidManager::activityName(const Target *target)
QDomDocument doc;
if (!openManifest(target, doc))
return QString();
QDomElement activityElem = doc.documentElement().firstChildElement(QLatin1String("application")).firstChildElement(QLatin1String("activity"));
QDomElement activityElem = doc.documentElement().firstChildElement(
QLatin1String("application")).firstChildElement(QLatin1String("activity"));
return activityElem.attribute(QLatin1String("android:name"));
}
@@ -418,17 +419,18 @@ static QString preferredAbi(const QStringList &appAbis, const Target *target)
QString AndroidManager::apkDevicePreferredAbi(const Target *target)
{
auto libsPath = androidBuildDirectory(target).pathAppended("libs");
const FilePath libsPath = androidBuildDirectory(target).pathAppended("libs");
if (!libsPath.exists()) {
if (const ProjectNode *node = currentProjectNode(target))
return preferredAbi(node->data(Android::Constants::AndroidAbis).toStringList(),
target);
}
QStringList apkAbis;
const auto libsPaths = QDir{libsPath.toString()}.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const auto &abi : libsPaths)
if (!QDir{libsPath.pathAppended(abi).toString()}.entryList(QStringList("*.so"), QDir::Files | QDir::NoDotAndDotDot).isEmpty())
apkAbis << abi;
const FilePaths libsPaths = libsPath.dirEntries(QDir::Dirs | QDir::NoDotAndDotDot);
for (const FilePath &abiDir : libsPaths) {
if (!abiDir.dirEntries(QStringList("*.so"), QDir::Files | QDir::NoDotAndDotDot).isEmpty())
apkAbis << abiDir.fileName();
}
return preferredAbi(apkAbis, target);
}

View File

@@ -195,7 +195,9 @@ static FilePath debugServer(bool useLldb, const Target *target)
const QString abiNeedle = lldbServerArch2(preferredAbi);
// The new, built-in LLDB.
QDirIterator it(prebuilt.toString(), QDir::Files|QDir::Executable, QDirIterator::Subdirectories);
const QDir::Filters dirFilter = HostOsInfo::isWindowsHost() ? QDir::Files
: QDir::Files|QDir::Executable;
QDirIterator it(prebuilt.toString(), dirFilter, QDirIterator::Subdirectories);
while (it.hasNext()) {
it.next();
const QString filePath = it.filePath();

View File

@@ -928,6 +928,7 @@ public:
m_started = false;
qCDebug(clangdLogTiming).noquote().nospace() << m_task << ": took " << m_elapsedMs
<< " ms in UI thread";
m_elapsedMs = 0;
}
void startSubtask()
{

View File

@@ -168,7 +168,7 @@ static FilePath qmakeFromCMakeCache(const CMakeConfig &config)
"project(qmake-probe LANGUAGES NONE)\n"
"\n"
"# Bypass Qt6's usage of find_dependency, which would require compiler\n"
"# and source code probing, which slows things unnecessarily"
"# and source code probing, which slows things unnecessarily\n"
"file(WRITE \"${CMAKE_SOURCE_DIR}/CMakeFindDependencyMacro.cmake\"\n"
"[=["
" macro(find_dependency dep)\n"

View File

@@ -255,15 +255,16 @@ ClangdSettingsWidget::ClangdSettingsWidget(const ClangdSettings::Data &settingsD
layout->addLayout(formLayout);
layout->addStretch(1);
const auto toggleEnabled = [=](const bool checked) {
chooserLabel->setEnabled(checked);
d->clangdChooser.setEnabled(checked);
indexingLabel->setEnabled(checked);
d->indexingCheckBox.setEnabled(checked);
autoIncludeHeadersLabel->setEnabled(checked);
d->autoIncludeHeadersCheckBox.setEnabled(checked);
d->threadLimitSpinBox.setEnabled(checked);
d->versionWarningLabel.setEnabled(checked);
static const auto setWidgetsEnabled = [](QLayout *layout, bool enabled, const auto &f) -> void {
for (int i = 0; i < layout->count(); ++i) {
if (QWidget * const w = layout->itemAt(i)->widget())
w->setEnabled(enabled);
else if (QLayout * const l = layout->itemAt(i)->layout())
f(l, enabled, f);
}
};
const auto toggleEnabled = [formLayout](const bool checked) {
setWidgetsEnabled(formLayout, checked, setWidgetsEnabled);
};
connect(&d->useClangdCheckBox, &QCheckBox::toggled, toggleEnabled);
toggleEnabled(d->useClangdCheckBox.isChecked());

View File

@@ -213,7 +213,15 @@ void LldbEngine::setupEngine()
showMessage("STARTING LLDB: " + lldbCmd.toUserOutput());
Environment environment = runParameters().debugger.environment;
environment.appendOrSet("PYTHONUNBUFFERED", "1"); // avoid flushing problem on macOS
if (lldbCmd.path().contains("/ndk-bundle/")) {
FilePath androidPythonDir = lldbCmd.parentDir().parentDir().pathAppended("python3");
if (HostOsInfo::isAnyUnixHost())
androidPythonDir = androidPythonDir.pathAppended("bin");
if (androidPythonDir.exists())
environment.prependOrSetPath(androidPythonDir.path());
}
m_lldbProc.setEnvironment(environment);
if (runParameters().debugger.workingDirectory.isDir())
m_lldbProc.setWorkingDirectory(runParameters().debugger.workingDirectory);

View File

@@ -49,12 +49,7 @@ extend_qtc_plugin(Help
macwebkithelpviewer.mm
)
set(BUILD_HELPVIEWERBACKEND_QTWEBENGINE_DEFAULT YES)
if (Qt6_FOUND)
set(BUILD_HELPVIEWERBACKEND_QTWEBENGINE_DEFAULT NO)
endif ()
option(BUILD_HELPVIEWERBACKEND_QTWEBENGINE "Build QtWebEngine based help viewer backend." ${BUILD_HELPVIEWERBACKEND_QTWEBENGINE_DEFAULT})
option(BUILD_HELPVIEWERBACKEND_QTWEBENGINE "Build QtWebEngine based help viewer backend." YES)
find_package(Qt5 COMPONENTS WebEngineWidgets QUIET)
extend_qtc_plugin(Help
CONDITION BUILD_HELPVIEWERBACKEND_QTWEBENGINE AND TARGET Qt5::WebEngineWidgets

View File

@@ -37,7 +37,11 @@
#include <QDesktopServices>
#include <QTimer>
#include <QVBoxLayout>
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
#include <QWebEngineContextMenuRequest>
#else
#include <QWebEngineContextMenuData>
#endif
#include <QWebEngineHistory>
#include <QWebEngineProfile>
#include <QWebEngineSettings>
@@ -335,7 +339,11 @@ bool WebView::eventFilter(QObject *src, QEvent *e)
void WebView::contextMenuEvent(QContextMenuEvent *event)
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
QMenu *menu = createStandardContextMenu();
#else
QMenu *menu = page()->createStandardContextMenu();
#endif
// insert Open as New Page etc if OpenLinkInThisWindow is also there
const QList<QAction*> actions = menu->actions();
auto it = std::find(actions.cbegin(), actions.cend(),
@@ -344,7 +352,11 @@ void WebView::contextMenuEvent(QContextMenuEvent *event)
// insert after
++it;
QAction *before = (it == actions.cend() ? 0 : *it);
#if QT_VERSION >= QT_VERSION_CHECK(6, 2, 0)
QUrl url = lastContextMenuRequest()->linkUrl();
#else
QUrl url = page()->contextMenuData().linkUrl();
#endif
if (m_viewer->isActionVisible(HelpViewer::Action::NewPage)) {
auto openLink = new QAction(QCoreApplication::translate("HelpViewer",
Constants::TR_OPEN_LINK_AS_NEW_PAGE), menu);

View File

@@ -494,6 +494,11 @@ void JsonWizardFactory::addWizardPath(const FilePath &path)
searchPaths().append(path);
}
void JsonWizardFactory::clearWizardPaths()
{
searchPaths().clear();
}
void JsonWizardFactory::setVerbose(int level)
{
m_verbose = level;

View File

@@ -51,6 +51,7 @@ class PROJECTEXPLORER_EXPORT JsonWizardFactory : public Core::IWizardFactory
public:
// Add search paths for wizard.json files. All subdirs are going to be checked.
static void addWizardPath(const Utils::FilePath &path);
static void clearWizardPaths();
// actual interface of the wizard factory:
class Generator {

View File

@@ -4,7 +4,7 @@ if (APPLE)
endif()
add_qtc_plugin(QmlDesigner
CONDITION TARGET Qt5::QuickWidgets
CONDITION TARGET Qt5::QuickWidgets AND TARGET Qt5::Svg
DEPENDS
QmlJS LanguageUtils QmlEditorWidgets AdvancedDockingSystem
Qt5::QuickWidgets Qt5::CorePrivate Sqlite Qt5::Xml Qt5::Svg
@@ -27,6 +27,7 @@ add_qtc_plugin(QmlDesigner
designmodewidget.cpp designmodewidget.h
documentmanager.cpp documentmanager.h
documentwarningwidget.cpp documentwarningwidget.h
cmakegeneratordialog.h cmakegeneratordialog.cpp
generateresource.cpp generateresource.h
generatecmakelists.cpp generatecmakelists.h
openuiqmlfiledialog.cpp openuiqmlfiledialog.h openuiqmlfiledialog.ui
@@ -201,6 +202,7 @@ extend_qtc_plugin(QmlDesigner
rubberbandselectionmanipulator.cpp rubberbandselectionmanipulator.h
scaleitem.cpp scaleitem.h
scalemanipulator.cpp scalemanipulator.h
seekerslider.cpp seekerslider.h
selectionindicator.cpp selectionindicator.h
selectionrectangle.cpp selectionrectangle.h
selectiontool.cpp selectiontool.h

View File

@@ -0,0 +1,154 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Tooling
**
** 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 "cmakegeneratordialog.h"
#include <QDialogButtonBox>
#include <QPushButton>
#include <QLayout>
#include <QLabel>
#include <QListView>
using namespace Utils;
namespace QmlDesigner {
namespace GenerateCmake {
CmakeGeneratorDialog::CmakeGeneratorDialog(const FilePath &rootDir, const FilePaths &files)
: QDialog()
{
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
auto *okButton = buttons->button(QDialogButtonBox::Ok);
okButton->setDefault(true);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
model = new CheckableFileListModel(rootDir, files, this);
QListView *list = new QListView(this);
list->setModel(model);
layout->addWidget(list);
layout->addWidget(buttons);
}
FilePaths CmakeGeneratorDialog::getFilePaths()
{
FilePaths paths;
QList<CheckableStandardItem*> items = model->checkedItems();
for (CheckableStandardItem *item: items) {
paths.append(FilePath::fromString(item->text()));
}
return paths;
}
CheckableFileListModel::CheckableFileListModel(const FilePath &rootDir, const FilePaths &files, QObject *parent)
:QStandardItemModel(parent),
rootDir(rootDir)
{
for (const FilePath &file: files) {
appendRow(new CheckableStandardItem(file.toString(), true));
}
}
QList<CheckableStandardItem*> CheckableFileListModel::checkedItems() const
{
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
QList<QStandardItem*> allItems = findItems("*", Qt::MatchWildcard);
#else
QList<QStandardItem*> allItems = findItems(".*", Qt::MatchRegularExpression);
#endif
QList<CheckableStandardItem*> checkedItems;
for (QStandardItem *standardItem : allItems) {
CheckableStandardItem *item = static_cast<CheckableStandardItem*>(standardItem);
if (item->isChecked())
checkedItems.append(item);
}
return checkedItems;
}
CheckableStandardItem::CheckableStandardItem(const QString &text, bool checked)
:QStandardItem(text),
checked(checked)
{
setFlags(flags() |= Qt::ItemIsUserCheckable);
}
void CheckableStandardItem::setChecked(bool checked)
{
this->checked = checked;
}
bool CheckableStandardItem::isChecked() const
{
return this->checked;
}
int CheckableStandardItem::type() const
{
return QStandardItem::UserType + 0x74d4f1;
}
QVariant CheckableFileListModel::data(const QModelIndex &index, int role) const
{
if (index.isValid()) {
if (role == Qt::CheckStateRole) {
CheckableStandardItem *item = static_cast<CheckableStandardItem*>(QStandardItemModel::item(index.row()));
return item->isChecked() ? Qt::Checked : Qt::Unchecked;
}
else if (role == Qt::DisplayRole) {
QVariant data = QStandardItemModel::data(index, role);
QString relativePath = data.toString().remove(rootDir.toString());
return QVariant(relativePath);
}
}
return QStandardItemModel::data(index, role);
}
bool CheckableFileListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (index.isValid() && role == Qt::CheckStateRole)
{
CheckableStandardItem *item = static_cast<CheckableStandardItem*>(QStandardItemModel::item(index.row()));
item->setChecked(value.value<bool>());
return true;
}
return QStandardItemModel::setData(index, value, role);
}
}
}

View File

@@ -0,0 +1,77 @@
/****************************************************************************
**
** Copyright (C) 2021 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the Qt Design Tooling
**
** 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.
**
****************************************************************************/
#ifndef CMAKEGENERATORDIALOG_H
#define CMAKEGENERATORDIALOG_H
#include <utils/fileutils.h>
#include <QDialog>
#include <QStandardItemModel>
namespace QmlDesigner {
namespace GenerateCmake {
class CheckableStandardItem : public QStandardItem
{
public:
explicit CheckableStandardItem(const QString &text = QString(), bool checked = false);
bool isChecked() const;
void setChecked(bool checked);
int type() const;
private:
bool checked;
};
class CheckableFileListModel : public QStandardItemModel
{
public:
CheckableFileListModel(const Utils::FilePath &rootDir, const Utils::FilePaths &files, QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role) const;
bool setData(const QModelIndex &index, const QVariant &value, int role);
QList<CheckableStandardItem*> checkedItems() const;
private:
Utils::FilePath rootDir;
};
class CmakeGeneratorDialog : public QDialog
{
public:
CmakeGeneratorDialog(const Utils::FilePath &rootDir, const Utils::FilePaths &files);
Utils::FilePaths getFilePaths();
private:
CheckableFileListModel *model;
};
}
}
Q_DECLARE_METATYPE(QmlDesigner::GenerateCmake::CheckableStandardItem)
#endif // CMAKEGENERATORDIALOG_H

View File

@@ -170,6 +170,13 @@ public:
visibilityOff, // visibilityOff2
visibilityOn,
wildcard,
wizardsAutomotive,
wizardsDesktop,
wizardsGeneric,
wizardsMcuEmpty,
wizardsMcuGraph,
wizardsMobile,
wizardsUnknown,
zoomAll,
zoomIn,
zoomOut,

View File

@@ -34,5 +34,15 @@
<file>images/select_item@2x.png</file>
<file>images/orthographic_camera.png</file>
<file>images/orthographic_camera@2x.png</file>
<file>images/particles_off.png</file>
<file>images/particles_off@2x.png</file>
<file>images/particles_on.png</file>
<file>images/particles_on@2x.png</file>
<file>images/particles_play.png</file>
<file>images/particles_play@2x.png</file>
<file>images/particles_pause.png</file>
<file>images/particles_pause@2x.png</file>
<file>images/particles_restart.png</file>
<file>images/particles_restart@2x.png</file>
</qresource>
</RCC>

View File

@@ -33,6 +33,7 @@
#include <designeractionmanager.h>
#include <designersettings.h>
#include <qmldesignerconstants.h>
#include <qmldesignerplugin.h>
#include <viewmanager.h>
#include <qmldesignericons.h>
#include <designmodecontext.h>
@@ -209,6 +210,11 @@ QSize Edit3DView::canvasSize() const
return {};
}
void Edit3DView::setSeeker(SeekerSlider *slider)
{
m_seeker = slider;
}
void Edit3DView::createEdit3DActions()
{
m_selectionModeAction
@@ -272,9 +278,59 @@ void Edit3DView::createEdit3DActions()
Icons::EDIT3D_GRID_ON.icon());
SelectionContextOperation resetTrigger = [this](const SelectionContext &) {
m_particlesPlayAction->action()->setEnabled(particlemode);
m_particlesRestartAction->action()->setEnabled(particlemode);
if (particlemode)
m_particlesPlayAction->action()->setChecked(true);
if (m_seeker)
m_seeker->setEnabled(false);
setCurrentStateNode(rootModelNode());
resetPuppet();
};
SelectionContextOperation particlesTrigger = [this](const SelectionContext &) {
particlemode = !particlemode;
m_particlesPlayAction->action()->setEnabled(particlemode);
m_particlesRestartAction->action()->setEnabled(particlemode);
if (m_seeker)
m_seeker->setEnabled(false);
QmlDesigner::DesignerSettings::setValue("particleMode", particlemode);
setCurrentStateNode(rootModelNode());
resetPuppet();
};
SelectionContextOperation particlesRestartTrigger = [this](const SelectionContext &) {
m_particlesPlayAction->action()->setChecked(true);
if (m_seeker)
m_seeker->setEnabled(false);
};
SelectionContextOperation particlesPlayTrigger = [this](const SelectionContext &) {
if (m_seeker)
m_seeker->setEnabled(!m_particlesPlayAction->action()->isChecked());
};
m_particleViewModeAction
= new Edit3DAction(
QmlDesigner::Constants::EDIT3D_PARTICLE_MODE, View3DActionCommand::Edit3DParticleModeToggle,
QCoreApplication::translate("ParticleViewModeAction", "Toggle particle animation On/Off"),
QKeySequence(Qt::Key_V), true, false, Icons::EDIT3D_PARTICLE_OFF.icon(),
Icons::EDIT3D_PARTICLE_ON.icon(), particlesTrigger);
particlemode = false;
m_particlesPlayAction
= new Edit3DAction(
QmlDesigner::Constants::EDIT3D_PARTICLES_PLAY, View3DActionCommand::ParticlesPlay,
QCoreApplication::translate("ParticlesPlayAction", "Play Particles"),
QKeySequence(Qt::Key_W), true, true, Icons::EDIT3D_PARTICLE_PLAY.icon(),
Icons::EDIT3D_PARTICLE_PAUSE.icon(), particlesPlayTrigger);
m_particlesRestartAction
= new Edit3DAction(
QmlDesigner::Constants::EDIT3D_PARTICLES_RESTART, View3DActionCommand::ParticlesRestart,
QCoreApplication::translate("ParticlesRestartAction", "Restart Particles"),
QKeySequence(Qt::Key_E), false, false, Icons::EDIT3D_PARTICLE_RESTART.icon(),
Icons::EDIT3D_PARTICLE_RESTART.icon(), particlesRestartTrigger);
m_particlesPlayAction->action()->setEnabled(particlemode);
m_particlesRestartAction->action()->setEnabled(particlemode);
m_resetAction
= new Edit3DAction(
QmlDesigner::Constants::EDIT3D_RESET_VIEW, View3DActionCommand::Empty,
@@ -296,6 +352,10 @@ void Edit3DView::createEdit3DActions()
m_leftActions << m_editLightAction;
m_leftActions << m_showGridAction;
m_rightActions << m_particleViewModeAction;
m_rightActions << m_particlesPlayAction;
m_rightActions << m_particlesRestartAction;
m_rightActions << nullptr;
m_rightActions << m_resetAction;
}
@@ -311,7 +371,8 @@ QVector<Edit3DAction *> Edit3DView::rightActions() const
void Edit3DView::addQuick3DImport()
{
if (model()) {
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
if (document && !document->inFileComponentModelActive() && model()) {
const QList<Import> imports = model()->possibleImports();
for (const auto &import : imports) {
if (import.url() == "QtQuick3D") {

View File

@@ -25,6 +25,7 @@
#pragma once
#include "view3dactioncommand.h"
#include "seekerslider.h"
#include <abstractview.h>
#include <QtGui/qevent.h>
@@ -68,6 +69,7 @@ public:
void createEdit3DActions();
QVector<Edit3DAction *> leftActions() const;
QVector<Edit3DAction *> rightActions() const;
void setSeeker(SeekerSlider *slider);
void addQuick3DImport();
@@ -90,6 +92,11 @@ private:
Edit3DAction *m_editLightAction = nullptr;
Edit3DAction *m_showGridAction = nullptr;
Edit3DAction *m_resetAction = nullptr;
Edit3DAction *m_particleViewModeAction = nullptr;
Edit3DAction *m_particlesPlayAction = nullptr;
Edit3DAction *m_particlesRestartAction = nullptr;
SeekerSlider *m_seeker = nullptr;
int particlemode;
};
} // namespace QmlDesigner

View File

@@ -33,6 +33,8 @@
#include "qmldesignerplugin.h"
#include "qmlvisualnode.h"
#include "viewmanager.h"
#include <seekerslider.h>
#include <nodeinstanceview.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
@@ -64,8 +66,11 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
fillLayout->setSpacing(0);
setLayout(fillLayout);
SeekerSlider *seeker = new SeekerSlider(this);
seeker->setEnabled(false);
// Initialize toolbar
m_toolBox = new ToolBox(this);
m_toolBox = new ToolBox(seeker, this);
fillLayout->addWidget(m_toolBox.data());
// Iterate through view actions. A null action indicates a separator and a second null action
@@ -100,7 +105,10 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
auto separator = new QAction(this);
separator->setSeparator(true);
addAction(separator);
if (left)
m_toolBox->addLeftSideAction(separator);
else
m_toolBox->addRightSideAction(separator);
previousWasSeparator = true;
}
}
@@ -109,6 +117,14 @@ Edit3DWidget::Edit3DWidget(Edit3DView *view) :
addActionsToToolBox(view->leftActions(), true);
addActionsToToolBox(view->rightActions(), false);
view->setSeeker(seeker);
seeker->setToolTip(QLatin1String("Seek particle system time when paused."));
QObject::connect(seeker, &SeekerSlider::positionChanged, [this, seeker](){
QmlDesignerPlugin::instance()->viewManager().nodeInstanceView()
->view3DAction(View3DSeekActionCommand(seeker->position()));
});
// Onboarding label contains instructions for new users how to get 3D content into the project
m_onboardingLabel = new QLabel(this);
QString labelText =

Binary file not shown.

After

Width:  |  Height:  |  Size: 226 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 395 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 157 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 203 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -42,7 +42,8 @@ SOURCES += formeditoritem.cpp \
backgroundaction.cpp \
formeditortoolbutton.cpp \
formeditorannotationicon.cpp \
transitiontool.cpp
transitiontool.cpp \
seekerslider.cpp
HEADERS += formeditorscene.h \
formeditorwidget.h \
@@ -87,6 +88,7 @@ HEADERS += formeditorscene.h \
backgroundaction.h \
formeditortoolbutton.h \
formeditorannotationicon.h \
transitiontool.h
transitiontool.h \
seekerslider.h
RESOURCES += formeditor.qrc

View File

@@ -8,5 +8,11 @@
<file>snapping_and_anchoring@2x.png</file>
<file>annotationsIcon.png</file>
<file>annotationsIconActive.png</file>
<file>scrubbg.png</file>
<file>scrubbg@2x.png</file>
<file>scrubhandle-24.png</file>
<file>scrubhandle-48.png</file>
<file>scrubhandle-disabled-24.png</file>
<file>scrubhandle-disabled-48.png</file>
</qresource>
</RCC>

View File

@@ -326,13 +326,15 @@ void FormEditorView::propertiesAboutToBeRemoved(const QList<AbstractProperty>& p
m_currentTool->itemsAboutToRemoved(removedItems);
}
static inline bool hasNodeSourceParent(const ModelNode &node)
static inline bool hasNodeSourceOrNonItemParent(const ModelNode &node)
{
if (node.hasParentProperty() && node.parentProperty().parentModelNode().isValid()) {
ModelNode parent = node.parentProperty().parentModelNode();
if (parent.nodeSourceType() != ModelNode::NodeWithoutSource)
if (parent.nodeSourceType() != ModelNode::NodeWithoutSource
|| !QmlItemNode::isItemOrWindow(parent)) {
return true;
return hasNodeSourceParent(parent);
}
return hasNodeSourceOrNonItemParent(parent);
}
return false;
}
@@ -867,7 +869,7 @@ void FormEditorView::addOrRemoveFormEditorItem(const ModelNode &node)
removeNodeFromScene(itemNode);
}
};
if (hasNodeSourceParent(node)) {
if (hasNodeSourceOrNonItemParent(node)) {
removeItemFromScene();
} else if (itemNode.isValid()) {
if (node.nodeSourceType() == ModelNode::NodeWithoutSource) {

View File

@@ -139,7 +139,7 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view)
addAction(m_rootHeightAction.data());
upperActions.append(m_rootHeightAction.data());
m_toolBox = new ToolBox(this);
m_toolBox = new ToolBox(nullptr, this);
fillLayout->addWidget(m_toolBox.data());
m_toolBox->setLeftSideActions(upperActions);
@@ -246,14 +246,14 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view)
};
m_zoomInAction = new QAction(zoomInIcon, tr("Zoom In"), this);
m_zoomInAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Plus));
m_zoomInAction->setShortcut(QKeySequence(QKeySequence::ZoomIn));
addAction(m_zoomInAction.data());
upperActions.append(m_zoomInAction.data());
m_toolBox->addRightSideAction(m_zoomInAction.data());
connect(m_zoomInAction.data(), &QAction::triggered, zoomIn);
m_zoomOutAction = new QAction(zoomOutIcon, tr("Zoom Out"), this);
m_zoomOutAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_Minus));
m_zoomOutAction->setShortcut(QKeySequence(QKeySequence::ZoomOut));
addAction(m_zoomOutAction.data());
upperActions.append(m_zoomOutAction.data());
m_toolBox->addRightSideAction(m_zoomOutAction.data());
@@ -266,7 +266,8 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view)
connect(m_zoomAction.data(), &ZoomAction::zoomLevelChanged, setZoomLevel);
m_zoomAllAction = new QAction(zoomAllIcon, tr("Zoom screen to fit all content."), this);
m_zoomAllAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_0));
m_zoomAllAction->setShortcut(QKeySequence(tr("Ctrl+Alt+0")));
addAction(m_zoomAllAction.data());
upperActions.append(m_zoomAllAction.data());
m_toolBox->addRightSideAction(m_zoomAllAction.data());
@@ -275,7 +276,7 @@ FormEditorWidget::FormEditorWidget(FormEditorView *view)
m_zoomSelectionAction = new QAction(zoomSelectionIcon,
tr("Zoom screen to fit current selection."),
this);
m_zoomSelectionAction->setShortcut(QKeySequence(Qt::CTRL | Qt::ALT | Qt::Key_I));
m_zoomSelectionAction->setShortcut(QKeySequence(tr("Ctrl+Alt+i")));
addAction(m_zoomSelectionAction.data());
upperActions.append(m_zoomSelectionAction.data());
m_toolBox->addRightSideAction(m_zoomSelectionAction.data());

Binary file not shown.

After

Width:  |  Height:  |  Size: 152 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 166 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 362 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 438 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 829 B

View File

@@ -0,0 +1,138 @@
/****************************************************************************
**
** Copyright (C) 2021 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 "seekerslider.h"
#include <utils/icon.h>
#include <QStyleOption>
#include <QSlider>
#include <QDebug>
#include <QPainter>
namespace QmlDesigner {
SeekerSlider::SeekerSlider(QWidget *parentWidget)
: QWidget(parentWidget),
m_bgIcon(QLatin1String(":/icon/layout/scrubbg.png"))
{
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-24.png"), QSize(24, 24));
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-48.png"), QSize(48, 48));
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-disabled-24.png"), QSize(24, 24), QIcon::Disabled);
m_handleIcon.addFile(QLatin1String(":/icon/layout/scrubhandle-disabled-48.png"), QSize(48, 48), QIcon::Disabled);
const Utils::Icon bg({{":/icon/layout/scrubbg.png", Utils::Theme::IconsBaseColor}});
m_bgWidth = bg.pixmap().width();
m_bgHeight = bg.pixmap().height();
m_handleWidth = m_bgHeight;
m_handleHeight = m_bgHeight;
int width = m_bgWidth + m_handleWidth * 2;
m_sliderHalfWidth = m_bgWidth / 2;
setMinimumWidth(width);
setMaximumWidth(width);
setProperty("panelwidget", true);
setProperty("panelwidget_singlerow", true);
}
void SeekerSlider::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
{
QStyleOptionToolBar option;
option.rect = rect();
option.state = QStyle::State_Horizontal;
style()->drawControl(QStyle::CE_ToolBar, &option, &painter, this);
}
int x = rect().width() / 2;
int y = rect().height() / 2;
const QPixmap bg = m_bgIcon.pixmap(QSize(m_bgWidth, m_bgHeight), isEnabled() ? QIcon::Normal : QIcon::Disabled, QIcon::On);
painter.drawPixmap(x - m_bgWidth / 2, y - m_bgHeight / 2, bg);
if (m_moving) {
const QPixmap handle = m_handleIcon.pixmap(QSize(m_handleWidth, m_handleHeight), QIcon::Active, QIcon::On);
painter.drawPixmap(x - m_handleWidth / 2 + m_sliderPos, y - m_handleHeight / 2, handle);
} else {
const QPixmap handle = m_handleIcon.pixmap(QSize(m_handleWidth, m_handleHeight), isEnabled() ? QIcon::Normal : QIcon::Disabled, QIcon::On);
painter.drawPixmap(x - m_handleWidth / 2, y - m_handleHeight / 2, handle);
}
}
void SeekerSlider::mousePressEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton) {
QWidget::mousePressEvent(event);
return;
}
int x = rect().width() / 2;
int y = rect().height() / 2;
auto pos = event->localPos();
if (pos.x() >= x - m_handleWidth / 2 && pos.x() <= x + m_handleWidth / 2
&& pos.y() >= y - m_handleHeight / 2 && pos.y() <= y + m_handleHeight / 2) {
m_moving = true;
m_startPos = pos.x();
}
}
void SeekerSlider::mouseMoveEvent(QMouseEvent *event)
{
if (!m_moving) {
QWidget::mouseMoveEvent(event);
return;
}
auto pos = event->localPos();
int delta = pos.x() - m_startPos;
m_sliderPos = qBound(-m_sliderHalfWidth, delta, m_sliderHalfWidth);
delta = m_maxPosition * m_sliderPos / m_sliderHalfWidth;
if (delta != m_position) {
m_position = delta;
Q_EMIT positionChanged();
update();
}
}
void SeekerSlider::mouseReleaseEvent(QMouseEvent *event)
{
if (!m_moving) {
QWidget::mouseReleaseEvent(event);
return;
}
m_moving = false;
m_position = 0;
m_startPos = 0;
m_sliderPos = 0;
Q_EMIT positionChanged();
update();
}
int SeekerSlider::position() const
{
return m_position;
}
} // namespace QmlDesigner

View File

@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2021 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 <QWidget>
#include <QMouseEvent>
#include <QIcon>
namespace QmlDesigner {
class SeekerSlider : public QWidget
{
Q_OBJECT
public:
SeekerSlider(QWidget *parentWidget);
int position() const;
int maxPosition() const
{
return m_maxPosition;
}
void setMaxPosition(int pos)
{
m_maxPosition = qMax(0, pos);
}
Q_SIGNALS:
void positionChanged();
protected:
void paintEvent(QPaintEvent *event) override;
void mousePressEvent(QMouseEvent *event) override;
void mouseMoveEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
int m_position = 0;
int m_startPos = 0;
int m_sliderPos = 0;
int m_sliderHalfWidth = 0;
int m_maxPosition = 30;
bool m_moving = false;
int m_bgWidth;
int m_bgHeight;
int m_handleWidth;
int m_handleHeight;
QIcon m_bgIcon;
QIcon m_handleIcon;
};
} // namespace QmlDesigner

View File

@@ -33,10 +33,11 @@
namespace QmlDesigner {
ToolBox::ToolBox(QWidget *parentWidget)
ToolBox::ToolBox(SeekerSlider *seeker, QWidget *parentWidget)
: Utils::StyledBar(parentWidget),
m_leftToolBar(new QToolBar(QLatin1String("LeftSidebar"), this)),
m_rightToolBar(new QToolBar(QLatin1String("RightSidebar"), this))
m_rightToolBar(new QToolBar(QLatin1String("RightSidebar"), this)),
m_seeker(seeker)
{
m_leftToolBar->setFloatable(true);
m_leftToolBar->setMovable(true);
@@ -62,6 +63,8 @@ ToolBox::ToolBox(QWidget *parentWidget)
m_rightToolBar->setOrientation(Qt::Horizontal);
horizontalLayout->addWidget(m_leftToolBar);
horizontalLayout->addWidget(stretchToolbar);
if (seeker)
horizontalLayout->addWidget(m_seeker);
horizontalLayout->addWidget(m_rightToolBar);
}
@@ -94,4 +97,9 @@ QList<QAction*> ToolBox::actions() const
return m_leftToolBar->actions() + m_rightToolBar->actions();
}
SeekerSlider *ToolBox::seeker() const
{
return m_seeker;
}
} // namespace QmlDesigner

View File

@@ -25,6 +25,7 @@
#pragma once
#include <utils/styledbar.h>
#include <seekerslider.h>
QT_BEGIN_NAMESPACE
class QToolBar;
@@ -37,16 +38,18 @@ namespace QmlDesigner {
class ToolBox : public Utils::StyledBar
{
public:
ToolBox(QWidget *parentWidget);
ToolBox(SeekerSlider *seeker, QWidget *parentWidget);
void setLeftSideActions(const QList<QAction*> &actions);
void setRightSideActions(const QList<QAction*> &actions);
void addLeftSideAction(QAction *action);
void addRightSideAction(QAction *action);
QList<QAction*> actions() const;
SeekerSlider *seeker() const;
private:
QToolBar *m_leftToolBar;
QToolBar *m_rightToolBar;
SeekerSlider *m_seeker;
};
} // namespace QmlDesigner

View File

@@ -210,6 +210,11 @@ bool DesignDocument::pasteSVG()
return true;
}
bool DesignDocument::inFileComponentModelActive() const
{
return !m_inFileComponentModel.isNull();
}
QList<DocumentMessage> DesignDocument::qmlParseWarnings() const
{
return m_rewriterView->warnings();

View File

@@ -76,6 +76,7 @@ public:
Model *currentModel() const;
Model *documentModel() const;
bool inFileComponentModelActive() const;
void contextHelp(const Core::IContext::HelpCallback &callback) const;
QList<DocumentMessage> qmlParseWarnings() const;

View File

@@ -354,7 +354,8 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
beginResetModel();
clearSections();
Utils::FilePath qmlFileName = QmlDesignerPlugin::instance()->currentDesignDocument()->fileName();
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
Utils::FilePath qmlFileName = document->fileName();
ProjectExplorer::Project *project = ProjectExplorer::SessionManager::projectForFile(qmlFileName);
QString projectName = project ? project->displayName() : "";
@@ -398,6 +399,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
itemLibImport->setImportExpanded(loadExpandedState(itemLibImport->importUrl()));
}
const bool blockNewImports = document->inFileComponentModelActive();
const QList<ItemLibraryEntry> itemLibEntries = itemLibraryInfo->entries();
for (const ItemLibraryEntry &entry : itemLibEntries) {
NodeMetaInfo metaInfo = model->metaInfo(entry.typeName());
@@ -429,7 +431,7 @@ void ItemLibraryModel::update(ItemLibraryInfo *itemLibraryInfo, Model *model)
bool hasImport = model->hasImport(import, true, true);
bool isImportPossible = false;
if (!hasImport)
isImportPossible = model->isImportPossible(import, true, true);
isImportPossible = !blockNewImports && model->isImportPossible(import, true, true);
bool isUsable = (valid && (isItem || forceVisibility))
&& (entry.requiredImport().isEmpty() || hasImport);
if (!blocked && (isUsable || isImportPossible)) {

View File

@@ -400,6 +400,17 @@ void ItemLibraryWidget::setModel(Model *model)
return;
setItemLibraryInfo(model->metaInfo().itemLibraryInfo());
if (DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument()) {
const bool subCompEditMode = document->inFileComponentModelActive();
if (m_subCompEditMode != subCompEditMode) {
m_subCompEditMode = subCompEditMode;
// Switch out of module add panel if it's active
if (m_subCompEditMode && m_stackedWidget->currentIndex() == 2)
m_stackedWidget->setCurrentIndex(0);
emit subCompEditModeChanged();
}
}
}
void ItemLibraryWidget::handleTabChanged(int index)
@@ -545,6 +556,11 @@ QPair<QString, QByteArray> ItemLibraryWidget::getAssetTypeAndData(const QString
return {};
}
bool ItemLibraryWidget::subCompEditMode() const
{
return m_subCompEditMode;
}
void ItemLibraryWidget::setFlowMode(bool b)
{
m_itemLibraryModel->setFlowMode(b);

View File

@@ -71,6 +71,8 @@ class ItemLibraryWidget : public QFrame
Q_OBJECT
public:
Q_PROPERTY(bool subCompEditMode READ subCompEditMode NOTIFY subCompEditModeChanged)
ItemLibraryWidget(AsynchronousImageCache &imageCache,
AsynchronousImageCache &asynchronousFontImageCache,
SynchronousImageCache &synchronousFontImageCache);
@@ -94,6 +96,8 @@ public:
inline static bool isHorizontalLayout = false;
bool subCompEditMode() const;
Q_INVOKABLE void startDragAndDrop(const QVariant &itemLibEntry, const QPointF &mousePos);
Q_INVOKABLE void startDragAsset(const QStringList &assetPaths, const QPointF &mousePos);
Q_INVOKABLE void removeImport(const QString &importUrl);
@@ -108,7 +112,8 @@ public:
Q_INVOKABLE QSet<QString> supportedDropSuffixes();
signals:
void itemActivated(const QString& itemName);
void itemActivated(const QString &itemName);
void subCompEditModeChanged();
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
@@ -152,6 +157,7 @@ private:
bool m_updateRetry = false;
QString m_filterText;
QPoint m_dragStartPoint;
bool m_subCompEditMode = false;
inline static int HORIZONTAL_LAYOUT_WIDTH_LIMIT = 600;
};

View File

@@ -551,6 +551,9 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
QList<ModelNode> addedNodes;
ModelNode currNode;
// Adding required imports is skipped if we are editing in-file subcomponent
DesignDocument *document = QmlDesignerPlugin::instance()->currentDesignDocument();
if (document && !document->inFileComponentModelActive()) {
QSet<QString> neededImports;
for (const QString &assetPath : assetsPaths) {
QString assetType = ItemLibraryWidget::getAssetTypeAndData(assetPath).first;
@@ -565,6 +568,7 @@ bool NavigatorTreeModel::dropMimeData(const QMimeData *mimeData,
for (const QString &import : std::as_const(neededImports))
addImport(import);
}
m_view->executeInTransaction("NavigatorTreeModel::dropMimeData", [&] {
for (const QString &assetPath : assetsPaths) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 97 B

After

Width:  |  Height:  |  Size: 113 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 118 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 121 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 B

After

Width:  |  Height:  |  Size: 96 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 B

After

Width:  |  Height:  |  Size: 103 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 B

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 B

After

Width:  |  Height:  |  Size: 115 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 110 B

After

Width:  |  Height:  |  Size: 120 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 118 B

After

Width:  |  Height:  |  Size: 126 B

Some files were not shown because too many files have changed in this diff Show More