3 Module for displaying dialogs related to errors, warnings, notifications,
6 __copyright__
= "Copyright (c) 2002-2005 Free Software Foundation, Inc."
8 Straw is free software; you can redistribute it and/or modify it under the
9 terms of the GNU General Public License as published by the Free Software
10 Foundation; either version 2 of the License, or (at your option) any later
13 Straw is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License along with
18 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 Place - Suite 330, Boston, MA 02111-1307, USA. """
21 from gettext
import gettext
as _
22 from straw
import opml
, error
, Config
28 import os
, os
.path
, re
, locale
, time
, calendar
30 import urllib
, string
, urlparse
33 class UIFactory(object):
38 ("refresh", gtk
.STOCK_REFRESH
, _("_Refresh"), None, _("Update this feed"), None),
39 ("add_child", gtk
.STOCK_ADD
, _("Add child"), None, _("Update this feed"), None),
40 ("mark_as_read", gtk
.STOCK_CLEAR
, _("_Mark As Read"),
41 None, _("Mark all items in this feed as read"), None),
42 ("stop_refresh", None, _("_Stop Refresh"), None, _("Stop updating this feed"), None),
43 ("remove", gtk
.STOCK_REMOVE
, _("Remo_ve"), None, _("Remove"), None),
44 ("properties", gtk
.STOCK_INFO
, _("_Information"), None, _("Feed-specific properties"), None),
45 ("text_copy", gtk
.STOCK_COPY
, "_Copy", None, None, None),
46 ("link_copy", None, "_Copy Link Location", None, None, None),
47 ("link_open", None, "_Open Link", None, None, None),
48 ("subscribe", None, "_Subscribe", None, None, None),
49 ("zoom_in", gtk
.STOCK_ZOOM_IN
, "Zoom _In", None, None, None),
50 ("zoom_out", gtk
.STOCK_ZOOM_OUT
, "Zoom _Out", None, None, None),
51 ("zoom_100", gtk
.STOCK_ZOOM_100
, "_Normal Size", None, None, None),
52 ("mark_as_unread", gtk
.STOCK_CONVERT
, "Mark as _Unread", None, "Mark this item as unread", None)
55 def __new__(cls
, *a
, **k
):
56 obj
= object.__new
__(cls
, *a
, **k
)
57 obj
.__dict
__ = cls
._shared
_state
60 def __init__(self
, name
):
62 print 'initializing ui manager'
63 self
.action_groups
= {}
64 self
.manager
= gtk
.UIManager()
65 action_group
= gtk
.ActionGroup(name
)
66 action_group
.add_actions(UIFactory
.actions
)
67 num_action_groups
= len(self
.manager
.get_action_groups())
68 self
.action_groups
[name
] = num_action_groups
69 self
.manager
.insert_action_group(action_group
, num_action_groups
)
70 ui
= os
.path
.join(straw
.defs
.STRAW_DATA_DIR
, 'ui.xml')
71 self
.manager
.add_ui_from_file(ui
)
73 def get_popup(self
, path
):
74 return self
.manager
.get_widget(path
)
76 def get_action(self
, path
):
77 return self
.manager
.get_action(path
)
79 def ensure_update(self
):
80 self
.manager
.ensure_update()
83 def report_error(primary
, secondary
, parent
=None):
84 dialog
= gtk
.MessageDialog(parent
,
85 type=gtk
.MESSAGE_ERROR
,
86 buttons
=gtk
.BUTTONS_OK
,
87 message_format
=primary
)
88 dialog
.format_secondary_text(secondary
)
89 response
= dialog
.run()
93 def report_offline_status(parent
=None):
94 dialog
= gtk
.MessageDialog(parent
,
95 type=gtk
.MESSAGE_WARNING
,
96 buttons
=gtk
.BUTTONS_OK_CANCEL
,
97 message_format
="You Are Offline!")
98 dialog
.format_secondary_markup(_("You are currently reading offline. Would you like to go online now?"))
99 response
= dialog
.run()
105 Juri Pakaste <juri@iki.fi>
108 Jan Alonzo <jmalonzo@unpluggable.com>
109 Ryan P. Skadberg <skadz@stigmata.org>
110 Leandro Lameiro <lameiro@gmail.com>
111 Tuukka Hastrup <tuukka@iki.fi>
114 Iain McCoy <iain@mccoy.id.au>
115 Lucas Nussbaum <lucas@lucas-nussbaum.net>
116 Olivier Crete <tester@tester.ca>
117 Scott Douglas-Watson <sdouglaswatson@yahoo.co.uk>
118 Terje R\xf8sten (distutils)
121 Mark Pilgrim (feedparser and feedfinder)
122 Joe Gregorio (httplib2)
124 iconfile
= os
.path
.join(straw
.defs
.STRAW_DATA_DIR
,"straw.png")
125 logo
= gtk
.gdk
.pixbuf_new_from_file(iconfile
)
126 description
= _("A Desktop Feed Reader")
127 straw_copyright
= u
"""
128 Copyright \xa9 2005-2007 Straw Contributors
129 Copyright \xa9 2002-2004 Juri Pakaste"""
131 u
'Jakub \'jimmac\' Steiner',
136 u
"GNOME i18n Project and Translators<http://developer.gnome.org/projects/gtp/>",
137 u
"Juri Pakaste <juri@iki.fi>",
138 u
"Martin Steldinger <tribble@hanfplantage.de>",
139 u
"David Rousseau <boiteaflood@wanadoo.fr>",
140 u
"Sergei Vavinov <svv@cmc.msu.ru>",
141 u
"Terje R\xf8sten <terjeros@phys.ntnu.no>",
142 u
"Francisco J. Fernandez <franciscojavier.fernandez.serrador@hispalinux.es>",
143 u
"Elros Cyriatan (Dutch Translation)"
146 translator_credits
= 'translator_credits'
147 about
= gtk
.AboutDialog()
148 about
.set_name(straw
.defs
.PACKAGE
)
149 about
.set_version(straw
.defs
.VERSION
)
150 about
.set_copyright(straw_copyright
)
151 about
.set_comments(description
)
152 about
.set_authors(people
.splitlines())
153 about
.set_artists(artists
)
155 about
.set_translator_credits(translator_credits
)
156 about
.set_license(__license__
)
157 gtk
.about_dialog_set_url_hook(lambda about
, url
: url_show(url
))
158 about
.set_website(straw
.defs
.STRAW_HOME
)
159 about
.set_website_label(straw
.defs
.STRAW_HOME
)
160 about
.connect('response', lambda widget
, response
: widget
.destroy())
163 def listdiff(l1
, l2
, test
=None):
165 return _listdifftest(l1
, l2
, test
)
180 return (common
, inl1
, inl2
)
183 config
= Config
.get_instance()
184 if config
.browser_cmd
:
186 cmdbin
, args
= string
.splitfields(str(config
.browser_cmd
), maxsplit
=1)
189 pid
= subprocess
.Popen([cmdbin
, link
]).pid
191 except ValueError, ve
:
192 raise UrlOpenException("Problem opening link %s" % ve
)
195 return gnomevfs
.url_show(url
)
197 def set_clipboard_text(text
):
198 clipboard
= gtk
.clipboard_get(selection
="CLIPBOARD")
199 clipboard
.set_text(text
)
202 class UrlOpenException(Exception):
205 entity
= re
.compile(r
'\&.\w*?\;')
206 def convert_entities(text
):
208 entities
= htmlentitydefs
.entitydefs
210 ent_code
= entities
.get(ents
[1:-1], None)
211 if ent_code
is not None:
213 ents
= unicode(ent_code
, get_locale_encoding())
214 except UnicodeDecodeError:
215 ents
= unicode(ent_code
, 'latin-1')
216 except Exception, ex
:
217 error
.log("error occurred while converting entity %s: %s" % (ents
, ex
))
219 # check if it still needs conversion
220 if entity
.search(ents
) is None:
229 return unichr(int(code
, base
))
233 in_entity
= entity
.search(text
)
234 if in_entity
is None:
237 ctext
= in_entity
.re
.sub(conv
, text
)
240 def complete_url(url
, feed_location
):
241 #print "---- COMPLETING %s WITH %s" % (url, feed_location)
242 url
= urllib
.quote(url
, safe
=string
.punctuation
)
243 if urlparse
.urlparse(url
)[0] == '':
244 return urlparse
.urljoin(feed_location
, url
)
248 def get_url_location(url
):
249 url
= urllib
.quote(url
, safe
=string
.punctuation
)
250 parsed_url
= urlparse
.urlsplit(url
)
251 return urlparse
.urlunsplit((parsed_url
[0], parsed_url
[1], '','',''))
253 def get_locale_encoding():
255 encoding
= locale
.getpreferredencoding()
257 encoding
= sys
.getdefaultencoding()
260 def format_date(date
, format
=None, encoding
=None):
263 format
= get_date_format()
265 encoding
= get_locale_encoding()
266 timestr
= time
.strftime(format
, time
.localtime(calendar
.timegm(date
)))
267 return unicode(timestr
, encoding
)
269 def get_date_format():
270 # this is here just to make xgettext happy: it should be defined in
271 # only one place, and a good one would be MainWindow.py module level.
272 # however, we can't access _ there.
273 # The format: %A is the full weekday name
274 # %B is the full month name
275 # %e is the day of the month as a decimal number,
276 # without leading zero
277 # This should be translated to be suitable for the locale in
278 # question, feel free to alter the order and the parameters (they
279 # are strftime(3) parameters, the whole string is passed to the
280 # function, Straw does no additional interpretation) if you feel
281 # it's necessary in the translation file.
282 return _('%A %B %e %H:%M')
284 def pango_escape(text
):
286 return xml
.sax
.saxutils
.escape(text
)
288 def html_replace(exc
):
289 """ Python Cookbook 2ed, Section 1.23
291 if isinstance(exc
, (UnicodeDecodeError, UnicodeTranslateError)):
292 s
= [ u
'&%s;' % codepoint2name
[ord(c
)] for c
in exc
.object[exc
.start
:exc
.end
]]
293 return ''.join(s
), exc
.end
295 raise TypeError("can't handle %s" % exc
.__name
__)
297 codecs
.register_error('html_replace', html_replace
)