#include "eaclock.h"
#include "cfg.h"
#include "globaldefine.h"
#include "tools.h"
#include <QBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPainter>
#include <QTimeZone>

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<QPointF> 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<QByteArray> 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;
}
