qt/LedOK/program/pagelistitem.cpp

633 lines
22 KiB
C++
Raw Normal View History

2023-10-23 14:58:29 +08:00
#include "pagelistitem.h"
2024-08-07 18:18:37 +08:00
#include "main.h"
2023-06-20 08:49:01 +08:00
#include "gutil/qgui.h"
2023-04-18 14:14:46 +08:00
#include "base/ffutil.h"
2022-08-25 18:37:24 +08:00
#include "base/lodateselector.h"
2023-05-09 15:08:39 +08:00
#include "program/eaclock.h"
#include "program/ebase.h"
2023-04-18 14:14:46 +08:00
#include "program/edclock.h"
#include "program/eenviron.h"
2023-05-09 15:08:39 +08:00
#include "program/egif.h"
2023-04-18 14:14:46 +08:00
#include "program/emultiwin.h"
2023-05-09 15:08:39 +08:00
#include "program/ephoto.h"
#include "program/etext.h"
#include "program/etimer.h"
2024-08-07 18:18:37 +08:00
#include "program/etimer2.h"
2023-05-09 15:08:39 +08:00
#include "program/evideo.h"
#include "program/eweb.h"
#include "tools.h"
2022-08-25 18:37:24 +08:00
#include <QDateEdit>
2023-05-09 15:08:39 +08:00
#include <QDir>
#include <QGraphicsView>
#include <QLineEdit>
#include <QMessageBox>
#include <QSpinBox>
2022-08-25 18:37:24 +08:00
class PageScene : public QGraphicsScene {
public:
2023-05-09 15:08:39 +08:00
using QGraphicsScene::QGraphicsScene;
2022-08-25 18:37:24 +08:00
void drawBackground(QPainter *painter, const QRectF &rect) {
QGraphicsScene::drawBackground(painter, rect);
painter->fillRect(sceneRect(), Qt::black);
}
};
2023-10-23 14:58:29 +08:00
PageListItem::PageListItem(const JObj &attr, const QString &pageDir) : mAttr(attr), mPageDir(pageDir) {
2023-06-20 16:09:25 +08:00
scale = qMin(128.0 / gProgItem->mWidth, 96.0 / gProgItem->mHeight);
viewW = scale * gProgItem->mWidth;
viewH = scale * gProgItem->mHeight;
setSizeHint(QSize(0, viewH+20));
2022-10-27 15:07:45 +08:00
mScene = new PageScene(0, 0, gProgItem->mWidth, gProgItem->mHeight, this);
2022-08-25 18:37:24 +08:00
auto elements = mAttr["elements"].toArray();
2023-10-23 14:58:29 +08:00
for(auto &ele : elements) {
auto type = ele["elementType"].toStr();
2023-04-18 14:14:46 +08:00
EBase *element = 0;
2023-10-23 14:58:29 +08:00
if(type=="Text") element = new EText(ele.toObj());
2024-02-21 18:08:50 +08:00
else if(type=="Image"||type=="Photo") element = EPhoto::create(ele.toObj(), this);
2023-10-23 14:58:29 +08:00
else if(type=="Gif") element = EGif::create(ele.toObj(), this);
2024-02-21 18:08:50 +08:00
else if(type=="Video"||type=="Movie") element = EVideo::create(ele.toObj(), this);
2023-10-23 14:58:29 +08:00
else if(type=="DClock") element = new EDClock(ele.toObj());
else if(type=="AClock") element = new EAClock(ele.toObj());
else if(type=="Temp") element = new EEnviron(ele.toObj());
else if(type=="Web") element = new EWeb(ele.toObj());
else if(type=="Timer") element = new ETimer(ele.toObj());
2024-08-07 18:18:37 +08:00
else if(type=="Timer2") element = new ETimer2(ele.toObj());
2023-10-23 14:58:29 +08:00
else if(type=="Window") element = new EMultiWin(ele.toObj(), this);
2023-04-18 14:14:46 +08:00
if(element) mScene->addItem(element);
2022-08-25 18:37:24 +08:00
}
}
//更新页属性参数到page.json
void PageListItem::updateJson() {
if(mAttrWgt==0) return; //没有点开该页面进行编辑
2023-10-23 14:58:29 +08:00
JArray elements;
2022-08-25 18:37:24 +08:00
auto items = mScene->items();
2023-10-23 14:58:29 +08:00
for(auto &item : items) {
auto element = (EBase*) item;
if(element->mMultiWin == 0) elements << element->attrJson();
2022-08-25 18:37:24 +08:00
}
2023-10-23 14:58:29 +08:00
mAttr["elements"] = elements;
2022-08-25 18:37:24 +08:00
auto cnt = mAudiosList->count();
2023-10-23 14:58:29 +08:00
if(cnt==0) mAttr.erase("audios");
else {
JArray audios;
for(int i=0; i<cnt; i++) {
auto info = mAudiosList->item(i)->data(Qt::UserRole).value<AudioInfo>();
audios << JObj{
{"dir", info.dir},
{"name", info.name},
{"dur", info.dur},
{"vol", info.vol}
};
}
mAttr["audios"] = audios;
2022-08-25 18:37:24 +08:00
}
}
bool PageListItem::saveFiles() {
2022-10-27 15:07:45 +08:00
mPageDir = gProgItem->mProgDir + "/" + mAttr["name"].toString();
2022-08-25 18:37:24 +08:00
QDir pageQDir(mPageDir);
2023-04-28 16:02:14 +08:00
if(! pageQDir.exists() && ! pageQDir.mkpath(mPageDir)) return false;
2022-08-25 18:37:24 +08:00
2023-10-23 14:58:29 +08:00
JArray elements;
2022-08-25 18:37:24 +08:00
auto items = mScene->items();
2023-10-23 14:58:29 +08:00
for(auto &item : items) {
auto element = (EBase*) item;
if(element->mMultiWin == 0 && element->save(mPageDir)) elements << element->attrJson();
2022-08-25 18:37:24 +08:00
}
2023-10-23 14:58:29 +08:00
mAttr["elements"] = elements;
2023-05-11 11:47:00 +08:00
if(mAttrWgt) {
2022-08-25 18:37:24 +08:00
auto cnt = mAudiosList->count();
2023-10-23 14:58:29 +08:00
if(cnt==0) mAttr.erase("audios");
else {
JArray audios;
for(int i=0; i<cnt; i++) {
auto info = mAudiosList->item(i)->data(Qt::UserRole).value<AudioInfo>();
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 << JObj{
{"dir", info.dir},
{"name", info.name},
{"dur", info.dur},
{"vol", info.vol}
};
}
mAttr["audios"] = audios;
2022-08-25 18:37:24 +08:00
}
}
QFile file(mPageDir + "/page.json");
if(! file.open(QIODevice::WriteOnly)) {
2023-05-11 11:47:00 +08:00
QMessageBox::critical(listWidget(), "Write Error", mPageDir + "/page.json "+file.errorString());
2022-08-25 18:37:24 +08:00
return false;
}
2023-10-23 14:58:29 +08:00
file.write(JToBytes(mAttr, "\t"));
2022-08-25 18:37:24 +08:00
file.close();
return true;
}
QWidget *PageListItem::itemWgt() {
2023-06-20 08:49:01 +08:00
auto wgtPage = new QWidget;
2023-06-20 16:09:25 +08:00
auto grid = new Grid(wgtPage);
grid->setContentsMargins(0,0,0,0);
grid->setSpacing(0);
2023-06-20 08:49:01 +08:00
2023-06-20 16:09:25 +08:00
grid->addWidget(fdIdx = new QLabel, 0, 0);
fdIdx->setMinimumWidth(32);
fdIdx->setAlignment(Qt::AlignCenter);
fdIdx->setNum(listWidget()->count());
mGraView = new QGraphicsView;
2022-08-25 18:37:24 +08:00
mGraView->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
mGraView->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
mGraView->setEnabled(false);
mGraView->setFrameShape(QFrame::NoFrame);
2023-06-20 16:09:25 +08:00
mGraView->setFixedSize(viewW, viewH);
2022-08-25 18:37:24 +08:00
mGraView->setStyleSheet("QGraphicsView{background-color:transparent;}");
mGraView->setScene(mScene);
mGraView->scale(scale, scale);
2023-06-20 16:09:25 +08:00
grid->addWidget(mGraView, 0, 1);
2022-08-25 18:37:24 +08:00
2023-06-20 16:09:25 +08:00
auto hBox = new HBox;
hBox->setSpacing(4);
grid->addLayout(hBox, 1, 1);
grid->setColumnStretch(2, 1);
grid->setRowStretch(2, 1);
2023-06-20 08:49:01 +08:00
2023-06-20 16:09:25 +08:00
hBox->addWidget(fdPlayTimes = new QLabel(QString::number(mAttr["repeat"].toInt())));
gFont(fdPlayTimes, 12);
2023-06-20 08:49:01 +08:00
2023-06-20 16:09:25 +08:00
auto fdTimes = new QLabel(tr("times"));
gFont(fdTimes, 12);
hBox->addWidget(fdTimes);
hBox->addStretch();
2022-08-25 18:37:24 +08:00
return wgtPage;
}
QWidget *PageListItem::attrWgt() {
2023-05-11 11:47:00 +08:00
if(mAttrWgt) return mAttrWgt;
2022-08-25 18:37:24 +08:00
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 {
2023-04-18 14:14:46 +08:00
image: url(:/res/program/AddPlan.png);
2022-08-25 18:37:24 +08:00
width: 24;
height: 24;
}
QPushButton#bnClearPlan {
2023-04-18 14:14:46 +08:00
image: url(:/res/program/Clean.png);
2022-08-25 18:37:24 +08:00
width: 24;
height: 24;
}
QPushButton#bnAddPlan:pressed,
QPushButton#bnClearPlan:pressed,
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();
2023-10-23 14:58:29 +08:00
if(listWgt) {
for(int i=0; i<listWgt->count(); i++) {
2022-08-25 18:37:24 +08:00
auto item = static_cast<PageListItem*>(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);
2023-04-18 14:14:46 +08:00
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);
2022-08-25 18:37:24 +08:00
hBox->addStretch();
vBox->addLayout(hBox);
2023-10-23 14:58:29 +08:00
auto line = new QFrame;
2022-08-25 18:37:24 +08:00
line->setFrameShape(QFrame::HLine);
line->setFrameShadow(QFrame::Sunken);
vBox->addWidget(line);
hBox = new QHBoxLayout();
auto lb = new QLabel();
2023-04-18 14:14:46 +08:00
lb->setPixmap(QPixmap(":/res/program/Audio.png").scaledToHeight(24, Qt::SmoothTransformation));
2022-08-25 18:37:24 +08:00
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();
2023-04-18 14:14:46 +08:00
btnAdd->setIcon(QIcon(":/res/program/Add.png"));
2022-08-25 18:37:24 +08:00
btnAdd->setProperty("style","multiTool");
2024-02-21 18:08:50 +08:00
mAudiosList = new QListWidget;
2023-05-11 11:47:00 +08:00
connect(btnAdd, &QPushButton::clicked, mAttrWgt, [this, fdTtlDur] {
auto files = QFileDialog::getOpenFileNames(mAttrWgt, tr("Select File"), gFileHome);
2022-08-25 18:37:24 +08:00
int durs = fdTtlDur->text().toInt();
for(int i=0; i<files.count(); i++) {
int64_t dur;
2023-04-18 14:14:46 +08:00
QString err = audioInfo(files[i].toUtf8(), &dur);
2022-08-25 18:37:24 +08:00
if(! err.isEmpty()) {
2023-05-11 11:47:00 +08:00
QMessageBox::critical(mAttrWgt, "Audio Error", err+"\n"+files[i]);
2022-08-25 18:37:24 +08:00
continue;
}
QFileInfo fInfo(files[i]);
2024-02-21 18:08:50 +08:00
AudioInfo info{fInfo.absolutePath(), fInfo.fileName(), (int)round(dur*0.000001)};
2023-04-18 14:14:46 +08:00
auto item = new QListWidgetItem(QIcon(":/res/program/Audio.png"), info.name);
2022-08-25 18:37:24 +08:00
item->setData(Qt::UserRole, QVariant::fromValue(info));
mAudiosList->addItem(item);
if(i == files.count()-1) {
mAudiosList->setCurrentItem(item);
2022-09-13 23:16:36 +08:00
gFileHome = fInfo.absolutePath();
2022-08-25 18:37:24 +08:00
}
durs += info.dur;
mAudiosList->addItem(item);
}
fdTtlDur->setText(QString::number(durs));
});
hBox->addWidget(btnAdd);
auto btnDel = new QPushButton();
2023-04-18 14:14:46 +08:00
btnDel->setIcon(QIcon(":/res/program/Delete.png"));
2022-08-25 18:37:24 +08:00
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<AudioInfo>(item->data(Qt::UserRole).value<AudioInfo>());
durs -= info.dur;
delete item;
fdTtlDur->setText(QString::number(durs));
});
hBox->addWidget(btnDel);
auto btnGoUp = new QPushButton();
2023-04-18 14:14:46 +08:00
btnGoUp->setIcon(QIcon(":/res/program/GoUp.png"));
2022-08-25 18:37:24 +08:00
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();
2023-04-18 14:14:46 +08:00
btnGoDown->setIcon(QIcon(":/res/program/GoDown.png"));
2022-08-25 18:37:24 +08:00
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);
2023-10-23 14:58:29 +08:00
auto audios = mAttr("audios");
2022-08-25 18:37:24 +08:00
int durs = 0;
2023-10-23 14:58:29 +08:00
for(auto &audio : audios) {
2022-08-25 18:37:24 +08:00
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;
2023-04-18 14:14:46 +08:00
auto item = new QListWidgetItem(QIcon(":/res/program/Audio.png"), info.name);
2022-08-25 18:37:24 +08:00
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<AudioInfo>(item->data(Qt::UserRole).value<AudioInfo>());
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<AudioInfo>(current->data(Qt::UserRole).value<AudioInfo>());
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);
2023-10-23 14:58:29 +08:00
auto validDate = mAttr["validDate"];
2022-08-25 18:37:24 +08:00
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) {
2023-05-11 11:47:00 +08:00
QMessageBox::warning(mAttrWgt, tr("Warning"), tr("Start Time can't be later than End Time"));
2022-08-25 18:37:24 +08:00
fdStart->setDate(end);
}
2023-10-23 14:58:29 +08:00
mAttr["validDate"] = JObj{
2022-08-25 18:37:24 +08:00
{"isValid", wValidDate->isChecked()},
{"start", fdStart->date().toString("yyyy-MM-dd")},
{"end", end.toString("yyyy-MM-dd")}
};
});
2023-05-11 11:47:00 +08:00
connect(fdEnd, &QDateEdit::dateChanged, mAttrWgt, [this, wValidDate, fdStart, fdEnd](const QDate &date) {
2022-08-25 18:37:24 +08:00
QDate start = fdStart->date();
if(! date.isValid() || start > date) {
2023-05-11 11:47:00 +08:00
QMessageBox::warning(mAttrWgt, tr("Warning"), tr("End Time can't be earlier than Start Time"));
2022-08-25 18:37:24 +08:00
fdEnd->setDate(start);
}
2023-10-23 14:58:29 +08:00
mAttr["validDate"] = JObj{
2022-08-25 18:37:24 +08:00
{"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);
2023-10-23 14:58:29 +08:00
mAttr["validDate"] = JObj{
2022-08-25 18:37:24 +08:00
{"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);
2023-10-23 14:58:29 +08:00
auto bnClearPlan = new QPushButton;
2022-08-25 18:37:24 +08:00
bnClearPlan->setObjectName("bnClearPlan");
hBox->addWidget(bnClearPlan);
vBox->addLayout(hBox);
2023-10-23 14:58:29 +08:00
auto listPlan = new QListWidget;
connect(bnClearPlan, &QPushButton::clicked, listPlan, [=] {
listPlan->clear();
mAttr.erase("plans");
});
auto planChanged = [this, listPlan] {
if(listPlan->count()==0) mAttr.erase("plans");
else {
JArray plans;
for(int i=0; i<listPlan->count(); i++) {
auto item = (PlanItemWgt*) listPlan->itemWidget(listPlan->item(i));
JArray weekly;
for(int i=0; i<7; ++i) if(item->btnDays[i]->isChecked()) weekly.append(i+1);
plans.append(JObj{
{"start", item->tStart->time().toString("hh:mm")},
{"end", item->tEnd->time().toString("hh:mm")},
{"weekly", weekly}
});
}
mAttr["plans"] = plans;
}
};
auto plans = mAttr("plans");
for(int i=0; i<(int)plans.size(); i++) {
QListWidgetItem *item = new QListWidgetItem(listPlan);
item->setSizeHint({1, 80});
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
auto json = plans[i].toObj();
auto widget = new PlanItemWgt(item, &json);
connect(widget, &PlanItemWgt::sigItemChanged, listPlan, planChanged);
}
connect(bnAddPlan, &QPushButton::clicked, listPlan, [=] {
QListWidgetItem *item = new QListWidgetItem(listPlan);
item->setSizeHint({1, 80});
item->setFlags(item->flags() & ~Qt::ItemIsSelectable);
auto widget = new PlanItemWgt(item);
connect(widget, &PlanItemWgt::sigItemChanged, listPlan, planChanged);
planChanged();
2022-08-25 18:37:24 +08:00
});
2023-10-23 14:58:29 +08:00
vBox->addWidget(listPlan, 2);
2022-08-25 18:37:24 +08:00
return mAttrWgt;
}
2023-10-23 14:58:29 +08:00
PlanItemWgt::PlanItemWgt(QListWidgetItem *item, const JObj *json) : m_item(item) {
auto vBox = new VBox(this);
vBox->setContentsMargins(6, 6, 6, 0);
auto hBox = new HBox(vBox);
fdIdx = new QLabel;
fdIdx->setNum(item->listWidget()->count());
hBox->addWidget(fdIdx);
hBox->addStretch();
tStart = new QTimeEdit;
tStart->setDisplayFormat("HH:mm");
tStart->setMinimumWidth(80);
auto ft = tStart->font();
ft.setPixelSize(14);
tStart->setFont(ft);
connect(tStart, &QTimeEdit::timeChanged, this, &PlanItemWgt::sigItemChanged);
hBox->addWidget(tStart);
hBox->addStretch();
tEnd = new QTimeEdit(QTime(23, 59));
tEnd->setDisplayFormat("HH:mm");
tEnd->setMinimumWidth(80);
tEnd->setFont(ft);
connect(tEnd, &QTimeEdit::timeChanged, this, &PlanItemWgt::sigItemChanged);
hBox->addWidget(tEnd);
hBox->addStretch();
bnDel = new QPushButton;
bnDel->setIcon(QIcon(":/res/program/Delete.png"));
bnDel->setFixedSize(24, 24);
bnDel->setObjectName("bnDel");
connect(bnDel, &QPushButton::clicked, this, [=] {
auto listPlan = m_item->listWidget();
listPlan->removeItemWidget(m_item);
delete m_item;
for(int i=0; i<listPlan->count(); i++) ((PlanItemWgt*) listPlan->itemWidget(listPlan->item(i)))->fdIdx->setNum(i+1);
emit sigItemChanged();
});
hBox->addWidget(bnDel);
hBox = new HBox(vBox);
QString strs[]{tr("M"), tr("Tu"), tr("W"), tr("Th"), tr("F"), tr("Sa"), tr("Su")};
for(int i=0; i<7; ++i) {
btnDays[i] = new QPushButton(strs[i]);
btnDays[i]->setCheckable(true);
btnDays[i]->setProperty("ssName", "weeklySelector");
hBox->addWidget(btnDays[i]);
hBox->addStretch();
}
if(json==0) for(int i=0; i<7; ++i) btnDays[i]->setChecked(true);
else {
tStart->setTime(QTime::fromString((*json)["start"].toString(), "hh:mm"));
tEnd->setTime(QTime::fromString((*json)["end"].toString(), "hh:mm"));
auto weekly = (*json)["weekly"].toArray();
for(auto &day : weekly) {
auto i = day.toInt()-1;
if(i>=0 && i<7) btnDays[i]->setChecked(true);
}
}
for(int i=0; i<7; ++i) connect(btnDays[i], &QPushButton::toggled, this, &PlanItemWgt::sigItemChanged);
vBox->addSpacing(6);
auto line = new QFrame;
line->setFrameStyle(QFrame::HLine | QFrame::Sunken);
vBox->addWidget(line);
item->listWidget()->setItemWidget(item, this);
}