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 ConfigOptions
import *
22 from gettext
import gettext
as _
31 import os
.path
, re
, locale
, time
, calendar
33 import urllib
, string
, urlparse
36 class UIFactory(object):
41 ("refresh", gtk
.STOCK_REFRESH
, _("_Refresh"), None, _("Update this feed"), None),
42 ("add_child", gtk
.STOCK_ADD
, _("Add child"), None, _("Update this feed"), None),
43 ("mark_as_read", gtk
.STOCK_CLEAR
, _("_Mark As Read"),
44 None, _("Mark all items in this feed as read"), None),
45 ("stop_refresh", None, _("_Stop Refresh"), None, _("Stop updating this feed"), None),
46 ("remove", gtk
.STOCK_REMOVE
, _("Remo_ve"), None, _("Remove"), None),
47 ("properties", gtk
.STOCK_INFO
, _("_Information"), None, _("Feed-specific properties"), None),
48 ("text_copy", gtk
.STOCK_COPY
, "_Copy", None, None, None),
49 ("link_copy", None, "_Copy Link Location", None, None, None),
50 ("link_open", None, "_Open Link", None, None, None),
51 ("subscribe", None, "_Subscribe", None, None, None),
52 ("zoom_in", gtk
.STOCK_ZOOM_IN
, "Zoom _In", None, None, None),
53 ("zoom_out", gtk
.STOCK_ZOOM_OUT
, "Zoom _Out", None, None, None),
54 ("zoom_100", gtk
.STOCK_ZOOM_100
, "_Normal Size", None, None, None),
55 ("mark_as_unread", gtk
.STOCK_CONVERT
, "Mark as _Unread", None, "Mark this item as unread", None)
58 def __new__(cls
, *a
, **k
):
59 obj
= object.__new
__(cls
, *a
, **k
)
60 obj
.__dict
__ = cls
._shared
_state
63 def __init__(self
, name
):
65 print 'initializing ui manager'
66 self
.action_groups
= {}
67 self
.manager
= gtk
.UIManager()
68 action_group
= gtk
.ActionGroup(name
)
69 action_group
.add_actions(UIFactory
.actions
)
70 num_action_groups
= len(self
.manager
.get_action_groups())
71 self
.action_groups
[name
] = num_action_groups
72 self
.manager
.insert_action_group(action_group
, num_action_groups
)
73 ui
= os
.path
.join(straw
.defs
.STRAW_DATA_DIR
, 'ui.xml')
74 self
.manager
.add_ui_from_file(ui
)
76 def get_popup(self
, path
):
77 return self
.manager
.get_widget(path
)
79 def get_action(self
, path
):
80 return self
.manager
.get_action(path
)
82 def ensure_update(self
):
83 self
.manager
.ensure_update()
86 def report_error(primary
, secondary
, parent
=None):
87 dialog
= gtk
.MessageDialog(parent
,
88 type=gtk
.MESSAGE_ERROR
,
89 buttons
=gtk
.BUTTONS_OK
,
90 message_format
=primary
)
91 dialog
.format_secondary_text(secondary
)
92 response
= dialog
.run()
96 def report_offline_status(parent
=None):
97 dialog
= gtk
.MessageDialog(parent
,
98 type=gtk
.MESSAGE_WARNING
,
99 buttons
=gtk
.BUTTONS_OK_CANCEL
,
100 message_format
="You Are Offline!")
101 dialog
.format_secondary_markup(_("You are currently reading offline. Would you like to go online now?"))
102 response
= dialog
.run()
108 Juri Pakaste <juri@iki.fi>
111 Jan Alonzo <jmalonzo@unpluggable.com>
112 Ryan P. Skadberg <skadz@stigmata.org>
113 Leandro Lameiro <lameiro@gmail.com>
114 Tuukka Hastrup <tuukka@iki.fi>
117 Iain McCoy <iain@mccoy.id.au>
118 Lucas Nussbaum <lucas@lucas-nussbaum.net>
119 Olivier Crete <tester@tester.ca>
120 Scott Douglas-Watson <sdouglaswatson@yahoo.co.uk>
121 Terje R\xf8sten (distutils)
124 Mark Pilgrim (feedparser and feedfinder)
125 Joe Gregorio (httplib2)
127 iconfile
= os
.path
.join(straw
.defs
.STRAW_DATA_DIR
,"straw.png")
128 logo
= gtk
.gdk
.pixbuf_new_from_file(iconfile
)
129 description
= _("A Desktop Feed Reader")
130 straw_copyright
= u
"""
131 Copyright \xa9 2005-2007 Straw Contributors
132 Copyright \xa9 2002-2004 Juri Pakaste"""
134 u
'Jakub \'jimmac\' Steiner',
139 u
"GNOME i18n Project and Translators<http://developer.gnome.org/projects/gtp/>",
140 u
"Juri Pakaste <juri@iki.fi>",
141 u
"Martin Steldinger <tribble@hanfplantage.de>",
142 u
"David Rousseau <boiteaflood@wanadoo.fr>",
143 u
"Sergei Vavinov <svv@cmc.msu.ru>",
144 u
"Terje R\xf8sten <terjeros@phys.ntnu.no>",
145 u
"Francisco J. Fernandez <franciscojavier.fernandez.serrador@hispalinux.es>",
146 u
"Elros Cyriatan (Dutch Translation)"
149 translator_credits
= 'translator_credits'
150 about
= gtk
.AboutDialog()
151 about
.set_name(straw
.defs
.PACKAGE
)
152 about
.set_version(straw
.defs
.VERSION
)
153 about
.set_copyright(straw_copyright
)
154 about
.set_comments(description
)
155 about
.set_authors(people
.splitlines())
156 about
.set_artists(artists
)
158 about
.set_translator_credits(translator_credits
)
159 about
.set_license(__license__
)
160 gtk
.about_dialog_set_url_hook(lambda about
, url
: url_show(url
))
161 about
.set_website(straw
.defs
.STRAW_HOME
)
162 about
.set_website_label(straw
.defs
.STRAW_HOME
)
163 about
.connect('response', lambda widget
, response
: widget
.destroy())
166 def listdiff(l1
, l2
, test
=None):
168 return _listdifftest(l1
, l2
, test
)
183 return (common
, inl1
, inl2
)
186 browser_cmd
= Config
.get(OPTION_BROWSER_CMD
)
190 cmdbin
, args
= string
.splitfields(browser_cmd
, maxsplit
=1)
193 pid
= subprocess
.Popen([cmdbin
, link
]).pid
195 except ValueError, ve
:
196 raise UrlOpenException("Problem opening link %s" % ve
)
198 return gnomevfs
.url_show(url
)
200 def set_clipboard_text(text
):
201 clipboard
= gtk
.clipboard_get(selection
="CLIPBOARD")
202 clipboard
.set_text(text
)
205 class UrlOpenException(Exception):
208 entity
= re
.compile(r
'\&.\w*?\;')
209 def convert_entities(text
):
211 entities
= htmlentitydefs
.entitydefs
213 ent_code
= entities
.get(ents
[1:-1], None)
214 if ent_code
is not None:
216 ents
= unicode(ent_code
, get_locale_encoding())
217 except UnicodeDecodeError:
218 ents
= unicode(ent_code
, 'latin-1')
219 except Exception, ex
:
220 error
.log("error occurred while converting entity %s: %s" % (ents
, ex
))
222 # check if it still needs conversion
223 if entity
.search(ents
) is None:
232 return unichr(int(code
, base
))
236 in_entity
= entity
.search(text
)
237 if in_entity
is None:
240 ctext
= in_entity
.re
.sub(conv
, text
)
243 def complete_url(url
, feed_location
):
244 #print "---- COMPLETING %s WITH %s" % (url, feed_location)
245 url
= urllib
.quote(url
, safe
=string
.punctuation
)
246 if urlparse
.urlparse(url
)[0] == '':
247 return urlparse
.urljoin(feed_location
, url
)
251 def get_url_location(url
):
252 url
= urllib
.quote(url
, safe
=string
.punctuation
)
253 parsed_url
= urlparse
.urlsplit(url
)
254 return urlparse
.urlunsplit((parsed_url
[0], parsed_url
[1], '','',''))
256 def get_locale_encoding():
258 encoding
= locale
.getpreferredencoding()
260 encoding
= sys
.getdefaultencoding()
263 def format_date(date
, format
=None, encoding
=None):
266 format
= get_date_format()
268 encoding
= get_locale_encoding()
269 timestr
= time
.strftime(format
, time
.localtime(calendar
.timegm(date
)))
270 return unicode(timestr
, encoding
)
272 def get_date_format():
273 # this is here just to make xgettext happy: it should be defined in
274 # only one place, and a good one would be MainWindow.py module level.
275 # however, we can't access _ there.
276 # The format: %A is the full weekday name
277 # %B is the full month name
278 # %e is the day of the month as a decimal number,
279 # without leading zero
280 # This should be translated to be suitable for the locale in
281 # question, feel free to alter the order and the parameters (they
282 # are strftime(3) parameters, the whole string is passed to the
283 # function, Straw does no additional interpretation) if you feel
284 # it's necessary in the translation file.
285 return _('%A %B %e %H:%M')
287 def pango_escape(text
):
289 return xml
.sax
.saxutils
.escape(text
)
293 def html_replace(exc
):
294 """ Python Cookbook 2ed, Section 1.23
296 if isinstance(exc
, (UnicodeDecodeError, UnicodeTranslateError)):
297 s
= [ u
'&%s;' % codepoint2name
[ord(c
)] for c
in exc
.object[exc
.start
:exc
.end
]]
298 return ''.join(s
), exc
.end
300 raise TypeError("can't handle %s" % exc
.__name
__)
302 codecs
.register_error('html_replace', html_replace
)