#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 #include #include #include #include #include #include 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 previewImg = source["previewImg"].toStr(); if(! previewImg.isEmpty()) { if(source["bSingleScroll"].toBool()) src.view = new EleScroll(box, dir+"/"+previewImg, 'l', source["iScrollSpeed"].toDouble()); else src.view = new EleScroll(box, dir+"/"+previewImg); } } 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); auto offX = source["offX"].toInt(); auto offY = source["offY"].toInt(); if(offX || offY) connect(web, &QWebEngineView::loadFinished, this, [=] { disconnect(web, &QWebEngineView::loadFinished, this, 0); web->page()->runJavaScript("window.scrollTo("+QString::number(offX)+", "+QString::number(offY)+")"); }); web->setZoomFactor(source["zoom"].toInt(100)/100.0); web->load(QUrl(source["url"].toString())); web->setFocusPolicy(Qt::NoFocus); 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(); layersrcs.begin(); srcsrcs.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::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::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(); }