#include "GreyClusteringConfigWidget.h" #include "GreyClusteringItemDelegate.h" #include "MultiLevelHeaderView.h" #include "ui_GreyClusteringConfigWidget.h" #include "dbService/GradeInfoService.h" #include "dbService/EffectIndexInfoService.h" #include "CMind.h" #include #include #include GreyClusteringConfigWidget::GreyClusteringConfigWidget(CMind *mind, int grayNumber, QWidget *parent) : QWidget(parent), ui(new Ui::GreyClusteringConfigWidget), m_mind(mind), m_grayNumber(grayNumber) { ui->setupUi(this); ui->grayConfigTableView->setAlternatingRowColors(false); ui->grayConfigTableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); ui->grayConfigTableView->horizontalHeader()->setStyleSheet( "QHeaderView::section{background:rgb(244,244,244);color: black;}"); ui->grayConfigTableView->verticalHeader()->setStyleSheet( "QHeaderView::section{background:rgb(244,244,244);color: black;}"); ui->grayConfigTableView->verticalHeader()->setDefaultAlignment(Qt::AlignCenter); ui->grayConfigTableView->setSelectionMode(QAbstractItemView::SingleSelection); // ui->grayConfigTableView->verticalHeader()->setDefaultSectionSize(20); ui->grayConfigTableView->horizontalHeader()->hide(); m_model = new QStandardItemModel(); ui->grayConfigTableView->setModel(m_model); ui->stackedWidget->setCurrentIndex(0); ui->grayNumber->setText(QString::number(grayNumber)); initFormLayout(); initClusteringItems(); refreshTableView(); resize(1200, 800); // ui->grayConfigTableView->setEditTriggers(QAbstractItemView::CurrentChanged); //单击触发 } GreyClusteringConfigWidget::~GreyClusteringConfigWidget() { delete ui; } void GreyClusteringConfigWidget::initFormLayout() { QList gradeInfoList; QMap grayLevelMaps; int projectId = m_mind->root().projectId; if (!GradeInfoService().QueryGradeByProjectIdAndType(&gradeInfoList, projectId, 1)) { QMessageBox::warning(this, "警告", "数据库访问失败"); } else { if (gradeInfoList.size() == 0) { for (int lvl = 0; lvl < m_grayNumber; ++lvl) { grayLevelMaps.insert(QString("级别 %1:").arg(lvl + 1), QString("E%1").arg(lvl + 1)); GradeInfo ginfo; ginfo.projectId = projectId; ginfo.gradeName = QString("级别 %1").arg(lvl + 1); ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1); ginfo.type = 1; if (!GradeInfoService().AddGradeInfo(ginfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); } } } else { for (const auto &gi : gradeInfoList) { grayLevelMaps.insert(gi->gradeName, gi->gradeValue); if (grayLevelMaps.size() >= m_grayNumber) { break; } } // 缺少再补 for (int lvl = grayLevelMaps.size(); lvl < m_grayNumber; ++lvl) { grayLevelMaps.insert(QString("级别 %1:").arg(lvl + 1), QString("E%1").arg(lvl + 1)); GradeInfo ginfo; ginfo.projectId = projectId; ginfo.gradeName = QString("级别 %1").arg(lvl + 1); ginfo.gradeValue = QString("灰类%1级").arg(lvl + 1); ginfo.type = 1; if (!GradeInfoService().AddGradeInfo(ginfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); } } m_grayNames = grayLevelMaps.values(); ui->stackedWidget->setCurrentIndex(1); } } qDeleteAll(gradeInfoList); QMapIterator iter(grayLevelMaps); while (iter.hasNext()) { iter.next(); auto le = new QLineEdit; le->setPlaceholderText("请输入类别"); le->setText(iter.value()); le->setMinimumHeight(28); le->setMinimumWidth(200); ui->grayFormLayout->addRow(iter.key() + ":", le); } // qDebug() << ui->grayFormLayout->rowCount(); connect(ui->graySaveBtn, &QToolButton::clicked, this, &GreyClusteringConfigWidget::onConfirmClick); connect(ui->editGrayBtn, &QToolButton::clicked, [=]() { ui->stackedWidget->setCurrentIndex(0); }); } void GreyClusteringConfigWidget::initClusteringItems() { // 脑图层级 < 2 时无效 if (m_mind->levels() < 2) { return; } m_greyClusterings.clear(); // 使用倒数第二层节点及其子节点 int row = 0; for (CNodeData n : m_mind->nodesInLevel(m_mind->levels() - 1)) { GreyClusteringItem parentItem = { n.name, row, 0, 1, 1, nullptr }; QList subNodes = m_mind->subNodes(n); parentItem.colSpan = subNodes.size() == 0 ? 2 : 1; // 没有子节点,占两列,否则占一列 parentItem.rowSpan = subNodes.size() == 0 ? 1 : subNodes.size(); // 没有子节点,占一行,否则占子节点数目行 if (subNodes.size() == 0) { // 没有子节点,需要录入值 GreyClusteringValue *sg = new GreyClusteringValue; sg->units = n.dimension; sg->weiget = 0; for (const auto &gname : m_grayNames) { sg->greyRanges << GreyRange { gname, true, 0, true, 0 }; } sg->leftExtension = 0; sg->rightExtension = 0; sg->oldValue = 0; sg->newValue = 0; parentItem.value.reset(sg); } m_greyClusterings.append(parentItem); int subRow = row; // 子节点 for (const CNodeData &sub : subNodes) { // 因为已有父节点,所以在第2列 GreyClusteringItem childItem = { sub.name, subRow, 1, 1, 1, nullptr }; GreyClusteringValue *sg = new GreyClusteringValue; sg->units = sub.dimension; sg->weiget = 0; for (const auto &gname : m_grayNames) { sg->greyRanges << GreyRange { gname, true, 0, true, 0 }; } sg->leftExtension = 0; sg->rightExtension = 0; sg->oldValue = 0; sg->newValue = 0; childItem.value.reset(sg); m_greyClusterings.append(childItem); subRow++; } row += parentItem.rowSpan; } m_rowCount = row; // 数据库对比更新 QList effectIndexInfoList; int projectid = m_mind->root().projectId; if (!EffectIndexInfoService().QueryEffectIndexInfoByProjectId(&effectIndexInfoList, projectid)) { QMessageBox::warning(this, "警告", "数据库访问失败"); return; } if (effectIndexInfoList.size() == 0) { for (const auto &item : m_greyClusterings) { if (item.value.isNull()) { continue; } EffectIndexInfo effInfo; effInfo.projectId = projectid; effInfo.effectIndexName = item.indexName; QString effectIndexValue; for (const auto &range : item.value->greyRanges) { effectIndexValue += ","; effectIndexValue += range.leftClose ? "[" : "("; effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue); effectIndexValue += range.rightClose ? "]" : ")"; } effInfo.effectIndexValue = effectIndexValue.mid(1); effInfo.effectIndexUnit = item.value->units; effInfo.extendLeft = item.value->leftExtension; effInfo.extendRight = item.value->rightExtension; if (!EffectIndexInfoService().AddEffectIndexInfo(effInfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); break; } } } else { for (auto &item : m_greyClusterings) { if (item.value.isNull()) { continue; } for (const auto &effInfo : effectIndexInfoList) { if (effInfo->effectIndexName == item.indexName) { if (effInfo->effectIndexUnit.length() > 0) { // item.value->units = effInfo->effectIndexUnit; } item.value->leftExtension = effInfo->extendLeft.toDouble(); item.value->rightExtension = effInfo->extendRight.toDouble(); //[0:0],[0:0],[0:0] QStringList valueList; if (effInfo->effectIndexValue.length() > 0) { valueList = effInfo->effectIndexValue.split(","); } int align = qMin(valueList.size(), item.value->greyRanges.size()); for (int str = 0; str < align; str++) { //[0:0] QStringList lr = valueList.at(str).mid(1, valueList.at(str).size() - 2).split(":"); if (valueList.at(str).left(1) == "[") { item.value->greyRanges[str].leftClose = true; } else { item.value->greyRanges[str].leftClose = false; } item.value->greyRanges[str].leftValue = lr.at(0).toDouble(); item.value->greyRanges[str].rightValue = lr.at(1).toDouble(); if (valueList.at(str).right(1) == "]") { item.value->greyRanges[str].rightClose = true; } else { item.value->greyRanges[str].rightClose = false; } } } } } } qDeleteAll(effectIndexInfoList); connect(ui->configSaveBtn, &QToolButton::clicked, this, &GreyClusteringConfigWidget::onConfigSaveBtnClick); } /** #if 0 // 竖直表头 auto vHeader = new MultiLevelHeaderView(Qt::Vertical, 9, 3, t); vHeader->setColumnWidth(0, 40); vHeader->setColumnWidth(1, 40); vHeader->setColumnWidth(2, 80); vHeader->setCellSpan(0, 0, 9, 1); vHeader->setCellSpan(0, 1, 1, 2); vHeader->setCellSpan(1, 1, 3, 1); vHeader->setCellSpan(1, 2, 1, 1); vHeader->setCellSpan(2, 2, 1, 1); vHeader->setCellSpan(3, 2, 1, 1); vHeader->setCellSpan(4, 1, 1, 2); vHeader->setCellSpan(5, 1, 1, 2); vHeader->setCellSpan(6, 1, 1, 2); vHeader->setCellSpan(7, 1, 2, 1); vHeader->setCellSpan(7, 2, 1, 1); vHeader->setCellSpan(8, 2, 1, 1); vHeader->setCellText(0, 0, "火力"); vHeader->setCellText(0, 1, "火炮口径"); vHeader->setCellText(1, 1, "初速"); vHeader->setCellText(1, 2, "穿甲弹"); vHeader->setCellText(2, 2, "破甲弹"); vHeader->setCellText(3, 2, "榴弹"); vHeader->setCellText(4, 1, "首发命中率"); vHeader->setCellText(5, 1, "直射距离"); vHeader->setCellText(6, 1, "弹药基数"); vHeader->setCellText(7, 1, "时间"); vHeader->setCellText(7, 2, "静对静"); vHeader->setCellText(8, 2, "静对动"); t->setVerticalHeader(vHeader); #endif */ struct IndexItem { QString name; int row; int col; int rowSpan; int colSpan; }; void GreyClusteringConfigWidget::refreshTableView() { QTableView *t = ui->grayConfigTableView; m_model->clear(); // 设置表头 { auto hHeader = new MultiLevelHeaderView(Qt::Horizontal, 2, nodeDepth + 3 + m_grayNames.size(), t); hHeader->setSectionResizeMode(QHeaderView::Stretch); hHeader->setCellSpan(0, 0, 2, nodeDepth); // 指标占位 for (int n = 0; n < 1 + m_grayNames.size(); ++n) { // 单位+灰度级占位 hHeader->setCellSpan(0, nodeDepth + n, 2, 1); } hHeader->setCellSpan(0, nodeDepth + 1 + m_grayNames.size(), 1, 2); // 延拓值占位 hHeader->setCellSpan(1, nodeDepth + 1 + m_grayNames.size(), 1, 1); hHeader->setCellSpan(1, nodeDepth + 1 + m_grayNames.size() + 1, 1, 1); // 一级 hHeader->setCellText(0, 0, QString("指标")); hHeader->setCellText(0, nodeDepth, QString("单位")); for (int i = 0; i < m_grayNames.size(); ++i) { hHeader->setCellText(0, nodeDepth + 1 + i, m_grayNames.at(i)); } hHeader->setCellText(0, nodeDepth + 1 + m_grayNames.size(), QString("延拓值")); // 二级 hHeader->setCellText(1, nodeDepth + 1 + m_grayNames.size(), "左"); hHeader->setCellText(1, nodeDepth + 2 + m_grayNames.size(), "右"); t->setHorizontalHeader(hHeader); } m_model->setColumnCount(nodeDepth + 3 + m_grayNames.size()); m_model->setRowCount(m_rowCount); // 其余的都可输入 for (int r = 0; r < m_model->rowCount(); ++r) { for (int c = nodeDepth; c < m_model->columnCount(); ++c) { auto s = new QStandardItem(); s->setTextAlignment(Qt::AlignCenter); m_model->setItem(r, c, s); } } for (auto &item : m_greyClusterings) { // 指标栏 auto s = new QStandardItem(item.indexName); s->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); s->setTextAlignment(Qt::AlignCenter); s->setToolTip(item.indexName); m_model->setItem(item.row, item.col, s); if (item.rowSpan > 1 || item.colSpan > 1) { t->setSpan(item.row, item.col, item.rowSpan, item.colSpan); } if (!item.value.isNull()) { m_model->item(item.row, nodeDepth)->setText(item.value->units); // 量纲 m_model->item(item.row, nodeDepth)->setEditable(false); for (int r = 0; r < item.value->greyRanges.size(); r++) { m_model->item(item.row, nodeDepth + r + 1) ->setText(QString("%1%2, %3%4") .arg((item.value->greyRanges[r].leftClose ? "[" : "(")) .arg(item.value->greyRanges[r].leftValue) .arg(item.value->greyRanges[r].rightValue) .arg((item.value->greyRanges[r].rightClose ? "]" : ")"))); } if (m_model->columnCount() > nodeDepth + m_grayNumber + 2) { m_model->item(item.row, nodeDepth + m_grayNumber + 1) ->setText(QString::number(item.value->leftExtension)); m_model->item(item.row, nodeDepth + m_grayNumber + 2) ->setText(QString::number(item.value->rightExtension)); } } } for (int c = 0; c < m_grayNames.size(); ++c) { t->setItemDelegateForColumn(c + nodeDepth + 1, new GreyClusteringItemRangeDelegate(t)); } for (int c = m_grayNames.size(); c < m_grayNames.size() + 2; ++c) { t->setItemDelegateForColumn(c + nodeDepth + 1, new GreyClusteringItemSpinDelegate(t)); } } void GreyClusteringConfigWidget::onConfirmClick() { QStringList names; for (int i = 0; i < m_grayNumber; ++i) { QLayoutItem *item = ui->grayFormLayout->itemAt(i + 1, QFormLayout::FieldRole); QLineEdit *le = qobject_cast(item->widget()); if (le) { if (le->text().trimmed().isEmpty()) { QMessageBox::warning(this, tr("警告"), tr("级别%1不能为空!").arg(i + 1)); return; } names << le->text().trimmed(); } } if (names.toSet().size() != m_grayNumber) { QMessageBox::warning(this, tr("警告"), tr("类别名不能重复!")); return; } m_grayNames = names; // 更新数据库等级值 QList gradeInfoList; if (!GradeInfoService().QueryGradeByProjectIdAndType(&gradeInfoList, m_mind->root().projectId, 1)) { QMessageBox::warning(this, "警告", "数据库访问失败"); return; } for (auto gi : gradeInfoList) { int num = gi->gradeName.mid(3, gi->gradeName.size() - 3).toInt(); if (num < names.size() + 1) { if (gi->gradeValue != names.at(num - 1)) { gi->gradeValue = names.at(num - 1); if (!GradeInfoService().UpdateGradeInfo(*gi)) { QMessageBox::warning(this, "警告", "数据库访问失败"); return; } } } } qDeleteAll(gradeInfoList); // 刷新表格 refreshTableView(); ui->stackedWidget->setCurrentIndex(1); } static bool isNeedUpdate(const EffectIndexInfo &effInfo, const GreyClusteringItem &item) { if (effInfo.effectIndexUnit != item.value->units) { return true; } QString effectIndexValue; for (const auto &range : item.value->greyRanges) { effectIndexValue += ","; effectIndexValue += range.leftClose ? "[" : "("; effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue); effectIndexValue += range.rightClose ? "]" : ")"; } if (effInfo.effectIndexValue != effectIndexValue.mid(1)) { return true; } if (effInfo.extendLeft.toDouble() != item.value->leftExtension) { return true; } if (effInfo.extendRight.toDouble() != item.value->rightExtension) { return true; } return false; } void GreyClusteringConfigWidget::onConfigSaveBtnClick() { for (auto &item : m_greyClusterings) { if (item.value.isNull()) { continue; } item.value->units = m_model->item(item.row, nodeDepth)->text(); // 指标 for (int r = 0; r < item.value->greyRanges.size(); r++) { QString str = m_model->item(item.row, nodeDepth + r + 1)->text(); item.value->greyRanges[r].leftClose = str[0] == "["; item.value->greyRanges[r].rightClose = str.right(1) == "]"; QStringList list = str.mid(1, str.size() - 2).replace(" ", "").split(","); item.value->greyRanges[r].leftValue = list.at(0).toDouble(); item.value->greyRanges[r].rightValue = list.at(1).toDouble(); } item.value->leftExtension = m_model->item(item.row, nodeDepth + m_grayNumber + 1)->text().toDouble(); item.value->rightExtension = m_model->item(item.row, nodeDepth + m_grayNumber + 2)->text().toDouble(); } // 更新数据库 QList effectIndexInfoList; int projectid = m_mind->root().projectId; if (!EffectIndexInfoService().QueryEffectIndexInfoByProjectId(&effectIndexInfoList, projectid)) { QMessageBox::warning(this, "警告", "数据库访问失败"); return; } for (auto &item : m_greyClusterings) { if (item.value.isNull()) { continue; } bool found = false; for (auto &effInfo : effectIndexInfoList) { if (effInfo->effectIndexName == item.indexName) { found = true; if (isNeedUpdate(*effInfo, item)) { QString effectIndexValue; for (const auto &range : item.value->greyRanges) { effectIndexValue += ","; effectIndexValue += range.leftClose ? "[" : "("; effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue); effectIndexValue += range.rightClose ? "]" : ")"; } effInfo->effectIndexValue = effectIndexValue.mid(1); effInfo->effectIndexUnit = item.value->units; effInfo->extendLeft = QString::number(item.value->leftExtension); effInfo->extendRight = QString::number(item.value->rightExtension); if (!EffectIndexInfoService().UpdateEffectIndexInfo(*effInfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); qDeleteAll(effectIndexInfoList); return; } } break; } } if (!found) { // 新增 EffectIndexInfo effInfo; effInfo.projectId = projectid; effInfo.effectIndexName = item.indexName; QString effectIndexValue; for (const auto &range : item.value->greyRanges) { effectIndexValue += ","; effectIndexValue += range.leftClose ? "[" : "("; effectIndexValue += QString("%1:%2").arg(range.leftValue).arg(range.rightValue); effectIndexValue += range.rightClose ? "]" : ")"; } effInfo.effectIndexValue = effectIndexValue.mid(1); effInfo.effectIndexUnit = item.value->units; effInfo.extendLeft = QString::number(item.value->leftExtension); effInfo.extendRight = QString::number(item.value->rightExtension); if (!EffectIndexInfoService().AddEffectIndexInfo(effInfo)) { QMessageBox::warning(this, "警告", "数据库访问失败"); break; } } } qDeleteAll(effectIndexInfoList); }