MatrixTableWidget.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. #include "MatrixTableWidget.h"
  2. #include "MatrixTableItemDelegate.h"
  3. #include "algorithm/ConsistencyCheck.h"
  4. #include <QApplication>
  5. #include <QDebug>
  6. #include <QDesktopWidget>
  7. #include <QHeaderView>
  8. #include <QMessageBox>
  9. #include <QTimer>
  10. #include <QtMath>
  11. #include "dbService/ClassSet.h"
  12. #include "dbService/DBServiceSet.h"
  13. #include "dbService/NodeMatrixService.h"
  14. #include "dbService/DemandWeightService.h"
  15. MatrixTableWidget::MatrixTableWidget(bool diagonalOne, QWidget *parent) : QTableView(parent), diagonalIsOne(diagonalOne)
  16. {
  17. model = new QStandardItemModel();
  18. this->setModel(model);
  19. paintDone = false;
  20. // connect(model, &QStandardItemModel::itemChanged, this,
  21. // &MatrixTableWidget::nodeValueChanged);
  22. connect(this, &QTableView::clicked, this, &MatrixTableWidget::itemClicked);
  23. }
  24. MatrixTableWidget::~MatrixTableWidget() { }
  25. void MatrixTableWidget::addRowNode(QString node, QString name, QString remark)
  26. {
  27. matrixRows << MatrixTableWidget::MatrixNode(node, name, remark);
  28. }
  29. void MatrixTableWidget::addColNode(QString node, QString name, QString remark)
  30. {
  31. matrixCols << MatrixTableWidget::MatrixNode(node, name, remark);
  32. }
  33. void MatrixTableWidget::setCurrentPage(int page)
  34. {
  35. currentPage = page;
  36. }
  37. void MatrixTableWidget::setTableIndexAndTableMsg(int index, int engineerId, int expertId, QString tableMsg)
  38. {
  39. m_tableIndex = index;
  40. m_engineerId = engineerId;
  41. m_expertId = expertId;
  42. m_table_msg = tableMsg;
  43. }
  44. void MatrixTableWidget::setMsgName(QString msgName)
  45. {
  46. m_msg_name = msgName;
  47. }
  48. QList<MatrixDataSource> MatrixTableWidget::getSource() const
  49. {
  50. return dataSource;
  51. }
  52. void MatrixTableWidget::paintMatrixTable(QList<NodeMatrixInfo *> nodeValueInfoList)
  53. {
  54. // qDebug() << "nodeValueInfoList========" << nodeValueInfoList.size();
  55. int row = matrixRows.count();
  56. int col = matrixCols.count();
  57. // qDebug() << row << col;
  58. this->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
  59. this->setSelectionMode(QAbstractItemView::SingleSelection);
  60. this->setSelectionBehavior(QAbstractItemView::SelectItems);
  61. model->setHorizontalHeaderItem(0, new QStandardItem(""));
  62. for (int c = 0; c < col; ++c) {
  63. model->setHorizontalHeaderItem(c + 1, new QStandardItem(matrixCols[c].name));
  64. model->horizontalHeaderItem(c + 1)->setToolTip(matrixCols[c].remark);
  65. }
  66. for (int r = 0; r < row; ++r) {
  67. model->setItem(r, 0, new QStandardItem(matrixRows[r].name));
  68. model->item(r, 0)->setToolTip(matrixRows[r].remark);
  69. model->item(r, 0)->setTextAlignment(Qt::AlignCenter);
  70. model->item(r, 0)->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
  71. for (int c = 1; c < col + 1; ++c) {
  72. MatrixDataSource data;
  73. data.row = r;
  74. data.col = c;
  75. if (c - 1 == r) {
  76. if (diagonalIsOne) {
  77. data.changed = true;
  78. data.nodeValue = "1";
  79. } else {
  80. data.changed = false;
  81. for (NodeMatrixInfo *nodeMatrixInfo : nodeValueInfoList) {
  82. if (nodeMatrixInfo->abscissa == matrixRows[r].name
  83. && nodeMatrixInfo->ordinate == matrixCols[c - 1].name) {
  84. data.nodeValue = nodeMatrixInfo->nodeValue;
  85. data.changed = true;
  86. }
  87. }
  88. // data.nodeValue = "";
  89. }
  90. } else {
  91. data.changed = false;
  92. // data.nodeValue = "";
  93. for (NodeMatrixInfo *nodeMatrixInfo : nodeValueInfoList) {
  94. if (nodeMatrixInfo->abscissa == matrixRows[r].name
  95. && nodeMatrixInfo->ordinate == matrixCols[c - 1].name) {
  96. data.nodeValue = nodeMatrixInfo->nodeValue;
  97. data.changed = true;
  98. }
  99. }
  100. }
  101. // data.nodeValue = QString("%1, %2").arg(r).arg(c);
  102. model->setItem(r, c, new QStandardItem(data.nodeValue));
  103. model->item(r, c)->setTextAlignment(Qt::AlignCenter);
  104. if ((r + 1 >= c) && diagonalIsOne) {
  105. model->item(r, c)->setFlags(Qt::ItemIsEnabled);
  106. model->item(r, c)->setBackground(QBrush(QColor("lightgray")));
  107. }
  108. if (diagonalIsOne) {
  109. data.node = matrixRows[r].node;
  110. } else {
  111. data.node = matrixCols[c - 1].node;
  112. }
  113. data.abscissa = matrixRows[r].name;
  114. data.ordinate = matrixCols[c - 1].name;
  115. dataSource << data;
  116. }
  117. }
  118. emit returnModel(model);
  119. emit returnModelName(m_msg_name);
  120. paintDone = true;
  121. }
  122. void MatrixTableWidget::nodeValueChanged(QStandardItem *item)
  123. {
  124. if (paintDone) {
  125. bool valid = false;
  126. QStringList valist = item->text().trimmed().split("/");
  127. if (valist.count() > 2) { // 两个除号
  128. valid = false;
  129. item->setText("");
  130. } else if (valist.count() == 2) {
  131. bool num = false; // 分子
  132. bool den = false; // 分母
  133. valist[0].toDouble(&num);
  134. valist[1].toDouble(&den);
  135. if ((!num) || (!den)) {
  136. valid = false;
  137. item->setText("");
  138. }
  139. } else {
  140. bool dou = false; // double
  141. item->text().trimmed().toDouble(&dou);
  142. if (!dou) {
  143. valid = false;
  144. item->setText("");
  145. }
  146. }
  147. if (diagonalIsOne) {
  148. if (item->row() + 1 < item->column()) {
  149. QString newText;
  150. QStringList split = item->text().split("/");
  151. if (split.count() == 1) {
  152. if (split[0].toDouble() == 1.) {
  153. newText = split[0];
  154. } else {
  155. newText = QString("1/%1").arg(item->text());
  156. }
  157. } else {
  158. if (split[0].toDouble() == 1.) {
  159. newText = split[1];
  160. } else {
  161. newText = split[1] + "/" + split[0];
  162. }
  163. }
  164. model->item(item->column() - 1, item->row() + 1)->setText(newText);
  165. }
  166. }
  167. bool inputDone = true;
  168. for (int i = 0; i < dataSource.count(); ++i) {
  169. if (dataSource[i].row == item->row() && dataSource[i].col == item->column()) {
  170. dataSource[i].nodeValue = item->text().trimmed();
  171. if (!item->text().trimmed().isEmpty()) {
  172. dataSource[i].changed = true;
  173. } else {
  174. dataSource[i].changed = false;
  175. }
  176. }
  177. if (!dataSource[i].changed) {
  178. inputDone = false;
  179. }
  180. }
  181. // if (inputDone) { qDebug() << "done"; }
  182. emit dataReady(inputDone);
  183. }
  184. }
  185. void MatrixTableWidget::itemClicked(const QModelIndex &index)
  186. {
  187. if (index.row() + 1 >= index.column()) {
  188. return;
  189. }
  190. QStringList l = { "1/9", "1/7", "1/5", "1/3", "1", "3", "5", "7", "9" };
  191. SchemeBar *scheme =
  192. new SchemeBar(model->item(index.row(), 0)->text(), model->horizontalHeaderItem(index.column())->text(), l);
  193. scheme->setModal(true);
  194. scheme->setAttribute(Qt::WA_DeleteOnClose);
  195. connect(scheme, &SchemeBar::setValue, [=](QString val) { editItemData(index, val); });
  196. scheme->show();
  197. QPoint p = QCursor::pos();
  198. if (p.x() + scheme->width() + 10 >= QApplication::desktop()->width()) {
  199. p.setX(QApplication::desktop()->width() - 10 - scheme->width());
  200. }
  201. scheme->move(p);
  202. }
  203. void MatrixTableWidget::pollCellsData()
  204. {
  205. // 检测是否存在空值
  206. for (int r = 0; r < model->rowCount(); ++r) {
  207. for (int c = 0; c < model->columnCount(); ++c) {
  208. if (model->item(r, c)->text().isEmpty()) {
  209. return;
  210. }
  211. }
  212. }
  213. QTimer::singleShot(0, this, [=]() {
  214. QStringList nodes;
  215. QVector<qreal> nxn((int)qPow(model->rowCount(), 2), 0);
  216. for (int r = 0; r < model->rowCount(); ++r) {
  217. nodes << model->item(r, 0)->text().trimmed();
  218. for (int c = 1; c < model->columnCount(); ++c) {
  219. QStringList content = model->item(r, c)->text().trimmed().split("/");
  220. if (content.size() == 1) {
  221. nxn[r * model->rowCount() + c - 1] = content[0].toDouble();
  222. } else {
  223. nxn[r * model->rowCount() + c - 1] = content[0].toDouble() / content[1].toDouble();
  224. }
  225. }
  226. }
  227. ConsistencyCheck cc(nodes, nxn);
  228. if (!cc.consitst()) {
  229. QMessageBox::warning(this, "一致性校验",
  230. QString("CR:%"
  231. "1\r\n您好,一致性检验未通过!请您检查填写的"
  232. "数据是否有逻辑上的矛盾,例如A比B重"
  233. "要,B比C重要,然后又判断有C比A重要。")
  234. .arg(cc.CR()));
  235. QStandardItem *item = model->item(model->rowCount() - 2, model->columnCount() - 1);
  236. QStandardItem *item1 = model->item(model->columnCount() - 2, model->rowCount() - 1);
  237. for (int i = 0; i < dataSource.count(); ++i) {
  238. if (dataSource[i].row == item->row() && dataSource[i].col == item->column()) {
  239. dataSource[i].nodeValue = "";
  240. item->setText("");
  241. dataSource[i].changed = false;
  242. } else if (dataSource[i].row == item1->row() && dataSource[i].col == item1->column()) {
  243. dataSource[i].nodeValue = "";
  244. item1->setText("");
  245. dataSource[i].changed = false;
  246. }
  247. }
  248. } else {
  249. // 校验成功持久化数据
  250. QStringList nodeList = cc.getNodes();
  251. QVector<qreal> weights = cc.getWeights();
  252. qDebug() << weights;
  253. qDebug() << currentPage;
  254. QList<DemandWeight *> list;
  255. if (currentPage == 1) {
  256. for (int i = 0; i < weights.length(); i++) {
  257. DemandWeight *demandWeight = new DemandWeight();
  258. demandWeight->nodeName = nodeList.at(i);
  259. demandWeight->nodeWeight = weights.at(i);
  260. demandWeight->engineerId = m_engineerId;
  261. demandWeight->expertId = m_expertId;
  262. demandWeight->isValid = 0;
  263. demandWeight->tableIndex = m_tableIndex;
  264. demandWeight->tableMsg = m_table_msg;
  265. list.append(demandWeight);
  266. }
  267. } else {
  268. // 查询出第一页权重
  269. QList<DemandWeight *> firstList;
  270. DemandWeightService().QueryByTableIndexAndTableMsg(&firstList, m_expertId, m_engineerId, 0,
  271. m_table_msg);
  272. qDebug() << "firstList===" << firstList.size();
  273. double weight = 0;
  274. if (firstList.size() != 0) {
  275. weight = firstList.at(m_tableIndex - 1)->nodeWeight;
  276. }
  277. for (int i = 0; i < weights.length(); i++) {
  278. DemandWeight *demandWeight = new DemandWeight();
  279. demandWeight->nodeName = nodeList.at(i);
  280. demandWeight->nodeWeight = weights.at(i);
  281. demandWeight->engineerId = m_engineerId;
  282. demandWeight->expertId = m_expertId;
  283. demandWeight->isValid = 0;
  284. demandWeight->tableIndex = m_tableIndex;
  285. demandWeight->tableMsg = m_table_msg;
  286. demandWeight->nodeValue = demandWeight->nodeWeight * weight;
  287. list.append(demandWeight);
  288. }
  289. }
  290. if (DemandWeightService().QueryByTableIndexAndTableMsg(m_expertId, m_engineerId, m_tableIndex,
  291. m_table_msg)) {
  292. DemandWeightService().UpdateNodeValueList(list);
  293. } else {
  294. DemandWeightService().AddNodeWeightInfoList(list);
  295. }
  296. QMessageBox::information(this, "一致性比例合格", QString("CR:%1").arg(cc.CR()));
  297. // TODO 判断是否是保存后修改后,如保存后修改续自动调用保存
  298. emit autoSave();
  299. }
  300. });
  301. }
  302. void MatrixTableWidget::editItemData(const QModelIndex &index, const QString &val)
  303. {
  304. model->itemFromIndex(index)->setText(val);
  305. QString symmetry;
  306. if (val.startsWith("1/")) {
  307. symmetry = val.split("/")[1];
  308. } else {
  309. if (val == "0" || val == "1") {
  310. symmetry = val;
  311. } else {
  312. symmetry = "1/" + val;
  313. }
  314. }
  315. model->item(index.column() - 1, index.row() + 1)->setText(symmetry);
  316. QStandardItem *item = model->itemFromIndex(index);
  317. QStandardItem *item1 = model->item(index.column() - 1, index.row() + 1);
  318. for (int i = 0; i < dataSource.count(); ++i) {
  319. if (dataSource[i].row == item->row() && dataSource[i].col == item->column()) {
  320. dataSource[i].nodeValue = item->text().trimmed();
  321. if (!item->text().trimmed().isEmpty()) {
  322. dataSource[i].changed = true;
  323. } else {
  324. dataSource[i].changed = false;
  325. }
  326. } else if (dataSource[i].row == item1->row() && dataSource[i].col == item1->column()) {
  327. dataSource[i].nodeValue = item1->text().trimmed();
  328. if (!item1->text().trimmed().isEmpty()) {
  329. dataSource[i].changed = true;
  330. } else {
  331. dataSource[i].changed = false;
  332. }
  333. }
  334. }
  335. pollCellsData();
  336. emit dataReady(isDataReady());
  337. }
  338. bool MatrixTableWidget::isDataReady() const
  339. {
  340. if (dataSource.count() == 0) {
  341. return false;
  342. }
  343. for (MatrixDataSource data : dataSource) {
  344. if (data.changed == false) {
  345. return false;
  346. }
  347. }
  348. return true;
  349. }