Improving GTK interface with scrollbars
[feedingit] / src / FeedingIt.py
1 #!/usr/bin/env python2.5
2
3
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.
9 #
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.
14 #
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/>.
17 #
18
19 # ============================================================================
20 # Name        : FeedingIt.py
21 # Author      : Yves Marcoz
22 # Version     : 0.1
23 # Description : PyGtk Example 
24 # ============================================================================
25
26 import gtk
27 import feedparser
28 import pango
29 import hildon
30 import gtkhtml2
31 import time
32 import webbrowser
33 import pickle
34 from os.path import isfile, isdir
35 from os import mkdir
36 import md5
37 import sys   
38 import urllib2
39
40 from rss import *
41    
42 class AddWidgetWizard(hildon.WizardDialog):
43     
44     def __init__(self, parent):
45         # Create a Notebook
46         self.notebook = gtk.Notebook()
47
48         self.nameEntry = hildon.Entry(gtk.HILDON_SIZE_AUTO)
49         self.nameEntry.set_placeholder("Enter Feed Name")
50         
51         self.urlEntry = hildon.Entry(gtk.HILDON_SIZE_AUTO)
52         
53         self.urlEntry.set_placeholder("Enter a URL")
54             
55         labelEnd = gtk.Label("Success")
56         
57         self.notebook.append_page(self.nameEntry, None)
58         self.notebook.append_page(self.urlEntry, None) 
59         self.notebook.append_page(labelEnd, None)      
60
61         hildon.WizardDialog.__init__(self, parent, "Add Feed", self.notebook)
62    
63         # Set a handler for "switch-page" signal
64         #self.notebook.connect("switch_page", self.on_page_switch, self)
65    
66         # Set a function to decide if user can go to next page
67         self.set_forward_page_func(self.some_page_func)
68    
69         self.show_all()
70         print dir(self)
71         
72     def getData(self):
73         return (self.nameEntry.get_text(), self.urlEntry.get_text())
74         
75     def on_page_switch(self, notebook, page, num, dialog):
76         print >>sys.stderr, "Page %d" % num
77         return True
78    
79     def some_page_func(self, nb, current, userdata):
80         # Validate data for 1st page
81         print current
82         if current == 0:
83             entry = nb.get_nth_page(current)
84             # Check the name is not null
85             return len(entry.get_text()) != 0
86         elif current == 1:
87             entry = nb.get_nth_page(current)
88             # Check the url is not null, and starts with http
89             print ( (len(entry.get_text()) != 0) and (entry.get_text().startswith("http")) )
90             return ( (len(entry.get_text()) != 0) and (entry.get_text().startswith("http")) )
91         elif current != 2:
92             return False
93         else:
94             return True
95
96 class FeedingIt:
97     def __init__(self):
98         # Init the windows
99         self.window = hildon.StackableWindow()
100         menu = hildon.AppMenu()
101         # Create a button and add it to the menu
102         button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
103         button.set_label("Update All Feeds")
104         button.connect("clicked", self.button_update_clicked, "All")
105         menu.append(button)
106         button = hildon.GtkButton(gtk.HILDON_SIZE_AUTO)
107         button.set_label("Add Feed")
108         button.connect("clicked", self.button_add_clicked)
109         menu.append(button)
110         
111         self.window.set_app_menu(menu)
112         menu.show_all()
113         
114         self.feedWindow = hildon.StackableWindow()
115         self.articleWindow = hildon.StackableWindow()
116
117         self.listing = Listing()
118         #self.listing.downloadFeeds()
119         self.displayListing() 
120         
121         #self.window.show_all()
122         #self.displayFeed(self.listing.getFeed(0))
123         
124     def button_add_clicked(self, button):
125         wizard = AddWidgetWizard(self.window)
126         ret = wizard.run()
127         if ret == 2:
128             (title, url) = wizard.getData()
129             if (not title == '') and (not url == ''): 
130                self.listing.addFeed(title, url)
131         wizard.destroy()
132         self.displayListing()
133         
134     def button_update_clicked(self, button, key):
135         hildon.hildon_gtk_window_set_progress_indicator(self.window, 1)
136         if key == "All":
137             self.listing.updateFeeds()
138         else:
139             self.listing.getFeed(key).updateFeed()
140         self.displayListing()
141         hildon.hildon_gtk_window_set_progress_indicator(self.window, 0)
142         
143     def displayListing(self):
144         try:
145             self.window.remove(self.pannableListing)
146         except:
147             pass
148         self.vboxListing = gtk.VBox(False,10)
149         self.pannableListing = hildon.PannableArea()
150         self.pannableListing.add_with_viewport(self.vboxListing)
151
152         for key in self.listing.getListOfFeeds():
153             #button = gtk.Button(item)
154             button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
155                               hildon.BUTTON_ARRANGEMENT_VERTICAL)
156             button.set_text(self.listing.getFeedTitle(key), self.listing.getFeedUpdateTime(key))
157             button.set_alignment(0,0,1,1)
158             #label = button.child
159             #label.modify_font(pango.FontDescription("sans 10"))
160             button.connect("clicked", self.buttonFeedClicked, self, self.window, key)
161             self.vboxListing.pack_start(button, expand=False)
162         self.window.add(self.pannableListing)
163         self.window.show_all()
164         
165     def displayFeed(self, key):
166         # Initialize the feed panel
167         self.vboxFeed = gtk.VBox(False, 10)
168         self.pannableFeed = hildon.PannableArea()
169         self.pannableFeed.add_with_viewport(self.vboxFeed)
170         
171         index = 0
172         for item in self.listing.getFeed(key).getEntries():
173             #button = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT,
174             #                  hildon.BUTTON_ARRANGEMENT_HORIZONTAL)
175             #button.set_text(item["title"], time.strftime("%a, %d %b %Y %H:%M:%S",item["updated_parsed"]))
176             #button.set_text(item["title"], time.asctime(item["updated_parsed"]))
177             #button.set_text(item["title"],"")
178             #button.set_alignment(0,0,1,1)
179             #button.set_markup(True)
180             button = gtk.Button(item["title"])
181             button.set_alignment(0,0)
182             label = button.child
183             #label.set_markup(item["title"])
184             label.modify_font(pango.FontDescription("sans 16"))
185             button.connect("clicked", self.button_clicked, self, self.window, key, index)
186             
187             self.vboxFeed.pack_start(button, expand=False)
188             index=index+1
189
190         self.feedWindow.add(self.pannableFeed)
191         self.feedWindow.show_all()
192      
193     def displayArticle(self, key, index):
194         text = self.listing.getFeed(key).getArticle(index)
195         self.articleWindow = hildon.StackableWindow()
196
197         # Init the article display    
198         self.view = gtkhtml2.View()
199         self.pannable_article = hildon.PannableArea()
200         self.pannable_article.add(self.view)
201         self.document = gtkhtml2.Document()
202         self.view.set_document(self.document)
203         
204         self.document.clear()
205         self.document.open_stream("text/html")
206         self.document.write_stream(text)
207         self.document.close_stream()
208         
209         self.articleWindow.add(self.pannable_article)
210         
211         self.articleWindow.show_all()
212         
213         self.document.connect("link_clicked", self._signal_link_clicked)
214         self.document.connect("request-url", self._signal_request_url)
215         
216         self.document.open_stream("text/html")
217         self.document.write_stream(text)
218         self.document.close_stream()
219         self.document.show()
220      
221     def tap(self):
222          pass
223 #    def _signal_on_url(self, object, url):
224 #        if url == None: url = ""
225 #        else: url = self._complete_url(url)
226         #self.emit("status_changed", url)
227
228     def _signal_link_clicked(self, object, link):
229         webbrowser.open(link)
230
231     def _signal_request_url(self, object, url, stream):
232         f = urllib2.urlopen(url)
233         stream.write(f.read())
234         stream.close()
235 #        
236 #    def _complete_url(self, url):
237 #        import string, urlparse, urllib
238 #        url = urllib.quote(url, safe=string.punctuation)
239 #        if urlparse.urlparse(url)[0] == '':
240 #            return urlparse.urljoin(self.location, url)
241 #        else:
242 #            return url
243 #        
244 #    def _open_url(self, url, headers=[]):
245 #        import urllib2
246 #        opener = urllib2.build_opener()
247 #        opener.addheaders = [('User-agent', 'Wikitin')]+headers
248 #        return opener.open(url)
249 #
250 #    def _fetch_url(self, url, headers=[]):
251 #        return self._open_url(url, headers).read()
252         
253         
254     def button_clicked(widget, button, app, window, key, index):
255         app.displayArticle(key, index)
256     
257     def buttonFeedClicked(widget, button, app, window, key):
258         app.displayFeed(key)
259      
260     def run(self):
261         self.window.connect("destroy", gtk.main_quit)
262         #self.window.show_all()
263         gtk.main()
264
265 if __name__ == "__main__":
266     if not isdir(CONFIGDIR):
267         try:
268             mkdir(CONFIGDIR)
269         except:
270             print "Error: Can't create configuration directory"
271             sys.exit(1)
272     app = FeedingIt()
273     app.run()