5 @todo Look into using two columns for displaying the value, split by the
6 decimal place. The left one would be right aligned and the right would be left
7 aligned (only if not in exponential notation
8 OR display everything in engineering notation
10 @tood Add a unit description dialog for when hildonized
12 @todo Add support for custom units
14 @todo Add support for compound units
41 _moduleLogger = logging.getLogger("gonvert_glade")
42 PROFILE_STARTUP = False
43 FORCE_HILDON_LIKE = False
45 if gettext is not None:
46 gettext.bindtextdomain('gonvert', '/usr/share/locale')
47 gettext.textdomain('gonvert')
50 def change_menu_label(widgets, labelname, newtext):
51 item_label = widgets.get_widget(labelname).get_children()[0]
52 item_label.set_text(newtext)
55 def split_number(number):
57 fractional, integer = math.modf(number)
59 integerDisplay = number
60 fractionalDisplay = ""
62 integerDisplay = str(integer)
63 fractionalDisplay = str(fractional)
64 if "e+" in integerDisplay:
65 integerDisplay = number
66 fractionalDisplay = ""
67 elif "e-" in fractionalDisplay and 0.0 < integer:
68 integerDisplay = number
69 fractionalDisplay = ""
70 elif "e-" in fractionalDisplay:
72 fractionalDisplay = number
74 integerDisplay = integerDisplay.split(".", 1)[0] + "."
75 fractionalDisplay = fractionalDisplay.rsplit(".", 1)[-1]
77 return integerDisplay, fractionalDisplay
80 class Gonvert(object):
83 os.path.join(os.path.dirname(__file__), "gonvert.glade"),
84 os.path.join(os.path.dirname(__file__), "../data/gonvert.glade"),
85 os.path.join(os.path.dirname(__file__), "../lib/gonvert.glade"),
86 '/usr/share/gonvert/gonvert.glade',
87 '/usr/lib/gonvert/gonvert.glade',
94 UNITS_FRACTION_IDX = 4
97 self._unitDataInCategory = None
98 self._unit_sort_direction = False
99 self._value_sort_direction = False
100 self._units_sort_direction = False
101 self._isFullScreen = False
103 self._find_result = [] # empty find result list
104 self._findIndex = 0 # default to find result number zero
106 self._selectedCategoryName = '' # preset to no selected category
107 self._defaultUnitForCategory = {} # empty dictionary for later use
109 #check to see if glade file is in current directory (user must be
110 # running from download untar directory)
111 for gladePath in self._glade_files:
112 if os.path.isfile(gladePath):
113 homepath = os.path.dirname(gladePath)
114 pixmapspath = "/".join((homepath, "pixmaps"))
115 widgets = gtk.glade.XML(gladePath)
118 _moduleLogger.error("UI Descriptor not found!")
122 self._mainWindow = widgets.get_widget('mainWindow')
123 self._app = hildonize.get_app_class()()
124 self._mainWindow = hildonize.hildonize_window(self._app, self._mainWindow)
126 change_menu_label(widgets, 'fileMenuItem', _('File'))
127 change_menu_label(widgets, 'exitMenuItem', _('Exit'))
128 change_menu_label(widgets, 'helpMenuItem', _('Help'))
129 change_menu_label(widgets, 'aboutMenuItem', _('About'))
130 change_menu_label(widgets, 'findButton', _('Find'))
132 self._categorySelectionButton = widgets.get_widget("categorySelectionButton")
133 self._categoryView = widgets.get_widget('categoryView')
135 self._unitsView = widgets.get_widget('unitsView')
136 self._unitsView.set_property('rules_hint', 1)
137 self._unitsView_selection = self._unitsView.get_selection()
139 self._unitName = widgets.get_widget('unitName')
140 self._unitValue = widgets.get_widget('unitValue')
141 self._previousUnitName = widgets.get_widget('previousUnitName')
142 self._previousUnitValue = widgets.get_widget('previousUnitValue')
144 self._unitSymbol = widgets.get_widget('unitSymbol')
145 self._previousUnitSymbol = widgets.get_widget('previousUnitSymbol')
147 self._unitDescription = widgets.get_widget('unitDescription')
149 self._searchLayout = widgets.get_widget('searchLayout')
150 self._searchLayout.hide()
151 self._findEntry = widgets.get_widget('findEntry')
152 self._findLabel = widgets.get_widget('findLabel')
153 self._findButton = widgets.get_widget('findButton')
155 #insert a self._categoryColumnumn into the units list even though the heading will not be seen
156 renderer = gtk.CellRendererText()
157 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
158 renderer.set_property("width-chars", len("grams per cubic cm plus some"))
159 self._unitNameColumn = gtk.TreeViewColumn(_('Name'), renderer)
160 self._unitNameColumn.set_property('resizable', True)
161 self._unitNameColumn.add_attribute(renderer, 'text', self.UNITS_NAME_IDX)
162 self._unitNameColumn.set_clickable(True)
163 self._unitNameColumn.connect("clicked", self._on_click_unit_column)
164 self._unitsView.append_column(self._unitNameColumn)
166 renderer = gtk.CellRendererText()
167 renderer.set_property("xalign", 1.0)
168 renderer.set_property("alignment", pango.ALIGN_RIGHT)
169 hildonize.set_cell_thumb_selectable(renderer)
170 self._unitIntegerColumn = gtk.TreeViewColumn(_('Value'), renderer)
171 self._unitIntegerColumn.set_property('resizable', True)
172 self._unitIntegerColumn.add_attribute(renderer, 'text', self.UNITS_INTEGER_IDX)
173 self._unitIntegerColumn.set_clickable(True)
174 self._unitIntegerColumn.connect("clicked", self._on_click_unit_column)
175 self._unitsView.append_column(self._unitIntegerColumn)
177 renderer = gtk.CellRendererText()
178 renderer.set_property("xalign", 0.0)
179 renderer.set_property("alignment", pango.ALIGN_LEFT)
180 self._unitFractionalColumn = gtk.TreeViewColumn(_(''), renderer)
181 self._unitFractionalColumn.set_property('resizable', True)
182 self._unitFractionalColumn.add_attribute(renderer, 'text', self.UNITS_FRACTION_IDX)
183 self._unitFractionalColumn.set_clickable(True)
184 self._unitFractionalColumn.connect("clicked", self._on_click_unit_column)
185 self._unitsView.append_column(self._unitFractionalColumn)
187 renderer = gtk.CellRendererText()
188 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
189 renderer.set_property("width-chars", len("G ohm plus some"))
190 self._unitSymbolColumn = gtk.TreeViewColumn(_('Units'), renderer)
191 self._unitSymbolColumn.set_property('resizable', True)
192 self._unitSymbolColumn.add_attribute(renderer, 'text', self.UNITS_SYMBOL_IDX)
193 self._unitSymbolColumn.set_clickable(True)
194 self._unitSymbolColumn.connect("clicked", self._on_click_unit_column)
195 self._unitsView.append_column(self._unitSymbolColumn)
197 self._unitModel = gtk.ListStore(
198 gobject.TYPE_STRING, # UNITS_NAME_IDX
199 gobject.TYPE_STRING, # UNITS_VALUE_IDX
200 gobject.TYPE_STRING, # UNITS_SYMBOL_IDX
201 gobject.TYPE_STRING, # UNITS_INTEGER_IDX
202 gobject.TYPE_STRING, # UNITS_FRACTION_IDX
204 self._sortedUnitModel = gtk.TreeModelSort(self._unitModel)
205 columns = self._get_column_sort_stuff()
206 for columnIndex, (column, sortDirection, col_cmp) in enumerate(columns):
207 self._sortedUnitModel.set_sort_func(columnIndex, col_cmp)
208 self._unitsView.set_model(self._sortedUnitModel)
210 #Insert a column into the category list even though the heading will not be seen
211 renderer = gtk.CellRendererText()
212 self._categoryColumn = gtk.TreeViewColumn('Title', renderer)
213 self._categoryColumn.set_property('resizable', 1)
214 self._categoryColumn.add_attribute(renderer, 'text', 0)
215 self._categoryView.append_column(self._categoryColumn)
217 self._categoryModel = gtk.ListStore(gobject.TYPE_STRING)
218 self._categoryView.set_model(self._categoryModel)
219 #colourize each row differently for easier reading
220 self._categoryView.set_property('rules_hint', 1)
222 #Populate the catagories list
223 for key in unit_data.UNIT_CATEGORIES:
225 self._categoryModel.append(row)
227 #--------- connections to GUI ----------------
228 self._mainWindow.connect("delete-event", self._on_user_exit)
229 self._mainWindow.connect("key-press-event", self._on_key_press)
230 self._mainWindow.connect("window-state-event", self._on_window_state_change)
231 self._categorySelectionButton.connect("clicked", self._on_category_selector_clicked)
232 self._categoryView.connect("cursor-changed", self._on_click_category)
233 self._findButton.connect("clicked", self._on_find_activate)
234 self._findEntry.connect("activate", self._on_find_activate)
235 self._findEntry.connect("changed", self._on_findEntry_changed)
236 self._previousUnitValue.connect("changed", self._on_previous_unit_value_changed)
237 self._unitValue.connect("changed", self._on_unit_value_changed)
238 self._unitsView.connect("cursor-changed", self._on_click_unit)
239 if hildonize.GTK_MENU_USED:
240 widgets.get_widget("aboutMenuItem").connect("activate", self._on_about_clicked)
241 widgets.get_widget("exitMenuItem").connect("activate", self._on_user_exit)
243 for scrollingWidgetName in (
244 "unitsViewScrolledWindow",
246 scrollingWidget = widgets.get_widget(scrollingWidgetName)
247 assert scrollingWidget is not None, scrollingWidgetName
248 hildonize.hildonize_scrollwindow_with_viewport(scrollingWidget)
250 if hildonize.IS_HILDON_SUPPORTED or FORCE_HILDON_LIKE:
251 self._categoryView.get_parent().hide()
252 self._unitsView.set_headers_visible(False)
253 self._previousUnitName.get_parent().hide()
254 self._unitDescription.get_parent().get_parent().hide()
256 self._categorySelectionButton.hide()
258 replacementButtons = []
259 menu = hildonize.hildonize_menu(
261 widgets.get_widget("mainMenuBar"),
265 if not hildonize.IS_HILDON_SUPPORTED:
266 _moduleLogger.info("No hildonization support")
268 hildonize.set_application_title(
269 self._mainWindow, "%s - Unit Conversion Utility" % constants.__pretty_app_name__
271 iconPath = pixmapspath + '/gonvert.png'
272 if os.path.exists(iconPath):
273 self._mainWindow.set_icon(gtk.gdk.pixbuf_new_from_file(iconPath))
275 _moduleLogger.warn("Error: Could not find gonvert icon: %s" % iconPath)
277 self._load_settings()
278 self._mainWindow.show()
280 def _load_settings(self):
281 #Restore window size from previously saved settings if it exists and is valid.
282 windowDatPath = "/".join((constants._data_path_, "window.dat"))
283 if os.path.exists(windowDatPath):
284 saved_window = pickle.load(open(windowDatPath, "r"))
286 a, b = saved_window['size']
290 self._mainWindow.resize(a, b)
292 #Restore selections from previously saved settings if it exists and is valid.
294 selectedCategoryName = unit_data.UNIT_CATEGORIES[0]
295 selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
296 if os.path.exists(selectionsDatPath):
297 selections = pickle.load(open(selectionsDatPath, 'r'))
299 self._defaultUnitForCategory = selections['selected_units']
304 selectedCategoryName = selections['selected_category']
309 categoryIndex = unit_data.UNIT_CATEGORIES.index(selectedCategoryName)
311 _moduleLogger.warn("Unknown category: %s" % selectedCategoryName)
313 self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % selectedCategoryName)
314 self._categoryView.set_cursor(categoryIndex, self._categoryColumn, False)
315 self._categoryView.grab_focus()
317 self._select_default_unit()
319 def _save_settings(self):
321 This routine saves the selections to a file, and
322 should therefore only be called when exiting the program.
324 Update selections dictionary which consists of the following keys:
325 'self._selectedCategoryName': full name of selected category
326 'self._defaultUnitForCategory': self._defaultUnitForCategory dictionary which contains:
327 [categoryname: #1 displayed unit, #2 displayed unit]
329 #Determine the contents of the selected category row
330 selected, iter = self._categoryView.get_selection().get_selected()
331 self._selectedCategoryName = self._categoryModel.get_value(iter, 0)
334 'selected_category': self._selectedCategoryName,
335 'selected_units': self._defaultUnitForCategory
337 selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
338 pickle.dump(selections, open(selectionsDatPath, 'w'))
340 #Get last size of app and save it
342 'size': self._mainWindow.get_size()
344 windowDatPath = "/".join((constants._data_path_, "window.dat"))
345 pickle.dump(window_settings, open(windowDatPath, 'w'))
347 def _clear_find(self):
348 # switch to "new find" state
349 self._find_result = []
352 # Clear our user message
353 self._findLabel.set_text('')
355 def _find_first(self):
356 assert len(self._find_result) == 0
357 assert self._findIndex == 0
358 findString = self._findEntry.get_text().strip().lower()
362 # Gather info on all the matching units from all categories
363 for catIndex, category in enumerate(unit_data.UNIT_CATEGORIES):
364 units = unit_data.get_units(category)
365 for unitIndex, unit in enumerate(units):
366 loweredUnit = unit.lower()
367 if loweredUnit in findString or findString in loweredUnit:
368 self._find_result.append((category, unit, catIndex, unitIndex))
370 def _update_find_selection(self):
371 assert 0 < len(self._find_result)
373 #check if next find is in a new category (prevent category changes when unnecessary
374 searchCategoryName = self._find_result[self._findIndex][0]
375 if self._selectedCategoryName != searchCategoryName:
376 self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % searchCategoryName)
377 self._categoryView.set_cursor(
378 self._find_result[self._findIndex][2], self._categoryColumn, False
381 self._unitsView.set_cursor(
382 self._find_result[self._findIndex][3], self._unitNameColumn, True
385 def _find_next(self):
386 if len(self._find_result) == 0:
389 if self._findIndex == len(self._find_result)-1:
394 if not self._find_result:
395 self._findLabel.set_text('Text not found')
397 self._update_find_selection()
398 resultsLeft = len(self._find_result) - self._findIndex - 1
399 self._findLabel.set_text(
400 '%s result(s) left' % (resultsLeft, )
403 def _find_previous(self):
404 if len(self._find_result) == 0:
407 if self._findIndex == 0:
408 self._findIndex = len(self._find_result)-1
412 if not self._find_result:
413 self._findLabel.set_text('Text not found')
415 self._update_find_selection()
416 resultsLeft = len(self._find_result) - self._findIndex - 1
417 self._findLabel.set_text(
418 '%s result(s) left' % (resultsLeft, )
421 def _toggle_find(self):
422 if self._searchLayout.get_property("visible"):
423 self._searchLayout.hide()
424 self._unitsView.grab_focus()
426 self._searchLayout.show()
427 self._findEntry.grab_focus()
429 def _unit_model_cmp(self, sortedModel, leftItr, rightItr):
430 leftUnitText = self._unitModel.get_value(leftItr, self.UNITS_NAME_IDX)
431 rightUnitText = self._unitModel.get_value(rightItr, self.UNITS_NAME_IDX)
432 return cmp(leftUnitText, rightUnitText)
434 def _symbol_model_cmp(self, sortedModel, leftItr, rightItr):
435 leftSymbolText = self._unitModel.get_value(leftItr, self.UNITS_SYMBOL_IDX)
436 rightSymbolText = self._unitModel.get_value(rightItr, self.UNITS_SYMBOL_IDX)
437 return cmp(leftSymbolText, rightSymbolText)
439 def _value_model_cmp(self, sortedModel, leftItr, rightItr):
440 #special sorting exceptions for ascii values (instead of float values)
441 if self._selectedCategoryName == "Computer Numbers":
442 leftValue = self._unitModel.get_value(leftItr, self.UNITS_VALUE_IDX)
443 rightValue = self._unitModel.get_value(rightItr, self.UNITS_VALUE_IDX)
445 leftValueText = self._unitModel.get_value(leftItr, self.UNITS_VALUE_IDX)
446 leftValue = float(leftValueText) if leftValueText else 0.0
448 rightValueText = self._unitModel.get_value(rightItr, self.UNITS_VALUE_IDX)
449 rightValue = float(rightValueText) if rightValueText else 0.0
450 return cmp(leftValue, rightValue)
452 def _get_column_sort_stuff(self):
454 (self._unitNameColumn, "_unit_sort_direction", self._unit_model_cmp),
455 (self._unitIntegerColumn, "_value_sort_direction", self._value_model_cmp),
456 (self._unitFractionalColumn, "_value_sort_direction", self._value_model_cmp),
457 (self._unitSymbolColumn, "_units_sort_direction", self._symbol_model_cmp),
461 def _switch_category(self, category):
462 self._selectedCategoryName = category
463 self._unitDataInCategory = unit_data.UNIT_DESCRIPTIONS[self._selectedCategoryName]
465 #Fill up the units descriptions and clear the value cells
466 self._clear_visible_unit_data()
467 for key in unit_data.get_units(self._selectedCategoryName):
468 row = key, '0.0', self._unitDataInCategory[key][1], '0.', '0'
469 self._unitModel.append(row)
470 self._sortedUnitModel.sort_column_changed()
472 self._select_default_unit()
474 def _clear_visible_unit_data(self):
475 self._unitDescription.get_buffer().set_text("")
476 self._unitName.set_text('')
477 self._unitValue.set_text('')
478 self._unitSymbol.set_text('')
480 self._previousUnitName.set_text('')
481 self._previousUnitValue.set_text('')
482 self._previousUnitSymbol.set_text('')
484 self._unitModel.clear()
486 def _select_default_unit(self):
487 # Restore the previous historical settings of previously selected units
488 # in this newly selected category
489 defaultPrimary = unit_data.get_base_unit(self._selectedCategoryName)
490 defaultSecondary = ""
491 if self._selectedCategoryName in self._defaultUnitForCategory:
492 if self._defaultUnitForCategory[self._selectedCategoryName][0]:
493 defaultPrimary = self._defaultUnitForCategory[self._selectedCategoryName][0]
494 if self._defaultUnitForCategory[self._selectedCategoryName][1]:
495 defaultSecondary = self._defaultUnitForCategory[self._selectedCategoryName][1]
497 units = unit_data.get_units(self._selectedCategoryName)
499 #Restore oldest selection first.
502 unitIndex = units.index(defaultPrimary)
505 self._unitsView.set_cursor(unitIndex, self._unitNameColumn, True)
507 #Restore newest selection second.
510 unitIndex = units.index(defaultSecondary)
513 self._unitsView.set_cursor(unitIndex, self._unitNameColumn, True)
515 # select the text so user can start typing right away
516 self._unitValue.grab_focus()
517 self._unitValue.select_region(0, -1)
519 def _sanitize_value(self, userEntry):
520 if self._selectedCategoryName == "Computer Numbers":
529 value = float(userEntry)
532 def _on_key_press(self, widget, event, *args):
534 @note Hildon specific
536 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
539 event.keyval == gtk.keysyms.F6 or
540 event.keyval in RETURN_TYPES and event.get_state() & gtk.gdk.CONTROL_MASK
542 if self._isFullScreen:
543 self._mainWindow.unfullscreen()
545 self._mainWindow.fullscreen()
546 elif event.keyval == gtk.keysyms.f and event.get_state() & gtk.gdk.CONTROL_MASK:
548 elif event.keyval == gtk.keysyms.p and event.get_state() & gtk.gdk.CONTROL_MASK:
549 self._find_previous()
550 elif event.keyval == gtk.keysyms.n and event.get_state() & gtk.gdk.CONTROL_MASK:
553 _moduleLogger.exception("_on_key_press")
555 def _on_window_state_change(self, widget, event, *args):
557 @note Hildon specific
560 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
561 self._isFullScreen = True
563 self._isFullScreen = False
565 _moduleLogger.exception("_on_window_state_change")
567 def _on_findEntry_changed(self, *args):
569 Clear out find results since the user wants to look for something new
574 _moduleLogger.exception("_on_findEntry_changed")
576 def _on_find_activate(self, *args):
579 self._findButton.grab_focus()
581 _moduleLogger.exception("_on_find_activate")
583 def _on_click_unit_column(self, col):
585 Sort the contents of the col when the user clicks on the title.
588 #Determine which column requires sorting
589 columns = self._get_column_sort_stuff()
590 for columnIndex, (maybeCol, directionName, col_cmp) in enumerate(columns):
592 direction = getattr(self, directionName)
593 gtkDirection = gtk.SORT_ASCENDING if direction else gtk.SORT_DESCENDING
596 self._sortedUnitModel.set_sort_column_id(columnIndex, gtkDirection)
598 # set the visual for sorting
599 col.set_sort_indicator(True)
600 col.set_sort_order(not direction)
602 setattr(self, directionName, not direction)
605 maybeCol.set_sort_indicator(False)
607 assert False, "Unknown column: %s" % (col.get_title(), )
609 _moduleLogger.exception("_on_click_unit_column")
611 def _on_category_selector_clicked(self, *args):
613 currenntIndex = unit_data.UNIT_CATEGORIES.index(self._selectedCategoryName)
614 newIndex = hildonize.touch_selector(
617 unit_data.UNIT_CATEGORIES,
621 selectedCategoryName = unit_data.UNIT_CATEGORIES[newIndex]
622 self._categorySelectionButton.set_label(selectedCategoryName)
623 self._categoryView.set_cursor(newIndex, self._categoryColumn, False)
624 self._categoryView.grab_focus()
626 _moduleLogger.exception("_on_category_selector_clicked")
628 def _on_click_category(self, *args):
630 selected, iter = self._categoryView.get_selection().get_selected()
632 # User is typing in an invalid string, not selecting any category
634 selectedCategory = self._categoryModel.get_value(iter, 0)
635 self._switch_category(selectedCategory)
637 _moduleLogger.exception("_on_click_category")
639 def _on_click_unit(self, *args):
641 selected, iter = self._unitsView.get_selection().get_selected()
642 selected_unit = selected.get_value(iter, self.UNITS_NAME_IDX)
643 unit_spec = self._unitDataInCategory[selected_unit]
647 if self._unitName.get_text() != selected_unit:
648 self._previousUnitName.set_text(self._unitName.get_text())
649 self._previousUnitValue.set_text(self._unitValue.get_text())
650 self._previousUnitSymbol.set_text(self._unitSymbol.get_text())
651 if self._unitSymbol.get_text():
654 self._unitName.set_text(selected_unit)
655 self._unitValue.set_text(selected.get_value(iter, self.UNITS_VALUE_IDX))
656 buffer = self._unitDescription.get_buffer()
657 buffer.set_text(unit_spec[2])
658 self._unitSymbol.set_text(unit_spec[1]) # put units into label text
665 self._unitSymbol.show()
666 self._previousUnitSymbol.show()
668 self._unitSymbol.hide()
669 self._previousUnitSymbol.hide()
671 if self._unitValue.get_text() == '':
672 if self._selectedCategoryName == "Computer Numbers":
673 self._unitValue.set_text("0")
675 self._unitValue.set_text("0.0")
677 self._defaultUnitForCategory[self._selectedCategoryName] = [
678 self._unitName.get_text(), self._previousUnitName.get_text()
681 # select the text so user can start typing right away
682 self._unitValue.grab_focus()
683 self._unitValue.select_region(0, -1)
685 _moduleLogger.exception("_on_click_unit")
687 def _on_unit_value_changed(self, *args):
689 if self._unitName.get_text() == '':
691 if not self._unitValue.is_focus():
694 #retrieve the conversion function and value from the selected unit
695 value = self._sanitize_value(self._unitValue.get_text())
696 func, arg = self._unitDataInCategory[self._unitName.get_text()][0]
697 base = func.to_base(value, arg)
699 #point to the first row
700 for row in self._unitModel:
701 func, arg = self._unitDataInCategory[row[self.UNITS_NAME_IDX]][0]
702 newValue = func.from_base(base, arg)
704 newValueDisplay = str(newValue)
705 integerDisplay, fractionalDisplay = split_number(newValue)
707 row[self.UNITS_VALUE_IDX] = newValueDisplay
708 row[self.UNITS_INTEGER_IDX] = integerDisplay
709 row[self.UNITS_FRACTION_IDX] = fractionalDisplay
711 # Update the secondary unit entry
712 if self._previousUnitName.get_text() != '':
713 func, arg = self._unitDataInCategory[self._previousUnitName.get_text()][0]
714 self._previousUnitValue.set_text(str(func.from_base(base, arg, )))
716 self._sortedUnitModel.sort_column_changed()
718 _moduleLogger.exception("_on_unit_value_changed")
720 def _on_previous_unit_value_changed(self, *args):
722 if self._previousUnitName.get_text() == '':
724 if not self._previousUnitValue.is_focus():
727 #retrieve the conversion function and value from the selected unit
728 value = self._sanitize_value(self._previousUnitValue.get_text())
729 func, arg = self._unitDataInCategory[self._previousUnitName.get_text()][0]
730 base = func.to_base(value, arg)
732 #point to the first row
733 for row in self._unitModel:
734 func, arg = self._unitDataInCategory[row[self.UNITS_NAME_IDX]][0]
735 newValue = func.from_base(base, arg)
737 newValueDisplay = str(newValue)
738 integerDisplay, fractionalDisplay = split_number(newValue)
740 row[self.UNITS_VALUE_IDX] = newValueDisplay
741 row[self.UNITS_INTEGER_IDX] = integerDisplay
742 row[self.UNITS_FRACTION_IDX] = fractionalDisplay
744 # Update the primary unit entry
745 func, arg = self._unitDataInCategory[self._unitName.get_text()][0]
746 self._unitValue.set_text(str(func.from_base(base, arg, )))
748 self._sortedUnitModel.sort_column_changed()
750 _moduleLogger.exception("_on_previous_unit_value_changed")
752 def _on_about_clicked(self, a):
753 dlg = gtk.AboutDialog()
754 dlg.set_name(constants.__pretty_app_name__)
755 dlg.set_version("%s-%d" % (constants.__version__, constants.__build__))
756 dlg.set_copyright("Copyright 2009 - GPL")
758 dlg.set_website("http://unihedron.com/projects/gonvert/gonvert.php")
759 dlg.set_authors(["Anthony Tekatch <anthony@unihedron.com>", "Ed Page <edpage@byu.net>"])
763 def _on_user_exit(self, *args):
765 self._save_settings()
767 _moduleLogger.exception("_on_user_exit")
773 gtk.gdk.threads_init()
774 if hildonize.IS_HILDON_SUPPORTED:
775 gtk.set_application_name(constants.__pretty_app_name__)
777 if not PROFILE_STARTUP:
781 if __name__ == "__main__":
782 logging.basicConfig(level = logging.DEBUG)
784 os.makedirs(constants._data_path_)