~cosmin.lupu/+junk/penguintv

« back to all changes in this revision

Viewing changes to penguintv/MainWindow.py

  • Committer: cosmin.lupu at gmail
  • Date: 2010-04-27 16:47:43 UTC
  • Revision ID: cosmin.lupu@gmail.com-20100427164743-ds8xrqonipp5ovdf
initial packaging

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import gtk
 
2
import gtk.glade
 
3
import gobject
 
4
import sys, os, os.path
 
5
import logging
 
6
try:
 
7
        set
 
8
except:
 
9
        from sets import Set as set
 
10
 
 
11
import ptvDB
 
12
import penguintv
 
13
import Player
 
14
import utils
 
15
import Downloader
 
16
#from trayicon.SonataNotification import TrayIconTips as tooltips
 
17
 
 
18
if utils.RUNNING_HILDON:
 
19
        import hildon
 
20
 
 
21
#status of the main window progress bar
 
22
U_NOBODY=0
 
23
U_DOWNLOAD=1
 
24
U_LOADING=2
 
25
U_POLL=3
 
26
U_STANDARD=4
 
27
 
 
28
#states
 
29
S_DEFAULT       = 0
 
30
S_MANUAL_SEARCH = 1
 
31
S_TAG_SEARCH    = 2
 
32
S_MAJOR_DB_OPERATION = 3
 
33
 
 
34
#filter model
 
35
F_FAVORITE = 0
 
36
F_NAME     = 1
 
37
F_DISPLAY  = 2
 
38
F_TYPE     = 3
 
39
 
 
40
#notebook tabs
 
41
N_FEEDS     = 0
 
42
N_PLAYER    = 1
 
43
N_DOWNLOADS = 2
 
44
 
 
45
import FeedList, PlanetView, DownloadView, EntryFormatter
 
46
 
 
47
if utils.HAS_SEARCH:
 
48
        import FeedFilterPropertiesDialog
 
49
        import AddSearchTagDialog
 
50
        import EditSearchesDialog
 
51
        import FeedFilterDialog
 
52
 
 
53
if not utils.RUNNING_HILDON:
 
54
        import SynchronizeDialog
 
55
        import EntryList, EntryView
 
56
        
 
57
if utils.HAS_GSTREAMER:
 
58
        import GStreamerPlayer
 
59
 
 
60
class MainWindow(gobject.GObject):
 
61
        COLUMN_TITLE = 0
 
62
        COLUMN_ITEM = 1
 
63
        COLUMN_BOLD = 2
 
64
        COLUMN_STICKY_FLAG = 3
 
65
        
 
66
        __gsignals__ = {
 
67
                'player-show': (gobject.SIGNAL_RUN_FIRST, 
 
68
                                                   gobject.TYPE_NONE, 
 
69
                                                   ([])),
 
70
                'player-hide': (gobject.SIGNAL_RUN_FIRST, 
 
71
                                                   gobject.TYPE_NONE, 
 
72
                                                   ([]))
 
73
        }
 
74
 
 
75
        def __init__(self, app, use_internal_player=False, window=None, status_icon=None):
 
76
                gobject.GObject.__init__(self)
 
77
                self._app = app
 
78
                self._window_inited = False
 
79
                self._mm = self._app.mediamanager
 
80
                self._glade_prefix = utils.get_glade_prefix()
 
81
                self._widgetTree = None
 
82
                self._menu_widgettree = None
 
83
                self.window_maximized = False
 
84
                self.changing_layout=False
 
85
                self.layout='standard'
 
86
                self._bar_owner = U_NOBODY
 
87
                self._status_owner = U_NOBODY
 
88
                self._state = S_DEFAULT
 
89
                self._fullscreen = False
 
90
                self._fullscreen_lock = False
 
91
                
 
92
                self._use_internal_player = False
 
93
                if utils.HAS_GSTREAMER and use_internal_player:
 
94
                        self._use_internal_player = True
 
95
                        
 
96
                self._status_icon = status_icon
 
97
                
 
98
                self._active_filter_name = FeedList.BUILTIN_TAGS[FeedList.ALL]
 
99
                self._active_filter_index = FeedList.ALL
 
100
                self._active_filter_path = (0,)
 
101
                
 
102
                if not utils.RUNNING_SUGAR and not utils.RUNNING_HILDON:
 
103
                        pixbuf = gtk.gdk.pixbuf_new_from_file(utils.get_image_path('ev_online.png'))
 
104
                        source = gtk.IconSource()
 
105
                        source.set_pixbuf(pixbuf)
 
106
                        source.set_size(gtk.ICON_SIZE_DIALOG)
 
107
                        source.set_size_wildcarded(False)
 
108
                        self._connected_iconset = gtk.IconSet()
 
109
                        self._connected_iconset.add_source(source)
 
110
 
 
111
                        pixbuf = gtk.gdk.pixbuf_new_from_file(utils.get_image_path('ev_offline.png'))
 
112
                        source = gtk.IconSource()
 
113
                        source.set_pixbuf(pixbuf)
 
114
                        source.set_size(gtk.ICON_SIZE_DIALOG)
 
115
                        source.set_size_wildcarded(False)
 
116
                        self._disconnected_iconset = gtk.IconSet()
 
117
                        self._disconnected_iconset.add_source(source)
 
118
                
 
119
                ##other WINDOWS we open
 
120
                if utils.HAS_SEARCH:
 
121
                        self._window_add_search = AddSearchTagDialog.AddSearchTagDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'extra_dialogs.glade'), "window_add_search_tag",'penguintv'),self._app)
 
122
                        self._feed_filter_properties_dialog = FeedFilterPropertiesDialog.FeedFilterPropertiesDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'extra_dialogs.glade'), "window_filter_properties",'penguintv'),self._app)
 
123
                if not utils.RUNNING_SUGAR and not utils.RUNNING_HILDON:
 
124
                        self._sync_dialog = SynchronizeDialog.SynchronizeDialog(os.path.join(self._glade_prefix,'extra_dialogs.glade'), self._app)
 
125
                
 
126
                self._window_add_feed = None
 
127
                self._filter_selector_dialog = None
 
128
                self._feed_properties_dialog = None
 
129
                
 
130
                #signals
 
131
                self._app.connect('feed-added', self.__feed_added_cb)
 
132
                self._app.connect('feed-removed', self.__feed_removed_cb)
 
133
                self._app.connect('feed-polled', self.__feed_polled_cb)
 
134
                self._app.connect('download-finished', self.__download_finished_cb)
 
135
                self._app.connect('setting-changed', self.__setting_changed_cb)
 
136
                self._app.connect('tags-changed', self.__tags_changed_cb)
 
137
                self._app.connect('app-loaded', self.__app_loaded_cb)
 
138
                self._app.connect('online-status-changed', self.__online_status_changed_cb)
 
139
                self._app.connect('state-changed', self.__state_changed_cb)
 
140
        
 
141
                #most of the initialization is done on Show()
 
142
                if utils.RUNNING_SUGAR:
 
143
                        gobject.idle_add(self.Show, window)
 
144
        
 
145
        def __link_activated_cb(self, o, link):
 
146
                self._app.activate_link(link)
 
147
                
 
148
        def __feed_clicked_cb(self, o):
 
149
                if utils.RUNNING_HILDON:
 
150
                        self.feed_tabs.set_current_page(1)
 
151
                                
 
152
        def __entrylistview_list_resized_cb(self, entrylistview, new_width):
 
153
                if self.layout == "widescreen" and self.app_window is not None:                 
 
154
                        listnview_width = self.app_window.get_size()[0] - self.feed_pane.get_position()
 
155
                        if listnview_width - new_width < 400: #ie, entry view will be tiny
 
156
                                self.entry_pane.set_position(listnview_width-400) #MAGIC NUMBER
 
157
                        elif new_width > 20: #MAGIC NUMBER
 
158
                                self.entry_pane.set_position(new_width)
 
159
                                
 
160
        def __feed_added_cb(self, app, feed_id, success):
 
161
                if success:
 
162
                        #HACK: we know it will already be selected
 
163
                        #self.select_feed(feed_id)
 
164
                        self.display_status_message(_("Feed Added"))
 
165
                        gobject.timeout_add(2000, self.display_status_message, "")
 
166
                else:
 
167
                        self.display_status_message(_("Error adding feed"))
 
168
                        self.select_feed(feed_id)
 
169
                        
 
170
        def __feed_polled_cb(self, app, feed_id, update_data):
 
171
                if not update_data.has_key('polling_multiple'):
 
172
                        self.display_status_message(_("Feed Updated"))
 
173
                        gobject.timeout_add(2000, self.display_status_message, "")
 
174
                        
 
175
        def __feed_removed_cb(self, app, feed_id):
 
176
                self.update_filters()
 
177
                
 
178
        def __download_finished_cb(self, app, d):
 
179
                self._download_view.update_downloads()
 
180
                self.update_download_progress()
 
181
                
 
182
        def __setting_changed_cb(self, app, typ, datum, value):
 
183
                if datum == '/apps/penguintv/show_notifications':
 
184
                        show_notifs_item = self._menu_widgettree.get_widget('show_notifications')
 
185
                        if show_notifs_item.get_active() != value:
 
186
                                show_notifs_item.set_active(value)
 
187
                                
 
188
        def __tags_changed_cb(self, app, val):
 
189
                self.update_filters()
 
190
                
 
191
        def __app_loaded_cb(self, app):
 
192
                if utils.RUNNING_SUGAR:
 
193
                        self._finish_sugar_toolbar()
 
194
                        
 
195
        def __online_status_changed_cb(self, app, connected):
 
196
                if connected:
 
197
                        if self._connection_button:
 
198
                                #p = utils.get_image_path('ev_online.png')
 
199
                                i = gtk.Image()
 
200
                                i.set_from_icon_set(self._connected_iconset, gtk.ICON_SIZE_DIALOG)
 
201
                                self._connection_button.set_image(i)
 
202
                else:
 
203
                        if self._connection_button:
 
204
                                #p = utils.get_image_path('ev_offline.png')
 
205
                                i = gtk.Image()
 
206
                                i.set_from_icon_set(self._disconnected_iconset, gtk.ICON_SIZE_DIALOG)
 
207
                                self._connection_button.set_image(i)
 
208
                        
 
209
        def update_downloads(self):
 
210
                self._download_view.update_downloads()
 
211
                
 
212
#       def __getitem__(self, key):
 
213
#               return self.widgets.get_widget(key)
 
214
 
 
215
        def Show(self, dock_widget = None):
 
216
                """shows the main window. if given a widget, it will put itself in the widget.  otherwise load a regular
 
217
                application window"""
 
218
                #if not utils.HAS_MOZILLA and self.layout.endswith("planet"):
 
219
                #       logging.warning("requested planet layout, but can't use because gtkmozembed isn't installed correctly (won't import)")
 
220
                #       self.layout = "standard"
 
221
                if utils.RUNNING_SUGAR:  #if we are in OLPC mode and just have to supply a widget...
 
222
                        self._status_view = None
 
223
                        self._disk_usage_widget = None
 
224
                        self.app_window = None
 
225
 
 
226
                        vbox = gtk.VBox()
 
227
                        self._layout_dock = self.load_notebook()
 
228
                        self._layout_dock.add(self.load_layout())
 
229
                        vbox.pack_start(self._notebook)
 
230
                        self._status_view = MainWindow._my_status_view()
 
231
                        vbox.pack_start(self._status_view, False, False)
 
232
                        dock_widget.set_canvas(vbox)
 
233
                        dock_widget.show_all()
 
234
                        
 
235
                        self.window = dock_widget
 
236
                        
 
237
                        self._connection_button = None
 
238
                        
 
239
                        #TODO fixme
 
240
                        self._widgetTree = gtk.glade.XML(os.path.join(self._glade_prefix,'..','penguintv.glade'), 'toolbar_holder','penguintv')
 
241
                        self.toolbar = self._load_sugar_toolbar()
 
242
                        self.toolbar.show()
 
243
                        
 
244
                        for key in dir(self.__class__): #python insaneness
 
245
                                if key[:3] == 'on_':
 
246
                                        self._widgetTree.signal_connect(key, getattr(self, key))
 
247
                                        
 
248
                        self.window.connect('key_press_event', self.on_app_key_press_event)
 
249
                elif utils.RUNNING_HILDON:
 
250
                        logging.debug("Hildon: setting up UI")
 
251
                        self._h_app = hildon.Program()
 
252
                        self.window = hildon.Window()
 
253
                        #self.window.set_title("PenguinTV "+utils.VERSION)
 
254
                        self.window.set_wmclass("penguintv","penguintv")
 
255
                        try:
 
256
                                gtk.set_application_name("PenguinTV "+utils.VERSION)
 
257
                        except:
 
258
                                logging.warning("set application name failed, old pymaemo?")
 
259
                        self.window.set_icon_from_file(utils.get_image_path('penguintvicon.png'))
 
260
                        
 
261
                        self._status_view = None
 
262
                        self._disk_usage_widget = None
 
263
                        self.app_window = None
 
264
 
 
265
                        vbox = gtk.VBox()
 
266
                        self._layout_dock = self.load_notebook()
 
267
                        self._layout_dock.add(self.load_layout())
 
268
                        
 
269
                        self._status_view = MainWindow._my_status_view()
 
270
                        
 
271
                        self._connection_button = None
 
272
                        
 
273
                        logging.debug("Hildon: getting toolbar")
 
274
                        self._widgetTree = gtk.glade.XML(os.path.join(self._glade_prefix,'hildon.glade'), 'hildon_toolbar_holder','penguintv')
 
275
                        self.toolbar = self._load_toolbar()
 
276
                        self.toolbar.unparent()
 
277
                        
 
278
                        vbox.pack_start(self._notebook)
 
279
                        vbox.pack_start(self._status_view, False, False)
 
280
 
 
281
                        self.window.add(vbox)
 
282
                        self.window.add_toolbar(self.toolbar)
 
283
                        self._h_app.add_window(self.window)
 
284
                        
 
285
                        self._menu_widgettree = gtk.glade.XML(os.path.join(self._glade_prefix,'hildon.glade'), 'hildon_menu','penguintv')
 
286
                        menu = self._build_hildon_menu(self._menu_widgettree)
 
287
                        self.window.set_menu(menu)
 
288
                        
 
289
                        show_notifs_item = self._menu_widgettree.get_widget('show_notifications')
 
290
                        show_notifs_item.set_active(self._app.db.get_setting(ptvDB.BOOL, 
 
291
                                           '/apps/penguintv/show_notifications', True))
 
292
                        
 
293
                        self.window.show_all()
 
294
                        
 
295
                        if not utils.HAS_STATUS_ICON:
 
296
                                show_notifs_item.hide()
 
297
                        
 
298
                        for key in dir(self.__class__): #python insaneness
 
299
                                if key[:3] == 'on_':
 
300
                                        self._widgetTree.signal_connect(key, getattr(self, key))
 
301
                                        self._menu_widgettree.signal_connect(key, getattr(self, key))
 
302
                                        
 
303
                        self.window.connect('destroy', self.on_app_destroy_event)
 
304
                        self.window.connect('delete-event', self.on_app_delete_event)
 
305
                        self.window.connect('key_press_event', self.on_app_key_press_event)
 
306
                else:   #if we are loading in a regular window...
 
307
                        self._load_app_window()
 
308
                        if not utils.HAS_SEARCH:
 
309
                                #remove UI elements that don't apply without search
 
310
                                self._widgetTree.get_widget('saved_searches').hide()
 
311
                                self._widgetTree.get_widget('separator11').hide()
 
312
                                self._widgetTree.get_widget('reindex_searches').hide()
 
313
                                self._widgetTree.get_widget('add_feed_filter').hide()
 
314
                        #if not utils.HAS_MOZILLA:
 
315
                                #self._widgetTree.get_widget('planet_layout').hide()
 
316
                        if not utils.HAS_STATUS_ICON:
 
317
                                self._widgetTree.get_widget('show_notifications').hide()
 
318
                        self.window = self.app_window
 
319
                        
 
320
                if self._use_internal_player:
 
321
                        #From Sonata/dbus_plugin.py
 
322
                        if utils.HAS_DBUS:
 
323
                                import dbus
 
324
                                try:
 
325
                                        bus = dbus.SessionBus()
 
326
                                        dbusObj = bus.get_object('org.freedesktop.DBus', '/org/freedesktop/DBus')
 
327
                                        dbusInterface = dbus.Interface(dbusObj, 'org.freedesktop.DBus')
 
328
                                        if dbusInterface.NameHasOwner('org.gnome.SettingsDaemon'):
 
329
                                                try:
 
330
                                                        # mmkeys for gnome 2.22+
 
331
                                                        settingsDaemonObj = bus.get_object('org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon/MediaKeys')
 
332
                                                        settingsDaemonInterface = dbus.Interface(settingsDaemonObj, 'org.gnome.SettingsDaemon.MediaKeys')
 
333
                                                        settingsDaemonInterface.GrabMediaPlayerKeys('PenguinTV', 0)
 
334
                                                except:
 
335
                                                        # mmkeys for gnome 2.18+
 
336
                                                        settingsDaemonObj = bus.get_object('org.gnome.SettingsDaemon', '/org/gnome/SettingsDaemon')
 
337
                                                        settingsDaemonInterface = dbus.Interface(settingsDaemonObj, 'org.gnome.SettingsDaemon')
 
338
                                                        settingsDaemonInterface.GrabMediaPlayerKeys('PenguinTV', 0)
 
339
                                                settingsDaemonInterface.connect_to_signal('MediaPlayerKeyPressed', lambda app, key:self._dbus_mmkeys_cb(app, key))
 
340
                                except:
 
341
                                        pass
 
342
                        else:
 
343
                                try:
 
344
                                        import mmkeys
 
345
                                        keys = mmkeys.MmKeys()
 
346
                        
 
347
                                        keys.connect("mm_prev", lambda x,y: self._gstreamer_player.prev())
 
348
                                        keys.connect("mm_next", lambda x,y: self._gstreamer_player.next())
 
349
                                        keys.connect("mm_playpause", lambda x,y: self._gstreamer_player.play_pause_toggle())
 
350
                                        keys.connect("mm_stop", lambda x,y: self._gstreamer_player.stop())
 
351
                                except:
 
352
                                        logging.debug("Multimedia Key Support not found")
 
353
                                
 
354
                        
 
355
                self._notebook.show_only(N_FEEDS)
 
356
                if not utils.HAS_SEARCH:
 
357
                        self.search_container.hide_all()
 
358
                if utils.RUNNING_HILDON:
 
359
                        self._layout_components.get_widget('filter_label').hide()
 
360
                        self._filter_unread_checkbox.hide()
 
361
                #if not utils.USE_TAGGING:
 
362
                #       self._filter_container.hide_all()
 
363
                if self._use_internal_player:
 
364
                        if self._gstreamer_player.get_queue_count() > 0:
 
365
                                self._notebook.show_page(N_PLAYER)
 
366
                                self.emit('player-show')
 
367
                                
 
368
                if not self._window_inited:
 
369
                        gobject.idle_add(self._app.post_show_init)
 
370
                        self._window_inited = True
 
371
                        
 
372
                return False
 
373
                
 
374
        def _dbus_mmkeys_cb(self, app, key):
 
375
                if app == 'PenguinTV':
 
376
                        if key in ("Play", "PlayPause", "Pause"):
 
377
                                key = "PlayPause"
 
378
                        self._app.player.control_internal(key)
 
379
                
 
380
        def _build_hildon_menu(self, widgets):
 
381
                menu = gtk.Menu()  
 
382
                
 
383
                menuitem = widgets.get_widget('file_menu')
 
384
                menuitem.unparent()
 
385
                menu.append(menuitem)
 
386
                
 
387
                menuitem = widgets.get_widget('edit_menu')
 
388
                menuitem.unparent()
 
389
                menu.append(menuitem)
 
390
                
 
391
                menuitem = widgets.get_widget('view_menu')
 
392
                menuitem.unparent()
 
393
                menu.append(menuitem)
 
394
                
 
395
                menuitem = widgets.get_widget('go_menu')
 
396
                menuitem.unparent()
 
397
                menu.append(menuitem)
 
398
                
 
399
                menuitem = widgets.get_widget('feed_menu')
 
400
                menuitem.unparent()
 
401
                menu.append(menuitem)
 
402
                
 
403
                menuitem = widgets.get_widget('help_menu')
 
404
                menuitem.unparent()
 
405
                menu.append(menuitem)
 
406
                
 
407
                separator = gtk.SeparatorMenuItem()
 
408
                menu.append(separator)
 
409
                
 
410
                item = gtk.ImageMenuItem('gtk-close')
 
411
                item.connect('activate', self.on_app_delete_event)
 
412
                menu.append(item)
 
413
                
 
414
                return menu
 
415
                        
 
416
        def _load_toolbar(self):
 
417
                toolbar = self._widgetTree.get_widget('toolbar1')
 
418
                
 
419
                #set up separator (see below)
 
420
                vseparator = self._widgetTree.get_widget('vseparator1')
 
421
                vseparator_toolitem = self._widgetTree.get_widget('toolitem1')
 
422
                vseparator_toolitem.set_expand(True)
 
423
                vseparator.set_draw(False)
 
424
                
 
425
                self._disk_usage_widget = self._widgetTree.get_widget('disk_usage')
 
426
                self._disk_usage_widget.set_use_markup(True)
 
427
                
 
428
                return toolbar
 
429
                
 
430
        def _load_sugar_toolbar(self):
 
431
                from sugar.graphics.toolbutton import ToolButton
 
432
                from sugar.graphics.palette import Palette
 
433
                
 
434
                toolbar = gtk.Toolbar()
 
435
                
 
436
                # Add Feed Palette (initialized later when the dialogs are set up)
 
437
                self.sugar_add_button = ToolButton('gtk-add')
 
438
                toolbar.insert(self.sugar_add_button, -1)
 
439
                self.sugar_add_button.show()
 
440
                
 
441
                # Remove Feed
 
442
                self._sugar_remove_button = ToolButton('gtk-remove')
 
443
                vbox = gtk.VBox()
 
444
                #vbox.set_size_request(300, 200)
 
445
                label = gtk.Label(_('Really remove feed?'))
 
446
                vbox.pack_start(label)
 
447
                hbox = gtk.HBox()
 
448
                expander_label = gtk.Label(' ')
 
449
                hbox.pack_start(expander_label)
 
450
                b = gtk.Button('gtk-remove')
 
451
                b.set_use_stock(True)
 
452
                b.connect('clicked', self.on_remove_feed_activate, True)
 
453
                hbox.pack_start(b, False)
 
454
                vbox.pack_start(hbox)
 
455
                palette = Palette(_('Remove Feed'))
 
456
                palette.set_content(vbox)
 
457
                vbox.show_all()
 
458
                self._sugar_remove_button.set_palette(palette)
 
459
                toolbar.insert(self._sugar_remove_button, -1)
 
460
                self._sugar_remove_button.show()
 
461
                
 
462
                # Refresh Feeds
 
463
                b = gtk.ToolButton('gtk-refresh')
 
464
                b.connect('clicked', self.on_feeds_poll_clicked)
 
465
                toolbar.insert(b, -1)
 
466
                b.show()
 
467
                
 
468
                # Download Media
 
469
                b = gtk.ToolButton('gtk-go-down')
 
470
                b.connect('clicked', self.on_download_unviewed_clicked)
 
471
                toolbar.insert(b, -1)
 
472
                b.show()
 
473
                
 
474
                # Separator
 
475
                sep = gtk.SeparatorToolItem()
 
476
                toolbar.insert(sep, -1)
 
477
                sep.show()
 
478
                
 
479
                # Preferences
 
480
                self._sugar_prefs_button = ToolButton('gtk-preferences')
 
481
                toolbar.insert(self._sugar_prefs_button, -1)
 
482
                self._sugar_prefs_button.show()
 
483
                
 
484
                return toolbar
 
485
                
 
486
        def _finish_sugar_toolbar(self):
 
487
                from sugar.graphics.toolbutton import ToolButton
 
488
                from sugar.graphics.palette import Palette
 
489
                
 
490
                if self._window_add_feed is None:
 
491
                        self.show_window_add_feed()
 
492
                        self.hide_window_add_feed()
 
493
                content = self._window_add_feed.extract_content()
 
494
                palette = Palette(_('Add Feed'))
 
495
                palette.set_content(content)
 
496
                self.sugar_add_button.set_palette(palette)
 
497
                
 
498
                content = self._app.window_preferences.extract_content()
 
499
                palette = Palette(_('Preferences'))
 
500
                palette.set_content(content)
 
501
                self._sugar_prefs_button.set_palette(palette)
 
502
                
 
503
        class _my_status_view(gtk.HBox):
 
504
                def __init__(self, homogeneous=False, spacing=0):
 
505
                        gtk.HBox.__init__(self, homogeneous=False, spacing=0)
 
506
                        self._progress = gtk.ProgressBar()
 
507
                        sep = gtk.VSeparator()
 
508
                        self._status = gtk.Label()
 
509
                        
 
510
                        self.pack_start(self._progress, False, False)
 
511
                        self.pack_start(sep, False, False)
 
512
                        self.pack_start(self._status, False, False)
 
513
                                                                
 
514
                def get_status(self):
 
515
                        return self._status
 
516
                        
 
517
                def set_status(self, m):
 
518
                        self._status.set_text(m)
 
519
                        if utils.RUNNING_HILDON:
 
520
                                if m == "":
 
521
                                        self._status.hide()
 
522
                                else:
 
523
                                        self._status.show()
 
524
                        
 
525
                def set_progress_percentage(self, p):
 
526
                        self._progress.set_fraction(p)
 
527
                        if utils.RUNNING_HILDON:
 
528
                                if p == 0.0:
 
529
                                        self._progress.hide()
 
530
                                else:
 
531
                                        self._progress.show()
 
532
                        
 
533
                def get_progress_percentage(self):
 
534
                        return self._progress.get_fraction()
 
535
                        
 
536
        def _load_app_window(self):
 
537
                self._widgetTree = gtk.glade.XML(os.path.join(self._glade_prefix,'desktop.glade'), 'app','penguintv')
 
538
                self._menu_widgettree = self._widgetTree
 
539
                
 
540
                notebook_dock = self._widgetTree.get_widget('layout_dock')
 
541
                self.app_window = self._widgetTree.get_widget('app')
 
542
                
 
543
                fancy_feedlist_item = self._menu_widgettree.get_widget('fancy_feed_display')
 
544
                fancy_feedlist_item.set_active(self._app.db.get_setting(ptvDB.BOOL, 
 
545
                                               '/apps/penguintv/fancy_feedlist', True))
 
546
                show_notifs_item = self._menu_widgettree.get_widget('show_notifications')
 
547
                show_notifs_item.set_active(self._app.db.get_setting(ptvDB.BOOL, 
 
548
                                           '/apps/penguintv/show_notifications', True))
 
549
                self._widgetTree.get_widget(self.layout+"_layout").set_active(True)
 
550
                self.app_window.set_icon_from_file(utils.get_image_path('penguintvicon.png'))
 
551
                #status_box = self._widgetTree.get_widget("status_hbox")
 
552
                #self._status_view = MainWindow._my_status_view()
 
553
                #status_box.pack_start(self._status_view)
 
554
                self._status_view = self._widgetTree.get_widget('appbar')
 
555
                self._load_toolbar()
 
556
                
 
557
                self._connection_button = self._widgetTree.get_widget('connection_button')
 
558
                #p = utils.get_image_path('ev_online.png')
 
559
                i = gtk.Image()
 
560
                i.set_from_icon_set(self._connected_iconset, gtk.ICON_SIZE_DIALOG)
 
561
                self._connection_button.set_image(i)
 
562
 
 
563
                #load the layout
 
564
                self._layout_dock = self.load_notebook()
 
565
                notebook_dock.add(self._notebook)
 
566
                self._layout_dock.add(self.load_layout())
 
567
 
 
568
                #sizing for the window comes from gconf
 
569
                x = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/app_window_position_x', 40)
 
570
                y = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/app_window_position_y', 40)
 
571
                if x < 0: x = 0
 
572
                if y < 0: y = 0
 
573
                self.app_window.move(x,y)
 
574
                w = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/app_window_size_x', 800)
 
575
                h = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/app_window_size_y', 500)
 
576
                
 
577
                def do_maximize():
 
578
                        self.app_window.maximize()
 
579
                        self.window_maximized = True
 
580
                        return False
 
581
                
 
582
                if w<0 or h<0:  #very cheesy.  negative values really means "maximize"
 
583
                        self.app_window.resize(abs(w),abs(h)) #but be good and don't make assumptions about negativity
 
584
                        gobject.idle_add(do_maximize)
 
585
                else:
 
586
                        self.app_window.resize(w,h)
 
587
 
 
588
                if self.layout.endswith("planet"):
 
589
                        self._menu_widgettree.get_widget('entry_menu_item').hide()
 
590
                else:
 
591
                        self._menu_widgettree.get_widget('entry_menu_item').show()
 
592
                        
 
593
                self.app_window.show_all()
 
594
                        
 
595
                for key in dir(self.__class__): #python insaneness
 
596
                        if key[:3] == 'on_':
 
597
                                self._widgetTree.signal_connect(key, getattr(self, key))
 
598
                                
 
599
        def show_window_add_feed(self, autolocation=True):
 
600
                import AddFeedDialog
 
601
                if self._window_add_feed is None:
 
602
                        if utils.RUNNING_HILDON:
 
603
                                self._window_add_feed = AddFeedDialog.AddFeedDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'hildon_dialog_add_feed.glade'), "window_add_feed",'penguintv'),self._app) #MAGIC
 
604
                        else:
 
605
                                self._window_add_feed = AddFeedDialog.AddFeedDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'dialog_add_feed.glade'), "window_add_feed",'penguintv'),self._app) #MAGIC
 
606
                self._window_add_feed.show(autolocation)
 
607
                        
 
608
        def hide_window_add_feed(self):
 
609
                if self._window_add_feed is None:
 
610
                        self.show_window_add_feed()
 
611
                        
 
612
                self._window_add_feed.hide()
 
613
                
 
614
        def set_window_add_feed_location(self, url):
 
615
                assert self._window_add_feed is not None
 
616
                self._window_add_feed.set_location(url)
 
617
                                
 
618
        def load_notebook(self):
 
619
                self._notebook = NotebookManager()
 
620
                self._notebook.set_property('tab-border',0)
 
621
                if utils.RUNNING_HILDON:
 
622
                        label = gtk.Label(_('Feeds'))
 
623
                else:
 
624
                        label = gtk.Label(_('<span size="small">Feeds</span>'))
 
625
                        label.set_property('use-markup',True)
 
626
                vbox = gtk.VBox()
 
627
                self._notebook.append_page(vbox, label)
 
628
                
 
629
                p_vbox = gtk.VBox()
 
630
                if self._use_internal_player:
 
631
                        self._gstreamer_player = GStreamerPlayer.GStreamerPlayer(p_vbox, os.path.join(utils.get_home(), "gst_playlist.pickle"), tick_interval=5)
 
632
                        self._gstreamer_player.connect('item-queued', self._on_player_item_queued)
 
633
                        self._gstreamer_player.connect('items-removed', self._on_player_items_removed)
 
634
                        self._gstreamer_player.Show()
 
635
                        self.emit('player-show')
 
636
                if utils.RUNNING_HILDON:
 
637
                        self._player_label = gtk.Label(_('Player'))
 
638
                else:
 
639
                        self._player_label = gtk.Label('<span size="small">'+_('Player')+'</span>')
 
640
                        self._player_label.set_property('use-markup',True)
 
641
                self._notebook.append_page(p_vbox, self._player_label)
 
642
                
 
643
                if utils.RUNNING_HILDON:
 
644
                        self._downloads_label = gtk.Label(_('Downloads'))
 
645
                else:
 
646
                        self._downloads_label = gtk.Label(_('<span size="small">Downloads</span>'))
 
647
                        self._downloads_label.set_property('use-markup',True)
 
648
                self._download_view = DownloadView.DownloadView(self._app, self._mm, self._app.db, os.path.join(self._glade_prefix,'dialogs.glade'))
 
649
                self._notebook.append_page(self._download_view.get_widget(), self._downloads_label)
 
650
                
 
651
                #self._notebook.set_show_tabs(False)
 
652
                self._notebook.set_property('show-border', False)
 
653
                self._notebook.connect('realize', self._on_notebook_realized)
 
654
                self._notebook.connect('switch-page', self._on_notebook_page_selected)
 
655
                
 
656
                self._notebook.show_all()
 
657
                return vbox
 
658
                
 
659
        def get_gst_player(self):
 
660
                try:
 
661
                        return self._gstreamer_player
 
662
                except:
 
663
                        logging.warning("no gstreamer player to get")
 
664
                        return None
 
665
                
 
666
        def notebook_select_page(self, page):
 
667
                self._notebook.set_current_page(page)
 
668
                
 
669
        def load_layout(self):
 
670
                components = gtk.glade.XML(os.path.join(self._glade_prefix,self.layout+'.glade'), 
 
671
                               self.layout+'_layout_container','penguintv') #MAGIC
 
672
                self._layout_components = components
 
673
                self._layout_container = components.get_widget(self.layout+'_layout_container')
 
674
                #dock_widget.add(self._layout_container)
 
675
                
 
676
                fancy = self._app.db.get_setting(ptvDB.BOOL, '/apps/penguintv/fancy_feedlist', True)
 
677
                if utils.RUNNING_SUGAR:
 
678
                        fancy = False
 
679
                elif utils.RUNNING_HILDON:
 
680
                        fancy = True
 
681
                
 
682
                self.feed_list_view = FeedList.FeedList(components,self._app, fancy)
 
683
                #renderer = EntryFormatter.MOZILLA
 
684
                #renderer = EntryFormatter.GTKHTML
 
685
                if utils.RUNNING_HILDON:
 
686
                        renderer = EntryFormatter.GTKHTML
 
687
                elif utils.HAS_MOZILLA:
 
688
                        renderer = EntryFormatter.MOZILLA
 
689
                else:
 
690
                        logging.warning("Mozilla (gtkmozembed) not found, falling back to GTKHTML")
 
691
                        renderer = EntryFormatter.GTKHTML
 
692
                #
 
693
                #if self.layout.endswith("planet") and renderer != EntryFormatter.MOZILLA:
 
694
                #       self.layout = "standard"
 
695
                #       return self.load_layout()       
 
696
                
 
697
                if not self.layout.endswith("planet"):
 
698
                        self.entry_list_view = EntryList.EntryList(components, self._app, 
 
699
                                                                   self.feed_list_view, self)
 
700
                        self.entry_view = EntryView.EntryView(components, self.feed_list_view, 
 
701
                                                                                          self.entry_list_view, self._app, self, renderer)
 
702
                else:
 
703
                        #self.entry_view = PlanetView.PlanetView(components, self.feed_list_view, 
 
704
                        #                                                                   self._app, self, self._app.db, renderer)
 
705
                        self.entry_view = PlanetView.PlanetView(components.get_widget('html_dock'), 
 
706
                                                                                                        self, self._app.db, utils.get_share_prefix(),
 
707
                                                                                                        self.feed_list_view, self._app, 
 
708
                                                                                                        renderer)
 
709
                        self.entry_list_view = self.entry_view
 
710
                
 
711
                for key in dir(self.__class__): #python insaneness
 
712
                        if key[:3] == 'on_':
 
713
                                components.signal_connect(key, getattr(self, key))
 
714
                                
 
715
                #some more signals
 
716
                self.feed_list_view.connect('link-activated', self.__link_activated_cb)
 
717
                self.feed_list_view.connect('feed-clicked', self.__feed_clicked_cb)
 
718
 
 
719
                if not self.layout.endswith("planet"):
 
720
                        self.entry_list_view.connect('entrylist-resized', self.__entrylistview_list_resized_cb)
 
721
                        #if we connected this in planetview, we'd activate links twice
 
722
                        self.entry_list_view.connect('link-activated', self.__link_activated_cb)
 
723
                
 
724
                self.entry_view.connect('link-activated', self.__link_activated_cb)
 
725
                                
 
726
                #major WIDGETS
 
727
                if not utils.RUNNING_HILDON:
 
728
                        self.feed_pane = components.get_widget('feed_pane')
 
729
                else:
 
730
                        self.feed_tabs = components.get_widget('feed_tabs')
 
731
                        self.feed_tabs.set_current_page(0)
 
732
                        self.feed_pane = None
 
733
                self._feedlist = components.get_widget('feedlistview')
 
734
                if self.layout.endswith("planet"):
 
735
                        self.entry_pane = self.feed_pane #cheat
 
736
                else:
 
737
                        self.entry_pane = components.get_widget('entry_pane')
 
738
                
 
739
                self._filter_container = components.get_widget('filter_container')
 
740
                self._filter_unread_checkbox = components.get_widget('unread_filter')
 
741
                self._filter_tree = gtk.TreeStore(str,      #filter displayable
 
742
                                                                                  str,          #filter name
 
743
                                                                                  int,      #seperator
 
744
                                                                                  bool)     #visible
 
745
                if utils.RUNNING_HILDON:
 
746
                        eventbox = components.get_widget('filter_selector_eventbox')
 
747
                        self._filter_selector_combo = gtk.ComboBox(self._filter_tree)
 
748
                        cell = gtk.CellRendererText()
 
749
                        cell.set_property("size-points", 24)
 
750
                        self._filter_selector_combo.pack_start(cell, True)
 
751
                        self._filter_selector_combo.add_attribute(cell, 'text', 0)
 
752
                        self._filter_selector_combo.connect('changed', self.on_filter_changed)
 
753
                        eventbox.add(self._filter_selector_combo)
 
754
                else:
 
755
                        self._filter_selector_combo = components.get_widget('filter_selector_combo')
 
756
                
 
757
                                                                                  
 
758
                filter_filter = self._filter_tree.filter_new()
 
759
                filter_filter.set_visible_column(3)
 
760
                
 
761
                #if not utils.RUNNING_HILDON:                                                             
 
762
                self._filter_selector_combo.set_model(filter_filter)
 
763
                self._filter_selector_combo.set_row_separator_func(lambda model,iter:model[iter][2]==1)
 
764
                
 
765
                self._filters = [] #text, text to display, type, tree path
 
766
                self._favorite_filters = [] #text, text to display, type
 
767
                
 
768
                self.search_entry = components.get_widget('search_entry')
 
769
                completion = gtk.EntryCompletion()
 
770
                completion_model = gtk.ListStore(str, str, int) #name, display, index
 
771
                completion.set_model(completion_model)
 
772
                renderer = gtk.CellRendererText()
 
773
                completion.pack_start(renderer)
 
774
                completion.add_attribute(renderer, 'text', 1)
 
775
                def match_func(comp, string, iter):
 
776
                        try: return comp.get_model()[iter][0].upper().startswith(string.upper())
 
777
                        except: return False
 
778
                completion.set_match_func(match_func)
 
779
                #completion.set_text_column(0)
 
780
                completion.connect('match-selected',self._on_completion_match_selected, 2)
 
781
                self.search_entry.set_completion(completion)
 
782
                self.search_container = components.get_widget('search_container')
 
783
                
 
784
                self.update_filters()
 
785
                
 
786
                #dnd
 
787
                self._TARGET_TYPE_TEXT = 80
 
788
                self._TARGET_TYPE_URL = 81
 
789
                drop_types = [ ('text/x-moz-url',0,self._TARGET_TYPE_URL),
 
790
                                                                         ('text/unicode',0,self._TARGET_TYPE_TEXT),
 
791
                                                                         ('text/plain',0,self._TARGET_TYPE_TEXT)]
 
792
                self._feedlist.drag_dest_set(gtk.DEST_DEFAULT_ALL, drop_types, gtk.gdk.ACTION_COPY)
 
793
 
 
794
                if not self.layout.endswith("planet"):
 
795
                        val = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/entry_pane_position', 370)
 
796
                        if val < 10: val = 50
 
797
                        self.entry_pane.set_position(val)
 
798
                
 
799
                if not utils.RUNNING_HILDON:
 
800
                        f_p_default = 370
 
801
                        val = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/feed_pane_position', f_p_default)
 
802
                        if val < 10: val=50
 
803
                        
 
804
                if self.feed_pane is not None:
 
805
                        self.feed_pane.connect('realize', self._on_feed_pane_realized, val)
 
806
                
 
807
                if not self.changing_layout:
 
808
                        self.set_active_filter(FeedList.ALL)
 
809
                
 
810
                        val = self._app.db.get_setting(ptvDB.STRING, '/apps/penguintv/default_filter')
 
811
                        if val is not None:
 
812
                                try:
 
813
                                        filter_index = [row[F_NAME] for row in self._filters].index(val)
 
814
                                        cur_filter = self._filters[filter_index]
 
815
                                        if utils.HAS_SEARCH:
 
816
                                                if cur_filter[F_TYPE] == ptvDB.T_SEARCH or filter_index==FeedList.SEARCH:
 
817
                                                        self.set_active_filter(FeedList.ALL)
 
818
                                                else:
 
819
                                                        self.set_active_filter(filter_index)
 
820
                                        else:
 
821
                                                self.set_active_filter(filter_index)
 
822
                                except ValueError: #didn't find the item in the model (.index(val) fails)
 
823
                                        self.set_active_filter(FeedList.ALL)
 
824
                        else:
 
825
                                self.set_active_filter(FeedList.ALL)
 
826
                else:
 
827
                        self.set_active_filter(self._active_filter_index)
 
828
                #sys.stderr.write("done")
 
829
                return self._layout_container
 
830
                        
 
831
        def Hide(self):
 
832
                if self.app_window:
 
833
                        self.app_window.hide()
 
834
                del self._widgetTree
 
835
                del self.feed_list_view
 
836
                del self.entry_list_view
 
837
                del self.entry_view
 
838
                                
 
839
                #some widgets
 
840
                if self.feed_pane is not None:
 
841
                        del self.feed_pane
 
842
                del self._feedlist
 
843
                if not self.layout.endswith("planet"):
 
844
                        del self.entry_pane
 
845
                del self.app_window
 
846
                del self._status_view
 
847
                del self._disk_usage_widget
 
848
                
 
849
        def get_parent(self):
 
850
                return self.window
 
851
                
 
852
        def on_toggle_fullscreen_activate(self, event=None):
 
853
                self.toggle_fullscreen()
 
854
                
 
855
        def toggle_fullscreen(self):
 
856
                #don't fullscreen under these exceptions
 
857
                if self._notebook.get_current_page() == N_PLAYER:
 
858
                        assert self._gstreamer_player is not None
 
859
                #if self._notebook.get_current_page() == N_DOWNLOADS:
 
860
                #       return
 
861
 
 
862
                #maemo throws X Window System errors when doing this -- ignore them
 
863
                #http://labs.morpheuz.eng.br/blog/14/08/2007/xv-and-mplayer-on-maemo/
 
864
                if utils.RUNNING_HILDON:
 
865
                        gtk.gdk.error_trap_push()
 
866
                        
 
867
                self._fullscreen = not self._fullscreen
 
868
                if self._fullscreen:
 
869
                        self._do_fullscreen()
 
870
                else:
 
871
                        self._do_unfullscreen()
 
872
 
 
873
                if utils.RUNNING_HILDON:
 
874
                        while gtk.events_pending():
 
875
                                gtk.main_iteration()
 
876
                        gtk.gdk.flush()
 
877
                        gtk.gdk.error_trap_pop()
 
878
 
 
879
        def _do_fullscreen(self):
 
880
                if self._notebook.get_current_page() == N_PLAYER:
 
881
                        pixmap = gtk.gdk.Pixmap(None, 1, 1, 1)
 
882
                        color = gtk.gdk.Color()
 
883
                        cursor = gtk.gdk.Cursor(pixmap, pixmap, color, color, 0, 0)
 
884
                        self.window.window.set_cursor(cursor)
 
885
                if self._use_internal_player:
 
886
                        if self._gstreamer_player:
 
887
                                self._gstreamer_player.toggle_controls(True)
 
888
                if utils.HAS_SEARCH:
 
889
                        self.search_container.hide_all()
 
890
                        
 
891
                #elif self._notebook.get_current_page() == N_FEEDS:
 
892
                if self.feed_pane is not None:
 
893
                        self._app.db.set_setting(ptvDB.INT, '/apps/penguintv/feed_pane_position', self.feed_pane.get_position())
 
894
                if self.entry_pane is not None:
 
895
                        self._app.db.set_setting(ptvDB.INT, '/apps/penguintv/entry_pane_position', self.entry_pane.get_position())
 
896
                if not utils.RUNNING_HILDON:
 
897
                        if self.layout.endswith('planet'):
 
898
                                self.entry_pane.set_position(0)
 
899
                        else:
 
900
                                self.feed_pane.set_position(0)
 
901
 
 
902
                self._notebook.set_keep_hidden(True)
 
903
                self._widgetTree.get_widget('toolbar1').hide()
 
904
                if utils.RUNNING_SUGAR:
 
905
                        self._status_view.hide()
 
906
                elif utils.RUNNING_HILDON:
 
907
                        self.window.fullscreen()
 
908
                else:
 
909
                        self._widgetTree.get_widget('menubar2').hide()
 
910
                        self._widgetTree.get_widget('status_hbox').hide()
 
911
                        self._filter_container.hide_all()
 
912
                        self.app_window.fullscreen()
 
913
 
 
914
        def _do_unfullscreen(self):
 
915
                if self._fullscreen_lock:
 
916
                        return
 
917
                        
 
918
                self._fullscreen_lock = True
 
919
                #if self._notebook.get_current_page() == N_PLAYER:
 
920
                self.window.window.set_cursor(None)
 
921
                if self._use_internal_player:
 
922
                        if self._gstreamer_player is not None:
 
923
                                self._gstreamer_player.toggle_controls(False)
 
924
                        
 
925
                if utils.HAS_SEARCH:
 
926
                        self.search_container.show_all()
 
927
                        
 
928
                #elif self._notebook.get_current_page() == N_FEEDS:
 
929
                if not utils.RUNNING_HILDON:
 
930
                        if self.layout.endswith('planet'):
 
931
                                val = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/entry_pane_position', 370)
 
932
                                self.entry_pane.set_position(val)
 
933
                        else:
 
934
                                val = self._app.db.get_setting(ptvDB.INT, '/apps/penguintv/feed_pane_position', 370)
 
935
                                self.feed_pane.set_position(val)
 
936
                        
 
937
                self._notebook.set_keep_hidden(False)
 
938
                
 
939
                #don't show the toolbar if we are on hildon and we are in the player
 
940
                pagenum = self._notebook.get_current_page()
 
941
                if not utils.RUNNING_HILDON or not pagenum == N_PLAYER:
 
942
                        self._widgetTree.get_widget('toolbar1').show_all()
 
943
                
 
944
                def _unfullscreen_finish():
 
945
                        self.app_window.unfullscreen()
 
946
                        self._fullscreen_lock = False
 
947
                        return False
 
948
                
 
949
                if utils.RUNNING_SUGAR:
 
950
                        self._status_view.show()
 
951
                        self._fullscreen_lock = False
 
952
                elif utils.RUNNING_HILDON:
 
953
                        self.window.unfullscreen()
 
954
                        self._fullscreen_lock = False
 
955
                else:
 
956
                        self._widgetTree.get_widget('menubar2').show_all()
 
957
                        self._widgetTree.get_widget('status_hbox').show_all()
 
958
                        self._filter_container.show_all()
 
959
                        gobject.idle_add(_unfullscreen_finish)
 
960
        
 
961
        def on_about_activate(self,event):
 
962
                widgets = gtk.glade.XML(os.path.join(self._glade_prefix,'dialogs.glade'), "aboutdialog1",'penguintv')
 
963
                about_box = widgets.get_widget('aboutdialog1')
 
964
                about_box.set_name('PenguinTV')
 
965
                about_box.set_version(utils.VERSION)
 
966
                about_box.connect('response', self.on_about_response)
 
967
                about_box.show_all()
 
968
                
 
969
        def on_about_response(self, widget, event):
 
970
                widget.destroy()
 
971
 
 
972
        def on_app_delete_event(self, event, data=None):
 
973
                self._app.do_quit()
 
974
                
 
975
                def gtkquit():
 
976
                        if not self._app.is_quit_complete():
 
977
                                return True
 
978
                        logging.debug('hildon main_quit')
 
979
                        gtk.main_quit()
 
980
                        return False
 
981
 
 
982
                if utils.RUNNING_HILDON:
 
983
                        gobject.timeout_add(250, gtkquit)
 
984
                        
 
985
                return self.window.hide_on_delete()
 
986
                
 
987
        def on_app_destroy_event(self,event,data=None):
 
988
                if utils.RUNNING_HILDON:
 
989
                        gtk.main_quit()
 
990
                else:
 
991
                        self._app.do_quit()
 
992
                        
 
993
        def on_app_window_state_event(self, client, event):
 
994
                if event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED:
 
995
                        self.window_maximized = True
 
996
                elif event.new_window_state & gtk.gdk.WINDOW_STATE_MAXIMIZED == 0:
 
997
                        self.window_maximized = False
 
998
                        
 
999
        def on_add_feed_activate(self, event=None):
 
1000
                if self._state == S_MAJOR_DB_OPERATION:
 
1001
                        logging.warning("Please wait until feeds have loaded before adding a new one")
 
1002
                        return 
 
1003
                self._notebook.set_current_page(N_FEEDS)
 
1004
                self.show_window_add_feed() #not modal / blocking
 
1005
                
 
1006
        def on_add_feed_filter_activate(self,event):
 
1007
                selected = self.feed_list_view.get_selected()
 
1008
                if selected:
 
1009
                        title = self._app.db.get_feed_title(selected)
 
1010
                        dialog = FeedFilterDialog.FeedFilterDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'extra_dialogs.glade'), "window_feed_filter",'penguintv'),self._app)
 
1011
                        dialog.show()
 
1012
                        dialog.set_pointed_feed(selected,title)
 
1013
                        d = { 'title':title }
 
1014
                        dialog.set_filter_name(_("%(title)s Filtered" % d))
 
1015
                else:
 
1016
                        dialog = gtk.Dialog(title=_("No Feed Selected"), parent=None, flags=gtk.DIALOG_MODAL, buttons=(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
 
1017
                        label = gtk.Label(_("Please select the feed you would like to filter"))
 
1018
                        dialog.vbox.pack_start(label, True, True, 0)
 
1019
                        label.show()
 
1020
                        dialog.set_transient_for(self._app.main_window.get_parent())
 
1021
                        response = dialog.run()
 
1022
                        dialog.hide()
 
1023
                        del dialog
 
1024
                        
 
1025
        def on_connection_button_clicked(self, event):
 
1026
                self._app.toggle_net_connection()
 
1027
                
 
1028
        def pane_to_feeds(self):
 
1029
                self.feed_tabs.set_current_page(0)
 
1030
                
 
1031
        def on_feed_add_clicked(self, event):
 
1032
                if self._state == S_MAJOR_DB_OPERATION:
 
1033
                        logging.warning("Please wait until feeds have loaded before adding a new one")
 
1034
                        return 
 
1035
                self.show_window_add_feed() #not modal / blocking
 
1036
        
 
1037
        #def on_feed_pane_expose_event(self, widget, event):
 
1038
        #       self.feed_list_view.resize_columns(self.feed_pane.get_position())
 
1039
        
 
1040
        def on_feed_properties_activate(self, event):
 
1041
                import FeedPropertiesDialog
 
1042
                selected = self.feed_list_view.get_selected()
 
1043
                if selected:
 
1044
                        #title, description, url, link
 
1045
                        feed_info = self._app.db.get_feed_info(selected)
 
1046
                        if self._feed_properties_dialog is None:
 
1047
                                if utils.RUNNING_HILDON:
 
1048
                                        self._feed_properties_dialog = FeedPropertiesDialog.FeedPropertiesDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'hildon_dialogs.glade'), "window_feed_properties",'penguintv'),self._app)
 
1049
                                else:
 
1050
                                        self._feed_properties_dialog = FeedPropertiesDialog.FeedPropertiesDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'dialogs.glade'), "window_feed_properties",'penguintv'),self._app)
 
1051
                        self._feed_properties_dialog.set_feedid(selected)
 
1052
                        self._feed_properties_dialog.set_title(feed_info['title'])
 
1053
                        self._feed_properties_dialog.set_rss(feed_info['url'])
 
1054
                        self._feed_properties_dialog.set_description(feed_info['description'])
 
1055
                        self._feed_properties_dialog.set_link(feed_info['link'])
 
1056
                        self._feed_properties_dialog.set_last_poll(feed_info['lastpoll'])
 
1057
                        self._feed_properties_dialog.set_tags(self._app.db.get_tags_for_feed(selected))
 
1058
                        self._feed_properties_dialog.set_flags(self._app.db.get_flags_for_feed(selected))
 
1059
                        if self._app.feed_refresh_method == penguintv.REFRESH_AUTO:
 
1060
                                self._feed_properties_dialog.set_next_poll(feed_info['lastpoll']+feed_info['pollfreq'])
 
1061
                        else:
 
1062
                                self._feed_properties_dialog.set_next_poll(feed_info['lastpoll']+self._app.polling_frequency)
 
1063
                        self._feed_properties_dialog.show()
 
1064
                        
 
1065
        def on_feed_filter_properties_activate(self, event):
 
1066
                selected = self.feed_list_view.get_selected()
 
1067
                if selected:
 
1068
                        #title, description, url, link
 
1069
                        feed_info = self._app.db.get_feed_info(selected)
 
1070
                        self._feed_filter_properties_dialog.set_feed_id(selected)
 
1071
                        self._feed_filter_properties_dialog.set_pointed_feed_id(feed_info['feed_pointer'])
 
1072
                        self._feed_filter_properties_dialog.set_filter_name(feed_info['title'])
 
1073
                        self._feed_filter_properties_dialog.set_query(feed_info['description'])
 
1074
                        self._feed_filter_properties_dialog.show()
 
1075
                
 
1076
        def on_download_entry_activate(self, event):
 
1077
                entry = self.entry_list_view.get_selected()['entry_id']
 
1078
                self._app.download_entry(entry)
 
1079
                        
 
1080
        def on_download_unviewed_activate(self, event):
 
1081
                self._app.download_unviewed()
 
1082
                                
 
1083
        def on_download_unviewed_clicked(self,event):
 
1084
                self._app.download_unviewed()
 
1085
                        
 
1086
        def on_delete_entry_media_activate(self,event):
 
1087
                selected = self.entry_list_view.get_selected()['entry_id']
 
1088
                self._app.delete_entry_media(selected)
 
1089
                        
 
1090
        def on_delete_feed_media_activate(self,event):
 
1091
                selected = self.feed_list_view.get_selected()
 
1092
                if selected:
 
1093
                        self._app.delete_feed_media(selected)
 
1094
                        
 
1095
        def on_edit_tags_for_all_activate(self, event):
 
1096
                """Bring up mass tag creation window"""
 
1097
                import TagEditorNG
 
1098
                window_edit_tags_multi = TagEditorNG.TagEditorNG(gtk.glade.XML(os.path.join(self._glade_prefix,'dialogs.glade'), "dialog_tag_editor_ng",'penguintv'), self._app)
 
1099
                window_edit_tags_multi.show()
 
1100
                        
 
1101
        def on_export_opml_activate(self, event):
 
1102
                self._app.export_opml()
 
1103
                
 
1104
        def _on_feed_pane_realized(self, widget, val):
 
1105
                widget.set_position(val)
 
1106
                
 
1107
        def on_feedlistview_drag_data_received(self, widget, context, x, y, selection, targetType, time):
 
1108
                widget.emit_stop_by_name('drag-data-received')
 
1109
                if targetType == self._TARGET_TYPE_TEXT:
 
1110
                        url = ""
 
1111
                        for c in selection.data:
 
1112
                                if c != "\0":  #for some reason ever other character is a null.  what gives?
 
1113
                                        url = url+c
 
1114
                        if url.split(':')[0] == 'feed':
 
1115
                                url = url[url.find(':')+1:]
 
1116
                        self._app.add_feed(url)
 
1117
                elif targetType == self._TARGET_TYPE_URL:
 
1118
                        url = ""
 
1119
                        for c in selection.data[0:selection.data.find('\n')]:
 
1120
                                if c != '\0':
 
1121
                                        url = url+c
 
1122
                        if url.split(':')[0] == 'feed': #stupid wordpress does 'feed:http://url.com/whatever'
 
1123
                                url = url[url.find(':')+1:]
 
1124
                        self._app.add_feed(url, url)
 
1125
                        
 
1126
        def on_feeds_poll_clicked(self,event):
 
1127
                self._app.poll_feeds()
 
1128
                
 
1129
        def set_hide_entries_menuitem(self, state):
 
1130
                self._menu_widgettree.get_widget('hide_viewed_entries_cb').set_active(state)
 
1131
                
 
1132
        def set_hide_entries_visibility(self, state):
 
1133
                if state:
 
1134
                        self._menu_widgettree.get_widget('hide_viewed_entries_cb').show()
 
1135
                else:
 
1136
                        self._menu_widgettree.get_widget('hide_viewed_entries_cb').hide()
 
1137
                
 
1138
        def on_hide_entries_cb_toggled(self, event):
 
1139
                self.entry_list_view.set_hide_viewed(self._menu_widgettree.get_widget('hide_viewed_entries_cb').get_active())
 
1140
                
 
1141
        def on_hide_feeds_cb_toggled(self, checkbox):
 
1142
                status = checkbox.get_active()
 
1143
                self.feed_list_view.set_unread_toggle(status)
 
1144
                self._menu_widgettree.get_widget('hide_viewed_feeds_cb').set_active(status)
 
1145
                self._filter_unread_checkbox.set_active(status)
 
1146
                
 
1147
        def on_synchronize_button_clicked(self,event):
 
1148
                self._sync_dialog.hide()
 
1149
                self._sync_dialog.on_sync_button_clicked(event) 
 
1150
                                
 
1151
        def on_edit_favorite_tags(self, o=None):
 
1152
                import FilterSelectorDialog
 
1153
                if self._filter_selector_dialog is None:
 
1154
                        self._filter_selector_dialog = FilterSelectorDialog.FilterSelectorDialog(gtk.glade.XML(os.path.join(self._glade_prefix,'dialogs.glade'), "dialog_tag_favorites",'penguintv'),self)
 
1155
                self._filter_selector_dialog.set_taglists(self._filters, self._favorite_filters)
 
1156
                self._filter_selector_dialog.Show()
 
1157
        
 
1158
        def on_filter_changed(self, widget):
 
1159
                model = widget.get_model()
 
1160
                
 
1161
                it = widget.get_active_iter()
 
1162
                if it is None:
 
1163
                        return
 
1164
                else:
 
1165
                        #if this is the edit tags menu item...
 
1166
                        if model[it][2] == 2:
 
1167
                                self.on_edit_favorite_tags()
 
1168
                                self._filter_selector_combo.set_active_iter(model.get_iter(self._active_filter_path))
 
1169
                                return
 
1170
                                
 
1171
                        if model[it][1] == _('All Tags'):
 
1172
                                return
 
1173
                
 
1174
                        names = [f[F_NAME] for f in self._filters]
 
1175
                        index = names.index(model[it][1])
 
1176
        
 
1177
                        if self._active_filter_index == index and not self.changing_layout:
 
1178
                                return
 
1179
                        self._active_filter_name = model[it][1]
 
1180
                        self._active_filter_index = index
 
1181
                        self._active_filter_path = model.get_path(it)
 
1182
                        
 
1183
                        if utils.HAS_SEARCH and index == FeedList.SEARCH:
 
1184
                                self._filter_tree[FeedList.SEARCH][3] = True
 
1185
                        else:
 
1186
                                self._filter_tree[FeedList.SEARCH][3] = False
 
1187
                                
 
1188
                        if utils.HAS_STATUS_ICON:
 
1189
                                self._filter_tree[FeedList.NOTIFY][3] = True
 
1190
                        else:
 
1191
                                self._filter_tree[FeedList.NOTIFY][3] = False
 
1192
 
 
1193
                        model.refilter()
 
1194
 
 
1195
                self._activate_filter()
 
1196
                
 
1197
        def _find_path(self, index):
 
1198
                model = self._filter_selector_combo.get_model()
 
1199
                name = self._filters[index][F_NAME]
 
1200
                self._active_filter_path = None
 
1201
                #if utils.RUNNING_HILDON:
 
1202
                #       #not a tree, so some filters appear twice.  Need to select first
 
1203
                #       #instance, which foreach does not do easily
 
1204
                #       for row in model:
 
1205
                #               if row[1] == name:
 
1206
                #                       self._active_filter_path = row.path
 
1207
                #                       break
 
1208
                #else:
 
1209
                def hunt_path(model, p, it):
 
1210
                        if model[it][1] == name and self._active_filter_path is None:
 
1211
                                self._active_filter_path = p
 
1212
                model.foreach(hunt_path)
 
1213
                
 
1214
        def set_active_filter(self, index):
 
1215
                model = self._filter_selector_combo.get_model()
 
1216
                if utils.HAS_SEARCH and index == FeedList.SEARCH:
 
1217
                        self._filter_tree[FeedList.SEARCH][3] = True
 
1218
                else:
 
1219
                        self._filter_tree[FeedList.SEARCH][3] = False
 
1220
                
 
1221
                if utils.HAS_STATUS_ICON:
 
1222
                        self._filter_tree[FeedList.NOTIFY][3] = True
 
1223
                else:
 
1224
                        self._filter_tree[FeedList.NOTIFY][3] = False
 
1225
                        
 
1226
                model.refilter()
 
1227
 
 
1228
                self._find_path(index)
 
1229
                it = model.get_iter(self._active_filter_path)
 
1230
                self._filter_selector_combo.set_active_iter(it)
 
1231
 
 
1232
        def _activate_filter(self):
 
1233
                current_filter = self._filters[self._active_filter_index]
 
1234
                if current_filter[F_TYPE] == ptvDB.T_SEARCH and self._state == S_MAJOR_DB_OPERATION:
 
1235
                        self.set_active_filter(FeedList.ALL)
 
1236
                        return
 
1237
                self._app.change_filter(current_filter[F_NAME],current_filter[F_TYPE])
 
1238
                
 
1239
        def on_import_opml_activate(self, event):
 
1240
                if utils.RUNNING_HILDON:
 
1241
                        dialog = hildon.FileChooserDialog(self.window, action=gtk.FILE_CHOOSER_ACTION_OPEN)
 
1242
                else:
 
1243
                        dialog = gtk.FileChooserDialog(_('Select OPML...'),None, action=gtk.FILE_CHOOSER_ACTION_OPEN,
 
1244
                                                                  buttons=(gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN,gtk.RESPONSE_OK))
 
1245
                        dialog.set_default_response(gtk.RESPONSE_OK)
 
1246
        
 
1247
                filter = gtk.FileFilter()
 
1248
                filter.set_name("OPML files")
 
1249
                filter.add_pattern("*.opml")
 
1250
                dialog.add_filter(filter)
 
1251
                
 
1252
                filter = gtk.FileFilter()
 
1253
                filter.set_name("All files")
 
1254
                filter.add_pattern("*")
 
1255
                dialog.add_filter(filter)
 
1256
                
 
1257
                dialog.set_transient_for(self._app.main_window.get_parent())
 
1258
                
 
1259
                response = dialog.run()
 
1260
                if response == gtk.RESPONSE_OK:
 
1261
                        f = open(dialog.get_filename(), "r")
 
1262
                        self.display_status_message(_("Importing Feeds, please wait..."))
 
1263
                        self._app.import_subscriptions(f)
 
1264
                elif response == gtk.RESPONSE_CANCEL:
 
1265
                        logging.info('Closed, no files selected')
 
1266
                dialog.destroy()                
 
1267
                
 
1268
        def on_app_key_press_event(self, widget, event):
 
1269
                keyname = gtk.gdk.keyval_name(event.keyval)
 
1270
                #if event.state & gtk.gdk.CONTROL_MASK:
 
1271
                #       if keyname == 'k':
 
1272
                #               self.search_entry.grab_focus()
 
1273
                
 
1274
                if event.state & gtk.gdk.MOD1_MASK:
 
1275
                        if keyname == '1':
 
1276
                                self._notebook.set_current_page(N_FEEDS)
 
1277
                        elif keyname == '2':
 
1278
                                if self._notebook.is_showing(N_PLAYER):
 
1279
                                        self._notebook.set_current_page(N_PLAYER)
 
1280
                        elif keyname == '3':
 
1281
                                if self._notebook.is_showing(N_DOWNLOADS):
 
1282
                                        self._notebook.set_current_page(N_DOWNLOADS)
 
1283
                
 
1284
                if utils.RUNNING_SUGAR:
 
1285
                        if keyname == 'KP_Left' or keyname == 'Left' or keyname == 'KP_4':
 
1286
                                self.feed_list_view.grab_focus()
 
1287
                        elif keyname == 'KP_Right' or keyname == 'Right' \
 
1288
                          or keyname == 'KP_6':
 
1289
                                self.entry_view.grab_focus()
 
1290
                elif utils.RUNNING_HILDON:
 
1291
                        #Move up                                Arrow key up    GDK_Up
 
1292
                        #Move down                              Arrow key down  GDK_Down
 
1293
                        #Move left                              Arrow key left  GDK_Left
 
1294
                        #Move right                         Arrow key right GDK_Right
 
1295
                        #Select, Confirm                        Return          GDK_Return
 
1296
                        #Cancel, Close                      Esc                 GDK_Escape
 
1297
                        #Open menu                              F4                  GDK_F4
 
1298
                        #Full screen                        F6              GDK_F6
 
1299
                        #Increase / Zoom in / Volume up         F7                  GDK_F7
 
1300
                        #Decrease / Zoom out / Volume down      F8                  GDK_F8
 
1301
                        
 
1302
                        if keyname == 'KP_Left' or keyname == 'Left':
 
1303
                                self.feed_list_view.grab_focus()
 
1304
                        elif keyname == 'KP_Right' or keyname == 'Right':
 
1305
                                self.entry_view.grab_focus()
 
1306
                        elif keyname == 'F6':
 
1307
                                self.toggle_fullscreen()
 
1308
                        elif keyname == 'F7':
 
1309
                                if self._gstreamer_player is not None:
 
1310
                                        self._gstreamer_player.vol_up()
 
1311
                        elif keyname == 'F8':
 
1312
                                if self._gstreamer_player is not None:
 
1313
                                        self._gstreamer_player.vol_down()
 
1314
                        elif keyname == 'Escape':
 
1315
                                self.feed_tabs.set_current_page(0)
 
1316
                else: #regular desktop version..
 
1317
                        if keyname == 'F11':
 
1318
                                self.toggle_fullscreen()
 
1319
                                #the key press will also trigger the accelerator once the menu
 
1320
                                #comes back -- stop it
 
1321
                                widget.stop_emission("key-press-event")
 
1322
                        else:
 
1323
                                if self._use_internal_player and self._notebook.get_current_page() == N_PLAYER:
 
1324
                                        #if gstreamer can do something with this key, stop further
 
1325
                                        #emission
 
1326
                                        if self._gstreamer_player.handle_key(keyname):
 
1327
                                                widget.stop_emission("key-press-event")
 
1328
                                        if keyname == "F" and event.state & gtk.gdk.CONTROL_MASK:
 
1329
                                                self._gstreamer_player.ff()
 
1330
                                        elif keyname == "B" and event.state & gtk.gdk.CONTROL_MASK:
 
1331
                                                self._gstreamer_player.rew()
 
1332
                        
 
1333
        def on_mark_entry_as_viewed_activate(self,event):
 
1334
                entry = self.entry_list_view.get_selected()
 
1335
                self._app.mark_entry_as_viewed(entry['entry_id'], entry['feed_id'])
 
1336
                
 
1337
        def on_mark_entry_as_unviewed_activate(self,event):
 
1338
                entry = self.entry_list_view.get_selected()['entry_id']
 
1339
                self._app.mark_entry_as_unviewed(entry)
 
1340
                
 
1341
        def on_keep_entry_new_activate(self, event):
 
1342
                entry = self.entry_list_view.get_selected()['entry_id']
 
1343
                self._app.activate_link("keep:%i" % (entry,))
 
1344
 
 
1345
        def on_unkeep_entry_new_activate(self, event):
 
1346
                entry = self.entry_list_view.get_selected()['entry_id']
 
1347
                self._app.activate_link("unkeep:%i" % (entry,))
 
1348
                
 
1349
        def on_mark_feed_as_viewed_activate(self, button=None, event=None):
 
1350
                feed = self.feed_list_view.get_selected()
 
1351
                if feed:
 
1352
                        self._app.mark_feed_as_viewed(feed)
 
1353
                        
 
1354
        def on_mark_all_viewed_activate(self, event):
 
1355
                self._app.mark_all_viewed()
 
1356
                        
 
1357
        def _on_notebook_realized(self, widget):
 
1358
                self._notebook.show_page(N_FEEDS)
 
1359
                if not utils.HAS_SEARCH:
 
1360
                        self.search_container.hide_all()
 
1361
                #if utils.RUNNING_SUGAR:
 
1362
                #       self._filter_container.hide_all()
 
1363
        
 
1364
                if self._use_internal_player:
 
1365
                        self._gstreamer_player.load()
 
1366
                        if self._gstreamer_player.get_queue_count() > 0:
 
1367
                                self._notebook.show_page(N_PLAYER)
 
1368
                                self.emit('player-show')
 
1369
                                
 
1370
        def _on_notebook_page_selected(self, widget, page, pagenum):
 
1371
                if utils.RUNNING_HILDON:
 
1372
                        if pagenum == N_PLAYER:
 
1373
                                self.toolbar.hide()
 
1374
                        else:
 
1375
                                self.toolbar.show()
 
1376
                
 
1377
        #def _on_gst_player_realized(self, widget):
 
1378
        #       print "seek seek seek"
 
1379
        #       self._gstreamer_player.seek_to_saved_position()
 
1380
 
 
1381
        def on_play_entry_activate(self, event):
 
1382
                entry = self.entry_list_view.get_selected()['entry_id']
 
1383
                self._app.play_entry(entry)
 
1384
                                
 
1385
        def on_play_unviewed_activate(self, event):
 
1386
                self._app.play_unviewed()
 
1387
                        
 
1388
        def on_play_unviewed_clicked(self, event):
 
1389
                self._app.play_unviewed()
 
1390
                
 
1391
        def _on_player_item_queued(self, player, filename, name, userdata):
 
1392
                self._notebook.show_page(N_PLAYER)
 
1393
                self.emit('player-show')        
 
1394
                #if player.get_queue_count() == 1:
 
1395
                #       try:
 
1396
                #               self._notebook.set_current_page(N_PLAYER)
 
1397
                #               player.play()
 
1398
                #       except:
 
1399
                #               pass #fails while loading
 
1400
                if utils.RUNNING_HILDON:
 
1401
                        self._player_label.set_markup(_('Player (%d)') % player.get_queue_count())
 
1402
                else:
 
1403
                        self._player_label.set_markup(_('<span size="small">Player (%d)</span>') % player.get_queue_count())
 
1404
                #if self._state != S_MAJOR_DB_OPERATION:
 
1405
                #       tip = tooltips(self._player_label)
 
1406
                #       tip.display_notification("title", "text")
 
1407
                
 
1408
        def _on_player_items_removed(self, player):
 
1409
                if player.get_queue_count() == 0:
 
1410
                        self._notebook.hide_page(N_PLAYER)
 
1411
                        self.emit('player-hide')
 
1412
                        player.stop()
 
1413
                if utils.RUNNING_HILDON:
 
1414
                        self._player_label.set_markup(_('Player (%d)') % player.get_queue_count())
 
1415
                else:
 
1416
                        self._player_label.set_markup(_('<span size="small">Player (%d)</span>') % player.get_queue_count())
 
1417
                
 
1418
        def on_preferences_activate(self, event):
 
1419
                self._app.window_preferences.show()
 
1420
                
 
1421
        def on_quit2_activate(self,event):
 
1422
                self._app.do_quit() #make the program quit, dumbass
 
1423
                ##DEBUG for exit_toolbutton
 
1424
                #if utils.RUNNING_SUGAR:
 
1425
                #       gtk.main_quit()
 
1426
                
 
1427
        def on_refresh_activate(self, event):
 
1428
                feed = self.feed_list_view.get_selected()
 
1429
                self._app.refresh_feed(feed)
 
1430
                
 
1431
        def on_refresh_feeds_activate(self, event):
 
1432
                self._app.poll_feeds()
 
1433
 
 
1434
        def on_refresh_feeds_with_errors_activate(self, event):
 
1435
                self._app.poll_feeds(ptvDB.A_ERROR_FEEDS)
 
1436
                
 
1437
        def on_refresh_visible_feeds_activate(self, event):
 
1438
                if self._active_filter_index > FeedList.SEARCH:
 
1439
                        feeds = self._app.db.get_feeds_for_tag(self._active_filter_name)
 
1440
                        self._app.do_poll_multiple(None, ptvDB.A_IGNORE_ETAG, feeds, 
 
1441
                                        message=_("Refreshing %s..." % self._active_filter_name))
 
1442
                elif utils.RUNNING_HILDON:
 
1443
                        self._app.do_poll_multiple(None, ptvDB.A_IGNORE_ETAG)
 
1444
                
 
1445
        def on_reindex_searches_activate(self, event):
 
1446
                self.search_container.set_sensitive(False)
 
1447
                self._app.set_state(penguintv.DEFAULT)
 
1448
                self.search_entry.set_text(_("Please wait..."))
 
1449
                self._app.db.doindex(self._app._done_populating)
 
1450
                
 
1451
        def _sensitize_search(self):
 
1452
                self.search_entry.set_text("")
 
1453
                self.search_container.set_sensitive(True)
 
1454
                
 
1455
        def on_remove_feed_activate(self, event, override=False):
 
1456
                assert self._state != S_MAJOR_DB_OPERATION
 
1457
                
 
1458
                selected = self.feed_list_view.get_selected()
 
1459
                if selected:
 
1460
                        self._notebook.set_current_page(N_FEEDS)
 
1461
                        if not override:
 
1462
                                dialog = gtk.Dialog(title=_("Really Remove Feed?"), parent=None, flags=gtk.DIALOG_MODAL, buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT, gtk.STOCK_REMOVE, gtk.RESPONSE_ACCEPT))
 
1463
                                label = gtk.Label(_("Are you sure you want to remove this feed, all its entries, and all its media?  \nThis operation cannot be undone."))
 
1464
                                dialog.vbox.pack_start(label, True, True, 0)
 
1465
                                label.show()
 
1466
                                dialog.set_transient_for(self._app.main_window.get_parent())
 
1467
                                response = dialog.run()
 
1468
                                dialog.hide()
 
1469
                                del dialog
 
1470
                                if response != gtk.RESPONSE_ACCEPT:             
 
1471
                                        return
 
1472
                        self._app.remove_feed(selected)
 
1473
                
 
1474
        def on_resume_all_activate(self, event):
 
1475
                self._app.resume_resumable()
 
1476
                
 
1477
        def on_save_search_clicked(self, event):
 
1478
                query = self.search_entry.get_text()
 
1479
                if query=="":
 
1480
                        return
 
1481
                self._window_add_search.show()
 
1482
                self._window_add_search.set_query(query)                
 
1483
                
 
1484
        def on_search_clear_clicked(self, event):
 
1485
                self._app.set_state(penguintv.DEFAULT)
 
1486
                
 
1487
        def on_saved_searches_activate(self, event):
 
1488
                window_edit_saved_searches = EditSearchesDialog.EditSearchesDialog(os.path.join(self._glade_prefix,'extra_dialogs.glade'),self._app)
 
1489
                window_edit_saved_searches.show()
 
1490
                del window_edit_saved_searches
 
1491
                
 
1492
        def on_search_entry_activate(self, event):
 
1493
                self._app.manual_search(self.search_entry.get_text())
 
1494
                
 
1495
        def on_search_entry_changed(self, widget):
 
1496
                pass
 
1497
                #self.search_entry.get_completion().complete()
 
1498
                #if self.search_container.get_property("sensitive"):
 
1499
                #       self._app.threaded_search(self.search_entry.get_text())
 
1500
                
 
1501
        def on_show_downloads_activate(self, event):
 
1502
                self._app.show_downloads()
 
1503
                
 
1504
        def on_stop_downloads_clicked(self, widget):
 
1505
                self._app.stop_downloads()
 
1506
                
 
1507
        #def on_stop_downloads_toggled(self, widget):
 
1508
        #       print "toggled"
 
1509
        #       self._app.stop_downloads_toggled(widget.get_active())
 
1510
        
 
1511
        def on_synchronize_activate(self, event):
 
1512
                self._sync_dialog.Show()
 
1513
 
 
1514
        def on_standard_layout_activate(self, event):   
 
1515
                self._app.change_layout('standard')
 
1516
        
 
1517
        def on_horizontal_layout_activate(self, event):
 
1518
                self._app.change_layout('widescreen')   
 
1519
 
 
1520
        def on_vertical_layout_activate(self,event):
 
1521
                self._app.change_layout('vertical')     
 
1522
                
 
1523
        def on_planet_layout_activate(self, event):
 
1524
                self._app.change_layout('planet')
 
1525
                
 
1526
        def on_fancy_feed_display_activate(self, menuitem):
 
1527
                self.feed_list_view.set_fancy(menuitem.get_active())
 
1528
                self._app.db.set_setting(ptvDB.BOOL, '/apps/penguintv/fancy_feedlist', menuitem.get_active())
 
1529
                
 
1530
        def on_show_notifications_activate(self, menuitem):
 
1531
                self._app.db.set_setting(ptvDB.BOOL, '/apps/penguintv/show_notifications',
 
1532
                                                         menuitem.get_active())
 
1533
                                
 
1534
        def activate_layout(self, layout):
 
1535
                """gets called by app when it's ready"""
 
1536
                self.changing_layout = True
 
1537
                self.layout=layout
 
1538
                self._app.save_settings()
 
1539
                self._app.write_feed_cache()
 
1540
                self._layout_dock.remove(self._layout_container)
 
1541
                
 
1542
                self._layout_dock.add(self.load_layout())
 
1543
                self.entry_view.post_show_init()
 
1544
                if self.layout.endswith("planet"):
 
1545
                        self._menu_widgettree.get_widget('entry_menu_item').hide()
 
1546
                else:
 
1547
                        self._menu_widgettree.get_widget('entry_menu_item').show()
 
1548
 
 
1549
                self._notebook.show_only(N_FEEDS)
 
1550
                if not utils.HAS_SEARCH:
 
1551
                        self.search_container.hide_all()
 
1552
                if utils.RUNNING_HILDON:
 
1553
                        self._layout_components.get_widget('filter_label').hide()
 
1554
                        self._filter_unread_checkbox.hide()
 
1555
                #if not utils.USE_TAGGING:
 
1556
                #       self._filter_container.hide_all()                       
 
1557
                if self._use_internal_player:
 
1558
                        if self._gstreamer_player.get_queue_count() > 0:
 
1559
                                self._notebook.show_page(N_PLAYER)
 
1560
                                self.emit('player-show')
 
1561
                #can't reset changing_layout because app hasn't updated pointers yet
 
1562
                
 
1563
        def is_changing_layout(self):
 
1564
                return self.changing_layout
 
1565
                
 
1566
        def display_status_message(self, m, update_category=U_STANDARD):
 
1567
                """displays a status message on the main status bar.  If this is a polling update or download
 
1568
                   update, we don't overwrite what's there."""  
 
1569
                if self._status_view is None:
 
1570
                        return
 
1571
                
 
1572
                current_text = self._status_view.get_status().get_text()
 
1573
        
 
1574
                if current_text == "":
 
1575
                        self._status_owner = update_category
 
1576
                        self._status_view.set_status(m)
 
1577
                        if utils.HAS_STATUS_ICON:
 
1578
                                self._status_icon.set_tooltip(m)
 
1579
                else:
 
1580
                        if update_category >= self._status_owner:
 
1581
                                self._status_view.set_status(m)
 
1582
                                if utils.HAS_STATUS_ICON:
 
1583
                                        self._status_icon.set_tooltip(m)
 
1584
                                if m == "":
 
1585
                                        self._status_owner = U_NOBODY
 
1586
                                else:
 
1587
                                        self._status_owner = update_category
 
1588
                        #if update_category==U_STANDARD:  #only overwrite if this is not a poll or download
 
1589
                        #       self._status_owner = update_category
 
1590
                        #       self._status_view.set_status(m)
 
1591
                        #elif update_category == U_POLL and self._status_owner != U_STANDARD:
 
1592
                        #       self._status_owner = update_category
 
1593
                        #       self._status_view.set_status(m)                         
 
1594
                        #elif update_category == U_DOWNLOAD and self._status_owner == U_DOWNLOAD:
 
1595
                        #       self._status_view.set_status(m)
 
1596
                
 
1597
                return False #in case of timeouts
 
1598
                
 
1599
        def update_progress_bar(self, p, update_category=U_STANDARD):
 
1600
                """Update the progress bar.  if both downloading and polling, polling wins"""
 
1601
                
 
1602
                if p==-1:
 
1603
                        self._bar_owner = U_NOBODY
 
1604
                        self._status_view.set_progress_percentage(0)
 
1605
                else:
 
1606
                        if update_category >= self._bar_owner:
 
1607
                                self._bar_owner = update_category
 
1608
                                self._status_view.set_progress_percentage(p)
 
1609
                                
 
1610
        def _unset_state(self):
 
1611
                """gets app ready to display new state by unloading current state"""
 
1612
                #bring state back to default
 
1613
                if self._state == S_MANUAL_SEARCH:
 
1614
                        self.search_entry.set_text("")
 
1615
                if self._state == S_MAJOR_DB_OPERATION:
 
1616
                        self._widgetTree.get_widget("feed_add_button").set_sensitive(True)
 
1617
                        self._widgetTree.get_widget("feed_remove").set_sensitive(True)
 
1618
                        if not utils.RUNNING_SUGAR:
 
1619
                                #these are menu items
 
1620
                                self._menu_widgettree.get_widget("add_feed").set_sensitive(True)
 
1621
                                self._menu_widgettree.get_widget("remove_feed").set_sensitive(True)
 
1622
                                self._menu_widgettree.get_widget("properties").set_sensitive(True)
 
1623
                        #elif not utils.USE_TAGGING:
 
1624
                        #       self._menu_widgettree.get_widget("add_feed_filter").set_sensitive(True)
 
1625
                        
 
1626
                        self.display_status_message("") 
 
1627
                        self.update_progress_bar(-1,U_LOADING)
 
1628
                        
 
1629
        def __state_changed_cb(self, app, new_state, data=None):
 
1630
                d = {penguintv.DEFAULT: S_DEFAULT,
 
1631
                         penguintv.MANUAL_SEARCH: S_MANUAL_SEARCH,
 
1632
                         penguintv.TAG_SEARCH: S_TAG_SEARCH,
 
1633
                         #penguintv.ACTIVE_DOWNLOADS: S_DEFAULT,
 
1634
                         penguintv.MAJOR_DB_OPERATION: S_MAJOR_DB_OPERATION}
 
1635
                         
 
1636
                new_state = d[new_state]
 
1637
                if self._state == new_state:
 
1638
                        return  
 
1639
                        
 
1640
                self._unset_state()
 
1641
                if new_state == S_MANUAL_SEARCH:
 
1642
                        if self.get_active_filter()[1] != FeedList.SEARCH:      
 
1643
                                self.set_active_filter(FeedList.SEARCH)
 
1644
                if new_state == S_TAG_SEARCH:
 
1645
                        self.search_entry.set_text("")
 
1646
                
 
1647
                if new_state == S_MAJOR_DB_OPERATION:
 
1648
                        self._widgetTree.get_widget("feed_add_button").set_sensitive(False)
 
1649
                        self._widgetTree.get_widget("feed_remove").set_sensitive(False)
 
1650
 
 
1651
                        if not utils.RUNNING_SUGAR:
 
1652
                                #these are menu items
 
1653
                                self._menu_widgettree.get_widget("add_feed").set_sensitive(False)
 
1654
                                self._menu_widgettree.get_widget("remove_feed").set_sensitive(False)
 
1655
                                self._menu_widgettree.get_widget("properties").set_sensitive(False)
 
1656
                        #elif not utils.USE_TAGGING:
 
1657
                        #       self._menu_widgettree.get_widget("add_feed_filter").set_sensitive(False)
 
1658
                        
 
1659
                self._state = new_state
 
1660
 
 
1661
        def update_filters(self):
 
1662
                """update the filter combo box with the current list of filters"""
 
1663
                #get name of current filter, if a tag
 
1664
                current_filter = self.get_active_filter()[0]
 
1665
                self._filters = []
 
1666
                self._favorite_filters = []
 
1667
                self._filter_tree.clear()
 
1668
                completion_model = self.search_entry.get_completion().get_model()
 
1669
                completion_model.clear()
 
1670
                                
 
1671
                i=0 #we set i here so that searches and regular tags have incrementing ids
 
1672
                
 
1673
                builtin = _("All Feeds")
 
1674
                text = builtin+" ("+str(len(self._app.db.get_feedlist()))+")"
 
1675
                self._filters.append([0,builtin,text,ptvDB.T_BUILTIN])
 
1676
                self._filter_tree.append(None, [text, builtin, 0, True])
 
1677
                i += 1
 
1678
                
 
1679
                builtin = _("Downloaded Media")
 
1680
                self._filters.append([0,builtin,builtin,ptvDB.T_BUILTIN])
 
1681
                self._filter_tree.append(None, [builtin, builtin, 0, True])
 
1682
                i += 1
 
1683
                
 
1684
                builtin = _("Notifying Feeds")
 
1685
                text = builtin+" ("+str(len(self._app.db.get_feeds_for_flag(ptvDB.FF_NOTIFYUPDATES)))+")"
 
1686
                self._filters.append([0,builtin,text,ptvDB.T_BUILTIN])
 
1687
                self._filter_tree.append(None, [text, builtin, 0, utils.HAS_STATUS_ICON])
 
1688
                i += 1
 
1689
                
 
1690
                builtin = _("Search Results")
 
1691
                self._filters.append([0,builtin,builtin,ptvDB.T_BUILTIN])
 
1692
                self._search_iter = self._filter_tree.append(None, [builtin, builtin, 0, False])
 
1693
                i += 1
 
1694
                
 
1695
                has_search = False
 
1696
                if utils.HAS_SEARCH:
 
1697
                        tags = self._app.db.get_all_tags(ptvDB.T_SEARCH)        
 
1698
                        if tags:
 
1699
                                has_search = True
 
1700
                                for tag,favorite in tags:
 
1701
                                        i+=1
 
1702
                                        self._filters.append([favorite, tag,tag,ptvDB.T_SEARCH])
 
1703
                                        completion_model.append([tag,_('tag: %s') % (tag,), i - 1])
 
1704
                                        if favorite > 0:
 
1705
                                                self._favorite_filters.append([favorite, tag,tag, i])
 
1706
                
 
1707
                tags = self._app.db.get_all_tags(ptvDB.T_TAG)
 
1708
                if tags:
 
1709
                        self._filter_tree.append(None, ["", "", 1, True])
 
1710
                        for tag,favorite in tags:
 
1711
                                i+=1
 
1712
                                self._filters.append([favorite, tag,tag+" ("+str(self._app.db.get_count_for_tag(tag))+")",ptvDB.T_TAG])
 
1713
                                completion_model.append([tag,_('tag: %s') % (tag,), i - 1])
 
1714
                                if favorite > 0:
 
1715
                                        self._favorite_filters.append([favorite, tag,tag+" ("+str(self._app.db.get_count_for_tag(tag))+")", i])
 
1716
                                
 
1717
                self._favorite_filters.sort()
 
1718
                self._favorite_filters = [f[1:] for f in self._favorite_filters]
 
1719
        
 
1720
                for fav in self._favorite_filters:
 
1721
                        self._filter_tree.append(None, [fav[1], fav[0], 0, True])
 
1722
                        
 
1723
                if tags:
 
1724
                        if utils.RUNNING_HILDON:
 
1725
                                all_tags_submenu = None
 
1726
                                self._filter_tree.append(None, ["", "", 1, True])
 
1727
                        else:
 
1728
                                all_tags_submenu = self._filter_tree.append(None, [_('All Tags'), _('All Tags'), 0, True])
 
1729
                        if has_search:
 
1730
                                for f in self._filters:
 
1731
                                        if f[F_TYPE] == ptvDB.T_SEARCH:
 
1732
                                                self._filter_tree.append(all_tags_submenu, [f[F_DISPLAY], f[F_NAME], 0, True])
 
1733
                                self._filter_tree.append(all_tags_submenu, ["", "", 1, True])
 
1734
                        for f in self._filters:
 
1735
                                if f[F_TYPE] == ptvDB.T_TAG:
 
1736
                                        self._filter_tree.append(all_tags_submenu, [f[F_DISPLAY], f[F_NAME], 0, True])
 
1737
                
 
1738
                if not utils.RUNNING_HILDON:    
 
1739
                        self._filter_tree.append(None, [_('Edit Favorite Tags...'), _('Edit Favorite Tags...'), 2, True])
 
1740
                
 
1741
                #get index for our previously selected tag
 
1742
                index = self.get_filter_index(current_filter)
 
1743
                if not self.changing_layout:
 
1744
                        if index is not None:
 
1745
                                self.set_active_filter(index)
 
1746
                        else:
 
1747
                                self.set_active_filter(FeedList.ALL)
 
1748
                                
 
1749
        def set_tag_favorites(self, tag_list):
 
1750
                old_order = [f[0] for f in self._favorite_filters]
 
1751
                i=0
 
1752
                for t in tag_list[:len(old_order)]:
 
1753
                        i+=1
 
1754
                        print t, i
 
1755
                        if t != old_order[i-1]:
 
1756
                                self._app.db.set_tag_favorite(t, i)
 
1757
                
 
1758
                if len(old_order) > 0:
 
1759
                        i = len(old_order)-1
 
1760
                else:
 
1761
                        i = 0
 
1762
                for t in tag_list[len(old_order):]:
 
1763
                        print t, i
 
1764
                        i+=1
 
1765
                        self._app.db.set_tag_favorite(t, i)
 
1766
                                
 
1767
                old = set(old_order)
 
1768
                new = set(tag_list)
 
1769
                removed = list(old.difference(new))
 
1770
                for t in removed:
 
1771
                        self._app.db.set_tag_favorite(t, 0)
 
1772
                self.update_filters()
 
1773
                
 
1774
        def _on_completion_match_selected(self, completion, model, iter, column):
 
1775
                self.search_entry.set_text("")
 
1776
                self.set_active_filter(model[iter][column])
 
1777
                                
 
1778
        def finish(self):
 
1779
                if self._use_internal_player:
 
1780
                        self._gstreamer_player.finish()
 
1781
                self.desensitize()
 
1782
                        
 
1783
        def get_filter_name(self, filt):
 
1784
                return self._filters[filt][F_NAME]
 
1785
                
 
1786
        def get_filter_index(self, string):
 
1787
                names = [m[F_NAME] for m in self._filters]
 
1788
                try:
 
1789
                        index = names.index(string)
 
1790
                        if names not in FeedList.BUILTIN_TAGS:
 
1791
                                return index
 
1792
                        return None
 
1793
                except:
 
1794
                        return None
 
1795
                
 
1796
        def get_active_filter(self):
 
1797
                return (self._active_filter_name,self._active_filter_index) 
 
1798
                
 
1799
        def rename_filter(self, old_name, new_name):
 
1800
                names = [m[F_NAME] for m in self._filters]
 
1801
                index = names.index(old_name)
 
1802
                self._filters[index][F_NAME] = new_name
 
1803
                self._filters[index][F_DISPLAY] = new_name
 
1804
                
 
1805
        def select_feed(self, feed_id):
 
1806
                #if we have a tag, pick the first one (really used just when adding
 
1807
                #feeds)
 
1808
                tags = self._app.db.get_tags_for_feed(feed_id)
 
1809
                if len(tags) > 0:
 
1810
                        if not self._active_filter_name in tags:
 
1811
                                self.set_active_filter(FeedList.ALL)
 
1812
                else:
 
1813
                        self.set_active_filter(FeedList.ALL)
 
1814
                self.feed_list_view.set_selected(feed_id)
 
1815
                self.feed_list_view.resize_columns()
 
1816
 
 
1817
        def update_disk_usage(self, size):
 
1818
                if self._disk_usage_widget is None:
 
1819
                        return
 
1820
                self._disk_usage_widget.set_markup(utils.format_size(size))
 
1821
 
 
1822
        def update_download_progress(self):
 
1823
                progresses = self._mm.get_download_list(Downloader.DOWNLOADING)
 
1824
                queued     = self._mm.get_download_list(Downloader.QUEUED)
 
1825
                paused     = self._mm.get_download_list(Downloader.PAUSED)
 
1826
                #print len(progresses)
 
1827
                if len(progresses)+len(queued)==0:
 
1828
                        self.display_status_message("")
 
1829
                        self.update_progress_bar(-1,U_DOWNLOAD)
 
1830
                        self._download_view.update_downloads()
 
1831
                        total = len(progresses) + len(queued) + len(paused)
 
1832
                        self._update_notebook_tabs(total)
 
1833
                        return
 
1834
                total_size = 0
 
1835
                downloaded = 0
 
1836
                for d in progresses+queued:
 
1837
                        if d.total_size<=0:
 
1838
                                total_size += 1
 
1839
                        else:
 
1840
                                total_size += d.total_size
 
1841
                        downloaded += (d.progress/100.0)*d.total_size
 
1842
                if total_size == 0:
 
1843
                        total_size=1
 
1844
                dict = { 'percent': downloaded*100.0/total_size,
 
1845
                                 'files': len(progresses)+len(queued),
 
1846
                                 'total': total_size>1 and "("+utils.format_size(total_size)+")" or '', #ternary operator simulation
 
1847
                                 's': len(progresses)>1 and 's' or '',
 
1848
                                 'queued': len(queued)} 
 
1849
                if dict['queued']>0:
 
1850
                        message = _("Downloaded %(percent)d%% of %(files)d file%(s)s, %(queued)d queued %(total)s") % dict
 
1851
                else:
 
1852
                        message = _("Downloaded %(percent)d%% of %(files)d file%(s)s %(total)s") % dict
 
1853
                self.display_status_message(message , U_DOWNLOAD) 
 
1854
                self.update_progress_bar(dict['percent']/100.0,U_DOWNLOAD)
 
1855
                
 
1856
                self._download_view.update_downloads()
 
1857
                self._update_notebook_tabs(len(progresses)+len(queued)+len(paused))
 
1858
                
 
1859
        def _update_notebook_tabs(self, number):
 
1860
                #logging.debug("updating notebook tabs (%i)" % number)
 
1861
                if number == 0:
 
1862
                        self._notebook.hide_page(N_DOWNLOADS)
 
1863
                else:
 
1864
                        if utils.RUNNING_HILDON:
 
1865
                                self._downloads_label.set_markup(_('Downloads (%d)') % number)
 
1866
                        else:
 
1867
                                self._downloads_label.set_markup(_('<span size="small">Downloads (%d)</span>') % number)
 
1868
                        self._notebook.show_page(N_DOWNLOADS)
 
1869
                                
 
1870
        def desensitize(self):
 
1871
                if self.app_window:
 
1872
                        self.app_window.set_sensitive(False)
 
1873
                else:
 
1874
                        self._layout_container.set_sensitive(False)
 
1875
                while gtk.events_pending(): #make sure the sensitivity change goes through
 
1876
                        gtk.main_iteration()
 
1877
                        
 
1878
        def sensitize(self):
 
1879
                if self.app_window:
 
1880
                        self.app_window.set_sensitive(True)
 
1881
                else:
 
1882
                        self._layout_container.set_sensitive(True)
 
1883
                while gtk.events_pending(): #make sure the sensitivity change goes through
 
1884
                        gtk.main_iteration()            
 
1885
                        
 
1886
class NotebookManager(gtk.Notebook):
 
1887
        """manages showing and hiding of tabs.  Also, hides the whole tab bar if only one 
 
1888
        tab open, and selects a different tab if the one we are closing is selected"""
 
1889
        def __init__(self):
 
1890
                gtk.Notebook.__init__(self)
 
1891
                # pages_showing refers to tabs that would be visible.
 
1892
                # It is overriden by keep_hidden
 
1893
                self._pages_showing = {}
 
1894
                self._default_page = 0
 
1895
                self._keep_hidden = False
 
1896
                
 
1897
        def append_page(self, widget, label):
 
1898
                self._pages_showing[len(self._pages_showing)] = False
 
1899
                gtk.Notebook.append_page(self, widget, label)
 
1900
        
 
1901
        def show_page(self, n):
 
1902
                if not self._pages_showing.has_key(n): return
 
1903
                if self._pages_showing[n] == True: return
 
1904
                self._pages_showing[n] = True
 
1905
                self.get_nth_page(n).show_all()
 
1906
                showing_count = 0
 
1907
                for key in self._pages_showing.keys():
 
1908
                        if self._pages_showing[key]:
 
1909
                                showing_count+=1
 
1910
                if showing_count > 1 and not self._keep_hidden:
 
1911
                        self.set_show_tabs(True)
 
1912
                                        
 
1913
        def hide_page(self, n):
 
1914
                if not self._pages_showing.has_key(n): return
 
1915
                if self._pages_showing[n] == False: return
 
1916
                self._pages_showing[n] = False
 
1917
                self.get_nth_page(n).hide()
 
1918
                showing_count = 0
 
1919
                for key in self._pages_showing.keys():
 
1920
                        if self._pages_showing[key]:
 
1921
                                showing_count+=1
 
1922
                if showing_count == 1:
 
1923
                        for key in self._pages_showing.keys():
 
1924
                                if self._pages_showing[key]:
 
1925
                                        self.set_current_page(key)
 
1926
                                        self.set_show_tabs(False)
 
1927
                if self.get_current_page() == n:
 
1928
                        self.set_current_page(self._default_page)
 
1929
                                        
 
1930
        def show_only(self, n):
 
1931
                if not self._pages_showing.has_key(n): return
 
1932
                self._default_page = n
 
1933
                for i in range(0,self.get_n_pages()):
 
1934
                        self._pages_showing[i] = i==n
 
1935
                        if i == n:
 
1936
                                self.get_nth_page(i).show_all()
 
1937
                        else:
 
1938
                                self.get_nth_page(i).hide_all()
 
1939
                self.set_current_page(n)
 
1940
                self.set_show_tabs(False)
 
1941
                
 
1942
        def set_keep_hidden(self, hide):
 
1943
                """For fullscreen mode, we never want to show tabs"""
 
1944
                
 
1945
                if hide:
 
1946
                        self.set_show_tabs(False)
 
1947
                        self._keep_hidden = True
 
1948
                else:
 
1949
                        self._keep_hidden = False
 
1950
                        showing_count = 0
 
1951
                        for key in self._pages_showing.keys():
 
1952
                                if self._pages_showing[key]:
 
1953
                                        showing_count+=1
 
1954
                        if showing_count > 1:
 
1955
                                self.set_show_tabs(True)
 
1956
                        
 
1957
        def is_showing(self, n):
 
1958
                try:
 
1959
                        return self._pages_showing[n]
 
1960
                except:
 
1961
                        return False
 
1962
                                        
 
1963
class ShouldntHappenError(Exception):
 
1964
        def __init__(self,error):
 
1965
                self.error = error
 
1966
        def __str__(self):
 
1967
                return self.error