#include "eaclock.h" #include "cfg.h" #include "globaldefine.h" #include "tools.h" #include #include #include #include #include eAClock::eAClock(EBase *multiWin) : EBase(multiWin) { mType = EBase::AClock; m_attr.timeZoneId = QTimeZone::systemTimeZoneId(); m_attr.hourMark = 0; m_attr.hourMarkSize = 5; m_attr.hourMarkColor = Qt::green; m_attr.minMark = 1; m_attr.minMarkSize = 2; m_attr.minMarkColor = Qt::yellow; m_attr.hourHandColor = Qt::yellow; m_attr.minHandColor = Qt::green; m_attr.secHandColor = Qt::red; m_attr.textFont = QFont("Arial", 9); m_attr.textColor = Qt::red; m_attr.playDuration = 10; m_attr.hasDialImg = false; init(); } eAClock::eAClock(const QJsonObject &json, EBase *multiWin) : EBase(multiWin) { mType = EBase::AClock; setBaseAttr(json); auto widget = json["widget"]; m_attr.timeZoneId = QByteArray().append(widget["timeZone"].toString().toUtf8()); m_attr.hourMark = widget["hourMark"].toInt(); m_attr.hourMarkSize = widget["hourMarkSize"].toInt(); auto color = widget["hourMarkColor"]; m_attr.hourMarkColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); m_attr.minMark = widget["minMark"].toInt(); m_attr.minMarkSize = widget["minMarkSize"].toInt(); color = widget["minMarkColor"]; m_attr.minMarkColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); color = widget["hourHandColor"]; m_attr.hourHandColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); color = widget["minHandColor"]; m_attr.minHandColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); color = widget["secHandColor"]; m_attr.secHandColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); color = widget["textColor"]; m_attr.textColor = color.isString() ? QColor(color.toString()) : Tools::int2Color(color.toInt()); m_attr.text = widget["text"].toString(); m_attr.textFont = QFont(widget["textFontFamily"].toString(), widget["textFontSize"].toInt()); m_attr.textFont.setBold(widget["textFontBold"].toBool()); m_attr.textFont.setItalic(widget["textFontItalics"].toBool()); m_attr.textFont.setUnderline(widget["textFontUnderline"].toBool()); m_attr.playDuration = json["play"]["duration"].toInt(); m_attr.path = widget["path"].toString(); m_attr.name = widget["name"].toString(); m_attr.selfCreateDialName= widget["selfCreateDialName"].toString(); m_attr.hasDialImg = widget["bCustomDial"].toBool(); if(! m_attr.hasDialImg) m_attr.selfCreateDialName = QString("%1%2%3%4%5.png").arg((int)zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); else dial_img.load(m_attr.path+"/"+m_attr.name); init(); } void eAClock::init() { connect(Tools::getInstance(), &Tools::sTick, this, [this]() { time = QDateTime::currentDateTime().toTimeZone(QTimeZone(m_attr.timeZoneId)).time(); update(); }); } qreal eAClock::radiusHour() const { qreal r = (rect().width() < rect().height() ? rect().width() : rect().height()) / 2; return r - m_attr.hourMarkSize / 2; } qreal eAClock::radiusMin() const { qreal r = (rect().width() < rect().height() ? rect().width() : rect().height()) / 2; return r - m_attr.minMarkSize / 2; } void eAClock::paintDial(QPainter *painter) { if(! m_attr.hasDialImg || dial_img.isNull()) { auto inner = innerRect(); qreal r = radius(); qreal cx = inner.width() / 2; qreal cy = inner.height() / 2; QVector plist; qreal x, y, ox, oy; qreal k; qreal a = 0; const qreal s = 6; for(int i=0; i<60; i++) { if (a < 90) { k = a * M_PI / 180; ox = sin(k) * r; oy = cos(k) * r; x = cx + ox; y = cy - oy; } else if (a < 180) { k = (a - 90) * M_PI / 180; ox = cos(k) * r; oy = sin(k) * r; x = cx + ox; y = cy + oy; } else if (a < 270) { k = (a - 180) * M_PI / 180; ox = sin(k) * r; oy = cos(k) * r; x = cx - ox; y = cy + oy; } else { k = (a - 270) * M_PI / 180; ox = cos(k) * r; oy = sin(k) * r; x = cx - ox; y = cy - oy; } a += s; plist.push_back(QPointF(x, y)); } a = 0; for(int i=0; i<60; i++) { if(i % 5) { switch (m_attr.minMark) { case 0: drawMarkCircular (painter, plist.at(i), m_attr.minMarkColor, m_attr.minMarkSize); break; case 1: drawMarkRectangle(painter, plist.at(i), m_attr.minMarkColor, m_attr.minMarkSize, a); break; default: break; } } else { switch (m_attr.hourMark) { case 0: drawMarkCircular (painter, plist.at(i), m_attr.hourMarkColor, m_attr.hourMarkSize); break; case 1: drawMarkRectangle(painter, plist.at(i), m_attr.hourMarkColor, m_attr.hourMarkSize, a); break; case 2: drawMarkNumber (painter, plist.at(i), m_attr.hourMarkColor, m_attr.hourMarkSize, i/5); break; default: break; } } a += s; } } else { auto inner = innerRect(); int wid, hei; double rate = qMin(inner.width() / dial_img.width(), inner.height() / dial_img.height()); wid = dial_img.width() * rate; hei = dial_img.height() * rate; painter->drawImage(QRectF((inner.width() - wid)/2, (inner.height() - hei)/2, wid, hei), dial_img, QRectF()); } } void eAClock::drawMarkCircular(QPainter *painter, const QPointF &pos, const QColor &color, qreal diameter) { QPointF cp(pos.x(), pos.y()); qreal r = diameter / 2; painter->save(); painter->setBrush(color); painter->setPen(color); painter->setRenderHint(QPainter::Antialiasing); painter->drawEllipse(cp, r, r); painter->restore(); } void eAClock::drawMarkRectangle(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, qreal angle) { QPointF cp(pos.x(), pos.y()); QRectF rect(-len/2, -len/2, len, len); painter->save(); painter->setBrush(color); painter->setPen(color); painter->translate(cp); painter->rotate(angle); painter->setRenderHint(QPainter::Antialiasing); painter->drawRect(rect); painter->restore(); } void eAClock::drawMarkNumber(QPainter *painter, const QPointF &pos, const QColor &color, qreal len, int num) { QRectF rect(pos.x()-len/2, pos.y()-len/2, len, len); QFont font("Arial"); font.setPointSizeF(len*0.75); QTextOption opt; opt.setAlignment(Qt::AlignCenter); painter->save(); painter->setPen(color); painter->setFont(font); painter->setRenderHint(QPainter::Antialiasing); if(num==0) num=12; painter->drawText(rect, QString("%1").arg(num), opt); painter->restore(); } void eAClock::drawHand(QPainter *painter, qreal angle, const QColor &color, qreal len, qreal base) { auto inner = innerRect(); qreal cx = inner.width() / 2; qreal cy = inner.height() / 2; QPointF points[3] = { QPointF(-base, 0), QPointF( base, 0), QPointF( 0, -len), }; painter->save(); painter->setBrush(color); painter->setPen(color); painter->translate(cx, cy); painter->rotate(angle); painter->setRenderHint(QPainter::Antialiasing); painter->drawPolygon(points, 3); painter->restore(); } void eAClock::paintText(QPainter *painter){ if(m_attr.text.isNull() || m_attr.text.isEmpty()) return; QRectF r(0, rect().height()/6, rect().width(), rect().height()/4); QTextOption opt; opt.setAlignment(Qt::AlignCenter); painter->save(); painter->setPen(m_attr.textColor); m_attr.textFont.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias); painter->setFont(m_attr.textFont); painter->drawText(r, m_attr.text, opt); painter->restore(); } void eAClock::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->save(); auto inner = innerRect(); painter->translate(inner.x(), inner.y()); paintDial(painter); paintText(painter); drawHand(painter, time.hour() * 30.0, m_attr.hourHandColor, radius()/2, radius() / 20); drawHand(painter, time.minute() * 6.0, m_attr.minHandColor, radius()*3/4, radius() / 30); drawHand(painter, time.second() * 6.0, m_attr.secHandColor, radius(), radius() / 40); painter->restore(); EBase::paint(painter, option, widget); } QWidget* eAClock::attrWgt() { auto wgtAttr = new QWidget(); auto vBox = new QVBoxLayout(wgtAttr); vBox->setContentsMargins(6, 0, 6, 0); if(mMultiWin!=nullptr) 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(); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Time Zone"))); auto wTimeZone = new QComboBox(); QList ids = QTimeZone::availableTimeZoneIds(); foreach(QByteArray id, ids) wTimeZone->addItem(QString::fromUtf8(id)); wTimeZone->setCurrentText(m_attr.timeZoneId); connect(wTimeZone, &QComboBox::currentTextChanged, this, [this](const QString &text) { m_attr.timeZoneId = text.toUtf8(); update(); }); hBox->addWidget(wTimeZone); hBox->addStretch(); vBox->addLayout(hBox); hBox = new QHBoxLayout(); auto fdHasDialImg = new QCheckBox(tr("Custom Dial")); fdHasDialImg->setChecked(m_attr.hasDialImg); hBox->addWidget(fdHasDialImg); line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); hBox->addWidget(line, 1); vBox->addLayout(hBox); auto wgtDial = new QWidget(); if(! m_attr.hasDialImg) wgtDial->setVisible(false); hBox = new QHBoxLayout(wgtDial); hBox->setContentsMargins(0, 0, 0, 0); hBox->addSpacing(6); auto fdDialImg = new QLineEdit(); fdDialImg->setReadOnly(true); if(! m_attr.path.isEmpty() && ! m_attr.name.isEmpty()) fdDialImg->setText(m_attr.path+"/"+m_attr.name); hBox->addWidget(fdDialImg); auto btnSelImg = new QPushButton(tr("Select")); btnSelImg->setProperty("ssType", "progManageTool"); connect(btnSelImg, &QPushButton::clicked, this, [this, fdDialImg] { QString fileName = QFileDialog::getOpenFileName(gMainWin, tr("Select Dail file"), "./AClock/", "Dail files(*.png)"); if(fileName.isEmpty()) return; fdDialImg->setText(fileName); QFileInfo info(fileName); if(info.exists()) { m_attr.name = info.fileName(); m_attr.path = info.absolutePath(); dial_img.load(info.absoluteFilePath()); update(); } }); hBox->addWidget(btnSelImg); vBox->addWidget(wgtDial); auto wgtMarks = new QWidget(); if(m_attr.hasDialImg) wgtMarks->setVisible(false); connect(fdHasDialImg, &QCheckBox::toggled, this, [this, wgtDial, wgtMarks, fdDialImg](bool checked) { m_attr.hasDialImg = checked; wgtDial->setVisible(checked); wgtMarks->setVisible(!checked); if(checked) { auto text = fdDialImg->text(); if(! text.isEmpty()) { QFileInfo info(text); if(info.exists()) { m_attr.name = info.fileName(); m_attr.path = info.absolutePath(); dial_img.load(info.absoluteFilePath()); } } } update(); }); auto vbMarks = new QVBoxLayout(wgtMarks); vbMarks->setContentsMargins(0, 0, 0, 0); hBox = new QHBoxLayout(); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Hour Mark"))); auto fdHourMark = new QComboBox(); fdHourMark->addItem(tr("Circular")); fdHourMark->addItem(tr("Rectangle")); fdHourMark->addItem(tr("Number")); fdHourMark->setCurrentIndex(m_attr.hourMark); connect(fdHourMark, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) { m_attr.hourMark = index; update(); }); hBox->addWidget(fdHourMark); auto fdHourMarkSize = new QSpinBox(); fdHourMarkSize->setMaximum(9999); fdHourMarkSize->setValue(m_attr.hourMarkSize); connect(fdHourMarkSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { m_attr.hourMarkSize = value; update(); }); hBox->addWidget(fdHourMarkSize); auto fdHourMarkColor = new LoColorSelector(tr("T"), m_attr.hourMarkColor); fdHourMarkColor->setFixedWidth(30); connect(fdHourMarkColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.hourMarkColor = color; update(); }); hBox->addWidget(fdHourMarkColor); hBox->addStretch(); vbMarks->addLayout(hBox); hBox = new QHBoxLayout(); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Min Mark"))); auto fdMinMark = new QComboBox(); fdMinMark->addItem(tr("Circular")); fdMinMark->addItem(tr("Rectangle")); fdMinMark->setCurrentIndex(m_attr.minMark); connect(fdMinMark, (void(QComboBox::*)(int))&QComboBox::currentIndexChanged, this, [this](int index) { m_attr.minMark = index; update(); }); hBox->addWidget(fdMinMark); auto fdMinMarkSize = new QSpinBox(); fdMinMarkSize->setMaximum(9999); fdMinMarkSize->setValue(m_attr.minMarkSize); connect(fdMinMarkSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { m_attr.minMarkSize = value; update(); }); hBox->addWidget(fdMinMarkSize); auto fdMinMarkColor = new LoColorSelector(tr("T"), m_attr.minMarkColor); fdMinMarkColor->setFixedWidth(30); connect(fdMinMarkColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.minMarkColor = color; update(); }); hBox->addWidget(fdMinMarkColor); hBox->addStretch(); vbMarks->addLayout(hBox); vBox->addWidget(wgtMarks); hBox = new QHBoxLayout(); hBox->addSpacing(6); hBox->addWidget(new QLabel(tr("Hand Color"))); auto fdHourHandColor = new LoColorSelector(tr("H"), m_attr.hourHandColor); fdHourHandColor->setFixedWidth(30); connect(fdHourHandColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.hourHandColor = color; update(); }); hBox->addWidget(fdHourHandColor); auto fdMinHandColor = new LoColorSelector(tr("M"), m_attr.minHandColor); fdMinHandColor->setFixedWidth(30); connect(fdMinHandColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.minHandColor = color; update(); }); hBox->addWidget(fdMinHandColor); auto fdSecHandColor = new LoColorSelector(tr("S"), m_attr.secHandColor); fdSecHandColor->setFixedWidth(30); connect(fdSecHandColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.secHandColor = color; update(); }); hBox->addWidget(fdSecHandColor); hBox->addStretch(); vBox->addLayout(hBox); line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); vBox->addWidget(line); auto fdText = new QTextEdit(m_attr.text); fdText->setMaximumHeight(60); fdText->setPlaceholderText(tr("Text")); connect(fdText, &QTextEdit::textChanged, this, [this, fdText] { m_attr.text = fdText->toPlainText(); }); vBox->addWidget(fdText); hBox = new QHBoxLayout(); hBox->addSpacing(6); auto fdFontFamily = new QFontComboBox(); fdFontFamily->setEditable(false); fdFontFamily->setCurrentText(m_attr.textFont.family()); connect(fdFontFamily, &QFontComboBox::currentFontChanged, this, [this](const QFont &font) { QFont newFont(font.family(), m_attr.textFont.pointSize()); newFont.setBold(m_attr.textFont.bold()); newFont.setItalic(m_attr.textFont.italic()); newFont.setUnderline(m_attr.textFont.underline()); m_attr.textFont = newFont; update(); }); hBox->addWidget(fdFontFamily); auto fdFontSize = new QSpinBox(); fdFontSize->setRange(4, 9999); fdFontSize->setValue(m_attr.textFont.pointSize()); connect(fdFontSize, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { m_attr.textFont.setPointSize(value); update(); }); hBox->addWidget(fdFontSize); hBox->addStretch(); vBox->addLayout(hBox); hBox = new QHBoxLayout(); hBox->addSpacing(6); auto fdBold = new QPushButton(); fdBold->setFixedSize(30, 30); QIcon icon; icon.addFile(":/res/ProgramManager/EditProgram/FontBold_u.png", QSize(), QIcon::Normal, QIcon::Off); icon.addFile(":/res/ProgramManager/EditProgram/FontBold_s.png", QSize(), QIcon::Normal, QIcon::On); fdBold->setIcon(icon); fdBold->setIconSize(QSize(30, 30)); fdBold->setCheckable(true); fdBold->setFlat(true); fdBold->setChecked(m_attr.textFont.bold()); connect(fdBold, &QPushButton::toggled, this, [this](bool checked) { m_attr.textFont.setBold(checked); update(); }); hBox->addWidget(fdBold); auto fdItalic = new QPushButton(); fdItalic->setFixedSize(30, 30); QIcon icon1; icon1.addFile(":/res/ProgramManager/EditProgram/FontItalics_u.png", QSize(), QIcon::Normal, QIcon::Off); icon1.addFile(":/res/ProgramManager/EditProgram/FontItalics_s.png", QSize(), QIcon::Normal, QIcon::On); fdItalic->setIcon(icon1); fdItalic->setIconSize(QSize(30, 30)); fdItalic->setCheckable(true); fdItalic->setFlat(true); fdItalic->setChecked(m_attr.textFont.italic()); connect(fdItalic, &QPushButton::toggled, this, [this](bool checked) { m_attr.textFont.setItalic(checked); update(); }); hBox->addWidget(fdItalic); auto fdUnderline = new QPushButton(); fdUnderline->setFixedSize(30, 30); QIcon icon2; icon2.addFile(":/res/ProgramManager/EditProgram/FontUnderline_u.png", QSize(), QIcon::Normal, QIcon::Off); icon2.addFile(":/res/ProgramManager/EditProgram/FontUnderline_s.png", QSize(), QIcon::Normal, QIcon::On); fdUnderline->setIcon(icon2); fdUnderline->setIconSize(QSize(30, 30)); fdUnderline->setCheckable(true); fdUnderline->setFlat(true); fdUnderline->setChecked(m_attr.textFont.underline()); connect(fdUnderline, &QPushButton::toggled, this, [this](bool checked) { m_attr.textFont.setUnderline(checked); update(); }); hBox->addWidget(fdUnderline); auto fdTextColor = new LoColorSelector(tr("T"), m_attr.textColor); fdTextColor->setFixedWidth(30); connect(fdTextColor, &LoColorSelector::sColorChanged, this, [this](const QColor &color) { m_attr.textColor = color; update(); }); hBox->addWidget(fdTextColor); hBox->addStretch(); 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->addSpacing(6); hBox->addWidget(new QLabel(tr("Play Duration"))); auto fdDuration = new QSpinBox(); fdDuration->setRange(1, 99999); fdDuration->setValue(m_attr.playDuration); connect(fdDuration, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { m_attr.playDuration = value; }); hBox->addWidget(fdDuration); hBox->addWidget(new QLabel(tr("s"))); hBox->addStretch(); vBox->addLayout(hBox); vBox->addStretch(); return wgtAttr; } bool eAClock::save(const QString &pRoot){ if(m_attr.hasDialImg) { QString file0 = m_attr.path + PAGEDEL_SUFFIX + "/" + m_attr.name; QString file1 = m_attr.path + "/" + m_attr.name; QFile f0(file0); QFile f1(file1); QString old_file; QString new_file = pRoot + "/" + m_attr.name; if(f0.exists()) { old_file = file0; } else if(f1.exists()) { old_file = file1; } else {//自己画点,不用背景表盘 return false; } QFile old_f(old_file); QFile new_f(new_file); if(!new_f.exists()) old_f.copy(new_file); } m_attr.selfCreateDialName = QString("%1%2%3%4%5.png").arg((int)zValue()).arg((int)x()).arg((int)y()).arg((int)mWidth).arg((int)mHeight); m_attr.path = pRoot; QRectF inner = innerRect(); QPixmap *tempPixamp = new QPixmap(inner.width(), inner.height()); tempPixamp->fill(Qt::transparent); QPainter painter; painter.begin(tempPixamp); this->paintDial(&painter); this->paintText(&painter); painter.end(); tempPixamp->save(pRoot+"/"+m_attr.selfCreateDialName, "PNG"); delete tempPixamp; //生成表盘背景图 return true; } QJsonObject eAClock::attrJson() const { QJsonObject oRoot; addBaseAttr(oRoot); oRoot["elementType"] = "AClock"; QJsonObject oWidget; oWidget["timeZone"] = QString::fromUtf8(m_attr.timeZoneId); oWidget["hourMark"] = m_attr.hourMark; oWidget["hourMarkSize"] = m_attr.hourMarkSize; oWidget["hourMarkColor"] = m_attr.hourMarkColor.name(); oWidget["minMark"] = m_attr.minMark; oWidget["minMarkSize"] = m_attr.minMarkSize; oWidget["minMarkColor"] = m_attr.minMarkColor.name(); oWidget["hourHandColor"] = m_attr.hourHandColor.name(); oWidget["minHandColor"] = m_attr.minHandColor.name(); oWidget["secHandColor"] = m_attr.secHandColor.name(); oWidget["text"] = m_attr.text; oWidget["textFontFamily"] = m_attr.textFont.family(); oWidget["textFontSize"] = m_attr.textFont.pointSize(); oWidget["textFontBold"] = m_attr.textFont.bold(); oWidget["textFontItalics"] = m_attr.textFont.italic(); oWidget["textFontUnderline"] = m_attr.textFont.underline(); oWidget["textColor"] = m_attr.textColor.name(); oWidget["path"] = m_attr.path; oWidget["name"] = m_attr.name; oWidget["selfCreateDialName"] = m_attr.selfCreateDialName; oWidget["bCustomDial"] = m_attr.hasDialImg; oRoot["widget"] = oWidget; oRoot["play"] = QJsonObject{{"duration", m_attr.playDuration}}; return oRoot; }