TODO : faire des try sur les import
TODO : documenter les classes
-
DONE 0.1.1 : Modélisation Objet
DONE 0.1.2 : Corriger l'indentation
DONE 0.1.3 : Faire un objet ListeHoraire
-
-
-
-
-
-
+ DONE 0.1.4 : Faire un .deb
+++ /dev/null
-[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
-
+++ /dev/null
-#!/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 LigneHoraire(object):
- def __init__(self, code_mission, heure_de_passage):
- self.code_mission = code_mission
- self.heure_de_passage = heure_de_passage
-
- def add_to_treestore(self, treestore):
- print treestore
- treestore.append(None, [self.code_mission, self.heure_de_passage])
-
-
-
-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 = []
- self.list_ligne_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')
-
- def get_list_ligne_horaire(self):
- print 'get_list_ligne_horaire'
- z = 0
- print self.liste_train
- for i in self.liste_train:
- self.list_ligne_horaire.append(LigneHoraire(code_mission=i, heure_de_passage=self.liste_horaire[z]))
- z += 1
- return self.list_ligne_horaire
-
-
-
-class Trajet(object):
- def __init__(self, gare_source, gare_dest):
- self.gare_source = gare_source
- self.gare_dest = gare_dest
- self.parse()
- def get_liste_train(self):
- return self.p.liste_train
- def get_liste_horaire(self):
- return self.p.liste_horaire
- def parse(self):
- self.p = tableParser()
- #print "URL:"
- #print 'http://www.transilien.com/web/ITProchainsTrainsAvecDest.do?codeTr3aDepart='+self.gare_source.shortname+'&codeTr3aDest='+self.gare_dest.shortname+'&urlModule=/site/pid/184&gareAcc=true'
- rsrc = urllib2.urlopen('http://www.transilien.com/web/ITProchainsTrainsAvecDest.do?codeTr3aDepart='+self.gare_source.shortname+'&codeTr3aDest='+self.gare_dest.shortname+'&urlModule=/site/pid/184&gareAcc=true')
- self.p.feed(rsrc.read())
- print "parsing ok"
-
- def refresh_treestore(self, treestore):
- print 'refresh'
- print treestore
-
- treestore.clear()
- liste_ligne_horaire = self.p.get_list_ligne_horaire()
- print liste_ligne_horaire
- for i in liste_ligne_horaire:
- print i
- i.add_to_treestore(treestore)
-
-class ConfFile(object):
- def __init__(self, fichier):
- self.c = ConfigParser.ConfigParser()
- self.c.read(fichier)
- def get_short_name(self, longname):
- return self.c.get('ListeDesGares', longname)
- def get_liste_des_gares(self):
- return self.c.items('ListeDesGares')
-
-class LongNameGare(object):
- def __init__(self, longname):
- self.longname = longname
- def get_gare(self, conffile):
- short_name = conffile.get_short_name(self.longname)
- return Gare(short_name)
-
-class Gare(object):
- def __init__(self, shortname):
- self.shortname = shortname
-
-
-
-
-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)
-
- for i in ConfFile('example.cfg').get_liste_des_gares():
- 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):
- gare_source = LongNameGare(self.combo_source.get_current_text()).get_gare(ConfFile('example.cfg'))
- gare_dest = LongNameGare(self.combo_dest.get_current_text()).get_gare(ConfFile('example.cfg'))
- trajet = Trajet(gare_source , gare_dest)
- print trajet
- print self.treestore
- trajet.refresh_treestore(self.treestore)
-
-
-if __name__ == "__main__":
- TransilienUI()
- gtk.main()
+++ /dev/null
-# -*- 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 <http://www.gnu.org/licenses/>.
-#
-
-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
-
--- /dev/null
+[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
+
--- /dev/null
+#!/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 LigneHoraire(object):
+ def __init__(self, code_mission, heure_de_passage):
+ self.code_mission = code_mission
+ self.heure_de_passage = heure_de_passage
+
+ def add_to_treestore(self, treestore):
+ print treestore
+ treestore.append(None, [self.code_mission, self.heure_de_passage])
+
+
+
+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 = []
+ self.list_ligne_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')
+
+ def get_list_ligne_horaire(self):
+ print 'get_list_ligne_horaire'
+ z = 0
+ print self.liste_train
+ for i in self.liste_train:
+ self.list_ligne_horaire.append(LigneHoraire(code_mission=i, heure_de_passage=self.liste_horaire[z]))
+ z += 1
+ return self.list_ligne_horaire
+
+
+
+class Trajet(object):
+ def __init__(self, gare_source, gare_dest):
+ self.gare_source = gare_source
+ self.gare_dest = gare_dest
+ self.parse()
+ def get_liste_train(self):
+ return self.p.liste_train
+ def get_liste_horaire(self):
+ return self.p.liste_horaire
+ def parse(self):
+ self.p = tableParser()
+ #print "URL:"
+ #print 'http://www.transilien.com/web/ITProchainsTrainsAvecDest.do?codeTr3aDepart='+self.gare_source.shortname+'&codeTr3aDest='+self.gare_dest.shortname+'&urlModule=/site/pid/184&gareAcc=true'
+ rsrc = urllib2.urlopen('http://www.transilien.com/web/ITProchainsTrainsAvecDest.do?codeTr3aDepart='+self.gare_source.shortname+'&codeTr3aDest='+self.gare_dest.shortname+'&urlModule=/site/pid/184&gareAcc=true')
+ self.p.feed(rsrc.read())
+ print "parsing ok"
+
+ def refresh_treestore(self, treestore):
+ print 'refresh'
+ print treestore
+
+ treestore.clear()
+ liste_ligne_horaire = self.p.get_list_ligne_horaire()
+ print liste_ligne_horaire
+ for i in liste_ligne_horaire:
+ print i
+ i.add_to_treestore(treestore)
+
+class ConfFile(object):
+ def __init__(self, fichier):
+ self.c = ConfigParser.ConfigParser()
+ self.c.read(fichier)
+ def get_short_name(self, longname):
+ return self.c.get('ListeDesGares', longname)
+ def get_liste_des_gares(self):
+ return self.c.items('ListeDesGares')
+
+class LongNameGare(object):
+ def __init__(self, longname):
+ self.longname = longname
+ def get_gare(self, conffile):
+ short_name = conffile.get_short_name(self.longname)
+ return Gare(short_name)
+
+class Gare(object):
+ def __init__(self, shortname):
+ self.shortname = shortname
+
+
+
+
+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)
+
+ for i in ConfFile('example.cfg').get_liste_des_gares():
+ 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):
+ gare_source = LongNameGare(self.combo_source.get_current_text()).get_gare(ConfFile('example.cfg'))
+ gare_dest = LongNameGare(self.combo_dest.get_current_text()).get_gare(ConfFile('example.cfg'))
+ trajet = Trajet(gare_source , gare_dest)
+ print trajet
+ print self.treestore
+ trajet.refresh_treestore(self.treestore)
+
+
+if __name__ == "__main__":
+ TransilienUI()
+ gtk.main()
--- /dev/null
+# -*- 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 <http://www.gnu.org/licenses/>.
+#
+
+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
+