3 This is the main module that binds everything together.
6 __copyright__
= "Copyright (c) 2002-2005 Free Software Foundation, Inc."
7 __license__
= """ GNU General Public License
9 This program is free software; you can redistribute it and/or modify it under the
10 terms of the GNU General Public License as published by the Free Software
11 Foundation; either version 2 of the License, or (at your option) any later
14 This program is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License along with
19 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
20 Place - Suite 330, Boston, MA 02111-1307, USA. """
23 from xml
.sax
import saxutils
36 import FeedCategoryList
39 from ItemView
import ItemView
40 from ItemList
import ItemListPresenter
, ItemListView
41 from FeedListView
import FeedsView
, FeedsPresenter
42 from OfflineToggle
import OfflineToggle
43 #from CategorySelector import CategoryPresenter, CategoryView
44 from MainloopManager
import MainloopManager
45 from FeedPropertiesDialog
import FeedPropertyView
, FeedPropertyPresenter
, show_feed_properties
as show_feed_properties_dialog
46 from PreferencesDialog
import PreferencesDialog
47 from Find
import FindPresenter
, FindView
56 class StatusPresenter(MVP
.BasicPresenter
):
57 def _initialize(self
):
58 self
._mmgr
= MessageManager
.get_instance()
59 self
._mmgr
.signal_connect(Event
.StatusDisplaySignal
,
63 def _display(self
, signal
):
64 cid
= self
._view
.get_context_id("straw_main")
66 self
._view
.push(cid
, self
._mmgr
.read_message())
70 def __init__(self
, widget
):
72 self
._tooltips
= gtk
.Tooltips()
74 self
._curr
_feed
= None
75 self
._curr
_category
= None
76 fclist
= FeedCategoryList
.get_instance()
77 fclist
.signal_connect(Event
.FeedCategoryChangedSignal
,
78 self
._category
_changed
)
80 def display_feed_error(self
, feed
):
81 if self
._curr
_feed
is not None:
82 self
._curr
_feed
.signal_disconnect(Event
.FeedErrorStatusChangedSignal
,
83 self
._error
_status
_changed
)
84 self
._curr
_feed
= feed
85 self
._curr
_feed
.signal_connect(Event
.FeedErrorStatusChangedSignal
,
86 self
._error
_status
_changed
)
90 def display_category_error(self
, category
):
92 self
._curr
_category
= category
96 def _update_view(self
):
98 if self
._curr
_category
and self
._curr
_category
.subscription
and self
._curr
_category
.subscription
.error
:
99 text
.append(_("Category error:"))
100 text
.append(self
._curr
_category
.subscription
.error
)
101 if self
._curr
_feed
and self
._curr
_feed
.error
:
102 text
.append(_("Feed Error:"))
103 text
.append(self
._curr
_feed
.error
)
106 self
._tooltips
.set_tip(self
._widget
,t
,t
)
107 self
._tooltips
.enable()
110 self
._tooltips
.disable()
114 def _category_changed(self
, signal
):
115 if signal
.sender
is self
._curr
_category
:
116 self
.display_category_error(self
._curr
_category
)
118 def _error_status_changed(self
, signal
):
119 if signal
.sender
is self
._curr
_feed
:
120 self
.display_feed_error(signal
.sender
)
126 class MenuFeedPropsPresenter(MVP
.BasicPresenter
):
127 def set_sensitive(self
, s
):
128 self
._view
.set_sensitive(s
)
131 class ToolbarView(MVP
.WidgetView
):
132 """ Widget: gtk.Toolbar"""
133 GCONF_DESKTOP_INTERFACE
= "/desktop/gnome/interface"
135 def _initialize(self
):
136 client
= gconf
.client_get_default()
137 if not client
.dir_exists(self
.GCONF_DESKTOP_INTERFACE
):
139 client
.add_dir(self
.GCONF_DESKTOP_INTERFACE
,
140 gconf
.CLIENT_PRELOAD_NONE
)
141 client
.notify_add(self
.GCONF_DESKTOP_INTERFACE
+"/toolbar_style",
142 self
._toolbar
_style
_changed
)
143 self
._widget
.set_tooltips(True)
145 def _toolbar_style_changed(self
, client
, notify_id
, entry
, *args
):
146 value
= entry
.value
.get_string()
147 self
._presenter
.style_changed(value
)
149 def set_style(self
, style
):
150 self
._widget
.set_style(style
)
153 client
= gconf
.client_get_default()
154 current_style
= client
.get_string(self
.GCONF_DESKTOP_INTERFACE
+"/toolbar_style")
157 class ToolbarPresenter(MVP
.BasicPresenter
):
158 STYLES
= {'both':gtk
.TOOLBAR_BOTH
,
159 'text':gtk
.TOOLBAR_TEXT
,
160 'icons':gtk
.TOOLBAR_ICONS
,
161 'both-horiz':gtk
.TOOLBAR_BOTH_HORIZ
}
163 def _initialize(self
):
164 style
= self
._view
.get_style()
165 if style
in self
.STYLES
.keys():
166 self
._view
.set_style(self
.STYLES
[style
])
169 def style_changed(self
, value
):
170 if value
in self
.STYLES
.keys():
171 self
._view
.set_style(self
.STYLES
[value
])
174 class ApplicationPresenter(MVP
.BasicPresenter
):
175 def _initialize(self
):
176 self
._curr
_category
= None
177 self
._curr
_feed
= None
178 self
._curr
_item
= None
180 self
._init
_presenters
()
182 self
._prefs
_dialog
= None
185 def _init_widgets(self
):
186 widget_tree
= self
._view
.get_widget_tree()
187 self
._itemlist
_view
_notebook
= widget_tree
.get_widget('mode_view_notebook')
188 self
._feedlist
_view
_notebook
= widget_tree
.get_widget('left_mode_view_notebook')
190 def _init_presenters(self
):
191 widget_tree
= self
._view
.get_widget_tree()
192 toolbar_presenter
= ToolbarPresenter(view
=ToolbarView(widget_tree
.get_widget('toolbar_default')))
194 self
._itemlist
_presenter
= ItemListPresenter(view
= ItemListView(widget_tree
.get_widget('item_selection_treeview')))
196 view
=FeedsView(widget_tree
.get_widget('feed_selection_treeview'))
197 self
._feed
_list
_presenter
= FeedsPresenter(view
=view
)
198 view
.add_selection_changed_listener(self
._itemlist
_presenter
)
200 # self._category_selector = CategoryPresenter(view=CategoryView(widget_tree.get_widget('category_combo')))
202 self
._error
_presenter
= ErrorPresenter(
203 widget_tree
.get_widget('statusbar_error_indicator'))
204 self
._offline
_presenter
= OfflineToggle(
205 widget_tree
.get_widget('offline_toggle'))
207 self
._item
_view
= ItemView(widget_tree
.get_widget('item_view_container'))
208 self
._status
_presenter
= StatusPresenter(view
= widget_tree
.get_widget("main_statusbar"))
209 self
._menufp
_presenter
= MenuFeedPropsPresenter( view
= widget_tree
.get_widget('menu_feed_properties'))
210 self
._menufp
_presenter
.set_sensitive(False)
211 # self._find_presenter = FindPresenter(view=FindView(widget_tree.get_widget("find_vbox")))
214 def _init_signals(self
):
215 # self._feed_list_presenter.signal_connect(Event.FeedSelectionChangedSignal,
216 # self._feed_selection_changed)
217 # self._feed_list_presenter.signal_connect(Event.FeedsEmptySignal,
218 # self._feeds_empty_cb)
219 self
._itemlist
_presenter
.signal_connect(Event
.ItemSelectionChangedSignal
,
220 self
._item
_view
.item_selection_changed
)
221 # self._category_selector.signal_connect(Event.CategorySelectionChangedSignal,
222 # self._category_selection_changed)
225 def _feed_selection_changed(self
, signal
):
226 if signal
.old
and self
._curr
_feed
:
227 self
._curr
_feed
.unload_contents()
230 self
._curr
_feed
.signal_disconnect(Event
.FeedPolledSignal
,
232 self
._curr
_feed
.signal_disconnect(Event
.ItemsAddedSignal
,
233 self
._feed
_items
_added
)
234 self
._curr
_feed
= signal
.new
235 self
._curr
_feed
.signal_connect(Event
.FeedPolledSignal
,
237 self
._curr
_feed
.signal_connect(Event
.ItemsAddedSignal
,
238 self
._feed
_items
_added
)
239 self
._display
_feed
(self
._curr
_feed
)
242 def _feed_polled(self
, signal
):
243 self
._feedinfo
_presenter
.display(signal
.sender
)
246 def _feed_items_added(self
, signal
):
247 self
._itemlist
_presenter
.display_feed_items(self
._curr
_feed
, False)
249 def _category_selection_changed(self
, signal
):
250 self
._display
_category
_feeds
(signal
.current
)
253 def _display_category_feeds(self
, category
, *args
):
254 self
._curr
_category
= category
256 # self._feed_list_presenter.display_category_feeds(category)
257 self
._error
_presenter
.display_category_error(category
)
259 # self._feed_list_presenter.display_empty_category()
260 self
._menufp
_presenter
.set_sensitive(False)
261 #self._itemlist_presenter.display_empty_feed()
262 self
._item
_view
.display_empty_feed()
265 def _display_feed(self
, feed
, select_first
= 1):
266 if feed
and feed
.number_of_items
< 1:
267 self
._item
_view
.display_empty_feed()
268 self
._error
_presenter
.display_feed_error(feed
)
269 self
._feedinfo
_presenter
.display(feed
)
270 #self._itemlist_presenter.display_feed_items(feed, select_first)
271 self
._menufp
_presenter
.set_sensitive(True)
274 def _feeds_empty_cb(self
, signal
):
275 #self._itemlist_presenter.display_empty_feed()
276 self
._item
_view
.display_empty_feed()
277 self
._feedinfo
_presenter
.hide()
278 self
._error
_presenter
.hide()
279 self
._menufp
_presenter
.set_sensitive(False)
282 def copy_itemview_text_selection(self
):
283 utils
.set_clipboard_text(self
._item
_view
.get_selected_text())
285 def check_allocation(self
, widget
, event
):
286 config
= Config
.get_instance()
287 def check_size((width
, height
, widget
)):
288 if width
== widget
.allocation
.width
and height
== widget
.allocation
.height
:
289 config
.main_window_size
= (width
, height
)
290 if event
.width
!= widget
.allocation
.width
or event
.height
!= widget
.allocation
.height
:
291 gobject
.timeout_add(1000, check_size
, (
292 (event
.width
, event
.height
, widget
)))
294 def check_main_pane_position(self
, widget
):
295 config
= Config
.get_instance()
296 def check_position((position
, widget
)):
297 if position
== widget
.get_position():
298 config
.main_pane_position
= position
299 pos
= widget
.get_position()
300 if pos
!= config
.main_pane_position
:
301 gobject
.timeout_add(1000, check_position
, (pos
, widget
))
303 def check_sub_pane_position(self
, widget
):
304 config
= Config
.get_instance()
305 def check_position((position
, widget
)):
306 if position
== widget
.get_position():
307 config
.sub_pane_position
= position
308 pos
= widget
.get_position()
309 if pos
!= config
.sub_pane_position
:
310 gobject
.timeout_add(1000, check_position
, (pos
, widget
))
313 return dialogs
.credits()
316 if self
._warn
_if
_offline
():
317 fclist
= FeedCategoryList
.get_instance()
318 self
._poll
_categories
(fclist
.all_categories
)
321 def poll_current_category(self
):
322 if self
._warn
_if
_offline
():
323 self
._poll
_categories
([self
._curr
_category
])
326 def poll_current_feed(self
):
327 if self
._warn
_if
_offline
():
328 pm
= PollManager
.get_instance()
329 pm
.poll([self
._curr
_feed
])
332 def mark_feed_as_read(self
):
333 self
._curr
_feed
.mark_all_read()
335 def mark_all_as_read(self
):
336 mmgr
= MainloopManager
.get_instance()
337 flist
= feeds
.get_instance().flatten_list()
341 if feed
is self
._curr
_feed
:
343 feed
.unload_contents()
346 def remove_selected_feed(self
):
347 # self._feed_list_presenter.remove_selected_feed()
350 def show_search(self
):
351 self
._itemlist
_presenter
.signal_disconnect(Event
.ItemSelectionChangedSignal
,
352 self
._item
_view
.item_selection_changed
)
353 # self._find_presenter.item_list.signal_connect(Event.ItemSelectionChangedSignal,
354 # self._item_view.item_selection_changed)
355 self
._item
_view
.display_empty_search()
356 self
._itemlist
_view
_notebook
.set_current_page(1)
357 self
._feedlist
_view
_notebook
.set_current_page(1)
358 self
._feedinfo
_presenter
.hide()
360 def hide_search(self
):
361 # self._find_presenter.clear()
362 self
._itemlist
_view
_notebook
.set_current_page(0)
363 self
._feedlist
_view
_notebook
.set_current_page(0)
364 self
._feedinfo
_presenter
.show()
365 # self._find_presenter.item_list.signal_disconnect(Event.ItemSelectionChangedSignal,
366 # self._item_view.item_selection_changed)
367 self
._itemlist
_presenter
.signal_connect(Event
.ItemSelectionChangedSignal
,
368 self
._item
_view
.item_selection_changed
)
370 def _poll_categories(self
, fclist
):
371 pm
= PollManager
.get_instance()
372 pm
.poll_categories(fclist
)
375 def _warn_if_offline(self
):
376 config
= Config
.get_instance()
379 response
= self
._view
.show_offline_dialog()
380 if response
== gtk
.RESPONSE_OK
:
381 config
.offline
= not config
.offline
387 def _get_next_category(self
, category
= None):
389 category
= self
._curr
_category
390 fclist
= FeedCategoryList
.get_instance()
391 allcats
= fclist
.user_categories
+ list(fclist
.pseudo_categories
)
393 category
= allcats
[0]
395 index
= allcats
.index(category
)
396 if index
< len(allcats
) - 1:
400 category
= allcats
[index
]
403 def _get_previous_category(self
, category
= None):
405 category
= self
._curr
_category
406 fclist
= FeedCategoryList
.get_instance()
407 allcats
= fclist
.user_categories
+ list(fclist
.pseudo_categories
)
409 category
= allcats
[-1]
411 index
= allcats
.index(category
)
415 index
= len(allcats
) - 1
416 category
= allcats
[index
]
419 def display_previous_category(self
, category
= None):
421 Displays the category before the current selected category
423 category
= self
._get
_previous
_category
(category
)
424 # self._category_selector.category_selected(category)
425 self
._display
_category
_feeds
(category
)
427 def display_next_category(self
, category
= None):
429 Display the category after the current selected category
431 category
= self
._get
_next
_category
(category
)
432 # self._category_selector.category_selected(category)
433 self
._display
_category
_feeds
(category
)
435 def display_previous_feed(self
, item
= None):
437 Displays the feed before the current selected feed
439 self
._feed
_list
_presenter
.select_previous_feed()
441 def display_next_feed(self
, item
=None):
443 Displays the feed after the current selected feed
445 # XXX feed_list_presenter usage
446 self
._feed
_list
_presenter
.select_next_feed()
449 def display_next_unread_feed(self
):
451 Displays the next feed with an unread item
453 # self._feed_list_presenter.select_next_unread_feed()
456 def display_previous_item(self
, item
=None):
458 Displays the item before the current selected item. If the item is the
459 first item, scrolls to the previous feed
461 is_prev
= self
._itemlist
_presenter
.select_previous_item()
463 # TODO HACK - implement select_previous_feed(select_last=True) ...
464 # ... to select previous feed's last item
465 # self._feed_list_presenter.select_previous_feed()
466 self
._itemlist
_presenter
.select_last_item()
469 def display_next_item(self
, item
=None):
471 Displays the item after the current selected item. If the item is the
472 last item, selectes the next feed. If the current feed is the last
473 feed in the list, it goes back and selects the first feed
475 is_next
= self
._itemlist
_presenter
.select_next_item()
477 # is_next_feed = self._feed_list_presenter.select_next_feed()
478 # if not is_next_feed:
479 # self._feed_list_presenter.select_first_feed()
482 def scroll_or_display_next_unread_item(self
, item
=None):
483 has_unread_item
= False
484 if not self
._item
_view
.scroll_down():
485 has_unread_item
= self
._itemlist
_presenter
.select_next_unread_item()
486 # if not has_unread_item:
487 # self._feed_list_presenter.select_next_unread_feed()
490 def show_preferences_dialog(self
, parent
):
491 if not self
._prefs
_dialog
:
492 xf
= utils
.find_glade_file()
493 xml
= gtk
.glade
.XML(xf
, "preferences_dialog", gettext
.textdomain())
494 self
._prefs
_dialog
= PreferencesDialog(xml
, parent
)
495 self
._prefs
_dialog
.show()
497 def show_feed_properties(self
, parent
):
498 fpd
= show_feed_properties_dialog(parent
, self
._curr
_feed
)
503 ItemStore
.get_instance().stop()
506 class ApplicationView(MVP
.WidgetView
):
510 def _initialize(self
):
511 self
._config
= Config
.get_instance()
512 self
._initialize
_dnd
()
513 self
._initialize
_window
_updater
()
514 self
._create
_unmodified
_accelerator
_group
()
515 self
._attach
_unmodified
_accelerator
_group
()
516 self
._initialize
_window
()
517 self
._find
_toggled
= False
519 def _initialize_window(self
):
520 widget_tree
= gtk
.glade
.get_widget_tree(self
._widget
)
521 if self
._config
.window_maximized
:
522 self
._widget
.maximize()
524 # we use resize here since configure-event seems to
525 # overwrite the default size if we use set_default_size.
526 self
._widget
.resize(*self
._config
.main_window_size
)
527 mmp
= widget_tree
.get_widget('main_main_pane')
528 msp
= widget_tree
.get_widget('main_sub_pane')
529 mmp
.set_position(self
._config
.main_pane_position
)
530 msp
.set_position(self
._config
.sub_pane_position
)
532 def _initialize_dnd(self
):
533 self
._widget
.drag_dest_set(
534 gtk
.DEST_DEFAULT_ALL
,
535 [('_NETSCAPE_URL', 0, 0), ('text/uri-list ', 0, 1),
536 ('x-url/http', 0, 2)],
537 gtk
.gdk
.ACTION_COPY | gtk
.gdk
.ACTION_MOVE
)
540 def _initialize_window_updater(self
):
541 feedlist
= feeds
.get_instance()
542 #feedlist.signal_connect(Event.AllItemsReadSignal,
543 # lambda signal: self._update_title(feedlist))
544 #feedlist.signal_connect(Event.ItemReadSignal,
545 # lambda signal: self._update_title(feedlist))
546 #feedlist.signal_connect(Event.ItemsAddedSignal,
547 # lambda signal: self._update_title(feedlist))
548 #feedlist.signal_connect(Event.FeedsChangedSignal,
549 # lambda signal: self._update_title(feedlist))
552 def _update_title(self
, flist
):
553 uritems
= urfeeds
= 0
555 listfeeds
= flist
.flatten_list()
556 for ur
in [f
.n_items_unread
for f
in listfeeds
]:
561 urfeeds
= len(listfeeds
)
564 item_feed_map
= {'uritems': uritems
,
567 title
= _('%(uritems)d unread in %(urfeeds)d %(fstring)s') % item_feed_map
568 self
._widget
.set_title( title
+ " - %s" % constants
.APPNAME
)
571 # We have a separate accelerator group for the unmodified and
572 # shifted accelerators, that is, stuff like space, N, P, etc. This
573 # is so that we can have the find pane work correctly
574 def _create_unmodified_accelerator_group(self
):
575 xml
= gtk
.glade
.get_widget_tree(self
._widget
)
576 agroup
= gtk
.AccelGroup()
577 accels
= (('menu_mark_feed_as_read', 'R', gtk
.gdk
.SHIFT_MASK
),
578 ('menu_mark_all_as_read', 'A', gtk
.gdk
.SHIFT_MASK
),
579 ('menu_next', 'N', gtk
.gdk
.SHIFT_MASK
),
580 ('menu_next_unread', ' ', 0),
581 ('menu_previous', 'P', gtk
.gdk
.SHIFT_MASK
))
582 for widget_name
, key
, mask
in accels
:
583 widget
= xml
.get_widget(widget_name
)
584 widget
.add_accelerator("activate", agroup
, ord(key
), mask
,
586 self
._unmodified
_accelerator
_group
= agroup
588 def _attach_unmodified_accelerator_group(self
):
589 self
._widget
.add_accel_group(self
._unmodified
_accelerator
_group
)
591 def _detach_unmodified_accelerator_group(self
):
592 self
._widget
.remove_accel_group(self
._unmodified
_accelerator
_group
)
594 def _on_straw_main_destroy_event(self
, *args
):
595 return self
._presenter
.quit()
597 def _on_straw_main_delete_event(self
, *args
):
598 return self
._presenter
.quit()
600 def _on_menu_quit_activate(self
, *args
):
601 return self
._presenter
.quit()
603 def _on_straw_main_configure_event(self
, widget
, event
, *args
):
604 if widget
.window
.get_state() is not gtk
.gdk
.WINDOW_STATE_MAXIMIZED
:
605 self
._config
.window_maximized
= False
606 self
._presenter
.check_allocation(widget
, event
)
608 self
._config
.window_maximized
= True
611 def _on_main_main_pane_size_allocate(self
, widget
, *args
):
612 self
._presenter
.check_main_pane_position(widget
)
614 def _on_main_sub_pane_size_allocate(self
, widget
, *args
):
615 self
._presenter
.check_sub_pane_position(widget
)
617 def _on_menu_report_problem_activate(self
, menuitem
, *args
):
618 utils
.url_show("http://bugzilla.gnome.org/simple-bug-guide.cgi?product=straw")
620 def _on_menu_about_activate(self
, menuitem
, *args
):
621 widget
= self
._presenter
.credits()
624 def _on_menu_refresh_all_activate(self
, *args
):
625 self
._presenter
.poll_all()
627 def _on_menu_refresh_category_activate(self
, *args
):
628 self
._presenter
.poll_current_category()
630 def _on_menu_refresh_selected_activate(self
, *args
):
631 self
._presenter
.poll_current_feed()
633 def _on_toolbar_refresh_all_button_clicked(self
, *args
):
634 self
._presenter
.poll_all()
636 def _on_menu_add_activate(self
, *args
):
637 subscribe
.display_window(parent
=self
._widget
)
639 def _on_toolbar_subscribe_button_clicked(self
, *args
):
640 subscribe
.display_window(parent
=self
._widget
)
642 def _on_menu_import_subscriptions_activate(self
, *args
):
643 dialogs
.import_subscriptions(self
._widget
)
645 def _on_menu_export_subscriptions_activate(self
, *args
):
646 dialogs
.export_subscriptions(self
._widget
)
648 def _on_menu_copy_text_activate(self
, *args
):
649 self
._presenter
.copy_itemview_text_selection()
651 def _on_menu_mark_feed_as_read_activate(self
, *args
):
652 self
._presenter
.mark_feed_as_read()
654 def _on_menu_mark_all_as_read_activate(self
, *args
):
655 self
._presenter
.mark_all_as_read()
657 def _on_find_activate(self
, widget
, *args
):
658 xml
= gtk
.glade
.get_widget_tree(self
._widget
)
659 menu_find
= xml
.get_widget('menu_find')
660 accel_label
= menu_find
.get_child()
662 if not self
._find
_toggled
:
663 self
._presenter
.show_search()
664 self
._detach
_unmodified
_accelerator
_group
()
665 self
._find
_toggled
= True
667 # save the "Find..." stock text for later recovery
668 self
._old
_label
_text
= accel_label
.get_text()
669 accel_label
.set_text(_('Return to feed list...'))
672 self
._presenter
.hide_search()
673 self
._attach
_unmodified
_accelerator
_group
()
674 self
._find
_toggled
= False
675 accel_label
.set_text(self
._old
_label
_text
)
677 def _on_menu_next_activate(self
, *args
):
678 self
._presenter
.display_next_item()
680 def _on_toolbar_scroll_or_next_button_clicked(self
, *args
):
681 self
._presenter
.scroll_or_display_next_unread_item()
683 def _on_menu_scroll_next_activate(self
, *args
):
684 self
._presenter
.scroll_or_display_next_unread_item()
686 def _on_menu_previous_activate(self
, *args
):
687 self
._presenter
.display_previous_item()
689 def _on_menu_next_feed_unread_activate(self
, *args
):
690 self
._presenter
.display_next_unread_feed()
692 def _on_menu_next_feed_activate(self
, *args
):
693 self
._presenter
.display_next_feed()
695 def _on_menu_previous_feed_activate(self
, *args
):
696 self
._presenter
.display_previous_feed()
698 def _on_menu_remove_selected_feed_activate(self
, *args
):
699 self
._presenter
.remove_selected_feed()
701 def _on_menu_next_category_activate(self
, *args
):
702 self
._presenter
.display_next_category()
704 def _on_menu_previous_category_activate(self
, *args
):
705 self
._presenter
.display_previous_category()
707 def _on_menu_next_category_activate(self
, *args
):
708 self
._presenter
.display_next_category()
710 def _on_menu_previous_category_activate(self
, *args
):
711 self
._presenter
.display_previous_category()
713 def _on_menu_preferences_activate(self
, *args
):
714 self
._presenter
.show_preferences_dialog(self
._widget
)
716 def _on_menu_feed_properties_activate(self
, *args
):
717 self
._presenter
.show_feed_properties(self
._widget
)
719 def _on_straw_main_drag_data_received(self
, w
, context
,
720 x
, y
, data
, info
, time
):
721 if data
and data
.format
== 8:
722 url
= data
.data
.split("\n")[0]
723 subscribe
.display_window("%s" % url
, self
._widget
)
724 context
.finish(True, False, time
)
726 context
.finish(False, False, time
)
728 def show_offline_dialog(self
):
729 return dialogs
.report_offline_status(self
._widget
)
731 def get_widget_tree(self
):
732 return gtk
.glade
.get_widget_tree(self
._widget
)
735 self
._widget
.present()
737 def should_present(self
):
738 if self
._widget
.window
.get_state() is not gtk
.gdk
.WINDOW_STATE_WITHDRAWN
:
741 self
._widget
.present()
751 gnome
.program_init(constants
.APPNAME
.lower(), constants
.VERSION
)
752 # initialize threading and environment
753 gobject
.threads_init()
754 config
= Config
.get_instance()
755 config
.reload_css
= os
.getenv('STRAW_RELOAD_CSS') is not None
757 gtk
.window_set_auto_startup_notification(True)
758 self
._initialize
_gettext
()
760 config
= Config
.get_instance()
762 feedlist
= feeds
.get_instance()
763 feed_categories
= FeedCategoryList
.get_instance()
766 #xmlfile = utils.find_glade_file()
767 #xml = gtk.glade.XML(xmlfile, "straw_main", gettext.textdomain())
768 #window = xml.get_widget('straw_main')
769 #self._main_presenter = ApplicationPresenter(view =
770 # ApplicationView(window))
772 if config
.first_time
:
773 libdir
= utils
.find_data_dir()
774 filepath
= os
.path
.join(libdir
, "default_subscriptions.opml")
775 OPMLImport
.import_opml(filepath
)
778 feed_categories
.load_data()
781 itemstore
= ItemStore
.get_instance()
782 except ItemStore
.ConvertException
, ex
:
783 dialogs
.report_error(_("There was a problem while converting the database."),
784 _("Straw will not behave as expected. You should probably quit now. " +
785 "The exception has been saved to the file '%s'. Please see the Straw README for further instructions."
789 ImageCache
.initialize()
793 xmlfile
= utils
.find_glade_file()
794 xml
= gtk
.glade
.XML(xmlfile
, "straw_main", gettext
.textdomain())
795 window
= xml
.get_widget('straw_main')
796 self
._main
_presenter
= ApplicationPresenter(view
=
797 ApplicationView(window
))
798 self
._main
_presenter
.view
.present()
800 PollManager
.get_instance().start_polling_loop()
801 # set the default icon for the windows
802 iconfile
= os
.path
.join(utils
.find_image_dir(),"straw.png")
803 gtk
.window_set_default_icon(gtk
.gdk
.pixbuf_new_from_file(iconfile
))
805 strawdbus
.start_services()
811 def _initialize_gettext(self
):
813 lname
= constants
.APPNAME
.lower()
815 localedir
= utils
.find_locale_dir()
816 gettext
.bindtextdomain(lname
, localedir
)
817 gettext
.textdomain(lname
)
818 gettext
.install(lname
, localedir
, unicode=1)
819 gtk
.glade
.bindtextdomain(lname
, localedir
)
821 def broken_gettext_workaround(s
):
823 __builtins__
.__dict
__['_'] = broken_gettext_workaround
824 locale
.setlocale(locale
.LC_ALL
, '')
828 from Tray
import Tray
830 tray
.connect('button_press_event', self
._tray
_clicked
)
832 def _tray_clicked(self
, signal
, event
):
833 if event
.button
== 1:
834 self
._main
_presenter
.view
.present()
835 self
._main
_presenter
.scroll_or_display_next_unread_item()
837 self
._main
_presenter
.view
.should_present()