Advertisement
Guest User

Untitled

a guest
Jul 22nd, 2019
120
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.55 KB | None | 0 0
  1. #ifndef CELL_H
  2. #define CELL_H
  3.  
  4. #include <QTableWidgetItem>
  5. #include <QWidget>
  6.  
  7. class Cell : public QTableWidgetItem
  8. {
  9.  
  10. public:
  11. Cell();
  12.  
  13. QTableWidgetItem *clone() const;
  14. void setData(int role, const QVariant &value);
  15. QVariant data(int role) const;
  16. void setFormula(const QString &formula);
  17. QString formula() const;
  18. void setDirty();
  19.  
  20. private:
  21. QVariant value() const;
  22. QVariant evalExpression(const QString &str, int &pos) const;
  23. QVariant evalTerm(const QString &str, int &pos) const;
  24. QVariant evalFactor(const QString &str, int &pos) const;
  25.  
  26. mutable QVariant cachedValue;
  27. mutable bool cacheIsDirty;
  28. };
  29.  
  30. #endif // CELL_H
  31.  
  32. #include "cell.h"
  33. #include <QtWidgets>
  34.  
  35. Cell::Cell()
  36. {
  37. setDirty();
  38. }
  39.  
  40. QTableWidgetItem *Cell::clone() const
  41. {
  42. return new Cell(*this);
  43. }
  44.  
  45. void Cell::setData(int role, const QVariant &value)
  46. {
  47. QTableWidgetItem::setData(role, value);
  48. if(role == Qt::EditRole)
  49. {
  50. setDirty();
  51. }
  52. }
  53.  
  54. QString Cell::formula() const
  55. {
  56. return data(Qt::EditRole).toString();
  57. }
  58.  
  59. const QVariant Invalid;
  60.  
  61. QVariant Cell::data(int role) const
  62. {
  63. if(role == Qt::DisplayRole)
  64. {
  65. if(this->value().isValid())
  66. return value().toString();
  67. else
  68. return "####";
  69. }
  70. else if(role == Qt::TextAlignmentRole)
  71. {
  72. if(this->value().type() == QVariant::String)
  73. return int(Qt::AlignCenter| Qt::AlignVCenter);
  74. else
  75. return int(Qt::AlignRight | Qt::AlignVCenter);
  76. }
  77. else
  78. {
  79. return QTableWidgetItem::data(role);
  80. }
  81. }
  82.  
  83. void Cell::setFormula(const QString &formula)
  84. {
  85. setData(Qt::EditRole, formula);
  86. }
  87.  
  88. void Cell::setDirty()
  89. {
  90. this->cacheIsDirty = true;
  91. }
  92.  
  93. QVariant Cell::value() const
  94. {
  95. if (cacheIsDirty)
  96. {
  97. cacheIsDirty = false;
  98.  
  99. QString formulaStr = formula();
  100. if (formulaStr.startsWith('''))
  101. {
  102. cachedValue = formulaStr.mid(1);
  103. }
  104. else if (formulaStr.startsWith('='))
  105. {
  106. cachedValue = Invalid;
  107. QString expr = formulaStr.mid(1);
  108. expr.replace(" ", "");
  109. expr.append(QChar::Null);
  110.  
  111. int pos = 0;
  112. cachedValue = evalExpression(expr, pos);
  113. if (expr[pos] != QChar::Null)
  114. cachedValue = Invalid;
  115. }
  116. else
  117. {
  118. bool ok;
  119. double d = formulaStr.toDouble(&ok);
  120. if (ok)
  121. {
  122. cachedValue = d;
  123. }
  124. else
  125. {
  126. cachedValue = formulaStr;
  127. }
  128. }
  129. }
  130. return cachedValue;
  131. }
  132.  
  133. QVariant Cell::evalExpression(const QString &str, int &pos) const
  134. {
  135. QVariant result = evalTerm(str, pos);
  136. while (str[pos] != QChar::Null)
  137. {
  138. QChar op = str[pos];
  139. if (op != '+' && op != '-')
  140. return result;
  141. ++pos;
  142.  
  143. QVariant term = evalTerm(str, pos);
  144. if (result.type() == QVariant::Double
  145. && term.type() == QVariant::Double)
  146. {
  147. if (op == '+')
  148. {
  149. result = result.toDouble() + term.toDouble();
  150. }
  151. else
  152. {
  153. result = result.toDouble() - term.toDouble();
  154. }
  155. }
  156. else
  157. {
  158. result = Invalid;
  159. }
  160. }
  161. return result;
  162. }
  163.  
  164. QVariant Cell::evalTerm(const QString &str, int &pos) const
  165. {
  166. QVariant result = evalFactor(str, pos);
  167. while (str[pos] != QChar::Null)
  168. {
  169. QChar op = str[pos];
  170. if (op != '*' && op != '/')
  171. return result;
  172. ++pos;
  173.  
  174. QVariant factor = evalFactor(str, pos);
  175. if (result.type() == QVariant::Double
  176. && factor.type() == QVariant::Double)
  177. {
  178. if (op == '*')
  179. {
  180. result = result.toDouble() * factor.toDouble();
  181. }
  182. else
  183. {
  184. if (factor.toDouble() == 0.0)
  185. {
  186. result = Invalid;
  187. }
  188. else
  189. {
  190. result = result.toDouble() / factor.toDouble();
  191. }
  192. }
  193. }
  194. else
  195. {
  196. result = Invalid;
  197. }
  198. }
  199. return result;
  200. }
  201.  
  202.  
  203. QVariant Cell::evalFactor(const QString &str, int &pos) const
  204. {
  205. QVariant result;
  206. bool negative = false;
  207.  
  208. if (str[pos] == '-')
  209. {
  210. negative = true;
  211. ++pos;
  212. }
  213.  
  214. if (str[pos] == '(')
  215. {
  216. ++pos;
  217. result = evalExpression(str, pos);
  218. if (str[pos] != ')')
  219. result = Invalid;
  220. ++pos;
  221. }
  222. else
  223. {
  224. QRegExp regExp("[A-Za-z][1-9][0-9]{0,2}");
  225. QString token;
  226.  
  227. while (str[pos].isLetterOrNumber() || str[pos] == '.')
  228. {
  229. token += str[pos];
  230. ++pos;
  231. }
  232.  
  233. if (regExp.exactMatch(token))
  234. {
  235. int column = token[0].toUpper().unicode() - 'A';
  236. int row = token.mid(1).toInt() - 1;
  237.  
  238. Cell *c = static_cast<Cell *>(
  239. tableWidget()->item(row, column));
  240. if (c)
  241. {
  242. result = c->value();
  243. }
  244. else
  245. {
  246. result = 0.0;
  247. }
  248. }
  249. else
  250. {
  251. bool ok;
  252. result = token.toDouble(&ok);
  253. if (!ok)
  254. result = Invalid;
  255. }
  256. }
  257.  
  258. if (negative)
  259. {
  260. if (result.type() == QVariant::Double)
  261. {
  262. result = -result.toDouble();
  263. }
  264. else
  265. {
  266. result = Invalid;
  267. }
  268. }
  269. return result;
  270. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement