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
40 _moduleLogger = logging.getLogger("gonvert_glade")
41 PROFILE_STARTUP = False
42 FORCE_HILDON_LIKE = True
44 if gettext is not None:
45 gettext.bindtextdomain('gonvert', '/usr/share/locale')
46 gettext.textdomain('gonvert')
49 def change_menu_label(widgets, labelname, newtext):
50 item_label = widgets.get_widget(labelname).get_children()[0]
51 item_label.set_text(newtext)
54 class Gonvert(object):
57 os.path.join(os.path.dirname(__file__), "gonvert.glade"),
58 os.path.join(os.path.dirname(__file__), "../data/gonvert.glade"),
59 os.path.join(os.path.dirname(__file__), "../lib/gonvert.glade"),
60 '/usr/share/gonvert/gonvert.glade',
61 '/usr/lib/gonvert/gonvert.glade',
69 self._unitDataInCategory = None
70 self._unit_sort_direction = False
71 self._value_sort_direction = False
72 self._units_sort_direction = False
73 self._isFullScreen = False
75 self._find_result = [] # empty find result list
76 self._findIndex = 0 # default to find result number zero
78 self._selectedCategoryName = '' # preset to no selected category
79 self._defaultUnitForCategory = {} # empty dictionary for later use
81 #check to see if glade file is in current directory (user must be
82 # running from download untar directory)
83 for gladePath in self._glade_files:
84 if os.path.isfile(gladePath):
85 homepath = os.path.dirname(gladePath)
86 pixmapspath = "/".join((homepath, "pixmaps"))
87 widgets = gtk.glade.XML(gladePath)
90 _moduleLogger.error("UI Descriptor not found!")
94 self._mainWindow = widgets.get_widget('mainWindow')
95 self._app = hildonize.get_app_class()()
96 self._mainWindow = hildonize.hildonize_window(self._app, self._mainWindow)
98 change_menu_label(widgets, 'fileMenuItem', _('File'))
99 change_menu_label(widgets, 'exitMenuItem', _('Exit'))
100 change_menu_label(widgets, 'toolsMenuItem', _('Tools'))
101 change_menu_label(widgets, 'clearSelectionMenuItem', _('Clear selections'))
102 change_menu_label(widgets, 'helpMenuItem', _('Help'))
103 change_menu_label(widgets, 'aboutMenuItem', _('About'))
104 change_menu_label(widgets, 'findButton', _('Find'))
106 self._shortlistcheck = widgets.get_widget('shortlistcheck')
107 self._toggleShortList = widgets.get_widget('toggleShortList')
109 self._categorySelectionButton = widgets.get_widget("categorySelectionButton")
110 self._categoryView = widgets.get_widget('categoryView')
112 self._unitsView = widgets.get_widget('unitsView')
113 self._unitsView.set_property('rules_hint', 1)
114 self._unitsView_selection = self._unitsView.get_selection()
116 self._unitName = widgets.get_widget('unitName')
117 self._unitValue = widgets.get_widget('unitValue')
118 self._previousUnitName = widgets.get_widget('previousUnitName')
119 self._previousUnitValue = widgets.get_widget('previousUnitValue')
121 self._unitSymbol = widgets.get_widget('unitSymbol')
122 self._previousUnitSymbol = widgets.get_widget('previousUnitSymbol')
124 self._unitDescription = widgets.get_widget('unitDescription')
126 self._searchLayout = widgets.get_widget('searchLayout')
127 self._searchLayout.hide()
128 self._findEntry = widgets.get_widget('findEntry')
129 self._findLabel = widgets.get_widget('findLabel')
130 self._findButton = widgets.get_widget('findButton')
132 #insert a self._categoryColumnumn into the units list even though the heading will not be seen
133 renderer = gtk.CellRendererText()
134 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
135 renderer.set_property("width-chars", len("grams per cubic cm plus some"))
136 hildonize.set_cell_thumb_selectable(renderer)
137 self._unitNameColumn = gtk.TreeViewColumn(_('Name'), renderer)
138 self._unitNameColumn.set_property('resizable', 1)
139 self._unitNameColumn.add_attribute(renderer, 'text', self.UNITS_NAME_IDX)
140 self._unitNameColumn.set_clickable(True)
141 self._unitNameColumn.connect("clicked", self._on_click_unit_column)
142 self._unitsView.append_column(self._unitNameColumn)
144 renderer = gtk.CellRendererText()
145 hildonize.set_cell_thumb_selectable(renderer)
146 self._unitValueColumn = gtk.TreeViewColumn(_('Value'), renderer)
147 self._unitValueColumn.set_property('resizable', 1)
148 self._unitValueColumn.add_attribute(renderer, 'text', self.UNITS_VALUE_IDX)
149 self._unitValueColumn.set_clickable(True)
150 self._unitValueColumn.connect("clicked", self._on_click_unit_column)
151 self._unitsView.append_column(self._unitValueColumn)
153 renderer = gtk.CellRendererText()
154 renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
155 renderer.set_property("width-chars", len("G ohm plus some"))
156 hildonize.set_cell_thumb_selectable(renderer)
157 self._unitSymbolColumn = gtk.TreeViewColumn(_('Units'), renderer)
158 self._unitSymbolColumn.set_property('resizable', 1)
159 self._unitSymbolColumn.add_attribute(renderer, 'text', self.UNITS_SYMBOL_IDX)
160 self._unitSymbolColumn.set_clickable(True)
161 self._unitSymbolColumn.connect("clicked", self._on_click_unit_column)
162 self._unitsView.append_column(self._unitSymbolColumn)
164 self._unitModel = gtk.ListStore(
165 gobject.TYPE_STRING, # UNITS_NAME_IDX
166 gobject.TYPE_STRING, # UNITS_VALUE_IDX
167 gobject.TYPE_STRING, # UNITS_SYMBOL_IDX
169 self._sortedUnitModel = gtk.TreeModelSort(self._unitModel)
170 columns = self._get_column_sort_stuff()
171 for columnIndex, (column, sortDirection, col_cmp) in enumerate(columns):
172 self._sortedUnitModel.set_sort_func(columnIndex, col_cmp)
173 self._unitsView.set_model(self._sortedUnitModel)
175 #Insert a column into the category list even though the heading will not be seen
176 renderer = gtk.CellRendererText()
177 self._categoryColumn = gtk.TreeViewColumn('Title', renderer)
178 self._categoryColumn.set_property('resizable', 1)
179 self._categoryColumn.add_attribute(renderer, 'text', 0)
180 self._categoryView.append_column(self._categoryColumn)
182 self._categoryModel = gtk.ListStore(gobject.TYPE_STRING)
183 self._categoryView.set_model(self._categoryModel)
184 #colourize each row differently for easier reading
185 self._categoryView.set_property('rules_hint', 1)
187 #Populate the catagories list
188 for key in unit_data.UNIT_CATEGORIES:
190 self._categoryModel.append(row)
192 #--------- connections to GUI ----------------
193 self._mainWindow.connect("delete-event", self._on_user_exit)
194 self._mainWindow.connect("key-press-event", self._on_key_press)
195 self._mainWindow.connect("window-state-event", self._on_window_state_change)
196 self._categorySelectionButton.connect("clicked", self._on_category_selector_clicked)
197 self._categoryView.connect("cursor-changed", self._on_click_category)
198 self._findButton.connect("clicked", self._on_find_activate)
199 self._findEntry.connect("activate", self._on_find_activate)
200 self._findEntry.connect("changed", self._on_findEntry_changed)
201 self._previousUnitValue.connect("changed", self._on_previous_unit_value_changed)
202 self._shortlistcheck.connect("toggled", self._on_shortlist_changed)
203 self._unitValue.connect("changed", self._on_unit_value_changed)
204 self._unitsView.connect("cursor-changed", self._on_click_unit)
205 if hildonize.GTK_MENU_USED:
206 widgets.get_widget("aboutMenuItem").connect("activate", self._on_about_clicked)
207 widgets.get_widget("clearSelectionMenuItem").connect("activate", self._on_user_clear_selections)
208 widgets.get_widget("editShortListMenuItem").connect("activate", self._on_edit_shortlist)
209 widgets.get_widget("exitMenuItem").connect("activate", self._on_user_exit)
211 for scrollingWidgetName in (
212 "unitsViewScrolledWindow",
214 scrollingWidget = widgets.get_widget(scrollingWidgetName)
215 assert scrollingWidget is not None, scrollingWidgetName
216 hildonize.hildonize_scrollwindow_with_viewport(scrollingWidget)
218 if hildonize.IS_HILDON_SUPPORTED or FORCE_HILDON_LIKE:
219 self._categoryView.get_parent().hide()
220 self._unitsView.set_headers_visible(False)
221 self._previousUnitName.get_parent().hide()
222 self._unitDescription.get_parent().get_parent().hide()
224 self._categorySelectionButton.hide()
226 replacementButtons = []
227 menu = hildonize.hildonize_menu(
229 widgets.get_widget("mainMenuBar"),
233 if not hildonize.IS_HILDON_SUPPORTED:
234 _moduleLogger.info("No hildonization support")
236 hildonize.set_application_title(
237 self._mainWindow, "%s - Unit Conversion Utility" % constants.__pretty_app_name__
239 iconPath = pixmapspath + '/gonvert.png'
240 if os.path.exists(iconPath):
241 self._mainWindow.set_icon(gtk.gdk.pixbuf_new_from_file(iconPath))
243 _moduleLogger.warn("Error: Could not find gonvert icon: %s" % iconPath)
245 self._load_settings()
246 self._mainWindow.show()
248 def _load_settings(self):
249 #Restore window size from previously saved settings if it exists and is valid.
250 windowDatPath = "/".join((constants._data_path_, "window.dat"))
251 if os.path.exists(windowDatPath):
252 saved_window = pickle.load(open(windowDatPath, "r"))
254 a, b = saved_window['size']
258 self._mainWindow.resize(a, b)
260 #Restore selections from previously saved settings if it exists and is valid.
262 selectedCategoryName = unit_data.UNIT_CATEGORIES[0]
263 selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
264 if os.path.exists(selectionsDatPath):
265 selections = pickle.load(open(selectionsDatPath, 'r'))
267 self._defaultUnitForCategory = selections['selected_units']
272 selectedCategoryName = selections['selected_category']
277 categoryIndex = unit_data.UNIT_CATEGORIES.index(selectedCategoryName)
279 _moduleLogger.warn("Unknown category: %s" % selectedCategoryName)
281 self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % selectedCategoryName)
282 self._categoryView.set_cursor(categoryIndex, self._categoryColumn, False)
283 self._categoryView.grab_focus()
285 self._select_default_unit()
287 def _save_settings(self):
289 This routine saves the selections to a file, and
290 should therefore only be called when exiting the program.
292 Update selections dictionary which consists of the following keys:
293 'self._selectedCategoryName': full name of selected category
294 'self._defaultUnitForCategory': self._defaultUnitForCategory dictionary which contains:
295 [categoryname: #1 displayed unit, #2 displayed unit]
297 #Determine the contents of the selected category row
298 selected, iter = self._categoryView.get_selection().get_selected()
299 self._selectedCategoryName = self._categoryModel.get_value(iter, 0)
302 'selected_category': self._selectedCategoryName,
303 'selected_units': self._defaultUnitForCategory
305 selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
306 pickle.dump(selections, open(selectionsDatPath, 'w'))
308 #Get last size of app and save it
310 'size': self._mainWindow.get_size()
312 windowDatPath = "/".join((constants._data_path_, "window.dat"))
313 pickle.dump(window_settings, open(windowDatPath, 'w'))
315 def _clear_find(self):
316 # switch to "new find" state
317 self._find_result = []
320 # Clear our user message
321 self._findLabel.set_text('')
323 def _find_first(self):
324 assert len(self._find_result) == 0
325 assert self._findIndex == 0
326 findString = self._findEntry.get_text().strip().lower()
330 # Gather info on all the matching units from all categories
331 for catIndex, category in enumerate(unit_data.UNIT_CATEGORIES):
332 units = unit_data.get_units(category)
333 for unitIndex, unit in enumerate(units):
334 loweredUnit = unit.lower()
335 if loweredUnit in findString or findString in loweredUnit:
336 self._find_result.append((category, unit, catIndex, unitIndex))
338 def _update_find_selection(self):
339 assert 0 < len(self._find_result)
341 #check if next find is in a new category (prevent category changes when unnecessary
342 searchCategoryName = self._find_result[self._findIndex][0]
343 if self._selectedCategoryName != searchCategoryName:
344 self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % searchCategoryName)
345 self._categoryView.set_cursor(
346 self._find_result[self._findIndex][2], self._categoryColumn, False
349 self._unitsView.set_cursor(
350 self._find_result[self._findIndex][3], self._unitNameColumn, True
353 def _find_next(self):
354 if len(self._find_result) == 0:
357 if self._findIndex == len(self._find_result)-1:
362 if not self._find_result:
363 self._findLabel.set_text('Text not found')
365 self._update_find_selection()
366 resultsLeft = len(self._find_result) - self._findIndex - 1
367 self._findLabel.set_text(
368 '%s result(s) left' % (resultsLeft, )
371 def _find_previous(self):
372 if len(self._find_result) == 0:
375 if self._findIndex == 0:
376 self._findIndex = len(self._find_result)-1
380 if not self._find_result:
381 self._findLabel.set_text('Text not found')
383 self._update_find_selection()
384 resultsLeft = len(self._find_result) - self._findIndex - 1
385 self._findLabel.set_text(
386 '%s result(s) left' % (resultsLeft, )
389 def _toggle_find(self):
390 if self._searchLayout.get_property("visible"):
391 self._searchLayout.hide()
392 self._unitsView.grab_focus()
394 self._searchLayout.show()
395 self._findEntry.grab_focus()
397 def _unit_model_cmp(self, sortedModel, leftItr, rightItr):
398 leftUnitText = self._unitModel.get_value(leftItr, 0)
399 rightUnitText = self._unitModel.get_value(rightItr, 0)
400 return cmp(leftUnitText, rightUnitText)
402 def _symbol_model_cmp(self, sortedModel, leftItr, rightItr):
403 leftSymbolText = self._unitModel.get_value(leftItr, 2)
404 rightSymbolText = self._unitModel.get_value(rightItr, 2)
405 return cmp(leftSymbolText, rightSymbolText)
407 def _value_model_cmp(self, sortedModel, leftItr, rightItr):
408 #special sorting exceptions for ascii values (instead of float values)
409 if self._selectedCategoryName == "Computer Numbers":
410 leftValue = self._unitModel.get_value(leftItr, 1)
411 rightValue = self._unitModel.get_value(rightItr, 1)
413 leftValueText = self._unitModel.get_value(leftItr, 1)
414 leftValue = float(leftValueText) if leftValueText else 0.0
416 rightValueText = self._unitModel.get_value(rightItr, 1)
417 rightValue = float(rightValueText) if rightValueText else 0.0
418 return cmp(leftValue, rightValue)
420 def _get_column_sort_stuff(self):
422 (self._unitNameColumn, "_unit_sort_direction", self._unit_model_cmp),
423 (self._unitValueColumn, "_value_sort_direction", self._value_model_cmp),
424 (self._unitSymbolColumn, "_units_sort_direction", self._symbol_model_cmp),
428 def _switch_category(self, category):
429 self._selectedCategoryName = category
430 self._unitDataInCategory = unit_data.UNIT_DESCRIPTIONS[self._selectedCategoryName]
432 #Fill up the units descriptions and clear the value cells
433 self._clear_visible_unit_data()
434 for key in unit_data.get_units(self._selectedCategoryName):
435 iter = self._unitModel.append()
436 self._unitModel.set(iter, 0, key, 1, '', 2, self._unitDataInCategory[key][1])
437 self._sortedUnitModel.sort_column_changed()
439 self._select_default_unit()
441 def _clear_visible_unit_data(self):
442 self._unitDescription.get_buffer().set_text("")
443 self._unitName.set_text('')
444 self._unitValue.set_text('')
445 self._unitSymbol.set_text('')
447 self._previousUnitName.set_text('')
448 self._previousUnitValue.set_text('')
449 self._previousUnitSymbol.set_text('')
451 self._unitModel.clear()
453 def _select_default_unit(self):
454 # Restore the previous historical settings of previously selected units
455 # in this newly selected category
456 defaultPrimary = unit_data.get_base_unit(self._selectedCategoryName)
457 defaultSecondary = ""
458 if self._selectedCategoryName in self._defaultUnitForCategory:
459 if self._defaultUnitForCategory[self._selectedCategoryName][0]:
460 defaultPrimary = self._defaultUnitForCategory[self._selectedCategoryName][0]
461 if self._defaultUnitForCategory[self._selectedCategoryName][1]:
462 defaultSecondary = self._defaultUnitForCategory[self._selectedCategoryName][1]
464 units = unit_data.get_units(self._selectedCategoryName)
466 #Restore oldest selection first.
469 unitIndex = units.index(defaultPrimary)
472 self._unitsView.set_cursor(unitIndex, self._unitNameColumn, True)
474 #Restore newest selection second.
477 unitIndex = units.index(defaultSecondary)
480 self._unitsView.set_cursor(unitIndex, self._unitNameColumn, True)
482 # select the text so user can start typing right away
483 self._unitValue.grab_focus()
484 self._unitValue.select_region(0, -1)
486 def _sanitize_value(self, userEntry):
487 if self._selectedCategoryName == "Computer Numbers":
496 value = float(userEntry)
499 def _on_shortlist_changed(self, *args):
501 raise NotImplementedError("%s" % self._shortlistcheck.get_active())
503 _moduleLogger.exception("_on_shortlist_changed")
505 def _on_edit_shortlist(self, *args):
507 raise NotImplementedError("%s" % self._toggleShortList.get_active())
509 _moduleLogger.exception("_on_edit_shortlist")
511 def _on_user_clear_selections(self, *args):
513 selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
514 os.remove(selectionsDatPath)
515 self._defaultUnitForCategory = {}
517 _moduleLogger.exception("_on_user_clear_selections")
519 def _on_key_press(self, widget, event, *args):
521 @note Hildon specific
523 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
526 event.keyval == gtk.keysyms.F6 or
527 event.keyval in RETURN_TYPES and event.get_state() & gtk.gdk.CONTROL_MASK
529 if self._isFullScreen:
530 self._mainWindow.unfullscreen()
532 self._mainWindow.fullscreen()
533 elif event.keyval == gtk.keysyms.f and event.get_state() & gtk.gdk.CONTROL_MASK:
535 elif event.keyval == gtk.keysyms.p and event.get_state() & gtk.gdk.CONTROL_MASK:
536 self._find_previous()
537 elif event.keyval == gtk.keysyms.n and event.get_state() & gtk.gdk.CONTROL_MASK:
540 _moduleLogger.exception("_on_key_press")
542 def _on_window_state_change(self, widget, event, *args):
544 @note Hildon specific
547 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
548 self._isFullScreen = True
550 self._isFullScreen = False
552 _moduleLogger.exception("_on_window_state_change")
554 def _on_findEntry_changed(self, *args):
556 Clear out find results since the user wants to look for something new
561 _moduleLogger.exception("_on_findEntry_changed")
563 def _on_find_activate(self, *args):
566 self._findButton.grab_focus()
568 _moduleLogger.exception("_on_find_activate")
570 def _on_click_unit_column(self, col):
572 Sort the contents of the col when the user clicks on the title.
575 #Determine which column requires sorting
576 columns = self._get_column_sort_stuff()
577 for columnIndex, (maybeCol, directionName, col_cmp) in enumerate(columns):
579 direction = getattr(self, directionName)
580 gtkDirection = gtk.SORT_ASCENDING if direction else gtk.SORT_DESCENDING
583 self._sortedUnitModel.set_sort_column_id(columnIndex, gtkDirection)
585 # set the visual for sorting
586 col.set_sort_indicator(True)
587 col.set_sort_order(not direction)
589 setattr(self, directionName, not direction)
592 maybeCol.set_sort_indicator(False)
594 assert False, "Unknown column: %s" % (col.get_title(), )
596 _moduleLogger.exception("_on_click_unit_column")
598 def _on_category_selector_clicked(self, *args):
600 currenntIndex = unit_data.UNIT_CATEGORIES.index(self._selectedCategoryName)
601 newIndex = hildonize.touch_selector(
604 unit_data.UNIT_CATEGORIES,
608 selectedCategoryName = unit_data.UNIT_CATEGORIES[newIndex]
609 self._categorySelectionButton.set_label(selectedCategoryName)
610 self._categoryView.set_cursor(newIndex, self._categoryColumn, False)
611 self._categoryView.grab_focus()
613 _moduleLogger.exception("_on_category_selector_clicked")
615 def _on_click_category(self, *args):
617 selected, iter = self._categoryView.get_selection().get_selected()
619 # User is typing in an invalid string, not selecting any category
621 selectedCategory = self._categoryModel.get_value(iter, 0)
622 self._switch_category(selectedCategory)
624 _moduleLogger.exception("_on_click_category")
626 def _on_click_unit(self, *args):
628 selected, iter = self._unitsView.get_selection().get_selected()
629 selected_unit = selected.get_value(iter, 0)
630 unit_spec = self._unitDataInCategory[selected_unit]
634 if self._unitName.get_text() != selected_unit:
635 self._previousUnitName.set_text(self._unitName.get_text())
636 self._previousUnitValue.set_text(self._unitValue.get_text())
637 self._previousUnitSymbol.set_text(self._unitSymbol.get_text())
638 if self._unitSymbol.get_text():
641 self._unitName.set_text(selected_unit)
642 self._unitValue.set_text(selected.get_value(iter, 1))
643 buffer = self._unitDescription.get_buffer()
644 buffer.set_text(unit_spec[2])
645 self._unitSymbol.set_text(unit_spec[1]) # put units into label text
652 self._unitSymbol.show()
653 self._previousUnitSymbol.show()
655 self._unitSymbol.hide()
656 self._previousUnitSymbol.hide()
658 if self._unitValue.get_text() == '':
659 if self._selectedCategoryName == "Computer Numbers":
660 self._unitValue.set_text("0")
662 self._unitValue.set_text("0.0")
664 self._defaultUnitForCategory[self._selectedCategoryName] = [
665 self._unitName.get_text(), self._previousUnitName.get_text()
668 # select the text so user can start typing right away
669 self._unitValue.grab_focus()
670 self._unitValue.select_region(0, -1)
672 _moduleLogger.exception("_on_click_unit")
674 def _on_unit_value_changed(self, *args):
676 if self._unitName.get_text() == '':
678 if not self._unitValue.is_focus():
681 #retrieve the conversion function and value from the selected unit
682 value = self._sanitize_value(self._unitValue.get_text())
683 func, arg = self._unitDataInCategory[self._unitName.get_text()][0]
684 base = func.to_base(value, arg)
686 #point to the first row
687 for row in self._unitModel:
688 func, arg = self._unitDataInCategory[row[0]][0]
689 row[1] = str(func.from_base(base, arg))
691 # Update the secondary unit entry
692 if self._previousUnitName.get_text() != '':
693 func, arg = self._unitDataInCategory[self._previousUnitName.get_text()][0]
694 self._previousUnitValue.set_text(str(func.from_base(base, arg, )))
696 _moduleLogger.exception("_on_unit_value_changed")
698 def _on_previous_unit_value_changed(self, *args):
700 if self._previousUnitName.get_text() == '':
702 if not self._previousUnitValue.is_focus():
705 #retrieve the conversion function and value from the selected unit
706 value = self._sanitize_value(self._previousUnitValue.get_text())
707 func, arg = self._unitDataInCategory[self._previousUnitName.get_text()][0]
708 base = func.to_base(value, arg)
710 #point to the first row
711 for row in self._unitModel:
712 func, arg = self._unitDataInCategory[row[0]][0]
713 row[1] = str(func.from_base(base, arg))
715 # Update the primary unit entry
716 func, arg = self._unitDataInCategory[self._unitName.get_text()][0]
717 self._unitValue.set_text(str(func.from_base(base, arg, )))
719 _moduleLogger.exception("_on_previous_unit_value_changed")
721 def _on_about_clicked(self, a):
722 dlg = gtk.AboutDialog()
723 dlg.set_name(constants.__pretty_app_name__)
724 dlg.set_version("%s-%d" % (constants.__version__, constants.__build__))
725 dlg.set_copyright("Copyright 2009 - GPL")
727 dlg.set_website("http://unihedron.com/projects/gonvert/gonvert.php")
728 dlg.set_authors(["Anthony Tekatch <anthony@unihedron.com>", "Ed Page <edpage@byu.net>"])
732 def _on_user_exit(self, *args):
734 self._save_settings()
736 _moduleLogger.exception("_on_user_exit")
742 gtk.gdk.threads_init()
743 if hildonize.IS_HILDON_SUPPORTED:
744 gtk.set_application_name(constants.__pretty_app_name__)
746 if not PROFILE_STARTUP:
750 if __name__ == "__main__":
751 logging.basicConfig(level = logging.DEBUG)
753 os.makedirs(constants._data_path_)