840 lines
31 KiB
C++
840 lines
31 KiB
C++
#include "base/locolorselector.h"
|
|
#include "etext.h"
|
|
#include "globaldefine.h"
|
|
#include "tools.h"
|
|
#include <QBoxLayout>
|
|
#include <QButtonGroup>
|
|
#include <QFontComboBox>
|
|
#include <QJsonArray>
|
|
#include <QMessageBox>
|
|
#include <QRadioButton>
|
|
#include <QSpinBox>
|
|
#include <QStackedLayout>
|
|
#include <QTextBlock>
|
|
#if(QT_VERSION_MAJOR > 5)
|
|
#include <QStringConverter>
|
|
#else
|
|
#include <QTextCodec>
|
|
#endif
|
|
#include <QTimeEdit>
|
|
#include <QToolButton>
|
|
#include <QPainter>
|
|
#include <QLabel>
|
|
|
|
static QColor charColors[]{"#fff","#f00","#f00","#f0f","#c0c","#ff0","#f80","#0f0","#0f0","#0a0","#0a0","#7b0","#00f","#00f","#0af","#0ef"};
|
|
|
|
EText::EText(EBase *multiWin) : EBase(multiWin) {
|
|
mType = EBase::Text;
|
|
m_attr.text = "<body>"+tr("Enter your text")+"</body>";
|
|
connect(this, &EText::sizeChanged, this, &EText::updImg);
|
|
updImg();
|
|
}
|
|
EText::EText(const JObj &json, EBase *multiWin) : EBase(multiWin) {
|
|
mType = EBase::Text;
|
|
setBaseAttr(json);
|
|
setElement(json, m_attr);
|
|
connect(this, &EText::sizeChanged, this, &EText::updImg);
|
|
updImg();
|
|
}
|
|
|
|
void EText::setElement(const JObj &json, Data &attr) {
|
|
auto widget = json["widget"];
|
|
attr.text = widget["text"].toString();
|
|
attr.align = static_cast<Qt::Alignment>(widget["align"].toInt());
|
|
attr.backColor = widget["backColor"].toString("#00000000");
|
|
auto play = json["play"];
|
|
attr.playMode = play["style"].toInt();
|
|
auto turning = play["turning"];
|
|
attr.flip.effect = turning["strEffect"].toString();
|
|
attr.flip.pageDuration = turning["iEffectTime"].toInt();
|
|
attr.flip.effectDuration = turning["iEffectSpeed"].toInt();
|
|
auto rolling = play["rolling"];
|
|
attr.scroll.effect = rolling["rollingStyle"].toInt();
|
|
attr.scroll.effectSpeed = rolling["rollingSpeed"].toInt();
|
|
attr.scroll.headTailSpacing = rolling["headTailSpacing"].toInt();
|
|
attr.scroll.duration = rolling["playDuration"].toInt();
|
|
attr.duration = play["static"]["playDuration"].toInt();
|
|
}
|
|
|
|
class TTextEdit : public QTextEdit {
|
|
public:
|
|
TTextEdit() {}
|
|
explicit TTextEdit(const QString &text) : QTextEdit(text){}
|
|
QSize minimumSizeHint() const override {
|
|
return sizeHint();
|
|
};
|
|
QSize sizeHint() const override {
|
|
auto size = QTextEdit::sizeHint();
|
|
auto minH = minimumHeight();
|
|
if(minH > 0) size.setHeight(minH+0xfff);
|
|
return size;
|
|
};
|
|
};
|
|
QWidget* EText::attrWgt() {
|
|
auto wgtAttr = new QWidget;
|
|
auto vBox = new QVBoxLayout(wgtAttr);
|
|
vBox->setContentsMargins(4, 0, 4, 0);
|
|
vBox->setSpacing(3);
|
|
|
|
addBaseAttrWgt(vBox);
|
|
|
|
auto hBox = new QHBoxLayout;
|
|
hBox->addWidget(new QLabel(tr("Basic Properties")));
|
|
|
|
auto line = new QFrame;
|
|
line->setFrameShape(QFrame::HLine);
|
|
line->setFrameShadow(QFrame::Sunken);
|
|
hBox->addWidget(line, 1);
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout;
|
|
|
|
auto fdText = new TTextEdit("");
|
|
|
|
auto fdFontFamily = new QFontComboBox;
|
|
fdFontFamily->setEditable(false);
|
|
fdFontFamily->setCurrentFont(QFont("黑体"));
|
|
connect(fdFontFamily, &QFontComboBox::currentFontChanged, fdText, [fdText](const QFont &f) {
|
|
QTextCharFormat fmt;
|
|
fmt.setFontFamilies({f.family()});
|
|
QTextCursor cursor = fdText->textCursor();
|
|
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
|
|
cursor.mergeCharFormat(fmt);
|
|
});
|
|
hBox->addWidget(fdFontFamily);
|
|
|
|
hBox->addStretch();
|
|
|
|
auto fdFontSize = new QSpinBox;
|
|
fdFontSize->setRange(4, 9999);
|
|
fdFontSize->setValue(16);
|
|
connect(fdFontSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, fdText, [fdText](int value) {
|
|
if(value <= 0) return;
|
|
QTextCharFormat fmt;
|
|
fmt.setProperty(QTextFormat::FontPixelSize, value);
|
|
QTextCursor cursor = fdText->textCursor();
|
|
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
|
|
cursor.mergeCharFormat(fmt);
|
|
});
|
|
hBox->addWidget(fdFontSize);
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout;
|
|
hBox->setSpacing(3);
|
|
|
|
auto wTextAlignHL = new QPushButton(QIcon(":/res/program/TextAlignHL.png"), "");
|
|
wTextAlignHL->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
|
|
wTextAlignHL->setFixedSize(30, 30);
|
|
wTextAlignHL->setIconSize(QSize(30, 30));
|
|
wTextAlignHL->setCheckable(true);
|
|
wTextAlignHL->setChecked(true);
|
|
hBox->addWidget(wTextAlignHL);
|
|
|
|
auto wTextAlignHC = new QPushButton(QIcon(":/res/program/TextAlignHC.png"), "");
|
|
wTextAlignHC->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
|
|
wTextAlignHC->setFixedSize(30, 30);
|
|
wTextAlignHC->setIconSize(QSize(30, 30));
|
|
wTextAlignHC->setCheckable(true);
|
|
hBox->addWidget(wTextAlignHC);
|
|
|
|
auto wTextAlignHR = new QPushButton(QIcon(":/res/program/TextAlignHR.png"), "");
|
|
wTextAlignHR->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
|
|
wTextAlignHR->setFixedSize(30, 30);
|
|
wTextAlignHR->setIconSize(QSize(30, 30));
|
|
wTextAlignHR->setCheckable(true);
|
|
hBox->addWidget(wTextAlignHR);
|
|
|
|
hBox->addStretch();
|
|
|
|
auto fdFontBold = new QPushButton("B");
|
|
fdFontBold->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-weight: bold;} QPushButton:checked{background: #29c; color: #fff;}");
|
|
fdFontBold->setFixedSize(30, 30);
|
|
fdFontBold->setCheckable(true);
|
|
connect(fdFontBold, &QToolButton::toggled, fdText, [fdText](bool checked) {
|
|
QTextCharFormat fmt;
|
|
fmt.setFontWeight(checked ? QFont::Bold : QFont::Normal);
|
|
Tools::mergeFormat(fdText, fmt);
|
|
});
|
|
hBox->addWidget(fdFontBold);
|
|
|
|
auto fdFontItalic = new QPushButton("I");
|
|
fdFontItalic->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; font-style: italic;} QPushButton:checked{background: #29c; color: #fff;}");
|
|
fdFontItalic->setFixedSize(30, 30);
|
|
fdFontItalic->setCheckable(true);
|
|
connect(fdFontItalic, &QToolButton::toggled, fdText, [fdText](bool checked) {
|
|
QTextCharFormat fmt;
|
|
fmt.setFontItalic(checked);
|
|
Tools::mergeFormat(fdText, fmt);
|
|
});
|
|
hBox->addWidget(fdFontItalic);
|
|
|
|
auto fdFontUnderline = new QPushButton("U");
|
|
fdFontUnderline->setStyleSheet("QPushButton{background: #bbb; color: #888; font-size: 20px; text-decoration: underline;} QPushButton:checked{background: #29c; color: #fff;}");
|
|
fdFontUnderline->setFixedSize(30, 30);
|
|
fdFontUnderline->setCheckable(true);
|
|
connect(fdFontUnderline, &QToolButton::toggled, fdText, [fdText](bool checked) {
|
|
QTextCharFormat fmt;
|
|
fmt.setFontUnderline(checked);
|
|
Tools::mergeFormat(fdText, fmt);
|
|
});
|
|
hBox->addWidget(fdFontUnderline);
|
|
|
|
hBox->addStretch();
|
|
|
|
auto fdTextColor = new LoColorSelector("T", Qt::white);
|
|
fdTextColor->setToolTip(tr("Text Color"));
|
|
fdTextColor->setFixedSize(30, 30);
|
|
connect(fdTextColor, &LoColorSelector::sColorChanged, fdText, [fdText](const QColor &color) {
|
|
if(! color.isValid()) return;
|
|
QTextCharFormat fmt;
|
|
fmt.setForeground(color);
|
|
Tools::mergeFormat(fdText, fmt);
|
|
});
|
|
hBox->addWidget(fdTextColor);
|
|
|
|
auto fdBackColor = new LoColorSelector("B", m_attr.backColor);
|
|
fdBackColor->setToolTip(tr("Back Color"));
|
|
fdBackColor->setFixedSize(30, 30);
|
|
connect(fdBackColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) {
|
|
if(! color.isValid()) return;
|
|
m_attr.backColor = color;
|
|
updImg();
|
|
});
|
|
hBox->addWidget(fdBackColor);
|
|
|
|
auto fdRandomColor = new QPushButton(QIcon(":/res/random.png"), "");
|
|
fdRandomColor->setToolTip(tr("Colorful Text"));
|
|
fdRandomColor->setFixedSize(30, 30);
|
|
fdRandomColor->setIconSize(QSize(30, 30));
|
|
connect(fdRandomColor, &QPushButton::clicked, fdText, [fdText] {
|
|
auto cursor = fdText->textCursor();
|
|
auto len = fdText->document()->characterCount();
|
|
QTextCharFormat fmt;
|
|
int last = -1, idx;
|
|
for(int i=0; i<len; i++) {
|
|
cursor.setPosition(i, QTextCursor::MoveAnchor);
|
|
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
|
|
while((idx = rand()%(sizeof(charColors)/sizeof(charColors[0])))==last) ;
|
|
last = idx;
|
|
fmt.setForeground(charColors[idx]);
|
|
cursor.mergeCharFormat(fmt);
|
|
}
|
|
});
|
|
hBox->addWidget(fdRandomColor);
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout;
|
|
hBox->setSpacing(3);
|
|
|
|
auto wTextAlignVT = new QPushButton(QIcon(":/res/program/TextAlignVT.png"), "");
|
|
wTextAlignVT->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
|
|
wTextAlignVT->setFixedSize(30, 30);
|
|
wTextAlignVT->setIconSize(QSize(30, 30));
|
|
wTextAlignVT->setCheckable(true);
|
|
hBox->addWidget(wTextAlignVT);
|
|
|
|
auto wTextAlignVC = new QPushButton(QIcon(":/res/program/TextAlignVC.png"), "");
|
|
wTextAlignVC->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
|
|
wTextAlignVC->setFixedSize(30, 30);
|
|
wTextAlignVC->setIconSize(QSize(30, 30));
|
|
wTextAlignVC->setCheckable(true);
|
|
hBox->addWidget(wTextAlignVC);
|
|
|
|
auto wTextAlignVB = new QPushButton(QIcon(":/res/program/TextAlignVB.png"), "");
|
|
wTextAlignVB->setStyleSheet("QPushButton{border: none; background: #bbb;} QPushButton:checked{background: #29c;}");
|
|
wTextAlignVB->setFixedSize(30, 30);
|
|
wTextAlignVB->setIconSize(QSize(30, 30));
|
|
wTextAlignVB->setCheckable(true);
|
|
hBox->addWidget(wTextAlignVB);
|
|
|
|
hBox->addStretch();
|
|
|
|
auto lb = new QLabel(tr("Kerning"));
|
|
lb->setToolTip(lb->text());
|
|
hBox->addWidget(lb);
|
|
|
|
auto fdLetterSpacing = new QSpinBox();
|
|
fdLetterSpacing->setMaximum(999);
|
|
connect(fdLetterSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdText](int value) {
|
|
QTextCharFormat fmt;
|
|
fmt.setFontLetterSpacing(value);
|
|
QTextCursor cursor = fdText->textCursor();
|
|
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
|
|
cursor.mergeCharFormat(fmt);
|
|
updImg();
|
|
});
|
|
hBox->addWidget(fdLetterSpacing);
|
|
|
|
lb = new QLabel(tr("Line Spacing"));
|
|
lb->setToolTip(lb->text());
|
|
hBox->addWidget(lb);
|
|
|
|
auto fdLineSpacing = new QSpinBox();
|
|
fdLineSpacing->setRange(-99, 999);
|
|
connect(fdLineSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this, fdText](int value) {
|
|
QTextBlockFormat fmt;
|
|
fmt.setLineHeight(value, QTextBlockFormat::LineDistanceHeight);
|
|
QTextCursor cursor = fdText->textCursor();
|
|
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
|
|
cursor.mergeBlockFormat(fmt);
|
|
updImg();
|
|
});
|
|
hBox->addWidget(fdLineSpacing);
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
auto wTextAlignH = new QButtonGroup(wgtAttr);
|
|
wTextAlignH->addButton(wTextAlignHL, Qt::AlignLeft);
|
|
wTextAlignH->addButton(wTextAlignHC, Qt::AlignHCenter);
|
|
wTextAlignH->addButton(wTextAlignHR, Qt::AlignRight);
|
|
connect(wTextAlignH, &QButtonGroup::idClicked, this, [this, fdText](int value) {
|
|
QTextBlockFormat fmt;
|
|
fmt.setAlignment((Qt::Alignment) value);
|
|
QTextCursor cursor = fdText->textCursor();
|
|
cursor.mergeBlockFormat(fmt);
|
|
updImg();
|
|
});
|
|
|
|
auto wTextAlignV = new QButtonGroup(wgtAttr);
|
|
wTextAlignV->addButton(wTextAlignVT, Qt::AlignTop);
|
|
wTextAlignV->addButton(wTextAlignVC, Qt::AlignVCenter);
|
|
wTextAlignV->addButton(wTextAlignVB, Qt::AlignBottom);
|
|
connect(wTextAlignV, &QButtonGroup::idClicked, this, [this](int value) {
|
|
m_attr.align = (Qt::Alignment) value;
|
|
updImg();
|
|
});
|
|
|
|
auto v_align = m_attr.align & Qt::AlignVertical_Mask;
|
|
if(v_align==Qt::AlignTop) wTextAlignVT->setChecked(true);
|
|
if(v_align==Qt::AlignVCenter) wTextAlignVC->setChecked(true);
|
|
if(v_align==Qt::AlignBottom) wTextAlignVB->setChecked(true);
|
|
|
|
fdText->setMinimumHeight(160);
|
|
auto doc = fdText->document();
|
|
if(doc) doc->setDocumentMargin(2);
|
|
auto font = fdText->font();
|
|
font.setFamilies({"Arial","黑体"});
|
|
font.setPixelSize(16);
|
|
if(! gTextAntialiasing) font.setStyleStrategy(QFont::NoAntialias);
|
|
fdText->setFont(font);
|
|
auto pal = fdText->palette();
|
|
pal.setColor(QPalette::Base, Qt::black);
|
|
pal.setColor(QPalette::Text, Qt::white);
|
|
fdText->setPalette(pal);
|
|
fdText->setFrameShape(QFrame::NoFrame);
|
|
fdText->setAcceptRichText(false);
|
|
fdText->setHtml(m_attr.text);
|
|
connect(fdText, &QTextEdit::textChanged, this, [this, fdText] {
|
|
m_attr.text = fdText->toHtml();
|
|
updImg();
|
|
});
|
|
connect(fdText, &QTextEdit::currentCharFormatChanged, this, [=](const QTextCharFormat &format) {
|
|
fdFontSize->blockSignals(true);
|
|
fdFontSize->setValue(format.font().pixelSize());
|
|
fdFontSize->blockSignals(false);
|
|
auto foreground = format.foreground();
|
|
fdTextColor->blockSignals(true);
|
|
fdTextColor->setColor(foreground.style()==Qt::NoBrush ? Qt::white : foreground.color());
|
|
fdTextColor->blockSignals(false);
|
|
});
|
|
vBox->addWidget(fdText);
|
|
|
|
hBox = new QHBoxLayout;
|
|
hBox->addStretch();
|
|
|
|
auto pageInfoWgt = new QWidget;
|
|
auto hhh = new QHBoxLayout(pageInfoWgt);
|
|
hhh->setContentsMargins(0,0,0,0);
|
|
|
|
hhh->addWidget(new QLabel(tr("PageCount:")));
|
|
|
|
auto fdPageCnt = new QLabel(QString::number(mImgs.size()));
|
|
hhh->addWidget(fdPageCnt);
|
|
|
|
hhh->addSpacing(20);
|
|
hhh->addWidget(new QLabel(tr("page")));
|
|
|
|
auto fdPageIdx = new QSpinBox();
|
|
fdPageIdx->setRange(1, mImgs.size());
|
|
connect(fdPageIdx, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int idx) {
|
|
curIdx = idx - 1;
|
|
update();
|
|
});
|
|
hhh->addWidget(fdPageIdx);
|
|
hBox->addWidget(pageInfoWgt);
|
|
|
|
hBox->addStretch();
|
|
|
|
auto btnImport = new QPushButton(tr("Import txt File"));
|
|
btnImport->setProperty("ssType", "progManageTool");
|
|
connect(btnImport, &QPushButton::clicked, fdText, [=] {
|
|
auto filePath = QFileDialog::getOpenFileName(wgtAttr, tr("Select File"), gFileHome, "Txt(*.txt)");
|
|
if(filePath.isEmpty()) return;
|
|
QFile qFile(filePath);
|
|
if(! qFile.open(QFile::ReadOnly)) {
|
|
QMessageBox::critical(wgtAttr, tr("Fail"), tr("Cannot Open File")+": "+qFile.errorString()+"\n"+filePath);
|
|
return;
|
|
}
|
|
auto data = qFile.readAll();
|
|
qFile.close();
|
|
#if(QT_VERSION_MAJOR > 5)
|
|
#include <QStringConverter>
|
|
QStringDecoder decoder(QStringDecoder::Utf8);
|
|
QString text = decoder(data);
|
|
if(decoder.hasError()) text = QStringDecoder(QStringDecoder::System)(data);
|
|
#else
|
|
QTextCodec::ConverterState state;
|
|
auto text = QTextCodec::codecForName("UTF-8")->toUnicode(data.constData(), data.size(), &state);
|
|
if(state.invalidChars > 0) text = QString::fromLocal8Bit(data);
|
|
#endif
|
|
fdText->setText(text);
|
|
});
|
|
hBox->addWidget(btnImport);
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout;
|
|
hBox->addWidget(new QLabel(tr("Play Properties")));
|
|
|
|
line = new QFrame();
|
|
line->setFrameShape(QFrame::HLine);
|
|
line->setFrameShadow(QFrame::Sunken);
|
|
hBox->addWidget(line, 1);
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout;
|
|
hBox->addStretch();
|
|
|
|
auto fdFlip = new QRadioButton(tr("Flip"));
|
|
hBox->addWidget(fdFlip);
|
|
hBox->addStretch();
|
|
|
|
auto fdScroll = new QRadioButton(tr("Scroll"));
|
|
hBox->addWidget(fdScroll);
|
|
hBox->addStretch();
|
|
|
|
auto fdStatic = new QRadioButton(tr("Static"));
|
|
hBox->addWidget(fdStatic);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
auto fdPlayStyle = new QButtonGroup(wgtAttr);
|
|
fdPlayStyle->addButton(fdFlip, EText::Flip);
|
|
fdPlayStyle->addButton(fdScroll, EText::Scroll);
|
|
fdPlayStyle->addButton(fdStatic, EText::Static);
|
|
if(m_attr.playMode==EText::Flip) fdFlip->setChecked(true);
|
|
else if(m_attr.playMode==EText::Scroll) fdScroll->setChecked(true);
|
|
else if(m_attr.playMode==EText::Static) fdStatic->setChecked(true);
|
|
|
|
auto wgtAttrFlip = new QWidget();
|
|
auto fdDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.flip.pageDuration * mImgs.size() * 1000));
|
|
auto fdPageDur = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.flip.pageDuration * 1000));
|
|
{
|
|
auto vBox = new QVBoxLayout(wgtAttrFlip);
|
|
vBox->setContentsMargins(2, 0, 2, 0);
|
|
vBox->setSpacing(3);
|
|
|
|
hBox = new QHBoxLayout;
|
|
|
|
auto label = new QLabel(tr("Play Duration"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
fdDur->setReadOnly(true);
|
|
fdDur->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
|
fdDur->setDisplayFormat("H:mm:ss");
|
|
fdDur->setStyleSheet("QTimeEdit{background-color:#ddd;}");
|
|
hBox->addWidget(fdDur);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout();
|
|
|
|
label = new QLabel(tr("Duration/Page"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
fdPageDur->setDisplayFormat("H:mm:ss");
|
|
fdPageDur->setCurrentSection(QTimeEdit::SecondSection);
|
|
hBox->addWidget(fdPageDur);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout();
|
|
|
|
label = new QLabel(tr("Entrance Effect"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto fdEff = new QComboBox();
|
|
fdEff->addItem(tr("no"), "no");
|
|
fdEff->addItem(tr("random"), "random");
|
|
fdEff->addItem(tr("right to left"), "right to left");
|
|
fdEff->addItem(tr("bottom to top"), "bottom to top");
|
|
fdEff->addItem(tr("left to right"), "left to right");
|
|
fdEff->addItem(tr("top to bottom"), "top to bottom");
|
|
int idx = fdEff->findData(m_attr.flip.effect);
|
|
if(idx!=-1) fdEff->setCurrentIndex(idx);
|
|
connect(fdEff, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this, fdEff] {
|
|
m_attr.flip.effect = fdEff->currentData().toString();
|
|
update();
|
|
});
|
|
hBox->addWidget(fdEff);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout();
|
|
|
|
label = new QLabel(tr("Effect time"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto wEffectSpeed = new QSpinBox();
|
|
wEffectSpeed->setValue(m_attr.flip.effectDuration);
|
|
hBox->addWidget(wEffectSpeed);
|
|
hBox->addWidget(new QLabel(tr("s")));
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
vBox->addStretch();
|
|
|
|
connect(fdPageDur, &QTimeEdit::timeChanged, this, [=](const QTime &time) {
|
|
int effDur = wEffectSpeed->value();
|
|
int pageDur = time.msecsSinceStartOfDay()/1000;
|
|
if(pageDur < effDur) {
|
|
QMessageBox::warning(wgtAttr, tr("Tip Info"), tr("Effect time cannot be longer than duration time"));
|
|
pageDur = effDur;
|
|
fdPageDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur*1000));
|
|
fdPageDur->setFocus();
|
|
}
|
|
m_attr.flip.pageDuration = pageDur;
|
|
fdDur->setTime(QTime::fromMSecsSinceStartOfDay(pageDur * mImgs.size() * 1000));
|
|
});
|
|
connect(wEffectSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [=](int value) {
|
|
int pageDur = fdPageDur->time().msecsSinceStartOfDay()/1000;
|
|
if(value > pageDur) {
|
|
QMessageBox::warning(wgtAttr, tr("Tip Info"), tr("Effect time cannot be longer than duration time"));
|
|
if(pageDur>1) value = pageDur-1;
|
|
else value = 0;
|
|
wEffectSpeed->setValue(value);
|
|
wEffectSpeed->setFocus();
|
|
}
|
|
m_attr.flip.effectDuration = value;
|
|
});
|
|
}
|
|
auto wgtAttrScroll = new QWidget();
|
|
{
|
|
auto vBox = new QVBoxLayout(wgtAttrScroll);
|
|
vBox->setContentsMargins(2, 0, 2, 0);
|
|
vBox->setSpacing(3);
|
|
|
|
auto hBox = new QHBoxLayout();
|
|
|
|
auto label = new QLabel(tr("Play Duration"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.scroll.duration*1000));
|
|
timeEdit->setDisplayFormat("H:mm:ss");
|
|
timeEdit->setCurrentSectionIndex(2);
|
|
connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) {
|
|
m_attr.scroll.duration = time.msecsSinceStartOfDay()/1000;
|
|
});
|
|
hBox->addWidget(timeEdit);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout();
|
|
|
|
label = new QLabel(tr("Head-Tail Spacing"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto wHeadTailSpacing = new QSpinBox;
|
|
wHeadTailSpacing->setRange(0, 9999);
|
|
wHeadTailSpacing->setValue(m_attr.scroll.headTailSpacing);
|
|
connect(wHeadTailSpacing, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
|
|
m_attr.scroll.headTailSpacing = value;
|
|
});
|
|
hBox->addWidget(wHeadTailSpacing);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout();
|
|
|
|
label = new QLabel(tr("Scroll Style"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto wRollingStyle = new QComboBox;
|
|
wRollingStyle->addItem(tr("Right -> Left"));
|
|
wRollingStyle->addItem(tr("Bottom -> Top"));
|
|
wRollingStyle->addItem(tr("Left -> Right"));
|
|
wRollingStyle->addItem(tr("Top -> Bottom"));
|
|
wRollingStyle->setCurrentIndex(m_attr.scroll.effect);
|
|
connect(wRollingStyle, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) {
|
|
m_attr.scroll.effect = index;
|
|
updImg();
|
|
});
|
|
hBox->addWidget(wRollingStyle);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
|
|
hBox = new QHBoxLayout();
|
|
|
|
label = new QLabel(tr("Scroll Speed"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto wRollingSpeed = new QSpinBox();
|
|
wRollingSpeed->setMaximum(9999);
|
|
wRollingSpeed->setValue(m_attr.scroll.effectSpeed);
|
|
connect(wRollingSpeed, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) {
|
|
m_attr.scroll.effectSpeed = value;
|
|
});
|
|
hBox->addWidget(wRollingSpeed);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
vBox->addStretch();
|
|
}
|
|
auto wgtAttrStatic = new QWidget();
|
|
{
|
|
auto vBox = new QVBoxLayout(wgtAttrStatic);
|
|
vBox->setContentsMargins(2, 0, 2, 0);
|
|
vBox->setSpacing(3);
|
|
|
|
hBox = new QHBoxLayout();
|
|
auto label = new QLabel(tr("Play Duration"));
|
|
label->setMinimumWidth(100);
|
|
hBox->addWidget(label);
|
|
|
|
auto timeEdit = new QTimeEdit(QTime::fromMSecsSinceStartOfDay(m_attr.duration*1000));
|
|
timeEdit->setDisplayFormat("H:mm:ss");
|
|
timeEdit->setCurrentSectionIndex(2);
|
|
connect(timeEdit, &QTimeEdit::timeChanged, this, [this](const QTime &time) {
|
|
m_attr.duration = time.msecsSinceStartOfDay() / 1000;
|
|
});
|
|
hBox->addWidget(timeEdit);
|
|
hBox->addStretch();
|
|
|
|
vBox->addLayout(hBox);
|
|
vBox->addStretch();
|
|
}
|
|
auto stackBox = new QStackedLayout;
|
|
vBox->addLayout(stackBox);
|
|
stackBox->addWidget(wgtAttrFlip);
|
|
stackBox->addWidget(wgtAttrScroll);
|
|
stackBox->addWidget(wgtAttrStatic);
|
|
stackBox->setCurrentIndex(m_attr.playMode);
|
|
connect(fdPlayStyle, &QButtonGroup::idToggled, this, [this, stackBox, pageInfoWgt](int value, bool checked) {
|
|
if(! checked) return;
|
|
m_attr.playMode = value;
|
|
updImg();
|
|
stackBox->setCurrentIndex(value);
|
|
pageInfoWgt->setVisible(value==Flip);
|
|
});
|
|
connect(this, &EText::updPageCnt, wgtAttr, [this, fdPageCnt, fdPageIdx, fdPageDur, fdDur] {
|
|
fdPageCnt->setText(QString::number(mImgs.size()));
|
|
fdPageIdx->setRange(1, mImgs.size());
|
|
fdPageIdx->setValue(1);
|
|
fdDur->setTime(QTime::fromMSecsSinceStartOfDay(fdPageDur->time().msecsSinceStartOfDay() * mImgs.size()));
|
|
});
|
|
return wgtAttr;
|
|
}
|
|
|
|
bool EText::save(const QString &pageDir) {
|
|
QString idDir = pageDir + QString("/%1-%2-%3-%4-%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight);
|
|
QDir().mkpath(idDir);
|
|
for(int i=0; i<mImgs.count(); i++) mImgs[i].save(idDir + QString("/text%1.png").arg(i));
|
|
return true;
|
|
}
|
|
JObj EText::attrJson() const {
|
|
JArray files;
|
|
for(int i=0; i<mImgs.count(); i++) files.append(QString("text%1.png").arg(i)); //上下滚动,生成一张纵向长图
|
|
JObj obj;
|
|
addBaseAttr(obj);
|
|
obj["elementType"] = "Text";
|
|
obj["widget"] = JObj{
|
|
{"text", m_attr.text},
|
|
{"align", (int) m_attr.align},
|
|
{"backColor", m_attr.backColor.name(QColor::HexArgb)},
|
|
{"files", files},
|
|
{"idDir", QString("%1-%2-%3-%4-%5").arg(zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight)}
|
|
};
|
|
obj["play"] = JObj{
|
|
{"style", m_attr.playMode},
|
|
{"turning", JObj{
|
|
{"strEffect", m_attr.flip.effect},
|
|
{"iEffectTime", m_attr.flip.pageDuration},
|
|
{"iEffectSpeed", m_attr.flip.effectDuration}
|
|
}},
|
|
{"rolling", JObj{
|
|
{"rollingStyle", m_attr.scroll.effect},
|
|
{"rollingSpeed", m_attr.scroll.effectSpeed},
|
|
{"headTailSpacing", m_attr.scroll.headTailSpacing},
|
|
{"playDuration", m_attr.scroll.duration}
|
|
}},
|
|
{"static", JObj{{"playDuration", m_attr.duration}}}
|
|
};
|
|
return obj;
|
|
}
|
|
|
|
void EText::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
|
|
painter->save();
|
|
auto rect = innerRect();
|
|
if(m_attr.playMode!=EText::Flip) curIdx = 0;
|
|
else if(curIdx>=mImgs.size()) curIdx = mImgs.size() - 1;
|
|
else if(curIdx < 0) curIdx = 0;
|
|
if(m_attr.playMode==EText::Scroll) painter->drawImage(rect.x(), rect.y(), mImgs[0], 0, 0, rect.width(), rect.height());
|
|
else painter->drawImage(rect.x(), rect.y(), mImgs[curIdx]);
|
|
painter->restore();
|
|
EBase::paint(painter, option, widget);
|
|
}
|
|
|
|
void EText::updImg() {
|
|
auto innerRect = this->innerRect();
|
|
int width = innerRect.width();
|
|
int height = innerRect.height();
|
|
if(width<1 || height<1) return;
|
|
QTextDocument doc;
|
|
doc.setDocumentMargin(0);
|
|
QFont font;
|
|
font.setFamilies({"Arial","黑体"});
|
|
font.setPixelSize(16);
|
|
if(! gTextAntialiasing) font.setStyleStrategy(QFont::NoAntialias);
|
|
doc.setDefaultFont(font);
|
|
doc.setDefaultStyleSheet("body {color: #fff;}");
|
|
doc.setHtml(m_attr.text);
|
|
if(m_attr.playMode==EText::Flip) {
|
|
doc.setPageSize(innerRect.size());
|
|
auto pageHeight = height;
|
|
auto pageCnt = doc.pageCount();
|
|
QImage img(width, pageHeight*pageCnt, QImage::Format_ARGB32);
|
|
img.fill(m_attr.backColor);
|
|
{
|
|
QPainter painter(&img);
|
|
doc.drawContents(&painter);
|
|
}
|
|
if(pageCnt > 1) {
|
|
check:
|
|
for(int y=pageHeight-1; y<img.height(); y+=pageHeight) for(int x=0; x<width; x++) if(img.pixelColor(x, y)!=m_attr.backColor) {
|
|
pageHeight *= 2;
|
|
doc.setPageSize(QSizeF(width, pageHeight));
|
|
pageCnt = doc.pageCount();
|
|
img = QImage(width, pageHeight*pageCnt, QImage::Format_ARGB32);
|
|
img.fill(m_attr.backColor);
|
|
{
|
|
QPainter painter(&img);
|
|
doc.drawContents(&painter);
|
|
}
|
|
if(pageHeight/height <= 16) goto check;
|
|
else goto forend;
|
|
}
|
|
if(pageCnt > 1) {
|
|
for(int y=img.height()-pageHeight; y<img.height(); y++) for(int x=0; x<width; x++) if(img.pixelColor(x, y)!=m_attr.backColor) goto forend;
|
|
pageCnt--;
|
|
}
|
|
}
|
|
forend:
|
|
QRect rect(0, 0, width, pageHeight);
|
|
mImgs.clear();
|
|
for(int i=0; i<pageCnt; i++) {
|
|
auto pageImg = img.copy(rect);
|
|
alignV(pageImg, height);
|
|
mImgs.append(pageImg);
|
|
rect.translate(0, pageHeight);
|
|
}
|
|
emit updPageCnt();
|
|
} else if(m_attr.playMode==EText::Scroll) {//生成一张大图
|
|
if(m_attr.scroll.effect==0||m_attr.scroll.effect==2) width = qMax(width, ((int)doc.idealWidth()) + m_attr.scroll.headTailSpacing);
|
|
else {
|
|
doc.setTextWidth(width);
|
|
height = doc.size().height() + m_attr.scroll.headTailSpacing;
|
|
}
|
|
QImage img(width, height, QImage::Format_ARGB32);
|
|
img.fill(m_attr.backColor);
|
|
{
|
|
QPainter painter(&img);
|
|
doc.drawContents(&painter);
|
|
}
|
|
if(m_attr.scroll.effect==0||m_attr.scroll.effect==2) alignV(img);
|
|
mImgs.clear();
|
|
mImgs.append(img);
|
|
// if(img.width()<=8192) mImgs.append(img);
|
|
// else {
|
|
// for(int i=0; i<img.width(); i+=8192) {
|
|
// QImage imgpart(8192, height, QImage::Format_ARGB32);
|
|
// imgpart.fill(m_attr.backColor);
|
|
// {
|
|
// QPainter painter(&imgpart);
|
|
// painter.drawImage(-i, 0, img);
|
|
// }
|
|
// mImgs.append(imgpart);
|
|
// }
|
|
// }
|
|
} else if(m_attr.playMode==EText::Static) {//生成一张图
|
|
doc.setTextWidth(width);
|
|
QImage img(width, height, QImage::Format_ARGB32);
|
|
img.fill(m_attr.backColor);
|
|
{
|
|
QPainter painter(&img);
|
|
doc.drawContents(&painter);
|
|
}
|
|
alignV(img);
|
|
mImgs.clear();
|
|
mImgs.append(img);
|
|
}
|
|
update();
|
|
}
|
|
void EText::alignV(QImage &img, int cutHeight) {
|
|
int width = img.width(), height = img.height();
|
|
if(cutHeight==0) cutHeight = height;
|
|
if(m_attr.align & Qt::AlignTop) {
|
|
int ss = 0;
|
|
for(; ss<height; ss++) for(int i=0; i<width; i++) if(img.pixelColor(i, ss)!=m_attr.backColor) goto l12;
|
|
if(cutHeight==height) return;
|
|
ss = 0;
|
|
l12:
|
|
img = copy(img, 0, ss, width, cutHeight);
|
|
} else if(m_attr.align & Qt::AlignVCenter) {
|
|
int ss = 0, ee = height - 1;
|
|
for(; ss<height; ss++) for(int i=0; i<width; i++) if(img.pixelColor(i, ss)!=m_attr.backColor) goto l2;
|
|
if(cutHeight==height) return;
|
|
ss = 0;
|
|
goto l3;
|
|
l2:
|
|
for(; ee>ss; ee--) for(int i=0; i<width; i++) if(img.pixelColor(i, ee)!=m_attr.backColor) goto l3;
|
|
l3:
|
|
img = copy(img, 0, (ss+ee-cutHeight+2)/2, width, cutHeight);
|
|
} else if(m_attr.align & Qt::AlignBottom) {
|
|
int ee = height - 1;
|
|
for(; ee>=0; ee--) for(int i=0; i<width; i++) if(img.pixelColor(i, ee)!=m_attr.backColor) goto l32;
|
|
if(cutHeight==height) return;
|
|
ee = height - 1;
|
|
l32:
|
|
img = copy(img, 0, ee+1-cutHeight, width, cutHeight);
|
|
} else if(cutHeight != height) img = copy(img, 0, 0, width, cutHeight);
|
|
}
|
|
|
|
QImage EText::copy(QImage &img, int x, int y, int w, int h) {
|
|
QImage imgpart(w, h, QImage::Format_ARGB32);
|
|
imgpart.fill(m_attr.backColor);
|
|
{
|
|
QPainter painter(&imgpart);
|
|
painter.drawImage(-x, -y, img);
|
|
}
|
|
return imgpart;
|
|
}
|