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
14 import util.misc as misc_utils
19 _moduleLogger = logging.getLogger(__name__)
22 class QCalcHistory(history.AbstractHistory):
28 def __init__(self, errorReporter):
29 super(QCalcHistory, self).__init__()
30 self._prettyRenderer = operation.render_number()
31 self._errorReporter = errorReporter
33 self._historyStore = QtGui.QStandardItemModel()
34 self._historyStore.setHorizontalHeaderLabels(["", "Equation", "Result"])
35 self._historyStore.itemChanged.connect(self._on_item_changed)
37 self._historyView = QtGui.QTreeView()
38 self._historyView.setModel(self._historyStore)
39 self._historyView.setUniformRowHeights(True)
40 self._historyView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
41 self._historyView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
42 self._historyView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
43 self._historyView.setHeaderHidden(True)
44 self._historyView.activated.connect(self._on_row_activated)
46 viewHeader = self._historyView.header()
47 viewHeader.setSortIndicatorShown(True)
48 viewHeader.setClickable(True)
50 viewHeader.setResizeMode(self._CLOSE_COLUMN, QtGui.QHeaderView.ResizeToContents)
51 viewHeader.setResizeMode(self._EQ_COLUMN, QtGui.QHeaderView.Stretch)
52 viewHeader.setResizeMode(self._RESULT_COLUMN, QtGui.QHeaderView.ResizeToContents)
53 viewHeader.setStretchLastSection(False)
56 self._programmaticUpdate = False
57 self._closeIcon = maeqt.get_theme_icon(("window-close", "general_close", "gtk-close"))
61 return self._historyView
64 def errorReporter(self):
65 return self._errorReporter
68 simpleNode = node.simplify()
70 closeIcon = self._closeIcon
71 icon = QtGui.QStandardItem(closeIcon, "")
72 icon.setEditable(False)
73 icon.setCheckable(False)
74 equation = QtGui.QStandardItem(operation.render_operation(self._prettyRenderer, node))
75 equation.setData(node)
76 equation.setCheckable(False)
77 result = QtGui.QStandardItem(operation.render_operation(self._prettyRenderer, simpleNode))
78 result.setData(simpleNode)
79 result.setEditable(False)
80 result.setCheckable(False)
82 row = (icon, equation, result)
83 self._historyStore.appendRow(row)
85 index = result.index()
86 self._historyView.scrollTo(index)
91 raise IndexError("Not enough items in the history for the operation")
93 icon, equation, result = self._historyStore.takeRow(self._rowCount - 1)
95 return equation.data().toPyObject()
99 raise IndexError("Not enough items in the history for the operation")
101 icon, equation, result = self._historyStore.takeRow(self._rowCount - 1)
102 row = (icon, equation, result)
103 self._historyStore.appendRow(row)
105 return equation.data().toPyObject()
108 self._historyStore.clear()
111 @misc_utils.log_exception(_moduleLogger)
112 def _on_row_activated(self, index):
113 if index.column() == self._CLOSE_COLUMN:
114 self._historyStore.removeRow(index.row(), index.parent())
116 elif index.column() == self._EQ_COLUMN:
117 self._duplicate_row(index)
118 elif index.column() == self._RESULT_COLUMN:
119 self._duplicate_row(index)
121 raise NotImplementedError("Unsupported column to activate %s" % index.column())
123 @misc_utils.log_exception(_moduleLogger)
124 def _on_item_changed(self, item):
125 if self._programmaticUpdate:
126 _moduleLogger.info("Blocking updating %r recursively" % item)
128 self._programmaticUpdate = True
130 if item.column() in [self._EQ_COLUMN, self._RESULT_COLUMN]:
131 self._update_input(item)
133 raise NotImplementedError("Unsupported column to edit %s" % item.column())
134 except StandardError, e:
135 self.errorReporter.push_exception()
137 self._programmaticUpdate = False
139 def _duplicate_row(self, index):
140 item = self._historyStore.item(index.row(), self._EQ_COLUMN)
141 self.push(item.data().toPyObject())
143 def _parse_value(self, value):
144 raise NotImplementedError("What?")
146 def _update_input(self, item):
147 node = item.data().toPyObject()
149 eqNode = self._parse_value(str(item.text()))
150 newText = operation.render_operation(self._prettyRenderer, eqNode)
152 eqItem = self._historyStore.item(item.row(), self._EQ_COLUMN)
153 eqItem.setData(eqNode)
154 eqItem.setText(newText)
156 resultNode = eqNode.simplify()
157 resultText = operation.render_operation(self._prettyRenderer, resultNode)
158 resultItem = self._historyStore.item(item.row(), self._RESULT_COLUMN)
159 resultItem.setData(resultNode)
160 resultItem.setText(resultText)
162 oldText = operation.render_operation(self._prettyRenderer, node)
163 item.setText(oldText)
167 return self._rowCount
170 for i in xrange(self._rowCount):
171 item = self._historyStore.item(i, self._EQ_COLUMN)
174 yield item.data().toPyObject()