#include "pagelistitem.h" #include "cfg.h" #include "tools.h" #include "base/ffutil.h" #include "program/wplanlist.h" #include "base/lodateselector.h" #include "program/ebase.h" #include "program/etext.h" #include "program/ephoto.h" #include "program/evideo.h" #include "program/eaudio.h" #include "program/egif.h" #include "program/edclock.h" #include "program/eaclock.h" #include "program/eenviron.h" #include "program/eweb.h" #include "program/etimer.h" #include "program/emultiwin.h" #include "globaldefine.h" #include #include #include #include #include #include #include class PageScene : public QGraphicsScene { public: PageScene(qreal x, qreal y, qreal width, qreal height, QObject *parent = nullptr) : QGraphicsScene(x, y, width, height, parent) {}; void drawBackground(QPainter *painter, const QRectF &rect) { QGraphicsScene::drawBackground(painter, rect); painter->fillRect(sceneRect(), Qt::black); } }; PageListItem::PageListItem(const QJsonObject &attr, const QString &pageDir) : mAttr(attr), mPageDir(pageDir) { setSizeHint(QSize(0,80)); mScene = new PageScene(0, 0, gProgItem->mWidth, gProgItem->mHeight, this); auto elements = mAttr["elements"].toArray(); foreach(auto ele, elements) { QString type = ele["elementType"].toString(); EBase *element = 0; if(type=="Text") element = new EText(ele.toObject()); else if(type=="Photo") element = EPhoto::create(ele.toObject(), this); else if(type=="Gif") element = EGif::create(ele.toObject(), this); else if(type=="Movie") element = EVideo::create(ele.toObject(), this); else if(type=="Audio") element = EAudio::create(ele.toObject(), this); else if(type=="DClock") element = new EDClock(ele.toObject()); else if(type=="AClock") element = new EAClock(ele.toObject()); else if(type=="Temp") element = new EEnviron(ele.toObject()); else if(type=="Web") element = new EWeb(ele.toObject()); else if(type=="Timer") element = new ETimer(ele.toObject()); else if(type=="Window") element = new EMultiWin(ele.toObject(), this); if(element) mScene->addItem(element); } } //更新页属性参数到page.json void PageListItem::updateJson() { if(mAttrWgt==0) return; //没有点开该页面进行编辑 QJsonArray elements; auto items = mScene->items(); foreach(auto item, items) { auto element = static_cast(item); if(element->mMultiWin == nullptr) elements.append(element->attrJson()); } mAttr.insert("elements", elements); QJsonArray audios; auto cnt = mAudiosList->count(); for(int i=0; iitem(i)->data(Qt::UserRole).value(); audios.append(QJsonObject{ {"dir", info.dir}, {"name", info.name}, {"dur", info.dur}, {"vol", info.vol} }); } mAttr.insert("audios", audios); } bool PageListItem::saveFiles() { mPageDir = gProgItem->mProgDir + "/" + mAttr["name"].toString(); QDir pageQDir(mPageDir); if(! pageQDir.exists() && ! pageQDir.mkpath(".")) return false; QJsonArray elements; auto items = mScene->items(); foreach(auto item, items) { auto element = static_cast(item); if(element->mMultiWin == nullptr && element->save(mPageDir)) elements.append(element->attrJson()); } mAttr.insert("elements", elements); if(mAttrWgt!=0) { QJsonArray audios; auto cnt = mAudiosList->count(); for(int i=0; iitem(i)->data(Qt::UserRole).value(); QString oldFile = info.dir + PAGEDEL_SUFFIX + "/" + info.name; if(QFileInfo::exists(oldFile)) ; else if(QFileInfo::exists(oldFile = info.dir + "/" + info.name)) ; else continue; QFile::copy(oldFile, mPageDir + "/" + info.name); info.dir = mPageDir; audios.append(QJsonObject{ {"dir", info.dir}, {"name", info.name}, {"dur", info.dur}, {"vol", info.vol} }); } mAttr.insert("audios", audios); } QFile file(mPageDir + "/page.json"); if(! file.open(QIODevice::WriteOnly)) { QMessageBox::critical(gMainWin, "Write Error", mPageDir + "/page.json "+file.errorString()); return false; } file.write(QJsonDocument(mAttr).toJson()); file.close(); return true; } QWidget *PageListItem::itemWgt() { auto wgtPage = new QWidget(); auto hBox = new QHBoxLayout(wgtPage); mGraView = new QGraphicsView(); mGraView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); mGraView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); mGraView->setEnabled(false); mGraView->setFrameShape(QFrame::NoFrame); mGraView->setFixedSize(120, 60); mGraView->setStyleSheet("QGraphicsView{background-color:transparent;}"); mGraView->setScene(mScene); qreal scale = qMin(mGraView->width() / mScene->width(), mGraView->height() / mScene->height()); mGraView->scale(scale, scale); hBox->addWidget(mGraView); fdPlayTimes = new QLabel(QString::number(mAttr["repeat"].toInt())); hBox->addWidget(fdPlayTimes); hBox->addWidget(new QLabel(tr("times"))); hBox->addStretch(); return wgtPage; } QWidget *PageListItem::attrWgt() { if(mAttrWgt!=0) return mAttrWgt; mAttrWgt = new QWidget(); mAttrWgt->setStyleSheet(R"rrr( QPushButton { padding-left: 4px; padding-right: 4px; padding-top: 2px; padding-bottom: 2px; border-radius: 4px; } QPushButton:hover { background-color: #dddddd; } QPushButton#bnAddPlan { image: url(:/res/program/AddPlan.png); width: 24; height: 24; } QPushButton#bnClearPlan { image: url(:/res/program/Clean.png); width: 24; height: 24; } QPushButton#bnDel { image: url(:/res/program/Delete.png); width: 18; height: 18; } QPushButton#bnAddPlan:pressed, QPushButton#bnClearPlan:pressed, QPushButton#bnDel:pressed { margin-top: 1px; margin-left: 1px; margin-bottom: -1px; margin-right: -1px; } QPushButton[ssName="weeklySelector"] { border: 1px solid #6A838F; width: 24; height: 24; } QPushButton[ssName="weeklySelector"]:checked { background-color: #0099cc; } )rrr"); auto vBox = new QVBoxLayout(mAttrWgt); vBox->setContentsMargins(6, 0, 6, 0); vBox->setSpacing(4); auto hBox = new QHBoxLayout(); auto lb1 = new QLabel(tr("Page name")); lb1->setMinimumWidth(80); hBox->addWidget(lb1); auto fdPageName = new QLineEdit(mAttr["name"].toString()); connect(fdPageName, &QLineEdit::textEdited, this, [this, fdPageName](const QString &text) { bool isDupli = false; auto listWgt = listWidget(); if(nullptr != listWgt) { int n = listWgt->count(); for(int i=0; i(listWgt->item(i)); if(text == item->mAttr["name"].toString()) { isDupli = true; break; } } } if(isDupli) { QString newName = tr("New") + QDateTime::currentDateTime().toString("yyyyMMddhhmmsszzz"); mAttr["name"] = newName; fdPageName->setText(newName); } else mAttr["name"] = text; }); hBox->addWidget(fdPageName); vBox->addLayout(hBox); hBox = new QHBoxLayout(); lb1 = new QLabel(tr("Play times")); lb1->setMinimumWidth(80); hBox->addWidget(lb1); auto fdPlayTimes = new QSpinBox(); fdPlayTimes->setRange(1, 9999); fdPlayTimes->setValue(mAttr["repeat"].toInt()); connect(fdPlayTimes, (void(QSpinBox::*)(int))&QSpinBox::valueChanged, this, [this](int value) { mAttr["repeat"] = value; this->fdPlayTimes->setText(QString::number(value)); }); hBox->addWidget(fdPlayTimes); hBox->addSpacing(20); auto fdLoop = new QCheckBox(tr("Sources Repeat")); fdLoop->setChecked(mAttr["loop"].toBool()); connect(fdLoop, &QCheckBox::toggled, this, [this](bool checked) { mAttr["loop"] = checked; }); hBox->addWidget(fdLoop); hBox->addStretch(); vBox->addLayout(hBox); auto line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); vBox->addWidget(line); hBox = new QHBoxLayout(); auto lb = new QLabel(); lb->setPixmap(QPixmap(":/res/program/Audio.png").scaledToHeight(24, Qt::SmoothTransformation)); hBox->addWidget(lb); hBox->addWidget(new QLabel(tr("Audios"))); hBox->addStretch(); hBox->addWidget(new QLabel(tr("Total Dur"))); auto fdTtlDur = new QLabel("0"); hBox->addWidget(fdTtlDur); hBox->addWidget(new QLabel(tr("s"))); hBox->addStretch(); auto btnAdd = new QPushButton(); btnAdd->setIcon(QIcon(":/res/program/Add.png")); btnAdd->setProperty("style","multiTool"); mAudiosList = new QListWidget(); connect(btnAdd, &QPushButton::clicked, this, [this, fdTtlDur] { auto files = QFileDialog::getOpenFileNames(gMainWin, tr("Select File"), gFileHome, EAudio::filters()); int durs = fdTtlDur->text().toInt(); for(int i=0; isetData(Qt::UserRole, QVariant::fromValue(info)); mAudiosList->addItem(item); if(i == files.count()-1) { mAudiosList->setCurrentItem(item); gFileHome = fInfo.absolutePath(); } durs += info.dur; mAudiosList->addItem(item); } fdTtlDur->setText(QString::number(durs)); }); hBox->addWidget(btnAdd); auto btnDel = new QPushButton(); btnDel->setIcon(QIcon(":/res/program/Delete.png")); btnDel->setProperty("style","multiTool"); connect(btnDel, &QPushButton::clicked, this, [this, fdTtlDur] { auto row = mAudiosList->currentRow(); if(row < 0) return; int durs = fdTtlDur->text().toInt(); auto item = mAudiosList->takeItem(row); auto info = static_cast(item->data(Qt::UserRole).value()); durs -= info.dur; delete item; fdTtlDur->setText(QString::number(durs)); }); hBox->addWidget(btnDel); auto btnGoUp = new QPushButton(); btnGoUp->setIcon(QIcon(":/res/program/GoUp.png")); btnGoUp->setProperty("style","multiTool"); connect(btnGoUp, &QPushButton::clicked, this, [this] { int row = mAudiosList->currentRow(); if(row < 1) return; mAudiosList->insertItem(row-1, mAudiosList->takeItem(row)); mAudiosList->setCurrentRow(row-1); }); hBox->addWidget(btnGoUp); auto btnGoDown = new QPushButton(); btnGoDown->setIcon(QIcon(":/res/program/GoDown.png")); btnGoDown->setProperty("style","multiTool"); connect(btnGoDown, &QPushButton::clicked, this, [this] { int row = mAudiosList->currentRow(); if(row < 0 || row > mAudiosList->count() - 2) return; mAudiosList->insertItem(row+1, mAudiosList->takeItem(row)); mAudiosList->setCurrentRow(row+1); }); hBox->addWidget(btnGoDown); vBox->addLayout(hBox); mAudiosList->setMinimumHeight(120); mAudiosList->setIconSize(QSize(20, 20)); vBox->addWidget(mAudiosList, 1); auto audios = mAttr["audios"].toArray(); int durs = 0; foreach(auto audio, audios) { AudioInfo info{audio["dir"].toString(), audio["name"].toString(), audio["dur"].toInt(), audio["vol"].toInt()}; if(info.dir.isEmpty() || info.name.isEmpty() || info.dur==0) continue; auto item = new QListWidgetItem(QIcon(":/res/program/Audio.png"), info.name); item->setData(Qt::UserRole, QVariant::fromValue(info)); durs += info.dur; mAudiosList->addItem(item); } fdTtlDur->setText(QString::number(durs)); auto wgtAudioInfo = new QWidget(); wgtAudioInfo->hide(); hBox = new QHBoxLayout(wgtAudioInfo); hBox->setContentsMargins(0,0,0,0); hBox->setSpacing(2); hBox->addWidget(new QLabel(tr("Duration"))); hBox->addSpacing(4); auto fdAudioDur = new QLabel("0"); hBox->addWidget(fdAudioDur); hBox->addWidget(new QLabel(tr("s"))); hBox->addStretch(); hBox->addWidget(new QLabel(tr("Vol"))); auto fdVol = new QSlider(Qt::Horizontal); fdVol->setMaximum(100); fdVol->setMinimumWidth(120); hBox->addWidget(fdVol); auto fdAudioVol = new QLabel("0"); fdAudioVol->setAlignment(Qt::AlignRight); fdAudioVol->setFixedWidth(38); hBox->addWidget(fdAudioVol); vBox->addWidget(wgtAudioInfo); connect(fdVol, &QSlider::valueChanged, this, [this, fdAudioVol](int value) { fdAudioVol->setText(QString::number(value)+"%"); auto item = mAudiosList->currentItem(); if(item==nullptr) return; auto info = static_cast(item->data(Qt::UserRole).value()); info.vol = value; item->setData(Qt::UserRole, QVariant::fromValue(info)); }); connect(mAudiosList, &QListWidget::currentItemChanged, this, [fdAudioDur, wgtAudioInfo, fdVol, fdAudioVol](QListWidgetItem *current, QListWidgetItem *) { if(current==nullptr) { wgtAudioInfo->hide(); return; } wgtAudioInfo->show(); auto info = static_cast(current->data(Qt::UserRole).value()); fdAudioDur->setText(QString::number(info.dur)); fdVol->setValue(info.vol); fdAudioVol->setText(QString::number(info.vol)+"%"); }); line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); vBox->addWidget(line); QJsonValue validDate = mAttr["validDate"]; auto wValidDate = new QCheckBox(tr("Valid Date")); bool isDateValid = validDate["isValid"].toBool(); wValidDate->setChecked(isDateValid); vBox->addWidget(wValidDate); hBox = new QHBoxLayout(); auto fdStart = new QDateEdit(); fdStart->setDisplayFormat("yyyy-MM-dd"); fdStart->setEnabled(isDateValid); fdStart->setDate(QDate::fromString(validDate["start"].toString(), "yyyy-MM-dd")); hBox->addWidget(fdStart); auto bnDateStart = new LoDateSelector(); bnDateStart->setEnabled(isDateValid); connect(bnDateStart, &LoDateSelector::sDateSelected, fdStart, &QDateEdit::setDate); hBox->addWidget(bnDateStart); hBox->addWidget(new QLabel("~")); auto fdEnd = new QDateEdit(); fdEnd->setDisplayFormat("yyyy-MM-dd"); fdEnd->setEnabled(isDateValid); fdEnd->setDate(QDate::fromString(validDate["end"].toString(), "yyyy-MM-dd")); connect(fdStart, &QDateEdit::dateChanged, this, [this, wValidDate, fdStart, fdEnd](const QDate &date) { auto end = fdEnd->date(); if(! date.isValid() || date > end) { QMessageBox::warning(gMainWin, tr("Warning"), tr("Start Time can't be later than End Time")); fdStart->setDate(end); } mAttr["validDate"] = QJsonObject{ {"isValid", wValidDate->isChecked()}, {"start", fdStart->date().toString("yyyy-MM-dd")}, {"end", end.toString("yyyy-MM-dd")} }; }); connect(fdEnd, &QDateEdit::dateChanged, this, [this, wValidDate, fdStart, fdEnd](const QDate &date) { QDate start = fdStart->date(); if(! date.isValid() || start > date) { QMessageBox::warning(gMainWin, tr("Warning"), tr("End Time can't be earlier than Start Time")); fdEnd->setDate(start); } mAttr["validDate"] = QJsonObject{ {"isValid", wValidDate->isChecked()}, {"start", start.toString("yyyy-MM-dd")}, {"end", fdEnd->date().toString("yyyy-MM-dd")} }; }); hBox->addWidget(fdEnd); auto bnDateEnd = new LoDateSelector(); bnDateEnd->setEnabled(isDateValid); connect(bnDateEnd, &LoDateSelector::sDateSelected, fdEnd, &QDateEdit::setDate); hBox->addWidget(bnDateEnd); hBox->addStretch(); connect(wValidDate, &QCheckBox::toggled, this, [this, fdStart, fdEnd, bnDateStart, bnDateEnd](bool checked) { fdStart->setEnabled(checked); fdEnd->setEnabled(checked); bnDateStart->setEnabled(checked); bnDateEnd->setEnabled(checked); mAttr["validDate"] = QJsonObject{ {"isValid", checked}, {"start", fdStart->date().toString("yyyy-MM-dd")}, {"end", fdEnd->date().toString("yyyy-MM-dd")} }; }); vBox->addLayout(hBox); line = new QFrame(); line->setFrameShape(QFrame::HLine); line->setFrameShadow(QFrame::Sunken); vBox->addWidget(line); hBox = new QHBoxLayout(); hBox->setSpacing(12); hBox->addWidget(new QLabel(tr("Plan"))); hBox->addStretch(); auto bnAddPlan = new QPushButton(); bnAddPlan->setObjectName("bnAddPlan"); hBox->addWidget(bnAddPlan); auto bnClearPlan = new QPushButton(); bnClearPlan->setObjectName("bnClearPlan"); hBox->addWidget(bnClearPlan); vBox->addLayout(hBox); auto wPlans = new wPlanList(); wPlans->setStyleSheet(R"rrr( QListWidget::item { height: 100; border-top: 1px solid #6A838F; margin-right: 9px; })rrr"); wPlans->onRestorePlan(mAttr["plans"].toArray()); connect(bnAddPlan, &QPushButton::clicked, wPlans, &wPlanList::onAddPlan); connect(bnClearPlan, &QPushButton::clicked, wPlans, &wPlanList::clear); connect(wPlans, &QListWidget::itemChanged, this, [this, wPlans] { mAttr["plans"] = wPlans->plansJson(); }); vBox->addWidget(wPlans, 2); return mAttrWgt; }