From e091da41ded7ab54c9341c0fbafe8c297789137a Mon Sep 17 00:00:00 2001
From: Doug Blank <doug.blank@gmail.com>
Date: Sun, 6 Dec 2009 00:36:10 +0000
Subject: [PATCH] Refinements and tests for cancelling processes

svn: r13719
---
 src/gen/utils/longop.py      | 27 ++++++++++++++++++++++-----
 src/gen/utils/progressmon.py | 13 ++++++++++++-
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/src/gen/utils/longop.py b/src/gen/utils/longop.py
index 64a601857..553727493 100644
--- a/src/gen/utils/longop.py
+++ b/src/gen/utils/longop.py
@@ -26,11 +26,11 @@ class LongOpStatus(Callback):
 	}
     
         def long(self):
-        status = LongOpStatus("doing long job", 100, 10)
+            status = LongOpStatus("doing long job", 100, 10)
 
             for i in xrange(0,99):
-            time.sleep(0.1)
-            status.heartbeat()
+                time.sleep(0.1)
+                status.heartbeat()
 
             status.end()
     
@@ -124,6 +124,12 @@ class LongOpStatus(Callback):
         """
         return self._secs_left
 
+    def was_cancelled(self):
+        """
+        Has this process been cancelled?
+        """
+        return self._cancel
+
     def cancel(self):
         """Inform the operation that it should complete.
         """
@@ -186,7 +192,7 @@ class LongOpStatus(Callback):
 
 if __name__ == '__main__':
 
-    s = LongOpStatus("msg", 100, 10)
+    s = LongOpStatus("msg", 100, 10, can_cancel=True)
 
     def heartbeat():
         print "heartbeat ", s.estimated_secs_to_complete()
@@ -197,9 +203,20 @@ if __name__ == '__main__':
     s.connect('op-heartbeat', heartbeat)
     s.connect('op-end', end)
 
+    import signal
+
+    def ctrlc_handler(signum, frame):
+        print "Received interrupt!"
+        s.cancel()
+
+    signal.signal(signal.SIGINT, ctrlc_handler)
+
     for i in xrange(0, 99):
+        if s.should_cancel():
+            break
         time.sleep(0.1)
         s.heartbeat()
 
-    s.end()
+    if not s.was_cancelled():
+        s.end()
     
diff --git a/src/gen/utils/progressmon.py b/src/gen/utils/progressmon.py
index d7aa2f38b..c347c1139 100644
--- a/src/gen/utils/progressmon.py
+++ b/src/gen/utils/progressmon.py
@@ -126,6 +126,10 @@ class ProgressMonitor(object):
         
         log.debug("heartbeat in ProgressMonitor")
         
+        if idx >= len(self._status_stack):
+            # this item has been cancelled
+            return
+
         facade = self._status_stack[idx]
         
         if facade.status_obj.estimated_secs_to_complete() > self._popup_time:
@@ -143,8 +147,15 @@ class ProgressMonitor(object):
     def _end(self, idx):
         # hide any progress dialog
         # remove the status object from the stack
-        
         log.debug("received end in ProgressMonitor")
+
+        if idx >= len(self._status_stack):
+            # this item has been cancelled
+            return
+
+        while idx < len(self._status_stack) - 1:
+            self._end(len(self._status_stack) - 1)
+
         facade = self._status_stack[idx]
         if facade.active:
             dlg = self._get_dlg()