#include "etimer2.h" #include "main.h" #include "gutil/qgui.h" #include "base/locolorselector.h" #include "base/lodateselector.h" #include #include #include #include #include #include #include #if(QT_VERSION_MAJOR > 5) #include #else #include #endif #include #include #include #include ETimer2::ETimer2(EBase *multiWin) : EBase(multiWin) { isUp = false; targetTime = QDateTime::currentDateTime(); html = ""+tr("There are")+" %d "+tr("Days")+" %h "+tr("Hours")+" %m "+tr("Mins")+" %s "+tr("Secs")+""; 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(" -1) hhhh = hhhh.mid(idx); idx = hhhh.indexOf(" -1 && ! hhhh.mid(idx+13, 8).contains("color:")) hhhh = hhhh.insert(idx+13, "color:#fff;"); hhhh.replace("", ""); 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(); }