/offlineimap/head: changeset 305
Believed to be somewhat working now
This commit is contained in:
		@@ -16,6 +16,9 @@
 | 
			
		||||
#    along with this program; if not, write to the Free Software
 | 
			
		||||
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
from threading import *
 | 
			
		||||
import thread
 | 
			
		||||
 | 
			
		||||
class BlinkenBase:
 | 
			
		||||
    """This is a mix-in class that should be mixed in with either UIBase
 | 
			
		||||
    or another appropriate base class.  The Tk interface, for instance,
 | 
			
		||||
@@ -66,4 +69,59 @@ class BlinkenBase:
 | 
			
		||||
        s.gettf().setcolor('pink')
 | 
			
		||||
        s.__class__.__bases__[-1].deletingflags(s, uid, flags, destlist)
 | 
			
		||||
 | 
			
		||||
    def init_banner(s):
 | 
			
		||||
        s.availablethreadframes = {}
 | 
			
		||||
        s.threadframes = {}
 | 
			
		||||
        s.tflock = Lock()
 | 
			
		||||
 | 
			
		||||
    def threadExited(s, thread):
 | 
			
		||||
        threadid = thread.threadid
 | 
			
		||||
        accountname = s.getthreadaccount(thread)
 | 
			
		||||
        s.tflock.acquire()
 | 
			
		||||
        try:
 | 
			
		||||
            if threadid in s.threadframes[accountname]:
 | 
			
		||||
                tf = s.threadframes[accountname][threadid]
 | 
			
		||||
                del s.threadframes[accountname][threadid]
 | 
			
		||||
                s.availablethreadframes[accountname].append(tf)
 | 
			
		||||
                tf.setthread(None)
 | 
			
		||||
        finally:
 | 
			
		||||
            s.tflock.release()
 | 
			
		||||
 | 
			
		||||
        UIBase.threadExited(s, thread)
 | 
			
		||||
 | 
			
		||||
    def gettf(s):
 | 
			
		||||
        threadid = thread.get_ident()
 | 
			
		||||
        accountname = s.getthreadaccount()
 | 
			
		||||
        
 | 
			
		||||
        s.tflock.acquire()
 | 
			
		||||
 | 
			
		||||
        print "b98"
 | 
			
		||||
 | 
			
		||||
        try:
 | 
			
		||||
            if not accountname in s.threadframes:
 | 
			
		||||
                s.threadframes[accountname] = {}
 | 
			
		||||
                
 | 
			
		||||
            if threadid in s.threadframes[accountname]:
 | 
			
		||||
                return s.threadframes[accountname][threadid]
 | 
			
		||||
 | 
			
		||||
            print 'b107'
 | 
			
		||||
 | 
			
		||||
            if not accountname in s.availablethreadframes:
 | 
			
		||||
                s.availablethreadframes[accountname] = []
 | 
			
		||||
 | 
			
		||||
            print 'b112'
 | 
			
		||||
 | 
			
		||||
            if len(s.availablethreadframes[accountname]):
 | 
			
		||||
                tf = s.availablethreadframes[accountname].pop(0)
 | 
			
		||||
                tf.setthread(currentThread())
 | 
			
		||||
            else:
 | 
			
		||||
                print 'b118'
 | 
			
		||||
                tf = s.getaccountframe().getnewthreadframe()
 | 
			
		||||
                print 'b120'
 | 
			
		||||
            s.threadframes[accountname][threadid] = tf
 | 
			
		||||
            return tf
 | 
			
		||||
        
 | 
			
		||||
        finally:
 | 
			
		||||
            s.tflock.release()
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -79,14 +79,35 @@ class CursesUtil:
 | 
			
		||||
        curses.endwin()
 | 
			
		||||
        del self.stdscr
 | 
			
		||||
 | 
			
		||||
    def resize(self):
 | 
			
		||||
    def reset(self):
 | 
			
		||||
        self.stop()
 | 
			
		||||
        self.start()
 | 
			
		||||
 | 
			
		||||
class CursesThreadFrame:
 | 
			
		||||
class CursesAccountFrame:
 | 
			
		||||
    def __init__(s, master):
 | 
			
		||||
        s.c = master
 | 
			
		||||
        s.children = []
 | 
			
		||||
 | 
			
		||||
    def setwindow(s, window):
 | 
			
		||||
        s.window = window
 | 
			
		||||
        location = 0
 | 
			
		||||
        for child in s.children:
 | 
			
		||||
            child.update(window, 0, location)
 | 
			
		||||
            location += 1
 | 
			
		||||
 | 
			
		||||
    def getnewthreadframe(s):
 | 
			
		||||
        tf = CursesThreadFrame(s.c, s.window, 0, len(s.children))
 | 
			
		||||
        s.children.append(tf)
 | 
			
		||||
        return tf
 | 
			
		||||
 | 
			
		||||
class CursesThreadFrame:
 | 
			
		||||
    def __init__(s, master, window, y, x):
 | 
			
		||||
        """master should be a CursesUtil object."""
 | 
			
		||||
        s.c = master
 | 
			
		||||
        s.window = window
 | 
			
		||||
        s.x = x
 | 
			
		||||
        s.y = y
 | 
			
		||||
        s.colors = []
 | 
			
		||||
        bg = curses.COLOR_BLACK
 | 
			
		||||
        s.colormap = {'black': s.c.getpair(curses.COLOR_BLACK, bg),
 | 
			
		||||
                         'gray': s.c.getpair(curses.COLOR_WHITE, bg),
 | 
			
		||||
@@ -100,13 +121,21 @@ class CursesThreadFrame:
 | 
			
		||||
                         'yellow': curses.A_BOLD | s.c.getpair(curses.COLOR_YELLOW, bg),
 | 
			
		||||
                         'pink': curses.A_BOLD | s.c.getpair(curses.COLOR_RED, bg)}
 | 
			
		||||
        s.setcolor('gray')
 | 
			
		||||
                         
 | 
			
		||||
 | 
			
		||||
    def setcolor(self, color):
 | 
			
		||||
        self.color = self.colormap[color]
 | 
			
		||||
        self.window.addstr(self.y, self.x, '.', self.color)
 | 
			
		||||
        self.window.refresh()
 | 
			
		||||
 | 
			
		||||
    def getcolor(self):
 | 
			
		||||
        return self.color
 | 
			
		||||
 | 
			
		||||
    def setthread(self, newthread):
 | 
			
		||||
        if newthread:
 | 
			
		||||
            self.setcolor('gray')
 | 
			
		||||
        else:
 | 
			
		||||
            self.setcolor('black')
 | 
			
		||||
 | 
			
		||||
class InputHandler:
 | 
			
		||||
    def __init__(s, util):
 | 
			
		||||
        s.c = util
 | 
			
		||||
@@ -181,12 +210,18 @@ class InputHandler:
 | 
			
		||||
class Blinkenlights(BlinkenBase, UIBase):
 | 
			
		||||
    def init_banner(s):
 | 
			
		||||
        s.iolock = Lock()
 | 
			
		||||
        s.af = {}
 | 
			
		||||
        s.aflock = Lock()
 | 
			
		||||
        s.c = CursesUtil()
 | 
			
		||||
        s.accounts = []
 | 
			
		||||
        s.text = []
 | 
			
		||||
        s.tf = CursesThreadFrame(s.c)
 | 
			
		||||
        s.setupwindows()
 | 
			
		||||
        BlinkenBase.init_banner(s)
 | 
			
		||||
        print 217
 | 
			
		||||
        s.setupwindows(dolock = 0)
 | 
			
		||||
        print '219a'
 | 
			
		||||
        s.inputhandler = InputHandler(s.c)
 | 
			
		||||
        print 219
 | 
			
		||||
        print 221
 | 
			
		||||
        
 | 
			
		||||
        s._msg(version.banner)
 | 
			
		||||
        s._msg(str(dir(s.c.stdscr)))
 | 
			
		||||
        s.inputhandler.set_bgchar(s.keypress)
 | 
			
		||||
@@ -209,17 +244,43 @@ class Blinkenlights(BlinkenBase, UIBase):
 | 
			
		||||
            s.inputhandler.input_release()
 | 
			
		||||
        return password
 | 
			
		||||
 | 
			
		||||
    def setupwindows(s):
 | 
			
		||||
        s.bannerwindow = curses.newwin(1, s.c.width, 0, 0)
 | 
			
		||||
        s.drawbanner()
 | 
			
		||||
        s.logheight = s.c.height - 1 - len(s.accounts) * 2
 | 
			
		||||
        s.logwindow = curses.newwin(s.logheight, s.c.width, 1, 0)
 | 
			
		||||
        s.logwindow.idlok(1)
 | 
			
		||||
        s.logwindow.scrollok(1)
 | 
			
		||||
        s.drawlog()
 | 
			
		||||
        curses.doupdate()
 | 
			
		||||
    def setupwindows(s, dolock = 1):
 | 
			
		||||
        print 244
 | 
			
		||||
        if dolock:
 | 
			
		||||
            s.iolock.acquire()
 | 
			
		||||
        try:
 | 
			
		||||
            s.bannerwindow = curses.newwin(1, s.c.width, 0, 0)
 | 
			
		||||
            s.setupwindow_drawbanner()
 | 
			
		||||
            s.logheight = s.c.height - 1 - len(s.af.keys())
 | 
			
		||||
            s.logwindow = curses.newwin(s.logheight, s.c.width, 1, 0)
 | 
			
		||||
            s.logwindow.idlok(1)
 | 
			
		||||
            s.logwindow.scrollok(1)
 | 
			
		||||
            s.setupwindow_drawlog()
 | 
			
		||||
 | 
			
		||||
    def drawbanner(s):
 | 
			
		||||
            print 258
 | 
			
		||||
 | 
			
		||||
            accounts = s.af.keys()
 | 
			
		||||
            accounts.sort()
 | 
			
		||||
            accounts.reverse()
 | 
			
		||||
 | 
			
		||||
            print 264
 | 
			
		||||
 | 
			
		||||
            pos = s.c.height - 1
 | 
			
		||||
            for account in accounts:
 | 
			
		||||
                accountwindow = curses.newwin(1, s.c.width, pos, 0)
 | 
			
		||||
                s.af[account].setwindow(accountwindow)
 | 
			
		||||
                pos -= 1
 | 
			
		||||
 | 
			
		||||
            print 272
 | 
			
		||||
            
 | 
			
		||||
            curses.doupdate()
 | 
			
		||||
 | 
			
		||||
            print 276
 | 
			
		||||
        finally:
 | 
			
		||||
            if dolock:
 | 
			
		||||
                s.iolock.release()
 | 
			
		||||
 | 
			
		||||
    def setupwindow_drawbanner(s):
 | 
			
		||||
        s.bannerwindow.bkgd(' ', curses.A_BOLD | \
 | 
			
		||||
                            s.c.getpair(curses.COLOR_WHITE,
 | 
			
		||||
                                        curses.COLOR_BLUE))
 | 
			
		||||
@@ -227,21 +288,36 @@ class Blinkenlights(BlinkenBase, UIBase):
 | 
			
		||||
                                         version.versionstr))
 | 
			
		||||
        s.bannerwindow.addstr(0, s.bannerwindow.getmaxyx()[1] - len(version.copyright) - 1,
 | 
			
		||||
                              version.copyright)
 | 
			
		||||
 | 
			
		||||
        
 | 
			
		||||
        s.bannerwindow.noutrefresh()
 | 
			
		||||
 | 
			
		||||
    def drawlog(s):
 | 
			
		||||
        s.iolock.acquire()
 | 
			
		||||
        try:
 | 
			
		||||
            s.logwindow.bkgd(' ', s.c.getpair(curses.COLOR_WHITE, curses.COLOR_BLACK))
 | 
			
		||||
            for line, color in s.text:
 | 
			
		||||
                s.logwindow.addstr(line + "\n", color)
 | 
			
		||||
                s.logwindow.noutrefresh()
 | 
			
		||||
        finally:
 | 
			
		||||
            s.iolock.release()
 | 
			
		||||
    def setupwindow_drawlog(s):
 | 
			
		||||
        s.logwindow.bkgd(' ', s.c.getpair(curses.COLOR_WHITE, curses.COLOR_BLACK))
 | 
			
		||||
        for line, color in s.text:
 | 
			
		||||
            s.logwindow.addstr(line + "\n", color)
 | 
			
		||||
            s.logwindow.noutrefresh()
 | 
			
		||||
 | 
			
		||||
    def getaccountframe(s):
 | 
			
		||||
        accountname = s.getthreadaccount()
 | 
			
		||||
        print 'c302: ', accountname
 | 
			
		||||
        s.aflock.acquire()
 | 
			
		||||
        print 'c304'
 | 
			
		||||
        try:
 | 
			
		||||
            if accountname in s.af:
 | 
			
		||||
                return s.af[accountname]
 | 
			
		||||
 | 
			
		||||
            # New one.
 | 
			
		||||
            s.af[accountname] = CursesAccountFrame(s.c)
 | 
			
		||||
            #s.iolock.acquire()
 | 
			
		||||
            print 297
 | 
			
		||||
            s.c.reset()
 | 
			
		||||
            s.setupwindows(dolock = 0)
 | 
			
		||||
            print 300
 | 
			
		||||
            #s.iolock.release()
 | 
			
		||||
        finally:
 | 
			
		||||
            s.aflock.release()
 | 
			
		||||
        return s.af[accountname]
 | 
			
		||||
 | 
			
		||||
    def gettf(s):
 | 
			
		||||
        return s.tf
 | 
			
		||||
 | 
			
		||||
    def _msg(s, msg, color = None):
 | 
			
		||||
        if "\n" in msg:
 | 
			
		||||
@@ -249,6 +325,7 @@ class Blinkenlights(BlinkenBase, UIBase):
 | 
			
		||||
                s._msg(thisline)
 | 
			
		||||
            return
 | 
			
		||||
        s.iolock.acquire()
 | 
			
		||||
        print 326
 | 
			
		||||
        try:
 | 
			
		||||
            if not s.c.isactive():
 | 
			
		||||
                # For dumping out exceptions and stuff.
 | 
			
		||||
@@ -258,6 +335,7 @@ class Blinkenlights(BlinkenBase, UIBase):
 | 
			
		||||
                s.gettf().setcolor(color)
 | 
			
		||||
            s._addline_unlocked(msg, s.gettf().getcolor())
 | 
			
		||||
            s.logwindow.refresh()
 | 
			
		||||
            print 336
 | 
			
		||||
        finally:
 | 
			
		||||
            s.iolock.release()
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@
 | 
			
		||||
#    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
			
		||||
 | 
			
		||||
import offlineimap.version
 | 
			
		||||
import re, time, sys, traceback, threading
 | 
			
		||||
import re, time, sys, traceback, threading, thread
 | 
			
		||||
from StringIO import StringIO
 | 
			
		||||
 | 
			
		||||
debugtypes = {'imap': 'IMAP protocol debugging',
 | 
			
		||||
@@ -38,6 +38,7 @@ class UIBase:
 | 
			
		||||
        s.debuglist = []
 | 
			
		||||
        s.debugmessages = {}
 | 
			
		||||
        s.debugmsglen = 50
 | 
			
		||||
        s.threadaccounts = {}
 | 
			
		||||
    
 | 
			
		||||
    ################################################## UTILS
 | 
			
		||||
    def _msg(s, msg):
 | 
			
		||||
@@ -50,6 +51,24 @@ class UIBase:
 | 
			
		||||
        else:
 | 
			
		||||
            s._msg("WARNING: " + msg)
 | 
			
		||||
 | 
			
		||||
    def registerthread(s, account):
 | 
			
		||||
        """Provides a hint to UIs about which account this particular
 | 
			
		||||
        thread is processing."""
 | 
			
		||||
        if s.threadaccounts.has_key(thread.get_ident()):
 | 
			
		||||
            raise ValueError, "Thread already registered (old %s, new %s)" % \
 | 
			
		||||
                  (s.getthreadaccount(s), account)
 | 
			
		||||
        s.threadaccounts[thread.get_ident()] = account
 | 
			
		||||
 | 
			
		||||
    def unregisterthread(s, thr):
 | 
			
		||||
        """Recognizes a thread has exited."""
 | 
			
		||||
        if s.threadaccounts.has_key(thr):
 | 
			
		||||
            del s.threadaccounts[thr]
 | 
			
		||||
 | 
			
		||||
    def getthreadaccount(s):
 | 
			
		||||
        if s.threadaccounts.has_key(thread.get_ident()):
 | 
			
		||||
            return s.threadaccounts[thread.get_ident()]
 | 
			
		||||
        return None
 | 
			
		||||
 | 
			
		||||
    def debug(s, debugtype, msg):
 | 
			
		||||
        thisthread = threading.currentThread()
 | 
			
		||||
        if s.debugmessages.has_key(thisthread):
 | 
			
		||||
@@ -258,6 +277,7 @@ class UIBase:
 | 
			
		||||
        """Called when a thread has exited normally.  Many UIs will
 | 
			
		||||
        just ignore this."""
 | 
			
		||||
        s.delThreadDebugLog(thread)
 | 
			
		||||
        s.unregisterthread(thread)
 | 
			
		||||
 | 
			
		||||
    ################################################## Other
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user