271 lines
11 KiB
C++
271 lines
11 KiB
C++
#include "playwin.h"
|
|
#include "eledigiclock.h"
|
|
#include "eleanaclock.h"
|
|
#include "eleborder.h"
|
|
#include "elegif.h"
|
|
#include "elescroll.h"
|
|
#include "eletimer.h"
|
|
#include "elevideo.h"
|
|
#include "srccopy.h"
|
|
#include "posdlg.h"
|
|
#include <QFileInfo>
|
|
#include <QLabel>
|
|
#include <QMouseEvent>
|
|
#include <QMovie>
|
|
#include <QWebEngineView>
|
|
#include <QGuiApplication>
|
|
#include <QOpenGLWidget>
|
|
|
|
PlayWin* PlayWin::self = 0;
|
|
QPoint gPlayPos{0, 0};
|
|
|
|
PlayWin *PlayWin::newIns(int width, int height, QString dir, const JValue &aprog, QWidget *parent) {
|
|
if(! gPlayPos.isNull() && QGuiApplication::screenAt(QPoint(gPlayPos.x()+width/2, gPlayPos.y()+height/2))==0) gPlayPos = QPoint();
|
|
return new PlayWin(gPlayPos.x(), gPlayPos.y(), width, height, dir, aprog, parent);
|
|
}
|
|
|
|
PlayWin::PlayWin(int x, int y, int width, int height, QString dir, const JValue &aprog, QWidget *parent) : QWidget(parent) {
|
|
self = this;
|
|
setAttribute(Qt::WA_DeleteOnClose);
|
|
setAttribute(Qt::WA_QuitOnClose, false);
|
|
setWindowFlag(Qt::FramelessWindowHint);
|
|
setWindowFlag(Qt::WindowStaysOnTopHint);
|
|
setGeometry(x, y, width, height+1);
|
|
auto plt = palette();
|
|
plt.setColor(QPalette::Window, Qt::black);
|
|
setPalette(plt);
|
|
gl = new QOpenGLWidget(this);
|
|
gl->setGeometry(0, height, width, 1);
|
|
connect(gl, &QOpenGLWidget::frameSwapped, gl, (void(QOpenGLWidget::*)())&QOpenGLWidget::update);
|
|
auto task = aprog["task"];
|
|
auto jpages = task["items"];
|
|
|
|
auto partLengths = task["partLengths"];
|
|
auto isVertical = task["isVertical"].toBool();
|
|
QWidget *box = this;
|
|
if(partLengths.size() > 1) {
|
|
box = new QWidget(this);
|
|
auto width = task["width"].toInt();
|
|
auto height = task["height"].toInt();
|
|
box->setGeometry(0, 0, width, height);
|
|
auto mask = new QWidget(this);
|
|
mask->setAutoFillBackground(true);
|
|
auto pal = mask->palette();
|
|
pal.setColor(QPalette::Window, Qt::black);
|
|
mask->setPalette(pal);
|
|
auto len0 = partLengths[0].toInt();
|
|
isVertical ? mask->setGeometry(0, len0, width, height - len0) : mask->setGeometry(len0, 0, width - len0, height);
|
|
int x = 0, y = 0;
|
|
for(int i=1; i<(int)partLengths.size(); i++) {
|
|
auto part = new SrcCopy(this, box);
|
|
if(isVertical) {
|
|
y -= partLengths[i-1].toInt();
|
|
x += width;
|
|
part->setGeometry(x, y, width, partLengths[i].toInt() - y);
|
|
} else {
|
|
x -= partLengths[i-1].toInt();
|
|
y += height;
|
|
part->setGeometry(x, y, partLengths[i].toInt() - x, height);
|
|
}
|
|
}
|
|
}
|
|
for(auto &pageMap : jpages) {
|
|
auto _program = pageMap["_program"];
|
|
auto layers = _program["layers"];
|
|
if(layers.empty()) continue;
|
|
Page page;
|
|
page.repeatTimes = pageMap["repeatTimes"].toInt();
|
|
for(int ll=(int)layers.size()-1; ll>=0; ll--) {
|
|
Layer layer;
|
|
layer.isLoop = layers[ll]["repeat"].toBool();
|
|
auto sources = layers[ll]["sources"];
|
|
auto border = layers[ll]["border"];
|
|
EleBorder *bdEle = 0;
|
|
int bdWidth = 0, bdStart = 0xffff, bdEnd = 0;
|
|
if(! border.isNull()) {
|
|
bdEle = new EleBorder(dir+"/"+border["img"].toString(), border["eff"].toString(), border["speed"].toInt(), box);
|
|
bdWidth = bdEle->img.height();
|
|
}
|
|
Source src;
|
|
for(auto &source : sources) {
|
|
src.type = source["_type"].toString();
|
|
if(src.type.isEmpty()) continue;
|
|
auto timeSpan = source["timeSpan"].toInt()*1000;
|
|
if(timeSpan==0) continue;
|
|
auto x = source["left"].toInt()+bdWidth;
|
|
auto y = source["top"].toInt()+bdWidth;
|
|
auto w = source["width"].toInt()-bdWidth-bdWidth;
|
|
auto h = source["height"].toInt()-bdWidth-bdWidth;
|
|
bool notAudio = src.type!="Audio";
|
|
if((w<=0 || h<=0) && notAudio) continue;
|
|
src.startTime = source["playTime"].toInt()*1000;
|
|
if(bdStart > src.startTime) bdStart = src.startTime;
|
|
src.endTime = src.startTime + timeSpan;
|
|
if(bdEnd < src.endTime) bdEnd = src.endTime;
|
|
if(layer.dur < src.endTime) layer.dur = src.endTime;
|
|
if(notAudio) {
|
|
if(page.sDur < src.endTime) page.sDur = src.endTime;
|
|
} else if(page.audioDur < src.endTime) page.audioDur = src.endTime;
|
|
|
|
if(src.exitDur!=0) src.exitStart = timeSpan*60/1000 - src.exitDur;
|
|
|
|
auto id = source["id"].toString();
|
|
src.view = 0;
|
|
if(src.type=="Image") {
|
|
if(source["fileExt"].toString()=="gif") src.view = new EleGif(dir+"/"+id, box);
|
|
else {
|
|
auto lb = new QLabel(box);
|
|
lb->setPixmap(QPixmap(dir+"/"+id));
|
|
lb->setScaledContents(true);
|
|
src.view = lb;
|
|
}
|
|
} else if(src.type.startsWith("Environ")) {
|
|
auto arrayPics = source["arrayPics"];
|
|
for(int i=(int)arrayPics.size()-1; i>=0; i--) if(arrayPics[i]["name"].toString() == "previewTmp") {
|
|
if(source["bSingleScroll"].toBool()) src.view = new EleScroll(box, dir+"/" + arrayPics[i]["id"].toString(), 'l', source["iScrollSpeed"].toDouble());
|
|
else src.view = new EleScroll(box, dir+"/"+arrayPics[i]["id"].toString());
|
|
break;
|
|
}
|
|
} else if(src.type=="MultiPng" || src.type=="SplitText") {
|
|
auto imgs = source["arrayPics"];
|
|
if(! imgs.empty()) src.view = new EleScroll(box, dir+"/", imgs[0], w, h);
|
|
} else if(src.type=="DigitalClockNew") src.view = new EleDigiClock(dir+"/", source, box);
|
|
else if(src.type=="AnalogClock") src.view = new EleAnaClock(w, h, dir+"/"+id, source, box);
|
|
else if(src.type=="Video" || src.type=="Audio") {
|
|
auto video = new EleVideo(dir+"/"+id, box);
|
|
auto vol = source["vol"].toInt(100);
|
|
if(vol<100) video->player->setVol(vol/100.0);
|
|
src.view = video;
|
|
} else if(src.type=="WebURL") {
|
|
auto web = new QWebEngineView(box);
|
|
web->load(QUrl(source["url"].toString()));
|
|
src.view = web;
|
|
}
|
|
else if(src.type=="Timer") src.view = new EleTimer(source, box);
|
|
else continue;
|
|
if(src.view==0) continue;
|
|
src.view->setVisible(false);
|
|
if(w) src.view->setGeometry(x, y, w, h);
|
|
layer.srcs.push_back(src);
|
|
}
|
|
if(bdEle && ! sources.empty()) {
|
|
auto geometry = border["geometry"];
|
|
src.startTime = bdStart;
|
|
src.endTime = bdEnd;
|
|
src.view = bdEle;
|
|
src.view->setVisible(false);
|
|
src.view->setGeometry(geometry[0].toInt(), geometry[1].toInt(), geometry[2].toInt(), geometry[3].toInt());
|
|
layer.srcs.push_back(src);
|
|
}
|
|
if(! layer.srcs.empty()) page.layers.emplace_back(std::move(layer));
|
|
}
|
|
if(page.sDur==0) {
|
|
if(page.audioDur > 0) page.sDur = page.audioDur;
|
|
else continue;
|
|
}
|
|
page.tDur = page.sDur * page.repeatTimes;
|
|
for(auto layer=page.layers.begin(); layer<page.layers.end(); ++layer) {
|
|
for(auto src=layer->srcs.begin(); src<layer->srcs.end(); ++src) {
|
|
if(src->startTime >= page.sDur) {
|
|
if(layer->srcs.size() > 1) layer->srcs.erase(src--);
|
|
else {
|
|
page.layers.erase(layer--);
|
|
goto conti_layer;
|
|
}
|
|
} else if(src->endTime > page.sDur) src->endTime = page.sDur;
|
|
}
|
|
if(layer->dur > page.sDur) layer->dur = page.sDur;
|
|
if(layer->dur == page.sDur) layer->isLoop = false;
|
|
conti_layer:;
|
|
}
|
|
pages.emplace_back(std::move(page));
|
|
}
|
|
|
|
menu = new QMenu(this);
|
|
auto act = menu->addAction(tr("Move to Top Left"));
|
|
connect(act, &QAction::triggered, this, [this] {
|
|
move(0,0);
|
|
});
|
|
act = menu->addAction(tr("Set Position"));
|
|
connect(act, &QAction::triggered, this, [this] {
|
|
PosDlg dlg(this);
|
|
dlg.exec();
|
|
});
|
|
act = menu->addAction(tr("Close"));
|
|
connect(act, &QAction::triggered, this, [this] {
|
|
if(self==this) self = nullptr;
|
|
close();
|
|
});
|
|
|
|
setVisible(true);
|
|
if(pages.empty()) return;
|
|
pages[0].setMillis((std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() + 999)/1000*1000);
|
|
|
|
connect(gl, &QOpenGLWidget::frameSwapped, this, &PlayWin::doFrame, Qt::UniqueConnection);
|
|
}
|
|
|
|
void PlayWin::doFrame() {
|
|
if(! isVisible()) return;
|
|
auto milli = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
|
auto& lastPage = pages[curAva];
|
|
if(milli >= lastPage.endMilli) {
|
|
lastPage.hide();
|
|
if(curTimes < lastPage.repeatTimes) curTimes++;
|
|
else {
|
|
curTimes = 1;
|
|
curAva++;
|
|
if(curAva >= (int)pages.size()) {
|
|
curAva = 0;
|
|
auto isDiff = milli-lastPage.endMilli>=1000;
|
|
pages[curAva].setMillis(isDiff ? milli : lastPage.endMilli);
|
|
return;
|
|
}
|
|
}
|
|
pages[curAva].setMillis(lastPage.endMilli);
|
|
} else {
|
|
for(auto &layer : lastPage.layers) {
|
|
for(auto &src : layer.srcs) {
|
|
if(src.view->isVisible()) {
|
|
if(milli >= src.endMilli) src.hide();
|
|
else src.doEff();
|
|
} else if(milli < src.endMilli && milli >= src.startMilli) src.show();
|
|
}
|
|
if(milli >= layer.endMilli) {
|
|
layer.endMilli += layer.dur;
|
|
for(auto &src : layer.srcs) {
|
|
src.endMilli += layer.dur;
|
|
src.startMilli += layer.dur;
|
|
if(src.startTime > 0) src.hide();
|
|
else src.show();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void PlayWin::mousePressEvent(QMouseEvent *e) {
|
|
if(e->button() == Qt::LeftButton) {
|
|
mPressRel = pos() - e->globalPos();
|
|
}
|
|
}
|
|
void PlayWin::mouseReleaseEvent(QMouseEvent *e) {
|
|
if(e->button() == Qt::LeftButton) mPressRel.setX(INT_MAX);
|
|
}
|
|
void PlayWin::mouseMoveEvent(QMouseEvent *e) {
|
|
if(e->buttons() & Qt::LeftButton) {
|
|
if(mPressRel.x()==INT_MAX) return;
|
|
move(mPressRel + e->globalPos());
|
|
}
|
|
}
|
|
void PlayWin::leaveEvent(QEvent *) {
|
|
mPressRel.setX(INT_MAX);
|
|
}
|
|
|
|
void PlayWin::contextMenuEvent(QContextMenuEvent *event){
|
|
menu->exec(event->globalPos());
|
|
}
|
|
void PlayWin::closeEvent(QCloseEvent *) {
|
|
if(self==this) self = 0;
|
|
gPlayPos = pos();
|
|
}
|