Beispiel #1
0
class OutlineDialog(BuilderAware):
    def __init__(self):
        super(OutlineDialog, self).__init__(join_to_file_dir(__file__, "outline.glade"))
        self.shortcuts = ShortcutActivator(self.window)
        self.shortcuts.bind("Escape", self.hide)
        self.shortcuts.bind("<alt>s", self.focus_search)

        set_activate_the_one_item(self.search_entry, self.outline_tree)

    def show(self, editor):
        self.tree = None
        self.editor = weakref.ref(editor)
        self.search_entry.grab_focus()

        editor.request_transient_for.emit(self.window)
        self.window.present()

        idle(self.fill)

    def get_tree(self):
        if not self.tree:
            visitor = OutlineVisitor()
            try:
                tree = parse_bad_code(self.editor().text)
                visitor.visit(tree)
                self.tree = visitor.nodes
            except (SyntaxError, IndentationError), e:
                print e
                self.tree = []

        return self.tree
Beispiel #2
0
class PluginDialog(BuilderAware):
    def __init__(self):
        BuilderAware.__init__(self, join_to_file_dir(__file__, 'plugin_prefs.glade'))
        self.activator = ShortcutActivator(self.window)
        self.activator.bind('Escape', self.hide)

        self.plugins_tree.get_columns()[0].get_cell_renderers()[0].props.activatable = True

    def show(self, enabled_plugins, callback):
        self.callback = callback
        self.fill_plugin_list(enabled_plugins)
        self.window.present()

    def hide(self):
        enabled_plugins = [p[1] for p in self.plugins if p[0]]
        self.callback(enabled_plugins)
        self.window.destroy()

    def on_delete_event(self, *args):
        idle(self.hide)
        return True

    def get_aviable_plugins(self):
        for pname in discover_plugins():
            try:
                package = get_plugin(pname)
            except:
                pass

            name = getattr(package, 'name', pname)
            desc = getattr(package, 'desc', 'Some weird plugin')
            markup = "<b>%s</b>\n<small>%s</small>" % tuple(
                map(markup_escape_text, (name, desc)))

            yield (pname, markup, name)

    def fill_plugin_list(self, enabled):
        self.plugins.clear()

        for p in sorted(self.get_aviable_plugins(), key=lambda r: r[-1]):
            self.plugins.append((p[0] in enabled,) + p)

        self.plugins_tree.columns_autosize()
        self.plugins_tree.set_cursor("0", self.plugins_tree.get_columns()[0])

    def on_enabled_toggled(self, renderer, path):
        iter = self.plugins.get_iter(path)
        self.plugins.set_value(iter, 0, not renderer.get_active())
Beispiel #3
0
class PreferencesDialog(BuilderAware):
    def __init__(self):
        BuilderAware.__init__(self, join_to_file_dir(__file__, 'prefs.glade'))

        from snaked.core.shortcuts import ShortcutActivator
        self.activator = ShortcutActivator(self.window)
        self.activator.bind('Escape', self.hide)
        self.activator.bind('<alt>s', self.focus_search)

        set_activate_the_one_item(self.search_entry, self.dialogs_view)

    def hide(self):
        self.window.destroy()

    def show(self, editor):
        self.editor = weakref.ref(editor)
        self.fill_dialogs(None)
        editor.request_transient_for.emit(self.window)
        self.window.show()

    def fill_dialogs(self, search):
        self.dialogs.clear()

        for name in sorted(prefs.registered_dialogs):
            keywords, show_func = prefs.registered_dialogs[name]
            if not search or any(w.startswith(search) for w in keywords):
                markup = '<b>%s</b>\n<small>%s</small>' % (
                    name, u' \u2022 '.join(keywords))
                self.dialogs.append((name, markup))

    def on_delete_event(self, *args):
        return False

    def on_search_entry_changed(self, *args):
        search = self.search_entry.get_text().strip().lower()
        idle(self.fill_dialogs, search)

    def activate(self, *args):
        (model, iter) = self.dialogs_view.get_selection().get_selected()
        if iter:
            name = model.get_value(iter, 0)
            prefs.registered_dialogs[name][1](self.editor())
            idle(self.hide)
        else:
            self.editor().message('You need select item')

    def focus_search(self):
        self.search_entry.grab_focus()
Beispiel #4
0
 def __init__(self):
     super(OutlineDialog, self).__init__(join_to_file_dir(__file__, 'outline.glade'))
     self.shortcuts = ShortcutActivator(self.window)
     self.shortcuts.bind('Escape', self.hide)
     self.shortcuts.bind('<alt>s', self.focus_search)
     
     set_activate_the_one_item(self.search_entry, self.outline_tree)
Beispiel #5
0
    def __init__(self):
        BuilderAware.__init__(self, join_to_file_dir(__file__, 'prefs.glade'))

        from snaked.core.shortcuts import ShortcutActivator
        self.activator = ShortcutActivator(self.window)
        self.activator.bind('Escape', self.hide)
        self.activator.bind('<alt>s', self.focus_search)

        set_activate_the_one_item(self.search_entry, self.dialogs_view)
Beispiel #6
0
    def __init__(self):
        super(QuickOpenDialog, self).__init__(join_to_file_dir(__file__, 'gui.glade'))
        self.shortcuts = ShortcutActivator(self.window)
        self.shortcuts.bind('Escape', self.escape)
        self.shortcuts.bind('<alt>Up', self.project_up)
        self.shortcuts.bind('<alt>Down', self.project_down)
        self.shortcuts.bind('<ctrl>Return', self.open_mime)
        self.shortcuts.bind('<alt>s', self.focus_search)
        self.shortcuts.bind('<ctrl>o', self.free_open)
        self.shortcuts.bind('<ctrl>p', self.popup_projects)
        self.shortcuts.bind('<ctrl>Delete', self.delete_project)
        self.shortcuts.bind('<ctrl>h', self.toggle_hidden)
        self.shortcuts.bind('BackSpace', self.browse_top)

        set_activate_the_one_item(self.search_entry, self.filelist_tree)
Beispiel #7
0
    def __init__(self):
        super(EditorListDialog, self).__init__(join_to_file_dir(__file__, 'gui.glade'))
        self.shortcuts = ShortcutActivator(self.window)
        self.shortcuts.bind('Escape', self.hide)
        self.shortcuts.bind('Delete', self.close_editor)

        self.editor = None
        self.block_cursor = False

        self.path2uri = {}
        self.paths = []
        self.editors_view.set_search_equal_func(search_func)
        self.editors_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        self.mnemonic_renderer.set_property('yalign', 0.5)
        self.mnemonic_renderer.set_property('weight', pango.WEIGHT_BOLD)
        self.mnemonic_renderer.set_property('width', 5)
        self.mnemonic_hole.set_property('width', 20)

        for i, m in enumerate(mnemonics):
            self.shortcuts.bind('<alt>'+m, self.mnemonic_activate, i)
Beispiel #8
0
    def __init__(self):
        BuilderAware.__init__(self, join_to_file_dir(__file__, 'plugin_prefs.glade'))
        self.activator = ShortcutActivator(self.window)
        self.activator.bind('Escape', self.hide)

        self.plugins_tree.get_columns()[0].get_cell_renderers()[0].props.activatable = True
Beispiel #9
0
class OutlineDialog(BuilderAware):
    def __init__(self):
        super(OutlineDialog, self).__init__(join_to_file_dir(__file__, 'outline.glade'))
        self.shortcuts = ShortcutActivator(self.window)
        self.shortcuts.bind('Escape', self.hide)
        self.shortcuts.bind('<alt>s', self.focus_search)
        
        set_activate_the_one_item(self.search_entry, self.outline_tree)

    def show(self, editor):
        self.editor = weakref.ref(editor)
        self.search_entry.grab_focus()
        
        editor.request_transient_for.emit(self.window)
        self.window.present()
        
        idle(self.fill)

    def hide(self):
        self.window.hide()
        
    def on_delete_event(self, *args):
        self.hide()
        return True

    def goto_name(self, *args):
        (model, iter) = self.outline_tree.get_selection().get_selected()
        if iter:
            self.hide()
            self.editor().add_spot()
            self.editor().goto_line(model.get_value(iter, 2))
        else:
            self.editor().message('You need select item')
            
    def on_search_entry_changed(self, *args):
        what = self.search_entry.get_text().strip()
        if what:
            idle(self.filter, what)
        else:
            idle(self.fill)
    
    def fill(self):
        self.outline.clear()
        current_search = object()
        self.current_search = current_search
        
        roots = (None, None)
        ptop = ()
        
        i = 0
        for top, name, line in get_outline(self.editor().text):
            if self.current_search is not current_search:
                return

            if len(top) == len(ptop):
                roots = roots[:-1] + (self.outline.append(roots[-2], (name, '', line)),)
            elif len(top) > len(ptop):
                roots = roots + (self.outline.append(roots[-1], (name, '', line)),)
            else:
                delta = len(ptop) - len(top) + 1
                roots = roots[:-delta] + (self.outline.append(roots[-delta-1], (name, '', line)),)

            ptop = top
            
            if i % 10 == 0:
                self.outline_tree.expand_all()
                self.outline_tree.columns_autosize()
                refresh_gui()
                
            i += 1

            self.outline_tree.expand_all()
            self.outline_tree.columns_autosize()
                
    def filter(self, search):
        self.outline.clear()
        
        current_search = object()
        self.current_search = current_search
        
        already_matched = {}
        i = 0
        
        def name_starts(name):
            return name.startswith(search)
            
        def name_contains(name):
            return search in name
        
        outline = list(get_outline(self.editor().text))
        
        for m in (name_starts, name_contains):
            for top, name, line in outline:
                if self.current_search is not current_search:
                    return
                
                if (top, name) in already_matched: continue
                
                if m(name):
                    already_matched[(top, name)] = True            
                    self.outline.append(None, (name, u'/'.join(top), line))
                
                if i % 10 == 0:
                    refresh_gui()
                    
                i += 1

        self.outline_tree.columns_autosize()

    def focus_search(self):
        self.search_entry.grab_focus()
Beispiel #10
0
class EditorListDialog(BuilderAware):
    """glade-file: gui.glade"""

    def __init__(self):
        super(EditorListDialog, self).__init__(join_to_file_dir(__file__, 'gui.glade'))
        self.shortcuts = ShortcutActivator(self.window)
        self.shortcuts.bind('Escape', self.hide)
        self.shortcuts.bind('Delete', self.close_editor)

        self.editor = None
        self.block_cursor = False

        self.path2uri = {}
        self.paths = []
        self.editors_view.set_search_equal_func(search_func)
        self.editors_view.get_selection().set_mode(gtk.SELECTION_MULTIPLE)

        self.mnemonic_renderer.set_property('yalign', 0.5)
        self.mnemonic_renderer.set_property('weight', pango.WEIGHT_BOLD)
        self.mnemonic_renderer.set_property('width', 5)
        self.mnemonic_hole.set_property('width', 20)

        for i, m in enumerate(mnemonics):
            self.shortcuts.bind('<alt>'+m, self.mnemonic_activate, i)

    def show(self, editor, editors, recent_editors):
        self.first_show = self.editor is None
        self.editor = weakref.ref(editor)
        self.editor_list = editors
        self.recent_editors = recent_editors

        self.block_cursor = True
        self.fill()
        editor.request_transient_for.emit(self.window)
        self.window.present()
        self.block_cursor = False

    def fill(self):
        self.editors.clear()
        self.path2uri.clear()
        self.paths[:] = []

        active_editor = self.editor()
        titles = [(e.get_title.emit(), e) for e in self.editor_list]
        editor_uris = {}

        def append(uri, title, weight, mnemonic_idx):
            if mnemonic_idx < len(mnemonics):
                m = '<b><small>%s</small></b>' % mnemonics[mnemonic_idx]
            else:
                m = ''

            iter = self.editors.append(None, (title, weight, m))
            path = self.editors.get_path(iter)
            self.path2uri[path] = uri
            self.paths.append(path)

        for i, (t, e) in enumerate(sorted(titles, key=lambda r: r[0])):
            editor_uris[e.uri] = True
            weight = pango.WEIGHT_BOLD if e is active_editor else pango.WEIGHT_NORMAL
            append(e.uri, t, weight, i)

        recent_titles = [(u, t) for u, t in self.recent_editors.items() if u not in editor_uris]
        if recent_titles:
            self.editors.append(None, ('----=== Recent ===----', pango.WEIGHT_NORMAL, ''))
            for u, t in sorted(recent_titles, key=lambda r: r[1]):
                i += 1
                append(u, t, pango.WEIGHT_NORMAL, i)

    def hide(self):
        self.window.hide()

    def on_delete_event(self, *args):
        self.escape()
        return True

    def close_editor_by_uri(self, uri):
        for e in self.editor_list:
            if uri == e.uri:
                e.request_close.emit()
                break

    def close_editor(self, *args):
        model, pathes = self.editors_view.get_selection().get_selected_rows()
        for p in pathes:
            if p in self.path2uri:
                self.close_editor_by_uri(self.path2uri[p])

        refresh_gui()
        if self.editor_list:
            idle(self.fill)
        else:
            self.hide()

    def activate_editor(self, path):
        if path in self.path2uri:
            idle(self.editor().open_file, self.path2uri[path])
            idle(self.hide)

    def on_editors_view_row_activated(self, view, path, *args):
        self.activate_editor(path)

    def on_editors_view_cursor_changed(self, *args):
        editor = self.editor()
        if editor and editor.snaked_conf['EDITOR_LIST_SWITCH_ON_SELECT'] and not self.block_cursor:
            path, _ = self.editors_view.get_cursor()
            if path in self.path2uri:
                idle(editor.open_file, self.path2uri[path])

    def mnemonic_activate(self, idx):
        if idx < len(self.paths):
            self.activate_editor(self.paths[idx])
Beispiel #11
0
class QuickOpenDialog(BuilderAware):
    """glade-file: gui.glade"""

    def __init__(self):
        super(QuickOpenDialog, self).__init__(join_to_file_dir(__file__, 'gui.glade'))
        self.shortcuts = ShortcutActivator(self.window)
        self.shortcuts.bind('Escape', self.escape)
        self.shortcuts.bind('<alt>Up', self.project_up)
        self.shortcuts.bind('<alt>Down', self.project_down)
        self.shortcuts.bind('<ctrl>Return', self.open_mime)
        self.shortcuts.bind('<alt>s', self.focus_search)
        self.shortcuts.bind('<ctrl>o', self.free_open)
        self.shortcuts.bind('<ctrl>p', self.popup_projects)
        self.shortcuts.bind('<ctrl>Delete', self.delete_project)
        self.shortcuts.bind('<ctrl>h', self.toggle_hidden)
        self.shortcuts.bind('BackSpace', self.browse_top)

        set_activate_the_one_item(self.search_entry, self.filelist_tree)

    def get_stored_recent_projects(self):
        return self.editor().snaked_conf['QUICK_OPEN_RECENT_PROJECTS']

    def store_recent_projects(self, projects):
        self.editor().snaked_conf['QUICK_OPEN_RECENT_PROJECTS'] = list(projects)

    def show(self, editor):
        self.editor = weakref.ref(editor)
        self.update_recent_projects()
        self.update_projects(editor.get_project_root(larva=True))
        editor.request_transient_for.emit(self.window)

        self.search_entry.grab_focus()

        self.window.present()

    def update_recent_projects(self):
        saved_projects = self.get_stored_recent_projects()

        if any(p not in saved_projects for p in settings.recent_projects):
            [saved_projects.append(p) for p in settings.recent_projects
                if p not in saved_projects]
            self.store_recent_projects(saved_projects)
            settings.recent_projects = saved_projects
            return

        if any(p not in settings.recent_projects for p in saved_projects):
            [settings.recent_projects.append(p) for p in saved_projects
                if p not in settings.recent_projects]

    def update_projects(self, root):
        old_root = self.get_current_root()

        self.projects_cbox.handler_block_by_func(self.on_projects_cbox_changed)

        self.projects_cbox.set_model(None)
        self.projectlist.clear()

        index = 0
        for i, r in enumerate(settings.recent_projects):
            if r == root:
                index = i
            self.projectlist.append((r,))

        for i, r in enumerate(reversed(sorted(settings.larva_projects, key=lambda r:len(r)))):
            if r == root:
                index = i + len(settings.recent_projects)
            self.projectlist.append((r,))

        if not len(self.projectlist):
            self.projectlist.append((os.getcwd(),))

        self.projects_cbox.set_model(self.projectlist)
        self.projects_cbox.set_active(index)

        self.projects_cbox.handler_unblock_by_func(self.on_projects_cbox_changed)

        if self.get_current_root() != old_root:
            self.on_search_entry_changed()

    def hide(self):
        self.current_search = None
        self.window.hide()

    def on_delete_event(self, *args):
        self.escape()
        return True

    def project_up(self):
        idx = self.projects_cbox.get_active()
        idx = ( idx - 1 ) % len(self.projectlist)
        self.projects_cbox.set_active(idx)

    def project_down(self):
        idx = self.projects_cbox.get_active()
        idx = ( idx + 1 ) % len(self.projectlist)
        self.projects_cbox.set_active(idx)

    def get_current_root(self):
        try:
            idx = self.projects_cbox.get_active()
            if idx >=0:
                return self.projectlist[idx][0]
        except IndexError:
            pass

        return None

    def fill_filelist(self, search, current_search):
        self.filelist.clear()

        already_matched = {}
        counter = [-1]

        def tick():
            counter[0] += 1
            if counter[0] % 50 == 0:
                refresh_gui()
                if self.current_search is not current_search:
                    raise StopIteration()

        root = self.get_current_root()

        try:
            bad_re = settings.ignore_contexts[root]['ignore']
            def bad_matcher(path):
                return bad_re.search(path)

        except KeyError:
            bad_matcher = None

        for m in (searcher.name_start_match, searcher.name_match,
                searcher.path_match, searcher.fuzzy_match):
            for p in searcher.search(root, '', m(search), already_matched, bad_matcher, tick):
                if self.current_search is not current_search:
                    return

                already_matched[p] = True
                self.filelist.append(p)

                if len(self.filelist) > 150:
                    self.filelist_tree.columns_autosize()
                    return

        self.filelist_tree.columns_autosize()

    def fill_with_dirs(self, top='', place=False):
        self.filelist.clear()

        dirs = []
        files = []

        conf = self.editor().snaked_conf
        hidden_masks = None
        if not conf['QUICK_OPEN_SHOW_HIDDEN']:
            hidden_masks = conf['QUICK_OPEN_HIDDEN_FILES']

        if top and not top.endswith('/'):
            top += '/'

        root = os.path.join(self.get_current_root(), top)
        for name in os.listdir(root):
            if hidden_masks and any(name.endswith(m) for m in hidden_masks):
                continue

            path = os.path.join(root, name)
            if os.path.isdir(path):
                dirs.append(name+'/')
            else:
                files.append(name)

        place_idx = 0
        for i, name in enumerate(sorted(dirs)):
            if name == place:
                place_idx = i
            self.filelist.append((name, top))

        for i, name in enumerate(sorted(files)):
            if name == place:
                place_idx = i + len(dirs)
            self.filelist.append((name, top))

        self.filelist_tree.columns_autosize()

        if place and len(self.filelist):
            self.filelist_tree.set_cursor((place_idx,))

    def on_search_entry_changed(self, *args):
        search = self.search_entry.get_text().strip()
        self.current_search = object()
        if search:
            idle(self.fill_filelist, search, self.current_search)
        else:
            idle(self.fill_with_dirs)

    def on_projects_cbox_changed(self, *args):
        self.on_search_entry_changed()

    def get_selected_file(self):
        (model, iter) = self.filelist_tree.get_selection().get_selected()
        if iter:
            name, top = self.filelist.get(iter, 0, 1)
            return os.path.join(self.get_current_root(), top, name), name, top
        else:
            return None, None, None

    def open_file(self, *args):
        fname, name, top = self.get_selected_file()
        if fname:
            if os.path.isdir(fname):
                idle(self.fill_with_dirs, os.path.join(top, name), True)
            else:
                self.hide()
                refresh_gui()
                self.editor().open_file(fname)

    def open_mime(self):
        fname, name, top = self.get_selected_file()
        if fname:
            self.hide()
            refresh_gui()
            open_mime(fname)

    def focus_search(self):
        self.search_entry.grab_focus()

    def escape(self):
        if hasattr(self.editor(), 'on_dialog_escape'):
            idle(self.editor().on_dialog_escape, self)
        self.hide()

    def free_open(self):
        dialog = gtk.FileChooserDialog("Open file...",
            None,
            gtk.FILE_CHOOSER_ACTION_OPEN,
            (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
            gtk.STOCK_OPEN, gtk.RESPONSE_OK))

        dialog.set_default_response(gtk.RESPONSE_OK)

        response = dialog.run()
        if response == gtk.RESPONSE_OK:
            idle(self.editor().open_file, dialog.get_filename())
            idle(self.hide)

        dialog.destroy()

    def popup_projects(self):
        self.projects_cbox.popup()

    def delete_project(self):
        if len(self.projectlist):
            current_root = self.get_current_root()
            if current_root == self.editor().project_root:
                self.editor().message('You can not remove current project')
                return
            settings.recent_projects.remove(current_root)
            self.store_recent_projects(settings.recent_projects)

            idx = self.projects_cbox.get_active()
            self.projectlist.remove(self.projects_cbox.get_active_iter())
            self.projects_cbox.set_active(idx % len(self.projectlist))
            self.editor().message('Project removed')

    def browse_top(self):
        if not self.filelist_tree.is_focus():
            return False

        if self.search_entry.get_text():
            self.editor().message('You are not in browse mode')
            return

        fname, name, top = self.get_selected_file()
        if fname:
            if not top:
                self.editor().message('No way!')
            else:
                place = os.path.basename(os.path.dirname(top)) + '/'
                idle(self.fill_with_dirs, os.path.dirname(os.path.dirname(top)), place)

    def toggle_hidden(self):
        if self.search_entry.get_text():
            self.editor().message('You are not in browse mode')
            return

        conf = self.editor().snaked_conf
        conf['QUICK_OPEN_SHOW_HIDDEN'] = not conf['QUICK_OPEN_SHOW_HIDDEN']

        self.editor().message('Show hidden files' if conf['QUICK_OPEN_SHOW_HIDDEN'] else
            'Do not show hidden files' )

        fname, name, top = self.get_selected_file()
        if fname:
            idle(self.fill_with_dirs, top, name)
        else:
            if len(self.filelist):
                name, top = self.filelist[0]
                idle(self.fill_with_dirs, top)
Beispiel #12
0
class PreferencesDialog(BuilderAware):
    """glade-file: prefs.glade"""

    def __init__(self, existing_snippets):
        BuilderAware.__init__(self, join_to_file_dir(__file__, 'prefs.glade'))

        from snaked.core.shortcuts import ShortcutActivator
        self.activator = ShortcutActivator(self.window)
        self.activator.bind('Escape', self.hide)
        self.activator.bind('<alt>s', self.focus_search)
        self.existing_snippets = existing_snippets

        set_activate_the_one_item(self.search_entry, self.snippets_view)

    def hide(self):
        self.window.destroy()

    def show(self, editor):
        self.editor = weakref.ref(editor)
        self.fill_snippets(None)
        editor.request_transient_for.emit(self.window)
        self.window.show()

    def fill_snippets(self, search):
        self.snippets.clear()
        for name in sorted(self.existing_snippets):
            if not search or search in name:
                self.snippets.append((name,))

    def on_delete_event(self, *args):
        return False

    def on_search_entry_changed(self, *args):
        search = self.search_entry.get_text().strip().lower()
        idle(self.fill_snippets, search)

    def activate(self, *args):
        (model, iter) = self.snippets_view.get_selection().get_selected()
        if iter:
            name = model.get_value(iter, 0)
            self.edit_context(name)
        else:
            self.editor().message('You need select item')

    def focus_search(self):
        self.search_entry.grab_focus()

    def edit_context(self, ctx):
        user_snippet_filename = join_to_settings_dir('snippets', ctx + '.snippets')
        if ctx in self.existing_snippets and \
                self.existing_snippets[ctx] != user_snippet_filename:

            import shutil
            make_missing_dirs(user_snippet_filename)
            shutil.copy(self.existing_snippets[ctx], user_snippet_filename)

        idle(self.hide)
        e = self.editor().open_file(user_snippet_filename)
        e.connect('file-saved', on_snippet_saved, ctx)

    def on_create_snippet_activate(self, button):
        ctx = self.search_entry.get_text()
        if ctx:
            self.edit_context(ctx)
        else:
            self.editor().message('Enter snippet name in search entry', 3000)