1 #!/usr/bin/env python2.5
4 # Copyright (c) 2007-2008 INdT.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Lesser General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # ============================================================================
21 # Author : Yves Marcoz
23 # Description : Simple RSS Reader
24 # ============================================================================
26 from xml.dom.minidom import parse, parseString
32 from os.path import isfile, dirname
35 class ExportOpmlData():
36 def __init__(self, parent, listing):
37 fs = hildon.FileSystemModel()
38 dialog = hildon.FileChooserDialog(parent, gtk.FILE_CHOOSER_ACTION_SAVE, fs)
39 #(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
40 #gtk.STOCK_SAVE, gtk.RESPONSE_OK))
42 #dialog = gobject.new(hildon.FileChooserDialog, \
43 # action=gtk.FILE_CHOOSER_ACTION_SAVE)
44 #dialog.set_default_response(gtk.RESPONSE_OK)
45 #dialog.set_property('autonaming',False)
46 #dialog.set_property('show-files',True)
47 dialog.set_current_folder('/home/user/MyDocs/')
48 dialog.set_current_name('feedingit-export')
49 dialog.set_extension('opml')
50 response = dialog.run()
52 if response == gtk.RESPONSE_OK:
53 filename = dialog.get_filename()
59 note = "File already exists. Aborted"
60 confirm = hildon.Note ("confirmation", parent, "File already exists. Are you sure you want to overwrite it?", gtk.STOCK_DIALOG_WARNING )
61 confirm.set_button_texts ("Yes", "Cancel")
62 response = confirm.run()
64 if response == gtk.RESPONSE_OK:
67 note = "Operation cancelled."
70 file = open(filename, "w")
71 file.write(self.getOpmlText(listing))
73 note = "Feeds exported to %s" %filename
75 note = "Failed to export feeds"
78 #dialog = hildon.Note ("information", parent, note , gtk.STOCK_DIALOG_INFO )
81 elif response == gtk.RESPONSE_CANCEL:
84 def getOpmlText(self, listing):
85 time_now = time.strftime('%a, %d %b %Y %H:%M:%S GMT', time.gmtime())
86 opml_text = """<?xml version="1.0" encoding="UTF-8"?>
89 <title>Feeding It Export</title>
93 for key in listing.getListOfFeeds():
94 title = listing.getFeedTitle(key)
95 url = listing.getFeedUrl(key)
96 if not title == "Archived Articles":
97 opml_text += """\n\t\t<outline type="rss" text="%s" title="%s" xmlUrl="%s"/>""" % (self.sanitize(title), self.sanitize(title), self.sanitize(url))
98 opml_text += """\n</body>\n</opml>\n"""
101 def sanitize(self, text):
102 from cgi import escape
103 return escape(text).encode('ascii', 'xmlcharrefreplace')
108 def __init__(self, parent):
110 dialog = hildon.Note ("confirmation", parent, "What type of OPML?", gtk.STOCK_DIALOG_WARNING )
111 dialog.set_button_texts ("File", "URL")
112 response = dialog.run()
115 if response == gtk.RESPONSE_OK:
117 self.data = self.askForFile()
120 self.data = self.downloadFile()
123 if not self.data == None:
124 dialog = OpmlDialog(self.parent, self.data)
125 response = dialog.run()
126 if response == gtk.RESPONSE_ACCEPT:
127 items = dialog.getItems()
134 def downloadFile(self):
135 dlg = gtk.Dialog("Import OPML from web", self.parent, gtk.DIALOG_DESTROY_WITH_PARENT,
136 ('Import', gtk.RESPONSE_OK,
137 gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL))
138 hb = gtk.HBox(False, 5)
139 hb.pack_start(gtk.Label('URL:'), expand=False)
140 entry = hildon.Entry(0)
141 entry.set_text("http://")
142 entry.select_region(-1, -1)
143 hb.pack_start(entry, expand=True)
145 dlg.vbox.pack_start(hb, False)
148 url = entry.get_text()
150 if resp == gtk.RESPONSE_CANCEL:
153 f = urllib2.urlopen(url)
161 def askForFile(self):
162 #dialog = hildon.FileChooserDialog(self.parent,
163 # gtk.FILE_CHOOSER_ACTION_OPEN)
164 #dialog = gobject.new(hildon.FileChooserDialog, \
165 # action=gtk.FILE_CHOOSER_ACTION_OPEN)
166 #dialog.set_default_response(gtk.RESPONSE_OK)
167 fs = hildon.FileSystemModel()
168 dialog = hildon.FileChooserDialog(self.parent, gtk.FILE_CHOOSER_ACTION_OPEN, fs)
170 filter = gtk.FileFilter()
171 filter.set_name("All files")
172 filter.add_pattern("*")
173 dialog.add_filter(filter)
175 filter = gtk.FileFilter()
176 filter.set_name("OPML")
177 filter.add_pattern("*.xml")
178 filter.add_pattern("*.opml")
179 dialog.add_filter(filter)
181 response = dialog.run()
182 if response == gtk.RESPONSE_OK:
183 file = open(dialog.get_filename())
188 elif response == gtk.RESPONSE_CANCEL:
193 class OpmlDialog(gtk.Dialog):
194 def parse(self, opmlData):
196 dom1 = parseString(opmlData)
198 outlines = dom1.getElementsByTagName('outline')
199 for outline in outlines:
200 title = outline.getAttribute('text')
201 url = outline.getAttribute('xmlUrl')
203 url = outline.getAttribute('htmlUrl')
205 self.feeds.append( (title, url) )
207 def getFeedLinks(self):
210 def __init__(self, parent, opmlData):
212 gtk.Dialog.__init__(self, "Select OPML Feeds", parent, gtk.DIALOG_DESTROY_WITH_PARENT, (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
214 self.pannableArea = hildon.PannableArea()
215 self.treestore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
216 self.treeview = gtk.TreeView(self.treestore)
220 self.set_default_size(-1, 600)
221 self.vbox.pack_start(self.pannableArea)
223 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
224 button.set_label("Select All")
225 button.connect("clicked", self.button_select_all_clicked)
226 self.action_area.pack_end(button)
228 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
229 button.set_label("Unselect All")
230 button.connect("clicked", self.button_select_none_clicked)
231 self.action_area.pack_end(button)
235 def button_select_all_clicked(self, button):
236 self.treeview.get_selection().select_all()
238 def button_select_none_clicked(self, button):
239 self.treeview.get_selection().unselect_all()
241 def displayFeeds(self):
242 self.treeview.destroy()
243 self.treestore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
244 self.treeview = gtk.TreeView()
246 self.treeview.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
247 hildon.hildon_gtk_tree_view_set_ui_mode(self.treeview, gtk.HILDON_UI_MODE_EDIT)
249 self.treeview.append_column(gtk.TreeViewColumn('Feed Name', gtk.CellRendererText(), text = 0))
251 self.pannableArea.add(self.treeview)
252 self.pannableArea.show_all()
253 self.treeview.get_selection().select_all()
255 def refreshList(self, selected=None, offset=0):
256 rect = self.treeview.get_visible_rect()
257 y = rect.y+rect.height
258 self.treestore = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
259 self.treeview.set_model(self.treestore)
260 for (title, url) in self.feeds:
261 item = self.treestore.append([title, url])
262 self.treeview.get_selection().select_iter(item)
263 #self.treeview.get_selection().select_all()
264 self.pannableArea.show_all()
268 treeselection = self.treeview.get_selection()
269 (model, pathlist) = treeselection.get_selected_rows()
270 for path in pathlist:
271 list.append( (model.get_value(model.get_iter(path),0), model.get_value(model.get_iter(path),1)) )
274 def showOpmlData(widget, parent, button):
275 dialog = GetOpmlData(parent)
276 print dialog.getData()
279 if __name__ == "__main__":
280 window = hildon.Window()
281 window.set_title("Test App")
284 button = gtk.Button("Click to confirm.")
286 button.connect("clicked", showOpmlData, window, button)
287 window.connect("destroy", gtk.main_quit)