HMI/source/graphicsItem/graphicsTextItem.cpp

321 lines
9.0 KiB
C++
Raw Normal View History

#include "graphicsItem/graphicsTextItem.h"
#include "graphicsItem/itemControlHandle.h"
#include "graphicsItem/graphicsItemGroup.h"
#include <QPainter>
#include <QStyleOptionGraphicsItem>
#include <QFont>
#include <QGraphicsScene>
#include <QFocusEvent>
#include <QTextDocument>
GraphicsTextItem::GraphicsTextItem(QGraphicsItem *parent)
: AbstractShapeType<QGraphicsTextItem>(parent)
{
m_type = T_item;
m_pen = QPen(Qt::NoPen);
m_brush = QBrush(Qt::NoBrush);
// 8 resize handles
m_vecHanle.reserve(H_left);
for (int i = H_leftTop; i <= H_left; i++) {
auto *h = new ItemControlHandle(this);
h->setType(T_resize);
h->setTag(i);
m_vecHanle.push_back(h);
}
// 4 rotate handles
for (int i = H_rotate_leftTop; i <= H_rotate_leftBottom; i++) {
auto *h = new ItemControlHandle(this);
h->setType(T_rotate);
h->setTag(i);
m_vecHanle.push_back(h);
}
setFlag(QGraphicsItem::ItemIsMovable, false); // we handle move via selector
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setAcceptHoverEvents(true);
QFont defaultFont;
defaultFont.setPointSize(14);
setFont(defaultFont);
setDefaultTextColor(Qt::black);
setPlainText("Text");
updateSizeFromText();
m_boundingRect = QRectF(0, 0, m_dWidth, m_dHeight);
setTransformOriginPoint(m_boundingRect.center());
m_lastBoundingRect = m_boundingRect;
// Keep bounding rect in sync with text content during editing
connect(document(), &QTextDocument::contentsChanged, this, [this]() {
prepareGeometryChange();
updateSizeFromText();
m_boundingRect = QRectF(0, 0, m_dWidth, m_dHeight);
setTransformOriginPoint(m_boundingRect.center());
updateHandles();
m_lastBoundingRect = m_boundingRect;
});
}
GraphicsTextItem::~GraphicsTextItem() {}
QString GraphicsTextItem::getPropertyGroup(const QString &propertyName) const
{
QList<QString> properties = {
QStringLiteral("text"),
QStringLiteral("ptPosition"),
QStringLiteral("textFont"),
QStringLiteral("textColor"),
QStringLiteral("backgroundColor")
};
if (!properties.contains(propertyName))
return {};
else
return QStringLiteral("基本信息");
}
QPainterPath GraphicsTextItem::shape()
{
QPainterPath path;
path.addRect(m_boundingRect);
return path;
}
void GraphicsTextItem::updateSizeFromText()
{
QSizeF textSize = document()->size();
double w = qMax(textSize.width(), 40.0);
double h = qMax(textSize.height(), 20.0);
m_dWidth = w;
m_dHeight = h;
}
void GraphicsTextItem::updateCoordinate()
{
if (!parentItem()) {
updateSizeFromText();
prepareGeometryChange();
m_boundingRect = QRectF(0, 0, m_dWidth, m_dHeight);
setTransformOriginPoint(m_boundingRect.center());
updateHandles();
}
m_lastBoundingRect = m_boundingRect;
m_dLastPointSize = font().pointSize();
}
void GraphicsTextItem::updateHandles()
{
AbstractShapeType<QGraphicsTextItem>::updateHandles();
}
void GraphicsTextItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
// Background fill
if (m_brush.style() != Qt::NoBrush) {
painter->setPen(Qt::NoPen);
painter->setBrush(m_brush);
painter->drawRect(m_boundingRect);
}
// Text rendering via QGraphicsTextItem
QGraphicsTextItem::paint(painter, option, widget);
// Selection indicator
if (option->state & QStyle::State_Selected) {
int nPenWidth = 1;
painter->setPen(QPen(QColor(70, 70, 70), nPenWidth, Qt::DashLine));
painter->setBrush(Qt::NoBrush);
painter->drawRect(m_boundingRect_selected);
painter->setBrush(Qt::red);
painter->drawEllipse(transformOriginPoint(), 4, 4);
}
}
void GraphicsTextItem::resize(int nHandle, double dSX, double dSY, const QPointF &basePoint)
{
switch (nHandle) {
case H_left:
case H_right:
dSY = 1;
break;
case H_top:
case H_bottom:
dSX = 1;
break;
default:
break;
}
QTransform trans;
trans.translate(basePoint.x(), basePoint.y());
trans.scale(dSX, dSY);
trans.translate(-basePoint.x(), -basePoint.y());
prepareGeometryChange();
m_boundingRect = trans.mapRect(m_lastBoundingRect);
m_dWidth = m_boundingRect.width();
m_dHeight = m_boundingRect.height();
// Scale font size proportionally from pre-drag value
double avgScale = (qAbs(dSX) + qAbs(dSY)) / 2.0;
QFont f = font();
int newSize = qMax(1, qRound(m_dLastPointSize * avgScale));
f.setPointSize(newSize);
setFont(f);
setTransformOriginPoint(m_boundingRect.center());
updateHandles();
}
void GraphicsTextItem::move(const QPointF &pt)
{
moveBy(pt.x(), pt.y());
}
QVariant GraphicsTextItem::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged) {
QGraphicsItemGroup *group = dynamic_cast<QGraphicsItemGroup *>(parentItem());
if (!group)
setHandleVisible(value.toBool());
else {
setSelected(false);
return QVariant::fromValue<bool>(false);
}
}
return QGraphicsTextItem::itemChange(change, value);
}
void GraphicsTextItem::startEditing()
{
m_bEditing = true;
setHandleVisible(false);
setTextInteractionFlags(Qt::TextEditorInteraction);
setFocus();
}
void GraphicsTextItem::endEditing()
{
m_bEditing = false;
setTextInteractionFlags(Qt::NoTextInteraction);
updateCoordinate();
if (isSelected())
setHandleVisible(true);
}
void GraphicsTextItem::focusOutEvent(QFocusEvent *event)
{
QGraphicsTextItem::focusOutEvent(event);
endEditing();
}
void GraphicsTextItem::focusInEvent(QFocusEvent *event)
{
QGraphicsTextItem::focusInEvent(event);
setHandleVisible(false);
}
void GraphicsTextItem::createOperationCopy()
{
m_pOperationCopy = new QGraphicsPathItem(shape());
m_pOperationCopy->setPen(Qt::DashLine);
m_pOperationCopy->setPos(pos());
m_pOperationCopy->setTransformOriginPoint(transformOriginPoint());
m_pOperationCopy->setTransform(transform());
m_pOperationCopy->setRotation(rotation());
m_pOperationCopy->setScale(scale());
m_pOperationCopy->setZValue(zValue());
QGraphicsScene *s = scene();
if (s && m_pOperationCopy) {
s->addItem(m_pOperationCopy);
m_movingIniPos = pos();
}
}
void GraphicsTextItem::removeOperationCopy()
{
QGraphicsScene *s = scene();
if (s && m_pOperationCopy) {
if (pos() != m_pOperationCopy->pos())
setPos(m_pOperationCopy->pos());
if (rotation() != m_pOperationCopy->rotation())
setRotation(m_pOperationCopy->rotation());
s->removeItem(m_pOperationCopy);
delete m_pOperationCopy;
m_pOperationCopy = nullptr;
}
}
void GraphicsTextItem::moveOperationCopy(const QPointF &distance)
{
if (m_pOperationCopy)
m_pOperationCopy->setPos(m_movingIniPos + distance);
}
void GraphicsTextItem::rotateOperationCopy(const double &dAngle)
{
if (m_pOperationCopy)
m_pOperationCopy->setRotation(dAngle);
}
void GraphicsTextItem::syncRotationDataFromParent(const double &data)
{
m_dSyncRotationByParent += data;
if (m_dSyncRotationByParent > 180)
m_dSyncRotationByParent -= 360;
if (m_dSyncRotationByParent < -180)
m_dSyncRotationByParent += 360;
}
#include "util/serializationUtils.h"
QJsonObject GraphicsTextItem::serialize() const
{
QJsonObject obj = serializeCommon(this, "text");
obj["text"] = toPlainText();
QJsonObject fontObj;
fontObj["family"] = font().family();
fontObj["bold"] = font().bold();
fontObj["italic"] = font().italic();
fontObj["underline"] = font().underline();
fontObj["pointSize"] = font().pointSize();
obj["font"] = fontObj;
obj["textColor"] = defaultTextColor().name(QColor::HexArgb);
obj["backgroundColor"] = m_brush.color().name(QColor::HexArgb);
return obj;
}
#include "util/serializationRegistry.h"
QGraphicsItem *GraphicsTextItem::createFromJson(const QJsonObject &obj)
{
auto *item = new GraphicsTextItem();
item->setPlainText(obj["text"].toString());
QJsonObject f = obj["font"].toObject();
QFont font(f["family"].toString(), f["pointSize"].toInt(14));
font.setBold(f["bold"].toBool());
font.setItalic(f["italic"].toBool());
font.setUnderline(f["underline"].toBool());
item->setFont(font);
item->setDefaultTextColor(QColor(obj["textColor"].toString()));
QColor bgColor(obj["backgroundColor"].toString());
if (bgColor.isValid())
item->setBrushColor(bgColor);
applyCommon(item, obj);
item->updateSizeFromText();
item->updateCoordinate();
item->setHandleVisible(false);
return item;
}
static struct TextItemRegistrar {
TextItemRegistrar() {
registerItemFactory("text", &GraphicsTextItem::createFromJson);
}
} _textItemRegistrar;