#include "checkperiodwidget.h" #include "GlobalVariable.h" #include "checkperiodfunc.h" #include "onedetectplan.h" #include "ui_checkperiodwidget.h" #include "addperioddialog.h" #include "UIStyleManager.h" #include "customcombobox.h" #include #include #include #include #include "checkperiodfunc.h" #include "tipwidget.h" #include "GlobalInfo.h" #include "timewidget.h" #include "SystemConfig.h" CheckPeriodWidget::CheckPeriodWidget(QWidget *parent) : QWidget(parent), ui(new Ui::CheckPeriodWidget) { ui->setupUi(this); m_logger = spdlog::get("ACASetting"); if(m_logger == nullptr) { fmt::print("CheckPeriodWidget: Logger ACASetting not found\n"); return; } /* 下拉框设置阴影 */ ui->comboBox_selectCompareItem->setViewShadowEffect(); /* 获取计划容器的布局指针 */ m_layoutDetectPlans = qobject_cast(ui->scrollArea_detectPlans->layout()); m_layoutNoDetectPlans = qobject_cast(ui->scrollArea_noDetectPlans->layout()); connect(ui->pBtn_addDetectPlan, &QPushButton::clicked, this, &CheckPeriodWidget::do_pBtn_addDetectPlan_clicked); connect(ui->pBtn_addNoDetectPlan, &QPushButton::clicked, this, &CheckPeriodWidget::do_pBtn_addNoDetectPlan_clicked); connect(ui->comboBox_selectCompareItem, QOverload::of(&QComboBox::currentIndexChanged), this, &CheckPeriodWidget::do_comboBox_selectCompareItem_currentIndexChanged); connect(ui->checkBox_applySlient, &QCheckBox::clicked, this, &CheckPeriodWidget::do_checkBox_clicked); connect(ui->checkBox_applyOverload, &QCheckBox::clicked, this, &CheckPeriodWidget::do_checkBox_clicked); connect(ui->checkBox_applyPhase, &QCheckBox::clicked, this, &CheckPeriodWidget::do_checkBox_clicked); connect(ui->checkBox_applyNoise, &QCheckBox::clicked, this, &CheckPeriodWidget::do_checkBox_clicked); connect(ui->pBtn_restore, &QPushButton::clicked, this, &CheckPeriodWidget::do_pBtn_restore_clicked); /* 设置UI */ UIStyle.registerWidget(this); QString qssPath = UIStyle.getQSSPath() + "/onedetectplan.qss"; QFile file(qssPath); if(file.open(QFile::ReadOnly)) { m_qssPlan = file.readAll(); file.close(); } else { SPDLOG_LOGGER_WARN(m_logger, "打开QSS文件失败: {}", qssPath.toStdString()); } /* 初始化列表 */ initListWidget(); } CheckPeriodWidget::~CheckPeriodWidget() { UIStyle.unregisterWidget(this); delete ui; } /* 更新可选的对比项列表 */ void CheckPeriodWidget::updateCompareItemList(const QList& compareItemList) { /* 先获取当前选择的列表项 */ int id = ui->comboBox_selectCompareItem->currentData().value(); /* 屏蔽comboBox信号 */ ui->comboBox_selectCompareItem->blockSignals(true); ui->comboBox_selectCompareItem->clear(); m_pListcurrDetect = nullptr; for(const auto& item : compareItemList) { /* 添加到下拉框 */ ui->comboBox_selectCompareItem->addItem(item.strName, item.nID); } /* 设置当前选择的对比项 */ if(id != 0) { /* 屏蔽comboBox信号 */ ui->comboBox_selectCompareItem->blockSignals(true); for(int i = 0; i < ui->comboBox_selectCompareItem->count(); ++i) { if(ui->comboBox_selectCompareItem->itemData(i).value() == id) { ui->comboBox_selectCompareItem->setCurrentIndex(i); break; } } } else { ui->comboBox_selectCompareItem->setCurrentIndex(0); } /* 恢复comboBox信号 */ ui->comboBox_selectCompareItem->blockSignals(false); /* 手动切换当前的列表 */ do_comboBox_selectCompareItem_currentIndexChanged(ui->comboBox_selectCompareItem->currentIndex()); } /* 保存设置 */ bool CheckPeriodWidget::saveSettings() { /* 更新静音过载反相的设置 */ m_mapNoDetectApply[m_currNoDetectApply.nID] = m_currNoDetectApply; /* 生成按照对比项相关的设置计划 */ QMap mapDetectConfig; updateCompareItemDetectPeriod(mapDetectConfig); /* 和已有的对比,只有有修改的地方,直接删除这个对比项ID所有计划,然后插入 */ const auto& oldMap = SysConfig.getDetectPeriodConfig(); QMap insertMap; QList deleteList; /* 先找出需要插入的 */ for(auto it = mapDetectConfig.cbegin(); it != mapDetectConfig.cend(); ++it) { int id = it.key(); if(oldMap.contains(id)) { /* 如果有修改,就删除原来的 */ if(oldMap[id] == it.value()) { continue; }else { deleteList.append(id); } } /* 无论是没有还是修改了,都需要重新插入 */ insertMap.insert(id, it.value()); } /* 先删除,再插入新数据 */ if(!deleteList.isEmpty()) { if(!m_fromWebAPI->deleteDetectPeriodConfig(deleteList)) { SPDLOG_LOGGER_ERROR(m_logger, "删除对比项检测时段配置失败"); TipWidget::display(TipWidget::OPERATOR_WARN, "删除对比项检测时段配置失败", GInfo.getTopWindow()); return false; } } if(!insertMap.isEmpty()) { if(!m_fromWebAPI->insertDetectPeriodConfig(insertMap)) { SPDLOG_LOGGER_ERROR(m_logger, "插入对比项检测时段配置失败"); TipWidget::display(TipWidget::OPERATOR_WARN, "插入对比项检测时段配置失败", GInfo.getTopWindow()); return false; } } /* 更新系统配置 */ SysConfig.setDetectPeriodConfig(mapDetectConfig); return true; } /* 选择了一个对比项,id是新对比项的id */ void CheckPeriodWidget::do_comboBox_selectCompareItem_currentIndexChanged(int index) { /* 获取当前选择的对比项id */ int id = ui->comboBox_selectCompareItem->itemData(index).value(); if(id == 0) { m_pListcurrDetect = nullptr; SPDLOG_LOGGER_WARN(m_logger, "对比项ID为0,无法获取检测计划列表"); return; } /* 如果已经有了,就不需要重新创建 */ if(m_mapDetectPlanList.contains(id)) { m_pListcurrDetect = m_mapDetectPlanList.value(id); }else { /* 创建一个新的列表 */ m_pListcurrDetect = new QList(); m_mapDetectPlanList.insert(id, m_pListcurrDetect); } if(m_mapNoDetectPlanList.contains(id)) { m_pListcurrNoDetect = m_mapNoDetectPlanList.value(id); } else { /* 创建一个新的列表 */ m_pListcurrNoDetect = new QList(); m_mapNoDetectPlanList.insert(id, m_pListcurrNoDetect); } /* 应用项目需要先保存当前的设置到对应的对比项ID中,然后再切换 */ m_currNoDetectApply.isApplySlient = ui->checkBox_applySlient->isChecked(); m_currNoDetectApply.isApplyOverload = ui->checkBox_applyOverload->isChecked(); m_currNoDetectApply.isApplyPhase = ui->checkBox_applyPhase->isChecked(); m_currNoDetectApply.isApplyNoise = ui->checkBox_applyNoise->isChecked(); /* 这里多次检测,是防止第一次进入这个页面,没有保存好的设置 */ if(m_currNoDetectApply.nID > 0) { if(m_mapNoDetectApply.contains(m_currNoDetectApply.nID)) { m_mapNoDetectApply[m_currNoDetectApply.nID] = m_currNoDetectApply; } else { m_mapNoDetectApply.insert(m_currNoDetectApply.nID, m_currNoDetectApply); } } if(m_mapNoDetectApply.contains(id)) { m_currNoDetectApply = m_mapNoDetectApply.value(id); } else { /* 清空设置 */ m_currNoDetectApply = NoDetectPlanApply_t(); m_currNoDetectApply.nID = id; m_mapNoDetectApply.insert(id, m_currNoDetectApply); } ui->checkBox_applySlient->setChecked(m_currNoDetectApply.isApplySlient); ui->checkBox_applyOverload->setChecked(m_currNoDetectApply.isApplyOverload); ui->checkBox_applyPhase->setChecked(m_currNoDetectApply.isApplyPhase); ui->checkBox_applyNoise->setChecked(m_currNoDetectApply.isApplyNoise); /* 清空当前的布局 */ removeAllDetectPlanWidgets(); removeAllNoDetectPlanWidgets(); addDetectPlanToLayout(); addNoDetectPlanToLayout(); } /* 添加一个检测计划 */ void CheckPeriodWidget::do_pBtn_addDetectPlan_clicked() { /* 检查当前有没有对比项选择 */ int id = ui->comboBox_selectCompareItem->currentData().value(); if(id <= 0) { TipWidget::display(TipWidget::OPERATOR_WARN, "请先选择一个对比项", GInfo.getTopWindow()); SPDLOG_LOGGER_WARN(m_logger, "没有选择对比项,无法添加检测计划"); return; } AddPeriodDialog dlg(PERIOD_WEEK); /* 更新计划列表 */ updateDetectPlanList(1); /* 设置计划列表 */ dlg.setPlanList(m_currentPlanList); dlg.exec(); if(!dlg.isOK()) { return; } OnePlan_t plan = dlg.getPlan(); addDetectPlan(plan); } /* 添加一个不检测计划 */ void CheckPeriodWidget::do_pBtn_addNoDetectPlan_clicked() { /* 检查当前有没有对比项选择 */ int id = ui->comboBox_selectCompareItem->currentData().value(); if(id <= 0) { TipWidget::display(TipWidget::OPERATOR_WARN, "请先选择一个对比项", GInfo.getTopWindow()); SPDLOG_LOGGER_WARN(m_logger, "没有选择对比项,无法添加检测计划"); return; } AddPeriodDialog dlg(PERIOD_DATE); dlg.exec(); if(!dlg.isOK()) { return; } OnePlan_t plan = dlg.getPlan(); addNoDetectPlan(plan); } /* 删除一个检测计划 */ void CheckPeriodWidget::do_pBtn_deleteDetectPlan_clicked() { /* 获取信号发送者 */ OneDetectPlan *pDetect = qobject_cast(sender()); if(pDetect == nullptr) { return; } m_layoutDetectPlans->removeWidget(pDetect); m_pListcurrDetect->removeAll(pDetect); delete pDetect; /* 重新排序 */ // sortDetectPlanList(); } /* 删除一个不检测计划 */ void CheckPeriodWidget::do_pBtn_deleteNoDetectPlan_clicked() { /* 获取信号发送者 */ OneDetectPlan *pDetect = qobject_cast(sender()); if(pDetect == nullptr) { return; } m_layoutNoDetectPlans->removeWidget(pDetect); m_pListcurrNoDetect->removeAll(pDetect); delete pDetect; /* 重新排序 */ // sortNoDetectPlanList(); } /* 修改了日期或周几,检测是否冲突 */ void CheckPeriodWidget::do_detectPlanModifiedWeek(OnePlan_t formerPlan, OnePlan_t newPlan) { OneDetectPlan *pDetect = qobject_cast(sender()); /* 更新计划 */ updateDetectPlanList(1); /* 检测是否冲突 */ if(isWeekPlanDuplicate(m_currentPlanList, newPlan, newPlan)) { /* 弹出提示 */ TipWidget::display(TipWidget::OPERATOR_WARN, "与已有计划冲突,请重新修改", GInfo.getTopWindow()); SPDLOG_LOGGER_WARN(m_logger, "检测计划冲突"); /* 恢复原计划 */ pDetect->setPlan(formerPlan); return; } /* 重新排序 */ sortDetectPlanList(); } /* 点击了检测计划的时间按钮,在这里修改时间 */ void CheckPeriodWidget::do_detectPlanModifiedTime(QPoint pBtnSize, bool isStartTime) { /* 获取信号发送者 */ auto one = qobject_cast(sender()); OnePlan_t plan = one->getPlan(); /* 创建时间选择控件 */ std::shared_ptr tw = std::make_shared(this, TimeWidget::ShowType::Dialog); /* 设置样式表 */ tw->setStyleSheet(m_qssPlan); /* 设置图标 */ tw->setIcon(":/icon/time.png"); tw->setIconShow(true); tw->setIconSize(16, 16); /* 重新设置大小 */ tw->setEditLine(112, 32); /* 设置选择框大小 */ tw->setTimeAreaWidth(140); /* 移动位置,覆盖显示时间的按钮,获取的坐标是相对于Dialog的位置 */ auto pos = this->mapFromGlobal(pBtnSize); // pos.setX(pos.x() - 1); /* 去掉阴影的宽度 */ // pos.setY(pos.y()); /* 去掉阴影的高度 */ tw->move(pos); // SPDLOG_LOGGER_DEBUG(m_logger, "移动前位置: {}, {}", pBtnSize.x(), pBtnSize.y()); // SPDLOG_LOGGER_DEBUG(m_logger, "移动后位置: {}, {}", pos.x(), pos.y()); /* 设置默认的时间 */ if(isStartTime) { tw->setTime(plan.timeStart); } else { tw->setTime(plan.timeEnd); } tw->execShow(); auto time = tw->getTime(); /* 判断时间有没有修改 */ if(isStartTime) { if(time == plan.timeStart) { return; // 没有修改 } } else { if(time == plan.timeEnd) { return; // 没有修改 } } SPDLOG_LOGGER_DEBUG(m_logger, "修改时间: {}, {}", time.toString("hh:mm:ss").toStdString(), isStartTime ? "开始时间" : "结束时间"); OnePlan_t newPlan = plan; if(isStartTime) { newPlan.timeStart = time; } else { newPlan.timeEnd = time; } /* 判断时间是否重复 */ updateDetectPlanList(1); if(isWeekPlanDuplicate(m_currentPlanList, newPlan, plan)) { /* 设置时间报警 */ TipWidget::display(TipWidget::OPERATOR_WARN, "与已有计划冲突,请重新修改", GInfo.getTopWindow()); SPDLOG_LOGGER_WARN(m_logger, "检测计划冲突"); return; } /* 设置时间 */ one->setPlan(newPlan); /* 重新排序 */ sortDetectPlanList(); } /* 修改了静音、反相、过载相关的设置 */ void CheckPeriodWidget::do_checkBox_clicked() { m_currNoDetectApply.isApplySlient = ui->checkBox_applySlient->isChecked(); m_currNoDetectApply.isApplyOverload = ui->checkBox_applyOverload->isChecked(); m_currNoDetectApply.isApplyPhase = ui->checkBox_applyPhase->isChecked(); m_currNoDetectApply.isApplyNoise = ui->checkBox_applyNoise->isChecked(); } /* 恢复配置项 */ void CheckPeriodWidget::do_pBtn_restore_clicked() { initListWidget(); } /* 初始化QListWidget */ void CheckPeriodWidget::initListWidget() { /* 获取读取到的检测计划 */ const auto& mapDetectConfig = SysConfig.getDetectPeriodConfig(); /* 将计划转换成列表组件 */ for(auto it = mapDetectConfig.cbegin(); it != mapDetectConfig.cend(); ++it) { int id = it.key(); const DetectPeriodConfig_t& config = it.value(); /* 如果已经有了,就不需要重新创建 */ if(m_mapDetectPlanList.contains(id)) { m_pListcurrDetect = m_mapDetectPlanList.value(id); }else { /* 创建一个新的列表 */ m_pListcurrDetect = new QList(); m_mapDetectPlanList.insert(id, m_pListcurrDetect); } if(m_mapNoDetectPlanList.contains(id)) { m_pListcurrNoDetect = m_mapNoDetectPlanList.value(id); } else { /* 创建一个新的列表 */ m_pListcurrNoDetect = new QList(); m_mapNoDetectPlanList.insert(id, m_pListcurrNoDetect); } /* 添加检测计划 */ for(const auto& plan : config.listDetect) { addDetectPlan(plan); } /* 添加非检测计划 */ for(const auto& plan : config.listNoDetect) { addNoDetectPlan(plan); } /* 设置应用配置 */ NoDetectPlanApply_t apply; apply.nID = id; apply.isApplySlient = config.isApplySlient; apply.isApplyOverload = config.isApplyOverload; apply.isApplyPhase = config.isApplyPhase; apply.isApplyNoise = config.isApplyNoise; m_mapNoDetectApply[id] = apply; } } /* 添加一个检测计划 */ void CheckPeriodWidget::addDetectPlan(const OnePlan_t& plan) { /* 传入的日期类型,不是特殊日就可以 */ OneDetectPlan *detectPlan = new OneDetectPlan(eWeekType::Week_Monday, this); /* 删除日期选择框 */ detectPlan->setQSS(m_qssPlan); detectPlan->setPlan(plan); connect(detectPlan, &OneDetectPlan::signal_oneDetectPlanCloseClicked, this, &CheckPeriodWidget::do_pBtn_deleteDetectPlan_clicked); connect(detectPlan, &OneDetectPlan::signal_planModifiedWeek, this, &CheckPeriodWidget::do_detectPlanModifiedWeek); connect(detectPlan, &OneDetectPlan::signal_timeButtonClicked, this, &CheckPeriodWidget::do_detectPlanModifiedTime); /* 将数据插入到列表中,在排序的时候会将新增加的插入到里面 */ m_pListcurrDetect->append(detectPlan); /* 排序 */ sortDetectPlanList(); } /* 添加一个非检测计划 */ void CheckPeriodWidget::addNoDetectPlan(const OnePlan_t& plan) { /* 传入特殊日的日期类型 */ OneDetectPlan *detectPlan = new OneDetectPlan(eWeekType::Week_Special, this); detectPlan->setQSS(m_qssPlan); detectPlan->setPlan(plan); connect(detectPlan, &OneDetectPlan::signal_oneDetectPlanCloseClicked, this, &CheckPeriodWidget::do_pBtn_deleteNoDetectPlan_clicked); m_pListcurrNoDetect->append(detectPlan); /* 排序并显示 */ sortNoDetectPlanList(); } /* 重新排序检测计划 */ void CheckPeriodWidget::sortDetectPlanList() { /* 清空列表 */ removeAllDetectPlanWidgets(); /* 排序 */ std::sort(m_pListcurrDetect->begin(), m_pListcurrDetect->end(), [](OneDetectPlan *a, OneDetectPlan *b) { const OnePlan_t &planA = a->getPlan(); const OnePlan_t &planB = b->getPlan(); /* 按时间从小到大升序 */ return weekTimeIsGerater(planB.weekType, planB.timeStart, planA.weekType, planA.timeStart); }); /* 重新插入 */ addDetectPlanToLayout(); update(); } /* 排序非检测日期列表 */ void CheckPeriodWidget::sortNoDetectPlanList() { /* 清空列表 */ removeAllNoDetectPlanWidgets(); /* 排序 */ std::sort(m_pListcurrDetect->begin(), m_pListcurrDetect->end(), [](OneDetectPlan *a, OneDetectPlan *b) { const OnePlan_t &planA = a->getPlan(); const OnePlan_t &planB = b->getPlan(); /* 按时间从小到大升序 */ return dateTimeIsGerater(planB.date, planB.timeStart, planA.date, planA.timeStart); }); /* 重新插入 */ addNoDetectPlanToLayout(); update(); } /* 获取计划列表 */ QList CheckPeriodWidget::updateDetectPlanList(int id) { m_currentPlanList.clear(); for(auto& pDetect : *m_pListcurrDetect) { OnePlan_t plan = pDetect->getPlan(); m_currentPlanList.append(plan); } return m_currentPlanList; } /* 清空当前检测计划布局中的控件 */ void CheckPeriodWidget::removeAllDetectPlanWidgets() { /* 清空布局中的所有控件,只剩一个弹簧 */ while (m_layoutDetectPlans->count() > 1) { QWidget *widget = m_layoutDetectPlans->itemAt(0)->widget(); if(widget) { m_layoutDetectPlans->removeWidget(widget); widget->hide(); } } } /* 清空当前非检测计划布局中的控件 */ void CheckPeriodWidget::removeAllNoDetectPlanWidgets() { /* 清空所有的非检测计划日期 */ while( m_layoutNoDetectPlans->count() > 1) { QWidget *widget = m_layoutNoDetectPlans->itemAt(0)->widget(); if(widget) { m_layoutNoDetectPlans->removeWidget(widget); widget->hide(); } } } /* 从当前列表中添加控件到布局 */ void CheckPeriodWidget::addDetectPlanToLayout() { for(auto& pDetect : *m_pListcurrDetect) { pDetect->show(); /* 添加到布局中 */ m_layoutDetectPlans->insertWidget(m_layoutDetectPlans->count() - 1, pDetect); } } /* 从当前列表中添加非检测计划控件到布局 */ void CheckPeriodWidget::addNoDetectPlanToLayout() { for(auto& pDetect : *m_pListcurrNoDetect) { pDetect->show(); /* 添加到布局中 */ m_layoutNoDetectPlans->insertWidget(m_layoutNoDetectPlans->count() - 1, pDetect); } } /* 更新所有对比项的计划周期 */ void CheckPeriodWidget::updateCompareItemDetectPeriod(QMap& mapDetectConfig) { /* 先更新检测计划 */ for(auto it = m_mapDetectPlanList.cbegin(); it != m_mapDetectPlanList.cend(); ++it) { int id = it.key(); QList* pList = it.value(); DetectPeriodConfig_t config; config.nID = id; /* 更新检测计划 */ for(auto& pDetect : *pList) { OnePlan_t plan = pDetect->getPlan(); config.listDetect.append(plan); } auto apply = m_mapNoDetectApply.find(id); if(apply != m_mapNoDetectApply.cend()) { config.isApplySlient = apply->isApplySlient; config.isApplyOverload = apply->isApplyOverload; config.isApplyPhase = apply->isApplyPhase; config.isApplyNoise = apply->isApplyNoise; } else { config.isApplySlient = false; config.isApplyOverload = false; config.isApplyPhase = false; config.isApplyNoise = false; } mapDetectConfig.insert(id, config); } /* 更新非检测计划 */ for(auto it = m_mapNoDetectPlanList.cbegin(); it != m_mapNoDetectPlanList.cend(); ++it) { int id = it.key(); QList* pList = it.value(); /* 查找的时候,如果没有,会自动插入一个key为id的值 */ DetectPeriodConfig_t& config = mapDetectConfig[id]; config.nID = id; /* 更新非检测计划 */ for(auto& pDetect : *pList) { OnePlan_t plan = pDetect->getPlan(); config.listNoDetect.append(plan); } /* 这里再查找一遍应用信息是因为防止没有检测计划,只有非检测计划 */ auto apply = m_mapNoDetectApply.find(id); if(apply != m_mapNoDetectApply.cend()) { config.isApplySlient = apply->isApplySlient; config.isApplyOverload = apply->isApplyOverload; config.isApplyPhase = apply->isApplyPhase; config.isApplyNoise = apply->isApplyNoise; } else { config.isApplySlient = false; config.isApplyOverload = false; config.isApplyPhase = false; config.isApplyNoise = false; } } }