09ebb5dba3e656ede0c1a836a930a1ec0b87679f
[watersofshiloah] / src / mormonchannel_gtk.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3
4 from __future__ import with_statement
5
6 import gc
7 import logging
8 import ConfigParser
9
10 import gtk
11
12 try:
13         import hildon
14 except ImportError:
15         hildon = None
16
17 try:
18         import osso
19 except ImportError:
20         osso = None
21
22 import constants
23 import hildonize
24 import gtk_toolbox
25
26 import imagestore
27 import player
28 import windows
29
30
31 _moduleLogger = logging.getLogger(__name__)
32 PROFILE_STARTUP = False
33
34
35 class MormonChannelProgram(hildonize.get_app_class()):
36
37         def __init__(self):
38                 super(MormonChannelProgram, self).__init__()
39                 self._clipboard = gtk.clipboard_get()
40
41                 self._window_in_fullscreen = False #The window isn't in full screen mode initially.
42
43                 #Create GUI main vbox
44                 vbox = gtk.VBox(homogeneous = False, spacing = 0)
45
46                 if hildonize.GTK_MENU_USED:
47                         #Create Menu and apply it for hildon
48                         filemenu = gtk.Menu()
49
50                         menu_items = gtk.MenuItem("Quit")
51                         filemenu.append(menu_items)
52                         menu_items.connect("activate", self._on_destroy, None)
53
54                         file_menu = gtk.MenuItem("File")
55                         file_menu.show()
56                         file_menu.set_submenu(filemenu)
57
58                         categorymenu = gtk.Menu()
59
60                         menu_items = gtk.MenuItem("Search")
61                         categorymenu.append(menu_items)
62                         menu_items.connect("activate", self._on_toggle_search)
63
64                         helpmenu = gtk.Menu()
65
66                         menu_items = gtk.MenuItem("About")
67                         helpmenu.append(menu_items)
68                         menu_items.connect("activate", self._on_show_about, None)
69
70                         help_menu = gtk.MenuItem("Help")
71                         help_menu.show()
72                         help_menu.set_submenu(helpmenu)
73
74                         menuBar = gtk.MenuBar()
75                         menuBar.show()
76                         menuBar.append (file_menu)
77                         menuBar.append (help_menu)
78
79                         vbox.pack_start(menuBar, False, False, 0)
80                 else:
81                         menuBar = gtk.MenuBar()
82                         menuBar.show()
83                         vbox.pack_start(menuBar, False, False, 0)
84
85                 #Get the Main Window, and connect the "destroy" event
86                 self._window = gtk.Window()
87                 self._window.add(vbox)
88
89                 self._window = hildonize.hildonize_window(self, self._window)
90                 hildonize.set_application_title(self._window, "%s" % constants.__pretty_app_name__)
91                 menuBar = hildonize.hildonize_menu(
92                         self._window,
93                         menuBar,
94                 )
95                 if hildonize.IS_FREMANTLE_SUPPORTED:
96                         searchButton= gtk.Button("Search")
97                         searchButton.connect("clicked", self._on_toggle_search)
98                         menuBar.append(searchButton)
99
100                         menuBar.show_all()
101
102                 if not hildonize.IS_HILDON_SUPPORTED:
103                         _moduleLogger.info("No hildonization support")
104
105                 if osso is not None:
106                         self._osso_c = osso.Context(constants.__app_name__, constants.__version__, False)
107                         self._deviceState = osso.DeviceState(self._osso_c)
108                         self._deviceState.set_device_state_callback(self._on_device_state_change, 0)
109                 else:
110                         _moduleLogger.info("No osso support")
111                         self._osso_c = None
112                         self._deviceState = None
113
114                 self._window.connect("delete-event", self._on_delete_event)
115                 self._window.connect("destroy", self._on_destroy)
116                 self._window.connect("key-press-event", self._on_key_press)
117                 self._window.connect("window-state-event", self._on_window_state_change)
118
119                 self._window.show_all()
120
121                 self._player = player.Player()
122                 self._store = imagestore.ImageStore("../data", "../data")
123                 self._windowStack = [windows.SourceSelector(self._player, self._store)]
124                 vbox.pack_start(self._windowStack[0].toplevel, True, True)
125
126                 self._load_settings()
127
128         def _save_settings(self):
129                 config = ConfigParser.SafeConfigParser()
130                 self.save_settings(config)
131                 with open(constants._user_settings_, "wb") as configFile:
132                         config.write(configFile)
133
134         def save_settings(self, config):
135                 config.add_section(constants.__pretty_app_name__)
136                 config.set(constants.__pretty_app_name__, "fullscreen", str(self._window_in_fullscreen))
137
138         def _load_settings(self):
139                 config = ConfigParser.SafeConfigParser()
140                 config.read(constants._user_settings_)
141                 self.load_settings(config)
142
143         def load_settings(self, config):
144                 try:
145                         self._window_in_fullscreen = config.getboolean(constants.__pretty_app_name__, "fullscreen")
146                 except ConfigParser.NoSectionError, e:
147                         _moduleLogger.info(
148                                 "Settings file %s is missing section %s" % (
149                                         constants._user_settings_,
150                                         e.section,
151                                 )
152                         )
153
154                 if self._window_in_fullscreen:
155                         self._window.fullscreen()
156                 else:
157                         self._window.unfullscreen()
158
159         def _toggle_search(self):
160                 if self._search.get_property("visible"):
161                         self._search.hide()
162                 else:
163                         self._search.show()
164
165         @gtk_toolbox.log_exception(_moduleLogger)
166         def _on_device_state_change(self, shutdown, save_unsaved_data, memory_low, system_inactivity, message, userData):
167                 """
168                 For system_inactivity, we have no background tasks to pause
169
170                 @note Hildon specific
171                 """
172                 if memory_low:
173                         gc.collect()
174
175                 if save_unsaved_data or shutdown:
176                         self._save_settings()
177
178         @gtk_toolbox.log_exception(_moduleLogger)
179         def _on_window_state_change(self, widget, event, *args):
180                 if event.new_window_state & gtk.gdk.WINDOW_STATE_FULLSCREEN:
181                         self._window_in_fullscreen = True
182                 else:
183                         self._window_in_fullscreen = False
184
185         @gtk_toolbox.log_exception(_moduleLogger)
186         def _on_key_press(self, widget, event, *args):
187                 RETURN_TYPES = (gtk.keysyms.Return, gtk.keysyms.ISO_Enter, gtk.keysyms.KP_Enter)
188                 isCtrl = bool(event.get_state() & gtk.gdk.CONTROL_MASK)
189                 if (
190                         event.keyval == gtk.keysyms.F6 or
191                         event.keyval in RETURN_TYPES and isCtrl
192                 ):
193                         # The "Full screen" hardware key has been pressed 
194                         if self._window_in_fullscreen:
195                                 self._window.unfullscreen ()
196                         else:
197                                 self._window.fullscreen ()
198                         return True
199                 elif event.keyval == gtk.keysyms.f and isCtrl:
200                         self._toggle_search()
201                         return True
202                 elif (
203                         event.keyval in (gtk.keysyms.w, gtk.keysyms.q) and
204                         event.get_state() & gtk.gdk.CONTROL_MASK
205                 ):
206                         self._window.destroy()
207                 elif event.keyval == gtk.keysyms.l and event.get_state() & gtk.gdk.CONTROL_MASK:
208                         with open(constants._user_logpath_, "r") as f:
209                                 logLines = f.xreadlines()
210                                 log = "".join(logLines)
211                                 self._clipboard.set_text(str(log))
212                         return True
213
214         @gtk_toolbox.log_exception(_moduleLogger)
215         def _on_toggle_search(self, *args):
216                 self._toggle_search()
217
218         @gtk_toolbox.log_exception(_moduleLogger)
219         def _on_delete_event(self, widget, event, data = None):
220                 return False
221
222         @gtk_toolbox.log_exception(_moduleLogger)
223         def _on_destroy(self, widget = None, data = None):
224                 try:
225                         self._save_settings()
226
227                         try:
228                                 self._deviceState.close()
229                         except AttributeError:
230                                 pass # Either None or close was removed (in Fremantle)
231                         try:
232                                 self._osso_c.close()
233                         except AttributeError:
234                                 pass # Either None or close was removed (in Fremantle)
235                 finally:
236                         gtk.main_quit()
237
238         @gtk_toolbox.log_exception(_moduleLogger)
239         def _on_show_about(self, widget = None, data = None):
240                 dialog = gtk.AboutDialog()
241                 dialog.set_position(gtk.WIN_POS_CENTER)
242                 dialog.set_name(constants.__pretty_app_name__)
243                 dialog.set_version(constants.__version__)
244                 dialog.set_copyright("")
245                 dialog.set_website("")
246                 comments = "Mormon Radio and Audiobook Player"
247                 dialog.set_comments(comments)
248                 dialog.set_authors(["Ed Page <eopage@byu.net>"])
249                 dialog.run()
250                 dialog.destroy()
251
252
253 def run():
254         if hildonize.IS_HILDON_SUPPORTED:
255                 gtk.set_application_name(constants.__pretty_app_name__)
256         app = MormonChannelProgram()
257         if not PROFILE_STARTUP:
258                 gtk.main()
259
260
261 if __name__ == "__main__":
262         logging.basicConfig(level=logging.DEBUG)
263         run()