From 2d8ab5e997593a65db83f64e5e22ca9dd119675a Mon Sep 17 00:00:00 2001 From: DrFrasierCrane Date: Sat, 1 Dec 2007 13:31:09 +0100 Subject: [PATCH] Intermediate work commit. --- data/preferences.glade | 645 +++++++++++++++-------------- data/sql/create_01.sql | 2 + data/subscribe.glade | 407 ++++++++++-------- straw/Application.py | 5 +- straw/{FeedUpdater.py => FeedDiscovery.py} | 61 +-- straw/FeedListView.py | 11 +- straw/FeedUpdater.py | 7 + straw/ImageCache.py | 9 +- straw/ItemView.py | 3 +- straw/SummaryParser.py | 31 +- straw/feedproperties.py | 23 +- straw/subscribe.py | 131 ++++-- 12 files changed, 742 insertions(+), 593 deletions(-) copy straw/{FeedUpdater.py => FeedDiscovery.py} (54%) diff --git a/data/preferences.glade b/data/preferences.glade index 45058cc..b54b49c 100644 --- a/data/preferences.glade +++ b/data/preferences.glade @@ -11,392 +11,415 @@ straw.png - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 + 8 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8 + 12 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 + 8 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 + 12 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - <b>Storage</b> - True - - - - - True - 2 - 2 - 6 - 6 - - - True - True - 100 0 1000 1 10 10 - 1 - - - - 1 - 2 - - - - - - True - True - 30 0 10000 1 10 10 - 1 - True - - - - 1 - 2 - 1 - 2 - GTK_FILL - - - + 6 - + True - 1 - _Number of articles per feed: - True - True - number_of_items_spin + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Storage</b> + True - - 1 - 2 - GTK_FILL - - - + True - 1 - _Refresh frequency: - True + 2 + 2 + 12 + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + 0 + + + True + True + 1 + _Refresh frequency: + True + True + True + + + + + GTK_FILL + GTK_FILL + 12 + + + + + True + True + 100 0 1000 1 10 10 + 1 + + + + 1 + 2 + + + + + + + True + True + 30 0 10000 1 10 10 + 1 + True + + + + 1 + 2 + 1 + 2 + + + + + + + True + 1 + _Number of articles per feed: + True + True + number_of_items_spin + + + 1 + 2 + GTK_FILL + GTK_FILL + 12 + + - GTK_FILL - + False + False + 1 False False - 1 - - - False - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - <b>Viewing</b> - True - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 2 - 2 - 6 - 6 + 6 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 + 0 + <b>Viewing</b> + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 2 + 2 + 6 + 6 - + True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - True - True - + 6 - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 + 0 + True + True + - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - vertical.png + 3 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-missing-image + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + (on top) + + + False + False + 1 + + + + + False + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + True + True + vertical_layout + - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - (on top) + 3 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-missing-image + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + (on the right) + + + False + False + 1 + + - - False - False - 1 - + + False + 1 + - False + 1 + 2 + 1 + 2 - + True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - True - True - vertical_layout - + 6 - + True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 3 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - horizontal.png - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - (on the right) - - - False - False - 1 - - + True + _top of the list + True + 0 + True + True + + + False + False + + + + + True + True + _bottom of the list + True + 0 + True + item_order_newest + + + + False + False + 1 + - False - 1 + 1 + 2 - - - 1 - 2 - 1 - 2 - - - - - True - 6 - + True - True - _top of the list + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0.20000000298023224 + _Item list layout : True - 0 - True - True - - False - False + 1 + 2 + GTK_FILL + - + True - True - _bottom of the list + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 1 + 0.20000000298023224 + _Location of new items : True - 0 - True - item_order_newest - - False - False - 1 + GTK_FILL + - 1 - 2 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 0.20000000298023224 - _Item list layout : - True - - - 1 - 2 - GTK_FILL - - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 1 - 0.20000000298023224 - _Location of new items : - True - - - GTK_FILL - + 1 + False + False 1 - - - False - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - <b>Web Browser</b> - True - - - False - False - 2 - - - - - True - 2 - + True - 7 - 6 - - - True - True - _Override preferred browser setting: - True - 0 - True - - - - False - False - - - - - True - False - True - * - - - - - 1 - - + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Web Browser</b> + True + + False + False + 2 + - + True + 2 - + True + 7 + 6 + + + True + True + _Override preferred browser setting: + True + 0 + True + + + + False + False + + + + + True + False + True + + + + + 1 + + - - False - - + True - 1 - <small><i>(example: <b>epiphany %s</b>)</i></small> - True - True + + + True + + + False + + + + + True + 1 + <small><i>(example: <b>epiphany %s</b>)</i></small> + True + True + + + 1 + + 1 @@ -404,51 +427,59 @@ - 1 + False + 3 - - False - 3 - + + 8 + - - - 8 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - GTK_BUTTONBOX_END - + True - True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-close - True - 0 - + 6 + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-close + True + 0 + + + + + False + False + 8 + 1 + - False - False 8 - 1 + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + page 1 + - 8 + tab + False diff --git a/data/sql/create_01.sql b/data/sql/create_01.sql index 500b8e4..6255f7d 100644 --- a/data/sql/create_01.sql +++ b/data/sql/create_01.sql @@ -28,4 +28,6 @@ CREATE TABLE IF NOT EXISTS treeview_nodes ( type VARCHAR(1) NOT NULL ); -- +CREATE INDEX idx_items_feed_id ON items(feed_id); +-- INSERT INTO categories (parent_id, title) VALUES (NULL, 'root'); \ No newline at end of file diff --git a/data/subscribe.glade b/data/subscribe.glade index e968a1f..a2ed87f 100644 --- a/data/subscribe.glade +++ b/data/subscribe.glade @@ -2,265 +2,340 @@ - + + 350 + 400 + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - Straw - Subscribe to Feed - 420 - 180 - True + 5 + GTK_WIN_POS_CENTER_ON_PARENT GDK_WINDOW_TYPE_HINT_DIALOG - - + False + + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + False + False - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 12 + 8 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8 + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Location</b> + True + True + + - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - + + 75 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK 0 - Feed _Location: + _URL: True + + False + 12 + True True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + http:// + + + 1 + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 8 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-dialog-error + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + False 1 + + + False + 6 + 2 + + + + + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 6 + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + 0 + <b>Authentication</b> + True + True + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8 - + + 75 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-dialog-error + 0 + Username: False + 12 - + True + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - False 1 - False 6 - 2 - - - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - + True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8 - + + 75 True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 8 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - If the feed requires authentication, please enter them below. - True - PANGO_WRAP_WORD_CHAR - PANGO_ELLIPSIZE_MIDDLE - 20 - - - False - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - _Username: - True - - - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - - - False - 1 - - - - - False - 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 0 - _Password: - True - - - False - - - - - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - True - - - 1 - - - - - False - 2 - - + 0 + Password: + + False + 12 + + + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + 1 + - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - _Username & Password - True - label_item + 1 - False 1 - - - - - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - 6 - GTK_BUTTONBOX_END - - - True - True - True - GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-close - True - 0 - - - - + True - True - True - True - True GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK - gtk-ok - True - 0 - + + + 50 + False + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + True + 0.05000000074505806 + + + - 1 + 2 False + 18 1 - 8 + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + page 1 + + + tab + False + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + True + + + 7 + + + + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + page 2 + + + tab + 1 + False + + + + + 1 + + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_BUTTONBOX_END + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-close + True + 0 + + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-go-forward + True + 0 + + + + 1 + + + + + True + True + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gtk-apply + True + 0 + + + + 2 - 8 + False + GTK_PACK_END diff --git a/straw/Application.py b/straw/Application.py index aef80c2..3e895d5 100644 --- a/straw/Application.py +++ b/straw/Application.py @@ -728,6 +728,9 @@ class Application: #ImageCache.initialize() + #import feedfinder + #print feedfinder.feeds("http://eclipse.org", True) + xml = gtk.glade.XML(os.path.join(straw.STRAW_DATA_DIR,'straw.glade'), "straw_main", gettext.textdomain()) window = xml.get_widget('straw_main') self._main_presenter = ApplicationPresenter(view = ApplicationView(window)) @@ -745,7 +748,6 @@ class Application: gtk.gdk.threads_enter() gtk.main() gtk.gdk.threads_leave() - return def _update(self,flist): uritems = urfeeds = 0 @@ -763,7 +765,6 @@ class Application: self.tray.hide() return - def _tray_clicked(self, widget, event=None): self._main_presenter.view.should_present() if event and not (event.button == 1): diff --git a/straw/FeedUpdater.py b/straw/FeedDiscovery.py similarity index 54% copy from straw/FeedUpdater.py copy to straw/FeedDiscovery.py index 1836a82..3531665 100644 --- a/straw/FeedUpdater.py +++ b/straw/FeedDiscovery.py @@ -1,4 +1,4 @@ -""" FeedUpdater.py +""" """ @@ -20,23 +20,21 @@ Place - Suite 330, Boston, MA 02111-1307, USA. """ from straw.JobManager import Job, TaskResult, TaskThread, TaskInfo, ThreadPoolJobHandler import time from threading import Lock +import feedfinder -class FeedUpdateJobHandler(ThreadPoolJobHandler): - job_id = "feed-update" +class FeedDiscoveryJobHandler(ThreadPoolJobHandler): + job_id = "feed-discovery" def __init__(self, job): ThreadPoolJobHandler.__init__(self, job) - self.pool_size = 3 - self.result_class = FeedUpdateTaskResult - self.task_class = FeedUpdateTaskThread + self.pool_size = 1 + self.result_class = FeedDiscoveryTaskResult + self.task_class = FeedDiscoveryTaskThread def _split(self): - i = 0 - for a in self.job.data: - i += 1 - ti = TaskInfo(i, { "feed" : a }) - self.task_queue.put(ti) + ti = TaskInfo(1, { "url" : self.job.data }) + self.task_queue.put(ti) def _prepare_result(self): list = [] @@ -46,7 +44,7 @@ class FeedUpdateJobHandler(ThreadPoolJobHandler): return list -class FeedUpdateTaskResult(TaskResult): +class FeedDiscoveryTaskResult(TaskResult): def __init__(self, task_info, result): self.task_info = task_info self.result = result @@ -54,45 +52,22 @@ class FeedUpdateTaskResult(TaskResult): def get(self): raise NotImplementedError -class FeedUpdateTaskThread(TaskThread): +class FeedDiscoveryTaskThread(TaskThread): def __init__(self, handler, task_queue, result_queue): TaskThread.__init__(self, handler, task_queue, result_queue) def _process(self, task): - import httplib2 - feed = task.data["feed"] - - import os - from straw import Config - CACHE_DIR = os.path.join(Config.straw_home(), 'cache') - h = httplib2.Http(CACHE_DIR) - #httplib2.debuglevel=4 - url = feed.location#feed.location - resp, content = h.request(url, "GET") - parsed = None - - print resp.status - - if not resp.fromcache: - import SummaryParser - parsed = SummaryParser.parse(content, feed) - else: - print "304: %s" % url + url = task.data["url"] - return parsed + import feedfinder + return feedfinder.feeds(url, True) import straw.JobManager as JobManager -JobManager.register_handler(FeedUpdateJobHandler) - -def update_urls(urls, observers): - update = Job("feed-update") - update.data = urls - update.observers = observers - JobManager.start_job(update, True) +JobManager.register_handler(FeedDiscoveryJobHandler) -def update_feeds(feeds, observers): - update = Job("feed-update") - update.data = feeds +def discover(url, observers): + update = Job("feed-discovery") + update.data = url update.observers = observers JobManager.start_job(update) diff --git a/straw/FeedListView.py b/straw/FeedListView.py index e21ee32..f8e14b6 100644 --- a/straw/FeedListView.py +++ b/straw/FeedListView.py @@ -419,8 +419,8 @@ class FeedsView(MVP.WidgetView): (model, pathlist) = selection.get_selected_rows() iters = [model.get_iter(path) for path in pathlist] path = pathlist.pop() - node_adapter = self.model.model[path][Column.object] - self._presenter.show_feed_information(node_adapter.feed) + node = self.model.model[path][Column.object] + self._presenter.show_feed_information(node) return def select_first_feed(self): @@ -570,12 +570,5 @@ class FeedsPresenter(MVP.BasicPresenter): elif fb is not None: retval = 1 return retval - #def sort_category(self, reverse=False): - # self._curr_category.sort() - # if reverse: - # self._curr_category.reverse() - # return - def show_feed_information(self, feed): straw.feed_properties_show(feed) - return diff --git a/straw/FeedUpdater.py b/straw/FeedUpdater.py index 1836a82..ada94ba 100644 --- a/straw/FeedUpdater.py +++ b/straw/FeedUpdater.py @@ -76,6 +76,13 @@ class FeedUpdateTaskThread(TaskThread): if not resp.fromcache: import SummaryParser parsed = SummaryParser.parse(content, feed) + i = 0 + for image in sum([item.images for item in parsed.items], []): + resp, content = h.request(image, "GET") + i = i + 1 + f = open("/home/ppawel/Desktop/test/%s" % i, "w") + f.write(content) + f.close() else: print "304: %s" % url diff --git a/straw/ImageCache.py b/straw/ImageCache.py index 0776ce2..f8cb3ef 100644 --- a/straw/ImageCache.py +++ b/straw/ImageCache.py @@ -75,7 +75,8 @@ class CacheEntry(object): self._pollstopper = None def _save_count(self): - ItemStore.get_instance().set_image_count(self._image.url, self._count) + pass + #ItemStore.get_instance().set_image_count(self._image.url, self._count) class Cache(gobject.GObject): @@ -92,6 +93,8 @@ class Cache(gobject.GObject): self.__cache = dict() def __getitem__(self, key): + print "got getitem for %s" % key + print "cache is %s" % self.__cache return self.__cache[key].image def add_refer(self, key, restore = False, item = None): @@ -109,8 +112,8 @@ class Cache(gobject.GObject): key, ic, priority=NetworkConstants.PRIORITY_IMAGE, headers=headers) - except URLFetch.RequestSchemeException, e: - ic.http_failed(e) + #except URLFetch.RequestSchemeException, e: + # ic.http_failed(e) except Exception, e: error.logtb("ImageCache.add_refer: ", str(e)) ic.http_failed(e) diff --git a/straw/ItemView.py b/straw/ItemView.py index 13eeeec..4908dd0 100644 --- a/straw/ItemView.py +++ b/straw/ItemView.py @@ -233,7 +233,8 @@ class HTMLPresenter(MVP.BasicPresenter): image = ImageCache.cache[url] stream.write(image.get_data()) except Exception, ex: - error.log("Error reading image in %s: %s" % (url, ex)) + #error.log("Error reading image in %s: %s" % (url, ex)) + pass finally: stream.close() stream = None diff --git a/straw/SummaryParser.py b/straw/SummaryParser.py index 64d9c9c..bb77f12 100644 --- a/straw/SummaryParser.py +++ b/straw/SummaryParser.py @@ -38,8 +38,8 @@ from straw import helpers class TitleImgParser(HTMLParser.HTMLParser): def __init__(self, feed=None): HTMLParser.HTMLParser.__init__(self) - self._chars = list() - self._image_urls = list() + self._chars = [] + self._image_urls = [] self._feed = feed def set_feed(self, feed): @@ -60,7 +60,7 @@ class TitleImgParser(HTMLParser.HTMLParser): def flush(self): del self._chars[:] - del self._image_urls[:] + #del self._image_urls[:] def handle_starttag(self, tag, attrs): if tag == 'img': @@ -149,24 +149,14 @@ def parse(content, feed): parsed = ParsedSummary.ParsedSummary() parsed_content, encoding = feedparser_parse(content) parsed = parse_channel_info(parsed, parsed_content, encoding) - - for entry in parsed_content.entries: - item = _parse_entry(entry, feed) - parsed.addItem(item) - _remove_ids_if_duplicates(parsed.items) - return parsed -def parse_url(url, feed): - parsed = ParsedSummary.ParsedSummary() - parsed_content, encoding = feedparser_parse(url) - parsed = parse_channel_info(parsed, parsed_content, encoding) - #print "bla = " + str(parsed_content.entries) for entry in parsed_content.entries: item = _parse_entry(entry, feed) parsed.addItem(item) + _remove_ids_if_duplicates(parsed.items) - return parsed + return parsed def sanitize_content(data, feed, limit=60): images = None @@ -175,18 +165,22 @@ def sanitize_content(data, feed, limit=60): tp = TitleImgParser(feed) try: tp.feed(data) - images = [image for image in tp.get_image_urls()] + #images = [image for image in tp.get_image_urls()] + #print tp.get_image_urls() + images = tp.get_image_urls() title = tp.get_text(limit) except Exception, ex: error.log(ex) finally: tp.close() + #print images return (title, images) def _parse_entry(entry, feed): from model import Item item = Item()#SummaryItem.SummaryItem() item.feed = feed + item.images = [] content = [] description = "" title = ""#_("No title") @@ -208,8 +202,9 @@ def _parse_entry(entry, feed): title = entry.get('title', '') if description: - #alttitle, images = sanitize_content(description, feed) - #[item.add_image(image) for image in images] + alttitle, item.images = sanitize_content(description, feed) + #import ImageCache + #[ImageCache.cache.add_refer(image, False, item) for image in images] if not title: pass # get the first MAXSPLIT words of the description and make that as our diff --git a/straw/feedproperties.py b/straw/feedproperties.py index 146efe0..fe618da 100644 --- a/straw/feedproperties.py +++ b/straw/feedproperties.py @@ -79,7 +79,7 @@ class FeedPropertyView(MVP.GladeView): self._categories_treeview.append_column(column) def set_feed(self, feed): - self._feed = feed + self._feed = feed.obj def member_toggled(self, cell, path): model = self._categories_treeview.get_model() @@ -111,8 +111,8 @@ class FeedPropertyView(MVP.GladeView): return def display_properties(self): - self._defaults['title'] = self._feed.title - loc, un, pw = self._feed.access_info + """self._defaults['title'] = self._feed.title + loc, un, pw = "", "", ""#self._feed.access_info self._defaults['url'] = loc self._defaults['username'] = un self._defaults['password'] = pw @@ -170,19 +170,21 @@ class FeedPropertyView(MVP.GladeView): helpers.format_date(time.gmtime(next))) self._next_refresh_label.show() else: - self._next_refresh_label.hide() + self._next_refresh_label.hide()""" self._display_feed_information(self._feed) self._restore_button.set_sensitive(False) def _display_feed_information(self, feed): - title = helpers.convert_entities(feed.channel_title) - if len(title) == 0: - title = feed.title or feed.channel_link - title = title.strip() + #title = helpers.convert_entities(feed.channel_title) + #if len(title) == 0: + # title = feed.title or feed.channel_link + #title = title.strip() - link = feed.channel_link.strip() + #link = feed.channel_link.strip() + link = None if not link: link = feed.location + print "link = %s" % link if link: link_button = gtk.LinkButton(link, link) @@ -374,6 +376,7 @@ def feed_properties_show(feed): del self.hash[feed] dialog = dialogs.get(feed, None) + if not dialog: gladefile = XML(os.path.join(straw.STRAW_DATA_DIR, "feed-properties.glade")) #idget_tree = gladefile.get_widget_tree('feed_properties') @@ -381,8 +384,8 @@ def feed_properties_show(feed): dialog.set_feed(feed) dialog.set_deleter(_dialogdeleter(feed, dialogs)) dialogs[feed] = dialog + dialog.view.show() - return def read_text(fragment, chars): """Read chars cdata characters from html fragment fragment""" diff --git a/straw/subscribe.py b/straw/subscribe.py index 60fb624..acbf570 100644 --- a/straw/subscribe.py +++ b/straw/subscribe.py @@ -19,40 +19,46 @@ this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """ -import os, os.path -import urlparse -import urllib -import pygtk -pygtk.require('2.0') -import gtk from gtk.glade import XML -import gettext -import error -import SummaryParser +from straw import helpers +import Config +import MVP import ParsedSummary +import SummaryParser +import error +import gettext +import gobject +import gtk +import os, os.path +import pygtk +import straw import time -import URLFetch -import MVP -import Config +import urllib +import urlparse +pygtk.require('2.0') -import straw -from straw import helpers +STATE_INTRO = 1 +STATE_FINISH = 2 class SubscribeView(MVP.GladeView): def _initialize(self): self._window = self._widget.get_widget('subscribe_dialog') + self._button1 = self._widget.get_widget('button1') + self._button2 = self._widget.get_widget('button2') + self._button3 = self._widget.get_widget('button3') + self._progress_bar = self._widget.get_widget('progress_bar') + self._notebook = self._widget.get_widget('notebook') self._location_entry = self._widget.get_widget('feed_location_entry') self._username_entry = self._widget.get_widget('username_entry') self._password_entry = self._widget.get_widget('password_entry') self._error_text = self._widget.get_widget('error_text') self._error_box = self._widget.get_widget('error_box') - self._location_entry.grab_focus() - def _on_ok_clicked(self, *args): + def _on_forward(self): location = self._location_entry.get_text() if not location: self.display_error(_("Feed Location must not be empty")) - return + return False username = self._username_entry.get_text() username = username.strip() password = self._password_entry.get_text() @@ -64,20 +70,42 @@ class SubscribeView(MVP.GladeView): response = helpers.report_offline_status(self._window) if response == gtk.RESPONSE_CANCEL: self.show() - return + return False config.offline = not config.offline - self._presenter.subscribe(location, username, password) - self._window.hide() - def _clear_entries(self): - self._location_entry.delete_text(0,-1) + import FeedDiscovery + FeedDiscovery.discover(location, { "job-done": [ self._discovery_finished ] }) + + #self._presenter.subscribe(location, username, password) + return True + + def progress_pulse(self, obj): + self._progress_bar.pulse() + return True + + def progress_destroy(self): + if self.timer != 0: + gobject.source_remove(self.timer) + self.timer = 0 + + def _setup_entries(self): + self._location_entry.set_text("http://") self._username_entry.delete_text(0,-1) self._password_entry.delete_text(0,-1) + self._location_entry.grab_focus() + def show(self): - self._clear_entries() + self.state = STATE_INTRO + self.set_state(gtk.STOCK_CLOSE, gtk.STOCK_GO_FORWARD, None) + self.timer = 0 + + self._setup_entries() self._error_box.set_property('visible',False) + self._notebook.set_current_page(0) self._window.show() + import threading + print threading.currentThread() def display_error(self, text): self._error_box.set_property('visible',True) @@ -89,9 +117,54 @@ class SubscribeView(MVP.GladeView): def set_parent(self, parent): self._window.set_transient_for(parent) - def _on_close_clicked(self, *args): + def _on_button1_clicked(self, *args): + self.progress_destroy() self._window.hide() + def _on_button2_clicked(self, *args): + if self.state == STATE_INTRO: + if self._on_forward(): + self._progress_bar.props.visible = True + self.timer = gobject.timeout_add(100, self.progress_pulse, self) + self._button2.set_sensitive(False) + elif self.state == STATE_FINISH: + self.state = STATE_INTRO + self.set_state(gtk.STOCK_CLOSE, gtk.STOCK_GO_FORWARD, None) + self._notebook.set_current_page(0) + + def _on_button3_clicked(self, *args): + if self.state == STATE_FINISH: + pass + + def _discovery_finished(self, handler, data): + gtk.threads_enter() + self._progress_bar.props.visible = False + self._button2.set_sensitive(True) + self.progress_destroy() + self.state = STATE_FINISH + self.set_state(gtk.STOCK_CLOSE, gtk.STOCK_GO_BACK, gtk.STOCK_APPLY) + self._notebook.set_current_page(1) + gtk.threads_leave() + + def set_state(self, b1, b2, b3): + if b1 == None: + self._button1.hide() + else: + self._button1.set_label(b1) + self._button1.show() + + if b2 == None: + self._button2.hide() + else: + self._button2.set_label(b2) + self._button2.show() + + if b3 == None: + self._button3.hide() + else: + self._button3.set_label(b3) + self._button3.show() + def _on_feed_location_entry_key_press_event(self, widget, event): if event.keyval == gtk.keysyms.Return: self._presenter.subscribe(self._location_entry.get_text()) @@ -126,15 +199,6 @@ class SubscribePresenter(MVP.BasicPresenter): feed.title = location FeedManager.save_feed(feed) - """ - consumer = SubscribeConsumer(self) - - try: - URLFetch.get_instance().request(location, consumer, - user=username, password=password) - except Exception, e: - consumer.http_failed(e)""" - def set_parent(self, parent): self.view.set_parent(parent) @@ -180,7 +244,6 @@ class SubscribeConsumer: feed.access_info = (url, user, password) feed.last_poll = int(time.time()) fclist = feeds.category_list - print feed fclist.append_feed(feed) feed.router.route_all(parsed) feed.poll_done() -- 2.11.4.GIT