qt/LedOK/progpanel.cpp

383 lines
16 KiB
C++
Raw Normal View History

2022-08-25 18:37:24 +08:00
#include "progpanel.h"
#include "globaldefine.h"
2023-04-18 14:14:46 +08:00
#include "gutil/qgui.h"
#include "cfg.h"
2022-08-25 18:37:24 +08:00
#include "player/playwin.h"
2023-04-18 14:14:46 +08:00
#include "program/progeditorwin.h"
#include "program/copydirthread.h"
2022-08-25 18:37:24 +08:00
#include <QApplication>
#include <QMessageBox>
2023-04-18 14:14:46 +08:00
#include <QStandardPaths>
#include <QProgressBar>
2023-05-15 16:06:10 +08:00
#include <QFileDialog>
2023-09-19 11:49:20 +08:00
#include <QLineEdit>
2022-08-25 18:37:24 +08:00
2023-08-01 11:42:41 +08:00
ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
2022-08-25 18:37:24 +08:00
setAttribute(Qt::WA_DeleteOnClose);
setAutoFillBackground(true);
QPalette pal;
pal.setBrush(QPalette::Window, QColor(0xeeeeee));
setPalette(pal);
auto vBox = new QVBoxLayout(this);
vBox->setContentsMargins(0, 0, 0, 0);
vBox->setSpacing(0);
auto hBox = new QHBoxLayout();
hBox->setContentsMargins(6,6,6,6);
hBox->setSpacing(6);
vBox->addLayout(hBox);
bnNew = new QPushButton(tr("New"));
bnNew->setFixedSize(88, 38);
bnNew->setProperty("ssType", "progManageTool");
hBox->addWidget(bnNew);
2022-09-30 18:08:39 +08:00
connect(bnNew, &QPushButton::clicked, this, [this] {
2023-04-18 14:14:46 +08:00
ProgCreateDlg dlg("", 512, 256, "", "", this);
2022-09-30 18:08:39 +08:00
if(dlg.exec() != QDialog::Accepted) return;
if(checkIfNameRepeated(dlg.fdName->text())) return;
2023-10-23 14:58:29 +08:00
QList<int> widths;
int max = 0;
2023-08-01 11:42:41 +08:00
auto width = dlg.fdWidth->value();
2023-10-23 14:58:29 +08:00
if(dlg.fdIsUltraLong->isChecked()) {
auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts);
int ttl = 0;
for(auto &splitWidth : splitWidths) {
int val = splitWidth.toInt();
if(val==0) continue;
if(max < val) max = val;
widths.append(val);
ttl += val;
if(ttl>=width) break;
}
if(max) {
while(ttl < width) {
widths.append(max);
ttl += max;
}
if(ttl > width) widths.last() -= ttl - width;
2023-04-18 14:14:46 +08:00
}
}
2023-05-11 11:47:00 +08:00
auto item = new ProgItem(mProgsDir, dlg.fdName->text(), width, dlg.fdHeight->value(), dlg.fdRemark->toPlainText(), widths, max, mProgTree);
2022-09-30 18:08:39 +08:00
item->save();//保存pro.json
2023-10-23 14:58:29 +08:00
if(mProgTree->fdCheckAll->checkState()==Qt::Checked) {
mProgTree->fdCheckAll->blockSignals(true);
mProgTree->fdCheckAll->setCheckState(Qt::PartiallyChecked);
mProgTree->fdCheckAll->blockSignals(false);
}
2023-05-11 11:47:00 +08:00
auto editor = new ProgEditorWin(item, this);
2023-04-28 16:02:14 +08:00
editor->show();
2022-09-30 18:08:39 +08:00
});
2022-08-25 18:37:24 +08:00
bnEdit = new QPushButton(tr("Edit"));
bnEdit->setFixedSize(QSize(88, 38));
bnEdit->setProperty("ssType", "progManageTool");
bnEdit->setEnabled(false);
hBox->addWidget(bnEdit);
connect(bnEdit, SIGNAL(clicked(bool)), this, SLOT(onEditClicked(bool)));
bnDelete = new QPushButton(tr("Delete"));
bnDelete->setFixedSize(QSize(88, 38));
bnDelete->setProperty("ssType", "progManageTool");
bnDelete->setEnabled(false);
hBox->addWidget(bnDelete);
connect(bnDelete, SIGNAL(clicked(bool)), this, SLOT(onDeleteClicked(bool)));
bnImport = new QPushButton(tr("Import"));
2023-04-18 14:14:46 +08:00
bnImport->setFixedSize(88, 38);
2022-08-25 18:37:24 +08:00
bnImport->setProperty("ssType", "progManageTool");
hBox->addWidget(bnImport);
2022-09-30 18:08:39 +08:00
connect(bnImport, &QPushButton::clicked, this, [this] {
2023-04-28 16:02:14 +08:00
auto dir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
2023-04-18 14:14:46 +08:00
if(dir.isEmpty()) return;
QString progsDir = programsDir();
if(dir.contains(progsDir, Qt::CaseInsensitive)) {
QMessageBox::warning(this, tr("Tip"), tr("The imported directory is already in the working directory, so there is no need to import it again!"));
return;
}
QStringList progDirs;
if(QFileInfo::exists(dir + "/pro.json")) progDirs.append(dir);
else {
QStringList subdirNames = QDir(dir).entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach(QString subdirName, subdirNames) {
auto subdir = dir + "/" + subdirName;
if(! QFileInfo::exists(subdir + "/pro.json")) continue;
if(QFileInfo::exists(progsDir + "/" + subdirName)) {
2023-05-11 11:47:00 +08:00
auto res = QMessageBox::information(this, tr("Tip Info"), subdirName + tr(":solution(s) already exist.are you sure you want to overwrite the existing solution(s)?"), QMessageBox::Yes, QMessageBox::No);
2023-04-18 14:14:46 +08:00
if(res == QMessageBox::No) continue;
}
progDirs.append(subdir);
}
if(progDirs.isEmpty()) return;
}
ProgPortDlg dlg(this, tr("Import"));
dlg.table->setRowCount(progDirs.count());
for(int i=0; i<progDirs.count(); i++) {
dlg.table->setItem(i, 0, new QTableWidgetItem(QFileInfo(progDirs[i]).fileName()));
dlg.table->setCellWidget(i, 1, new QProgressBar);
}
connect(dlg.bnOK, &QPushButton::clicked, this, [=, &dlg] {
for(int i=0; i<progDirs.count(); i++) ((QProgressBar*)dlg.table->cellWidget(i, 1))->setMaximum(dirFileSize(progDirs[i]));
auto thread = new CopyDirThread();
thread->dirSrcs = progDirs;
thread->dirDst = progsDir;
connect(thread, &CopyDirThread::sigProgress, &dlg, [&dlg](int i, int value) {
((QProgressBar*)dlg.table->cellWidget(i, 1))->setValue(value);
});
thread->start();
});
dlg.exec();
mProgTree->clear();
QStringList progNames = QDir(mProgsDir).entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach(QString pro_name, progNames) {
QFile jFile(mProgsDir + "/" + pro_name + "/pro.json");
if(! jFile.exists()) continue;
if(! jFile.open(QIODevice::ReadOnly)) continue;
auto data = jFile.readAll();
jFile.close();
2023-05-11 11:47:00 +08:00
m_pwPorgramItemList.append(new ProgItem(mProgsDir, QJsonDocument::fromJson(data).object(), mProgTree));
2023-04-18 14:14:46 +08:00
}
2022-09-30 18:08:39 +08:00
});
2022-08-25 18:37:24 +08:00
bnExport = new QPushButton(tr("Export"));
bnExport->setFixedSize(QSize(88, 38));
bnExport->setEnabled(false);
bnExport->setProperty("ssType", "progManageTool");
hBox->addWidget(bnExport);
2023-04-18 14:14:46 +08:00
connect(bnExport, &QPushButton::clicked, this, [=] {
int cnt = mProgTree->topLevelItemCount();
QStringList progNames;
2023-09-19 11:49:20 +08:00
for(int i=0; i<cnt; i++) if(mProgTree->item(i)->checkState("check") == Qt::Checked) progNames.append(((ProgItem*) mProgTree->topLevelItem(i))->mName);
2023-04-18 14:14:46 +08:00
if(progNames.isEmpty()) return;
ProgPortDlg dlg(this, tr("Export"));
dlg.table->setRowCount(progNames.count());
for(int i=0; i<progNames.count(); i++) {
dlg.table->setItem(i, 0, new QTableWidgetItem(progNames[i]));
dlg.table->setCellWidget(i, 1, new QProgressBar);
}
connect(dlg.bnOK, &QPushButton::clicked, this, [=, &dlg] {
QString dirDst = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
if(dirDst.isEmpty()) return;
auto progsDir = programsDir();
auto thread = new CopyDirThread();
for(int i=0; i<progNames.count(); i++) {
auto dir = progsDir+"/"+progNames[i];
((QProgressBar*)dlg.table->cellWidget(i, 1))->setMaximum(dirFileSize(dir));
thread->dirSrcs.append(dir);
}
thread->dirDst = dirDst;
connect(thread, &CopyDirThread::sigProgress, &dlg, [&dlg](int i, int value) {
((QProgressBar*)dlg.table->cellWidget(i, 1))->setValue(value);
});
thread->start();
});
dlg.exec();
});
2022-08-25 18:37:24 +08:00
bnSend = new QPushButton(tr("Send"));
bnSend->setFixedSize(QSize(88, 38));
bnSend->setProperty("ssType", "progManageTool");
bnSend->setEnabled(false);
bnSend->hide();
hBox->addWidget(bnSend);
btnPlay = new QPushButton(tr("Play")+"/"+tr("Stop"));
btnPlay->setFixedSize(QSize(88, 38));
btnPlay->setProperty("ssType", "progManageTool");
hBox->addWidget(btnPlay);
2023-08-01 11:42:41 +08:00
connect(btnPlay, &QPushButton::clicked, this, [this] {
if(PlayWin::self) PlayWin::self->close();
2022-08-25 18:37:24 +08:00
else {
2022-09-30 18:08:39 +08:00
int cnt = mProgTree->topLevelItemCount();
2023-09-19 11:49:20 +08:00
for(int i=0; i<cnt; i++) if(mProgTree->item(i)->checkState("check") == Qt::Checked) {
auto item = (ProgItem*) mProgTree->topLevelItem(i);
2023-10-23 14:58:29 +08:00
auto dir = mProgsDir+"/"+item->mName+"_tmp";
2022-08-25 18:37:24 +08:00
QFile file(dir+"/program");
if(! file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
2023-10-23 14:58:29 +08:00
auto value = file.readAll();
2022-08-25 18:37:24 +08:00
file.close();
2023-10-23 14:58:29 +08:00
QString jsErr;
auto prog = JFrom(value, &jsErr);
if(! jsErr.isEmpty()) return;
2023-04-18 14:14:46 +08:00
if(item->mSplitWidths.isEmpty()) PlayWin::self = PlayWin::newIns(item->mWidth, item->mHeight, dir, prog);
else PlayWin::self = PlayWin::newIns(item->mMaxWidth, item->mHeight * item->mSplitWidths.size(), dir, prog);
2022-08-25 18:37:24 +08:00
break;
}
}
});
hBox->addStretch();
2023-09-19 11:49:20 +08:00
auto fdSearch = new QLineEdit;
fdSearch->setFixedWidth(200);
auto search = new QAction;
2023-04-18 14:14:46 +08:00
search->setIcon(QIcon(":/res/program/bnSearch.png"));
2023-09-19 11:49:20 +08:00
fdSearch->addAction(search, QLineEdit::LeadingPosition);
fdSearch->setClearButtonEnabled(true);
fdSearch->setStyleSheet("border: 2px solid #aaa;");
connect(fdSearch, &QLineEdit::textChanged, this, [this](const QString &text) {
auto cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) {
auto item = mProgTree->item(i);
item->setHidden(! (text.isEmpty() || item->text("name").contains(text) || item->text("resolution").contains(text)));
2022-08-25 18:37:24 +08:00
}
});
2023-09-19 11:49:20 +08:00
hBox->addWidget(fdSearch);
auto table = new LoQTreeWidget;
table->addCol("#", "", 20);
table->addCol("check", "", 36).margin(6);
table->addCol("name", "", 300, QHeaderView::Stretch);
table->addCol("resolution", "", 150, QHeaderView::Stretch);
table->addCol("size", "", 100, QHeaderView::Stretch);
table->addCol("lasttime", "", 180);
table->addCol("usb", "", 80);
table->addCol("send", "", 80);
table->setDefs()->setHeaderAlignC();
table->addFd();
table->minRowHeight = 36;
table->setSelectionMode(QAbstractItemView::NoSelection);
table->setSortingEnabled(true);
connect(table, &LoQTreeWidget::selChanged, this, [=] {
auto en = table->fdCheckAll->checkState()!=Qt::Unchecked;
bnEdit->setEnabled(en);
bnDelete->setEnabled(en);
bnExport->setEnabled(en);
bnSend->setEnabled(en);
});
vBox->addWidget(mProgTree = table);
2022-08-25 18:37:24 +08:00
QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
if(!doc_path.isEmpty()) {
QString app_path = doc_path + "/" + QApplication::applicationName();
2022-10-27 15:07:45 +08:00
mProgsDir = app_path + "/NPrograms";
2023-08-01 11:42:41 +08:00
if(!QFileInfo::exists(mProgsDir)) QDir(app_path).mkdir("NPrograms");
2022-08-25 18:37:24 +08:00
}
//查找根路径下的项目文件夹查找文件夹下的节目pro.json信息包括节目名称大小像素备注等信息
2022-10-27 15:07:45 +08:00
if(!mProgsDir.isEmpty()) {
QDir root_dir(mProgsDir);
2022-08-25 18:37:24 +08:00
QStringList pro_list = root_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach(QString pro_name, pro_list) {
2022-10-27 15:07:45 +08:00
QDir pro_dir(mProgsDir + "/" + pro_name);
2022-08-25 18:37:24 +08:00
if(pro_dir.exists("pro.json")) {
QFile fPro(pro_dir.path() + "/pro.json");
fPro.open(QIODevice::ReadOnly);
QJsonDocument pro = QJsonDocument::fromJson(fPro.readAll());
fPro.close();
2023-05-11 11:47:00 +08:00
m_pwPorgramItemList.append(new ProgItem(mProgsDir, pro.object(), mProgTree));
2022-08-25 18:37:24 +08:00
}
}
}
2023-08-01 11:42:41 +08:00
QSettings settings;
2022-09-30 18:08:39 +08:00
if(settings.value("ProgramListSortOrder").toInt()==0) mProgTree->sortByColumn(settings.value("ProgramListSortColumn").toInt(),Qt::SortOrder::AscendingOrder);
else mProgTree->sortByColumn(settings.value("ProgramListSortColumn").toInt(),Qt::SortOrder::DescendingOrder);
2022-08-25 18:37:24 +08:00
2023-09-19 11:49:20 +08:00
transUi();
2022-08-25 18:37:24 +08:00
}
void ProgPanel::changeEvent(QEvent *event) {
QWidget::changeEvent(event);
if(event->type() == QEvent::LanguageChange) transUi();
}
void ProgPanel::transUi() {
2023-09-19 11:49:20 +08:00
mProgTree->headerItem()->setText("name"**mProgTree, tr("Name"));
mProgTree->headerItem()->setText("resolution"**mProgTree, tr("Resolution"));
mProgTree->headerItem()->setText("size"**mProgTree, tr("File Size"));
mProgTree->headerItem()->setText("lasttime"**mProgTree, tr("Last Modify"));
mProgTree->headerItem()->setText("usb"**mProgTree, tr("USB Update"));
mProgTree->headerItem()->setText("send"**mProgTree, tr("Publish"));
2022-08-25 18:37:24 +08:00
bnNew->setText(tr("New"));
bnEdit->setText(tr("Edit"));
bnDelete->setText(tr("Delete"));
bnImport->setText(tr("Import"));
bnExport->setText(tr("Export"));
bnSend->setText(tr("Send"));
btnPlay->setText(tr("Play")+"/"+tr("Stop"));
}
void ProgPanel::onEditClicked(bool){
2022-09-30 18:08:39 +08:00
int cnt = mProgTree->topLevelItemCount();
2022-08-25 18:37:24 +08:00
for(int i=0; i<cnt; i++) {
2023-09-19 11:49:20 +08:00
if(mProgTree->item(i)->checkState("check") == Qt::Checked) {
2022-09-30 18:08:39 +08:00
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
2023-05-11 11:47:00 +08:00
auto editor = new ProgEditorWin(item, this);
2023-04-28 16:02:14 +08:00
editor->show();
2022-08-25 18:37:24 +08:00
break;
}
}
}
bool ProgPanel::checkIfNameRepeated(const QString &name, QTreeWidgetItem *skip){
2022-09-30 18:08:39 +08:00
int cnt = mProgTree->topLevelItemCount();
2022-08-25 18:37:24 +08:00
for(int i=0; i<cnt; i++) {
2022-09-30 18:08:39 +08:00
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
2022-08-25 18:37:24 +08:00
if(item == skip) continue;
2022-10-27 15:07:45 +08:00
if(name == item->mName) {
2022-08-25 18:37:24 +08:00
QMessageBox::warning(this, tr("Warning"), tr("Program name conflicted"));
return true;
}
}
return false;
}
2023-04-18 14:14:46 +08:00
void ProgPanel::onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, QList<int> &splitWidths, int max)
2022-08-25 18:37:24 +08:00
{
if(checkIfNameRepeated(name)) return;
2023-05-11 11:47:00 +08:00
auto item = new ProgItem(mProgsDir, name, res.width(), res.height(), remarks, splitWidths, max, mProgTree);
2022-08-25 18:37:24 +08:00
item->save();//保存pro.json
2023-10-23 14:58:29 +08:00
if(mProgTree->fdCheckAll->checkState()==Qt::Checked) {
mProgTree->fdCheckAll->blockSignals(true);
mProgTree->fdCheckAll->setCheckState(Qt::PartiallyChecked);
mProgTree->fdCheckAll->blockSignals(false);
}
2023-05-11 11:47:00 +08:00
auto editor = new ProgEditorWin(item, this);
2023-04-28 16:02:14 +08:00
editor->show();
2022-08-25 18:37:24 +08:00
}
void ProgPanel::onDeleteClicked(bool){
auto res = QMessageBox::information(this, tr("Tip Info"), tr("You will delete the selected solution(s),are you sure?"), QMessageBox::Ok, QMessageBox::Cancel);
if(res == QMessageBox::Ok) {
2023-10-23 14:58:29 +08:00
for(int i=0; i<mProgTree->topLevelItemCount(); i++) if(mProgTree->item(i)->checkState("check") == Qt::Checked) {
2023-09-19 11:49:20 +08:00
auto item = (ProgItem*) mProgTree->topLevelItem(i--);
2022-08-25 18:37:24 +08:00
item->del();
delete item;
}
2023-09-19 11:49:20 +08:00
mProgTree->fdCheckAll->blockSignals(true);
mProgTree->fdCheckAll->setCheckState(Qt::Unchecked);
mProgTree->fdCheckAll->blockSignals(false);
emit mProgTree->selChanged();
2022-08-25 18:37:24 +08:00
}
}
2023-04-25 16:30:58 +08:00
ProgPortDlg::ProgPortDlg(QWidget *parent, QString title) : QDialog(parent) {
2023-05-15 16:06:10 +08:00
#ifdef Q_OS_WIN
2023-04-25 16:30:58 +08:00
setWindowFlag(Qt::WindowContextHelpButtonHint, 0);
2023-05-15 16:06:10 +08:00
#endif
2023-04-18 14:14:46 +08:00
resize(600, 400);
2023-04-25 16:30:58 +08:00
setWindowTitle(title);
2023-04-18 14:14:46 +08:00
auto vBox = new VBox(this);
2023-04-25 16:30:58 +08:00
vBox->setContentsMargins(0, 0, 0, 6);
2023-04-18 14:14:46 +08:00
table = new QTableWidget(0, 2);
table->setSelectionMode(QTableWidget::NoSelection);
table->setEditTriggers(QAbstractItemView::NoEditTriggers);
table->setAlternatingRowColors(true);
table->horizontalHeader()->setBackgroundRole(QPalette::Window);
table->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
table->horizontalHeader()->resizeSection(1, 200);
table->setHorizontalHeaderLabels({tr("Solution Name"), tr("Progress")});
vBox->addWidget(table);
2023-04-25 16:30:58 +08:00
auto hBox = new HBox(vBox);
2023-04-18 14:14:46 +08:00
hBox->addStretch();
bnOK = new QPushButton(title);
hBox->addWidget(bnOK);
auto bnDone = new QPushButton(tr("Done"));
2023-05-15 16:06:10 +08:00
connect(bnDone, &QPushButton::clicked, this, &QDialog::accept);
2023-04-18 14:14:46 +08:00
hBox->addWidget(bnDone);
}