| 4 | from gobject import GObject, SIGNAL_RUN_FIRST |
| 5 | |
| 6 | class GtkWorker (GObject, Thread): |
| 7 | |
| 8 | __gsignals__ = { |
| 9 | "progressed": (SIGNAL_RUN_FIRST, None, (float,)), |
| 10 | "published": (SIGNAL_RUN_FIRST, None, (object,)), |
| 11 | "done": (SIGNAL_RUN_FIRST, None, ()) |
| 12 | } |
| 13 | |
| 14 | def __init__ (self, func): |
| 15 | """ Initialize a new GtkWorker around a specific function """ |
| 16 | |
| 17 | # WARNING: This deadlocks if calling code already has the gdk lock and |
| 18 | # is not the MainThread |
| 19 | if type(currentThread()) != _MainThread: |
| 20 | threads_enter() |
| 21 | GObject.__init__(self) |
| 22 | if type(currentThread()) != _MainThread: |
| 23 | threads_leave() |
| 24 | |
| 25 | Thread.__init__(self) |
| 26 | self.setDaemon(True) |
| 27 | |
| 28 | # By some reason we cannot access __gsignals__, so we have to do a |
| 29 | # little double work here |
| 30 | self.connections = {"progressed": 0, "published": 0, "done": 0} |
| 31 | self.handler_ids = {} |
| 32 | |
| 33 | self.func = func |
| 34 | self.cancelled = False |
| 35 | self.done = False |
| 36 | self.progress = 0 |
| 37 | |
| 38 | ######################################################################## |
| 39 | # Publish and progress queues # |
| 40 | ######################################################################## |
| 41 | |
| 42 | class Publisher (Thread): |
| 43 | SEND_LIST, SEND_LAST = range(2) |
| 44 | |
| 45 | def __init__ (self, parrent, queue, signal, sendPolicy): |
| 46 | Thread.__init__(self) |
| 47 | self.setDaemon(True) |
| 48 | self.parrent = parrent |
| 49 | self.queue = queue |
| 50 | self.signal = signal |
| 51 | self.sendPolicy = sendPolicy |
| 52 | |
| 53 | def run (self): |
| 54 | while True: |
| 55 | v = self.queue.get() |
| 56 | if v == None: |
| 57 | break |
| 58 | threads_enter() |
| 59 | l = [v] |
| 60 | while True: |
| 61 | try: |
| 62 | v = self.queue.get_nowait() |
| 63 | except Queue.Empty: |