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 RowData(object):
23 HEADERS = ["", "Equation", "Result"]
24 ALIGNMENT = [QtCore.Qt.AlignLeft, QtCore.Qt.AlignLeft, QtCore.Qt.AlignLeft]
29 def __init__(self, renderer, node, simpleNode):
31 self._simpleNode = simpleNode
32 self._prettyRenderer = renderer
40 return self._simpleNode
44 return operation.render_operation(self._prettyRenderer, self._node)
48 return operation.render_operation(self._prettyRenderer, self._simpleNode)
50 def data(self, column):
51 if column == self.CLOSE_COLUMN:
53 elif column == self.EQ_COLUMN:
55 elif column == self.RESULT_COLUMN:
61 class HistoryModel(QtCore.QAbstractItemModel):
63 def __init__(self, parent=None):
64 super(HistoryModel, self).__init__(parent)
68 @misc_utils.log_exception(_moduleLogger)
69 def columnCount(self, parent):
73 return len(RowData.HEADERS)
75 @misc_utils.log_exception(_moduleLogger)
76 def data(self, index, role):
77 if not index.isValid():
80 if role == QtCore.Qt.DisplayRole:
81 item = index.internalPointer()
82 if isinstance(item, RowData):
83 print "d-rw", item.data(index.column())
84 return item.data(index.column())
85 elif item is RowData.HEADERS:
86 print "d-h", item[index.column()]
87 return item[index.column()]
88 elif role == QtCore.Qt.TextAlignmentRole:
89 return RowData.ALIGNMENT[index.column()]
90 elif role == QtCore.Qt.DecorationRole:
91 if index.column() == RowData.CLOSE_COLUMN:
98 @misc_utils.log_exception(_moduleLogger)
99 def flags(self, index):
100 if not index.isValid():
101 return QtCore.Qt.NoItemFlags
103 return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable
105 @misc_utils.log_exception(_moduleLogger)
106 def headerData(self, section, orientation, role):
107 if orientation == QtCore.Qt.Horizontal and role == QtCore.Qt.DisplayRole:
108 return RowData.HEADERS[section]
112 @misc_utils.log_exception(_moduleLogger)
113 def index(self, row, column, parent):
114 if not self.hasIndex(row, column, parent):
115 return QtCore.QModelIndex()
117 elif parent.isValid():
118 return QtCore.QModelIndex()
120 parentItem = RowData.HEADERS
121 childItem = self._children[row]
123 print "i", row, column, childItem
124 return self.createIndex(row, column, childItem)
126 return QtCore.QModelIndex()
128 @misc_utils.log_exception(_moduleLogger)
129 def parent(self, index):
130 if not index.isValid():
131 return QtCore.QModelIndex()
133 childItem = index.internalPointer()
134 if isinstance(childItem, RowData):
135 return QtCore.QModelIndex()
136 elif childItem is RowData.HEADERS:
139 @misc_utils.log_exception(_moduleLogger)
140 def rowCount(self, parent):
141 if 0 < parent.column():
144 if not parent.isValid():
145 print "rc", len(self._children)
146 return len(self._children)
148 print "rc", len(self._children)
149 return len(self._children)
152 self._children.append(row)
153 self._signal_rows_added()
155 print "push", len(self._children)
158 data = self._children[-1]
159 del self._children[-1]
160 self._signal_rows_removed()
165 data = self._children[-1]
169 del self._children[:]
173 return len(self._children)
176 return iter(self._children)
178 def _signal_rows_added(self):
179 # @todo Only signal new rows
182 def _signal_rows_removed(self):
183 # @todo Only signal new rows
186 def _all_changed(self):
187 if not self._children:
189 topLeft = self.createIndex(0, 0, self._children[0])
190 bottomRight = self.createIndex(len(self._children)-1, len(RowData.HEADERS)-1, self._children[-1])
191 self.dataChanged.emit(topLeft, bottomRight)
194 class QCalcHistory(history.AbstractHistory):
197 super(QCalcHistory, self).__init__()
198 self._prettyRenderer = operation.render_number()
200 self._historyStore = HistoryModel()
202 self._historyView = QtGui.QTreeView()
203 self._historyView.setModel(self._historyStore)
204 self._historyView.setUniformRowHeights(True)
205 self._historyView.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
206 self._historyView.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
207 self._historyView.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
208 self._historyView.setHeaderHidden(True)
210 viewHeader = self._historyView.header()
211 viewHeader.setSortIndicatorShown(True)
212 viewHeader.setClickable(True)
214 viewHeader.setResizeMode(RowData.CLOSE_COLUMN, QtGui.QHeaderView.ResizeToContents)
215 viewHeader.setResizeMode(RowData.EQ_COLUMN, QtGui.QHeaderView.ResizeToContents)
216 viewHeader.setResizeMode(RowData.RESULT_COLUMN, QtGui.QHeaderView.ResizeToContents)
217 viewHeader.setStretchLastSection(False)
221 return self._historyView
223 def push(self, node):
224 simpleNode = node.simplify()
225 row = RowData(self._prettyRenderer, node, simpleNode)
226 self._historyStore.push(row)
228 # @todo Scroll to bottom
231 if len(self._historyStore) == 0:
232 raise IndexError("Not enough items in the history for the operation")
234 row = self._historyStore.pop()
238 if len(self._historyStore) == 0:
239 raise IndexError("Not enough items in the history for the operation")
240 row = self._historyStore.peek()
244 self._historyStore.clear()
247 return len(self._historyStore)
250 for row in iter(self._historyStore):