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 : PyGtk Example
24 # ============================================================================
34 from os.path import isfile, isdir
39 from portrait import FremantleRotation
43 class AddWidgetWizard(hildon.WizardDialog):
45 def __init__(self, parent):
47 self.notebook = gtk.Notebook()
49 self.nameEntry = hildon.Entry(gtk.HILDON_SIZE_AUTO)
50 self.nameEntry.set_placeholder("Enter Feed Name")
52 self.urlEntry = hildon.Entry(gtk.HILDON_SIZE_AUTO)
54 self.urlEntry.set_placeholder("Enter a URL")
56 labelEnd = gtk.Label("Success")
58 self.notebook.append_page(self.nameEntry, None)
59 self.notebook.append_page(self.urlEntry, None)
60 self.notebook.append_page(labelEnd, None)
62 hildon.WizardDialog.__init__(self, parent, "Add Feed", self.notebook)
64 # Set a handler for "switch-page" signal
65 #self.notebook.connect("switch_page", self.on_page_switch, self)
67 # Set a function to decide if user can go to next page
68 self.set_forward_page_func(self.some_page_func)
73 return (self.nameEntry.get_text(), self.urlEntry.get_text())
75 def on_page_switch(self, notebook, page, num, dialog):
78 def some_page_func(self, nb, current, userdata):
79 # Validate data for 1st page
81 entry = nb.get_nth_page(current)
82 # Check the name is not null
83 return len(entry.get_text()) != 0
85 entry = nb.get_nth_page(current)
86 # Check the url is not null, and starts with http
87 return ( (len(entry.get_text()) != 0) and (entry.get_text().startswith("http")) )
93 class DisplayFeed(hildon.StackableWindow):
94 def __init__(self, listing, key):
95 hildon.StackableWindow.__init__(self)
96 self.listing = listing
103 self.listing = Listing()
106 self.window = hildon.StackableWindow()
107 self.window.set_title("FeedingIt")
108 FremantleRotation("FeedingIt", main_window=self.window)
109 menu = hildon.AppMenu()
110 # Create a button and add it to the menu
111 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
112 button.set_label("Update All Feeds")
113 button.connect("clicked", self.button_update_clicked, "All")
115 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
116 button.set_label("Add Feed")
117 button.connect("clicked", self.button_add_clicked)
120 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
121 button.set_label("Delete Feed")
122 #button.set_selector(self.create_selector())
123 button.connect("clicked", self.button_delete_clicked)
126 self.window.set_app_menu(menu)
129 self.feedWindow = hildon.StackableWindow()
130 self.articleWindow = hildon.StackableWindow()
132 #self.listing.downloadFeeds()
133 self.displayListing()
135 #self.window.show_all()
136 #self.displayFeed(self.listing.getFeed(0))
138 def button_add_clicked(self, button):
139 wizard = AddWidgetWizard(self.window)
142 (title, url) = wizard.getData()
143 if (not title == '') and (not url == ''):
144 self.listing.addFeed(title, url)
146 self.displayListing()
148 def button_update_clicked(self, button, key):
149 #hildon.hildon_gtk_window_set_progress_indicator(self.window, 1)
151 self.listing.updateFeeds()
153 self.listing.getFeed(key).updateFeed()
154 self.displayFeed(key)
155 self.displayListing()
156 #hildon.hildon_gtk_window_set_progress_indicator(self.window, 0)
158 def button_delete_clicked(self, button):
159 self.pickerDialog = hildon.PickerDialog(self.window)
161 self.pickerDialog.set_selector(self.create_selector())
162 self.pickerDialog.show_all()
164 def create_selector(self):
165 selector = hildon.TouchSelector(text=True)
167 #selector.set_column_selection_mode(hildon.TOUCH_SELECTOR_SELECTION_MODE_MULTIPLE)
169 selector.connect("changed", self.selection_changed)
171 for key in self.listing.getListOfFeeds():
172 title=self.listing.getFeedTitle(key)
173 selector.append_text(title)
174 self.mapping[title]=key
178 def selection_changed(self, widget, data):
179 current_selection = widget.get_current_text()
180 #print 'Current selection: %s' % current_selection
181 #print "To Delete: %s" % self.mapping[current_selection]
182 self.pickerDialog.destroy()
183 if self.show_confirmation_note(self.window, current_selection):
184 self.listing.removeFeed(self.mapping[current_selection])
186 self.displayListing()
188 def show_confirmation_note(self, parent, title):
189 note = hildon.Note("confirmation", parent, "Are you sure you want to delete " + title +"?")
191 retcode = gtk.Dialog.run(note)
194 if retcode == gtk.RESPONSE_OK:
199 def displayListing(self):
201 self.window.remove(self.pannableListing)
204 self.vboxListing = gtk.VBox(False,10)
205 self.pannableListing = hildon.PannableArea()
206 self.pannableListing.add_with_viewport(self.vboxListing)
208 for key in self.listing.getListOfFeeds():
209 #button = gtk.Button(item)
210 button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
211 hildon.BUTTON_ARRANGEMENT_VERTICAL)
212 button.set_text(self.listing.getFeedTitle(key), self.listing.getFeedUpdateTime(key))
213 button.set_alignment(0,0,1,1)
214 #label = button.child
215 #label.modify_font(pango.FontDescription("sans 10"))
216 button.connect("clicked", self.buttonFeedClicked, self, self.window, key)
217 self.vboxListing.pack_start(button, expand=False)
218 self.window.add(self.pannableListing)
219 self.window.show_all()
221 def displayFeed(self, key):
222 # Initialize the feed panel
224 self.feedWindow.destroy()
227 self.feedWindow.set_title(self.listing.getFeedTitle(key))
228 self.vboxFeed = gtk.VBox(False, 10)
229 self.pannableFeed = hildon.PannableArea()
230 self.pannableFeed.add_with_viewport(self.vboxFeed)
231 self.pannableFeed.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
233 menu = hildon.AppMenu()
234 # Create a button and add it to the menu
235 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
236 button.set_label("Update Feed")
237 button.connect("clicked", self.button_update_clicked, key)
239 self.feedWindow.set_app_menu(menu)
243 for item in self.listing.getFeed(key).getEntries():
244 button = gtk.Button(item["title"])
245 button.set_alignment(0,0)
247 label.modify_font(pango.FontDescription("sans 16"))
248 label.set_line_wrap(True)
250 label.set_size_request(self.feedWindow.get_size()[0]-50, -1)
251 button.connect("clicked", self.button_clicked, self, self.window, key, index)
253 self.vboxFeed.pack_start(button, expand=False)
256 self.feedWindow.add(self.pannableFeed)
257 self.feedWindow.show_all()
259 def displayArticle(self, key, index):
260 self.text = self.listing.getFeed(key).getArticle(index)
261 self.articleWindow = hildon.StackableWindow()
262 self.articleWindow.set_title(self.listing.getFeedTitle(key))
264 menu = hildon.AppMenu()
265 # Create a button and add it to the menu
266 button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
267 button.set_label("Display Images")
268 button.connect("clicked", self.reloadArticle)
270 self.articleWindow.set_app_menu(menu)
273 # Init the article display
274 self.view = gtkhtml2.View()
275 self.pannable_article = hildon.PannableArea()
276 self.pannable_article.add(self.view)
277 self.pannable_article.set_property("mov-mode", hildon.MOVEMENT_MODE_BOTH)
278 self.document = gtkhtml2.Document()
279 self.view.set_document(self.document)
281 self.document.clear()
282 self.document.open_stream("text/html")
283 self.document.write_stream(self.text)
284 self.document.close_stream()
286 self.articleWindow.add(self.pannable_article)
288 self.articleWindow.show_all()
290 self.document.connect("link_clicked", self._signal_link_clicked)
291 self.document.connect("request-url", self._signal_request_url)
292 #self.document.connect("ReloadArticle", self.reloadArticle)
294 def reloadArticle(self, widget):
295 self.document.open_stream("text/html")
296 self.document.write_stream(self.text)
297 self.document.close_stream()
299 # def _signal_on_url(self, object, url):
300 # if url == None: url = ""
301 # else: url = self._complete_url(url)
302 #self.emit("status_changed", url)
304 def _signal_link_clicked(self, object, link):
305 webbrowser.open(link)
307 def _signal_request_url(self, object, url, stream):
308 f = urllib2.urlopen(url)
309 stream.write(f.read())
312 # def _complete_url(self, url):
313 # import string, urlparse, urllib
314 # url = urllib.quote(url, safe=string.punctuation)
315 # if urlparse.urlparse(url)[0] == '':
316 # return urlparse.urljoin(self.location, url)
320 # def _open_url(self, url, headers=[]):
322 # opener = urllib2.build_opener()
323 # opener.addheaders = [('User-agent', 'Wikitin')]+headers
324 # return opener.open(url)
326 # def _fetch_url(self, url, headers=[]):
327 # return self._open_url(url, headers).read()
329 def button_clicked(widget, button, app, window, key, index):
330 app.displayArticle(key, index)
331 #app.document.emit("ReloadArticle")
333 def buttonFeedClicked(widget, button, app, window, key):
337 self.window.connect("destroy", gtk.main_quit)
340 if __name__ == "__main__":
341 #gobject.signal_new("ReloadArticle", gtkhtml2.Document,
342 # gobject.SIGNAL_RUN_LAST,
343 # gobject.TYPE_NONE, ())
344 if not isdir(CONFIGDIR):
348 print "Error: Can't create configuration directory"