[go: up one dir, main page]

Menu

[r3]: / app / gapito / gapito  Maximize  Restore  History

Download this file

342 lines (277 with data), 11.1 kB

#!/usr/bin/python

import sys
import gtk
import vte
import console
import gtk.glade as glade
from math import ceil, sqrt
import re
import time

class Terminal:

    def __init__(self):
        window = gtk.Window()
        scrollbar = gtk.VScrollbar()
        checkbutton = gtk.CheckButton()
        terminal = vte.Terminal()

        vbox = gtk.VBox()
        hbox = gtk.HBox()

        window.add(hbox)
        hbox.pack_start(terminal, True, True, 0)
        hbox.pack_start(vbox, False, False, 0)
        vbox.pack_start(checkbutton, False, False, 0)
        vbox.pack_start(scrollbar, True, True, 0)

        scrollbar.set_adjustment(terminal.get_adjustment())
        terminal.set_size_request(30, 30)
        checkbutton.set_active(1)
        window.set_default_size(640, 320)
        window.show_all()

        self.window = window
        self.vte = terminal
        self.checkbutton = checkbutton
        self.repeating = 0
        self.visible = True

    def is_selected(self):
        return self.checkbutton.get_active()

    def select(self, value=True):
        self.checkbutton.set_active(value)

    def vte_connect(self, signal, func):
        self.vte.connect(signal, func, self, signal)

    def vte_reemit(self, signal, event):
        self.repeating += 1
        try:
            self.vte.emit(signal, event.copy())
        except:
            pass
        self.repeating -= 1

    def show(self, visible=True):
        self.visible = visible
        if visible:
            self.window.show()
        else:
            self.window.hide()

class App:

    def _on_vte_event(self, srcvte, event, srcterm, signal):
        if srcterm.is_selected() and not srcterm.repeating:
            for t in self.terms:
                if srcterm != t:
                    if t.is_selected():
                        t.vte_reemit(signal, event)

    def _on_window_close(self, srcwin, event, srcterm):
        self.terms = [ t for t in self.terms if t != srcterm ]

    def _make_terminal(self, title, cmd, args):
        t = Terminal()
        t.window.set_title(title)
        
        t.vte_connect("key-press-event", self._on_vte_event)
        t.vte_connect("key-release-event", self._on_vte_event)

        t.window.connect("delete-event", self._on_window_close, t)
        
        t.vte.fork_command(cmd, args)
        return t

    def __init__(self):
        gx = glade.XML('gapito.glade')
        self.glade_xml = gx
        control = gx.get_widget('control_window')
        # control.show_all()
        self.control_window = control

        gx.get_widget('quit').connect('activate', self._on_quit)
        gx.get_widget('control_window').connect('delete_event', self._on_quit)

        gx.get_widget('new_terminal').connect('activate', self._on_new_terminal)
        gx.get_widget('new_terminal_ok').connect('clicked', self._on_new_terminal_ok)
        gx.get_widget('new_terminal_cancel').connect('clicked', self._on_new_terminal_cancel)
        
        gx.get_widget('new_terminal_dialog').connect('delete_event', self._on_new_terminal_cancel)
        
        gx.get_widget('select_all').connect('activate', self._on_select_all)
        gx.get_widget('unselect_all').connect('activate', self._on_unselect_all)
        gx.get_widget('toggle_selected').connect('activate', self._on_toggle_selected)

        gx.get_widget('show_all').connect('activate', self._on_show_all)
        gx.get_widget('hide_unselected').connect('activate', self._on_hide_unselected)

        gx.get_widget('about').connect('activate', self._on_about)
        gx.get_widget('about_dialog').connect('delete_event', self._on_close_about)

        gx.get_widget('arrange_windows').connect('activate', self._on_arrange_windows)

        gx.get_widget('new_terminal_schema').set_active(0)

        self.shortcuts = {}

    def _on_about(self, *more):
        self.glade_xml.get_widget('about_dialog').show_all()

    def _on_close_about(self, *more):
        self.glade_xml.get_widget('about_dialog').hide()
        return True
    
    def _on_quit(self, *more):
        gtk.main_quit()

    def _on_arrange_windows(self, *more):
        cols = 4
        l = len(self.terms)
        sl = int(sqrt(l))
        if cols > sl:
            cols = sl
        rows = int(ceil(l/cols))
        screen = self.glade_xml.get_widget('control_window').get_screen()
        width = screen.get_width()
        height = screen.get_height()

        dx = width/cols
        dy = height/rows

        i = 0; j = 0
        for t in self.terms:
            t.window.resize(int(0.95 * dx), int(0.90 * dy))
            t.window.move(dx * i, dy * j)
            j += 1
            if j >= rows:
                j = 0
                i += 1

    def _on_select_all(self, *more):
        for t in self.terms:
            if t.visible:
                t.select()

    def _on_unselect_all(self, *more):
        for t in self.terms:
            if t.visible:
                t.select(False)

    def _on_toggle_selected(self, *more):
        for t in self.terms:
            if t.visible:
                t.select(not t.is_selected())

    def _on_show_all(self, *more):
        for t in self.terms:
            if not t.visible:
                t.show()

    def _on_hide_unselected(self, more):
        for t in self.terms:
            if not t.is_selected():
                if t.visible:
                    t.select(False)
                    t.show(False)

    def _on_new_terminal(self, src):
        dialog = self.glade_xml.get_widget('new_terminal_dialog')
        dialog.show_all()
        dialog.present()

    def _on_new_terminal_cancel(self, *more):
        dialog = self.glade_xml.get_widget('new_terminal_dialog')
        dialog.hide()

    def _on_new_terminal_ok(self, *more):
        schema = self.glade_xml.get_widget('new_terminal_schema').get_active_text()
        host = self.glade_xml.get_widget('new_terminal_host').get_text()
        port = self.glade_xml.get_widget('new_terminal_port').get_text()
        username = self.glade_xml.get_widget('new_terminal_username').get_text()
        password = self.glade_xml.get_widget('new_terminal_password').get_text()
        self._create_new_terminal(schema, host, port, username, password)

    def _create_new_terminal(self, schema, host, port, username, password):
        # print 'schema:', schema, 'host:', host, 'port:', port, 'username:', username

        name = host
        if port != '':
            name = name + ':' + port
        if username != '':
            name = username + '@' + name
        name = schema + '://' + name

        cmd = ''
        args = []

        print "new terminal", name
        
        if schema == 'ssh':
            cmd = '/usr/bin/ssh'
            args = [host]
            if port != '':
                args += ('-p', port)
            if username != '':
                args += ('-l', username)

        elif schema == 'plink':
            cmd = '/usr/bin/plink'
            args = [host]
            if port != '':
                args += ('-P', port)
            if username != '':
                args += ('-l', username)
            if password != '':
                args += ('-pw', password)

        elif schema == 'shell':
            name = 'shell'
            cmd = '/bin/bash'
            args = ['--login']

        elif schema == 'shortcut':
            scs = self.shortcuts[host]
            print "opening terminals for shortcut", host,"=>", scs
            if not scs:
                print "shortcut not defined"
                return
            for sc in scs:
                mo = re.compile('^(?:(\w+)://)?(?:(\w+)(?::([^:]+))?@)?([^@:]+)(?::(\d+))?$').search(sc)
                if not mo:
                    print "bad format for shortcut", sc
                    continue
                if self.shortcuts.has_key(sc):
                    self._create_new_terminal('shortcut', sc, port, username, password)
                    continue
                (schema, scusername, scpassword, host, scport) = mo.groups()
                if schema == None:
                    schema = 'ssh'
                if username == '' and scusername != None:
                    username = scusername
                if password == '' and scpassword != None:
                    password = scpassword
                if port == '' and scport != None:
                    port = scport
                self._create_new_terminal(schema, host, port, username, password)
                #for i in range(1,250):
                #    gtk.main_iteration()
                #    # time.sleep(.01)
            return
        else:
            print "invalid schema", schema
            return

        t = self._make_terminal(name, cmd, [cmd] + args)
        self.terms.append(t)

    def main(self, argv):
        # self.make_console()

        while len(argv) > 0 and argv[0] == '-s':
            self._load_shortcuts(argv[1])
            argv = argv[2:]

        print "shortcuts:", self.shortcuts.keys()

        terms = []
        self.terms = terms
        
        for arg in argv:
            if self.shortcuts.has_key(arg):
                self._create_new_terminal('shortcut', arg, '','','')
            else:
                mo = re.compile('^(?:(\w+)://)?(?:(\w+)(?::([^:]+))?@)?([^@:]*)(?::(\d+))?$').search(arg)
                if mo:
                    (schema, username, password, host, port) = mo.groups()
                    if schema == None:
                        schema = 'ssh'
                    if username == None:
                        username = ''
                    if password == None:
                        password = ''
                    if port == None:
                        port == ''
                    t = self._create_new_terminal(schema, username, password, host, port)
                    terms.append(t)
                else:
                    print "bad url", arg

        gtk.main()

    def _load_shortcuts(self, fn):
        fd = open(fn)
        for line in fd:
            print "line:", line
            s = line.split()
            if len(s) == 0:
                continue
            if len(s) == 1:
                print "empty group", s[0], "found"
            acu = []
            map(lambda x: acu.extend(self._resolve_name(x)), s[1:])
            self.shortcuts[s[0]] = acu

    def _resolve_name(self, name):
        if self.shortcuts.has_key(name):
            return self.shortcuts[name]
        return [name]

    def _make_console(self):
        window = gtk.Window()
        window.set_title("python")
        swin = gtk.ScrolledWindow()
        swin.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_ALWAYS)
        window.add(swin)
        con = console.Console(banner="Hello there!",
                              use_rlcompleter=False,
                              start_script="from gtk import *\n")
        swin.add(con)
        window.set_default_size(500, 400)
        window.show_all()
        window.connect("destroy", gtk.main_quit)
        return con


if __name__ == '__main__':
    App().main(sys.argv[1:])