4 http://www.grigoriev.ru/svgmath/ (MathML->SVG in Python)
5 http://helm.cs.unibo.it/mml-widget/ (MathML widget in C++)
10 from PyQt4 import QtGui
11 from PyQt4 import QtCore
13 import util.misc as misc_utils
18 _moduleLogger = logging.getLogger(__name__)
21 class QCalcHistory(history.AbstractHistory):
27 def __init__(self, errorReporter):
28 super(QCalcHistory, self).__init__()
29 self._prettyRenderer = operation.render_number()
30 self._errorReporter = errorReporter
32 self._historyStore = QtGui.QStandardItemModel()
33 self._historyStore.setHorizontalHeaderLabels(["", "Equation", "Result"])
34 self._historyStore.itemChanged.connect(self._on_item_changed)
36 self._historyView = QtGui.QTreeView()
37 self._historyView.setModel(self._historyStore)
38 self._historyView.setUniformRowHeights(True)
39 self._historyView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
40 self._historyView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
41 self._historyView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
42 self._historyView.setHeaderHidden(True)
43 self._historyView.activated.connect(self._on_delete_row)
45 viewHeader = self._historyView.header()
46 viewHeader.setSortIndicatorShown(True)
47 viewHeader.setClickable(True)
49 viewHeader.setResizeMode(self._CLOSE_COLUMN, QtGui.QHeaderView.ResizeToContents)
50 viewHeader.setResizeMode(self._EQ_COLUMN, QtGui.QHeaderView.Stretch)
51 viewHeader.setResizeMode(self._RESULT_COLUMN, QtGui.QHeaderView.ResizeToContents)
52 viewHeader.setStretchLastSection(False)
55 self._programmaticUpdate = False
59 return self._historyView
62 def errorReporter(self):
63 return self._errorReporter
66 simpleNode = node.simplify()
68 icon = QtGui.QStandardItem(QtGui.QIcon.fromTheme("gtk-close"), "")
69 icon.setEditable(False)
70 icon.setCheckable(False)
71 equation = QtGui.QStandardItem(operation.render_operation(self._prettyRenderer, node))
72 equation.setData(node)
73 equation.setCheckable(False)
74 result = QtGui.QStandardItem(operation.render_operation(self._prettyRenderer, simpleNode))
75 result.setData(simpleNode)
76 result.setCheckable(False)
78 row = (icon, equation, result)
79 self._historyStore.appendRow(row)
81 index = result.index()
82 self._historyView.scrollTo(index)
87 raise IndexError("Not enough items in the history for the operation")
89 icon, equation, result = self._historyStore.takeRow(self._rowCount - 1)
91 return equation.data().toPyObject()
95 raise IndexError("Not enough items in the history for the operation")
97 icon, equation, result = self._historyStore.takeRow(self._rowCount - 1)
98 row = (icon, equation, result)
99 self._historyStore.appendRow(row)
101 return equation.data().toPyObject()
104 self._historyStore.clear()
107 @misc_utils.log_exception(_moduleLogger)
108 def _on_delete_row(self, index):
109 if index.column() == self._CLOSE_COLUMN:
110 self._historyStore.removeRow(index.row(), index.parent())
112 raise NotImplementedError("Unsupported column to activate %s" % index.column())
114 @misc_utils.log_exception(_moduleLogger)
115 def _on_item_changed(self, item):
116 if self._programmaticUpdate:
117 _moduleLogger.info("Blocking updating %r recursively" % item)
119 self._programmaticUpdate = True
121 if item.column() in [self._EQ_COLUMN, self._RESULT_COLUMN]:
122 self._update_input(item)
124 raise NotImplementedError("Unsupported column to edit %s" % item.column())
125 except StandardError, e:
126 self.errorReporter.push_exception()
128 self._programmaticUpdate = False
130 def _parse_value(self, value):
131 raise NotImplementedError("What?")
133 def _update_input(self, item):
134 node = item.data().toPyObject()
136 eqNode = self._parse_value(str(item.text()))
137 newText = operation.render_operation(self._prettyRenderer, eqNode)
139 eqItem = self._historyStore.item(item.row(), self._EQ_COLUMN)
140 eqItem.setData(eqNode)
141 eqItem.setText(newText)
143 resultNode = eqNode.simplify()
144 resultText = operation.render_operation(self._prettyRenderer, resultNode)
145 resultItem = self._historyStore.item(item.row(), self._RESULT_COLUMN)
146 resultItem.setData(resultNode)
147 resultItem.setText(resultText)
149 oldText = operation.render_operation(self._prettyRenderer, node)
150 item.setText(oldText)
154 return self._rowCount
157 for i in xrange(self._rowCount):
158 yield self._historyStore.item(i, 1).data().toPyObject()