qt/LedOK/progpanel.cpp
2023-08-07 09:04:53 +08:00

448 lines
20 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "progpanel.h"
#include "globaldefine.h"
#include "gutil/qgui.h"
#include "cfg.h"
#include "player/playwin.h"
#include "program/progcreatedlg.h"
#include "program/progeditorwin.h"
#include "program/copydirthread.h"
#include <QApplication>
#include <QHeaderView>
#include <QMessageBox>
#include <QStandardPaths>
#include <QProgressBar>
#include <QFileDialog>
ProgPanel::ProgPanel(QWidget *parent) : QWidget(parent) {
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);
connect(bnNew, &QPushButton::clicked, this, [this] {
ProgCreateDlg dlg("", 512, 256, "", "", this);
if(dlg.exec() != QDialog::Accepted) return;
if(checkIfNameRepeated(dlg.fdName->text())) return;
auto splitWidths = dlg.fdSplitWidths->text().split(" ", Qt::SkipEmptyParts);
QList<int> widths; int max = 0, ttl = 0;
auto width = dlg.fdWidth->value();
foreach(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;
}
auto item = new ProgItem(mProgsDir, dlg.fdName->text(), width, dlg.fdHeight->value(), dlg.fdRemark->toPlainText(), widths, max, mProgTree);
item->save();//保存pro.json
mProgTree->adjustCheckState();
auto editor = new ProgEditorWin(item, this);
editor->show();
});
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"));
bnImport->setFixedSize(88, 38);
bnImport->setProperty("ssType", "progManageTool");
hBox->addWidget(bnImport);
connect(bnImport, &QPushButton::clicked, this, [this] {
auto dir = QFileDialog::getExistingDirectory(this, tr("Choose Directory"), "/home", QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
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)) {
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);
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();
m_pwPorgramItemList.append(new ProgItem(mProgsDir, QJsonDocument::fromJson(data).object(), mProgTree));
}
});
bnExport = new QPushButton(tr("Export"));
bnExport->setFixedSize(QSize(88, 38));
bnExport->setEnabled(false);
bnExport->setProperty("ssType", "progManageTool");
hBox->addWidget(bnExport);
connect(bnExport, &QPushButton::clicked, this, [=] {
int cnt = mProgTree->topLevelItemCount();
QStringList progNames;
for(int i=0; i<cnt; i++) if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) progNames.append(static_cast<ProgItem*>(mProgTree->topLevelItem(i))->mName);
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();
});
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);
connect(btnPlay, &QPushButton::clicked, this, [this] {
if(PlayWin::self) PlayWin::self->close();
else {
int cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
QString dir = mProgsDir+"/"+item->mName+"_tmp";
QFile file(dir+"/program");
if(! file.open(QIODevice::ReadOnly | QIODevice::Text)) return;
QString value = file.readAll();
file.close();
QJsonParseError jsErr;
QJsonObject prog = QJsonDocument::fromJson(value.toUtf8(), &jsErr).object();
if(jsErr.error) return;
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);
break;
}
}
});
hBox->addStretch();
auto txtSearch = new QLineEdit(this);
txtSearch->setFixedSize(QSize(240, 36));
QAction *search = new QAction(txtSearch);
search->setIcon(QIcon(":/res/program/bnSearch.png"));
txtSearch->addAction(search, QLineEdit::LeadingPosition);
txtSearch->setClearButtonEnabled(true);
txtSearch->setStyleSheet("border: 2px solid #aaaaaa;");
hBox->addWidget(txtSearch);
connect(txtSearch,SIGNAL(textChanged(const QString &)),this,SLOT(FilterProgram(const QString &)));
mProgTree = new LoQTreeWidget();
mProgTree->setIndentation(6);
mProgTree->setSortingEnabled(true);
m_headerItem = new QTreeWidgetItem();
for(int i=1; i<ENUM_PROGRAMLISTHEADERITEM_END; i++) m_headerItem->setTextAlignment(i, Qt::AlignCenter);
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_CHECK, Qt::DisplayRole, "");
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_NAME, Qt::DisplayRole, tr("Name"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, Qt::DisplayRole, tr("Resolution"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, Qt::DisplayRole, tr("File Size"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, Qt::DisplayRole, tr("Last Modify"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, Qt::DisplayRole, tr("USB Update"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SEND, Qt::DisplayRole, tr("Publish"));
mProgTree->setHeaderItem(m_headerItem);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_CHECK, QHeaderView::Fixed);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_NAME, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_SIZE, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, QHeaderView::Stretch);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, QHeaderView::Fixed);
mProgTree->header()->setSectionResizeMode(ENUM_PROGRAMLISTHEADERITEM_SEND, QHeaderView::Fixed);
mProgTree->header()->setStretchLastSection(false);
mProgTree->setColumnWidth(ENUM_PROGRAMLISTHEADERITEM_CHECK, 66);
mProgTree->setColumnWidth(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, 100);
mProgTree->setColumnWidth(ENUM_PROGRAMLISTHEADERITEM_SEND, 72);
vBox->addWidget(mProgTree);
connect(mProgTree, &LoQTreeWidget::sigCheckStateChanged, this, [this](int f){
switch(f) {
case LoQTreeWidget::CheckNone:
bnEdit->setEnabled(false);
bnDelete->setEnabled(false);
bnExport->setEnabled(false);
bnSend->setEnabled(false);
break;
case LoQTreeWidget::CheckOne:
bnEdit ->setEnabled(true);
bnDelete->setEnabled(true);
bnExport->setEnabled(true);
bnSend ->setEnabled(true);
break;
case LoQTreeWidget::CheckMulti:
bnEdit ->setEnabled(false);
bnDelete->setEnabled(true);
bnExport->setEnabled(true);
bnSend ->setEnabled(true);
break;
default: break;
}
});
QString doc_path = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
if(!doc_path.isEmpty()) {
QString app_path = doc_path + "/" + QApplication::applicationName();
mProgsDir = app_path + "/NPrograms";
if(!QFileInfo::exists(mProgsDir)) QDir(app_path).mkdir("NPrograms");
}
//connect(search, SIGNAL(triggered(bool)), this, SLOT(FilterProgram()));
//查找根路径下的项目文件夹查找文件夹下的节目pro.json信息包括节目名称大小像素备注等信息
if(!mProgsDir.isEmpty()) {
QDir root_dir(mProgsDir);
QStringList pro_list = root_dir.entryList(QDir::Dirs | QDir::NoDotAndDotDot | QDir::NoSymLinks);
foreach(QString pro_name, pro_list) {
QDir pro_dir(mProgsDir + "/" + pro_name);
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();
m_pwPorgramItemList.append(new ProgItem(mProgsDir, pro.object(), mProgTree));
}
}
}
QSettings settings;
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);
// ui->wProgramList->setSortingEnabled( false ); //不使能QT的自动排序
// ui->wProgramList->header()->setSortIndicatorShown( true ); // 设置三角标识符可见
// ui->wProgramList->header()->setSectionsClickable( true ); // 设置标题栏单击响应使能
// connect( ui->wProgramList->header(), SIGNAL( sectionClicked(int) ), this, SLOT( OnClickColumn(int) ) );
}
void ProgPanel::OnClickColumn(int iColumn) {
if(iColumn!=ENUM_PROGRAMLISTHEADERITEM_CHECK && iColumn!=ENUM_PROGRAMLISTHEADERITEM_SEND) mProgTree->sortByColumn(iColumn, mProgTree->header()->sortIndicatorOrder());
}
void ProgPanel::changeEvent(QEvent *event) {
QWidget::changeEvent(event);
if(event->type() == QEvent::LanguageChange) transUi();
}
void ProgPanel::transUi() {
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_CHECK, 0, "");
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_NAME, 0, tr("Name"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_RESOLUTION, 0, tr("Resolution"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SIZE, 0, tr("File Size"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_LASTTIME, 0, tr("Last Modify"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_USB_EXPORT, 0, tr("USB Update"));
m_headerItem->setData(ENUM_PROGRAMLISTHEADERITEM_SEND, 0, tr("Publish"));
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){
int cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) {
if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
auto editor = new ProgEditorWin(item, this);
editor->show();
break;
}
}
}
bool ProgPanel::checkIfNameRepeated(const QString &name, QTreeWidgetItem *skip){
int cnt = mProgTree->topLevelItemCount();
for(int i=0; i<cnt; i++) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
if(item == skip) continue;
if(name == item->mName) {
QMessageBox::warning(this, tr("Warning"), tr("Program name conflicted"));
return true;
}
}
return false;
}
void ProgPanel::onCreateNewProgramOnOpenEditProgramWidget(QString name, QSize res, QString remarks, QList<int> &splitWidths, int max)
{
if(checkIfNameRepeated(name)) return;
auto item = new ProgItem(mProgsDir, name, res.width(), res.height(), remarks, splitWidths, max, mProgTree);
item->save();//保存pro.json
mProgTree->adjustCheckState();
auto editor = new ProgEditorWin(item, this);
editor->show();
}
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) {
int cnt = mProgTree->topLevelItemCount();
QList<ProgItem*> list;
for(int i=0; i<cnt; i++) {
if(mProgTree->topLevelItem(i)->checkState(0) == Qt::Checked) {
auto item = static_cast<ProgItem*>(mProgTree->topLevelItem(i));
list.push_back(item);
}
}
while(!list.isEmpty()) {
auto item = list.takeFirst();
item->del();
delete item;
}
mProgTree->adjustCheckState();
}
}
void ProgPanel::FilterProgram(const QString &strtemp){
if (strtemp.isEmpty()) //显示全部
{
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i)
{
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),false);
}
}
else
{
QList<QTreeWidgetItem*> resultList = mProgTree->findItems(strtemp, Qt::MatchContains,ENUM_PROGRAMLISTHEADERITEM_NAME); //搜索结果
if (resultList.size() > 0)
{
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i)
{
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
if (resultList.contains(topItem))
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),false); //显示匹配的结果
else
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果
}
}
else {
QList<QTreeWidgetItem*> resultList1 = mProgTree->findItems(strtemp, Qt::MatchContains,ENUM_PROGRAMLISTHEADERITEM_RESOLUTION); //搜索结果
if (resultList1.size() > 0){
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i){
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
if (resultList1.contains(topItem)) mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),false); //显示匹配的结果
else mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果
}
}
else {
for (int i = 0; i< mProgTree->topLevelItemCount(); ++i){
QTreeWidgetItem* topItem = mProgTree->topLevelItem(i);
mProgTree->setRowHidden(i,mProgTree->indexFromItem(topItem->parent()),true); //隐藏不匹配的结果
}
}
}
}
}
ProgPortDlg::ProgPortDlg(QWidget *parent, QString title) : QDialog(parent) {
#ifdef Q_OS_WIN
setWindowFlag(Qt::WindowContextHelpButtonHint, 0);
#endif
resize(600, 400);
setWindowTitle(title);
auto vBox = new VBox(this);
vBox->setContentsMargins(0, 0, 0, 6);
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);
auto hBox = new HBox(vBox);
hBox->addStretch();
bnOK = new QPushButton(title);
hBox->addWidget(bnOK);
auto bnDone = new QPushButton(tr("Done"));
connect(bnDone, &QPushButton::clicked, this, &QDialog::accept);
hBox->addWidget(bnDone);
}