+++ /dev/null
-<?xml version="1.0"?>
-<glade-interface>
- <!-- interface-requires gtk+ 2.16 -->
- <!-- interface-naming-policy toplevel-contextual -->
- <widget class="GtkWindow" id="mainWindow">
- <property name="title" translatable="yes">Gonvert</property>
- <child>
- <widget class="GtkVBox" id="mainLayout">
- <property name="visible">True</property>
- <child>
- <widget class="GtkMenuBar" id="mainMenuBar">
- <property name="visible">True</property>
- <child>
- <widget class="GtkMenuItem" id="fileMenuItem">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_File</property>
- <property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="fileMenu">
- <child>
- <widget class="GtkMenuItem" id="exitMenuItem">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Exit</property>
- <property name="use_underline">True</property>
- <accelerator key="q" signal="activate" modifiers="GDK_CONTROL_MASK"/>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkMenuItem" id="editMenuItem">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Edit</property>
- <property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="menu1">
- <property name="visible">True</property>
- <child>
- <widget class="GtkImageMenuItem" id="searchMenuItem">
- <property name="label">gtk-find</property>
- <property name="visible">True</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- <child>
- <widget class="GtkMenuItem" id="helpMenuItem">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_Help</property>
- <property name="use_underline">True</property>
- <child>
- <widget class="GtkMenu" id="helpMenu">
- <child>
- <widget class="GtkMenuItem" id="aboutMenuItem">
- <property name="visible">True</property>
- <property name="label" translatable="yes">_About</property>
- <property name="use_underline">True</property>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="actionAreaLayout">
- <property name="visible">True</property>
- <child>
- <widget class="GtkScrolledWindow" id="categoryScrolledWindow">
- <property name="width_request">260</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <widget class="GtkTreeView" id="categoryView">
- <property name="width_request">250</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="headers_visible">False</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="unitConversionLayout">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkButton" id="categorySelectionButton">
- <property name="label" translatable="yes">ERROR</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="focus_on_click">False</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="selectedUnitLayout">
- <property name="visible">True</property>
- <child>
- <widget class="GtkEntry" id="unitName">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="invisible_char">●</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="unitValue">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">●</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="unitSymbol">
- <property name="width_request">60</property>
- <property name="visible">True</property>
- <property name="xalign">0.10000000149011612</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="previousSelectedUnitLayout">
- <property name="visible">True</property>
- <child>
- <widget class="GtkEntry" id="previousUnitName">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="invisible_char">●</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="previousUnitValue">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="invisible_char">●</property>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="previousUnitSymbol">
- <property name="width_request">60</property>
- <property name="visible">True</property>
- <property name="xalign">0.10000000149011612</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkVBox" id="unitsAndDescriptionLayout">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkScrolledWindow" id="unitsViewScrolledWindow">
- <property name="height_request">300</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">never</property>
- <property name="vscrollbar_policy">automatic</property>
- <child>
- <widget class="GtkViewport" id="maemo5HackViewport">
- <property name="visible">True</property>
- <property name="resize_mode">queue</property>
- <child>
- <widget class="GtkVBox" id="maemo5HackVBox">
- <property name="visible">True</property>
- <property name="orientation">vertical</property>
- <child>
- <widget class="GtkTreeView" id="unitsView">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkScrolledWindow" id="unitDescriptionScrolledWindow">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="hscrollbar_policy">automatic</property>
- <property name="vscrollbar_policy">automatic</property>
- <property name="shadow_type">in</property>
- <child>
- <widget class="GtkViewport" id="viewport1">
- <property name="visible">True</property>
- <property name="resize_mode">queue</property>
- <child>
- <widget class="GtkTextView" id="unitDescription">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="editable">False</property>
- <property name="wrap_mode">word</property>
- </widget>
- </child>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- <child>
- <widget class="GtkHBox" id="searchLayout">
- <property name="visible">True</property>
- <child>
- <widget class="GtkButton" id="findButton">
- <property name="label" translatable="yes">gtk-find</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <property name="use_underline">True</property>
- <property name="use_stock">True</property>
- <accelerator key="F6" signal="clicked"/>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <widget class="GtkEntry" id="findEntry">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="tooltip" translatable="yes">Enter unit to find here</property>
- <property name="invisible_char">●</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">1</property>
- </packing>
- </child>
- <child>
- <widget class="GtkLabel" id="findLabel">
- <property name="visible">True</property>
- <property name="label" translatable="yes">Press to find text.</property>
- <property name="justify">center</property>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">2</property>
- </packing>
- </child>
- <child>
- <widget class="GtkButton" id="closeSearchButton">
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">True</property>
- <child>
- <widget class="GtkImage" id="image1">
- <property name="visible">True</property>
- <property name="stock">gtk-close</property>
- <property name="icon-size">1</property>
- </widget>
- </child>
- </widget>
- <packing>
- <property name="position">3</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="expand">False</property>
- <property name="position">4</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- <packing>
- <property name="position">1</property>
- </packing>
- </child>
- </widget>
- </child>
- </widget>
-</glade-interface>
+++ /dev/null
-#!/usr/bin/env python
-# -*- coding: UTF8 -*-
-
-from __future__ import with_statement
-
-import os
-import math
-import pickle
-import logging
-
-import pango
-import gobject
-import gtk
-import gtk.glade
-import gtk.gdk
-
-import constants
-import hildonize
-import gtk_toolbox
-import unit_data
-
-try:
- import gettext
-except ImportError:
- _ = lambda x: x
- gettext = None
-else:
- _ = gettext.gettext
-
-
-_moduleLogger = logging.getLogger(__name__)
-
-
-if gettext is not None:
- gettext.bindtextdomain('gonvert', '/usr/share/locale')
- gettext.textdomain('gonvert')
-
-
-def change_menu_label(widgets, labelname, newtext):
- item_label = widgets.get_widget(labelname).get_children()[0]
- item_label.set_text(newtext)
-
-
-def split_number(number):
- try:
- fractional, integer = math.modf(number)
- except TypeError:
- integerDisplay = number
- fractionalDisplay = ""
- else:
- integerDisplay = str(integer)
- fractionalDisplay = str(fractional)
- if "e+" in integerDisplay:
- integerDisplay = number
- fractionalDisplay = ""
- elif "e-" in fractionalDisplay and 0.0 < integer:
- integerDisplay = number
- fractionalDisplay = ""
- elif "e-" in fractionalDisplay:
- integerDisplay = ""
- fractionalDisplay = number
- else:
- integerDisplay = integerDisplay.split(".", 1)[0] + "."
- fractionalDisplay = fractionalDisplay.rsplit(".", 1)[-1]
-
- return integerDisplay, fractionalDisplay
-
-
-class Gonvert(object):
-
- _glade_files = [
- os.path.join(os.path.dirname(__file__), "gonvert.glade"),
- os.path.join(os.path.dirname(__file__), "../data/gonvert.glade"),
- os.path.join(os.path.dirname(__file__), "../share/gonvert.glade"),
- '/usr/share/gonvert/gonvert.glade',
- ]
-
- UNITS_NAME_IDX = 0
- UNITS_VALUE_IDX = 1
- UNITS_SYMBOL_IDX = 2
- UNITS_INTEGER_IDX = 3
- UNITS_FRACTION_IDX = 4
-
- def __init__(self):
- self._unitDataInCategory = None
- self._unit_sort_direction = False
- self._value_sort_direction = False
- self._units_sort_direction = False
- self.__isPortrait = False
- self._isFullScreen = False
- self._clipboard = gtk.clipboard_get()
-
- self._find_result = [] # empty find result list
- self._findIndex = 0 # default to find result number zero
-
- self._selectedCategoryName = '' # preset to no selected category
- self._defaultUnitForCategory = {} # empty dictionary for later use
-
- #check to see if glade file is in current directory (user must be
- # running from download untar directory)
- for gladePath in self._glade_files:
- if os.path.isfile(gladePath):
- homepath = os.path.dirname(gladePath)
- pixmapspath = "/".join((homepath, "pixmaps"))
- widgets = gtk.glade.XML(gladePath)
- break
- else:
- _moduleLogger.error("UI Descriptor not found!")
- gtk.main_quit()
- return
-
- self._mainWindow = widgets.get_widget('mainWindow')
- self._app = hildonize.get_app_class()()
- self._mainWindow = hildonize.hildonize_window(self._app, self._mainWindow)
-
- change_menu_label(widgets, 'fileMenuItem', _('File'))
- change_menu_label(widgets, 'exitMenuItem', _('Exit'))
- change_menu_label(widgets, 'helpMenuItem', _('Help'))
- change_menu_label(widgets, 'aboutMenuItem', _('About'))
-
- self._categorySelectionButton = widgets.get_widget("categorySelectionButton")
- self._categoryView = widgets.get_widget('categoryView')
-
- self._unitsView = widgets.get_widget('unitsView')
- self._unitsView.set_property('rules_hint', 1)
- self._unitsView_selection = self._unitsView.get_selection()
-
- self._unitName = widgets.get_widget('unitName')
- self._unitValue = widgets.get_widget('unitValue')
- self._previousUnitName = widgets.get_widget('previousUnitName')
- self._previousUnitValue = widgets.get_widget('previousUnitValue')
-
- self._unitSymbol = widgets.get_widget('unitSymbol')
- self._previousUnitSymbol = widgets.get_widget('previousUnitSymbol')
-
- self._unitDescription = widgets.get_widget('unitDescription')
-
- self._searchLayout = widgets.get_widget('searchLayout')
- self._searchLayout.hide()
- self._findEntry = widgets.get_widget('findEntry')
- self._findLabel = widgets.get_widget('findLabel')
- self._findButton = widgets.get_widget('findButton')
- self._closeSearchButton = widgets.get_widget('closeSearchButton')
-
- self._unitsNameRenderer = gtk.CellRendererText()
- self._unitsNameRenderer.set_property("scale", 0.75)
- if constants.FORCE_HILDON_LIKE:
- self._unitsNameRenderer.set_property("ellipsize", pango.ELLIPSIZE_END)
- self._unitsNameRenderer.set_property("width-chars", 5)
- self._unitNameColumn = gtk.TreeViewColumn(_('Name'), self._unitsNameRenderer)
- self._unitNameColumn.set_property('resizable', True)
- self._unitNameColumn.add_attribute(self._unitsNameRenderer, 'text', self.UNITS_NAME_IDX)
- self._unitNameColumn.set_clickable(True)
- self._unitNameColumn.connect("clicked", self._on_click_unit_column)
- self._unitsView.append_column(self._unitNameColumn)
-
- renderer = gtk.CellRendererText()
- renderer.set_property("xalign", 1.0)
- renderer.set_property("alignment", pango.ALIGN_RIGHT)
- hildonize.set_cell_thumb_selectable(renderer)
- self._unitIntegerColumn = gtk.TreeViewColumn(_('Value'), renderer)
- self._unitIntegerColumn.set_property('resizable', True)
- self._unitIntegerColumn.add_attribute(renderer, 'text', self.UNITS_INTEGER_IDX)
- self._unitIntegerColumn.set_clickable(True)
- self._unitIntegerColumn.connect("clicked", self._on_click_unit_column)
- self._unitsView.append_column(self._unitIntegerColumn)
-
- renderer = gtk.CellRendererText()
- renderer.set_property("xalign", 0.0)
- renderer.set_property("alignment", pango.ALIGN_LEFT)
- renderer.set_property("scale", 0.75)
- self._unitFractionalColumn = gtk.TreeViewColumn(_(''), renderer)
- self._unitFractionalColumn.set_property('resizable', True)
- self._unitFractionalColumn.add_attribute(renderer, 'text', self.UNITS_FRACTION_IDX)
- self._unitFractionalColumn.set_clickable(True)
- self._unitFractionalColumn.connect("clicked", self._on_click_unit_column)
- self._unitsView.append_column(self._unitFractionalColumn)
-
- renderer = gtk.CellRendererText()
- renderer.set_property("ellipsize", pango.ELLIPSIZE_END)
- #renderer.set_property("scale", 0.5)
- self._unitSymbolColumn = gtk.TreeViewColumn(_('Units'), renderer)
- self._unitSymbolColumn.set_property('resizable', True)
- self._unitSymbolColumn.add_attribute(renderer, 'text', self.UNITS_SYMBOL_IDX)
- self._unitSymbolColumn.set_clickable(True)
- self._unitSymbolColumn.connect("clicked", self._on_click_unit_column)
- self._unitsView.append_column(self._unitSymbolColumn)
-
- self._unitModel = gtk.ListStore(
- gobject.TYPE_STRING, # UNITS_NAME_IDX
- gobject.TYPE_STRING, # UNITS_VALUE_IDX
- gobject.TYPE_STRING, # UNITS_SYMBOL_IDX
- gobject.TYPE_STRING, # UNITS_INTEGER_IDX
- gobject.TYPE_STRING, # UNITS_FRACTION_IDX
- )
- self._sortedUnitModel = gtk.TreeModelSort(self._unitModel)
- columns = self._get_column_sort_stuff()
- for columnIndex, (column, sortDirection, col_cmp) in enumerate(columns):
- self._sortedUnitModel.set_sort_func(columnIndex, col_cmp)
- self._unitsView.set_model(self._sortedUnitModel)
-
- #Insert a column into the category list even though the heading will not be seen
- renderer = gtk.CellRendererText()
- self._categoryColumn = gtk.TreeViewColumn('Title', renderer)
- self._categoryColumn.set_property('resizable', 1)
- self._categoryColumn.add_attribute(renderer, 'text', 0)
- self._categoryView.append_column(self._categoryColumn)
-
- self._categoryModel = gtk.ListStore(gobject.TYPE_STRING)
- self._categoryView.set_model(self._categoryModel)
- #colourize each row differently for easier reading
- self._categoryView.set_property('rules_hint', 1)
-
- #Populate the catagories list
- for key in unit_data.UNIT_CATEGORIES:
- row = (key, )
- self._categoryModel.append(row)
-
- #--------- connections to GUI ----------------
- self._mainWindow.connect("destroy", self._on_user_exit)
- self._mainWindow.connect("key-press-event", self._on_key_press)
- self._mainWindow.connect("window-state-event", self._on_window_state_change)
- self._categorySelectionButton.connect("clicked", self._on_category_selector_clicked)
- self._categoryView.connect("cursor-changed", self._on_click_category)
- self._findButton.connect("clicked", self._on_find_activate)
- self._findEntry.connect("activate", self._on_find_activate)
- self._findEntry.connect("changed", self._on_findEntry_changed)
- self._closeSearchButton.connect("clicked", self._on_toggle_search)
- self._previousUnitValue.connect("changed", self._on_previous_unit_value_changed)
- self._unitValue.connect("changed", self._on_unit_value_changed)
- self._unitValue.connect("key-press-event", self._on_browse_key_press)
- self._unitsView.connect("cursor-changed", self._on_click_unit)
- self._unitsView.connect("key-press-event", self._on_browse_key_press)
- if hildonize.GTK_MENU_USED:
- widgets.get_widget("aboutMenuItem").connect("activate", self._on_about_clicked)
- widgets.get_widget("searchMenuItem").connect("activate", self._on_toggle_search)
- widgets.get_widget("exitMenuItem").connect("activate", self._on_user_exit)
-
- for scrollingWidgetName in (
- "unitsViewScrolledWindow",
- ):
- scrollingWidget = widgets.get_widget(scrollingWidgetName)
- assert scrollingWidget is not None, scrollingWidgetName
- scroller = hildonize.hildonize_scrollwindow(scrollingWidget)
- scroller.show_all()
-
- # Simplify the UI
- if hildonize.IS_HILDON_SUPPORTED or constants.FORCE_HILDON_LIKE:
- self._categoryView.get_parent().hide()
- self._unitsView.set_headers_visible(False)
- self._previousUnitName.get_parent().hide()
- self._unitDescription.get_parent().get_parent().hide()
- else:
- self._categorySelectionButton.hide()
-
- menu = hildonize.hildonize_menu(
- self._mainWindow,
- widgets.get_widget("mainMenuBar"),
- )
- if not hildonize.GTK_MENU_USED:
- button = gtk.Button("Search")
- button.connect("clicked", self._on_toggle_search)
- menu.append(button)
-
- button = hildonize.hildon.GtkRadioButton(gtk.HILDON_SIZE_AUTO, None)
- button.set_label("Name")
- menu.add_filter(button)
- button.connect("clicked", self._on_click_menu_filter, self._unitNameColumn)
- button.set_mode(False)
- filterGroup = button
-
- button = hildonize.hildon.GtkRadioButton(gtk.HILDON_SIZE_AUTO, filterGroup)
- button.set_label("Value")
- menu.add_filter(button)
- button.connect("clicked", self._on_click_menu_filter, self._unitIntegerColumn)
- button.set_mode(False)
-
- button = hildonize.hildon.GtkRadioButton(gtk.HILDON_SIZE_AUTO, filterGroup)
- button.set_label("Unit")
- menu.add_filter(button)
- button.connect("clicked", self._on_click_menu_filter, self._unitSymbolColumn)
- button.set_mode(False)
-
- menu.show_all()
-
- if not hildonize.IS_HILDON_SUPPORTED:
- _moduleLogger.info("No hildonization support")
-
- hildonize.set_application_name(
- "%s - Unit Conversion Utility" % constants.__pretty_app_name__
- )
- iconPath = pixmapspath + '/gonvert.png'
- if os.path.exists(iconPath):
- self._mainWindow.set_icon(gtk.gdk.pixbuf_new_from_file(iconPath))
- else:
- _moduleLogger.warn("Error: Could not find gonvert icon: %s" % iconPath)
-
- self._load_settings()
- self._mainWindow.show()
-
- def _load_settings(self):
- #Restore window size from previously saved settings if it exists and is valid.
- windowDatPath = "/".join((constants._data_path_, "window.dat"))
- if os.path.exists(windowDatPath):
- saved_window = pickle.load(open(windowDatPath, "r"))
- try:
- a, b = saved_window['size']
- except KeyError:
- pass
- else:
- self._mainWindow.resize(a, b)
- try:
- isFullscreen = saved_window["isFullscreen"]
- except KeyError:
- pass
- else:
- if isFullscreen:
- self._mainWindow.fullscreen()
- try:
- isPortrait = saved_window["isPortrait"]
- except KeyError:
- pass
- else:
- if isPortrait ^ self.__isPortrait:
- if isPortrait:
- orientation = gtk.ORIENTATION_VERTICAL
- else:
- orientation = gtk.ORIENTATION_HORIZONTAL
- self.set_orientation(orientation)
-
- #Restore selections from previously saved settings if it exists and is valid.
- categoryIndex = 0
- selectedCategoryName = unit_data.UNIT_CATEGORIES[0]
- selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
- if os.path.exists(selectionsDatPath):
- selections = pickle.load(open(selectionsDatPath, 'r'))
- try:
- self._defaultUnitForCategory = selections['selected_units']
- except KeyError:
- pass
-
- try:
- selectedCategoryName = selections['selected_category']
- except KeyError:
- pass
- else:
- try:
- categoryIndex = unit_data.UNIT_CATEGORIES.index(selectedCategoryName)
- except ValueError:
- _moduleLogger.warn("Unknown category: %s" % selectedCategoryName)
-
- self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % selectedCategoryName)
- self._categoryView.set_cursor(categoryIndex, self._categoryColumn, False)
- self._categoryView.grab_focus()
-
- self._select_default_unit()
-
- def _save_settings(self):
- """
- This routine saves the selections to a file, and
- should therefore only be called when exiting the program.
-
- Update selections dictionary which consists of the following keys:
- 'self._selectedCategoryName': full name of selected category
- 'self._defaultUnitForCategory': self._defaultUnitForCategory dictionary which contains:
- [categoryname: #1 displayed unit, #2 displayed unit]
- """
- #Determine the contents of the selected category row
- selected, iter = self._categoryView.get_selection().get_selected()
- self._selectedCategoryName = self._categoryModel.get_value(iter, 0)
-
- selections = {
- 'selected_category': self._selectedCategoryName,
- 'selected_units': self._defaultUnitForCategory
- }
- selectionsDatPath = "/".join((constants._data_path_, "selections.dat"))
- pickle.dump(selections, open(selectionsDatPath, 'w'))
-
- #Get last size of app and save it
- window_settings = {
- 'size': self._mainWindow.get_size(),
- "isFullscreen": self._isFullScreen,
- "isPortrait": self.__isPortrait,
- }
- windowDatPath = "/".join((constants._data_path_, "window.dat"))
- pickle.dump(window_settings, open(windowDatPath, 'w'))
-
- def _refresh_columns(self):
- self._unitsView.remove_column(self._unitNameColumn)
- self._unitsView.remove_column(self._unitIntegerColumn)
- self._unitsView.remove_column(self._unitFractionalColumn)
- self._unitsView.remove_column(self._unitSymbolColumn)
-
- self._unitsView.append_column(self._unitNameColumn)
- self._unitsView.append_column(self._unitIntegerColumn)
- self._unitsView.append_column(self._unitFractionalColumn)
- self._unitsView.append_column(self._unitSymbolColumn)
-
- def _clear_find(self):
- # switch to "new find" state
- self._find_result = []
- self._findIndex = 0
-
- # Clear our user message
- self._findLabel.set_text('')
-
- def _find_first(self):
- assert len(self._find_result) == 0
- assert self._findIndex == 0
- findString = self._findEntry.get_text().strip().lower()
- if not findString:
- return
-
- # Gather info on all the matching units from all categories
- for catIndex, category in enumerate(unit_data.UNIT_CATEGORIES):
- units = unit_data.get_units(category)
- for unitIndex, unit in enumerate(units):
- loweredUnit = unit.lower()
- if loweredUnit in findString or findString in loweredUnit:
- self._find_result.append((category, unit, catIndex, unitIndex))
-
- def _update_find_selection(self):
- assert 0 < len(self._find_result)
-
- #check if next find is in a new category (prevent category changes when unnecessary
- searchCategoryName = self._find_result[self._findIndex][0]
- if self._selectedCategoryName != searchCategoryName:
- self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % searchCategoryName)
- self._categoryView.set_cursor(
- self._find_result[self._findIndex][2], self._categoryColumn, False
- )
-
- self._unitsView.set_cursor(
- self._find_result[self._findIndex][3], self._unitNameColumn, True
- )
-
- def _find_next(self):
- if len(self._find_result) == 0:
- self._find_first()
- else:
- if self._findIndex == len(self._find_result)-1:
- self._findIndex = 0
- else:
- self._findIndex += 1
-
- if not self._find_result:
- self._findLabel.set_text('Text not found')
- else:
- self._update_find_selection()
- resultsLeft = len(self._find_result) - self._findIndex - 1
- self._findLabel.set_text(
- '%s result(s) left' % (resultsLeft, )
- )
-
- def _find_previous(self):
- if len(self._find_result) == 0:
- self._find_first()
- else:
- if self._findIndex == 0:
- self._findIndex = len(self._find_result)-1
- else:
- self._findIndex -= 1
-
- if not self._find_result:
- self._findLabel.set_text('Text not found')
- else:
- self._update_find_selection()
- resultsLeft = len(self._find_result) - self._findIndex - 1
- self._findLabel.set_text(
- '%s result(s) left' % (resultsLeft, )
- )
-
- def _toggle_find(self):
- if self._searchLayout.get_property("visible"):
- self._searchLayout.hide()
- self._unitsView.grab_focus()
- else:
- self._searchLayout.show()
- self._findEntry.grab_focus()
-
- def _unit_model_cmp(self, sortedModel, leftItr, rightItr):
- leftUnitText = self._unitModel.get_value(leftItr, self.UNITS_NAME_IDX)
- rightUnitText = self._unitModel.get_value(rightItr, self.UNITS_NAME_IDX)
- return cmp(leftUnitText, rightUnitText)
-
- def _symbol_model_cmp(self, sortedModel, leftItr, rightItr):
- leftSymbolText = self._unitModel.get_value(leftItr, self.UNITS_SYMBOL_IDX)
- rightSymbolText = self._unitModel.get_value(rightItr, self.UNITS_SYMBOL_IDX)
- return cmp(leftSymbolText, rightSymbolText)
-
- def _value_model_cmp(self, sortedModel, leftItr, rightItr):
- #special sorting exceptions for ascii values (instead of float values)
- if self._selectedCategoryName == "Computer Numbers":
- leftValue = self._unitModel.get_value(leftItr, self.UNITS_VALUE_IDX)
- rightValue = self._unitModel.get_value(rightItr, self.UNITS_VALUE_IDX)
- else:
- leftValueText = self._unitModel.get_value(leftItr, self.UNITS_VALUE_IDX)
- leftValue = float(leftValueText) if leftValueText else 0.0
-
- rightValueText = self._unitModel.get_value(rightItr, self.UNITS_VALUE_IDX)
- rightValue = float(rightValueText) if rightValueText else 0.0
- return cmp(leftValue, rightValue)
-
- def _get_column_sort_stuff(self):
- columns = (
- (self._unitNameColumn, "_unit_sort_direction", self._unit_model_cmp),
- (self._unitIntegerColumn, "_value_sort_direction", self._value_model_cmp),
- (self._unitFractionalColumn, "_value_sort_direction", self._value_model_cmp),
- (self._unitSymbolColumn, "_units_sort_direction", self._symbol_model_cmp),
- )
- return columns
-
- def _switch_category(self, category):
- self._selectedCategoryName = category
- self._unitDataInCategory = unit_data.UNIT_DESCRIPTIONS[self._selectedCategoryName]
-
- #Fill up the units descriptions and clear the value cells
- self._clear_visible_unit_data()
- nameLength = 0
- for key in unit_data.get_units(self._selectedCategoryName):
- row = key, '0.0', self._unitDataInCategory[key][1], '0.', '0'
- self._unitModel.append(row)
- nameLength = max(nameLength, len(key))
- self._sortedUnitModel.sort_column_changed()
-
- if constants.FORCE_HILDON_LIKE:
- maxCatCharWidth = int(nameLength * 0.75)
- maxCharWidth = int(len("nibble | hexit | quadbit") * 0.75)
- charWidth = min(maxCatCharWidth, maxCharWidth)
- self._unitsNameRenderer.set_property("width-chars", charWidth)
-
- self._select_default_unit()
-
- def _clear_visible_unit_data(self):
- self._unitDescription.get_buffer().set_text("")
- self._unitName.set_text('')
- self._unitValue.set_text('')
- self._unitSymbol.set_text('')
-
- self._previousUnitName.set_text('')
- self._previousUnitValue.set_text('')
- self._previousUnitSymbol.set_text('')
-
- self._unitModel.clear()
-
- def _select_default_unit(self):
- # Restore the previous historical settings of previously selected units
- # in this newly selected category
- defaultPrimary = unit_data.get_base_unit(self._selectedCategoryName)
- defaultSecondary = ""
- if self._selectedCategoryName in self._defaultUnitForCategory:
- if self._defaultUnitForCategory[self._selectedCategoryName][0]:
- defaultPrimary = self._defaultUnitForCategory[self._selectedCategoryName][0]
- if self._defaultUnitForCategory[self._selectedCategoryName][1]:
- defaultSecondary = self._defaultUnitForCategory[self._selectedCategoryName][1]
-
- units = unit_data.get_units(self._selectedCategoryName)
-
- #Restore oldest selection first.
- if defaultPrimary:
- try:
- unitIndex = units.index(defaultPrimary)
- except ValueError:
- unitIndex = 0
- self._unitsView.set_cursor(unitIndex, self._unitNameColumn, True)
-
- #Restore newest selection second.
- if defaultSecondary:
- try:
- unitIndex = units.index(defaultSecondary)
- except ValueError:
- unitIndex = 0
- self._unitsView.set_cursor(unitIndex, self._unitNameColumn, True)
-
- # select the text so user can start typing right away
- self._unitValue.grab_focus()
- self._unitValue.select_region(0, -1)
-
- def _sanitize_value(self, userEntry):
- if self._selectedCategoryName == "Computer Numbers":
- if userEntry == '':
- value = '0'
- else:
- value = userEntry
- else:
- if userEntry == '':
- value = 0.0
- else:
- value = float(userEntry)
- return value
-
- def _select_sort_column(self, col):
- #Determine which column requires sorting
- columns = self._get_column_sort_stuff()
- for columnIndex, (maybeCol, directionName, col_cmp) in enumerate(columns):
- if col is maybeCol:
- direction = getattr(self, directionName)
- gtkDirection = gtk.SORT_ASCENDING if direction else gtk.SORT_DESCENDING
-
- # cause a sort
- self._sortedUnitModel.set_sort_column_id(columnIndex, gtkDirection)
-
- # set the visual for sorting
- col.set_sort_indicator(True)
- col.set_sort_order(not direction)
-
- setattr(self, directionName, not direction)
- break
- else:
- maybeCol.set_sort_indicator(False)
- else:
- assert False, "Unknown column: %s" % (col.get_title(), )
-
- def set_orientation(self, orientation):
- if orientation == gtk.ORIENTATION_VERTICAL:
- hildonize.window_to_portrait(self._mainWindow)
- self.__isPortrait = True
- elif orientation == gtk.ORIENTATION_HORIZONTAL:
- hildonize.window_to_landscape(self._mainWindow)
- self.__isPortrait = False
- else:
- raise NotImplementedError(orientation)
-
- def get_orientation(self):
- return gtk.ORIENTATION_VERTICAL if self.__isPortrait else gtk.ORIENTATION_HORIZONTAL
-
- def _toggle_rotate(self):
- if self.__isPortrait:
- self.set_orientation(gtk.ORIENTATION_HORIZONTAL)
- else:
- self.set_orientation(gtk.ORIENTATION_VERTICAL)
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_key_press(self, widget, event, *args):
- """
- @note Hildon specific
- """
- RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
- if (
- event.keyval == gtk.keysyms.F6 or
- event.keyval in RETURN_TYPES and event.get_state() & gtk.gdk.CONTROL_MASK
- ):
- if self._isFullScreen:
- self._mainWindow.unfullscreen()
- else:
- self._mainWindow.fullscreen()
- elif event.keyval == gtk.keysyms.f and event.get_state() & gtk.gdk.CONTROL_MASK:
- if not hildonize.GTK_MENU_USED:
- self._toggle_find()
- elif event.keyval == gtk.keysyms.p and event.get_state() & gtk.gdk.CONTROL_MASK:
- self._find_previous()
- elif event.keyval == gtk.keysyms.n and event.get_state() & gtk.gdk.CONTROL_MASK:
- self._find_next()
- elif event.keyval == gtk.keysyms.o and event.get_state() & gtk.gdk.CONTROL_MASK:
- self._toggle_rotate()
- elif (
- event.keyval in (gtk.keysyms.w, gtk.keysyms.q) and
- event.get_state() & gtk.gdk.CONTROL_MASK
- ):
- self._mainWindow.destroy()
- elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK:
- with open(constants._user_logpath_, "r") as f:
- logLines = f.xreadlines()
- log = "".join(logLines)
- self._clipboard.set_text(str(log))
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_toggle_search(self, *args):
- self._toggle_find()
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_browse_key_press(self, widget, event, *args):
- if event.keyval == gtk.keysyms.uparrow or event.keyval == gtk.keysyms.Up:
- index, column = self._unitsView.get_cursor()
- newIndex = max(index[0]-1, 0)
- path = (newIndex, )
- self._unitsView.set_cursor(path, column, True)
- self._unitsView.scroll_to_cell(path, column, False, 0, 0)
- return True # override default behavior
- elif event.keyval == gtk.keysyms.downarrow or event.keyval == gtk.keysyms.Down:
- index, column = self._unitsView.get_cursor()
- newIndex = min(index[0]+1, len(self._unitModel)-1)
- path = (newIndex, )
- self._unitsView.set_cursor(path, column, True)
- self._unitsView.scroll_to_cell(path, column, False, 0, 0)
- return True # override default behavior
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_window_state_change(self, widget, event, *args):
- """
- @note Hildon specific
- """
- if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
- self._isFullScreen = True
- else:
- self._isFullScreen = False
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_findEntry_changed(self, *args):
- """
- Clear out find results since the user wants to look for something new
- """
- self._clear_find()
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_find_activate(self, *args):
- self._find_next()
- self._findButton.grab_focus()
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_click_menu_filter(self, button, col):
- self._select_sort_column(col)
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_click_unit_column(self, col):
- """
- Sort the contents of the col when the user clicks on the title.
- """
- self._select_sort_column(col)
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_category_selector_clicked(self, *args):
- currenntIndex = unit_data.UNIT_CATEGORIES.index(self._selectedCategoryName)
- newIndex = hildonize.touch_selector(
- self._mainWindow,
- "Categories",
- unit_data.UNIT_CATEGORIES,
- currenntIndex,
- )
-
- selectedCategoryName = unit_data.UNIT_CATEGORIES[newIndex]
- self._categorySelectionButton.get_child().set_markup("<big>%s</big>" % selectedCategoryName)
- self._switch_category(selectedCategoryName)
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_click_category(self, *args):
- selected, iter = self._categoryView.get_selection().get_selected()
- if iter is None:
- # User is typing in an invalid string, not selecting any category
- return
- selectedCategory = self._categoryModel.get_value(iter, 0)
- self._switch_category(selectedCategory)
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_click_unit(self, *args):
- selected, iter = self._unitsView.get_selection().get_selected()
- selected_unit = selected.get_value(iter, self.UNITS_NAME_IDX)
- unit_spec = self._unitDataInCategory[selected_unit]
-
- showSymbol = False
-
- if self._unitName.get_text() != selected_unit:
- self._previousUnitName.set_text(self._unitName.get_text())
- self._previousUnitValue.set_text(self._unitValue.get_text())
- self._previousUnitSymbol.set_text(self._unitSymbol.get_text())
- if self._unitSymbol.get_text():
- showSymbol = True
-
- self._unitName.set_text(selected_unit)
- self._unitValue.set_text(selected.get_value(iter, self.UNITS_VALUE_IDX))
- buffer = self._unitDescription.get_buffer()
- buffer.set_text(unit_spec[2])
- self._unitSymbol.set_text(unit_spec[1]) # put units into label text
- if unit_spec[1]:
- showSymbol = True
- else:
- showSymbol = False
-
- if showSymbol:
- self._unitSymbol.show()
- self._previousUnitSymbol.show()
- else:
- self._unitSymbol.hide()
- self._previousUnitSymbol.hide()
-
- if self._unitValue.get_text() == '':
- if self._selectedCategoryName == "Computer Numbers":
- self._unitValue.set_text("0")
- else:
- self._unitValue.set_text("0.0")
-
- self._defaultUnitForCategory[self._selectedCategoryName] = [
- self._unitName.get_text(), self._previousUnitName.get_text()
- ]
-
- # select the text so user can start typing right away
- self._unitValue.grab_focus()
- self._unitValue.select_region(0, -1)
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_unit_value_changed(self, *args):
- if self._unitName.get_text() == '':
- return
- if not self._unitValue.is_focus():
- return
-
- #retrieve the conversion function and value from the selected unit
- value = self._sanitize_value(self._unitValue.get_text())
- func, arg = self._unitDataInCategory[self._unitName.get_text()][0]
- base = func.to_base(value, arg)
-
- #point to the first row
- for row in self._unitModel:
- func, arg = self._unitDataInCategory[row[self.UNITS_NAME_IDX]][0]
- newValue = func.from_base(base, arg)
-
- newValueDisplay = str(newValue)
- integerDisplay, fractionalDisplay = split_number(newValue)
-
- row[self.UNITS_VALUE_IDX] = newValueDisplay
- row[self.UNITS_INTEGER_IDX] = integerDisplay
- row[self.UNITS_FRACTION_IDX] = fractionalDisplay
-
- # Update the secondary unit entry
- if self._previousUnitName.get_text() != '':
- func, arg = self._unitDataInCategory[self._previousUnitName.get_text()][0]
- self._previousUnitValue.set_text(str(func.from_base(base, arg, )))
-
- self._sortedUnitModel.sort_column_changed()
- self._refresh_columns()
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_previous_unit_value_changed(self, *args):
- if self._previousUnitName.get_text() == '':
- return
- if not self._previousUnitValue.is_focus():
- return
-
- #retrieve the conversion function and value from the selected unit
- value = self._sanitize_value(self._previousUnitValue.get_text())
- func, arg = self._unitDataInCategory[self._previousUnitName.get_text()][0]
- base = func.to_base(value, arg)
-
- #point to the first row
- for row in self._unitModel:
- func, arg = self._unitDataInCategory[row[self.UNITS_NAME_IDX]][0]
- newValue = func.from_base(base, arg)
-
- newValueDisplay = str(newValue)
- integerDisplay, fractionalDisplay = split_number(newValue)
-
- row[self.UNITS_VALUE_IDX] = newValueDisplay
- row[self.UNITS_INTEGER_IDX] = integerDisplay
- row[self.UNITS_FRACTION_IDX] = fractionalDisplay
-
- # Update the primary unit entry
- func, arg = self._unitDataInCategory[self._unitName.get_text()][0]
- self._unitValue.set_text(str(func.from_base(base, arg, )))
-
- self._sortedUnitModel.sort_column_changed()
- self._refresh_columns()
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_about_clicked(self, a):
- dlg = gtk.AboutDialog()
- dlg.set_name(constants.__pretty_app_name__)
- dlg.set_version("%s-%d" % (constants.__version__, constants.__build__))
- dlg.set_copyright("Copyright 2009 - GPL")
- dlg.set_comments("")
- dlg.set_website("http://unihedron.com/projects/gonvert/gonvert.php")
- dlg.set_authors(["Anthony Tekatch <anthony@unihedron.com>", "Ed Page <eopage@byu.net> (Blame him for the most recent bugs)"])
- dlg.run()
- dlg.destroy()
-
- @gtk_toolbox.log_exception(_moduleLogger)
- def _on_user_exit(self, *args):
- try:
- self._save_settings()
- except Exception:
- pass
- finally:
- gtk.main_quit()
-
-
-def run_gonvert():
- gtk.gdk.threads_init()
- if hildonize.IS_HILDON_SUPPORTED:
- gtk.set_application_name(constants.__pretty_app_name__)
- handle = Gonvert()
- if not constants.PROFILE_STARTUP:
- gtk.main()
-
-
-if __name__ == "__main__":
- logging.basicConfig(level = logging.DEBUG)
- try:
- os.makedirs(constants._data_path_)
- except OSError, e:
- if e.errno != 17:
- raise
-
- run_gonvert()
+++ /dev/null
-#!/usr/bin/python
-
-from __future__ import with_statement
-
-import os
-import errno
-import sys
-import time
-import itertools
-import functools
-import contextlib
-import logging
-import threading
-import Queue
-
-import gobject
-import gtk
-
-
-_moduleLogger = logging.getLogger(__name__)
-
-
-def get_screen_orientation():
- width, height = gtk.gdk.get_default_root_window().get_size()
- if width < height:
- return gtk.ORIENTATION_VERTICAL
- else:
- return gtk.ORIENTATION_HORIZONTAL
-
-
-def orientation_change_connect(handler, *args):
- """
- @param handler(orientation, *args) -> None(?)
- """
- initialScreenOrientation = get_screen_orientation()
- orientationAndArgs = list(itertools.chain((initialScreenOrientation, ), args))
-
- def _on_screen_size_changed(screen):
- newScreenOrientation = get_screen_orientation()
- if newScreenOrientation != orientationAndArgs[0]:
- orientationAndArgs[0] = newScreenOrientation
- handler(*orientationAndArgs)
-
- rootScreen = gtk.gdk.get_default_root_window()
- return gtk.connect(rootScreen, "size-changed", _on_screen_size_changed)
-
-
-@contextlib.contextmanager
-def flock(path, timeout=-1):
- WAIT_FOREVER = -1
- DELAY = 0.1
- timeSpent = 0
-
- acquired = False
-
- while timeSpent <= timeout or timeout == WAIT_FOREVER:
- try:
- fd = os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR)
- acquired = True
- break
- except OSError, e:
- if e.errno != errno.EEXIST:
- raise
- time.sleep(DELAY)
- timeSpent += DELAY
-
- assert acquired, "Failed to grab file-lock %s within timeout %d" % (path, timeout)
-
- try:
- yield fd
- finally:
- os.unlink(path)
-
-
-@contextlib.contextmanager
-def gtk_lock():
- gtk.gdk.threads_enter()
- try:
- yield
- finally:
- gtk.gdk.threads_leave()
-
-
-def find_parent_window(widget):
- while True:
- parent = widget.get_parent()
- if isinstance(parent, gtk.Window):
- return parent
- widget = parent
-
-
-def make_idler(func):
- """
- Decorator that makes a generator-function into a function that will continue execution on next call
- """
- a = []
-
- @functools.wraps(func)
- def decorated_func(*args, **kwds):
- if not a:
- a.append(func(*args, **kwds))
- try:
- a[0].next()
- return True
- except StopIteration:
- del a[:]
- return False
-
- return decorated_func
-
-
-def asynchronous_gtk_message(original_func):
- """
- @note Idea came from http://www.aclevername.com/articles/python-webgui/
- """
-
- def execute(allArgs):
- args, kwargs = allArgs
- with gtk_lock():
- original_func(*args, **kwargs)
- return False
-
- @functools.wraps(original_func)
- def delayed_func(*args, **kwargs):
- gobject.idle_add(execute, (args, kwargs))
-
- return delayed_func
-
-
-def synchronous_gtk_message(original_func):
- """
- @note Idea came from http://www.aclevername.com/articles/python-webgui/
- """
-
- @functools.wraps(original_func)
- def immediate_func(*args, **kwargs):
- with gtk_lock():
- return original_func(*args, **kwargs)
-
- return immediate_func
-
-
-def autostart(func):
- """
- >>> @autostart
- ... def grep_sink(pattern):
- ... print "Looking for %s" % pattern
- ... while True:
- ... line = yield
- ... if pattern in line:
- ... print line,
- >>> g = grep_sink("python")
- Looking for python
- >>> g.send("Yeah but no but yeah but no")
- >>> g.send("A series of tubes")
- >>> g.send("python generators rock!")
- python generators rock!
- >>> g.close()
- """
-
- @functools.wraps(func)
- def start(*args, **kwargs):
- cr = func(*args, **kwargs)
- cr.next()
- return cr
-
- return start
-
-
-@autostart
-def printer_sink(format = "%s"):
- """
- >>> pr = printer_sink("%r")
- >>> pr.send("Hello")
- 'Hello'
- >>> pr.send("5")
- '5'
- >>> pr.send(5)
- 5
- >>> p = printer_sink()
- >>> p.send("Hello")
- Hello
- >>> p.send("World")
- World
- >>> # p.throw(RuntimeError, "Goodbye")
- >>> # p.send("Meh")
- >>> # p.close()
- """
- while True:
- item = yield
- print format % (item, )
-
-
-@autostart
-def null_sink():
- """
- Good for uses like with cochain to pick up any slack
- """
- while True:
- item = yield
-
-
-@autostart
-def comap(function, target):
- """
- >>> p = printer_sink()
- >>> cm = comap(lambda x: x+1, p)
- >>> cm.send((0, ))
- 1
- >>> cm.send((1.0, ))
- 2.0
- >>> cm.send((-2, ))
- -1
- """
- while True:
- try:
- item = yield
- mappedItem = function(*item)
- target.send(mappedItem)
- except Exception, e:
- _moduleLogger.exception("Forwarding exception!")
- target.throw(e.__class__, str(e))
-
-
-def _flush_queue(queue):
- while not queue.empty():
- yield queue.get()
-
-
-@autostart
-def queue_sink(queue):
- """
- >>> q = Queue.Queue()
- >>> qs = queue_sink(q)
- >>> qs.send("Hello")
- >>> qs.send("World")
- >>> qs.throw(RuntimeError, "Goodbye")
- >>> qs.send("Meh")
- >>> qs.close()
- >>> print [i for i in _flush_queue(q)]
- [(None, 'Hello'), (None, 'World'), (<type 'exceptions.RuntimeError'>, 'Goodbye'), (None, 'Meh'), (<type 'exceptions.GeneratorExit'>, None)]
- """
- while True:
- try:
- item = yield
- queue.put((None, item))
- except Exception, e:
- queue.put((e.__class__, str(e)))
- except GeneratorExit:
- queue.put((GeneratorExit, None))
- raise
-
-
-def decode_item(item, target):
- if item[0] is None:
- target.send(item[1])
- return False
- elif item[0] is GeneratorExit:
- target.close()
- return True
- else:
- target.throw(item[0], item[1])
- return False
-
-
-def nonqueue_source(queue, target):
- isDone = False
- while not isDone:
- item = queue.get()
- isDone = decode_item(item, target)
- while not queue.empty():
- queue.get_nowait()
-
-
-def threaded_stage(target, thread_factory = threading.Thread):
- messages = Queue.Queue()
-
- run_source = functools.partial(nonqueue_source, messages, target)
- thread = thread_factory(target=run_source)
- thread.setDaemon(True)
- thread.start()
-
- # Sink running in current thread
- return queue_sink(messages)
-
-
-def log_exception(logger):
-
- def log_exception_decorator(func):
-
- @functools.wraps(func)
- def wrapper(*args, **kwds):
- try:
- return func(*args, **kwds)
- except Exception:
- logger.exception(func.__name__)
-
- return wrapper
-
- return log_exception_decorator
-
-
-class LoginWindow(object):
-
- def __init__(self, widgetTree):
- """
- @note Thread agnostic
- """
- self._dialog = widgetTree.get_widget("loginDialog")
- self._parentWindow = widgetTree.get_widget("mainWindow")
- self._serviceCombo = widgetTree.get_widget("serviceCombo")
- self._usernameEntry = widgetTree.get_widget("usernameentry")
- self._passwordEntry = widgetTree.get_widget("passwordentry")
-
- self._serviceList = gtk.ListStore(gobject.TYPE_INT, gobject.TYPE_STRING)
- self._serviceCombo.set_model(self._serviceList)
- cell = gtk.CellRendererText()
- self._serviceCombo.pack_start(cell, True)
- self._serviceCombo.add_attribute(cell, 'text', 1)
- self._serviceCombo.set_active(0)
-
- widgetTree.get_widget("loginbutton").connect("clicked", self._on_loginbutton_clicked)
- widgetTree.get_widget("logins_close_button").connect("clicked", self._on_loginclose_clicked)
-
- def request_credentials(self,
- parentWindow = None,
- defaultCredentials = ("", "")
- ):
- """
- @note UI Thread
- """
- if parentWindow is None:
- parentWindow = self._parentWindow
-
- self._serviceCombo.hide()
- self._serviceList.clear()
-
- self._usernameEntry.set_text(defaultCredentials[0])
- self._passwordEntry.set_text(defaultCredentials[1])
-
- try:
- self._dialog.set_transient_for(parentWindow)
- self._dialog.set_default_response(gtk.RESPONSE_OK)
- response = self._dialog.run()
- if response != gtk.RESPONSE_OK:
- raise RuntimeError("Login Cancelled")
-
- username = self._usernameEntry.get_text()
- password = self._passwordEntry.get_text()
- self._passwordEntry.set_text("")
- finally:
- self._dialog.hide()
-
- return username, password
-
- def request_credentials_from(self,
- services,
- parentWindow = None,
- defaultCredentials = ("", "")
- ):
- """
- @note UI Thread
- """
- if parentWindow is None:
- parentWindow = self._parentWindow
-
- self._serviceList.clear()
- for serviceIdserviceName in services:
- self._serviceList.append(serviceIdserviceName)
- self._serviceCombo.set_active(0)
- self._serviceCombo.show()
-
- self._usernameEntry.set_text(defaultCredentials[0])
- self._passwordEntry.set_text(defaultCredentials[1])
-
- try:
- self._dialog.set_transient_for(parentWindow)
- self._dialog.set_default_response(gtk.RESPONSE_OK)
- response = self._dialog.run()
- if response != gtk.RESPONSE_OK:
- raise RuntimeError("Login Cancelled")
-
- username = self._usernameEntry.get_text()
- password = self._passwordEntry.get_text()
- finally:
- self._dialog.hide()
-
- itr = self._serviceCombo.get_active_iter()
- serviceId = int(self._serviceList.get_value(itr, 0))
- self._serviceList.clear()
- return serviceId, username, password
-
- def _on_loginbutton_clicked(self, *args):
- self._dialog.response(gtk.RESPONSE_OK)
-
- def _on_loginclose_clicked(self, *args):
- self._dialog.response(gtk.RESPONSE_CANCEL)
-
-
-def safecall(f, errorDisplay=None, default=None, exception=Exception):
- '''
- Returns modified f. When the modified f is called and throws an
- exception, the default value is returned
- '''
- def _safecall(*args, **argv):
- try:
- return f(*args,**argv)
- except exception, e:
- if errorDisplay is not None:
- errorDisplay.push_exception(e)
- return default
- return _safecall
-
-
-class ErrorDisplay(object):
-
- def __init__(self, widgetTree):
- super(ErrorDisplay, self).__init__()
- self.__errorBox = widgetTree.get_widget("errorEventBox")
- self.__errorDescription = widgetTree.get_widget("errorDescription")
- self.__errorClose = widgetTree.get_widget("errorClose")
- self.__parentBox = self.__errorBox.get_parent()
-
- self.__errorBox.connect("button_release_event", self._on_close)
-
- self.__messages = []
- self.__parentBox.remove(self.__errorBox)
-
- def push_message_with_lock(self, message):
- with gtk_lock():
- self.push_message(message)
-
- def push_message(self, message):
- self.__messages.append(message)
- if 1 == len(self.__messages):
- self.__show_message(message)
-
- def push_exception_with_lock(self):
- with gtk_lock():
- self.push_exception()
-
- def push_exception(self):
- userMessage = str(sys.exc_info()[1])
- self.push_message(userMessage)
- _moduleLogger.exception(userMessage)
-
- def pop_message(self):
- del self.__messages[0]
- if 0 == len(self.__messages):
- self.__hide_message()
- else:
- self.__errorDescription.set_text(self.__messages[0])
-
- def _on_close(self, *args):
- self.pop_message()
-
- def __show_message(self, message):
- self.__errorDescription.set_text(message)
- self.__parentBox.pack_start(self.__errorBox, False, False)
- self.__parentBox.reorder_child(self.__errorBox, 1)
-
- def __hide_message(self):
- self.__errorDescription.set_text("")
- self.__parentBox.remove(self.__errorBox)
-
-
-class DummyErrorDisplay(object):
-
- def __init__(self):
- super(DummyErrorDisplay, self).__init__()
-
- self.__messages = []
-
- def push_message_with_lock(self, message):
- self.push_message(message)
-
- def push_message(self, message):
- if 0 < len(self.__messages):
- self.__messages.append(message)
- else:
- self.__show_message(message)
-
- def push_exception(self, exception = None):
- userMessage = str(sys.exc_value)
- _moduleLogger.exception(userMessage)
-
- def pop_message(self):
- if 0 < len(self.__messages):
- self.__show_message(self.__messages[0])
- del self.__messages[0]
-
- def __show_message(self, message):
- _moduleLogger.debug(message)
-
-
-class MessageBox(gtk.MessageDialog):
-
- def __init__(self, message):
- parent = None
- gtk.MessageDialog.__init__(
- self,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_ERROR,
- gtk.BUTTONS_OK,
- message,
- )
- self.set_default_response(gtk.RESPONSE_OK)
- self.connect('response', self._handle_clicked)
-
- def _handle_clicked(self, *args):
- self.destroy()
-
-
-class MessageBox2(gtk.MessageDialog):
-
- def __init__(self, message):
- parent = None
- gtk.MessageDialog.__init__(
- self,
- parent,
- gtk.DIALOG_DESTROY_WITH_PARENT,
- gtk.MESSAGE_ERROR,
- gtk.BUTTONS_OK,
- message,
- )
- self.set_default_response(gtk.RESPONSE_OK)
- self.connect('response', self._handle_clicked)
-
- def _handle_clicked(self, *args):
- self.destroy()
-
-
-class PopupCalendar(object):
-
- def __init__(self, parent, displayDate, title = ""):
- self._displayDate = displayDate
-
- self._calendar = gtk.Calendar()
- self._calendar.select_month(self._displayDate.month, self._displayDate.year)
- self._calendar.select_day(self._displayDate.day)
- self._calendar.set_display_options(
- gtk.CALENDAR_SHOW_HEADING |
- gtk.CALENDAR_SHOW_DAY_NAMES |
- gtk.CALENDAR_NO_MONTH_CHANGE |
- 0
- )
- self._calendar.connect("day-selected", self._on_day_selected)
-
- self._popupWindow = gtk.Window()
- self._popupWindow.set_title(title)
- self._popupWindow.add(self._calendar)
- self._popupWindow.set_transient_for(parent)
- self._popupWindow.set_modal(True)
- self._popupWindow.set_type_hint(gtk.gdk.WINDOW_TYPE_HINT_DIALOG)
- self._popupWindow.set_skip_pager_hint(True)
- self._popupWindow.set_skip_taskbar_hint(True)
-
- def run(self):
- self._popupWindow.show_all()
-
- def _on_day_selected(self, *args):
- try:
- self._calendar.select_month(self._displayDate.month, self._displayDate.year)
- self._calendar.select_day(self._displayDate.day)
- except Exception, e:
- _moduleLogger.exception(e)
-
-
-class QuickAddView(object):
-
- def __init__(self, widgetTree, errorDisplay, signalSink, prefix):
- self._errorDisplay = errorDisplay
- self._manager = None
- self._signalSink = signalSink
-
- self._clipboard = gtk.clipboard_get()
-
- self._taskNameEntry = widgetTree.get_widget(prefix+"-nameEntry")
- self._addTaskButton = widgetTree.get_widget(prefix+"-addButton")
- self._pasteTaskNameButton = widgetTree.get_widget(prefix+"-pasteNameButton")
- self._clearTaskNameButton = widgetTree.get_widget(prefix+"-clearNameButton")
- self._onAddId = None
- self._onAddClickedId = None
- self._onAddReleasedId = None
- self._addToEditTimerId = None
- self._onClearId = None
- self._onPasteId = None
-
- def enable(self, manager):
- self._manager = manager
-
- self._onAddId = self._addTaskButton.connect("clicked", self._on_add)
- self._onAddClickedId = self._addTaskButton.connect("pressed", self._on_add_pressed)
- self._onAddReleasedId = self._addTaskButton.connect("released", self._on_add_released)
- self._onPasteId = self._pasteTaskNameButton.connect("clicked", self._on_paste)
- self._onClearId = self._clearTaskNameButton.connect("clicked", self._on_clear)
-
- def disable(self):
- self._manager = None
-
- self._addTaskButton.disconnect(self._onAddId)
- self._addTaskButton.disconnect(self._onAddClickedId)
- self._addTaskButton.disconnect(self._onAddReleasedId)
- self._pasteTaskNameButton.disconnect(self._onPasteId)
- self._clearTaskNameButton.disconnect(self._onClearId)
-
- def set_addability(self, addability):
- self._addTaskButton.set_sensitive(addability)
-
- def _on_add(self, *args):
- try:
- name = self._taskNameEntry.get_text()
- self._taskNameEntry.set_text("")
-
- self._signalSink.stage.send(("add", name))
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_add_edit(self, *args):
- try:
- name = self._taskNameEntry.get_text()
- self._taskNameEntry.set_text("")
-
- self._signalSink.stage.send(("add-edit", name))
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_add_pressed(self, widget):
- try:
- self._addToEditTimerId = gobject.timeout_add(1000, self._on_add_edit)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_add_released(self, widget):
- try:
- if self._addToEditTimerId is not None:
- gobject.source_remove(self._addToEditTimerId)
- self._addToEditTimerId = None
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_paste(self, *args):
- try:
- entry = self._taskNameEntry.get_text()
- addedText = self._clipboard.wait_for_text()
- if addedText:
- entry += addedText
- self._taskNameEntry.set_text(entry)
- except Exception, e:
- self._errorDisplay.push_exception()
-
- def _on_clear(self, *args):
- try:
- self._taskNameEntry.set_text("")
- except Exception, e:
- self._errorDisplay.push_exception()
-
-
-class TapOrHold(object):
-
- def __init__(self, widget):
- self._widget = widget
- self._isTap = True
- self._isPointerInside = True
- self._holdTimeoutId = None
- self._tapTimeoutId = None
- self._taps = 0
-
- self._bpeId = None
- self._breId = None
- self._eneId = None
- self._lneId = None
-
- def enable(self):
- self._bpeId = self._widget.connect("button-press-event", self._on_button_press)
- self._breId = self._widget.connect("button-release-event", self._on_button_release)
- self._eneId = self._widget.connect("enter-notify-event", self._on_enter)
- self._lneId = self._widget.connect("leave-notify-event", self._on_leave)
-
- def disable(self):
- self._widget.disconnect(self._bpeId)
- self._widget.disconnect(self._breId)
- self._widget.disconnect(self._eneId)
- self._widget.disconnect(self._lneId)
-
- def on_tap(self, taps):
- print "TAP", taps
-
- def on_hold(self, taps):
- print "HOLD", taps
-
- def on_holding(self):
- print "HOLDING"
-
- def on_cancel(self):
- print "CANCEL"
-
- def _on_button_press(self, *args):
- # Hack to handle weird notebook behavior
- self._isPointerInside = True
- self._isTap = True
-
- if self._tapTimeoutId is not None:
- gobject.source_remove(self._tapTimeoutId)
- self._tapTimeoutId = None
-
- # Handle double taps
- if self._holdTimeoutId is None:
- self._tapTimeoutId = None
-
- self._taps = 1
- self._holdTimeoutId = gobject.timeout_add(1000, self._on_hold_timeout)
- else:
- self._taps = 2
-
- def _on_button_release(self, *args):
- assert self._tapTimeoutId is None
- # Handle release after timeout if user hasn't double-clicked
- self._tapTimeoutId = gobject.timeout_add(100, self._on_tap_timeout)
-
- def _on_actual_press(self, *args):
- if self._holdTimeoutId is not None:
- gobject.source_remove(self._holdTimeoutId)
- self._holdTimeoutId = None
-
- if self._isPointerInside:
- if self._isTap:
- self.on_tap(self._taps)
- else:
- self.on_hold(self._taps)
- else:
- self.on_cancel()
-
- def _on_tap_timeout(self, *args):
- self._tapTimeoutId = None
- self._on_actual_press()
- return False
-
- def _on_hold_timeout(self, *args):
- self._holdTimeoutId = None
- self._isTap = False
- self.on_holding()
- return False
-
- def _on_enter(self, *args):
- self._isPointerInside = True
-
- def _on_leave(self, *args):
- self._isPointerInside = False
-
-
-if __name__ == "__main__":
- if True:
- win = gtk.Window()
- win.set_title("Tap'N'Hold")
- eventBox = gtk.EventBox()
- win.add(eventBox)
-
- context = ContextHandler(eventBox, coroutines.printer_sink())
- context.enable()
- win.connect("destroy", lambda w: gtk.main_quit())
-
- win.show_all()
-
- if False:
- import datetime
- cal = PopupCalendar(None, datetime.datetime.now())
- cal._popupWindow.connect("destroy", lambda w: gtk.main_quit())
- cal.run()
-
- gtk.main()
+++ /dev/null
-#!/usr/bin/env python
-
-"""
-Open Issues
- @bug not all of a message is shown
- @bug Buttons are too small
-"""
-
-
-import gobject
-import gtk
-import dbus
-
-
-class _NullHildonModule(object):
- pass
-
-
-try:
- import hildon as _hildon
- hildon = _hildon # Dumb but gets around pyflakiness
-except (ImportError, OSError):
- hildon = _NullHildonModule
-
-
-IS_HILDON_SUPPORTED = hildon is not _NullHildonModule
-
-
-class _NullHildonProgram(object):
-
- def add_window(self, window):
- pass
-
-
-def _hildon_get_app_class():
- return hildon.Program
-
-
-def _null_get_app_class():
- return _NullHildonProgram
-
-
-try:
- hildon.Program
- get_app_class = _hildon_get_app_class
-except AttributeError:
- get_app_class = _null_get_app_class
-
-
-def _hildon_set_application_name(name):
- gtk.set_application_name(name)
-
-
-def _null_set_application_name(name):
- pass
-
-
-try:
- gtk.set_application_name
- set_application_name = _hildon_set_application_name
-except AttributeError:
- set_application_name = _null_set_application_name
-
-
-def _fremantle_hildonize_window(app, window):
- oldWindow = window
- newWindow = hildon.StackableWindow()
- if oldWindow.get_child() is not None:
- oldWindow.get_child().reparent(newWindow)
- app.add_window(newWindow)
- return newWindow
-
-
-def _hildon_hildonize_window(app, window):
- oldWindow = window
- newWindow = hildon.Window()
- if oldWindow.get_child() is not None:
- oldWindow.get_child().reparent(newWindow)
- app.add_window(newWindow)
- return newWindow
-
-
-def _null_hildonize_window(app, window):
- return window
-
-
-try:
- hildon.StackableWindow
- hildonize_window = _fremantle_hildonize_window
-except AttributeError:
- try:
- hildon.Window
- hildonize_window = _hildon_hildonize_window
- except AttributeError:
- hildonize_window = _null_hildonize_window
-
-
-def _fremantle_hildonize_menu(window, gtkMenu):
- appMenu = hildon.AppMenu()
- window.set_app_menu(appMenu)
- gtkMenu.get_parent().remove(gtkMenu)
- return appMenu
-
-
-def _hildon_hildonize_menu(window, gtkMenu):
- hildonMenu = gtk.Menu()
- for child in gtkMenu.get_children():
- child.reparent(hildonMenu)
- window.set_menu(hildonMenu)
- gtkMenu.destroy()
- return hildonMenu
-
-
-def _null_hildonize_menu(window, gtkMenu):
- return gtkMenu
-
-
-try:
- hildon.AppMenu
- GTK_MENU_USED = False
- IS_FREMANTLE_SUPPORTED = True
- hildonize_menu = _fremantle_hildonize_menu
-except AttributeError:
- GTK_MENU_USED = True
- IS_FREMANTLE_SUPPORTED = False
- if IS_HILDON_SUPPORTED:
- hildonize_menu = _hildon_hildonize_menu
- else:
- hildonize_menu = _null_hildonize_menu
-
-
-def _hildon_set_button_auto_selectable(button):
- button.set_theme_size(hildon.HILDON_SIZE_AUTO_HEIGHT)
-
-
-def _null_set_button_auto_selectable(button):
- pass
-
-
-try:
- hildon.HILDON_SIZE_AUTO_HEIGHT
- gtk.Button.set_theme_size
- set_button_auto_selectable = _hildon_set_button_auto_selectable
-except AttributeError:
- set_button_auto_selectable = _null_set_button_auto_selectable
-
-
-def _hildon_set_button_finger_selectable(button):
- button.set_theme_size(hildon.HILDON_SIZE_FINGER_HEIGHT)
-
-
-def _null_set_button_finger_selectable(button):
- pass
-
-
-try:
- hildon.HILDON_SIZE_FINGER_HEIGHT
- gtk.Button.set_theme_size
- set_button_finger_selectable = _hildon_set_button_finger_selectable
-except AttributeError:
- set_button_finger_selectable = _null_set_button_finger_selectable
-
-
-def _hildon_set_button_thumb_selectable(button):
- button.set_theme_size(hildon.HILDON_SIZE_THUMB_HEIGHT)
-
-
-def _null_set_button_thumb_selectable(button):
- pass
-
-
-try:
- hildon.HILDON_SIZE_THUMB_HEIGHT
- gtk.Button.set_theme_size
- set_button_thumb_selectable = _hildon_set_button_thumb_selectable
-except AttributeError:
- set_button_thumb_selectable = _null_set_button_thumb_selectable
-
-
-def _hildon_set_cell_thumb_selectable(renderer):
- renderer.set_property("scale", 1.5)
-
-
-def _null_set_cell_thumb_selectable(renderer):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- set_cell_thumb_selectable = _hildon_set_cell_thumb_selectable
-else:
- set_cell_thumb_selectable = _null_set_cell_thumb_selectable
-
-
-def _hildon_set_pix_cell_thumb_selectable(renderer):
- renderer.set_property("stock-size", 48)
-
-
-def _null_set_pix_cell_thumb_selectable(renderer):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- set_pix_cell_thumb_selectable = _hildon_set_pix_cell_thumb_selectable
-else:
- set_pix_cell_thumb_selectable = _null_set_pix_cell_thumb_selectable
-
-
-def _fremantle_show_information_banner(parent, message):
- hildon.hildon_banner_show_information(parent, "", message)
-
-
-def _hildon_show_information_banner(parent, message):
- hildon.hildon_banner_show_information(parent, None, message)
-
-
-def _null_show_information_banner(parent, message):
- pass
-
-
-if IS_FREMANTLE_SUPPORTED:
- show_information_banner = _fremantle_show_information_banner
-else:
- try:
- hildon.hildon_banner_show_information
- show_information_banner = _hildon_show_information_banner
- except AttributeError:
- show_information_banner = _null_show_information_banner
-
-
-def _fremantle_show_busy_banner_start(parent, message):
- hildon.hildon_gtk_window_set_progress_indicator(parent, True)
- return parent
-
-
-def _fremantle_show_busy_banner_end(banner):
- hildon.hildon_gtk_window_set_progress_indicator(banner, False)
-
-
-def _hildon_show_busy_banner_start(parent, message):
- return hildon.hildon_banner_show_animation(parent, None, message)
-
-
-def _hildon_show_busy_banner_end(banner):
- banner.destroy()
-
-
-def _null_show_busy_banner_start(parent, message):
- return None
-
-
-def _null_show_busy_banner_end(banner):
- assert banner is None
-
-
-try:
- hildon.hildon_gtk_window_set_progress_indicator
- show_busy_banner_start = _fremantle_show_busy_banner_start
- show_busy_banner_end = _fremantle_show_busy_banner_end
-except AttributeError:
- try:
- hildon.hildon_banner_show_animation
- show_busy_banner_start = _hildon_show_busy_banner_start
- show_busy_banner_end = _hildon_show_busy_banner_end
- except AttributeError:
- show_busy_banner_start = _null_show_busy_banner_start
- show_busy_banner_end = _null_show_busy_banner_end
-
-
-def _hildon_hildonize_text_entry(textEntry):
- textEntry.set_property('hildon-input-mode', 7)
-
-
-def _null_hildonize_text_entry(textEntry):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- hildonize_text_entry = _hildon_hildonize_text_entry
-else:
- hildonize_text_entry = _null_hildonize_text_entry
-
-
-def _hildon_window_to_portrait(window):
- # gtk documentation is unclear whether this does a "=" or a "|="
- flags = hildon.PORTRAIT_MODE_SUPPORT | hildon.PORTRAIT_MODE_REQUEST
- hildon.hildon_gtk_window_set_portrait_flags(window, flags)
-
-
-def _hildon_window_to_landscape(window):
- # gtk documentation is unclear whether this does a "=" or a "&= ~"
- flags = hildon.PORTRAIT_MODE_SUPPORT
- hildon.hildon_gtk_window_set_portrait_flags(window, flags)
-
-
-def _null_window_to_portrait(window):
- pass
-
-
-def _null_window_to_landscape(window):
- pass
-
-
-try:
- hildon.PORTRAIT_MODE_SUPPORT
- hildon.PORTRAIT_MODE_REQUEST
- hildon.hildon_gtk_window_set_portrait_flags
-
- window_to_portrait = _hildon_window_to_portrait
- window_to_landscape = _hildon_window_to_landscape
-except AttributeError:
- window_to_portrait = _null_window_to_portrait
- window_to_landscape = _null_window_to_landscape
-
-
-def get_device_orientation():
- bus = dbus.SystemBus()
- try:
- rawMceRequest = bus.get_object("com.nokia.mce", "/com/nokia/mce/request")
- mceRequest = dbus.Interface(rawMceRequest, dbus_interface="com.nokia.mce.request")
- orientation, standState, faceState, xAxis, yAxis, zAxis = mceRequest.get_device_orientation()
- except dbus.exception.DBusException:
- # catching for documentation purposes that when a system doesn't
- # support this, this is what to expect
- raise
-
- if orientation == "":
- return gtk.ORIENTATION_HORIZONTAL
- elif orientation == "":
- return gtk.ORIENTATION_VERTICAL
- else:
- raise RuntimeError("Unknown orientation: %s" % orientation)
-
-
-def _hildon_hildonize_password_entry(textEntry):
- textEntry.set_property('hildon-input-mode', 7 | (1 << 29))
-
-
-def _null_hildonize_password_entry(textEntry):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- hildonize_password_entry = _hildon_hildonize_password_entry
-else:
- hildonize_password_entry = _null_hildonize_password_entry
-
-
-def _hildon_hildonize_combo_entry(comboEntry):
- comboEntry.set_property('hildon-input-mode', 1 << 4)
-
-
-def _null_hildonize_combo_entry(textEntry):
- pass
-
-
-if IS_HILDON_SUPPORTED:
- hildonize_combo_entry = _hildon_hildonize_combo_entry
-else:
- hildonize_combo_entry = _null_hildonize_combo_entry
-
-
-def _null_create_seekbar():
- adjustment = gtk.Adjustment(0, 0, 101, 1, 5, 1)
- seek = gtk.HScale(adjustment)
- seek.set_draw_value(False)
- return seek
-
-
-def _fremantle_create_seekbar():
- seek = hildon.Seekbar()
- seek.set_range(0.0, 100)
- seek.set_draw_value(False)
- seek.set_update_policy(gtk.UPDATE_DISCONTINUOUS)
- return seek
-
-
-try:
- hildon.Seekbar
- create_seekbar = _fremantle_create_seekbar
-except AttributeError:
- create_seekbar = _null_create_seekbar
-
-
-def _fremantle_hildonize_scrollwindow(scrolledWindow):
- pannableWindow = hildon.PannableArea()
-
- child = scrolledWindow.get_child()
- scrolledWindow.remove(child)
- pannableWindow.add(child)
-
- parent = scrolledWindow.get_parent()
- if parent is not None:
- parent.remove(scrolledWindow)
- parent.add(pannableWindow)
-
- return pannableWindow
-
-
-def _hildon_hildonize_scrollwindow(scrolledWindow):
- hildon.hildon_helper_set_thumb_scrollbar(scrolledWindow, True)
- return scrolledWindow
-
-
-def _null_hildonize_scrollwindow(scrolledWindow):
- return scrolledWindow
-
-
-try:
- hildon.PannableArea
- hildonize_scrollwindow = _fremantle_hildonize_scrollwindow
- hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
-except AttributeError:
- try:
- hildon.hildon_helper_set_thumb_scrollbar
- hildonize_scrollwindow = _hildon_hildonize_scrollwindow
- hildonize_scrollwindow_with_viewport = _hildon_hildonize_scrollwindow
- except AttributeError:
- hildonize_scrollwindow = _null_hildonize_scrollwindow
- hildonize_scrollwindow_with_viewport = _null_hildonize_scrollwindow
-
-
-def _hildon_request_number(parent, title, range, default):
- spinner = hildon.NumberEditor(*range)
- spinner.set_value(default)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(spinner)
-
- try:
- dialog.show_all()
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- return spinner.get_value()
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
- finally:
- dialog.hide()
- dialog.destroy()
-
-
-def _null_request_number(parent, title, range, default):
- adjustment = gtk.Adjustment(default, range[0], range[1], 1, 5, 0)
- spinner = gtk.SpinButton(adjustment, 0, 0)
- spinner.set_wrap(False)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(spinner)
-
- try:
- dialog.show_all()
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- return spinner.get_value_as_int()
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
- finally:
- dialog.hide()
- dialog.destroy()
-
-
-try:
- hildon.NumberEditor # TODO deprecated in fremantle
- request_number = _hildon_request_number
-except AttributeError:
- request_number = _null_request_number
-
-
-def _hildon_touch_selector(parent, title, items, defaultIndex):
- model = gtk.ListStore(gobject.TYPE_STRING)
- for item in items:
- model.append((item, ))
-
- selector = hildon.TouchSelector()
- selector.append_text_column(model, True)
- selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_SINGLE)
- selector.set_active(0, defaultIndex)
-
- dialog = hildon.PickerDialog(parent)
- dialog.set_selector(selector)
-
- try:
- dialog.show_all()
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- return selector.get_active(0)
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
- finally:
- dialog.hide()
- dialog.destroy()
-
-
-def _on_null_touch_selector_activated(treeView, path, column, dialog, pathData):
- dialog.response(gtk.RESPONSE_OK)
- pathData[0] = path
-
-
-def _null_touch_selector(parent, title, items, defaultIndex = -1):
- parentSize = parent.get_size()
-
- model = gtk.ListStore(gobject.TYPE_STRING)
- for item in items:
- model.append((item, ))
-
- cell = gtk.CellRendererText()
- set_cell_thumb_selectable(cell)
- column = gtk.TreeViewColumn(title)
- column.pack_start(cell, expand=True)
- column.add_attribute(cell, "text", 0)
-
- treeView = gtk.TreeView()
- treeView.set_model(model)
- treeView.append_column(column)
- selection = treeView.get_selection()
- selection.set_mode(gtk.SELECTION_SINGLE)
- if 0 < defaultIndex:
- selection.select_path((defaultIndex, ))
-
- scrolledWin = gtk.ScrolledWindow()
- scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scrolledWin.add(treeView)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(scrolledWin)
- dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
-
- scrolledWin = hildonize_scrollwindow(scrolledWin)
- pathData = [None]
- treeView.connect("row-activated", _on_null_touch_selector_activated, dialog, pathData)
-
- try:
- dialog.show_all()
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- if pathData[0] is None:
- raise RuntimeError("No selection made")
- return pathData[0][0]
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
- finally:
- dialog.hide()
- dialog.destroy()
-
-
-try:
- hildon.PickerDialog
- hildon.TouchSelector
- touch_selector = _hildon_touch_selector
-except AttributeError:
- touch_selector = _null_touch_selector
-
-
-def _hildon_touch_selector_entry(parent, title, items, defaultItem):
- # Got a segfault when using append_text_column with TouchSelectorEntry, so using this way
- try:
- selector = hildon.TouchSelectorEntry(text=True)
- except TypeError:
- selector = hildon.hildon_touch_selector_entry_new_text()
- defaultIndex = -1
- for i, item in enumerate(items):
- selector.append_text(item)
- if item == defaultItem:
- defaultIndex = i
-
- dialog = hildon.PickerDialog(parent)
- dialog.set_selector(selector)
-
- if 0 < defaultIndex:
- selector.set_active(0, defaultIndex)
- else:
- selector.get_entry().set_text(defaultItem)
-
- try:
- dialog.show_all()
- response = dialog.run()
- finally:
- dialog.hide()
-
- if response == gtk.RESPONSE_OK:
- return selector.get_entry().get_text()
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
-
-
-def _on_null_touch_selector_entry_entry_changed(entry, result, selection, defaultIndex):
- custom = entry.get_text().strip()
- if custom:
- result[0] = custom
- selection.unselect_all()
- else:
- result[0] = None
- selection.select_path((defaultIndex, ))
-
-
-def _on_null_touch_selector_entry_entry_activated(customEntry, dialog, result):
- dialog.response(gtk.RESPONSE_OK)
- result[0] = customEntry.get_text()
-
-
-def _on_null_touch_selector_entry_tree_activated(treeView, path, column, dialog, result):
- dialog.response(gtk.RESPONSE_OK)
- model = treeView.get_model()
- itr = model.get_iter(path)
- if itr is not None:
- result[0] = model.get_value(itr, 0)
-
-
-def _null_touch_selector_entry(parent, title, items, defaultItem):
- parentSize = parent.get_size()
-
- model = gtk.ListStore(gobject.TYPE_STRING)
- defaultIndex = -1
- for i, item in enumerate(items):
- model.append((item, ))
- if item == defaultItem:
- defaultIndex = i
-
- cell = gtk.CellRendererText()
- set_cell_thumb_selectable(cell)
- column = gtk.TreeViewColumn(title)
- column.pack_start(cell, expand=True)
- column.add_attribute(cell, "text", 0)
-
- treeView = gtk.TreeView()
- treeView.set_model(model)
- treeView.append_column(column)
- selection = treeView.get_selection()
- selection.set_mode(gtk.SELECTION_SINGLE)
-
- scrolledWin = gtk.ScrolledWindow()
- scrolledWin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- scrolledWin.add(treeView)
-
- customEntry = gtk.Entry()
-
- layout = gtk.VBox()
- layout.pack_start(customEntry, expand=False)
- layout.pack_start(scrolledWin)
-
- dialog = gtk.Dialog(
- title,
- parent,
- gtk.DIALOG_MODAL|gtk.DIALOG_DESTROY_WITH_PARENT,
- (gtk.STOCK_OK, gtk.RESPONSE_OK, gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL),
- )
- dialog.set_default_response(gtk.RESPONSE_CANCEL)
- dialog.get_child().add(layout)
- dialog.resize(parentSize[0], max(parentSize[1]-100, 100))
-
- scrolledWin = hildonize_scrollwindow(scrolledWin)
-
- result = [None]
- if 0 < defaultIndex:
- selection.select_path((defaultIndex, ))
- result[0] = defaultItem
- else:
- customEntry.set_text(defaultItem)
-
- customEntry.connect("activate", _on_null_touch_selector_entry_entry_activated, dialog, result)
- customEntry.connect("changed", _on_null_touch_selector_entry_entry_changed, result, selection, defaultIndex)
- treeView.connect("row-activated", _on_null_touch_selector_entry_tree_activated, dialog, result)
-
- try:
- dialog.show_all()
- response = dialog.run()
-
- if response == gtk.RESPONSE_OK:
- _, itr = selection.get_selected()
- if itr is not None:
- return model.get_value(itr, 0)
- else:
- enteredText = customEntry.get_text().strip()
- if enteredText:
- return enteredText
- elif result[0] is not None:
- return result[0]
- else:
- raise RuntimeError("No selection made")
- elif response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_DELETE_EVENT:
- raise RuntimeError("User cancelled request")
- else:
- raise RuntimeError("Unrecognized response %r", response)
- finally:
- dialog.hide()
- dialog.destroy()
-
-
-try:
- hildon.PickerDialog
- hildon.TouchSelectorEntry
- touch_selector_entry = _hildon_touch_selector_entry
-except AttributeError:
- touch_selector_entry = _null_touch_selector_entry
-
-
-if __name__ == "__main__":
- app = get_app_class()()
-
- label = gtk.Label("Hello World from a Label!")
-
- win = gtk.Window()
- win.add(label)
- win = hildonize_window(app, win)
- if False and IS_FREMANTLE_SUPPORTED:
- appMenu = hildon.AppMenu()
- for i in xrange(5):
- b = gtk.Button(str(i))
- appMenu.append(b)
- win.set_app_menu(appMenu)
- win.show_all()
- appMenu.show_all()
- gtk.main()
- elif False:
- print touch_selector(win, "Test", ["A", "B", "C", "D"], 2)
- elif False:
- print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "C")
- print touch_selector_entry(win, "Test", ["A", "B", "C", "D"], "Blah")
- elif False:
- import pprint
- name, value = "", ""
- goodLocals = [
- (name, value) for (name, value) in locals().iteritems()
- if not name.startswith("_")
- ]
- pprint.pprint(goodLocals)
- elif False:
- import time
- show_information_banner(win, "Hello World")
- time.sleep(5)
- elif False:
- import time
- banner = show_busy_banner_start(win, "Hello World")
- time.sleep(5)
- show_busy_banner_end(banner)