From 8575f4276c5854670873131eb16b20f36138fcd8 Mon Sep 17 00:00:00 2001 From: Juke Date: Thu, 4 Feb 2010 16:07:13 +0100 Subject: [PATCH] initial commit --- example.cfg | 10 ++++ gtk_transilien.py | 123 ++++++++++++++++++++++++++++++++++++++ portrait.py | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 305 insertions(+) create mode 100644 example.cfg create mode 100755 gtk_transilien.py create mode 100644 portrait.py diff --git a/example.cfg b/example.cfg new file mode 100644 index 0000000..b7d87ce --- /dev/null +++ b/example.cfg @@ -0,0 +1,10 @@ +[ListeDesGares] +bibliotheque francois mitterand = BFM +savigny sur orge = SAO +melun = MEL +juvisy = JY +gare de lyon = PAA +chatelet = CLX +villeneuve st georges = VSG +le mee = WEE + diff --git a/gtk_transilien.py b/gtk_transilien.py new file mode 100755 index 0000000..e221c31 --- /dev/null +++ b/gtk_transilien.py @@ -0,0 +1,123 @@ +#!/usr/bin/python +import pygtk +pygtk.require("2.0") +import gtk +import urllib2 +import HTMLParser +import hildon +import ConfigParser + +from portrait import FremantleRotation + +#main_window = mainWindow # your main hildon.StackableWindow +app_name = 'NameOfYourApp' # the name of your app +app_version = '1.0' # the version number of your app +initial_mode = FremantleRotation.AUTOMATIC + +class tableParser(HTMLParser.HTMLParser): + def __init__(self): + HTMLParser.HTMLParser.__init__(self) + self.table_horaires3 = False + self.code_de_mission = False + self.a_code_de_mission = False + self.heure_de_passage = False + self.liste_train = [] + self.liste_horaire = [] + + def handle_starttag(self, tag, attrs): + if (tag == 'table' and (dict(attrs)['class'] == 'horaires3')): + self.table_horaires3 = True + + elif self.table_horaires3 and tag == 'td': + try: + self.code_de_mission = ( + dict(attrs)['headers'] == 'Code_de_mission') + self.heure_de_passage = ( + dict(attrs)['headers'] == 'Heure_de_passage') + except KeyError: + if dict(attrs).has_key('headers'): + raise + else: + pass + else: + self.a_code_de_mission = (tag == 'a' and self.code_de_mission) + + def handle_data(self, data): + if self.a_code_de_mission: + self.liste_train.append(data.strip()) + if self.heure_de_passage: + self.liste_horaire.append(data.strip()) + + def handle_endtag(self,tag): + self.a_code_de_mission ^= (self.a_code_de_mission and tag == 'a') + self.heure_de_passage ^= (self.heure_de_passage and tag == 'td') + +class TransilienUI: + def __init__(self): + mainWindow = hildon.Window() + mainWindow.set_title("Horaires des Prochains Trains") + mainWindow.connect("destroy", self.on_mainWindow_destroy) + + rotation_object = FremantleRotation(app_name, mainWindow, app_version, initial_mode) + refreshButton = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, + hildon.BUTTON_ARRANGEMENT_HORIZONTAL, "Actualiser") + refreshButton.connect("clicked", self.on_refreshButton_clicked) + + self.treestore = gtk.TreeStore(str, str) + self.treeview = gtk.TreeView(self.treestore) + + self.tvcolumn_train = gtk.TreeViewColumn('Train', gtk.CellRendererText(), text=0) + self.treeview.append_column(self.tvcolumn_train) + + self.tvcolumn_horaire = gtk.TreeViewColumn('Horaire', gtk.CellRendererText(), text=1) + self.treeview.append_column(self.tvcolumn_horaire) + + + picker_button_source = hildon.PickerButton(gtk.HILDON_SIZE_AUTO, hildon.BUTTON_ARRANGEMENT_VERTICAL) + picker_button_source.set_title("Gare de Depart") + self.combo_source = hildon.TouchSelectorEntry(text=True) + self.combo_dest = hildon.TouchSelectorEntry(text=True) + + self.c = ConfigParser.ConfigParser() + self.c.read('example.cfg') + for i in self.c.items('ListeDesGares'): + self.combo_source.append_text(i[0]) + self.combo_dest.append_text(i[0]) + picker_button_source.set_selector(self.combo_source) + + + picker_button_dest = hildon.PickerButton(gtk.HILDON_SIZE_AUTO, hildon.BUTTON_ARRANGEMENT_VERTICAL) + picker_button_dest.set_title("Gare d'arrivee") + picker_button_dest.set_selector(self.combo_dest) + + + vBox = gtk.VBox() + hBox = gtk.HBox() + vBox.pack_start(hBox) + hBox.pack_start(picker_button_source) + hBox.pack_start(picker_button_dest) + vBox.pack_start(self.treeview) + vBox.pack_start(refreshButton) + + + mainWindow.add(vBox) + mainWindow.show_all() + + def on_mainWindow_destroy(self, widget): + gtk.main_quit() + + def on_refreshButton_clicked(self, widget): + self.treestore.clear() + p = tableParser() + print self.c.get('ListeDesGares', self.combo_source.get_current_text()) + print self.c.get('ListeDesGares', self.combo_dest.get_current_text()) + p.feed(urllib2.urlopen('http://www.transilien.com/web/ITProchainsTrainsAvecDest.do?codeTr3aDepart='+self.c.get('ListeDesGares', self.combo_source.get_current_text())+'&codeTr3aDest='+self.c.get('ListeDesGares', self.combo_dest.get_current_text())+'&urlModule=/site/pid/184&gareAcc=true').read()) + z=0 + for i in p.liste_train: + print p.liste_horaire[z] + self.treestore.append(None, [i, p.liste_horaire[z]]) + z += 1 + +if __name__ == "__main__": + TransilienUI() + gtk.main() diff --git a/portrait.py b/portrait.py new file mode 100644 index 0000000..ce16aa8 --- /dev/null +++ b/portrait.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# +# gPodder - A media aggregator and podcast client +# Copyright (c) 2005-2010 Thomas Perl and the gPodder Team +# +# gPodder is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# gPodder is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# + +import dbus +import dbus.glib + +import hildon +import osso + +# Replace this with your own gettext() functionality +import gpodder +_ = gpodder.gettext + + +class FremantleRotation(object): + """thp's screen rotation for Maemo 5 + + Simply instantiate an object of this class and let it auto-rotate + your StackableWindows depending on the device orientation. + + If you need to relayout a window, connect to its "configure-event" + signal and measure the ratio of width/height and relayout for that. + + You can set the mode for rotation to AUTOMATIC (default), NEVER or + ALWAYS with the set_mode() method. + """ + AUTOMATIC, NEVER, ALWAYS = range(3) + + # Human-readable captions for the above constants + MODE_CAPTIONS = (_('Automatic'), _('Landscape'), _('Portrait')) + + # Privately-used constants + _PORTRAIT, _LANDSCAPE = ('portrait', 'landscape') + _ENABLE_ACCEL = 'req_accelerometer_enable' + _DISABLE_ACCEL = 'req_accelerometer_disable' + + # Defined in mce/dbus-names.h + _MCE_SERVICE = 'com.nokia.mce' + _MCE_REQUEST_PATH = '/com/nokia/mce/request' + _MCE_REQUEST_IF = 'com.nokia.mce.request' + + def __init__(self, app_name, main_window=None, version='1.0', mode=0): + """Create a new rotation manager + + app_name ... The name of your application (for osso.Context) + main_window ... The root window (optional, hildon.StackableWindow) + version ... The version of your application (optional, string) + mode ... Initial mode for this manager (default: AUTOMATIC) + """ + self._orientation = None + self._main_window = main_window + self._stack = hildon.WindowStack.get_default() + self._mode = -1 + self._last_dbus_orientation = None + app_id = '-'.join((app_name, self.__class__.__name__)) + self._osso_context = osso.Context(app_id, version, False) + program = hildon.Program.get_instance() + program.connect('notify::is-topmost', self._on_topmost_changed) + system_bus = dbus.Bus.get_system() + system_bus.add_signal_receiver(self._on_orientation_signal, \ + signal_name='sig_device_orientation_ind', \ + dbus_interface='com.nokia.mce.signal', \ + path='/com/nokia/mce/signal') + self.set_mode(mode) + + def get_mode(self): + """Get the currently-set rotation mode + + This will return one of three values: AUTOMATIC, ALWAYS or NEVER. + """ + return self._mode + + def set_mode(self, new_mode): + """Set the rotation mode + + You can set the rotation mode to AUTOMATIC (use hardware rotation + info), ALWAYS (force portrait) and NEVER (force landscape). + """ + if new_mode not in (self.AUTOMATIC, self.ALWAYS, self.NEVER): + raise ValueError('Unknown rotation mode') + + if self._mode != new_mode: + if self._mode == self.AUTOMATIC: + # Remember the current "automatic" orientation for later + self._last_dbus_orientation = self._orientation + # Tell MCE that we don't need the accelerometer anymore + self._send_mce_request(self._DISABLE_ACCEL) + + if new_mode == self.NEVER: + self._orientation_changed(self._LANDSCAPE) + elif new_mode == self.ALWAYS: + self._orientation_changed(self._PORTRAIT) + elif new_mode == self.AUTOMATIC: + # Restore the last-known "automatic" orientation + self._orientation_changed(self._last_dbus_orientation) + # Tell MCE that we need the accelerometer again + self._send_mce_request(self._ENABLE_ACCEL) + + self._mode = new_mode + + def _send_mce_request(self, request): + rpc = osso.Rpc(self._osso_context) + rpc.rpc_run(self._MCE_SERVICE, \ + self._MCE_REQUEST_PATH, \ + self._MCE_REQUEST_IF, \ + request, \ + use_system_bus=True) + + def _on_topmost_changed(self, program, property_spec): + # XXX: This seems to never get called on Fremantle(?) + if self._mode == self.AUTOMATIC: + if program.get_is_topmost(): + self._send_mce_request(self._ENABLE_ACCEL) + else: + self._send_mce_request(self._DISABLE_ACCEL) + + def _get_main_window(self): + if self._main_window: + # If we have gotten the main window as parameter, return it and + # don't try "harder" to find another window using the stack + return self._main_window + else: + # The main window is at the "bottom" of the window stack, and as + # the list we get with get_windows() is sorted "topmost first", we + # simply take the last item of the list to get our main window + windows = self._stack.get_windows() + if windows: + return windows[-1] + else: + return None + + def _orientation_changed(self, orientation): + if self._orientation == orientation: + # Ignore repeated requests + return + + flags = hildon.PORTRAIT_MODE_SUPPORT + if orientation == self._PORTRAIT: + flags |= hildon.PORTRAIT_MODE_REQUEST + + window = self._get_main_window() + if window is not None: + hildon.hildon_gtk_window_set_portrait_flags(window, flags) + + self._orientation = orientation + + def _on_orientation_signal(self, orientation, stand, face, x, y, z): + if orientation in (self._PORTRAIT, self._LANDSCAPE): + if self._mode == self.AUTOMATIC: + # Automatically set the rotation based on hardware orientation + self._orientation_changed(orientation) + else: + # Ignore orientation changes for non-automatic modes, but save + # the current orientation for "automatic" mode later on + self._last_dbus_orientation = orientation + -- 1.7.9.5