forked from qt-creator/qt-creator
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>
This commit is contained in:
@@ -480,6 +480,11 @@ void ViewManager::exportAsImage()
|
||||
d->formEditorView.exportAsImage();
|
||||
}
|
||||
|
||||
QImage ViewManager::takeFormEditorScreenshot()
|
||||
{
|
||||
return d->formEditorView.takeFormEditorScreenshot();
|
||||
}
|
||||
|
||||
void ViewManager::reformatFileUsingTextEditorView()
|
||||
{
|
||||
d->textEditorView.reformatFile();
|
||||
|
@@ -74,6 +74,7 @@ public:
|
||||
const AbstractView *view() const;
|
||||
|
||||
void exportAsImage();
|
||||
QImage takeFormEditorScreenshot();
|
||||
void reformatFileUsingTextEditorView();
|
||||
|
||||
QWidgetAction *componentViewAction() const;
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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>());
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -117,6 +117,7 @@ public:
|
||||
void setGotoErrorCallback(std::function<void(int, int)> gotoErrorCallback);
|
||||
|
||||
void exportAsImage();
|
||||
QImage takeFormEditorScreenshot();
|
||||
QPicture renderToPicture() const;
|
||||
|
||||
void setupFormEditorWidget();
|
||||
|
@@ -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()) {
|
||||
|
@@ -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();
|
||||
|
@@ -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
|
||||
|
@@ -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,
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user