diff options
author | Thomas Hartmann <thomas.hartmann@qt.io> | 2023-06-29 17:22:42 +0200 |
---|---|---|
committer | Thomas Hartmann <thomas.hartmann@qt.io> | 2023-07-06 14:08:06 +0000 |
commit | b85eb8aa04df5f7e6fe7c68f6a0e36b739ed781e (patch) | |
tree | 514cdf0f7cac92dc361329cc49f50c7c5d441ae5 | |
parent | ccdf0730dffd7769135dda7e1db866660961d495 (diff) |
QmlDesigner: Keep context as background
When drilling into components we keep the context as an image
in the background.
Change-Id: I12c291ab1cff02d30f53f92ccd9a551a9dd63704
Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io>
Reviewed-by: Henning Gründl <henning.gruendl@qt.io>
15 files changed, 153 insertions, 11 deletions
diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp index 29bee73620..fc30ab99f9 100644 --- a/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp +++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.cpp @@ -480,6 +480,11 @@ void ViewManager::exportAsImage() d->formEditorView.exportAsImage(); } +QImage ViewManager::takeFormEditorScreenshot() +{ + return d->formEditorView.takeFormEditorScreenshot(); +} + void ViewManager::reformatFileUsingTextEditorView() { d->textEditorView.reformatFile(); diff --git a/src/plugins/qmldesigner/components/componentcore/viewmanager.h b/src/plugins/qmldesigner/components/componentcore/viewmanager.h index 4201065f99..a3cacbe907 100644 --- a/src/plugins/qmldesigner/components/componentcore/viewmanager.h +++ b/src/plugins/qmldesigner/components/componentcore/viewmanager.h @@ -74,6 +74,7 @@ public: const AbstractView *view() const; void exportAsImage(); + QImage takeFormEditorScreenshot(); void reformatFileUsingTextEditorView(); QWidgetAction *componentViewAction() const; diff --git a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp index 37dfafad9a..07a16de7bb 100644 --- a/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp +++ b/src/plugins/qmldesigner/components/formeditor/backgroundaction.cpp @@ -3,6 +3,8 @@ #include "backgroundaction.h" +#include <theme.h> + #include <utils/stylehelper.h> #include <QComboBox> @@ -28,6 +30,14 @@ QIcon iconForColor(const QColor &color) { image.fill(0); QPainter p(&image); + if (color == BackgroundAction::ContextImage) { + const QString unicode = Theme::getIconUnicode(Theme::Icon::textures_medium); + const QString fontName = "qtds_propertyIconFont.ttf"; + QIcon icon = Utils::StyleHelper::getIconFromIconFont(fontName, unicode, 10, 10, Qt::white); + + return icon; + } + p.fillRect(2, 2, size - 4, size - 4, Qt::black); if (color.alpha() == 0) { @@ -70,13 +80,13 @@ QList<QColor> BackgroundAction::colors() { static QColor alphaZero(Qt::transparent); static QList<QColor> colorList = {alphaZero, + QColor(BackgroundAction::ContextImage), QColor(Qt::black), QColor(0x4c4e50), QColor(Qt::darkGray), QColor(Qt::lightGray), QColor(Qt::white)}; - return colorList; } diff --git a/src/plugins/qmldesigner/components/formeditor/backgroundaction.h b/src/plugins/qmldesigner/components/formeditor/backgroundaction.h index 34bd4cd322..c6eeb212fe 100644 --- a/src/plugins/qmldesigner/components/formeditor/backgroundaction.h +++ b/src/plugins/qmldesigner/components/formeditor/backgroundaction.h @@ -11,14 +11,12 @@ namespace QmlDesigner { class BackgroundAction : public QWidgetAction { - enum BackgroundType { - CheckboardBackground, - WhiteBackground, - BlackBackground - }; + enum BackgroundType { CheckboardBackground, WhiteBackground, BlackBackground }; Q_OBJECT public: + enum SpecialColor { ContextImage = Qt::yellow }; + explicit BackgroundAction(QObject *parent); void setColor(const QColor &color); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp index 1e67884ad8..9549ce9dd4 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.cpp @@ -2,9 +2,13 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "formeditorgraphicsview.h" +#include "backgroundaction.h" #include "formeditoritem.h" #include "formeditorwidget.h" #include "navigation2d.h" + +#include <theme.h> + #include <utils/hostosinfo.h> #include <QAction> @@ -198,10 +202,28 @@ void FormEditorGraphicsView::drawBackground(QPainter *painter, const QRectF &rec painter->save(); painter->setBrushOrigin(0, 0); - painter->fillRect(rectangle.intersected(rootItemRect()), backgroundBrush()); // paint rect around editable area - painter->setPen(Qt::black); - painter->drawRect(rootItemRect()); + + if (backgroundBrush().color() == BackgroundAction::ContextImage) { + painter->fillRect(rectangle.intersected(rootItemRect()), Qt::gray); + painter->setOpacity(0.5); + if (!m_backgroundImage.isNull()) + painter->drawImage(rootItemRect().topLeft() + m_backgroundImage.offset(), + m_backgroundImage); + painter->setOpacity(1.0); + } else { + painter->fillRect(rectangle.intersected(rootItemRect()), backgroundBrush()); + } + + QPen pen(Utils::creatorTheme()->color(Utils::Theme::QmlDesigner_FormEditorSelectionColor)); + + pen.setStyle(Qt::DotLine); + pen.setWidth(1); + + painter->setPen(pen); + + painter->drawRect(rootItemRect().adjusted(-1, -1, 0, 0)); + painter->restore(); } @@ -210,6 +232,17 @@ void FormEditorGraphicsView::frame(const QRectF &boundingRect) fitInView(boundingRect, Qt::KeepAspectRatio); } +void FormEditorGraphicsView::setBackgoundImage(const QImage &image) +{ + m_backgroundImage = image; + update(); +} + +QImage FormEditorGraphicsView::backgroundImage() const +{ + return m_backgroundImage; +} + void FormEditorGraphicsView::setZoomFactor(double zoom) { resetTransform(); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h index 28a49b0046..60e02582cd 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorgraphicsview.h @@ -28,6 +28,9 @@ public: void setZoomFactor(double zoom); void frame(const QRectF &bbox); + void setBackgoundImage(const QImage &image); + QImage backgroundImage() const; + protected: bool eventFilter(QObject *watched, QEvent *event) override; void wheelEvent(QWheelEvent *event) override; @@ -45,6 +48,7 @@ private: Panning m_isPanning = Panning::NotStarted; QPoint m_panningStartPosition; QRectF m_rootItemRect; + QImage m_backgroundImage; }; } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp index 5661e4ff79..6b580a7d5f 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.cpp @@ -63,6 +63,8 @@ void FormEditorView::modelAttached(Model *model) if (!isEnabled()) return; + m_formEditorWidget->setBackgoundImage({}); + temporaryBlockView(); setupFormEditorWidget(); @@ -649,6 +651,10 @@ void FormEditorView::auxiliaryDataChanged(const ModelNode &node, if (FormEditorItem *editorItem = scene()->itemForQmlItemNode(item)) editorItem->setFrameColor(data.value<QColor>()); } + + if (key == contextImageProperty) { + m_formEditorWidget->setBackgoundImage(data.value<QImage>()); + } } static void updateTransitions(FormEditorScene *scene, const QmlItemNode &qmlItemNode) @@ -784,6 +790,11 @@ void FormEditorView::exportAsImage() m_formEditorWidget->exportAsImage(m_scene->rootFormEditorItem()->boundingRect()); } +QImage FormEditorView::takeFormEditorScreenshot() +{ + return m_formEditorWidget->takeFormEditorScreenshot(); +} + QPicture FormEditorView::renderToPicture() const { return m_formEditorWidget->renderToPicture(); @@ -954,6 +965,11 @@ void FormEditorView::setupRootItemSize() formEditorWidget()->setRootItemRect(rootQmlNode.instanceBoundingRect()); formEditorWidget()->centerScene(); + + auto contextImage = rootModelNode().auxiliaryData(contextImageProperty); + + if (contextImage) + m_formEditorWidget->setBackgoundImage(contextImage.value().value<QImage>()); } } diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorview.h b/src/plugins/qmldesigner/components/formeditor/formeditorview.h index f97959acb3..1a9f15d016 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorview.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorview.h @@ -117,6 +117,7 @@ public: void setGotoErrorCallback(std::function<void(int, int)> gotoErrorCallback); void exportAsImage(); + QImage takeFormEditorScreenshot(); QPicture renderToPicture() const; void setupFormEditorWidget(); diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp index bfc03d2b23..ef7ed1d52d 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.cpp @@ -2,6 +2,7 @@ // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "formeditorwidget.h" +#include "backgroundaction.h" #include "designeractionmanager.h" #include "designericons.h" #include "designersettings.h" @@ -332,11 +333,13 @@ void FormEditorWidget::changeBackgound(const QColor &color) if (color.alpha() == 0) { m_graphicsView->activateCheckboardBackground(); if (m_formEditorView->rootModelNode().hasAuxiliaryData(formeditorColorProperty)) { - m_formEditorView->rootModelNode().setAuxiliaryData(formeditorColorProperty, {}); + m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty, + {}); } } else { m_graphicsView->activateColoredBackground(color); - m_formEditorView->rootModelNode().setAuxiliaryData(formeditorColorProperty, color); + m_formEditorView->rootModelNode().setAuxiliaryDataWithoutLock(formeditorColorProperty, + color); } } @@ -397,6 +400,10 @@ void FormEditorWidget::updateActions() } else { m_backgroundAction->setColor(Qt::transparent); } + + if (m_formEditorView->rootModelNode().hasAuxiliaryData(contextImageProperty)) + m_backgroundAction->setColor(BackgroundAction::ContextImage); + } else { m_rootWidthAction->clearLineEditText(); m_rootHeightAction->clearLineEditText(); @@ -540,6 +547,40 @@ void FormEditorWidget::exportAsImage(const QRectF &boundingRect) } } +QImage FormEditorWidget::takeFormEditorScreenshot() +{ + const QRectF boundingRect = m_formEditorView->scene()->rootFormEditorItem()->boundingRect(); + + m_formEditorView->scene()->manipulatorLayerItem()->setVisible(false); + QImage image(boundingRect.size().toSize(), QImage::Format_ARGB32); + + if (!m_graphicsView->backgroundImage().isNull()) { + image = m_graphicsView->backgroundImage(); + const QPoint offset = m_graphicsView->backgroundImage().offset(); + + QPainter painter(&image); + QTransform viewportTransform = m_graphicsView->viewportTransform(); + + m_graphicsView->render(&painter, + QRectF(-offset, boundingRect.size()), + viewportTransform.mapRect(boundingRect).toRect()); + + image.setOffset(offset); + + } else { + QPainter painter(&image); + QTransform viewportTransform = m_graphicsView->viewportTransform(); + + m_graphicsView->render(&painter, + QRectF(0, 0, image.width(), image.height()), + viewportTransform.mapRect(boundingRect).toRect()); + } + + m_formEditorView->scene()->manipulatorLayerItem()->setVisible(true); + + return image; +} + QPicture FormEditorWidget::renderToPicture() const { QPicture picture; @@ -568,6 +609,17 @@ bool FormEditorWidget::errorMessageBoxIsVisible() const return m_documentErrorWidget && m_documentErrorWidget->isVisible(); } +void FormEditorWidget::setBackgoundImage(const QImage &image) +{ + m_graphicsView->setBackgoundImage(image); + updateActions(); +} + +QImage FormEditorWidget::backgroundImage() const +{ + return m_graphicsView->backgroundImage(); +} + DocumentWarningWidget *FormEditorWidget::errorWidget() { if (m_documentErrorWidget.isNull()) { diff --git a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h index 5e4e29d155..8135ce8139 100644 --- a/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h +++ b/src/plugins/qmldesigner/components/formeditor/formeditorwidget.h @@ -63,12 +63,17 @@ public: void showWarningMessageBox(const QList<DocumentMessage> &warnings); void exportAsImage(const QRectF &boundingRect); + + QImage takeFormEditorScreenshot(); QPicture renderToPicture() const; FormEditorGraphicsView *graphicsView() const; bool errorMessageBoxIsVisible() const; + void setBackgoundImage(const QImage &image); + QImage backgroundImage() const; + protected: QActionGroup *toolActionGroup() const; DocumentWarningWidget *errorWidget(); diff --git a/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h b/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h index 4c12af14fe..b93626a331 100644 --- a/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h +++ b/src/plugins/qmldesigner/designercore/include/auxiliarydataproperties.h @@ -108,6 +108,8 @@ inline constexpr AuxiliaryDataKeyView rotBlockProperty{AuxiliaryDataType::NodeIn inline constexpr AuxiliaryDataKeyView languageProperty{AuxiliaryDataType::Temporary, "language"}; inline constexpr AuxiliaryDataKeyView bakeLightsManualProperty{AuxiliaryDataType::Document, "bakeLightsManual"}; +inline constexpr AuxiliaryDataKeyView contextImageProperty{AuxiliaryDataType::Temporary, + "contextImage"}; // Most material preview aux properties are duplicated as document and instance types, as they // are both required to be persistent and used at runtime to control material preview rendering diff --git a/src/plugins/qmldesigner/designercore/include/modelnode.h b/src/plugins/qmldesigner/designercore/include/modelnode.h index 657093b0ac..5740449e45 100644 --- a/src/plugins/qmldesigner/designercore/include/modelnode.h +++ b/src/plugins/qmldesigner/designercore/include/modelnode.h @@ -182,6 +182,7 @@ public: QVariant auxiliaryDataWithDefault(AuxiliaryDataKeyView key) const; QVariant auxiliaryDataWithDefault(AuxiliaryDataKeyDefaultValue key) const; void setAuxiliaryData(AuxiliaryDataKeyView key, const QVariant &data) const; + void setAuxiliaryDataWithoutLock(AuxiliaryDataKeyView key, const QVariant &data) const; void setAuxiliaryData(AuxiliaryDataType type, Utils::SmallStringView name, const QVariant &data) const; void setAuxiliaryDataWithoutLock(AuxiliaryDataType type, Utils::SmallStringView name, diff --git a/src/plugins/qmldesigner/designercore/model/model.cpp b/src/plugins/qmldesigner/designercore/model/model.cpp index 12a8c09183..e05a895062 100644 --- a/src/plugins/qmldesigner/designercore/model/model.cpp +++ b/src/plugins/qmldesigner/designercore/model/model.cpp @@ -1473,6 +1473,7 @@ WriteLocker::WriteLocker(ModelPrivate *model) if (m_model->m_writeLock) qWarning() << "QmlDesigner: Misbehaving view calls back to model!!!"; // FIXME: Enable it again + QTC_CHECK(!m_model->m_writeLock); Q_ASSERT(!m_model->m_writeLock); model->m_writeLock = true; } @@ -1484,6 +1485,7 @@ WriteLocker::WriteLocker(Model *model) if (m_model->m_writeLock) qWarning() << "QmlDesigner: Misbehaving view calls back to model!!!"; // FIXME: Enable it again + QTC_CHECK(!m_model->m_writeLock); Q_ASSERT(!m_model->m_writeLock); m_model->m_writeLock = true; } @@ -1493,6 +1495,7 @@ WriteLocker::~WriteLocker() if (!m_model->m_writeLock) qWarning() << "QmlDesigner: WriterLocker out of sync!!!"; // FIXME: Enable it again + QTC_CHECK(m_model->m_writeLock); Q_ASSERT(m_model->m_writeLock); m_model->m_writeLock = false; } diff --git a/src/plugins/qmldesigner/designercore/model/modelnode.cpp b/src/plugins/qmldesigner/designercore/model/modelnode.cpp index 45c076022d..78f2b14e98 100644 --- a/src/plugins/qmldesigner/designercore/model/modelnode.cpp +++ b/src/plugins/qmldesigner/designercore/model/modelnode.cpp @@ -1002,6 +1002,12 @@ void ModelNode::setAuxiliaryData(AuxiliaryDataKeyView key, const QVariant &data) } } +void ModelNode::setAuxiliaryDataWithoutLock(AuxiliaryDataKeyView key, const QVariant &data) const +{ + if (isValid()) + m_model->d->setAuxiliaryData(internalNode(), key, data); +} + void ModelNode::setAuxiliaryDataWithoutLock(AuxiliaryDataType type, Utils::SmallStringView name, const QVariant &data) const diff --git a/src/plugins/qmldesigner/documentmanager.cpp b/src/plugins/qmldesigner/documentmanager.cpp index e3460622e7..5ec3c5b336 100644 --- a/src/plugins/qmldesigner/documentmanager.cpp +++ b/src/plugins/qmldesigner/documentmanager.cpp @@ -265,6 +265,9 @@ void DocumentManager::resetPossibleImports() bool DocumentManager::goIntoComponent(const ModelNode &modelNode) { + QImage image = QmlDesignerPlugin::instance()->viewManager().takeFormEditorScreenshot(); + const QPoint offset = image.offset(); + image.setOffset(offset - QmlItemNode(modelNode).instancePosition().toPoint()); if (modelNode.isValid() && modelNode.isComponent() && designDocument()) { QmlDesignerPlugin::instance()->viewManager().setComponentNode(modelNode); QHash<PropertyName, QVariant> oldProperties = getProperties(modelNode); @@ -282,6 +285,8 @@ bool DocumentManager::goIntoComponent(const ModelNode &modelNode) ModelNode rootModelNode = designDocument()->rewriterView()->rootModelNode(); applyProperties(rootModelNode, oldProperties); + rootModelNode.setAuxiliaryData(AuxiliaryDataType::Temporary, "contextImage", image); + return true; } |