qt/LedOK/program/etimer2.cpp

405 lines
14 KiB
C++
Raw Permalink Normal View History

2024-08-07 18:18:37 +08:00
#include "etimer2.h"
#include "main.h"
#include "gutil/qgui.h"
#include "base/locolorselector.h"
#include "base/lodateselector.h"
#include <QButtonGroup>
#include <QFontComboBox>
#include <QMessageBox>
#include <QRadioButton>
#include <QSpinBox>
#include <QStackedLayout>
#include <QTextBlock>
#if(QT_VERSION_MAJOR > 5)
#include <QStringConverter>
#else
#include <QTextCodec>
#endif
#include <QTextEdit>
#include <QTimeEdit>
#include <QToolButton>
#include <QPainter>
ETimer2::ETimer2(EBase *multiWin) : EBase(multiWin) {
isUp = false;
targetTime = QDateTime::currentDateTime();
html = "<body>"+tr("There are")+" %d "+tr("Days")+" %h "+tr("Hours")+" %m "+tr("Mins")+" %s "+tr("Secs")+"</body>";
init();
}
ETimer2::ETimer2(const JObj &json, EBase *multiWin) : EBase(multiWin) {
setBaseAttr(json);
isUp = json["isUp"].toBool();
targetTime = QDateTime::fromString(json["targetTime"].toString(), "yyyy-MM-dd HH:mm:ss");
html = json["html"].toString();
backColor = json["backColor"].toString("#00000000");
init();
}
void ETimer2::init() {
mType = EBase::Timer2;
doc.setDocumentMargin(0);
QFont font;
font.setFamily("Arial");
font.setFamilies({"Arial","黑体"});
font.setPixelSize(16);
doc.setDefaultFont(font);
doc.setDefaultStyleSheet("body {color: #fff; line-height:1}");
connect(this, &ETimer2::sizeChanged, this, &ETimer2::updImg);
connect(gTick, &Tick::secChanged, this, [this](const QDateTime &cur) {
auto sss = isUp ? targetTime.secsTo(cur) : cur.secsTo(targetTime);
if(sss < 0) sss = 0;
if(secs==sss) return;
secs = sss;
updImg();
}, Qt::UniqueConnection);
updImg();
}
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* ETimer2::attrWgt() {
auto wgtAttr = new QWidget;
auto vBox = new VBox(wgtAttr);
vBox->setContentsMargins(4, 0, 4, 0);
vBox->setSpacing(3);
addBaseAttrWgt(vBox);
auto hBox = new HBox(vBox);
hBox->addLabel(tr("Basic Properties"));
auto line = new QFrame;
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
hBox->addWidget(line, 1);
hBox = new HBox(vBox);
hBox->addStretch();
auto fdCntDown = new QRadioButton(tr("Count Down"));
auto fdCntUp = new QRadioButton(tr("Count Up"));
(isUp ? fdCntUp : fdCntDown)->setChecked(true);
auto cntGroup = new QButtonGroup(wgtAttr);
cntGroup->addButton(fdCntDown);
cntGroup->addButton(fdCntUp);
connect(fdCntUp, &QRadioButton::toggled, this, [this](bool checked) {
isUp = checked;
update();
});
hBox->addWidget(fdCntDown);
hBox->addStretch();
hBox->addWidget(fdCntUp);
hBox->addStretch();
hBox = new HBox(vBox);
hBox->addSpacing(6);
hBox->addLabel(tr("Time"));
auto fdTime = new QDateTimeEdit(targetTime);
fdTime->setDisplayFormat("yyyy-MM-dd HH:mm:ss");
connect(fdTime, &QTimeEdit::dateTimeChanged, this, [this](const QDateTime &dateTime) {
targetTime = dateTime;
update();
});
hBox->addWidget(fdTime);
auto wDateSelector = new LoDateSelector;
connect(wDateSelector, &LoDateSelector::sDateSelected, fdTime, &QDateTimeEdit::setDate);
hBox->addWidget(wDateSelector);
hBox->addStretch();
auto fdText = new TTextEdit("");
hBox = new HBox(vBox);
hBox->setSpacing(3);
hBox->addLabel(tr("Font Size")+":");
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);
auto cursor = fdText->textCursor();
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeCharFormat(fmt);
});
hBox->addWidget(fdFontSize);
hBox->addLabel(tr("Line Height"));
auto edLineHeight = new QDoubleSpinBox;
edLineHeight->setDecimals(1);
edLineHeight->setRange(-999, 999);
edLineHeight->setValue(1);
connect(edLineHeight, (void(QDoubleSpinBox::*)(double))&QDoubleSpinBox::valueChanged, this, [this, fdText](double value) {
QTextBlockFormat fmt;
fmt.setLineHeight(value*100, QTextBlockFormat::ProportionalHeight);
auto cursor = fdText->textCursor();
if(! cursor.hasSelection()) cursor.select(QTextCursor::WordUnderCursor);
cursor.mergeBlockFormat(fmt);
updImg();
});
hBox->addWidget(edLineHeight);
hBox->addStretch();
hBox = new HBox(vBox);
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);
MergeFmt(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);
MergeFmt(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);
MergeFmt(fdText, fmt);
});
hBox->addWidget(fdFontUnderline);
hBox->addStretch();
auto edTextColor = new LoColorSelector("F", Qt::white);
edTextColor->setToolTip(tr("Foreground Color"));
edTextColor->setFixedSize(30, 30);
connect(edTextColor, &LoColorSelector::sColorChanged, fdText, [fdText](const QColor &color) {
if(! color.isValid()) return;
QTextCharFormat fmt;
fmt.setForeground(color);
MergeFmt(fdText, fmt);
});
hBox->addWidget(edTextColor);
auto edBack = new LoColorSelector("LB", Qt::white);
edBack->setToolTip(tr("Line Background"));
edBack->setFixedSize(34, 30);
connect(edBack, &LoColorSelector::sColorChanged, fdText, [fdText](const QColor &color) {
if(! color.isValid()) return;
QTextCharFormat fmt;
fmt.setBackground(color);
MergeFmt(fdText, fmt);
});
hBox->addWidget(edBack);
auto edBackColor = new LoColorSelector("B", backColor);
edBackColor->setToolTip(tr("Background Color"));
edBackColor->setFixedSize(30, 30);
connect(edBackColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) {
if(! color.isValid()) return;
backColor = color;
updImg();
});
hBox->addWidget(edBackColor);
auto fdAlignH = new QButtonGroup(wgtAttr);
fdAlignH->addButton(wTextAlignHL, Qt::AlignLeft);
fdAlignH->addButton(wTextAlignHC, Qt::AlignHCenter);
fdAlignH->addButton(wTextAlignHR, Qt::AlignRight);
connect(fdAlignH, &QButtonGroup::idClicked, this, [this, fdText](int value) {
QTextBlockFormat fmt;
fmt.setAlignment((Qt::Alignment) value);
QTextCursor cursor = fdText->textCursor();
cursor.mergeBlockFormat(fmt);
updImg();
});
auto ll = vBox->addLabel("%d: "+tr("Days")+", %h: "+tr("Hours")+", %m: "+tr("Mins")+", %s: "+tr("Secs"));
gFont(ll, 16);
fdText->setMinimumHeight(160);
auto doc = fdText->document();
if(doc) doc->setDocumentMargin(2);
auto font = fdText->font();
font.setFamily("Arial");
font.setFamilies({"Arial","黑体"});
font.setPixelSize(16);
fdText->setFont(font);
auto pal = fdText->palette();
pal.setColor(QPalette::Base, Qt::black);
pal.setColor(QPalette::Text, Qt::white);
fdText->setPalette(pal);
fdText->document()->setDefaultStyleSheet("body {color: #fff; line-height:1}");
fdText->setFrameShape(QFrame::NoFrame);
fdText->setAcceptRichText(false);
fdText->setHtml(html);
connect(fdText, &QTextEdit::textChanged, this, [this, fdText] {
html = 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();
edTextColor->blockSignals(true);
edTextColor->setColor(foreground.style()==Qt::NoBrush ? Qt::white : foreground.color());
edTextColor->blockSignals(false);
auto background = format.background();
edBack->blockSignals(true);
edBack->setColor(background.style()==Qt::NoBrush ? Qt::transparent : background.color());
edBack->blockSignals(false);
auto cursor = fdText->textCursor();
auto blockFormat = cursor.blockFormat();
auto btn = fdAlignH->button(blockFormat.alignment() & Qt::AlignHorizontal_Mask);
if(btn) btn->setChecked(true);
edLineHeight->blockSignals(true);
edLineHeight->setValue(blockFormat.lineHeightType()==QTextBlockFormat::ProportionalHeight ? blockFormat.lineHeight()*0.01 : 1.0);
edLineHeight->blockSignals(false);
});
vBox->addWidget(fdText);
return wgtAttr;
}
void repLineHeight(QString &html) {
QString pre;
int last = 0, idx;
while((idx = html.indexOf("line-height:", last)) > -1) {
idx += 12;
auto end = idx;
QChar ch;
while((ch = html[end])<='9' && ch>='-' && ch!='/') if(++end >= html.size()) goto end;
if(ch!='%') last = end;
else {
pre += html.mid(last, idx-last) + QString::number(html.mid(idx, end-idx).toDouble() / 100);
last = end + 1;
}
}
end:
if(! pre.isEmpty()) html = pre + html.mid(last);
}
JObj ETimer2::attrJson() const {
JObj ele{{"elementType", "Timer2"}};
addBaseAttr(ele);
ele["isUp"] = isUp;
auto hhhh = html;
auto idx = hhhh.indexOf("<html");
if(idx > -1) hhhh = hhhh.mid(idx);
idx = hhhh.indexOf("<body style=\"");
if(idx > -1 && ! hhhh.mid(idx+13, 8).contains("color:")) hhhh = hhhh.insert(idx+13, "color:#fff;");
hhhh.replace("<meta name=\"qrichtext\" content=\"1\" />", "");
hhhh.replace(" -qt-block-indent:0; text-indent:0px;", "");
repLineHeight(hhhh);
ele["html"] = hhhh.replace("margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;", "margin:0;");
ele["targetTime"] = targetTime.toString("yyyy-MM-dd HH:mm:ss");
ele["backColor"] = backColor.name(QColor::HexArgb);
return ele;
}
void ETimer2::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
painter->save();
auto rect = innerRect();
painter->drawImage(rect, img);
painter->restore();
EBase::paint(painter, option, widget);
}
void ETimer2::updImg() {
auto innerRect = this->innerRect();
int width = innerRect.width();
int height = innerRect.height();
if(width<1 || height<1) return;
auto hasDay = html.contains("%d");
auto hasHour = html.contains("%h");
auto hasMin = html.contains("%m");
auto hasSec = html.contains("%s");
auto htm = html;
if(hasDay) {
htm = htm.replace("%d", QString::number(secs/86400));
secs %= 86400;
}
if(hasHour) {
htm = htm.replace("%h", QString::asprintf("%02d", secs/3600));
secs %= 3600;
}
if(hasMin) {
htm = htm.replace("%m", QString::asprintf("%02d", secs/60));
secs %= 60;
}
if(hasSec) htm = htm.replace("%s", QString::asprintf("%02d", secs));
doc.setHtml(htm);
doc.setTextWidth(width);
width<<=1;
height<<=1;
if(img.width()!=width || img.height()!=height) img = QImage(width, height, QImage::Format_ARGB32);
img.fill(backColor);
{
QPainter painter(&img);
painter.scale(2,2);
doc.drawContents(&painter);
}
update();
}