279 lines
11 KiB
C++
279 lines
11 KiB
C++
#include "etext.h"
|
|
#include "etextattr.h"
|
|
#include "etextinput.h"
|
|
|
|
eText::eText(InteractiveType type, QGraphicsItem *parent) :
|
|
eObject(QRectF(0, 0, 120, 100), type, parent),
|
|
m_wAttr(nullptr),
|
|
m_wTextInput(nullptr)
|
|
{
|
|
// Widget
|
|
m_attr.text = tr("Hello Text !");
|
|
m_attr.opt.setAlignment(Qt::AlignCenter);
|
|
m_attr.opt.setWrapMode(QTextOption::WrapAnywhere);
|
|
m_attr.cText = Qt::red;
|
|
m_attr.cTextShadow = QColor(0,0,0,0);
|
|
m_attr.cBackground = QColor(0,0,0,0);
|
|
m_attr.lineSpacing = 0;
|
|
//Play
|
|
m_attr.playStyle = Static;
|
|
m_attr.headTailConnected = false;
|
|
m_attr.headTailSpacing = 0;
|
|
m_attr.rollingSpeed = 0;
|
|
m_attr.rollingStyle = Left2Right;
|
|
m_attr.playDuration = 0;
|
|
}
|
|
|
|
eText::eText(const QJsonObject &json, InteractiveType type, QGraphicsItem *parent) :
|
|
eObject(json["geometry"].toObject(), type, parent),
|
|
m_wAttr(nullptr),
|
|
m_wTextInput(nullptr)
|
|
{
|
|
QJsonDocument jRoot;
|
|
jRoot.setObject(json);
|
|
// Widget
|
|
m_attr.text = jRoot["widget"]["text"] .toString();
|
|
m_attr.font.setFamily( jRoot["widget"]["font"]["family"] .toString());
|
|
m_attr.font.setPointSize( jRoot["widget"]["font"]["size"] .toInt());
|
|
m_attr.font.setBold( jRoot["widget"]["font"]["bold"] .toBool());
|
|
m_attr.font.setItalic( jRoot["widget"]["font"]["italic"] .toBool());
|
|
m_attr.font.setUnderline( jRoot["widget"]["font"]["underline"] .toBool());
|
|
m_attr.font.setLetterSpacing(QFont::AbsoluteSpacing, jRoot["widget"]["font"]["letterSpacing"].toInt());
|
|
m_attr.opt.setAlignment(static_cast<Qt::Alignment>( jRoot["widget"]["align"] .toInt()));
|
|
m_attr.cText = LoAppTools::getInstance()->int2Color(jRoot["widget"]["color"]["text"] .toInt());
|
|
m_attr.cTextShadow = LoAppTools::getInstance()->int2Color(jRoot["widget"]["color"]["shadow"] .toInt());
|
|
m_attr.cBackground = LoAppTools::getInstance()->int2Color(jRoot["widget"]["color"]["background"] .toInt());
|
|
m_attr.lineSpacing = jRoot["widget"]["lineSpacing"] .toInt();
|
|
// Play
|
|
m_attr.playStyle = jRoot["play"]["style"] .toInt();
|
|
m_attr.headTailConnected = jRoot["play"]["headTailConnected"].toBool();
|
|
m_attr.headTailSpacing = jRoot["play"]["headTailSpacing"] .toInt();
|
|
m_attr.rollingSpeed = jRoot["play"]["rollingSpeed"] .toInt();
|
|
m_attr.rollingStyle = jRoot["play"]["rollingStyle"] .toInt();
|
|
m_attr.playDuration = jRoot["play"]["duration"] .toInt();
|
|
}
|
|
|
|
QWidget* eText::wAttr()
|
|
{
|
|
QWidget *wObj = eObject::wAttr();
|
|
QWidget *w = wAttrElement();
|
|
static_cast<QBoxLayout*>(w->layout())->insertWidget(0, wObj);
|
|
return w;
|
|
}
|
|
|
|
QWidget* eText::wAttrElement()
|
|
{
|
|
eTextAttr *w = new eTextAttr(m_attr);
|
|
connect(w, SIGNAL(destroyed(QObject*)), this, SLOT(onWAttrClosed()));
|
|
// Widget
|
|
connect(w, SIGNAL(sFontFamilyChanged(const QString&)), this, SLOT(onFontFamilyChanged(const QString&)));
|
|
connect(w, SIGNAL(sFontSizeChanged(int)), this, SLOT(onFontSizeChanged(int)));
|
|
connect(w, SIGNAL(sFontBoldChanged(bool)), this, SLOT(onFontBoldChanged(bool)));
|
|
connect(w, SIGNAL(sFontItalicsChanged(bool)), this, SLOT(onFontItalicsChanged(bool)));
|
|
connect(w, SIGNAL(sFontUnderlineChanged(bool)), this, SLOT(onFontUnderlineChanged(bool)));
|
|
connect(w, SIGNAL(sTextHAlignChanged(int)), this, SLOT(onTextHAlignChanged(int)));
|
|
connect(w, SIGNAL(sTextVAlignChanged(int)), this, SLOT(onTextVAlignChanged(int)));
|
|
connect(w, SIGNAL(sTextColorChanged(const QColor&)), this, SLOT(onTextColorChanged(const QColor&)));
|
|
connect(w, SIGNAL(sTextShadowColorChanged(const QColor&)), this, SLOT(onTextShadowColorChanged(const QColor&)));
|
|
connect(w, SIGNAL(sBackgroundColorChanged(const QColor&)), this, SLOT(onBackgroundColorChanged(const QColor&)));
|
|
connect(w, SIGNAL(sTextLetterSpacingChanged(int)), this, SLOT(onTextLetterSpacingChanged(int)));
|
|
connect(w, SIGNAL(sTextLineSpacingChanged(int)), this, SLOT(onTextLineSpacingChanged(int)));
|
|
// Play
|
|
connect(w, SIGNAL(sPlayStyleChanged(int)), this, SLOT(onPlayStyleChanged(int)));
|
|
connect(w, SIGNAL(sHeadTailConnected(bool)), this, SLOT(onHeadTailConnected(bool)));
|
|
connect(w, SIGNAL(sHeadTailSpacingChanged(int)), this, SLOT(onHeadTailSpacingChanged(int)));
|
|
connect(w, SIGNAL(sRollingSpeedChanged(int)), this, SLOT(onRollingSpeedChanged(int)));
|
|
connect(w, SIGNAL(sRollingStyleChanged(int)), this, SLOT(onRollingStyleChanged(int)));
|
|
connect(w, SIGNAL(sPlayDurationChanged(int)), this, SLOT(onPlayDurationChanged(int)));
|
|
m_wAttr = w;
|
|
return w;
|
|
}
|
|
|
|
QJsonObject eText::elementJson() const
|
|
{
|
|
QJsonObject oRoot;
|
|
QJsonObject oWidget;
|
|
QJsonObject oColor;
|
|
QJsonObject oFont;
|
|
QJsonObject oPlay;
|
|
// Interior
|
|
oRoot["elementType"] = "Text";
|
|
oRoot["elementTypeId"] = type();
|
|
oRoot["geometry"] = eObject::elementJson();
|
|
// Widget
|
|
oWidget["text"] = m_attr.text;
|
|
oFont["family"] = m_attr.font.family();
|
|
oFont["size"] = m_attr.font.pointSize();
|
|
oFont["bold"] = m_attr.font.bold();
|
|
oFont["italic"] = m_attr.font.italic();
|
|
oFont["underline"] = m_attr.font.underline();
|
|
oFont["letterSpacing"] = m_attr.font.letterSpacing();
|
|
oWidget["font"] = oFont;
|
|
oWidget["align"] = static_cast<int>(m_attr.opt.alignment());
|
|
oColor["text"] = LoAppTools::getInstance()->color2Int(m_attr.cText);
|
|
oColor["shadow"] = LoAppTools::getInstance()->color2Int(m_attr.cTextShadow);
|
|
oColor["background"] = LoAppTools::getInstance()->color2Int(m_attr.cBackground);
|
|
oWidget["color"] = oColor;
|
|
oWidget["lineSpacing"] = m_attr.lineSpacing;
|
|
oRoot["widget"] = oWidget;
|
|
// Play
|
|
oPlay["style"] = m_attr.playStyle;
|
|
oPlay["headTailConnected"] = m_attr.headTailConnected;
|
|
oPlay["headTailSpacing"] = m_attr.headTailSpacing;
|
|
oPlay["rollingSpeed"] = m_attr.rollingSpeed;
|
|
oPlay["rollingStyle"] = m_attr.rollingStyle;
|
|
oPlay["duration"] = m_attr.playDuration;
|
|
oRoot["play"] = oPlay;
|
|
return oRoot;
|
|
}
|
|
|
|
void eText::setTextContents(QTextDocument &doc)
|
|
{
|
|
const int lineSpacing = QFontMetrics(m_attr.font).lineSpacing();
|
|
m_lineH = m_attr.lineSpacing + lineSpacing;
|
|
|
|
QString ctx = QString("<style>p{"
|
|
"color:rgba(%1,%2,%3,%4);"
|
|
"line-height:%5px;"
|
|
"white-space:pre-wrap;"
|
|
"}</style>"
|
|
"<p>%6</p>")
|
|
.arg(m_attr.cText.red()).arg(m_attr.cText.green())
|
|
.arg(m_attr.cText.blue()).arg(m_attr.cText.alpha())
|
|
.arg(m_lineH)
|
|
.arg(m_attr.text);
|
|
doc.setHtml(ctx);
|
|
}
|
|
|
|
void eText::setTextVAlign(int align, QTextDocument &doc)
|
|
{
|
|
qreal ls, ofs_h, ofs_v;
|
|
qreal painter_x, painter_y;
|
|
qreal clip_x, clip_y, clip_w, clip_h;
|
|
QRectF r = rect();
|
|
QSizeF s = doc.size();
|
|
align &= Qt::AlignVertical_Mask;
|
|
|
|
if(s.height() > r.height()) {
|
|
int num = static_cast<int>(r.height()) / m_lineH;
|
|
ofs_h = r.height() - m_lineH * num;
|
|
clip_x = r.x();
|
|
clip_y = r.y();
|
|
clip_w = r.width();
|
|
clip_h = num ? m_lineH * num : 0.000001;
|
|
r = QRectF(clip_x, clip_y, clip_w, clip_h);
|
|
ls = rect().height() - clip_h + QFontMetrics(m_attr.font).leading();
|
|
} else {
|
|
ls = QFontMetrics(m_attr.font).leading() + m_attr.lineSpacing;
|
|
}
|
|
|
|
clip_x = 0;
|
|
clip_y = 0;
|
|
clip_w = r.width();
|
|
clip_h = (s.height() < r.height()) ? s.height() : r.height();
|
|
|
|
painter_x = r.x();
|
|
switch (align) {
|
|
case Qt::AlignTop:
|
|
ofs_v = 0;
|
|
painter_y = 0;
|
|
break;
|
|
case Qt::AlignVCenter:
|
|
ofs_v = (r.height() - s.height()) / 2;
|
|
painter_y = (s.height() < r.height()) ? r.y() + ofs_v : 0;
|
|
painter_y += ls / 2;
|
|
break;
|
|
case Qt::AlignBottom:
|
|
ofs_v = r.height() - s.height();
|
|
painter_y = (s.height() < r.height()) ? r.y() + ofs_v : 0;
|
|
painter_y += ls;
|
|
break;
|
|
default:
|
|
return;
|
|
}
|
|
|
|
m_pText = QPointF(painter_x, painter_y);
|
|
m_rClip = QRectF(clip_x, clip_y, clip_w, clip_h);
|
|
}
|
|
|
|
void eText::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
|
|
{
|
|
painter->save();
|
|
|
|
QBrush bshBackground = LoAppTools::getInstance()->getBrush(m_attr.cBackground);
|
|
if(bshBackground != Qt::NoBrush) {
|
|
#if 1
|
|
painter->fillRect(rect(), bshBackground);
|
|
#else
|
|
QRectF r = rect();
|
|
qreal x, y, w, h;
|
|
x = r.x() - 1;
|
|
y = r.y() - 1;
|
|
w = r.width() + 2;
|
|
h = r.height() + 2;
|
|
r = QRectF(x, y, w, h);
|
|
painter->fillRect(r, bshBackground);
|
|
#endif
|
|
}
|
|
|
|
QBrush bshTextShadow = LoAppTools::getInstance()->getBrush(m_attr.cTextShadow);
|
|
if(bshTextShadow != Qt::NoBrush) {
|
|
painter->setBackgroundMode(Qt::OpaqueMode);
|
|
painter->setBackground(bshTextShadow);
|
|
}
|
|
#if 0
|
|
painter->setPen(m_attr.pen);
|
|
painter->setFont(m_attr.font);
|
|
painter->drawText(rect(), m_attr.text, m_attr.opt);
|
|
#else
|
|
QTextDocument doc;
|
|
doc.setDefaultFont(m_attr.font);
|
|
doc.setDefaultTextOption(m_attr.opt);
|
|
doc.setDocumentMargin(0);
|
|
doc.setTextWidth(rect().width());
|
|
setTextContents(doc);
|
|
setTextVAlign(m_attr.opt.alignment(), doc);
|
|
painter->translate(m_pText);
|
|
doc.drawContents(painter, m_rClip);
|
|
// qDebug() << "Block Count:" << doc.blockCount();
|
|
#endif
|
|
|
|
painter->restore();
|
|
LoQGraphicsObject::paint(painter, option, widget);
|
|
}
|
|
|
|
void eText::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event)
|
|
{
|
|
if(Qt::LeftButton == event->button()) {
|
|
setInput();
|
|
}
|
|
}
|
|
|
|
void eText::setInput()
|
|
{
|
|
if(nullptr == m_wTextInput && nullptr != m_wAttr) {
|
|
m_wTextInput = new eTextInput(m_attr.text, m_wAttr);
|
|
connect(m_wTextInput, SIGNAL(sTextChanged(const QString &)), this, SLOT(onTextChanged(const QString &)));
|
|
connect(m_wTextInput, SIGNAL(destroyed(QObject*)), this, SLOT(onInputClosed()));
|
|
m_wTextInput->show();
|
|
}
|
|
}
|
|
|
|
void eText::onTextHAlignChanged(int align)
|
|
{
|
|
int res = m_attr.opt.alignment();
|
|
res &= ~Qt::AlignHorizontal_Mask;
|
|
res |= align;
|
|
m_attr.opt.setAlignment(static_cast<Qt::Alignment>(res));
|
|
updateGeometry();
|
|
}
|
|
|
|
void eText::onTextVAlignChanged(int align)
|
|
{
|
|
int res = m_attr.opt.alignment();
|
|
res &= ~Qt::AlignVertical_Mask;
|
|
res |= align;
|
|
m_attr.opt.setAlignment(static_cast<Qt::Alignment>(res));
|
|
updateGeometry();
|
|
}
|