Source

asterator / Asterator / channeltree.py


import gobject
import pygtk
pygtk.require('2.0')
import gtk

(
    NAME_COLUMN,
    STATE_COLUMN,
    TIME_COLUMN,
    CALLERID_COLUMN,
    LOCATION_COLUMN,
    APP_COLUMN
) = range(6)

class channel_tree(gtk.TreeView):
    def gen_model(self):
        model = gtk.TreeStore(
            gobject.TYPE_STRING,
            gobject.TYPE_STRING,
            gobject.TYPE_STRING,
            gobject.TYPE_STRING,
            gobject.TYPE_STRING,
            gobject.TYPE_STRING)

        self.channels = model.append(None)
        model.set(self.channels,
                  NAME_COLUMN, '[Orphaned]',
                  STATE_COLUMN, '',
                  TIME_COLUMN, '',
                  CALLERID_COLUMN, '',
                  LOCATION_COLUMN, '',
                  APP_COLUMN, '')
        
        self.links = model.append(None)
        model.set(self.links,
                  NAME_COLUMN, '[Linked]',
                  STATE_COLUMN, '',
                  TIME_COLUMN, '',
                  CALLERID_COLUMN, '',
                  LOCATION_COLUMN, '',
                  APP_COLUMN, '')
        
        self.parkedcalls = model.append(None)
        model.set(self.parkedcalls,
                  NAME_COLUMN, '[Parked]',
                  STATE_COLUMN, '',
                  TIME_COLUMN, '',
                  CALLERID_COLUMN, '',
                  LOCATION_COLUMN, '',
                  APP_COLUMN, '')
        
        self.channel_cnt = 0
        self.link_cnt = 0
        self.parkedcall_cnt = 0

        return model
    
    def __init__(self):
        model = self.gen_model()
        
        gtk.TreeView.__init__(self, model)
        self.set_rules_hint(True)
        self.get_selection().set_mode(gtk.SELECTION_MULTIPLE)
        self.connect('realize', lambda tv: tv.expand_all())
        self.connect('row-activated', self.on_rowactivated)
        self.connect('button_press_event', self.on_treeview_button_press_event)
        
        renderer = gtk.CellRendererText()
        renderer.set_property("xalign", 0.0)
        column = gtk.TreeViewColumn("Channel", renderer, text=NAME_COLUMN)
        column.set_resizable(True)
        self.append_column(column)
        
        renderer = gtk.CellRendererText()
        renderer.set_property("xalign", 0.0)
        column = gtk.TreeViewColumn("State", renderer, text=STATE_COLUMN)
        column.set_resizable(True)
        self.append_column(column)
        
        renderer = gtk.CellRendererText()
        renderer.set_property("xalign", 0.0)
        column = gtk.TreeViewColumn("Alive", renderer, text=TIME_COLUMN)
        column.set_resizable(True)
        self.append_column(column)
        
        renderer = gtk.CellRendererText()
        renderer.set_property("xalign", 0.0)
        column = gtk.TreeViewColumn("CallerID", renderer, text=CALLERID_COLUMN)
        column.set_resizable(True)
        self.append_column(column)
        
        renderer = gtk.CellRendererText()
        renderer.set_property("xalign", 0.0)
        column = gtk.TreeViewColumn("Location", renderer, text=LOCATION_COLUMN)
        column.set_resizable(True)
        self.append_column(column)
        
        renderer = gtk.CellRendererText()
        renderer.set_property("xalign", 0.0)
        column = gtk.TreeViewColumn("App", renderer, text=APP_COLUMN)
        column.set_resizable(True)
        self.append_column(column)
        
    def on_rowactivated(self, tv, path, view_col):
        if tv.row_expanded(path):
            tv.collapse_row(path)
        else:
            tv.expand_row(path, False)

    def on_treeview_button_press_event(self, treeview, event):
        if event.button > 3:
            dlg = gtk.MessageDialog(None, gtk.DIALOG_DESTROY_WITH_PARENT,
                                    gtk.MESSAGE_ERROR, gtk.BUTTONS_OK,
                                    str(event.button))
            dlg.run()
            dlg.hide()
        if event.button == 3:
            self.popup.popup(None, None, None, event.button, event.time)
            return 1

    def clear(self):
        self.set_model(self.gen_model())

    def myset(self, model, chan):
        model.set(chan.iter,
                  NAME_COLUMN, chan.name,
                  STATE_COLUMN, chan.state,
                  TIME_COLUMN, chan.get_timealive(),
                  CALLERID_COLUMN, chan.get_callerid(),
                  LOCATION_COLUMN, chan.get_location(),
                  APP_COLUMN, chan.get_app())

    def reconcile(self, listener):
        """A quickly written refresh method

        Don't call this from within a listener callback or you'll get
        a deadlock lolz because this locks the listener object.

        ToDo: Make this better
        
        """
        self.clear()
        listener.lock()
        for channel in listener.channels.values():
            self.add_channel(channel)
            if channel.parked:
                self.prk_channel(channel)
        for link in listener.links:
            self.add_link(link)
        listener.unlock()

    def add_channel(self, chan):
        model = self.get_model()
        self.channel_cnt += 1
        
        iter = model.append(self.channels)
        chan.iter = iter
        self.myset(model, chan)
        
        if self.channel_cnt == 1:
            self.expand_row(model.get_string_from_iter(self.channels), True)

    def del_channel(self, chan):
        model = self.get_model()
        model.remove(chan.iter)
        self.channel_cnt -= 1
        assert self.channel_cnt >= 0

    def upd_channel(self, chan):
        model = self.get_model()
        self.myset(model, chan)
        
    def prk_channel(self, chan):
        self.del_channel(chan)
        
        model = self.get_model()
        self.parkedcall_cnt += 1
        
        iter = model.append(self.parkedcalls)
        chan.iter = iter
        self.myset(model, chan)
        
        if self.parkedcall_cnt == 1:
            self.expand_row(model.get_string_from_iter(self.parkedcalls), True)
            
    def unprk_channel(self, chan):
        model = self.get_model()
        model.remove(chan.iter)
        self.add_channel(chan)
        self.parkedcall_cnt -= 1
        assert self.parkedcall_cnt >= 0

    def add_link(self, link):
        model = self.get_model()
        self.link_cnt += 1
        
        self.del_channel(link.chan1)
        self.del_channel(link.chan2)
        iter = model.append(self.links)
        link.iter = iter
        model.set(iter,
                  NAME_COLUMN, link.chan1.name + ' & ' + link.chan2.name,
                  STATE_COLUMN, '',
                  TIME_COLUMN, '',
                  CALLERID_COLUMN, '',
                  LOCATION_COLUMN, '',
                  APP_COLUMN, '')
        
        child = model.append(iter)
        link.chan1.iter = child
        self.myset(model, link.chan1)
        
        child = model.append(iter)
        link.chan2.iter = child
        self.myset(model, link.chan2)
        
        self.expand_row(model.get_string_from_iter(iter), True)
        if self.link_cnt == 1:
            self.expand_row(model.get_string_from_iter(self.links), True)
        
    def del_link(self, link):
        model = self.get_model()

        self.add_channel(link.chan1)
        self.add_channel(link.chan2)
        model.remove(link.iter)
        
        self.link_cnt -= 1
        assert self.link_cnt >= 0