Beispiel #1
0
class clickable_eventbox(gtk.EventBox):

    gsignal('clicked')
    gsignal('popup')
    gsignal('active')
    gsignal('unactive')

    def __init__(self, widget=None, menu=None):
        gtk.EventBox.__init__(self)
        # initialise the event box
        self.add_events(gtk.gdk.BUTTON_PRESS_MASK)
        self.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
        self.connect('button-press-event', self.on_button_press_event)
        self.connect('button-release-event', self.on_button_release_event)
        self.__widget = widget
        if widget is not None:
            self.add(widget)
        self.__menu = menu
        self.__clickedstate = False

    # public API

    def popup(self, event, menu=None):
        """Popup the menu."""
        if menu is None:
            menu = self.__menu
        if menu is not None:
            menu.popup(None, None, None, event.button, event.time)
        self.emit('popup')

    def set_menu(self, menu):
        """Set the menu."""
        self.__menu = menu

    def has_menu(self):
        """Whether the widget has a menu set."""
        return self.__menu is not None

    def clicked(self):
        self.emit('clicked')

    def get_widget(self):
        return self.__widget

    def on_button_press_event(self, eventbox, event):
        if event.button == 1:
            self.grab_add()
            self.__clickedstate = True
            self.emit('active')
        elif event.button == 3:
            self.popup(event)

    def on_button_release_event(self, eventbox, event):
        if event.button == 1:
            self.grab_remove()
            if self.__clickedstate:
                self.clicked()
                self.__clickedstate = False
                self.emit('unactive')
class GtkReader(gobject.GObject):
    """Read status results from a sub process."""

    gsignal('started')

    gsignal('finished', str)

    gsignal('plain-data', str)

    gsignal('status-data', str)

    def __init__(self, scriptpath):
        self.__dirq = []
        self.scriptpath = scriptpath
        self.current_directory = None
        gobject.GObject.__init__(self)

    def ls(self, directory):
        self.__dirq.append(directory)
        if len(self.__dirq) == 1:
            self._ls()

    def _ls(self):
        qlen = len(self.__dirq)
        if not qlen:
            return
        self.emit('started')
        p = subprocess.Popen(['python', self.scriptpath, self.__dirq[0]],
                             stdout=subprocess.PIPE)
        self.__watch = gobject.io_add_watch(p.stdout, gobject.IO_IN,
                                            self.cb_read)
        gobject.io_add_watch(p.stdout.fileno(), gobject.IO_HUP, self.cb_hup)

    def _received(self, d):
        typ, data = d.split(' ', 1)
        if typ == '<p>':
            sig = 'plain-data'
        else:
            sig = 'status-data'
        self.emit(sig, data)

    def cb_read(self, fd, cond):
        d = fd.readline().strip()
        self._received(d)
        return True

    def cb_hup(self, fd, cond):
        def _f():
            gobject.source_remove(self.__watch)
            self.current_directory = self.__dirq.pop(0)
            self.emit('finished', self.current_directory)
            self._ls()

        gobject.idle_add(_f)
Beispiel #3
0
class ErrorReader(gobject.GObject):

    gsignal('started')

    gsignal('data', gobject.TYPE_PYOBJECT)

    def __init__(self):
        super(ErrorReader, self).__init__()
        self._readers = {}
        for name in [READER_PYFLAKES, READER_PYLINT, READER_PYCHECKER]:
            self._readers[name] = GobjectReader()
            self._readers[name].connect('data', self.cb_data, name)

    def run(self, filename, readers):
        self.stop_reader(READER_PYFLAKES)
        self.stop_reader(READER_PYLINT)
        self.stop_reader(READER_PYCHECKER)
        self.emit('started')
        if READER_PYFLAKES in readers:
            self.run_flakes(filename)
        if READER_PYLINT in readers:
            self.run_lint(filename)
        if READER_PYCHECKER in readers:
            self.run_checker(filename)

    def run_flakes(self, filename):
        try:
            self._readers[READER_PYFLAKES].run('pyflakes', filename)
        except OSError:
            pass

    def run_lint(self, filename):
        try:
            self._readers[READER_PYLINT].run('pylint', '--parseable=y', '-r',
                                             'n', filename)
        except OSError:
            pass

    def run_checker(self, filename):
        try:
            self._readers[READER_PYCHECKER].run(
                'pychecker', '-Q', '-q',
                '--blacklist="Tkinter,wxPython,gtk,GTK,GDK,wx,_gobject,gobject"',
                '-a', '-I', '-8', '-1', filename)
        except OSError:
            pass

    def stop_reader(self, name):
        self._readers[name].stop()

    def cb_data(self, reader, data, name):
        m = Message(data, name)
        self.emit('data', m)
Beispiel #4
0
class reactor(gobject.GObject):

    gsignal('received', object)

    def __init__(self, localsocketfile):
        gobject.GObject.__init__(self)
        self.socketfile = localsocketfile
        self.__buffers = {}

    def start(self):
        if os.path.exists(self.socketfile):
            os.remove(self.socketfile)
        self.socket = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
        self.socket.bind(self.socketfile)
        gobject.io_add_watch(self.socket, gobject.IO_IN, self.cb_read)

    def stop(self):
        os.unlink(self.socketfile)

    def cb_read(self, socket, condition):
        if condition == gobject.IO_IN:
            data, address = socket.recvfrom(6024)
            self.received_data(data, address)
        return True

    def send(self, address, data):
        self.socket.sendto(data, address)

    def local(self, address, command, *args):
        self.emit('received', [address, command, args])

    def remote(self, command, *args):
        commandstring = '%s\1%s\0' % (command, '\1'.join(args))
        self.send(commandstring)

    def received_data(self, data, address):
        buf = self.__buffers.setdefault(address, '')
        self.__buffers[address] = buf + data
        print self.__buffers
        self.process_data(address)

    def process_data(self, address):
        lines = self.__buffers[address].split('\0')
        self.__buffers[address] = lines.pop()
        for line in lines:
            self.received_line(line, address)

    def received_line(self, line, address):
        args = line.split('\1')
        command = args.pop(0)
        self.local(address, command, *args)
Beispiel #5
0
class control_box(gtk.HBox):

    gsignal('detach-clicked')
    gsignal('close-clicked')

    icon_theme = gtk.IconTheme()
    icon_theme.set_custom_theme('Humility')
    load_flags = gtk.ICON_LOOKUP_FORCE_SVG

    close_pixbuf = icon_theme.load_icon('gtk-close', 14, load_flags)
    detach_pixbuf = icon_theme.load_icon('gtk-go-up', 12, load_flags)

    def __init__(self, detach_button=True, close_button=True):
        gtk.HBox.__init__(self)
        db = clickable_eventbox(self.get_detach_image())
        db.connect('clicked', self.cb_detach_clicked)
        if detach_button:
            self.pack_start(db)
        cb = clickable_eventbox(self.get_close_image())
        cb.connect('clicked', self.cb_close_clicked)
        if close_button:
            self.pack_start(cb)

    def cb_close_clicked(self, eventbox):
        self.emit('close-clicked')

    def cb_detach_clicked(self, eventbox):
        self.emit('detach-clicked')

    def get_close_image(self):
        close_image = gtk.Image()
        close_image.set_from_pixbuf(self.close_pixbuf)
        return close_image

    def get_detach_image(self):
        detach_image = gtk.Image()
        detach_image.set_from_pixbuf(self.detach_pixbuf)
        return detach_image
Beispiel #6
0
class Pscyntilla(gobject.GObject):

    gsignal('mark-clicked', gobject.TYPE_INT, gobject.TYPE_BOOLEAN)

    def __init__(self):
        gobject.GObject.__init__(self)
        self._sc = Scintilla()
        self._setup()
        self.filename = None

    def _setup(self):
        self._setup_margins()
        self._sc.connect('key', self.cb_unhandled_key)
        self._sc.connect('char-added', self.cb_char)

    def _setup_margins(self):
        self._sc.set_margin_type_n(0, scintilla.SC_MARGIN_NUMBER)
        
        self._sc.set_margin_type_n(2, scintilla.SC_MARGIN_SYMBOL)
        self._sc.set_margin_mask_n(2, scintilla.SC_MASK_FOLDERS)
        self._sc.set_property("tab.timmy.whinge.level", "1")
        self._sc.set_property("fold.comment.python", "0")
        self._sc.set_property("fold.quotes.python", "0")
        # bp margin and marker
        self._sc.set_margin_type_n(1, scintilla.SC_MARGIN_SYMBOL)
        self._sc.set_margin_width_n(1, 14)
        self._sc.set_margin_sensitive_n(1, True)
        self._sc.set_margin_mask_n(1, ~scintilla.SC_MASK_FOLDERS)
        self._sc.marker_define(1, scintilla.SC_MARK_SMALLRECT)
        self._sc.marker_set_back(1, self._sc_colour('#900000'))
        self._sc.marker_set_fore(1, self._sc_colour('#900000'))
        # folding markers
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDEREND,
                           scintilla.SC_MARK_BOXPLUSCONNECTED)
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDEROPENMID,
                           scintilla.SC_MARK_BOXMINUSCONNECTED)
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDERMIDTAIL,
                           scintilla.SC_MARK_TCORNER)
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDERTAIL,
                           scintilla.SC_MARK_LCORNER)
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDERSUB,
                           scintilla.SC_MARK_VLINE)
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDER,
                           scintilla.SC_MARK_BOXPLUS)
        self._sc.marker_define(scintilla.SC_MARKNUM_FOLDEROPEN,
                           scintilla.SC_MARK_BOXMINUS)
        self._sc.connect('margin-click', self.cb_margin_click)

    def get_is_modified(self):
        return self._sc.get_modify() != 0

    def goto_line(self, linenumber):
        self._sc.goto_line(linenumber - 1)
        wanted = linenumber - (self._sc.lines_on_screen() / 2)
        actual = self._sc.get_first_visible_line()
        self._sc.line_scroll(0, wanted - actual)
        self._sc.grab_focus()

    def set_caret_colour(self, colour):
        self._sc.set_caret_fore(self._sc_colour(colour))

    def set_caret_line_visible(self, visible, colour=None):
        self._sc.set_caret_line_visible(visible)
        if colour is not None:
            self._sc.set_caret_line_back(self._sc_colour(colour))

    def set_currentline_visible(self, visible):
        self._sc.set_caret_line_visible(visible)

    def set_currentline_color(self, color):
        self._sc.set_caret_line_back(self._sc_colour(color))

    def set_edge_column_visible(self, visible, size):
        self._sc.set_edge_mode((visible and scintilla.EDGE_LINE) or 
            scintilla.EDGE_NONE)
        self._sc.set_edge_column(size)
    
    def set_edge_color(self, color):
        self._sc.set_edge_colour(self._sc_colour(color))

    def set_use_tabs(self, use_tabs):
        self._sc.set_use_tabs(use_tabs)

    def set_tab_width(self, tab_width):
        self._sc.set_tab_width(tab_width)

    def set_spaceindent_width(self, si_width):
        self._sc.set_indent(si_width)

    def set_linenumbers_visible(self, visible, width=32):
        if not visible:
            width = 0
        self._sc.set_margin_width_n(0, width)

    def use_folding(self, use, width=14, show_line=True):
        if use:
            self._sc.set_property('fold', '1')
            if show_line:
                self._sc.set_fold_flags(16)
        else:
            width = 0
            self._sc.set_property('fold', '0')
        self._sc.set_margin_width_n(2, width)
        self._sc.set_margin_sensitive_n(2, use)

    def set_foldmargin_colours(self, fore, back):
        b = self._sc_colour(back)
        f = self._sc_colour(fore)
        self._sc.set_fold_margin_colour(True, b)
        self._sc.set_fold_margin_hi_colour(True, b)
        for i in range(25, 32):
            self._sc.marker_set_back(i, f)
            self._sc.marker_set_fore(i, b)
        self.set_style(scintilla.STYLE_DEFAULT, fore=fore)
        
    def set_style(self, number,
                        fore=None,
                        back=None,
                        bold=None,
                        font=None,
                        size=None,
                        italic=None):
        if fore is not None:
            self._sc.style_set_fore(number, self._sc_colour(fore))
        if back is not None:
            self._sc.style_set_back(number, self._sc_colour(back))
        if bold is not None:
            self._sc.style_set_bold(number, bold)
        if font is not None:
            self._sc.style_set_font(number, '!%s' % font)
        if size is not None:
            self._sc.style_set_size(number, size)
        if italic is not None:
            self._sc.style_set_italic(number, italic)

    def set_font_name(self, font_name):
        self.set_style(scintilla.STYLE_DEFAULT, font=font_name)
    
    def set_font_size(self, font_size):
        self.set_style(scintilla.STYLE_DEFAULT, size=font_size)
    
    def set_linenumber_margin_colours(self, foreground, background):
        self.set_style(scintilla.STYLE_LINENUMBER, fore=foreground,
                        back=background)
    
    def get_widget(self):
        return self._sc

    def _sc_colour(self, colorspec):
        c = gtk.gdk.color_parse(colorspec)
        return (c.red/256) | (c.green/256) << 8 | (c.blue/256) << 16

    def load_file(self, filename):
        self.filename = filename
        f = open(filename, 'r')
        mimetype, n = mimetypes.guess_type(filename)
        
        try:
            ftype = LEXERS[mimetype]
            self._sc.set_lexer_language(ftype)
            if ftype == 'python':
                self._sc.set_key_words(0, ' '.join(kwlist))
                
        except KeyError:
            pass
        self.load_fd(f)
        self._sc.set_code_page(scintilla.SC_CP_UTF8)
        self._sc.empty_undo_buffer()
        self._sc.set_save_point()

    def grab_focus(self):
        self._sc.grab_focus()

    def cut(self):
        self._sc.cut()

    def copy(self):
        self._sc.copy()

    def paste(self):
        self._sc.paste()

    def undo(self):
        self._sc.undo()

    def redo(self):
        self._sc.redo()
    
    def revert(self):
        if self.filename is not None:
            self._sc.clear_all()
            self.load_file(self.filename)

    def can_undo(self):
        return self._sc.can_undo()

    def can_redo(self):
        return self._sc.can_redo()

    def can_paste(self):
        return self._sc.can_paste()

    def save(self):
        """Saves the current buffer to the file"""
        assert getattr(self, "filename", None) is not None
        fd = SafeFileWrite(self.filename)
        fd.write(self._sc.get_text())
        fd.close()
        self._sc.set_save_point()
        self.service.boss.call_command('buffermanager',
            'reset_current_document')

    def load_fd(self, fd):
        for line in fd:
            self._sc.append_text(line)
        self._sc.colourise(0, -1)

    def get_all_fold_headers(self):
        for i in xrange(self._sc.get_line_count()):
            level = self._sc.get_fold_level(i)
            if level & scintilla.SC_FOLDLEVELHEADERFLAG:
                yield i, level
    
    def get_toplevel_fold_headers(self):
        for i, level in self.get_all_fold_headers():
            if level & scintilla.SC_FOLDLEVELNUMBERMASK == 1024:
                yield i
    
    def collapse_all(self):
        for i in self.get_toplevel_fold_headers():
            if self._sc.get_fold_expanded(i):
                self._sc.toggle_fold(i)
    
    def expand_all(self):
        for i in self.get_toplevel_fold_headers():
            if not self._sc.get_fold_expanded(i):
                self._sc.toggle_fold(i)

    def auto_complete(self):
        pos =  self._sc.get_current_pos()
        wpos = self._sc.word_start_position(pos, True)
        linepos, line = self._sc.get_cur_line()
        word = line[linepos - (pos - wpos):linepos]
        if word:
            pattern = sre.compile(r'\W(%s.+?)\W' % word)
            text = self._sc.get_text()
            words = set(pattern.findall(text))
            self._sc.auto_c_set_choose_single(True)
            self._sc.auto_c_set_drop_rest_of_word(True)
            self._sc.auto_c_show(len(word), ' '.join(sorted(list(words))))


    def cb_margin_click(self, ed, mod, pos, margin):
        if margin == 2:
            if mod == 1:
                self.collapse_all()
            elif mod == 6:
                self.expand_all()
            else:
                line = self._sc.line_from_position(pos)
                if (self._sc.get_fold_level(line) &
                    scintilla.SC_FOLDLEVELHEADERFLAG):
                    self._sc.toggle_fold(line)
        elif margin == 1:
            # bp margin
            line = self._sc.line_from_position(pos)
            marker = self._sc.marker_get(line)
            self.emit('mark-clicked', line, marker & 2)

    def show_mark(self, line):
        self._sc.marker_add(line, 1)

    def hide_mark(self, line):
        self._sc.marker_delete(line, 1)

    def cb_unhandled_key(self, widg, *args):
        if args == (122, 4):
            i = self._sc.line_from_position(self._sc.get_current_pos())
            self._sc.toggle_fold(i)
        elif args == (83, 2):
            #TODO: emit a saved event
            self.save()
        elif args == (78, 2): # ctrl-n
            self.auto_complete()

    def cb_char(self, scint, ch):
        if ch in [10, 13]:
            pos =  self._sc.get_current_pos()
            i = self._sc.line_from_position(pos)
            text = self._sc.get_line(i - 1)

            for c in text:
                if c in '\t ':
                    self._sc.insert_text(pos, c)
                    pos = pos + 1
                    self._sc.goto_pos(pos)
                else:
                    break

    def set_background_color(self, back):
        self.set_style(scintilla.STYLE_DEFAULT,
                       back=back)
        for i in range(32):
            self.set_style(i, back=back)

    def set_selection_color(self, color):
        self._sc.set_sel_back(True, self._sc_colour(color))

    def use_dark_theme(self):
        update_style_from_schema(self, COLOR_SCHEMA, DARK)
        return
        self.set_background_color('#000033')
        self.set_style(0, fore='#f0f0f0')
        self.set_style(1, fore='#a0a0a0')
        self.set_style(2, fore='#00f000')
        self.set_style(3, fore='#c000c0')
        self.set_style(4, fore='#c000c0')
        self.set_style(5, fore='#6060fa')
        self.set_style(6, fore='#c0c000')
        self.set_style(7, fore='#c0c000')
        self.set_style(8, fore='#00f000', bold=True)
        self.set_style(9, fore='#f0a000', bold=True)
        self.set_style(10, fore='#00f0f0')
        self.set_style(11, fore='#f0f0f0')
        self.set_style(12, fore='#a0a0a0')

    def use_light_theme(self):
        update_style_from_schema(self, COLOR_SCHEMA, NATIVE)
        return
        self.set_background_color('#fafafa')
        # base
        self.set_style(0, fore='#000000')
        # comments
        self.set_style(1, fore='#909090')
        # numbers
        self.set_style(2, fore='#00a000')
        # dq strings
        self.set_style(3, fore='#600060')
        # sq strings
        self.set_style(4, fore='#600060')
        # keywords
        self.set_style(5, fore='#0000a0')
        self.set_style(6, fore='#00c000')
        # docstring
        self.set_style(7, fore='#a0a000')
        # class names
        self.set_style(8, fore='#009000')
        # func names
        self.set_style(9, fore='#a05000')
        # symbols
        self.set_style(10, fore='#c00000')
        # base
        self.set_style(11, fore='#000000')
        self.set_style(12, fore='#0000a0')

    def set_color_schema(self, schema):
        update_style_from_schema(self, COLOR_SCHEMA, schema)
Beispiel #7
0
class config_view(contentview.content_view):

    gsignal('data-changed')

    has_apply_button = False
    HAS_DETACH_BUTTON = False

    def init(self):
        self.__registries = {}
        self.__pages = {}
        self.__widgets = {}
        self.__init_widgets()
        self.__current_page_name = None

    def __init_widgets(self):
        pane = gtk.HPaned()
        self.widget.pack_start(pane)
        self.__list = config_tree()
        self.__list.set_property('markup-format-string', '%(markup)s')
        pane.pack1(self.__list)
        self.__list.set_size_request(200, -1)
        self.__list.connect('clicked', self.cb_list_clicked)
        self.__notebook = gtk.Notebook()
        pane.pack2(self.__notebook)
        self.__notebook.set_show_tabs(False)
        self.__notebook.set_show_border(False)
        self.__init_buttons()

    def __init_buttons(self):
        holder = gtk.Alignment(1, 0.5)
        holder.set_border_width(6)
        self.widget.pack_start(holder, expand=False, padding=5)
        box = gtk.HButtonBox()
        holder.add(box)
        but = gtk.Button(stock=gtk.STOCK_CANCEL)
        box.pack_start(but)
        but.connect('clicked', self.cb_cancel_clicked)
        but = gtk.Button(stock=gtk.STOCK_UNDO)
        box.pack_start(but)
        but.connect('clicked', self.cb_undo_clicked)
        but = gtk.Button(stock=gtk.STOCK_APPLY)
        if self.has_apply_button:
            box.pack_start(but)
        but.connect('clicked', self.cb_apply_clicked)
        but = gtk.Button(stock=gtk.STOCK_SAVE)
        box.pack_start(but)
        but.connect('clicked', self.cb_save_clicked)

    def __build_list(self):
        for name in self.__registries:

            class di(object):
                markup = self.service.boss.get_service_displayname(name)
                if not markup:
                    markup = name
                key = name

            self.__list.add_item(di(), key=name)

    def __build_page(self, pagename):
        if pagename in self.__pages:
            page = self.__pages[pagename]
            self.__set_current_page(page, pagename)
        elif pagename in self.__registries:
            reg = self.__registries[pagename]
            displayname = self.service.boss.get_service_displayname(pagename)
            if not displayname:
                displayname = pagename.capitalize()
            page, wids = create_notebook_from_registry(reg, displayname)
            self.__pages[pagename] = page
            for names, wid in wids:
                self.__widgets[names] = wid
            self.__notebook.append_page(page)
            page.show_all()
            self.__set_current_page(page, pagename)

    def __set_current_page(self, page, pagename):
        self.__current_page_name = pagename
        pagenum = self.__notebook.page_num(page)
        self.__notebook.set_current_page(pagenum)

    def __apply(self):
        for group, name in self.__widgets:
            self.__widgets[(group, name)].save()

    def __save(self):
        for name, registry in self.__registries.iteritems():
            registry.save()
        self.emit('data-changed')

    def __reset(self):
        pagename = self.__current_page_name
        print pagename
        for i in xrange(self.__notebook.get_n_pages()):
            self.__notebook.remove_page(i)
        self.__pages = {}
        self.__widgets = {}
        self.set_registries([(name, self.__registries[name])
                             for name in self.__registries])
        self.__list.set_selected(pagename)

    def set_registries(self, registries):
        self.__list.clear()
        first = None
        for name, reg in registries:
            if len(reg):
                if not first:
                    first = name
                self.__registries[name] = reg
        self.__build_list()
        if first is not None:
            self.__list.set_selected(first)

    def cb_list_clicked(self, listview, item):
        self.__build_page(item.key)

    def cb_undo_clicked(self, button):
        self.__reset()

    def cb_apply_clicked(self, button):
        self.__apply()

    def cb_save_clicked(self, button):
        self.__apply()
        self.__save()
        self.close()

    def cb_cancel_clicked(self, button):
        self.close()

    def show_page(self, pagename):
        self.__list.set_selected(pagename)
class FileBrowser(contentview.content_view):

    gsignal('file-activated', str)

    ICON_NAME = 'filemanager'
    LONG_TITLE = 'File manager'
    SHORT_TITLE = 'Files'
    HAS_CLOSE_BUTTON = False
    HAS_DETACH_BUTTON = False
    HAS_TITLE = False
    HAS_CONTROL_BOX = False

    def init(self, scriptpath):
        gobject.GObject.__init__(self)
        self._reader = glr.PkgresourcesReader('ls.py')
        self._reader.connect('started', self.cb_started)
        self._reader.connect('finished', self.cb_finished)
        self._reader.connect('data', self.cb_data)
        self._files = {}
        self._recent = {}
        self._visrect = None
        self._no_statuses = False
        self.cwd = None
        self.create_toolbar()
        self.create_actions()
        self.create_tree()

    def create_toolbar(self):
        self._toolbar = gtk.Toolbar()
        self.widget.pack_start(self._toolbar, expand=False)
        self._toolbar.set_icon_size(gtk.ICON_SIZE_MENU)
        self._toolbar.set_style(gtk.TOOLBAR_ICONS)

    def create_actions(self):
        self._homeact = gtk.Action('Home', 'Home', 'Browse the project root',
                                   'gtk-project')
        self.add_action_to_toolbar(self._homeact)
        self._homeact.connect('activate', self.cb_act_home)
        self._upact = gtk.Action('Up', 'Up', 'go up', gtk.STOCK_GO_UP)
        self.add_action_to_toolbar(self._upact)
        self._upact.connect('activate', self.cb_act_up)
        self._refreshact = gtk.Action('Refresh', 'Refresh',
                                      'Refresh the directory',
                                      gtk.STOCK_REFRESH)
        self.add_action_to_toolbar(self._refreshact)
        self._refreshact.connect('activate', self.cb_act_refresh)
        self._newfileact = gtk.Action('New', 'New', 'Create a new file here',
                                      gtk.STOCK_NEW)
        self.add_action_to_toolbar(self._newfileact)
        self._newfileact.connect('activate', self.cb_act_new_file)
        self._newdiract = gtk.Action('NewDir', 'New Directory',
                                     'Create a new directory here',
                                     'gtk-directory')
        self.add_action_to_toolbar(self._newdiract)
        self._newdiract.connect('activate', self.cb_act_new_dir)
        self._termact = gtk.Action('Terminal', 'Terminal',
                                   'Open a terminal in this directory',
                                   'gtk-terminal')
        self.add_action_to_toolbar(self._termact)
        self._termact.connect('activate', self.cb_act_terminal)
        self._searchact = gtk.Action('Search', 'Search',
                                     'Search files for text', 'gtk-searchtool')
        self.add_action_to_toolbar(self._searchact)
        self._searchact.connect('activate', self.cb_act_search)

    def add_action_to_toolbar(self, action):
        toolitem = action.create_tool_item()
        self._toolbar.add(toolitem)

    def create_tree(self):
        self._view = FileTree()
        self._view.set_property('markup-format-string', '%(markup)s')
        self._view.connect('clicked', self.cb_click)
        self._view.connect('double-clicked', self.cb_double_click)
        self._view.connect('right-clicked', self.cb_right_click)
        self.widget.pack_start(self._view)
        return self._view

    def browse(self, directory=None):
        if directory is None:
            directory = os.path.expanduser('~')
        self.service.events.emit('directory_changed', directory=directory)
        if directory in self._recent:
            self._view.clear()
            for fsi in self._recent[directory].values():
                self._view.add_item(fsi)
            self.cwd = directory
            self.long_title = self.cwd
        else:
            self._no_statuses = False
            self._reader.run(directory)

    def browse_up(self):
        directory = self.cwd
        if directory is not None and directory != '/':
            parent = os.path.dirname(directory)
            self.browse(parent)

    def forget(self, directory):
        if directory in self._recent:
            del self._recent[directory]

    def refresh(self):
        if self.cwd is not None:
            self.forget(self.cwd)
            self._visrect = self._view.view.get_visible_rect()
            self.browse(self.cwd)

    def cb_started(self, reader):
        self._files = {}
        self._view.clear()

    def cb_finished(self, reader, args):
        if self._no_statuses:
            for f in self._files.values():
                f.status = 2
                f.reset_markup()
        self.cwd = args[-1]
        self._recent[self.cwd] = self._files
        self.long_title = self.cwd
        if self._visrect is not None:
            self._view.view.scroll_to_point(self._visrect.x, self._visrect.y)
            self._visrect = None

    def cb_data(self, reader, data):
        typ, data = data.split(' ', 1)
        if typ == '<p>':
            sig = self.cb_plain_data
        else:
            sig = self.cb_status_data
        sig(reader, data)

    def cb_plain_data(self, reader, path):
        if path not in self._files:
            fsi = FileSystemItem(path)
            self._files[path] = fsi
            self._view.add_item(fsi)

    def cb_status_data(self, reader, path):
        status, path = path.split(' ', 1)
        if status == '<s>':
            self._no_statuses = True
        else:
            try:
                status = int(status)
            except:
                return
            if path in self._files:
                f = self._files[path]
                f.status = status
                f.reset_markup()
            else:
                f = FileSystemItem(path)
                self._files[path] = f
                f.status = status
                self._view.add_item(f)

    def cb_click(self, tv, item):
        pass

    def cb_double_click(self, tv, item):
        fsi = item.value
        if fsi.isdir:
            self.browse(fsi.path)
        else:
            self.emit('file-activated', fsi.path)

    def cb_act_up(self, action):
        self.browse_up()

    def cb_act_refresh(self, action):
        self.refresh()

    def cb_act_home(self, action):
        project = self.service.boss.call_command('projectmanager',
                                                 'get_current_project')
        if project is not None:
            project_root = project.source__directory
            self.service.call('browse', directory=project_root)
        else:
            self.service.log.info('there is no project to go to its root')

    def cb_act_new_file(self, action):
        self.service.boss.call_command('newfile',
                                       'create_interactive',
                                       directory=self.cwd)

    def cb_act_new_dir(self, action):
        self.service.boss.call_command('newfile',
                                       'create_interactive',
                                       directory=self.cwd,
                                       mkdir=True)

    def cb_act_terminal(self, action):
        self.service.boss.call_command('terminal',
                                       'execute_shell',
                                       kwdict={'directory': self.cwd})

    def cb_act_search(self, action):
        self.service.boss.call_command('grepper',
                                       'find_interactive',
                                       directories=[self.cwd])

    def _popup_file(self, path, event):
        menu = self.service.boss.call_command('contexts',
                                              'get_context_menu',
                                              ctxname='file',
                                              ctxargs=[path])
        menu.get_children()[0].hide()
        action = self.service.action_group.get_action('filemanager+open')
        mi = action.create_menu_item()
        menu.insert(mi, 0)
        menu.popup(None, None, None, event.button, event.time)

    def _popup_dir(self, path, event):
        menu = self.service.boss.call_command('contexts',
                                              'get_context_menu',
                                              ctxname='directory',
                                              ctxargs=[path])
        menu.popup(None, None, None, event.button, event.time)

    def cb_right_click(self, view, fileitem, event):
        if fileitem is None:
            return
        fsi = fileitem.value
        if os.path.isdir(fsi.path):
            self._popup_dir(fsi.path, event)
        else:
            self._popup_file(fsi.path, event)
Beispiel #9
0
class FileBrowser(contentview.content_view):

    gsignal('file-activated', str)

    ICON_NAME = 'filemanager'
    LONG_TITLE = 'File manager'
    SHORT_TITLE = 'Files'
    HAS_CLOSE_BUTTON = False
    HAS_DETACH_BUTTON = False
    HAS_TITLE = False
    HAS_CONTROL_BOX = False

    def init(self, scriptpath):
        gobject.GObject.__init__(self)
        self.cwd = None
        self.create_toolbar()
        self.create_actions()
        self.create_tree()
        self.counter = 0

    def create_toolbar(self):
        self._toolbar = gtk.Toolbar()
        self.widget.pack_start(self._toolbar, expand=False)
        self._toolbar.set_icon_size(gtk.ICON_SIZE_MENU)
        self._toolbar.set_style(gtk.TOOLBAR_ICONS)

    def create_actions(self):
        self._tips = gtk.Tooltips()
        self._homeact = gtk.Action('Home', 'Home', 'Browse the project root',
                                   'gtk-project')
        self.add_action_to_toolbar(self._homeact)
        self._homeact.connect('activate', self.cb_act_home)
        self._upact = gtk.Action('Up', 'Up', 'Browse the parent directory',
                                 gtk.STOCK_GO_UP)
        self.add_action_to_toolbar(self._upact)
        self._upact.connect('activate', self.cb_act_up)
        self._refreshact = gtk.Action('Refresh', 'Refresh',
                                      'Refresh the directory',
                                      gtk.STOCK_REFRESH)
        self.add_action_to_toolbar(self._refreshact)
        self._refreshact.connect('activate', self.cb_act_refresh)
        self._hidden_act = gtk.ToggleAction('ShowHidden', 'ShowHidden',
                                            'Show the hidden files',
                                            'gtk-hidden')
        self._hidden_act.connect('toggled', self.cb_show_hidden)
        self.add_action_to_toolbar(self._hidden_act)
        self._newfileact = gtk.Action('New', 'New', 'Create a new file here',
                                      gtk.STOCK_NEW)
        #self.add_action_to_toolbar(self._newfileact)
        self._newfileact.connect('activate', self.cb_act_new_file)
        self._newdiract = gtk.Action('NewDir', 'New Directory',
                                     'Create a new directory here',
                                     'gtk-directory')
        self.add_action_to_toolbar(self._newdiract)
        self._newdiract.connect('activate', self.cb_act_new_dir)
        self._termact = gtk.Action('Terminal', 'Terminal',
                                   'Open a terminal in this directory',
                                   'gtk-terminal')
        self.add_action_to_toolbar(self._termact)
        self._termact.connect('activate', self.cb_act_terminal)
        self._searchact = gtk.Action('Search', 'Search',
                                     'Search files for text', 'gtk-searchtool')
        self.add_action_to_toolbar(self._searchact)
        self._searchact.connect('activate', self.cb_act_search)

    def add_action_to_toolbar(self, action):
        toolitem = action.create_tool_item()
        self._toolbar.add(toolitem)
        toolitem.set_tooltip(self._tips, action.props.tooltip)
        return toolitem

    def create_tree(self):
        self._view = FileTree()
        self._view.set_property('markup-format-string', '%(markup)s')
        self._view.connect('double-clicked', self.cb_double_click)
        self._view.connect('right-clicked', self.cb_right_click)
        self.widget.pack_start(self._view)
        return self._view

    def check_counter(self, counter):
        return counter == self.counter

    def browse(self, directory=None):
        if directory is None:
            directory = os.path.expanduser('~')
        self.service.events.emit('directory_changed', directory=directory)
        self.counter = self.counter + 1
        lister = StatusLister(self._view, self.counter, self.check_counter,
                              self.get_show_hidden())
        self._view.clear()
        self.cwd = directory
        lister.list(directory)

    def browse_up(self):
        directory = self.cwd
        if directory is not None and directory != '/':
            parent = os.path.dirname(directory)
            self.browse(parent)

    def refresh(self):
        if self.cwd is not None:
            self._visrect = self._view.view.get_visible_rect()
            self.browse(self.cwd)

    def cb_double_click(self, tv, item):
        fsi = item.value
        if fsi.isdir:
            self.browse(fsi.path)
        else:
            self.emit('file-activated', fsi.path)

    def cb_act_up(self, action):
        self.browse_up()

    def cb_act_refresh(self, action):
        self.refresh()

    def cb_act_home(self, action):
        project = self.service.boss.call_command('projectmanager',
                                                 'get_current_project')
        if project is not None:
            project_root = project.source__directory
            self.service.call('browse', directory=project_root)
        else:
            self.service.log.info('there is no project to go to its root')

    def cb_show_hidden(self, action):
        self.refresh()

    def get_show_hidden(self):
        return self._hidden_act.get_active()

    def cb_act_new_file(self, action):
        self.service.boss.call_command('newfile',
                                       'create_interactive',
                                       directory=self.cwd)

    def cb_act_new_dir(self, action):
        self.service.boss.call_command('newfile',
                                       'create_interactive',
                                       directory=self.cwd,
                                       mkdir=True)

    def cb_act_terminal(self, action):
        self.service.boss.call_command('terminal',
                                       'execute_shell',
                                       kwdict={'directory': self.cwd})

    def cb_act_search(self, action):
        self.service.boss.call_command('grepper',
                                       'find_interactive',
                                       directories=[self.cwd])

    def _popup_file(self, path, event):
        menu = self.service.boss.call_command('contexts',
                                              'get_context_menu',
                                              ctxname='file',
                                              ctxargs=[path])
        menu.get_children()[0].hide()
        action = self.service.action_group.get_action('filemanager+open')
        mi = action.create_menu_item()
        menu.insert(mi, 0)
        menu.popup(None, None, None, event.button, event.time)

    def _popup_dir(self, path, event):
        menu = self.service.boss.call_command('contexts',
                                              'get_context_menu',
                                              ctxname='directory',
                                              ctxargs=[path])
        menu.popup(None, None, None, event.button, event.time)

    def cb_right_click(self, view, fileitem, event):
        if fileitem is None:
            return
        fsi = fileitem.value
        if os.path.isdir(fsi.path):
            self._popup_dir(fsi.path, event)
        else:
            self._popup_file(fsi.path, event)