MatrixTableWidget.cpp 14 KB

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