Mercurial > pidgin
comparison finch/libgnt/pygnt/example/rss/gntrss-ui.py @ 18722:8b5082d54c1d
Make the rss-reader look and behave nicer.
author | Sadrul Habib Chowdhury <imadil@gmail.com> |
---|---|
date | Sun, 29 Jul 2007 19:00:14 +0000 |
parents | 64a7b13d3b8d |
children | 1aeda1e812a8 |
comparison
equal
deleted
inserted
replaced
18721:7389b597a812 | 18722:8b5082d54c1d |
---|---|
21 USA | 21 USA |
22 """ | 22 """ |
23 | 23 |
24 """ | 24 """ |
25 This file deals with the UI part (gnt) of the application | 25 This file deals with the UI part (gnt) of the application |
26 | |
27 TODO: | |
28 - Allow showing feeds of only selected 'category' and/or 'priority'. A different | |
29 window should be used to change such filtering. | |
30 - Display details of each item in its own window. | |
31 - Add search capability, and allow searching only in title/body. Also allow | |
32 filtering in the search results. | |
33 - Show the data and time for feed items (probably in a separate column .. perhaps not) | |
34 - Have a simple way to add a feed. | |
35 - Allow renaming a feed. | |
26 """ | 36 """ |
27 | 37 |
28 import gntrss | 38 import gntrss |
29 import gnt | 39 import gnt |
30 import gobject | 40 import gobject |
37 | 47 |
38 gnt.gnt_init() | 48 gnt.gnt_init() |
39 | 49 |
40 class RssTree(gnt.Tree): | 50 class RssTree(gnt.Tree): |
41 __gsignals__ = { | 51 __gsignals__ = { |
42 'active_changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)), | 52 'active_changed' : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, (gobject.TYPE_OBJECT,)) |
43 'key_pressed' : 'override' | |
44 } | 53 } |
45 | 54 |
46 def __init__(self): | 55 def __init__(self): |
47 self.active = None | 56 self.active = None |
48 gnt.Tree.__init__(self) | 57 gnt.Tree.__init__(self) |
58 gnt.set_flag(self, 8) # remove borders | |
59 self.connect('key_pressed', self.do_key_pressed) | |
49 | 60 |
50 def set_active(self, active): | 61 def set_active(self, active): |
51 if self.active == active: | 62 if self.active == active: |
52 return | 63 return |
53 if self.active: | 64 if self.active: |
55 old = self.active | 66 old = self.active |
56 self.active = active | 67 self.active = active |
57 self.set_row_flags(self.active, gnt.TEXT_FLAG_UNDERLINE) | 68 self.set_row_flags(self.active, gnt.TEXT_FLAG_UNDERLINE) |
58 self.emit('active_changed', old) | 69 self.emit('active_changed', old) |
59 | 70 |
60 def do_key_pressed(self, text): | 71 def do_key_pressed(self, null, text): |
61 if text == '\r': | 72 if text == '\r': |
62 now = self.get_selection_data() | 73 now = self.get_selection_data() |
63 self.set_active(now) | 74 self.set_active(now) |
64 return True | 75 return True |
65 return False | 76 return False |
121 | 132 |
122 #### | 133 #### |
123 # [[[ The list of feeds | 134 # [[[ The list of feeds |
124 ### | 135 ### |
125 | 136 |
137 # 'Add Feed' dialog | |
138 add_feed_win = None | |
139 def add_feed_win_closed(win): | |
140 global add_feed_win | |
141 add_feed_win = None | |
142 | |
143 def add_new_feed(): | |
144 global add_feed_win | |
145 | |
146 if add_feed_win: | |
147 gnt.gnt_window_present(add_feed_win) | |
148 return | |
149 win = gnt.Window() | |
150 win.set_title("New Feed") | |
151 | |
152 box = gnt.Box(False, False) | |
153 label = gnt.Label("Link") | |
154 box.add_widget(label) | |
155 entry = gnt.Entry("") | |
156 entry.set_size(40, 1) | |
157 box.add_widget(entry) | |
158 | |
159 win.add_widget(box) | |
160 win.show() | |
161 add_feed_win = win | |
162 add_feed_win.connect("destroy", add_feed_win_closed) | |
163 | |
126 # | 164 # |
127 # The active row in the feed-list has changed. Update the feed-item table. | 165 # The active row in the feed-list has changed. Update the feed-item table. |
128 def feed_active_changed(tree, old): | 166 def feed_active_changed(tree, old): |
129 items.remove_all() | 167 items.remove_all() |
130 if not tree.active: | 168 if not tree.active: |
131 return | 169 return |
170 update_items_title() | |
132 for item in tree.active.items: | 171 for item in tree.active.items: |
133 add_feed_item(item) | 172 add_feed_item(item) |
134 | 173 |
135 # | 174 # |
136 # Check for the action keys and decide how to deal with them. | 175 # Check for the action keys and decide how to deal with them. |
137 def feed_key_pressed(tree, text): | 176 def feed_key_pressed(tree, text): |
177 if tree.is_searching(): | |
178 return | |
138 if text == 'r': | 179 if text == 'r': |
139 feed = tree.get_selection_data() | 180 feed = tree.get_selection_data() |
140 tree.perform_action_key('j') | 181 tree.perform_action_key('j') |
141 #tree.perform_action('move-down') | 182 #tree.perform_action('move-down') |
142 feed.refresh() | 183 feed.refresh() |
143 elif text == 'R': | 184 elif text == 'R': |
144 feeds = tree.get_rows() | 185 feeds = tree.get_rows() |
145 for feed in feeds: | 186 for feed in feeds: |
146 feed.refresh() | 187 feed.refresh() |
188 elif text == 'a': | |
189 add_new_feed() | |
147 else: | 190 else: |
148 return False | 191 return False |
149 return True | 192 return True |
150 | 193 |
151 feeds = RssTree() | 194 feeds = RssTree() |
152 feeds.set_property('columns', 2) | 195 feeds.set_property('columns', 2) |
153 feeds.set_col_width(0, 20) | 196 feeds.set_col_width(0, 20) |
154 feeds.set_col_width(1, 4) | 197 feeds.set_col_width(1, 8) |
155 feeds.set_column_resizable(0, False) | 198 feeds.set_column_resizable(0, False) |
156 feeds.set_column_resizable(1, False) | 199 feeds.set_column_resizable(1, False) |
157 feeds.set_column_is_right_aligned(1, True) | 200 feeds.set_column_is_right_aligned(1, True) |
158 feeds.set_show_separator(False) | 201 feeds.set_show_separator(False) |
202 feeds.set_column_title(0, "Feeds") | |
203 feeds.set_show_title(True) | |
159 | 204 |
160 feeds.connect('active_changed', feed_active_changed) | 205 feeds.connect('active_changed', feed_active_changed) |
161 feeds.connect('key_pressed', feed_key_pressed) | 206 feeds.connect('key_pressed', feed_key_pressed) |
207 gnt.unset_flag(feeds, 256) # Fix the width | |
162 | 208 |
163 #### | 209 #### |
164 # ]]] The list of feeds | 210 # ]]] The list of feeds |
165 ### | 211 ### |
166 | 212 |
175 details.clear() | 221 details.clear() |
176 if not tree.active: | 222 if not tree.active: |
177 return | 223 return |
178 item = tree.active | 224 item = tree.active |
179 details.append_text_with_flags(str(item.title) + "\n", gnt.TEXT_FLAG_BOLD) | 225 details.append_text_with_flags(str(item.title) + "\n", gnt.TEXT_FLAG_BOLD) |
180 details.append_text_with_flags(str(item.summary), gnt.TEXT_FLAG_NORMAL) | 226 details.append_text_with_flags("Link: ", gnt.TEXT_FLAG_BOLD) |
181 details.scroll(0) | 227 details.append_text_with_flags(str(item.link) + "\n", gnt.TEXT_FLAG_UNDERLINE) |
182 if item.unread: | 228 details.append_text_with_flags("Date: ", gnt.TEXT_FLAG_BOLD) |
183 item.set_property('unread', False) | 229 details.append_text_with_flags(str(item.date) + "\n", gnt.TEXT_FLAG_NORMAL) |
184 if old and old.unread: | 230 |
185 old.set_property('unread', True) | 231 details.append_text_with_flags("\n" + str(item.summary), gnt.TEXT_FLAG_NORMAL) |
232 item.mark_unread(False) | |
233 | |
234 if old and old.unread: # If the last selected item is marked 'unread', then make sure it's bold | |
235 items.set_row_flags(old, gnt.TEXT_FLAG_BOLD) | |
186 | 236 |
187 # | 237 # |
188 # Look for action keys in the feed-item list. | 238 # Look for action keys in the feed-item list. |
189 def item_key_pressed(tree, text): | 239 def item_key_pressed(tree, text): |
240 if tree.is_searching(): | |
241 return | |
190 current = tree.get_selection_data() | 242 current = tree.get_selection_data() |
191 if text == 'M': # Mark all of the items 'read' | 243 if text == 'M': # Mark all of the items 'read' |
192 all = tree.get_rows() | 244 all = tree.get_rows() |
193 for item in all: | 245 for item in all: |
194 item.unread = False | 246 item.mark_unread(False) |
195 elif text == 'm': # Mark the current item 'read' | 247 elif text == 'm': # Mark the current item 'read' |
196 if current.unread: | 248 current.mark_unread(False) |
197 current.set_property('unread', False) | |
198 tree.perform_action_key('j') | 249 tree.perform_action_key('j') |
199 elif text == 'U': # Mark the current item 'unread' | 250 elif text == 'U': # Mark the current item 'unread' |
200 if not current.unread: | 251 current.mark_unread(True) |
201 current.set_property('unread', True) | |
202 elif text == 'd': | 252 elif text == 'd': |
203 current.remove() | 253 current.remove() |
204 tree.perform_action_key('j') | 254 tree.perform_action_key('j') |
205 else: | 255 else: |
206 return False | 256 return False |
207 return True | 257 return True |
208 | 258 |
209 items = RssTree() | 259 items = RssTree() |
210 items.set_property('columns', 1) | 260 items.set_property('columns', 1) |
211 items.set_col_width(0, 40) | 261 items.set_col_width(0, 40) |
262 items.set_column_title(0, "Items") | |
263 items.set_show_title(True) | |
212 items.connect('key_pressed', item_key_pressed) | 264 items.connect('key_pressed', item_key_pressed) |
213 items.connect('active_changed', item_active_changed) | 265 items.connect('active_changed', item_active_changed) |
214 | 266 |
267 size = gnt.screen_size() | |
268 items.set_size(size[0], size[1]) | |
269 | |
215 #### | 270 #### |
216 # ]]] The list of items in the feed | 271 # ]]] The list of items in the feed |
217 #### | 272 #### |
218 | 273 |
274 # | |
275 # Update the title of the items list depending on the selection in the feed list | |
276 def update_items_title(): | |
277 feed = feeds.active | |
278 if feed: | |
279 items.set_column_title(0, str(feed.title) + ": " + str(feed.unread) + "(" + str(len(feed.items)) + ")") | |
280 else: | |
281 items.set_column_title(0, "Items") | |
282 items.draw() | |
283 | |
219 # The container on the top | 284 # The container on the top |
285 line = gnt.Line(vertical = False) | |
286 | |
287 # The textview to show the details of a feed | |
288 details = gnt.TextView() | |
289 details.set_take_focus(True) | |
290 details.set_flag(gnt.TEXT_VIEW_TOP_ALIGN) | |
291 details.attach_scroll_widget(details) | |
292 | |
293 # Category tree | |
294 cat = gnt.Tree() | |
295 cat.set_property('columns', 1) | |
296 cat.set_column_title(0, 'Category') | |
297 cat.set_show_title(True) | |
298 gnt.set_flag(cat, 8) # remove borders | |
299 | |
220 box = gnt.Box(homo = False, vert = False) | 300 box = gnt.Box(homo = False, vert = False) |
221 box.set_pad(0) | 301 box.set_pad(0) |
222 box.add_widget(feeds) | 302 |
223 box.add_widget(items) | 303 vbox = gnt.Box(homo = False, vert = True) |
304 vbox.set_pad(0) | |
305 vbox.add_widget(feeds) | |
306 vbox.add_widget(gnt.Line(False)) | |
307 vbox.add_widget(cat) | |
308 box.add_widget(vbox) | |
309 | |
310 box.add_widget(gnt.Line(True)) | |
311 | |
312 vbox = gnt.Box(homo = False, vert = True) | |
313 vbox.set_pad(0) | |
314 vbox.add_widget(items) | |
315 vbox.add_widget(gnt.Line(False)) | |
316 vbox.add_widget(details) | |
317 box.add_widget(vbox) | |
224 | 318 |
225 win.add_widget(box) | 319 win.add_widget(box) |
226 | |
227 line = gnt.Line(vertical = False) | |
228 win.add_widget(line) | |
229 | |
230 # The textview to show the details of a feed | |
231 details = gnt.TextView() | |
232 | |
233 win.add_widget(details) | |
234 | |
235 browser = gnt.Button("Open in Browser") | |
236 win.add_widget(browser) | |
237 details.attach_scroll_widget(browser) | |
238 | |
239 win.show() | 320 win.show() |
240 | 321 |
241 def update_feed_title(feed, property): | 322 def update_feed_title(feed, property): |
242 if property.name == 'title': | 323 if property.name == 'title': |
243 feeds.change_text(feed, 0, feed.title) | 324 feeds.change_text(feed, 0, feed.title) |
244 elif property.name == 'unread': | 325 elif property.name == 'unread': |
245 feeds.change_text(feed, 1, str(feed.unread)) | 326 feeds.change_text(feed, 1, str(feed.unread) + "(" + str(len(feed.items)) + ")") |
327 if feeds.active == feed: | |
328 update_items_title() | |
246 | 329 |
247 # populate everything | 330 # populate everything |
248 for feed in gntrss.feeds: | 331 for feed in gntrss.feeds: |
249 feed.refresh() | 332 feed.refresh() |
250 add_feed(feed) | 333 add_feed(feed) |