""" Application.py
This is the main module that binds everything together.
"""
__copyright__ = "Copyright (c) 2002-2005 Free Software Foundation, Inc."
__license__ = """ GNU General Public License
This program is free software; you can redistribute it and/or modify it under the
terms of the GNU General Public License as published by the Free Software
Foundation; either version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place - Suite 330, Boston, MA 02111-1307, USA. """
import time
from xml.sax import saxutils
import pygtk
pygtk.require('2.0')
import gobject
import gtk
import gtk.glade
import gnome
import gconf
import utils
import subscribe
import Event
import MessageManager
import FeedList
import FeedCategoryList
import Config
import error
from ItemView import ItemView
from ItemList import ItemListPresenter, ItemListView
from FeedListView import FeedsView, FeedsPresenter
from OfflineToggle import OfflineToggle
from CategorySelector import CategoryPresenter, CategoryView
from MainloopManager import MainloopManager
from FeedPropertiesDialog import FeedPropertiesDialog
from PreferencesDialog import PreferencesDialog
from Find import FindPresenter, FindView
import OPMLImport
import MVP
import ItemStore
import ImageCache
import PollManager
import dialogs
import constants
class StatusPresenter(MVP.BasicPresenter):
def _initialize(self):
self._mmgr = MessageManager.get_instance()
self._mmgr.signal_connect(Event.StatusDisplaySignal,
self._display)
return
def _display(self, signal):
cid = self._view.get_context_id("straw_main")
self._view.pop(cid)
self._view.push(cid, self._mmgr.read_message())
return
class ErrorPresenter:
def __init__(self, widget):
self._widget = widget
self._tooltips = gtk.Tooltips()
self._text = ''
self._curr_feed = None
self._curr_category = None
fclist = FeedCategoryList.get_instance()
fclist.signal_connect(Event.FeedCategoryChangedSignal,
self._category_changed)
def display_feed_error(self, feed):
if self._curr_feed is not None:
self._curr_feed.signal_disconnect(Event.FeedErrorStatusChangedSignal,
self._error_status_changed)
self._curr_feed = feed
self._curr_feed.signal_connect(Event.FeedErrorStatusChangedSignal,
self._error_status_changed)
self._update_view()
return
def display_category_error(self, category):
if category:
self._curr_category = category
self._update_view()
return
def _update_view(self):
text = list()
if self._curr_category and self._curr_category.subscription and self._curr_category.subscription.error:
text.append(_("Category error:"))
text.append(self._curr_category.subscription.error)
if self._curr_feed and self._curr_feed.error:
text.append(_("Feed Error:"))
text.append(self._curr_feed.error)
if text:
t = "\n".join(text)
self._tooltips.set_tip(self._widget,t,t)
self._tooltips.enable()
self._widget.show()
else:
self._tooltips.disable()
self._widget.hide()
return
def _category_changed(self, signal):
if signal.sender is self._curr_category:
self.display_category_error(self._curr_category)
def _error_status_changed(self, signal):
if signal.sender is self._curr_feed:
self.display_feed_error(signal.sender)
return
def hide(self):
self._widget.hide()
class FeedInfoView(MVP.WidgetView):
def _initialize(self):
widget_tree = gtk.glade.get_widget_tree(self._widget)
self._title = widget_tree.get_widget('feed_item_label')
self._refresh = widget_tree.get_widget('feed_refresh_label')
def set_title(self, title):
self._title.set_label(title)
return
def set_refresh(self, refresh):
self._refresh.set_label(refresh)
self._refresh.show()
return
def hide(self):
self._widget.hide()
return
def show(self):
self._widget.show()
return
class FeedInfoPresenter(MVP.BasicPresenter):
def display(self, feed):
next = feed.next_refresh
if feed:
text = _("Next Refresh: %s") % utils.format_date(time.gmtime(next))
self._view.set_refresh(text)
self._view.set_title(_("%s") % saxutils.escape(feed.title))
self._view.show()
else:
self._view.hide()
return
def hide(self):
self._view.set_title("")
self._view.set_refresh("")
def show(self): self._view.show()
class MenuFeedPropsPresenter(MVP.BasicPresenter):
def set_sensitive(self, s):
self._view.set_sensitive(s)
return
class ToolbarView(MVP.WidgetView):
""" Widget: gtk.Toolbar"""
GCONF_DESKTOP_INTERFACE = "/desktop/gnome/interface"
def _initialize(self):
client = gconf.client_get_default()
if not client.dir_exists(self.GCONF_DESKTOP_INTERFACE):
return
client.add_dir(self.GCONF_DESKTOP_INTERFACE,
gconf.CLIENT_PRELOAD_NONE)
client.notify_add(self.GCONF_DESKTOP_INTERFACE+"/toolbar_style",
self._toolbar_style_changed)
self._widget.set_tooltips(True)
def _toolbar_style_changed(self, client, notify_id, entry, *args):
value = entry.value.get_string()
self._presenter.style_changed(value)
def set_style(self, style):
self._widget.set_style(style)
def get_style(self):
client = gconf.client_get_default()
current_style = client.get_string(self.GCONF_DESKTOP_INTERFACE+"/toolbar_style")
return current_style
class ToolbarPresenter(MVP.BasicPresenter):
STYLES = {'both':gtk.TOOLBAR_BOTH,
'text':gtk.TOOLBAR_TEXT,
'icons':gtk.TOOLBAR_ICONS,
'both-horiz':gtk.TOOLBAR_BOTH_HORIZ}
def _initialize(self):
style = self._view.get_style()
if style in self.STYLES.keys():
self._view.set_style(self.STYLES[style])
return
def style_changed(self, value):
if value in self.STYLES.keys():
self._view.set_style(self.STYLES[value])
return
class ApplicationPresenter(MVP.BasicPresenter):
def _initialize(self):
self._curr_category = None
self._curr_feed = None
self._curr_item = None
self._init_widgets()
self._init_presenters()
self._init_signals()
self._prefs_dialog = None
self._view.present()
def _init_widgets(self):
widget_tree = self._view.get_widget_tree()
self._itemlist_view_notebook = widget_tree.get_widget('mode_view_notebook')
self._feedlist_view_notebook = widget_tree.get_widget('left_mode_view_notebook')
def _init_presenters(self):
widget_tree = self._view.get_widget_tree()
toolbar_presenter = ToolbarPresenter(view=ToolbarView(widget_tree.get_widget('toolbar_default')))
self._feed_list_presenter = FeedsPresenter(view=FeedsView(widget_tree.get_widget('feed_selection_treeview')))
self._category_selector = CategoryPresenter(view=CategoryView(widget_tree.get_widget('category_combo')))
self._error_presenter = ErrorPresenter(
widget_tree.get_widget('statusbar_error_indicator'))
self._offline_presenter = OfflineToggle(
widget_tree.get_widget('offline_toggle'))
self._itemlist_presenter = ItemListPresenter(view = ItemListView(widget_tree.get_widget('item_selection_treeview')))
self._item_view = ItemView(widget_tree.get_widget('item_view_container'))
self._status_presenter = StatusPresenter(view = widget_tree.get_widget("main_statusbar"))
self._menufp_presenter = MenuFeedPropsPresenter( view = widget_tree.get_widget('menu_feed_properties'))
self._menufp_presenter.set_sensitive(False)
self._feedinfo_presenter = FeedInfoPresenter(view = FeedInfoView(widget_tree.get_widget('article_refresh_hbox')))
self._find_presenter = FindPresenter(view=FindView(widget_tree.get_widget("find_vbox")))
return
def _init_signals(self):
self._feed_list_presenter.signal_connect(Event.FeedSelectionChangedSignal,
self._feed_selection_changed)
self._feed_list_presenter.signal_connect(Event.FeedsEmptySignal,
self._feeds_empty_cb)
self._itemlist_presenter.signal_connect(Event.ItemSelectionChangedSignal,
self._item_view.item_selection_changed)
self._category_selector.signal_connect(Event.CategorySelectionChangedSignal,
self._category_selection_changed)
return
def _feed_selection_changed(self, signal):
if signal.old and self._curr_feed:
self._curr_feed.unload_contents()
if signal.new:
if self._curr_feed:
self._curr_feed.signal_disconnect(Event.FeedPolledSignal,
self._feed_polled)
self._curr_feed.signal_disconnect(Event.ItemsAddedSignal,
self._feed_items_added)
self._curr_feed = signal.new
self._curr_feed.signal_connect(Event.FeedPolledSignal,
self._feed_polled)
self._curr_feed.signal_connect(Event.ItemsAddedSignal,
self._feed_items_added)
self._display_feed(self._curr_feed)
return
def _feed_polled(self, signal):
self._feedinfo_presenter.display(signal.sender)
return
def _feed_items_added(self, signal):
self._itemlist_presenter.display_feed_items(self._curr_feed, False)
def _category_selection_changed(self, signal):
self._display_category_feeds(signal.current)
return
def _display_category_feeds(self, category, *args):
self._curr_category = category
if category:
self._feed_list_presenter.display_category_feeds(category)
self._error_presenter.display_category_error(category)
else:
self._feed_list_presenter.display_empty_category()
self._menufp_presenter.set_sensitive(False)
self._itemlist_presenter.display_empty_feed()
self._item_view.display_empty_feed()
return
def _display_feed(self, feed, select_first = 1):
if feed and feed.number_of_items < 1:
self._item_view.display_empty_feed()
self._error_presenter.display_feed_error(feed)
self._feedinfo_presenter.display(feed)
self._itemlist_presenter.display_feed_items(feed, select_first)
self._menufp_presenter.set_sensitive(True)
return
def _feeds_empty_cb(self, signal):
self._itemlist_presenter.display_empty_feed()
self._item_view.display_empty_feed()
self._feedinfo_presenter.hide()
self._error_presenter.hide()
self._menufp_presenter.set_sensitive(False)
return
def copy_itemview_text_selection(self):
utils.set_clipboard_text(self._item_view.get_selected_text())
def check_allocation(self, widget, event):
config = Config.get_instance()
def check_size((width, height, widget)):
if width == widget.allocation.width and height == widget.allocation.height:
config.main_window_size = (width, height)
if event.width != widget.allocation.width or event.height != widget.allocation.height:
gobject.timeout_add(1000, check_size, (
(event.width, event.height, widget)))
def check_main_pane_position(self, widget):
config = Config.get_instance()
def check_position((position, widget)):
if position == widget.get_position():
config.main_pane_position = position
pos = widget.get_position()
if pos != config.main_pane_position:
gobject.timeout_add(1000, check_position, (pos, widget))
def check_sub_pane_position(self, widget):
config = Config.get_instance()
def check_position((position, widget)):
if position == widget.get_position():
config.sub_pane_position = position
pos = widget.get_position()
if pos != config.sub_pane_position:
gobject.timeout_add(1000, check_position, (pos, widget))
def credits(self):
return dialogs.credits()
def poll_all(self):
if self._warn_if_offline():
fclist = FeedCategoryList.get_instance()
self._poll_categories(fclist.all_categories)
return
def poll_current_category(self):
if self._warn_if_offline():
self._poll_categories([self._curr_category])
return
def poll_current_feed(self):
if self._warn_if_offline():
pm = PollManager.get_instance()
pm.poll([self._curr_feed])
return
def mark_feed_as_read(self):
self._curr_feed.mark_all_read()
def mark_all_as_read(self):
mmgr = MainloopManager.get_instance()
flist = FeedList.get_instance().flatten_list()
mmgr.call_pending()
for feed in flist:
feed.mark_all_read()
if feed is self._curr_feed:
continue
feed.unload_contents()
mmgr.call_pending()
def remove_selected_feed(self):
self._feed_list_presenter.remove_selected_feed()
def show_search(self):
self._itemlist_presenter.signal_disconnect(Event.ItemSelectionChangedSignal,
self._item_view.item_selection_changed)
self._find_presenter.item_list.signal_connect(Event.ItemSelectionChangedSignal,
self._item_view.item_selection_changed)
self._item_view.display_empty_search()
self._itemlist_view_notebook.set_current_page(1)
self._feedlist_view_notebook.set_current_page(1)
self._feedinfo_presenter.hide()
def hide_search(self):
self._find_presenter.clear()
self._itemlist_view_notebook.set_current_page(0)
self._feedlist_view_notebook.set_current_page(0)
self._feedinfo_presenter.show()
self._find_presenter.item_list.signal_disconnect(Event.ItemSelectionChangedSignal,
self._item_view.item_selection_changed)
self._itemlist_presenter.signal_connect(Event.ItemSelectionChangedSignal,
self._item_view.item_selection_changed)
def _poll_categories(self, fclist):
pm = PollManager.get_instance()
pm.poll_categories(fclist)
return
def _warn_if_offline(self):
config = Config.get_instance()
will_poll = False
if config.offline:
response = self._view.show_offline_dialog()
if response == gtk.RESPONSE_OK:
config.offline = not config.offline
will_poll = True
else:
will_poll = True
return will_poll
def _get_next_category(self, category = None):
if not category:
category = self._curr_category
fclist = FeedCategoryList.get_instance()
allcats = fclist.user_categories + list(fclist.pseudo_categories)
if category is None:
category = allcats[0]
else:
index = allcats.index(category)
if index < len(allcats) - 1:
index += 1
else:
index = 0
category = allcats[index]
return category
def _get_previous_category(self, category = None):
if category is None:
category = self._curr_category
fclist = FeedCategoryList.get_instance()
allcats = fclist.user_categories + list(fclist.pseudo_categories)
if category is None:
category = allcats[-1]
else:
index = allcats.index(category)
if index > 0:
index -= 1
else:
index = len(allcats) - 1
category = allcats[index]
return category
def display_previous_category(self, category = None):
"""
Displays the category before the current selected category
"""
category = self._get_previous_category(category)
self._category_selector.category_selected(category)
self._display_category_feeds(category)
def display_next_category(self, category = None):
"""
Display the category after the current selected category
"""
category = self._get_next_category(category)
self._category_selector.category_selected(category)
self._display_category_feeds(category)
def display_previous_feed(self, item = None):
"""
Displays the feed before the current selected feed
"""
self._feed_list_presenter.select_previous_feed()
def display_next_feed(self, item=None):
"""
Displays the feed after the current selected feed
"""
is_next = self._feed_list_presenter.select_next_feed()
if not is_next:
self._feed_list_presenter.select_first_feed()
return
def display_next_unread_feed(self):
"""
Displays the next feed with an unread item
"""
self._feed_list_presenter.select_next_unread_feed()
def display_previous_item(self, item=None):
"""
Displays the item before the current selected item. If the item is the
first item, scrolls to the previous feed
"""
is_prev = self._itemlist_presenter.select_previous_item()
if not is_prev:
# TODO HACK - implement select_previous_feed(select_last=True) ...
# ... to select previous feed's last item
self._feed_list_presenter.select_previous_feed()
self._itemlist_presenter.select_last_item()
return
def display_next_item(self, item=None):
"""
Displays the item after the current selected item. If the item is the
last item, selectes the next feed. If the current feed is the last
feed in the list, it goes back and selects the first feed
"""
is_next = self._itemlist_presenter.select_next_item()
if not is_next:
is_next_feed = self._feed_list_presenter.select_next_feed()
if not is_next_feed:
self._feed_list_presenter.select_first_feed()
return
def scroll_or_display_next_unread_item(self, item=None):
has_unread_item = False
if not self._item_view.scroll_down():
has_unread_item = self._itemlist_presenter.select_next_unread_item()
if not has_unread_item:
self._feed_list_presenter.select_next_unread_feed()
return
def show_preferences_dialog(self, parent):
if not self._prefs_dialog:
xf = utils.find_glade_file()
xml = gtk.glade.XML(xf, "preferences_dialog", gettext.textdomain())
self._prefs_dialog = PreferencesDialog(xml, parent)
self._prefs_dialog.show()
def show_feed_properties(self, parent):
fpd = FeedPropertiesDialog.show_feed_properties(parent, self._curr_feed)
return
def quit(self):
gtk.main_quit()
ItemStore.get_instance().stop()
return
class ApplicationView(MVP.WidgetView):
"""
Widget: straw_main
"""
def _initialize(self):
self._config = Config.get_instance()
self._initialize_dnd()
self._initialize_window_updater()
self._create_unmodified_accelerator_group()
self._attach_unmodified_accelerator_group()
self._initialize_window()
self._find_toggled = False
def _initialize_window(self):
widget_tree = gtk.glade.get_widget_tree(self._widget)
if self._config.window_maximized:
self._widget.maximize()
else:
# we use resize here since configure-event seems to
# overwrite the default size if we use set_default_size.
self._widget.resize(*self._config.main_window_size)
mmp = widget_tree.get_widget('main_main_pane')
msp = widget_tree.get_widget('main_sub_pane')
mmp.set_position(self._config.main_pane_position)
msp.set_position(self._config.sub_pane_position)
def _initialize_dnd(self):
self._widget.drag_dest_set(
gtk.DEST_DEFAULT_ALL,
[('_NETSCAPE_URL', 0, 0), ('text/uri-list ', 0, 1),
('x-url/http', 0, 2)],
gtk.gdk.ACTION_COPY | gtk.gdk.ACTION_MOVE)
return
def _initialize_window_updater(self):
feedlist = FeedList.get_instance()
feedlist.signal_connect(Event.AllItemsReadSignal,
lambda signal: self._update_title(feedlist))
feedlist.signal_connect(Event.ItemReadSignal,
lambda signal: self._update_title(feedlist))
feedlist.signal_connect(Event.ItemsAddedSignal,
lambda signal: self._update_title(feedlist))
feedlist.signal_connect(Event.FeedsChangedSignal,
lambda signal: self._update_title(feedlist))
return
def _update_title(self, flist):
uritems = urfeeds = 0
sfeeds = "feeds"
listfeeds = flist.flatten_list()
for ur in [f.n_items_unread for f in listfeeds]:
if ur:
uritems += ur
urfeeds += 1
else:
urfeeds = len(listfeeds)
if urfeeds < 2:
sfeeds = "feed"
item_feed_map = {'uritems': uritems,
'urfeeds': urfeeds,
'fstring' : sfeeds}
title = _('%(uritems)d unread in %(urfeeds)d %(fstring)s') % item_feed_map
self._widget.set_title( title + " - %s" % constants.APPNAME)
return
# We have a separate accelerator group for the unmodified and
# shifted accelerators, that is, stuff like space, N, P, etc. This
# is so that we can have the find pane work correctly
def _create_unmodified_accelerator_group(self):
xml = gtk.glade.get_widget_tree(self._widget)
agroup = gtk.AccelGroup()
accels = (('menu_mark_feed_as_read', 'R', gtk.gdk.SHIFT_MASK),
('menu_mark_all_as_read', 'A', gtk.gdk.SHIFT_MASK),
('menu_next', 'N', gtk.gdk.SHIFT_MASK),
('menu_next_unread', ' ', 0),
('menu_previous', 'P', gtk.gdk.SHIFT_MASK))
for widget_name, key, mask in accels:
widget = xml.get_widget(widget_name)
widget.add_accelerator("activate", agroup, ord(key), mask,
gtk.ACCEL_VISIBLE)
self._unmodified_accelerator_group = agroup
def _attach_unmodified_accelerator_group(self):
self._widget.add_accel_group(self._unmodified_accelerator_group)
def _detach_unmodified_accelerator_group(self):
self._widget.remove_accel_group(self._unmodified_accelerator_group)
def _on_straw_main_destroy_event(self, *args):
return self._presenter.quit()
def _on_straw_main_delete_event(self, *args):
return self._presenter.quit()
def _on_menu_quit_activate(self, *args):
return self._presenter.quit()
def _on_straw_main_configure_event(self, widget, event, *args):
if widget.window.get_state() is not gtk.gdk.WINDOW_STATE_MAXIMIZED:
self._config.window_maximized = False
self._presenter.check_allocation(widget, event)
else:
self._config.window_maximized = True
return
def _on_main_main_pane_size_allocate(self, widget, *args):
self._presenter.check_main_pane_position(widget)
def _on_main_sub_pane_size_allocate(self, widget, *args):
self._presenter.check_sub_pane_position(widget)
def _on_menu_report_problem_activate(self, menuitem, *args):
utils.url_show("http://bugzilla.gnome.org/simple-bug-guide.cgi?product=straw")
def _on_menu_about_activate(self, menuitem, *args):
widget = self._presenter.credits()
widget.show()
def _on_menu_refresh_all_activate(self, *args):
self._presenter.poll_all()
def _on_menu_refresh_category_activate(self, *args):
self._presenter.poll_current_category()
def _on_menu_refresh_selected_activate(self, *args):
self._presenter.poll_current_feed()
def _on_toolbar_refresh_all_button_clicked(self, *args):
self._presenter.poll_all()
def _on_menu_add_activate(self, *args):
subscribe.show(self._widget)
def _on_toolbar_subscribe_button_clicked(self, *args):
subscribe.show(self._widget)
def _on_menu_import_subscriptions_activate(self, *args):
dialogs.import_subscriptions(self._widget)
def _on_menu_export_subscriptions_activate(self, *args):
dialogs.export_subscriptions(self._widget)
def _on_menu_copy_text_activate(self, *args):
self._presenter.copy_itemview_text_selection()
def _on_menu_mark_feed_as_read_activate(self, *args):
self._presenter.mark_feed_as_read()
def _on_menu_mark_all_as_read_activate(self, *args):
self._presenter.mark_all_as_read()
def _on_find_activate(self, widget, *args):
xml = gtk.glade.get_widget_tree(self._widget)
menu_find = xml.get_widget('menu_find')
accel_label = menu_find.get_child()
if not self._find_toggled:
self._presenter.show_search()
self._detach_unmodified_accelerator_group()
self._find_toggled = True
# save the "Find..." stock text for later recovery
self._old_label_text = accel_label.get_text()
accel_label.set_text(_('Return to feed list...'))
else:
self._presenter.hide_search()
self._attach_unmodified_accelerator_group()
self._find_toggled = False
accel_label.set_text(self._old_label_text)
def _on_menu_next_activate(self, *args):
self._presenter.display_next_item()
def _on_toolbar_scroll_or_next_button_clicked(self, *args):
self._presenter.scroll_or_display_next_unread_item()
def _on_menu_scroll_next_activate(self, *args):
self._presenter.scroll_or_display_next_unread_item()
def _on_menu_previous_activate(self, *args):
self._presenter.display_previous_item()
def _on_menu_next_feed_unread_activate(self, *args):
self._presenter.display_next_unread_feed()
def _on_menu_next_feed_activate(self, *args):
self._presenter.display_next_feed()
def _on_menu_previous_feed_activate(self, *args):
self._presenter.display_previous_feed()
def _on_menu_remove_selected_feed_activate(self, *args):
self._presenter.remove_selected_feed()
def _on_menu_next_category_activate(self, *args):
self._presenter.display_next_category()
def _on_menu_previous_category_activate(self, *args):
self._presenter.display_previous_category()
def _on_menu_next_category_activate(self, *args):
self._presenter.display_next_category()
def _on_menu_previous_category_activate(self, *args):
self._presenter.display_previous_category()
def _on_menu_preferences_activate(self, *args):
self._presenter.show_preferences_dialog(self._widget)
def _on_menu_feed_properties_activate(self, *args):
self._presenter.show_feed_properties(self._widget)
def _on_straw_main_drag_data_received(self, w, context,
x, y, data, info, time):
if data and data.format == 8:
url = data.data.split("\n")[0]
subscribe.show(self._widget, "%s" % url)
context.finish(True, False, time)
else:
context.finish(False, False, time)
def show_offline_dialog(self):
return dialogs.report_offline_status(self._widget)
def get_widget_tree(self):
return gtk.glade.get_widget_tree(self._widget)
def present(self):
self._widget.present()
def should_present(self):
if self._widget.window.get_state() is not gtk.gdk.WINDOW_STATE_WITHDRAWN:
self._widget.hide()
else:
self._widget.present()
import os
import gettext
import getopt
import sys
import strawdbus
class Application:
def __init__(self):
gnome.program_init(constants.APPNAME.lower(), constants.VERSION)
self._initialize_config_from_environment()
gtk.window_set_auto_startup_notification(True)
self._initialize_gettext()
config = Config.get_instance()
config.proxy_config.lookup_host()
feedlist = FeedList.get_instance()
feed_categories = FeedCategoryList.get_instance()
# initialise GUI
xmlfile = utils.find_glade_file()
xml = gtk.glade.XML(xmlfile, "straw_main", gettext.textdomain())
window = xml.get_widget('straw_main')
self._main_presenter = ApplicationPresenter(view =
ApplicationView(window))
if config.first_time:
libdir = utils.find_data_dir()
filepath = os.path.join(libdir, "default_subscriptions.opml")
OPMLImport.import_opml(filepath)
else:
feedlist.load_data()
feed_categories.load_data()
try:
itemstore = ItemStore.get_instance(config.straw_dir)
except ItemStore.ConvertException, ex:
dialogs.report_error(_("There was a problem while converting the database."),
_("Straw will not behave as expected. You should probably quit now. " +
"The exception has been saved to the file '%s'. Please see the Straw README for further instructions."
) % ex.reason)
sys.exit()
ImageCache.initialize()
itemstore.start()
self._main_presenter.view.present()
PollManager.get_instance().start_polling_loop()
# set the default icon for the windows
iconfile = os.path.join(utils.find_image_dir(),"straw.png")
gtk.window_set_default_icon(gtk.gdk.pixbuf_new_from_file(iconfile))
strawdbus.start_services()
def mainloop(self):
threads = Config.get_instance().use_threads
if threads: gtk.threads_enter()
gtk.main()
if threads: gtk.threads_leave()
return
def _initialize_config_from_environment(self):
threads = os.getenv('STRAW_THREAD_DNS') is not None
if threads:
try:
gtk.threads_init()
except:
threads = False
else:
threads = True
config = Config.get_instance()
config.use_threads = threads
config.reload_css = os.getenv('STRAW_RELOAD_CSS') is not None
config.no_etags = os.getenv('STRAW_NO_ETAGS') is not None
return
def _initialize_gettext(self):
import locale
lname = constants.APPNAME.lower()
try:
localedir = utils.find_locale_dir()
gettext.bindtextdomain(lname, localedir)
gettext.textdomain(lname)
gettext.install(lname, localedir, unicode=1)
gtk.glade.bindtextdomain(lname, localedir)
except IOError:
def broken_gettext_workaround(s):
return s
__builtins__.__dict__['_'] = broken_gettext_workaround
locale.setlocale(locale.LC_ALL, '')
return
def load_tray(self):
from Tray import Tray
tray = Tray()
tray.connect('button_press_event', self._tray_clicked)
def _tray_clicked(self, signal, event):
if event.button == 1:
self._main_presenter.view.present()
self._main_presenter.scroll_or_display_next_unread_item()
else:
self._main_presenter.view.should_present()
return
syntax highlighted by Code2HTML, v. 0.9.1