QmlDesigner: Show canvas background in states view

* Forward the auxiliary property formeditorColorProperty to the states
  editor delegate
* Add functionality to enabled/disable certain colors in the form editor
  canvas background combo box
* Disable context image property in the combo box when it isn't set
* When context image is set as the canvas background make the states
  background transparent
* Fix Item as root being rendered with white background in
  Qt5NodeInstanceServer::grabRenderControl

Task-number: QDS-12914
Change-Id: Ie2850986f4a54c6e03f33527d8308d01ba16884e
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
Henning Gruendl
2024-06-05 18:46:12 +02:00
committed by Henning Gründl
parent 24c79573db
commit 0c92c8aaf7
12 changed files with 83 additions and 22 deletions

View File

@@ -562,6 +562,7 @@ Rectangle {
isChecked: root.currentStateInternalId === 0 isChecked: root.currentStateInternalId === 0
thumbnailImageSource: StatesEditorBackend.statesEditorModel.baseState.stateImageSource ?? "" // TODO Get rid of the QVariantMap thumbnailImageSource: StatesEditorBackend.statesEditorModel.baseState.stateImageSource ?? "" // TODO Get rid of the QVariantMap
isTiny: root.tinyMode isTiny: root.tinyMode
backgroundColor: StatesEditorBackend.statesEditorModel.backgroundColor
onFocusSignal: root.currentStateInternalId = 0 onFocusSignal: root.currentStateInternalId = 0
onDefaultClicked: StatesEditorBackend.statesEditorModel.resetDefaultState() onDefaultClicked: StatesEditorBackend.statesEditorModel.resetDefaultState()
@@ -830,6 +831,7 @@ Rectangle {
visualIndex: delegateRoot.visualIndex visualIndex: delegateRoot.visualIndex
internalNodeId: delegateRoot.internalNodeId internalNodeId: delegateRoot.internalNodeId
isTiny: root.tinyMode isTiny: root.tinyMode
backgroundColor: StatesEditorBackend.statesEditorModel.backgroundColor
hasExtend: delegateRoot.hasExtend hasExtend: delegateRoot.hasExtend
extendString: delegateRoot.extendString extendString: delegateRoot.extendString

View File

@@ -65,6 +65,8 @@ Item {
property int internalNodeId property int internalNodeId
property color backgroundColor: "transparent"
signal focusSignal signal focusSignal
signal defaultClicked signal defaultClicked
signal clone signal clone
@@ -241,7 +243,7 @@ Item {
(stateBackground.innerHeight - thumbnailImage.paintedHeight) / 2) - StudioTheme.Values.border (stateBackground.innerHeight - thumbnailImage.paintedHeight) / 2) - StudioTheme.Values.border
width: Math.round(thumbnailImage.paintedWidth) + 2 * StudioTheme.Values.border width: Math.round(thumbnailImage.paintedWidth) + 2 * StudioTheme.Values.border
height: Math.round(thumbnailImage.paintedHeight) + 2 * StudioTheme.Values.border height: Math.round(thumbnailImage.paintedHeight) + 2 * StudioTheme.Values.border
color: "transparent" color: root.backgroundColor
border.width: StudioTheme.Values.border border.width: StudioTheme.Values.border
border.color: StudioTheme.Values.themeStatePreviewOutline border.color: StudioTheme.Values.themeStatePreviewOutline
} }

View File

@@ -10,6 +10,8 @@
#include <QComboBox> #include <QComboBox>
#include <QPainter> #include <QPainter>
#include <QStandardItemModel>
namespace QmlDesigner { namespace QmlDesigner {
BackgroundAction::BackgroundAction(QObject *parent) : BackgroundAction::BackgroundAction(QObject *parent) :
@@ -21,7 +23,17 @@ void BackgroundAction::setColor(const QColor &color)
{ {
if (m_comboBox) if (m_comboBox)
m_comboBox->setCurrentIndex(colors().indexOf(color)); m_comboBox->setCurrentIndex(colors().indexOf(color));
}
void BackgroundAction::setColorEnabled(const QColor &color, bool enable)
{
if (!m_comboBox)
return;
QStandardItemModel *model = qobject_cast<QStandardItemModel *>(m_comboBox->model());
if (QStandardItem *item = model->item(colors().indexOf(color)))
item->setFlags(enable ? item->flags() | Qt::ItemIsEnabled
: item->flags() & ~Qt::ItemIsEnabled);
} }
QIcon iconForColor(const QColor &color) { QIcon iconForColor(const QColor &color) {

View File

@@ -20,6 +20,7 @@ public:
explicit BackgroundAction(QObject *parent); explicit BackgroundAction(QObject *parent);
void setColor(const QColor &color); void setColor(const QColor &color);
void setColorEnabled(const QColor &color, bool enable);
signals: signals:
void backgroundChanged(const QColor &color); void backgroundChanged(const QColor &color);

View File

@@ -1000,10 +1000,8 @@ void FormEditorView::setupRootItemSize()
formEditorWidget()->setRootItemRect(rootRect); formEditorWidget()->setRootItemRect(rootRect);
formEditorWidget()->centerScene(); formEditorWidget()->centerScene();
auto contextImage = rootModelNode().auxiliaryData(contextImageProperty); if (auto contextImage = rootModelNode().auxiliaryData(contextImageProperty))
formEditorWidget()->setBackgoundImage(contextImage.value().value<QImage>());
if (contextImage)
m_formEditorWidget->setBackgoundImage(contextImage.value().value<QImage>());
} }
} }

View File

@@ -326,17 +326,12 @@ void FormEditorWidget::changeRootItemHeight(const QString &heighText)
void FormEditorWidget::changeBackgound(const QColor &color) void FormEditorWidget::changeBackgound(const QColor &color)
{ {
if (color.alpha() == 0) { if (color.alpha() == 0)
m_graphicsView->activateCheckboardBackground(); m_graphicsView->activateCheckboardBackground();
if (m_formEditorView->rootModelNode().hasAuxiliaryData(formeditorColorProperty)) { else
m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty,
{});
}
} else {
m_graphicsView->activateColoredBackground(color); m_graphicsView->activateColoredBackground(color);
m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty,
color); m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty, color);
}
} }
void FormEditorWidget::registerActionAsCommand( void FormEditorWidget::registerActionAsCommand(
@@ -397,8 +392,12 @@ void FormEditorWidget::updateActions()
m_backgroundAction->setColor(Qt::transparent); m_backgroundAction->setColor(Qt::transparent);
} }
if (m_formEditorView->rootModelNode().hasAuxiliaryData(contextImageProperty)) if (m_formEditorView->rootModelNode().hasAuxiliaryData(contextImageProperty)) {
m_backgroundAction->setColorEnabled(BackgroundAction::ContextImage, true);
m_backgroundAction->setColor(BackgroundAction::ContextImage); m_backgroundAction->setColor(BackgroundAction::ContextImage);
} else {
m_backgroundAction->setColorEnabled(BackgroundAction::ContextImage, false);
}
} else { } else {
m_rootWidthAction->clearLineEditText(); m_rootWidthAction->clearLineEditText();

View File

@@ -462,6 +462,21 @@ void StatesEditorModel::setCanAddNewStates(bool b)
emit canAddNewStatesChanged(); emit canAddNewStatesChanged();
} }
QColor StatesEditorModel::backgroundColor() const
{
return m_backgrounColor;
}
void StatesEditorModel::setBackgroundColor(const QColor &c)
{
if (c == m_backgrounColor)
return;
m_backgrounColor = c;
emit backgroundColorChanged();
}
bool StatesEditorModel::isMCUs() const bool StatesEditorModel::isMCUs() const
{ {
return DesignerMcuManager::instance().isMCUProject(); return DesignerMcuManager::instance().isMCUProject();

View File

@@ -4,6 +4,7 @@
#pragma once #pragma once
#include <QAbstractListModel> #include <QAbstractListModel>
#include <QColor>
#include <QPointer> #include <QPointer>
namespace QmlDesigner { namespace QmlDesigner {
@@ -16,6 +17,8 @@ class StatesEditorModel : public QAbstractListModel
Q_PROPERTY(bool canAddNewStates READ canAddNewStates WRITE setCanAddNewStates NOTIFY Q_PROPERTY(bool canAddNewStates READ canAddNewStates WRITE setCanAddNewStates NOTIFY
canAddNewStatesChanged) canAddNewStatesChanged)
Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor NOTIFY
backgroundColorChanged FINAL)
enum { enum {
StateNameRole = Qt::DisplayRole, StateNameRole = Qt::DisplayRole,
@@ -93,6 +96,9 @@ public:
bool canAddNewStates() const; bool canAddNewStates() const;
void setCanAddNewStates(bool b); void setCanAddNewStates(bool b);
QColor backgroundColor() const;
void setBackgroundColor(const QColor &c);
bool isMCUs() const; bool isMCUs() const;
signals: signals:
@@ -104,6 +110,7 @@ signals:
void activeStateGroupIndexChanged(); void activeStateGroupIndexChanged();
void stateGroupsChanged(); void stateGroupsChanged();
void canAddNewStatesChanged(); void canAddNewStatesChanged();
void backgroundColorChanged();
void isMCUsChanged(); void isMCUsChanged();
private: private:
@@ -111,6 +118,7 @@ private:
bool m_hasExtend; bool m_hasExtend;
QStringList m_extendedStates; QStringList m_extendedStates;
bool m_canAddNewStates = false; bool m_canAddNewStates = false;
QColor m_backgrounColor = Qt::transparent;
}; };
} // namespace QmlDesigner } // namespace QmlDesigner

View File

@@ -14,6 +14,8 @@
#include <nodemetainfo.h> #include <nodemetainfo.h>
#include <auxiliarydataproperties.h>
#include <backgroundaction.h>
#include <bindingproperty.h> #include <bindingproperty.h>
#include <customnotifications.h> #include <customnotifications.h>
#include <nodelistproperty.h> #include <nodelistproperty.h>
@@ -719,6 +721,13 @@ void StatesEditorView::modelAttached(Model *model)
resetModel(); resetModel();
resetStateGroups(); resetStateGroups();
// Initially set background color from auxiliary data
if (rootModelNode().hasAuxiliaryData(formeditorColorProperty)) {
QColor color = rootModelNode().auxiliaryDataWithDefault(formeditorColorProperty).value<QColor>();
m_statesEditorModel->setBackgroundColor(
color == BackgroundAction::ContextImage ? Qt::transparent : color);
}
emit m_statesEditorModel->activeStateGroupChanged(); emit m_statesEditorModel->activeStateGroupChanged();
emit m_statesEditorModel->activeStateGroupIndexChanged(); emit m_statesEditorModel->activeStateGroupIndexChanged();
} }
@@ -880,6 +889,17 @@ void StatesEditorView::variantPropertiesChanged(const QList<VariantProperty> &pr
} }
} }
void StatesEditorView::auxiliaryDataChanged(const ModelNode &,
AuxiliaryDataKeyView key,
const QVariant &data)
{
if (key == formeditorColorProperty) {
QColor color = data.value<QColor>();
m_statesEditorModel->setBackgroundColor(
color == BackgroundAction::ContextImage ? Qt::transparent : color);
}
}
void StatesEditorView::customNotification(const AbstractView * /*view*/, void StatesEditorView::customNotification(const AbstractView * /*view*/,
const QString &identifier, const QString &identifier,
const QList<ModelNode> & /*nodeList*/, const QList<ModelNode> & /*nodeList*/,

View File

@@ -64,15 +64,15 @@ public:
PropertyChangeFlags propertyChange) override; PropertyChangeFlags propertyChange) override;
void variantPropertiesChanged(const QList<VariantProperty> &propertyList, void variantPropertiesChanged(const QList<VariantProperty> &propertyList,
PropertyChangeFlags propertyChange) override; PropertyChangeFlags propertyChange) override;
void auxiliaryDataChanged(const ModelNode &node,
AuxiliaryDataKeyView key,
const QVariant &data) override;
void customNotification(const AbstractView *view, void customNotification(const AbstractView *view,
const QString &identifier, const QString &identifier,
const QList<ModelNode> &nodeList, const QList<ModelNode> &nodeList,
const QList<QVariant> &data) override; const QList<QVariant> &data) override;
void rewriterBeginTransaction() override; void rewriterBeginTransaction() override;
void rewriterEndTransaction() override; void rewriterEndTransaction() override;
// AbstractView
void currentStateChanged(const ModelNode &node) override; void currentStateChanged(const ModelNode &node) override;
void instancesPreviewImageChanged(const QVector<ModelNode> &nodeList) override; void instancesPreviewImageChanged(const QVector<ModelNode> &nodeList) override;

View File

@@ -4,6 +4,7 @@
#include "documentmanager.h" #include "documentmanager.h"
#include "qmldesignerplugin.h" #include "qmldesignerplugin.h"
#include <auxiliarydataproperties.h>
#include <bindingproperty.h> #include <bindingproperty.h>
#include <model/modelutils.h> #include <model/modelutils.h>
#include <modelnode.h> #include <modelnode.h>
@@ -295,7 +296,7 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode)
ModelNode rootModelNode = designDocument()->rewriterView()->rootModelNode(); ModelNode rootModelNode = designDocument()->rewriterView()->rootModelNode();
applyProperties(rootModelNode, oldProperties); applyProperties(rootModelNode, oldProperties);
rootModelNode.setAuxiliaryData(AuxiliaryDataType::Temporary, "contextImage", image); rootModelNode.setAuxiliaryData(contextImageProperty, image);
return true; return true;
} }

View File

@@ -89,6 +89,7 @@ void Qt5NodeInstanceServer::initializeView()
m_viewData.renderControl = new QQuickRenderControl; m_viewData.renderControl = new QQuickRenderControl;
m_viewData.window = new QQuickWindow(m_viewData.renderControl); m_viewData.window = new QQuickWindow(m_viewData.renderControl);
m_viewData.window->setColor(Qt::transparent);
setPipelineCacheConfig(m_viewData.window); setPipelineCacheConfig(m_viewData.window);
m_viewData.renderControl->initialize(); m_viewData.renderControl->initialize();
m_qmlEngine = new QQmlEngine; m_qmlEngine = new QQmlEngine;
@@ -379,9 +380,11 @@ QImage Qt5NodeInstanceServer::grabRenderControl([[maybe_unused]] RenderViewData
QRhiReadbackResult readResult; QRhiReadbackResult readResult;
readResult.completed = [&] { readResult.completed = [&] {
readCompleted = true; readCompleted = true;
QImage wrapperImage(reinterpret_cast<const uchar *>(readResult.data.constData()), QImage wrapperImage(
readResult.pixelSize.width(), readResult.pixelSize.height(), reinterpret_cast<const uchar *>(readResult.data.constData()),
QImage::Format_RGBA8888_Premultiplied); readResult.pixelSize.width(),
readResult.pixelSize.height(),
QImage::Format_RGBA8888_Premultiplied);
if (viewData.rhi->isYUpInFramebuffer()) if (viewData.rhi->isYUpInFramebuffer())
renderImage = wrapperImage.mirrored(); renderImage = wrapperImage.mirrored();
else else