qt/LedOK/program/gentmpthread.cpp
2023-05-15 16:06:10 +08:00

626 lines
25 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "gentmpthread.h"
#include "cfg.h"
#include "globaldefine.h"
#include "tools.h"
#include "program/eenviron.h"
#include "program/etext.h"
#include "program/evideo.h"
#include <QBuffer>
#include <QJsonArray>
#include <QProcess>
#include <QMessageBox>
#include <QPainter>
GenTmpThread::GenTmpThread(ProgItem *progItem, const QString &prog_name, const QString &zip_file, const QString &password) : mProgItem(progItem), prog_name(prog_name), zip_file(zip_file), password(password) {
connect(this, &QThread::finished, this, &QThread::deleteLater);
}
void GenTmpThread::run() {
auto srcDir = programsDir() + "/" + prog_name;
dstDir = srcDir + "_tmp";
//清空目录
emit sProgress(tr("Preparing ..."), 0);
QDir progsDir(programsDir());
progsDir.remove(prog_name + "_tmp.zip");
QDir dstQDir(dstDir);
if(! dstQDir.exists() || dstQDir.removeRecursively()) {
int iReTryCount = 0;
while(!progsDir.mkdir(prog_name + "_tmp")) {
QThread::msleep(250);
iReTryCount++;
if(iReTryCount > 4) break;
}
}
QFile jsonFile(srcDir+"/pro.json");
if(! jsonFile.open(QIODevice::ReadOnly)) {
emit onErr("Can't open "+srcDir+"/pro.json");
return;
}
auto data = jsonFile.readAll();
jsonFile.close();
QJsonParseError error;
auto proJson = QJsonDocument::fromJson(data, &error);
if(error.error != QJsonParseError::NoError) {
emit onErr("Parse "+srcDir+"/pro.json Error: "+error.errorString());
return;
}
//扫描节目, 返回多个节目数组
emit sProgress(tr("Scan program ..."), 30);
QStringList pageNames = QDir(srcDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot);
//查询 order 属性, 将最上层的放在转换后 layers 的最前面
//一个 page.json 对应节目任务中的一个 items 里的 program
QList<QJsonDocument> pageJsons;
foreach(QString pageName, pageNames) {
QFile jsonFile(srcDir+"/"+pageName+"/page.json");
if(jsonFile.open(QIODevice::ReadOnly)) {
auto data = jsonFile.readAll();
jsonFile.close();
auto pageJson = QJsonDocument::fromJson(data, &error);
if(error.error == QJsonParseError::NoError) pageJsons.append(pageJson);
}
}
std::sort(pageJsons.begin(), pageJsons.end(), [](const QJsonDocument &a, const QJsonDocument &b) {
return a["order"].toInt() < b["order"].toInt();
});
QJsonArray items;
foreach(QJsonDocument pageJson, pageJsons) {
srcPageDir = srcDir + "/" + pageJson["name"].toString();
items.append(cvtPage(pageJson, proJson));
}
emit sProgress(tr("Create json ..."), 60);
QJsonObject json;
json["_type"] = "PlayXixunTask";
json["id"] = QUuid::createUuid().toString(QUuid::WithoutBraces);
json["preDownloadURL"] = "http://192.168.8.202:23412/file/download?id=";
json["notificationURL"] = "http://192.168.8.202:23412/test";
json["task"] = QJsonObject{
{"_id", QUuid::createUuid().toString(QUuid::WithoutBraces)},
{"name", prog_name},
{"cmdId", QUuid::createUuid().toString(QUuid::WithoutBraces)},
{"items", items}
};
QFile program(dstDir + "/program");
if(program.open(QFile::WriteOnly)) {
program.write(QJsonDocument(json).toJson());
program.close();
}
//如果是usb更新则生成压缩包网络发送则不需要
if(! zip_file.isEmpty()) {
#ifdef Q_OS_WIN
QStringList args{"a", zip_file, dstDir+"/*"};
if(! password.isEmpty()) args << "-p"+password;
QProcess::execute("7z.exe", args);
#else
QStringList args{"-r", zip_file};
if(! password.isEmpty()) args << "-P" << password;
args += QDir(dstDir).entryList(QDir::AllEntries | QDir::NoDotAndDotDot);
QProcess process;
process.setWorkingDirectory(dstDir);
process.start("zip", args);
process.waitForFinished();
#endif
}
}
//此处需要把幻灯片中的元素按层顺序排序再放入layers中每个元素对一个layer。ewindow中的多个顺序元素为一个层上的时间轴上的素材
QJsonObject GenTmpThread::cvtPage(const QJsonDocument &pageJson, const QJsonDocument &proJson) {
auto audios = pageJson["audios"].toArray();
auto sourceRepeat = pageJson["loop"].toBool();
QJsonArray sources;
int start = 0;
foreach(QJsonValue audio, audios) {
auto dur = audio["dur"].toInt();
if(dur==0) continue;
auto name = audio["name"].toString();
if(name.isEmpty()) continue;
QString file = audio["dir"].toString()+"/"+name;
QFileInfo srcInfo(file);
if(! srcInfo.isFile()) continue;
QString id = Tools::fileMd5(file);
if(id.isEmpty()) continue;
QFile::copy(file, dstDir+"/"+id);
QJsonObject source;
source.insert("_type", "Audio");
source["id"] = id;
source["md5"] = id;
source["name"] = name;
source["size"] = srcInfo.size();
source["fileExt"] = srcInfo.suffix().toLower();
source["timeSpan"] = dur;
source["playTime"] = start;
source["vol"] = audio["vol"].toInt();
source["enabled"] = true;
source["left"] = -1;
source["top"] = -1;
source["width"] = 1;
source["height"] = 1;
sources.append(source);
start += dur;
}
QJsonArray layers;
if(! sources.isEmpty()) layers.append(QJsonObject{{"repeat", sourceRepeat}, {"sources", sources}});
auto elements = pageJson["elements"].toArray();
foreach(auto ele, elements) {
QString type = ele["elementType"].toString();
auto geometry = ele["geometry"];
QJsonArray sources;
if(type=="Window") {
auto elements = ele["elements"].toArray();
auto left = geometry["x"];
auto top = geometry["y"];
auto width = geometry["w"];
auto height = geometry["h"];
QList<QJsonObject> eles;
foreach(auto value, elements) eles.append(value.toObject());
std::sort(eles.begin(), eles.end(), [](const QJsonObject &a, const QJsonObject &b) {
return a["geometry"]["order"].toInt() < b["geometry"]["order"].toInt();
});
int playTime = 0;
foreach(const auto ele, eles) {
QJsonObject source = cvtEle(ele["elementType"].toString(), ele);
if(source.isEmpty()) continue;
source["left"] = left;
source["top"] = top;
source["width"] = width;
source["height"] = height;
source["playTime"] = playTime;
playTime += source["timeSpan"].toInt();
sources.append(source);
}
} else {
QJsonObject source = cvtEle(type, ele.toObject());
if(! source.isEmpty()) {
if(mProgItem->mMaxWidth && (type=="Photo" || type=="Movie")) {
source["left"] = 0;
source["top"] = 0;
source["width"] = mProgItem->mMaxWidth;
source["height"] = mProgItem->mHeight * mProgItem->mSplitWidths.size();
} else {
source["left"] = geometry["x"];
source["top"] = geometry["y"];
source["width"] = geometry["w"];
source["height"] = geometry["h"];
}
source["playTime"] = 0;
sources.append(source);
}
}
if(! sources.isEmpty()) {
QJsonObject layer{{"repeat", sourceRepeat}, {"sources", sources}};
auto border = ele["border"].toString();
if(! border.isEmpty()) {
QString bdSrc = ":res/borders/"+border;
QString id = Tools::fileMd5(bdSrc);
QFile::copy(bdSrc, dstDir+"/"+id);
auto borderSize = ele["borderSize"];
if(borderSize.isUndefined() || borderSize.isNull()){
QImage img(bdSrc);
borderSize = QJsonArray{img.width(), img.height()};
}
layer.insert("border", QJsonObject{
{"img", id},
{"eff", ele["borderEff"]},
{"speed", ele["borderSpeed"]},
{"img_size", borderSize},
{"geometry", QJsonArray{geometry["x"], geometry["y"], geometry["w"], geometry["h"]}}
});
}
layers.append(layer);
}
}
QJsonArray schedules, plans = pageJson["plans"].toArray();
auto validDate = pageJson["validDate"];
bool isValid = validDate["isValid"].toBool();
if(plans.isEmpty()) {
if(isValid) {
QJsonObject schedule;
schedule["dateType"] = "Range";
schedule["startDate"] = validDate["start"];
schedule["endDate"] = validDate["end"];
schedule["timeType"] = "All";
schedule["filterType"] = "None";
schedule["monthFilter"] = QJsonArray();
schedule["weekFilter"] = QJsonArray();
schedules.append(schedule);
}
} else {
foreach(QJsonValue plan, plans) {
QJsonObject schedule;
if(isValid) {
schedule["dateType"] = "Range";
schedule["startDate"] = validDate["start"];
schedule["endDate"] = validDate["end"];
} else schedule["dateType"] = "All";
schedule["timeType"] = "Range";
schedule["startTime"] = plan["start"];
schedule["endTime"] = plan["end"];
auto weekly = plan["weekly"];
schedule["weekFilter"] = weekly;
schedule["filterType"] = weekly.toArray().isEmpty() ? "None" : "Week";
schedule["monthFilter"] = QJsonArray();
schedules.append(schedule);
}
}
return QJsonObject{
{"_id", QUuid::createUuid().toString(QUuid::WithoutBraces)},
{"priority", 0},
{"version", 0},
{"schedules", schedules},
{"_program", QJsonObject{
{"_id", QUuid::createUuid().toString(QUuid::WithoutBraces)},
{"totalSize", 0},
{"name", pageJson["name"].toString()},
{"width", proJson["resolution"]["w"]},
{"height", proJson["resolution"]["h"]},
{"splitWidths", proJson["splitWidths"]},
{"_company", "alahover"},
{"_department", "alahover"},
{"_role", "alahover"},
{"_user", "alahover"},
{"__v", 0},
{"dateCreated", pageJson["last_edit"]},
{"layers", layers}
}},
{"repeatTimes", pageJson["repeat"]}
};
}
QJsonObject GenTmpThread::cvtEle(const QString &type, const QJsonObject &ele) {
if(type=="Text") return convertText(ele);
else if(type=="Photo") return convertPhoto(ele);
else if(type=="Movie") return EVideo::genProg(ele, dstDir, mProgItem);
else if(type=="Gif") return convertGif(ele);
else if(type=="DClock") return convertDClock(ele);
else if(type=="AClock") return convertAClock(ele);
else if(type=="Temp") return EEnviron::genProg(ele, dstDir, srcPageDir);
else if(type=="Web") return convertWeb(ele);
else if(type=="Timer") return convertTimer(ele);
return QJsonObject();
}
QJsonObject GenTmpThread::convertText(const QJsonObject &json) {
EText::Data attr;
EText::setElement(json, attr);
QJsonObject source;
auto type = mProgItem->mMaxWidth ? "SplitText" : "MultiPng";
source["_type"] = type;
source["name"] = type;
source["id"] = res_id++;
auto widget = json["widget"];
QJsonArray srcFiles = widget["files"].toArray();
source["iPicCount"] = srcFiles.size();
if(attr.playMode==EText::Flip) {
source["playMode"] = "Flip";
source["timeSpan"] = attr.flip.pageDuration * srcFiles.size();
if(attr.flip.effectDuration >= attr.flip.pageDuration) attr.flip.effectDuration = attr.flip.pageDuration / 2;
} else if(attr.playMode==EText::Scroll) {
source["playMode"] = "Scroll";
source["timeSpan"] = attr.scroll.duration;
} else if(attr.playMode==EText::Static) {
source["playMode"] = "Static";
source["timeSpan"] = attr.duration;
}
QJsonArray arrayPics;
QString filePrefix = srcPageDir+"/"+widget["idDir"].toString()+"/";
for(int i=0; i<srcFiles.size(); i++) {
QString srcFile = filePrefix + srcFiles[i].toString();
QFile srcQFile(srcFile);
if(! srcQFile.exists()) continue;
QJsonObject arrayPic;
QString id = Tools::fileMd5(srcFile);
srcQFile.copy(dstDir+"/"+id);
arrayPic["id"] = id;
arrayPic["mime"] = "image/png";
if(attr.playMode==EText::Flip) {
arrayPic["effect"] = attr.flip.effect;
arrayPic["effectSpeed"] = attr.flip.effectDuration;
arrayPic["picDuration"] = attr.flip.pageDuration;
} else if(attr.playMode==EText::Scroll) {
if(attr.scroll.effect==0) arrayPic["effect"] = "right to left";
else if(attr.scroll.effect==1) arrayPic["effect"] = "bottom to top";
else if(attr.scroll.effect==2) arrayPic["effect"] = "left to right";
else if(attr.scroll.effect==3) arrayPic["effect"] = "top to bottom";
arrayPic["effectSpeed"] = attr.scroll.effectSpeed;
arrayPic["picDuration"] = 0;
} else if(attr.playMode==EText::Static) {
arrayPic["effect"] = "no";
arrayPic["effectSpeed"] = 0;
arrayPic["picDuration"] = attr.duration;
}
arrayPics.append(arrayPic);
}
source["arrayPics"] = arrayPics;
return source;
}
//转换图片
QJsonObject GenTmpThread::convertPhoto(const QJsonObject &ele){
auto widget = ele["widget"];
auto name = widget["file"].toString();
QString srcFile = widget["path"].toString() + "/" + name;
QFileInfo srcInfo(srcFile);
QJsonObject source;
if(! srcInfo.isFile()) return source;
if(mProgItem->mMaxWidth) {
srcFile += "-square.png";
auto md5 = Tools::fileMd5(srcFile);
if(md5.isEmpty()) return source;
QFile::copy(srcFile, dstDir+"/"+md5);
source["id"] = md5;
source["md5"] = md5;
source["size"] = srcInfo.size();
source["name"] = name;
source["fileExt"] = "png";
source["mime"] = "image/png";
} else {
QImage img(srcFile);
auto geometry = ele["geometry"];
int width = geometry["w"].toInt();
int height = geometry["h"].toInt();
if(img.width() > width*2 && img.height() > height*2) {
QBuffer buf;
img.scaled(width, height, Qt::IgnoreAspectRatio, Qt::SmoothTransformation).save(&buf, "PNG");
QCryptographicHash cryptoHash(QCryptographicHash::Md5);
cryptoHash.addData(buf.data());
auto md5 = QString::fromLatin1(cryptoHash.result().toHex());
QFile file(dstDir+"/"+md5);
if(! file.open(QFile::WriteOnly)) return source;
file.write(buf.data());
file.close();
source["id"] = md5;
source["md5"] = md5;
source["size"] = buf.size();
source["name"] = srcInfo.baseName()+".png";
source["fileExt"] = "png";
source["mime"] = "image/png";
} else {
auto md5 = Tools::fileMd5(srcFile);
if(md5.isEmpty()) return source;
QFile::copy(srcFile, dstDir+"/"+md5);
source["id"] = md5;
source["md5"] = md5;
source["size"] = srcInfo.size();
source["name"] = name;
QString sufLower = srcInfo.suffix().toLower();
source["fileExt"] = sufLower;
source["mime"] = "image/"+(sufLower=="jpg" ? "jpeg" : sufLower);
}
}
source["_type"] = "Image";
auto play = ele["play"];
source["timeSpan"] = play["playDuration"];
source["enabled"] = true;
source["enabledBy"] = "";
source["oldFilePath"] = "";
static const int effSize = 13;
static const int effs[effSize] = {0,1,3,4,5,6,7,9,10,11,12,17,18};
int enterStyle = play["enterStyle"].toInt();
source["entryEffect"] = enterStyle < effSize ? effs[enterStyle] : 0;
source["exitEffect"] = 0;
source["entryEffectTimeSpan"] = play["enterDuration"];
source["exitEffectTimeSpan"] = 0;
return source;
}
//转换图片
QJsonObject GenTmpThread::convertGif(const QJsonObject &json) {
auto widget = json["widget"];
auto path = widget["path"].toString();
auto name = widget["file"].toString();
QString srcFile = path + "/" + name;
QFileInfo srcInfo(srcFile);
if(! srcInfo.isFile()) return QJsonObject();
QString id = Tools::fileMd5(srcFile);
if(id.isEmpty()) return QJsonObject();
QFile::copy(srcFile, dstDir+"/"+id);
QJsonObject oRes;
oRes["_type"] = "Image";
oRes["id"] = id;
oRes["md5"] = id;
oRes["name"] = name;
oRes["size"] = srcInfo.size();
QString suffix = srcInfo.suffix().toLower();
oRes["fileExt"] = suffix;
oRes["mime"] = "image/gif";
auto play = json["play"];
oRes["timeSpan"] = play["playDuration"].toInt() * play["playTimes"].toInt();
oRes["enabled"] = true;
oRes["entryEffect"] = "None";
oRes["exitEffect"] = "None";
oRes["entryEffectTimeSpan"] = 0;
oRes["exitEffectTimeSpan"] = 0;
return oRes;
}
QJsonObject GenTmpThread::convertDClock(const QJsonObject &json){
QJsonObject oRes;
oRes["_type"] = "DigitalClockNew";
oRes["name"] = "DigitalClockNew";
oRes["id"] = "";
oRes["timeSpan"] = json["play"]["duration"];
oRes["timezone"] = 8;
auto widget = json["widget"];
oRes["year"] = widget["year"];
oRes["month"] = widget["month"];
oRes["day"] = widget["day"];
oRes["hour"] = widget["hour"];
oRes["min"] = widget["min"];
oRes["sec"] = widget["sec"];
oRes["weekly"] = widget["weekly"];
oRes["fullYear"] = widget["fullYear"];
oRes["hour12"] = widget["12Hour"];
oRes["AmPm"] = widget["AmPm"];
oRes["dateStyle"] = widget["dateStyle"];
oRes["timeStyle"] = widget["timeStyle"];
oRes["multiline"] = widget["multiline"];
oRes["fontSize"] = widget["font"]["size"];
oRes["entryEffect"] = "None";
oRes["exitEffect"] = "None";
oRes["entryEffectTimeSpan"] = 0;
oRes["exitEffectTimeSpan"] = 0;
auto fontVal = widget["font"];
auto textColor = Tools::int2Color(fontVal["color"].toInt());
QFont font(fontVal["family"].toString());
font.setPixelSize(fontVal["size"].toInt());
font.setBold(fontVal["bold"].toBool());
font.setItalic(fontVal["italics"].toBool());
font.setUnderline(fontVal["underline"].toBool());
font.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias);
QFontMetricsF metricF(font);
oRes["spaceWidth"] = metricF.horizontalAdvance(" ");
QFontMetrics metric(font);
QColor color(textColor);
QJsonArray imgs;
for(auto str : str0_9) Tools::saveImg2(dstDir, metric, font, color, imgs, str, str);
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("MON"), "MON");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("TUE"), "TUE");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("WED"), "WED");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("THU"), "THU");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("FRI"), "FRI");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("SAT"), "SAT");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("SUN"), "SUN");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("AM"), "AM");
Tools::saveImg2(dstDir, metric, font, color, imgs, tr("PM"), "PM");
Tools::saveImg2(dstDir, metric, font, color, imgs, "", "YEAR");
Tools::saveImg2(dstDir, metric, font, color, imgs, "", "MONTH");
Tools::saveImg2(dstDir, metric, font, color, imgs, "", "DAY");
Tools::saveImg2(dstDir, metric, font, color, imgs, ":", "maohao");
Tools::saveImg2(dstDir, metric, font, color, imgs, "/", "xiegang");
Tools::saveImg2(dstDir, metric, font, color, imgs, "-", "hengxian");
oRes["iPicCount"] = imgs.size();
oRes["arrayPics"] = imgs;
return oRes;
}
QJsonObject GenTmpThread::convertAClock(const QJsonObject &json) {
auto widget = json["widget"];
QString srcFile = srcPageDir + "/" + widget["selfCreateDialName"].toString();
QFile srcQFile(srcFile);
if(! srcQFile.exists()) return QJsonObject();
QString id = Tools::fileMd5(srcFile);
srcQFile.copy(dstDir+"/"+id);
QJsonObject oRes;
oRes["_type"] = "AnalogClock";
oRes["id"] = id;
oRes["md5"] = id;
oRes["mime"] = "image/png";
oRes["name"] = "001";
oRes["timeSpan"] = json["play"]["duration"];
oRes["shade"] = 0;//表盘形状
oRes["opacity"] = 1;//透明度
oRes["showBg"] = false;//是否显示背景色
oRes["bgColor"] = 0;
oRes["showHourScale"] = false;//是否显示时针
auto color = widget["hourMarkColor"];
oRes["scaleHourColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name();
color = widget["minMarkColor"];
oRes["scaleMinColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name();
color = widget["hourHandColor"];
oRes["pinHourColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name();
color = widget["minHandColor"];
oRes["pinMinColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name();
color = widget["secHandColor"];
oRes["pinSecColor"] = color.isString() ? color : Tools::int2Color(color.toInt()).name();
oRes["pinHourLen"] = widget["hhLen"].toInt();
oRes["pinMinLen"] = widget["mhLen"].toInt();
oRes["pinSecLen"] = widget["shLen"].toInt();
oRes["pinHourWidth"] = widget["hhWidth"].toInt();
oRes["pinMinWidth"] = widget["mhWidth"].toInt();
oRes["pinSecWidth"] = widget["shWidth"].toInt();
oRes["showMinScale"] = false;
oRes["scaleStyle"] = 0;
oRes["showScaleNum"] = false;
oRes["pinStyle"] = 1;
oRes["showSecond"] = widget["showSecHand"];
//下同Video
oRes["entryEffect"] = "None";
oRes["exitEffect"] = "None";
oRes["entryEffectTimeSpan"] = 0;
oRes["exitEffectTimeSpan"] = 0 ;
return oRes;
}
QJsonObject GenTmpThread::convertWeb(const QJsonObject &res) {
QJsonObject dst;
dst["_type"] = "WebURL";
dst["id"] = "";
dst["name"] = "WebURL";
dst["url"] = res["url"];
dst["timeSpan"] = res["duration"];
return dst;
}
QJsonObject GenTmpThread::convertTimer(const QJsonObject &json) {
QJsonObject oRes;
oRes["_type"] = "Timer";
oRes["name"] = "Timer";
oRes["id"] = "";
oRes["targetTime"] = json["targetTime"];
oRes["isDown"] = json["isDown"];
oRes["hasDay"] = json["hasDay"];
oRes["hasHour"] = json["hasHour"];
oRes["hasMin"] = json["hasMin"];
oRes["hasSec"] = json["hasSec"];
oRes["isMultiline"] = json["isMultiline"];
auto text = json["text"].toString();
oRes["text"] = text;
QFont font(json["font"].toString());
font.setPixelSize(json["fontSize"].toInt());
font.setBold(json["fontBold"].toBool());
font.setItalic(json["fontItalic"].toBool());
font.setUnderline(json["fontUnderline"].toBool());
oRes["font"] = font.family();
oRes["fontSize"] = font.pixelSize();
oRes["fontBold"] = font.bold();
oRes["fontItalic"] = font.italic();
oRes["fontUnderline"] = font.underline();
auto textColor = json["textColor"].toString();
oRes["textColor"] = textColor;
oRes["backColor"] = json["backColor"];
oRes["timeSpan"] = json["duration"];
font.setStyleStrategy(gTextAntialiasing ? QFont::PreferAntialias : QFont::NoAntialias);
QFontMetricsF metricF(font);
oRes["spaceWidth"] = metricF.horizontalAdvance(" ");
QFontMetrics metric(font);
QColor color(textColor);
QJsonObject imgs;
for(auto str : str0_9) Tools::saveImg(dstDir, metric, font, color, imgs, str, str);
Tools::saveImg(dstDir, metric, font, color, imgs, tr("day"), "day");
Tools::saveImg(dstDir, metric, font, color, imgs, tr("hour"), "hour");
Tools::saveImg(dstDir, metric, font, color, imgs, tr("min"), "min");
Tools::saveImg(dstDir, metric, font, color, imgs, tr("sec"), "sec");
if(! text.isEmpty()) {
auto innerW = json["innerW"].toInt();
auto innerH = json["innerH"].toInt();
auto rect = metric.boundingRect(0, 0, innerW, innerH, Qt::AlignCenter | Qt::TextWordWrap, text);
QImage img(qMin(rect.width(), innerW), qMin(rect.height(), innerH), QImage::Format_ARGB32);
img.fill(Qt::transparent);
{
QPainter painter(&img);
painter.setFont(font);
painter.setPen(color);
painter.drawText(QRectF(0, 0, img.width(), img.height()), text, QTextOption(Qt::AlignCenter));
}
QByteArray data;
QBuffer buffer(&data);
buffer.open(QIODevice::WriteOnly);
if(img.save(&buffer, "PNG")) {
QCryptographicHash cryptoHash(QCryptographicHash::Md5);
cryptoHash.addData(data);
auto md5 = QString::fromLatin1(cryptoHash.result().toHex());
QFile file(dstDir+"/"+md5);
if(file.open(QFile::WriteOnly)) {
file.write(data);
file.close();
imgs.insert("text", md5);
} else emit onErr("convertTimer file.open false");
} else emit onErr("convertTimer img.save false");
}
oRes["imgs"] = imgs;
return oRes;
}