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
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())
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()
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 __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 __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 __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 __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
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()
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])
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)
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)