Merge branch 'master' of https://git.maemo.org/projects/feedingit
[feedingit] / src / FeedingIt.py
index 3fcf18a..a48251f 100644 (file)
@@ -42,10 +42,10 @@ from aboutdialog import HeAboutDialog
 from portrait import FremantleRotation
 from threading import Thread, activeCount
 from feedingitdbus import ServerObject
-from updatedbus import UpdateServerObject, get_lock
 from config import Config
 from cgi import escape
 import weakref
+import dbus
 import debugging
 import logging
 logger = logging.getLogger(__name__)
@@ -54,7 +54,6 @@ from rss_sqlite import Listing
 from opml import GetOpmlData, ExportOpmlData
 
 import mainthread
-from jobmanager import JobManager
 
 from socket import setdefaulttimeout
 timeout = 5
@@ -283,10 +282,6 @@ class DownloadBar(gtk.ProgressBar):
         if hasattr (cls, 'class_init_done'):
             return
 
-        jm = JobManager ()
-        jm.stats_hook_register (cls.update_progress,
-                                run_in_main_thread=True)
-
         cls.downloadbars = []
         # Total number of jobs we are monitoring.
         cls.total = 0
@@ -297,6 +292,13 @@ class DownloadBar(gtk.ProgressBar):
 
         cls.class_init_done = True
 
+        bus = dbus.SessionBus()
+        bus.add_signal_receiver(handler_function=cls.update_progress,
+                                bus_name=None,
+                                signal_name='UpdateProgress',
+                                dbus_interface='org.marcoz.feedingit',
+                                path='/org/marcoz/feedingit/update')
+
     def __init__(self, parent):
         self.class_init ()
 
@@ -309,43 +311,43 @@ class DownloadBar(gtk.ProgressBar):
 
     @classmethod
     def downloading(cls):
-        return hasattr (cls, 'jobs_at_start')
+        cls.class_init ()
+        return cls.done != cls.total
 
     @classmethod
-    def update_progress(cls, jm, old_stats, new_stats, updated_feed):
-        if not cls.downloading():
-            cls.jobs_at_start = old_stats['jobs-completed']
-
+    def update_progress(cls, percent_complete,
+                        completed, in_progress, queued,
+                        bytes_downloaded, bytes_updated, bytes_per_second,
+                        feed_updated):
         if not cls.downloadbars:
             return
 
-        if new_stats['jobs-in-progress'] + new_stats['jobs-queued'] == 0:
-            del cls.jobs_at_start
+        cls.total = completed + in_progress + queued
+        cls.done = completed
+        cls.progress = percent_complete / 100.
+        if cls.progress < 0: cls.progress = 0
+        if cls.progress > 1: cls.progress = 1
+
+        if feed_updated:
             for ref in cls.downloadbars:
                 bar = ref ()
                 if bar is None:
                     # The download bar disappeared.
                     cls.downloadbars.remove (ref)
                 else:
-                    bar.emit("download-done", None)
-            return
+                    bar.emit("download-done", feed_updated)
 
-        # This should never be called if new_stats['jobs'] is 0, but
-        # just in case...
-        cls.total = max (1, new_stats['jobs'] - cls.jobs_at_start)
-        cls.done = new_stats['jobs-completed'] - cls.jobs_at_start
-        cls.progress = 1 - (new_stats['jobs-in-progress'] / 2.
-                            + new_stats['jobs-queued']) / cls.total
-        cls.update_bars()
-
-        if updated_feed:
+        if in_progress == 0 and queued == 0:
             for ref in cls.downloadbars:
                 bar = ref ()
                 if bar is None:
                     # The download bar disappeared.
                     cls.downloadbars.remove (ref)
                 else:
-                    bar.emit("download-done", updated_feed)
+                    bar.emit("download-done", None)
+            return
+
+        cls.update_bars()
 
     @classmethod
     def update_bars(cls):
@@ -716,7 +718,7 @@ class DisplayArticle(hildon.StackableWindow):
             iface.open_new_window(link)
 
 class DisplayFeed(hildon.StackableWindow):
-    def __init__(self, listing, feed, title, key, config, updateDbusHandler):
+    def __init__(self, listing, feed, title, key, config):
         hildon.StackableWindow.__init__(self)
         self.listing = listing
         self.feed = feed
@@ -725,7 +727,6 @@ class DisplayFeed(hildon.StackableWindow):
         self.key=key
         self.current = list()
         self.config = config
-        self.updateDbusHandler = updateDbusHandler
         
         self.downloadDialog = False
         
@@ -956,8 +957,12 @@ class DisplayFeed(hildon.StackableWindow):
         #self.feed.saveFeed(CONFIGDIR)
         self.displayFeed()
 
-    def button_update_clicked(self, button):
+
+    def do_update_feed(self):
         self.listing.updateFeed (self.key, priority=-1)
+
+    def button_update_clicked(self, button):
+        gobject.idle_add(self.do_update_feed)
             
     def show_download_bar(self):
         if not type(self.downloadDialog).__name__=="DownloadBar":
@@ -968,12 +973,13 @@ class DisplayFeed(hildon.StackableWindow):
             self.show_all()
         
     def onDownloadDone(self, widget, feed):
-        if feed == self.feed or feed is None:
-            self.downloadDialog.destroy()
-            self.downloadDialog = False
+        if feed == self.feed:
             self.feed = self.listing.getFeed(self.key)
             self.displayFeed()
-            self.updateDbusHandler.ArticleCountUpdated()
+
+        if feed is None:
+            self.downloadDialog.destroy()
+            self.downloadDialog = False
 
     def buttonReadAllClicked(self, button):
         #self.clear()
@@ -1011,32 +1017,8 @@ class FeedingIt:
         self.config = Config(self.window, CONFIGDIR+"config.ini")
         gobject.idle_add(self.createWindow)
 
-        # This is set to try when the user interacts with the program.
-        # If, after an update is complete, we discover that the
-        # environment variable DBUS_STARTED_ADDRESS is set and
-        # self.had_interaction is False, we quit.
-        self.had_interaction = False
-        
     def createWindow(self):
         self.category = 0
-        
-        self.app_lock = get_lock("app_lock")
-        if self.app_lock == None:
-            try:
-                self.stopButton.set_sensitive(True)
-            except:
-                self.stopButton = hildon.Button(gtk.HILDON_SIZE_AUTO_WIDTH | gtk.HILDON_SIZE_FINGER_HEIGHT, hildon.BUTTON_ARRANGEMENT_VERTICAL)
-                self.stopButton.set_text("Stop update","")
-                self.stopButton.connect("clicked", self.stop_running_update)
-                self.mainVbox.pack_end(self.stopButton, expand=False, fill=False)
-                self.window.show_all()
-            self.introLabel.set_label("Update in progress, please wait.")
-            gobject.timeout_add_seconds(3, self.createWindow)
-            return False
-        try:
-            self.stopButton.destroy()
-        except:
-            pass
         self.listing = Listing(self.config, CONFIGDIR)
 
         self.downloadDialog = False
@@ -1112,11 +1094,11 @@ class FeedingIt:
         hildon.hildon_gtk_window_set_progress_indicator(self.window, 0)
         gobject.idle_add(self.late_init)
         
-    def job_manager_update(self, jm, old_stats, new_stats, updated_feed):
-        if (not self.downloadDialog
-            and new_stats['jobs-in-progress'] + new_stats['jobs-queued'] > 0):
-            self.updateDbusHandler.UpdateStarted()
-
+    def update_progress(self, percent_complete,
+                        completed, in_progress, queued,
+                        bytes_downloaded, bytes_updated, bytes_per_second,
+                        updated_feed):
+        if (in_progress or queued) and not self.downloadDialog:
             self.downloadDialog = DownloadBar(self.window)
             self.downloadDialog.connect("download-done", self.onDownloadDone)
             self.mainVbox.pack_end(self.downloadDialog, expand=False, fill=False)
@@ -1130,72 +1112,17 @@ class FeedingIt:
             self.downloadDialog.destroy()
             self.downloadDialog = False
             self.displayListing()
-            self.updateDbusHandler.UpdateFinished()
-            self.updateDbusHandler.ArticleCountUpdated()
-
-        if not self.had_interaction and 'DBUS_STARTER_ADDRESS' in environ:
-            logger.info(
-                "Update complete. No interaction, started by dbus: quitting.")
-            self.quit()
-    def stop_running_update(self, button):
-        self.stopButton.set_sensitive(False)
-        import dbus
-        bus=dbus.SessionBus()
-        remote_object = bus.get_object("org.marcoz.feedingit", # Connection name
-                               "/org/marcoz/feedingit/update" # Object's path
-                              )
-        iface = dbus.Interface(remote_object, 'org.marcoz.feedingit')
-        iface.StopUpdate()
-
-    def increase_download_parallelism(self):
-        # The system has been idle for a while.  Enable parallel
-        # downloads.
-        JobManager().num_threads = 4
-        gobject.source_remove (self.increase_download_parallelism_id)
-        del self.increase_download_parallelism_id
-        return False
-
-    def system_inactivity_ind(self, idle):
-        # The system's idle state changed.
-        if (self.am_idle and idle) or (not self.am_idle and not idle):
-            # No change.
-            return
-
-        if not idle:
-            if hasattr (self, 'increase_download_parallelism_id'):
-                gobject.source_remove (self.increase_download_parallelism_id)
-                del self.increase_download_parallelism_id
-        else:
-            self.increase_download_parallelism_id = \
-                gobject.timeout_add_seconds(
-                    60, self.increase_download_parallelism)
-
-        if not idle:
-            JobManager().num_threads = 1
-
-        self.am_idle = idle
 
     def late_init(self):
         self.dbusHandler = ServerObject(self)
-        self.updateDbusHandler = UpdateServerObject(self)
-
-        jm = JobManager()
-        jm.stats_hook_register (self.job_manager_update,
-                                run_in_main_thread=True)
-        jm.num_threads = 1
-        self.am_idle = False
-        JobManager(True)
-
-        import dbus
-        bus = dbus.SystemBus()
-        proxy = bus.get_object('com.nokia.mce',
-                               '/com/nokia/mce/signal')
-        iface = dbus.Interface(proxy, 'com.nokia.mce.signal')
-        iface.connect_to_signal('system_inactivity_ind',
-                                self.system_inactivity_ind)
+        bus = dbus.SessionBus()
+        bus.add_signal_receiver(handler_function=self.update_progress,
+                                bus_name=None,
+                                signal_name='UpdateProgress',
+                                dbus_interface='org.marcoz.feedingit',
+                                path='/org/marcoz/feedingit/update')
 
     def button_markAll(self, button):
-        self.had_interaction = True
         for key in self.listing.getListOfFeeds():
             feed = self.listing.getFeed(key)
             feed.markAllAsRead()
@@ -1205,7 +1132,6 @@ class FeedingIt:
         self.displayListing()
 
     def button_about_clicked(self, button):
-        self.had_interaction = True
         HeAboutDialog.present(self.window, \
                 __appname__, \
                 ABOUT_ICON, \
@@ -1217,11 +1143,9 @@ class FeedingIt:
                 ABOUT_DONATE)
 
     def button_export_clicked(self, button):
-        self.had_interaction = True
         opml = ExportOpmlData(self.window, self.listing)
         
     def button_import_clicked(self, button):
-        self.had_interaction = True
         opml = GetOpmlData(self.window)
         feeds = opml.getData()
         for (title, url) in feeds:
@@ -1229,7 +1153,6 @@ class FeedingIt:
         self.displayListing()
 
     def addFeed(self, urlIn="http://"):
-        self.had_interaction = True
         wizard = AddWidgetWizard(self.window, self.listing, urlIn, self.listing.getListOfCategories())
         ret = wizard.run()
         if ret == 2:
@@ -1240,26 +1163,23 @@ class FeedingIt:
         self.displayListing()
 
     def button_organize_clicked(self, button):
-        self.had_interaction = True
         def after_closing():
             self.displayListing()
         SortList(self.window, self.listing, self, after_closing)
 
-    def button_update_clicked(self, button, key):
-        self.had_interaction = True
+    def do_update_feeds(self):
         for k in self.listing.getListOfFeeds():
             self.listing.updateFeed (k)
-        #self.displayListing()
+
+    def button_update_clicked(self, button, key):
+        gobject.idle_add(self.do_update_feeds)
 
     def onDownloadsDone(self, *widget):
         self.downloadDialog.destroy()
         self.downloadDialog = False
         self.displayListing()
-        self.updateDbusHandler.UpdateFinished()
-        self.updateDbusHandler.ArticleCountUpdated()
 
     def button_preferences_clicked(self, button):
-        self.had_interaction = True
         dialog = self.config.createDialog()
         dialog.connect("destroy", self.prefsClosed)
 
@@ -1353,7 +1273,6 @@ class FeedingIt:
         #    pass
 
     def on_feedList_row_activated(self, treeview, path, column):
-        self.had_interaction = True
         model = treeview.get_model()
         iter = model.get_iter(path)
         key = model.get_value(iter, COLUMN_KEY)
@@ -1377,59 +1296,24 @@ class FeedingIt:
                 self.openFeed(key)
             
     def openFeed(self, key):
-        try:
-            self.feed_lock
-        except:
-            # If feed_lock doesn't exist, we can open the feed, else we do nothing
-            if key != None:
-                self.feed_lock = get_lock(key)
-                self.disp = DisplayFeed(self.listing, self.listing.getFeed(key), \
-                        self.listing.getFeedTitle(key), key, \
-                        self.config, self.updateDbusHandler)
-                self.disp.connect("feed-closed", self.onFeedClosed)
+        if key != None:
+            self.disp = DisplayFeed(
+                self.listing, self.listing.getFeed(key),
+                self.listing.getFeedTitle(key), key,
+                self.config)
+            self.disp.connect("feed-closed", self.onFeedClosed)
                 
     def openArticle(self, key, id):
-        try:
-            self.feed_lock
-        except:
-            # If feed_lock doesn't exist, we can open the feed, else we do nothing
-            if key != None:
-                self.feed_lock = get_lock(key)
-                self.disp = DisplayFeed(self.listing, self.listing.getFeed(key), \
-                        self.listing.getFeedTitle(key), key, \
-                        self.config, self.updateDbusHandler)
-                self.disp.button_clicked(None, id)
-                self.disp.connect("feed-closed", self.onFeedClosed)
-        
+        if key != None:
+            self.openFeed(key)
+            self.disp.button_clicked(None, id)
 
     def onFeedClosed(self, object, key):
-        #self.listing.saveConfig()
-        #del self.feed_lock
-        gobject.idle_add(self.onFeedClosedTimeout)
         self.displayListing()
-        #self.updateDbusHandler.ArticleCountUpdated()
         
-    def onFeedClosedTimeout(self):
-        del self.feed_lock
-        self.updateDbusHandler.ArticleCountUpdated()
-
     def quit(self, *args):
         self.window.hide()
-
-        if hasattr (self, 'app_lock'):
-            del self.app_lock
-
-        # Wait until all slave threads have properly exited before
-        # terminating the mainloop.
-        jm = JobManager()
-        jm.quit ()
-        stats = jm.stats()
-        if stats['jobs-in-progress'] == 0 and stats['jobs-queued'] == 0:
-            gtk.main_quit ()
-        else:
-            gobject.timeout_add(500, self.quit)
-
-        return False
+        gtk.main_quit ()
 
     def run(self):
         self.window.connect("destroy", self.quit)
@@ -1470,13 +1354,6 @@ class FeedingIt:
         self.button_update_clicked(None, None)
         return True
     
-    def stopUpdate(self):
-        # Not implemented in the app (see update_feeds.py)
-        try:
-            JobManager().cancel ()
-        except:
-            pass
-    
     def getStatus(self):
         status = ""
         for key in self.listing.getListOfFeeds():