UI/NumbersWidget.py

changeset 372
237c3fe739f5
child 373
1299126510eb
equal deleted inserted replaced
371:913f2c88915b 372:237c3fe739f5
1 # -*- coding: utf-8 -*-
2
3 # Copyright (c) 2010 Detlev Offenbach <detlev@die-offenbachs.de>
4 #
5
6 """
7 Module implementing a widget to show numbers in different formats.
8 """
9
10 from PyQt4.QtCore import pyqtSlot, pyqtSignal, Qt, QAbstractTableModel
11 from PyQt4.QtGui import QWidget, QHeaderView
12
13 from E5Gui.E5Application import e5App
14
15 from .Ui_NumbersWidget import Ui_NumbersWidget
16
17 import UI.PixmapCache
18
19 class BinaryModel(QAbstractTableModel):
20 """
21 Class implementing a model for entering binary numbers.
22 """
23 def __init__(self, parent = None):
24 """
25 Constructor
26
27 @param parent reference to the parent widget (QWidget)
28 """
29 QAbstractTableModel.__init__(self, parent)
30
31 self.__bits = 0
32 self.__value = 0
33
34 def rowCount(self, parent):
35 """
36 Public method to get the number of rows of the model.
37
38 @param parent parent index (QModelIndex)
39 @return number of columns (integer)
40 """
41 return 1
42
43 def columnCount(self, parent):
44 """
45 Public method to get the number of columns of the model.
46
47 @param parent parent index (QModelIndex)
48 @return number of columns (integer)
49 """
50 return self.__bits
51
52 def data(self, index, role = Qt.DisplayRole):
53 """
54 Public method to get data from the model.
55
56 @param index index to get data for (QModelIndex)
57 @param role role of the data to retrieve (integer)
58 @return requested data
59 """
60 if role == Qt.CheckStateRole:
61 return (self.__value >> (self.__bits - index.column() - 1)) & 1
62
63 elif role == Qt.DisplayRole:
64 return ""
65
66 return None
67
68 def flags(self, index):
69 """
70 Public method to get flags from the model.
71
72 @param index index to get flags for (QModelIndex)
73 @return flags (Qt.ItemFlags)
74 """
75 return Qt.ItemIsUserCheckable | Qt.ItemIsEnabled | Qt.ItemIsSelectable
76
77 def headerData(self, section, orientation, role = Qt.DisplayRole):
78 """
79 Public method to get header data from the model.
80
81 @param section section number (integer)
82 @param orientation orientation (Qt.Orientation)
83 @param role role of the data to retrieve (integer)
84 @return requested data
85 """
86 if orientation == Qt.Horizontal and role == Qt.DisplayRole:
87 return str(self.__bits - section - 1)
88
89 return QAbstractTableModel.headerData(self, section, orientation, role)
90
91 def setBits(self, bits):
92 """
93 Public slot to set the number of bits.
94
95 @param bits number of bits to show (integer)
96 """
97 self.__bits = bits
98 self.reset()
99
100 def setValue(self, value):
101 """
102 Public slot to set the value to show.
103
104 @param value value to show (integer)
105 """
106 self.__value = value
107 self.reset()
108
109 def setBitsAndValue(self, bits, value):
110 """
111 Public slot to set the number of bits and the value to show.
112
113 @param bits number of bits to show (integer)
114 @param value value to show (integer)
115 """
116 self.__bits = bits
117 self.__value = value
118 self.reset()
119
120 def getValue(self):
121 """
122 Public slot to get the current value.
123
124 @return current value of the model (integer)
125 """
126 return self.__value
127
128 def setData(self, index, value, role = Qt.EditRole):
129 """
130 Public method to set the data of a node cell.
131
132 @param index index of the node cell (QModelIndex)
133 @param value value to be set
134 @param role role of the data (integer)
135 @return flag indicating success (boolean)
136 """
137 print(role, value)
138 if role == Qt.CheckStateRole:
139 if value == Qt.Checked and not self.data(index, Qt.CheckStateRole):
140 # that seems like a hack; Qt 4.6 always sends Qt.Checked
141 self.__value |= (1 << self.__bits - index.column() - 1)
142 else:
143 self.__value &= ~(1 << self.__bits - index.column() - 1)
144 self.dataChanged.emit(index, index)
145 return True
146
147 return False
148
149 class NumbersWidget(QWidget, Ui_NumbersWidget):
150 """
151 Class implementing a widget to show numbers in different formats.
152
153 @signal insertNumber(str) emitted after the user has entered a number
154 and selected the number format
155 """
156 insertNumber = pyqtSignal(str)
157
158 def __init__(self, parent = None):
159 """
160 Constructor
161
162 @param parent reference to the parent widget (QWidget)
163 """
164 QWidget.__init__(self, parent)
165 self.setupUi(self)
166
167 self.setWindowIcon(UI.PixmapCache.getIcon("eric.png"))
168
169 self.__badNumberSheet = "background-color: #ffa0a0;"
170
171 self.binInButton.setIcon(UI.PixmapCache.getIcon("2downarrow.png"))
172 self.binOutButton.setIcon(UI.PixmapCache.getIcon("2uparrow.png"))
173 self.octInButton.setIcon(UI.PixmapCache.getIcon("2downarrow.png"))
174 self.octOutButton.setIcon(UI.PixmapCache.getIcon("2uparrow.png"))
175 self.decInButton.setIcon(UI.PixmapCache.getIcon("2downarrow.png"))
176 self.decOutButton.setIcon(UI.PixmapCache.getIcon("2uparrow.png"))
177 self.hexInButton.setIcon(UI.PixmapCache.getIcon("2downarrow.png"))
178 self.hexOutButton.setIcon(UI.PixmapCache.getIcon("2uparrow.png"))
179
180 self.formatBox.addItem(self.trUtf8("Auto"), 0)
181 self.formatBox.addItem(self.trUtf8("Dec"), 10)
182 self.formatBox.addItem(self.trUtf8("Hex"), 16)
183 self.formatBox.addItem(self.trUtf8("Oct"), 8)
184 self.formatBox.addItem(self.trUtf8("Bin"), 2)
185
186 self.sizeBox.addItem("8", 8)
187 self.sizeBox.addItem("16", 16)
188 self.sizeBox.addItem("32", 32)
189 self.sizeBox.addItem("64", 64)
190
191 self.__input = 0
192 self.__inputValid = True
193 self.__bytes = 1
194
195 self.__model = BinaryModel(self)
196 self.binTable.setModel(self.__model)
197 self.binTable.horizontalHeader().setResizeMode(QHeaderView.ResizeToContents)
198 self.__model.setBitsAndValue(self.__bytes * 8, self.__input)
199 self.__model.dataChanged.connect(self.__binModelDataChanged)
200
201 def __formatNumbers(self, format):
202 """
203 Private method to format the various number inputs.
204
205 @param format number format indicator (integer)
206 """
207 self.__block(True)
208
209 self.binEdit.setStyleSheet("")
210 self.octEdit.setStyleSheet("")
211 self.decEdit.setStyleSheet("")
212 self.hexEdit.setStyleSheet("")
213
214 # determine byte count
215 bytes = 8
216 tmp = self.__input
217 for i in range(8):
218 c = (tmp & 0xff00000000000000) >> 7 * 8
219 if c != 0 and self.__input >= 0:
220 break
221 if c != 0xff and self.__input < 0:
222 break
223 tmp <<= 8
224 bytes -= 1
225 if bytes == 0:
226 bytes = 1
227 self.__bytes = bytes
228
229 bytesIn = self.sizeBox.itemData(self.sizeBox.currentIndex()) // 8
230 if bytesIn and bytes > bytesIn:
231 self.sizeBox.setStyleSheet(self.__badNumberSheet)
232 else:
233 self.sizeBox.setStyleSheet("")
234
235 # octal
236 if format != 8:
237 self.octEdit.setText("{0:0{1}o}".format(self.__input, bytesIn * 3))
238
239 # decimal
240 if format != 10:
241 self.decEdit.setText("{0:d}".format(self.__input))
242
243 # hexadecimal
244 if format != 16:
245 self.hexEdit.setText("{0:0{1}x}".format(self.__input, bytesIn * 2))
246
247 # octal
248 if format != 8:
249 self.octEdit.setText("{0:0{1}o}".format(self.__input, bytesIn * 3))
250
251 # binary
252 if format != 2:
253 num = "{0:0{1}b}".format(self.__input, bytesIn * 8)
254 self.binEdit.setText(num)
255
256 self.__model.setBitsAndValue(len(self.binEdit.text()), self.__input)
257
258 self.__block(False)
259
260 def __block(self, b):
261 """
262 Private slot to block some signals.
263
264 @param b flah indicating the blocking state (boolean)
265 """
266 self.hexEdit.blockSignals(b)
267 self.decEdit.blockSignals(b)
268 self.octEdit.blockSignals(b)
269 self.binEdit.blockSignals(b)
270 self.binTable.blockSignals(b)
271
272 @pyqtSlot(int)
273 def on_sizeBox_valueChanged(self, index):
274 """
275 Slot documentation goes here.
276 """
277 self.__formatNumbers(10)
278
279 @pyqtSlot()
280 def on_byteOrderButton_clicked(self):
281 """
282 Private slot to swap the byte order.
283 """
284 bytesIn = self.sizeBox.itemData(self.sizeBox.currentIndex()) // 8
285 if bytesIn == 0:
286 bytesIn = self.__bytes
287
288 tmp1 = self.__input
289 tmp2 = 0
290 for i in range(bytesIn):
291 tmp2 <<= 8
292 tmp2 |= tmp1 & 0xff
293 tmp1 >>= 8
294
295 self.__input = tmp2
296 self.__formatNumbers(0)
297
298 @pyqtSlot()
299 def on_binInButton_clicked(self):
300 """
301 Private slot to retrieve a binary number from the current editor.
302 """
303 number = e5App().getObject("ViewManager").getNumber()
304 if number == "":
305 return
306
307 self.binEdit.setText(number)
308 self.binEdit.setFocus()
309
310 @pyqtSlot(str)
311 def on_binEdit_textChanged(self, txt):
312 """
313 Private slot to handle input of a binary number.
314
315 @param txt text entered (string)
316 """
317 try:
318 self.__input = int(txt, 2)
319 self.__inputValid = True
320 except ValueError:
321 self.__inputValid = False
322
323 if self.__inputValid:
324 self.__formatNumbers(2)
325 else:
326 self.binEdit.setStyleSheet(self.__badNumberSheet)
327
328 @pyqtSlot()
329 def on_binOutButton_clicked(self):
330 """
331 Private slot to send a binary number.
332 """
333 self.insertNumber.emit(self.binEdit.text())
334
335 def __binModelDataChanged(self, start, end):
336 """
337 Private slot to handle a change of the binary model value by the user.
338
339 @param start start index (QModelIndex)
340 @param end end index (QModelIndex)
341 """
342 val = self.__model.getValue()
343 bytesIn = self.sizeBox.itemData(self.sizeBox.currentIndex()) // 8
344 num = "{0:0{1}b}".format(val, bytesIn * 8)
345 self.binEdit.setText(num)
346
347 @pyqtSlot()
348 def on_octInButton_clicked(self):
349 """
350 Private slot to retrieve an octal number from the current editor.
351 """
352 number = e5App().getObject("ViewManager").getNumber()
353 if number == "":
354 return
355
356 self.octEdit.setText(number)
357 self.octEdit.setFocus()
358
359 @pyqtSlot(str)
360 def on_octEdit_textChanged(self, txt):
361 """
362 Private slot to handle input of an octal number.
363
364 @param txt text entered (string)
365 """
366 try:
367 self.__input = int(txt, 8)
368 self.__inputValid = True
369 except ValueError:
370 self.__inputValid = False
371
372 if self.__inputValid:
373 self.__formatNumbers(8)
374 else:
375 self.octEdit.setStyleSheet(self.__badNumberSheet)
376
377 @pyqtSlot()
378 def on_octOutButton_clicked(self):
379 """
380 Private slot to send an octal number.
381 """
382 self.insertNumber.emit(self.octEdit.text())
383
384 @pyqtSlot()
385 def on_decInButton_clicked(self):
386 """
387 Private slot to retrieve a decimal number from the current editor.
388 """
389 number = e5App().getObject("ViewManager").getNumber()
390 if number == "":
391 return
392
393 self.decEdit.setText(number)
394 self.decEdit.setFocus()
395
396 @pyqtSlot(str)
397 def on_decEdit_textChanged(self, txt):
398 """
399 Private slot to handle input of a decimal number.
400
401 @param txt text entered (string)
402 """
403 try:
404 self.__input = int(txt, 10)
405 self.__inputValid = True
406 except ValueError:
407 self.__inputValid = False
408
409 if self.__inputValid:
410 self.__formatNumbers(10)
411 else:
412 self.decEdit.setStyleSheet(self.__badNumberSheet)
413
414 @pyqtSlot()
415 def on_decOutButton_clicked(self):
416 """
417 Private slot to send a decimal number.
418 """
419 self.insertNumber.emit(self.decEdit.text())
420
421 @pyqtSlot()
422 def on_hexInButton_clicked(self):
423 """
424 Private slot to retrieve a hexadecimal number from the current editor.
425 """
426 number = e5App().getObject("ViewManager").getNumber()
427 if number == "":
428 return
429
430 self.hexEdit.setText(number)
431 self.hexEdit.setFocus()
432
433 @pyqtSlot(str)
434 def on_hexEdit_textChanged(self, txt):
435 """
436 Private slot to handle input of a hexadecimal number.
437
438 @param txt text entered (string)
439 """
440 try:
441 self.__input = int(txt, 16)
442 self.__inputValid = True
443 except ValueError:
444 self.__inputValid = False
445
446 if self.__inputValid:
447 self.__formatNumbers(16)
448 else:
449 self.hexEdit.setStyleSheet(self.__badNumberSheet)
450
451 @pyqtSlot()
452 def on_hexOutButton_clicked(self):
453 """
454 Private slot to send a hexadecimal number.
455 """
456 self.insertNumber.emit(self.hexEdit.text())
457
458 def setNumber(self, number):
459 """
460 Public method to set the number.
461 """
462 # TODO: implement this

eric ide

mercurial