xed/plugins/snippets/snippets/Manager.py

1158 lines
48 KiB
Python
Executable File

# Pluma snippets plugin
# Copyright (C) 2005-2006 Jesse van den Kieboom <jesse@icecrew.nl>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
import os
import tempfile
import shutil
import gobject
import gtk
from gtk import gdk
import gtksourceview2 as gsv
import pango
import pluma
import gio
from Snippet import Snippet
from Helper import *
from Library import *
from Importer import *
from Exporter import *
from Document import Document
from LanguageManager import get_language_manager
class Manager:
NAME_COLUMN = 0
SORT_COLUMN = 1
OBJ_COLUMN = 2
TARGET_URI = 105
model = None
drag_icons = ('mate-mime-application-x-tarz', 'mate-package', 'package')
default_export_name = _('Snippets archive') + '.tar.gz'
dragging = False
dnd_target_list = [('text/uri-list', 0, TARGET_URI)]
def __init__(self, datadir):
self.datadir = datadir
self.snippet = None
self.dlg = None
self._temp_export = None
self.snippets_doc = None
self.manager = None
self.default_size = None
self.key_press_id = 0
self.run()
def get_language_snippets(self, path, name = None):
library = Library()
name = self.get_language(path)
nodes = library.get_snippets(name)
return nodes
def add_new_snippet_node(self, parent):
return self.model.append(parent, ('<i>' + _('Add a new snippet...') + \
'</i>', '', None))
def fill_language(self, piter, expand=True):
# Remove all children
child = self.model.iter_children(piter)
while child and self.model.remove(child):
True
path = self.model.get_path(piter)
nodes = self.get_language_snippets(path)
language = self.get_language(path)
Library().ref(language)
if nodes:
for node in nodes:
self.add_snippet(piter, node)
else:
# Add node that tells there are no snippets currently
self.add_new_snippet_node(piter)
if expand:
self.tree_view.expand_row(path, False)
def build_model(self, force_reload = False):
window = pluma.app_get_default().get_active_window()
if window:
view = window.get_active_view()
if not view:
current_lang = None
else:
current_lang = view.get_buffer().get_language()
source_view = self['source_view_snippet']
else:
current_lang = None
tree_view = self['tree_view_snippets']
expand = None
if not self.model or force_reload:
self.model = gtk.TreeStore(str, str, object)
self.model.set_sort_column_id(self.SORT_COLUMN, gtk.SORT_ASCENDING)
manager = get_language_manager()
langs = pluma.language_manager_list_languages_sorted(manager, True)
piter = self.model.append(None, (_('Global'), '', None))
# Add dummy node
self.model.append(piter, ('', '', None))
nm = None
if current_lang:
nm = current_lang.get_name()
for lang in langs:
name = lang.get_name()
parent = self.model.append(None, (name, name, lang))
# Add dummy node
self.model.append(parent, ('', '', None))
if (nm == name):
expand = parent
else:
if current_lang:
piter = self.model.get_iter_first()
nm = current_lang.get_name()
while piter:
lang = self.model.get_value(piter, \
self.SORT_COLUMN)
if lang == nm:
expand = piter
break;
piter = self.model.iter_next(piter)
tree_view.set_model(self.model)
if not expand:
expand = self.model.get_iter_root()
tree_view.expand_row(self.model.get_path(expand), False)
self.select_iter(expand)
def get_cell_data_pixbuf_cb(self, column, cell, model, iter):
s = model.get_value(iter, self.OBJ_COLUMN)
snippet = isinstance(s, SnippetData)
if snippet and not s.valid:
cell.set_property('stock-id', gtk.STOCK_DIALOG_ERROR)
else:
cell.set_property('stock-id', None)
cell.set_property('xalign', 1.0)
def get_cell_data_cb(self, column, cell, model, iter):
s = model.get_value(iter, self.OBJ_COLUMN)
snippet = isinstance(s, SnippetData)
cell.set_property('editable', snippet)
cell.set_property('markup', model.get_value(iter, self.NAME_COLUMN))
def on_tree_view_drag_data_get(self, widget, context, selection_data, info, time):
gfile = gio.File(self._temp_export)
selection_data.set_uris([gfile.get_uri()])
def on_tree_view_drag_begin(self, widget, context):
self.dragging = True
if self._temp_export:
shutil.rmtree(os.path.dirname(self._temp_export))
self._temp_export = None
if self.dnd_name:
context.set_icon_name(self.dnd_name, 0, 0)
dirname = tempfile.mkdtemp()
filename = os.path.join(dirname, self.default_export_name)
# Generate temporary file name
self.export_snippets(filename, False)
self._temp_export = filename
def on_tree_view_drag_end(self, widget, context):
self.dragging = False
def on_tree_view_drag_data_received(self, widget, context, x, y, selection, info, timestamp):
uris = selection.get_uris()
self.import_snippets(uris)
def on_tree_view_drag_motion(self, widget, context, x, y, timestamp):
# Return False if we are dragging
if self.dragging:
return False
# Check uri target
if not gtk.targets_include_uri(context.targets):
return False
# Check action
action = None
if context.suggested_action == gdk.ACTION_COPY:
action = gdk.ACTION_COPY
else:
for act in context.actions:
if act == gdk.ACTION_COPY:
action = gdk.ACTION_COPY
break
if action == gdk.ACTION_COPY:
context.drag_status(gdk.ACTION_COPY, timestamp)
return True
else:
return False
def build_dnd(self):
tv = self.tree_view
# Set it as a drag source for exporting snippets
tv.drag_source_set(gdk.BUTTON1_MASK, self.dnd_target_list, gdk.ACTION_DEFAULT | gdk.ACTION_COPY)
# Set it as a drag destination for importing snippets
tv.drag_dest_set(gtk.DEST_DEFAULT_HIGHLIGHT | gtk.DEST_DEFAULT_DROP,
self.dnd_target_list, gdk.ACTION_DEFAULT | gdk.ACTION_COPY)
tv.connect('drag_data_get', self.on_tree_view_drag_data_get)
tv.connect('drag_begin', self.on_tree_view_drag_begin)
tv.connect('drag_end', self.on_tree_view_drag_end)
tv.connect('drag_data_received', self.on_tree_view_drag_data_received)
tv.connect('drag_motion', self.on_tree_view_drag_motion)
theme = gtk.icon_theme_get_for_screen(tv.get_screen())
self.dnd_name = None
for name in self.drag_icons:
icon = theme.lookup_icon(name, gtk.ICON_SIZE_DND, 0)
if icon:
self.dnd_name = name
break
def build_tree_view(self):
self.tree_view = self['tree_view_snippets']
self.column = gtk.TreeViewColumn(None)
self.renderer = gtk.CellRendererText()
self.column.pack_start(self.renderer, False)
self.column.set_cell_data_func(self.renderer, self.get_cell_data_cb)
renderer = gtk.CellRendererPixbuf()
self.column.pack_start(renderer, True)
self.column.set_cell_data_func(renderer, self.get_cell_data_pixbuf_cb)
self.tree_view.append_column(self.column)
self.renderer.connect('edited', self.on_cell_edited)
self.renderer.connect('editing-started', self.on_cell_editing_started)
selection = self.tree_view.get_selection()
selection.set_mode(gtk.SELECTION_MULTIPLE)
selection.connect('changed', self.on_tree_view_selection_changed)
self.build_dnd()
def build(self):
self.builder = gtk.Builder()
self.builder.add_from_file(os.path.join(self.datadir, 'ui', 'snippets.ui'))
handlers_dic = {
'on_dialog_snippets_response': self.on_dialog_snippets_response,
'on_dialog_snippets_destroy': self.on_dialog_snippets_destroy,
'on_button_new_snippet_clicked': self.on_button_new_snippet_clicked,
'on_button_import_snippets_clicked': self.on_button_import_snippets_clicked,
'on_button_export_snippets_clicked': self.on_button_export_snippets_clicked,
'on_button_remove_snippet_clicked': self.on_button_remove_snippet_clicked,
'on_entry_tab_trigger_focus_out': self.on_entry_tab_trigger_focus_out,
'on_entry_tab_trigger_changed': self.on_entry_tab_trigger_changed,
'on_entry_accelerator_focus_out': self.on_entry_accelerator_focus_out,
'on_entry_accelerator_focus_in': self.on_entry_accelerator_focus_in,
'on_entry_accelerator_key_press': self.on_entry_accelerator_key_press,
'on_source_view_snippet_focus_out': self.on_source_view_snippet_focus_out,
'on_tree_view_snippets_row_expanded': self.on_tree_view_snippets_row_expanded,
'on_tree_view_snippets_key_press': self.on_tree_view_snippets_key_press}
self.builder.connect_signals(handlers_dic)
self.build_tree_view()
self.build_model()
image = self['image_remove']
image.set_from_stock(gtk.STOCK_REMOVE, gtk.ICON_SIZE_SMALL_TOOLBAR)
source_view = self['source_view_snippet']
manager = get_language_manager()
lang = manager.get_language('snippets')
if lang:
source_view.get_buffer().set_highlight_syntax(True)
source_view.get_buffer().set_language(lang)
self.snippets_doc = Document(None, source_view)
combo = self['combo_drop_targets']
combo.set_text_column(0)
entry = combo.child
entry.connect('focus-out-event', self.on_entry_drop_targets_focus_out)
entry.connect('drag-data-received', self.on_entry_drop_targets_drag_data_received)
lst = entry.drag_dest_get_target_list()
lst = gtk.target_list_add_uri_targets(entry.drag_dest_get_target_list(), self.TARGET_URI)
entry.drag_dest_set_target_list(lst)
self.dlg = self['dialog_snippets']
if self.default_size:
self.dlg.set_default_size(*self.default_size)
def __getitem__(self, key):
return self.builder.get_object(key)
def is_filled(self, piter):
if not self.model.iter_has_child(piter):
return True
child = self.model.iter_children(piter)
nm = self.model.get_value(child, self.NAME_COLUMN)
obj = self.model.get_value(child, self.OBJ_COLUMN)
return (obj or nm)
def fill_if_needed(self, piter, expand=True):
if not self.is_filled(piter):
self.fill_language(piter, expand)
def find_iter(self, parent, snippet):
self.fill_if_needed(parent)
piter = self.model.iter_children(parent)
while (piter):
node = self.model.get_value(piter, self.OBJ_COLUMN)
if node == snippet.data:
return piter
piter = self.model.iter_next(piter)
return None
def selected_snippets_state(self):
snippets = self.selected_snippets(False)
override = False
remove = False
system = False
for snippet in snippets:
if not snippet:
continue
if snippet.is_override():
override = True
elif snippet.can_modify():
remove = True
else:
system = True
# No need to continue if both are found
if override and remove:
break
return (override, remove, system)
def update_buttons(self):
button_remove = self['button_remove_snippet']
button_new = self['button_new_snippet']
image_remove = self['image_remove']
button_new.set_sensitive(self.language_path != None)
override, remove, system = self.selected_snippets_state()
if not (override ^ remove) or system:
button_remove.set_sensitive(False)
image_remove.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_BUTTON)
else:
button_remove.set_sensitive(True)
if override:
image_remove.set_from_stock(gtk.STOCK_UNDO, gtk.ICON_SIZE_BUTTON)
tooltip = _('Revert selected snippet')
else:
image_remove.set_from_stock(gtk.STOCK_DELETE, gtk.ICON_SIZE_BUTTON)
tooltip = _('Delete selected snippet')
button_remove.set_tooltip_text(tooltip)
def snippet_changed(self, piter = None):
if piter:
node = self.model.get_value(piter, self.OBJ_COLUMN)
s = Snippet(node)
else:
s = self.snippet
piter = self.find_iter(self.model.get_iter(self.language_path), s)
if piter:
nm = s.display()
self.model.set(piter, self.NAME_COLUMN, nm, self.SORT_COLUMN, nm)
self.update_buttons()
self.entry_tab_trigger_update_valid()
return piter
def add_snippet(self, parent, snippet):
piter = self.model.append(parent, ('', '', snippet))
return self.snippet_changed(piter)
def run(self):
if not self.dlg:
self.build()
self.dlg.show()
else:
self.build_model()
self.dlg.present()
def snippet_from_iter(self, model, piter):
parent = model.iter_parent(piter)
if parent:
return model.get_value(piter, self.OBJ_COLUMN)
else:
return None
def language_snippets(self, model, parent, as_path=False):
self.fill_if_needed(parent, False)
piter = model.iter_children(parent)
snippets = []
if not piter:
return snippets
while piter:
snippet = self.snippet_from_iter(model, piter)
if snippet:
if as_path:
snippets.append(model.get_path(piter))
else:
snippets.append(snippet)
piter = model.iter_next(piter)
return snippets
def selected_snippets(self, include_languages=True, as_path=False):
selection = self.tree_view.get_selection()
(model, paths) = selection.get_selected_rows()
snippets = []
if paths and len(paths) != 0:
for p in paths:
piter = model.get_iter(p)
parent = model.iter_parent(piter)
if not piter:
continue
if parent:
snippet = self.snippet_from_iter(model, piter)
if not snippet:
continue
if as_path:
snippets.append(p)
else:
snippets.append(snippet)
elif include_languages:
snippets += self.language_snippets(model, piter, as_path)
return snippets
def selected_snippet(self):
selection = self.tree_view.get_selection()
(model, paths) = selection.get_selected_rows()
if len(paths) == 1:
piter = model.get_iter(paths[0])
parent = model.iter_parent(piter)
snippet = self.snippet_from_iter(model, piter)
return parent, piter, snippet
else:
return None, None, None
def selection_changed(self):
if not self.snippet:
sens = False
self['entry_tab_trigger'].set_text('')
self['entry_accelerator'].set_text('')
buf = self['source_view_snippet'].get_buffer()
buf.begin_not_undoable_action()
buf.set_text('')
buf.end_not_undoable_action()
self['combo_drop_targets'].child.set_text('')
else:
sens = True
self['entry_tab_trigger'].set_text(self.snippet['tag'])
self['entry_accelerator'].set_text( \
self.snippet.accelerator_display())
self['combo_drop_targets'].child.set_text(', '.join(self.snippet['drop-targets']))
buf = self['source_view_snippet'].get_buffer()
buf.begin_not_undoable_action()
buf.set_text(self.snippet['text'])
buf.end_not_undoable_action()
for name in ['source_view_snippet', 'label_tab_trigger',
'entry_tab_trigger', 'label_accelerator',
'entry_accelerator', 'label_drop_targets',
'combo_drop_targets']:
self[name].set_sensitive(sens)
self.update_buttons()
def select_iter(self, piter, unselect=True):
selection = self.tree_view.get_selection()
if unselect:
selection.unselect_all()
selection.select_iter(piter)
self.tree_view.scroll_to_cell(self.model.get_path(piter), None, \
True, 0.5, 0.5)
def get_language(self, path):
if path[0] == 0:
return None
else:
return self.model.get_value(self.model.get_iter( \
(path[0],)), self.OBJ_COLUMN).get_id()
def new_snippet(self, properties=None):
if not self.language_path:
return None
snippet = Library().new_snippet(self.get_language(self.language_path), properties)
return Snippet(snippet)
def get_dummy(self, parent):
if not self.model.iter_n_children(parent) == 1:
return None
dummy = self.model.iter_children(parent)
if not self.model.get_value(dummy, self.OBJ_COLUMN):
return dummy
return None
def unref_languages(self):
piter = self.model.get_iter_first()
library = Library()
while piter:
if self.is_filled(piter):
language = self.get_language(self.model.get_path(piter))
library.save(language)
library.unref(language)
piter = self.model.iter_next(piter)
# Callbacks
def on_dialog_snippets_destroy(self, dlg):
# Remove temporary drag export
if self._temp_export:
shutil.rmtree(os.path.dirname(self._temp_export))
self._temp_export = None
if self.snippets_doc:
self.snippets_doc.stop()
self.default_size = [dlg.allocation.width, dlg.allocation.height]
self.manager = None
self.unref_languages()
self.snippet = None
self.model = None
self.dlg = None
def on_dialog_snippets_response(self, dlg, resp):
if resp == gtk.RESPONSE_HELP:
pluma.help_display(self.dlg, 'pluma', 'pluma-snippets-plugin')
return
self.dlg.destroy()
def on_cell_editing_started(self, renderer, editable, path):
piter = self.model.get_iter(path)
if not self.model.iter_parent(piter):
renderer.stop_editing(True)
editable.remove_widget()
elif isinstance(editable, gtk.Entry):
if self.snippet:
editable.set_text(self.snippet['description'])
else:
# This is the `Add a new snippet...` item
editable.set_text('')
editable.grab_focus()
def on_cell_edited(self, cell, path, new_text):
if new_text != '':
piter = self.model.get_iter(path)
node = self.model.get_value(piter, self.OBJ_COLUMN)
if node:
if node == self.snippet.data:
s = self.snippet
else:
s = Snippet(node)
s['description'] = new_text
self.snippet_changed(piter)
self.select_iter(piter)
else:
# This is the `Add a new snippet...` item
# We create a new snippet
snippet = self.new_snippet({'description': new_text})
if snippet:
self.model.set(piter, self.OBJ_COLUMN, snippet.data)
self.snippet_changed(piter)
self.snippet = snippet
self.selection_changed()
def on_entry_accelerator_focus_out(self, entry, event):
if not self.snippet:
return
entry.set_text(self.snippet.accelerator_display())
def entry_tab_trigger_update_valid(self):
entry = self['entry_tab_trigger']
text = entry.get_text()
if text and not Library().valid_tab_trigger(text):
img = self['image_tab_trigger']
img.set_from_stock(gtk.STOCK_DIALOG_ERROR, gtk.ICON_SIZE_BUTTON)
img.show()
#self['hbox_tab_trigger'].set_spacing(3)
tip = _('This is not a valid Tab trigger. Triggers can either contain letters or a single (non-alphanumeric) character like: {, [, etc.')
entry.set_tooltip_text(tip)
img.set_tooltip_text(tip)
else:
self['image_tab_trigger'].hide()
#self['hbox_tab_trigger'].set_spacing(0)
entry.set_tooltip_text(_('Single word the snippet is activated with after pressing Tab'))
return False
def on_entry_tab_trigger_focus_out(self, entry, event):
if not self.snippet:
return
text = entry.get_text()
# save tag
self.snippet['tag'] = text
self.snippet_changed()
def on_entry_drop_targets_focus_out(self, entry, event):
if not self.snippet:
return
text = entry.get_text()
# save drop targets
self.snippet['drop-targets'] = text
self.snippet_changed()
def on_entry_tab_trigger_changed(self, entry):
self.entry_tab_trigger_update_valid()
def on_source_view_snippet_focus_out(self, source_view, event):
if not self.snippet:
return
buf = source_view.get_buffer()
text = buf.get_text(buf.get_start_iter(), \
buf.get_end_iter())
self.snippet['text'] = text
self.snippet_changed()
def on_button_new_snippet_clicked(self, button):
snippet = self.new_snippet()
if not snippet:
return
parent = self.model.get_iter(self.language_path)
path = self.model.get_path(parent)
dummy = self.get_dummy(parent)
if dummy:
# Remove the dummy
self.model.remove(dummy)
# Add the snippet
piter = self.add_snippet(parent, snippet.data)
self.select_iter(piter)
if not self.tree_view.row_expanded(path):
self.tree_view.expand_row(path, False)
self.select_iter(piter)
self.tree_view.grab_focus()
path = self.model.get_path(piter)
self.tree_view.set_cursor(path, self.column, True)
def file_filter(self, name, pattern):
fil = gtk.FileFilter()
fil.set_name(name)
for p in pattern:
fil.add_pattern(p)
return fil
def import_snippets(self, filenames):
success = True
for filename in filenames:
if not pluma.utils.uri_has_file_scheme(filename):
continue
# Remove file://
gfile = gio.File(filename)
filename = gfile.get_path()
importer = Importer(filename)
error = importer.run()
if error:
message = _('The following error occurred while importing: %s') % error
success = False
message_dialog(self.dlg, gtk.MESSAGE_ERROR, message)
self.build_model(True)
if success:
message = _('Import successfully completed')
message_dialog(self.dlg, gtk.MESSAGE_INFO, message)
def on_import_response(self, dialog, response):
if response == gtk.RESPONSE_CANCEL or response == gtk.RESPONSE_CLOSE:
dialog.destroy()
return
f = dialog.get_uris()
dialog.destroy()
self.import_snippets(f)
def on_button_import_snippets_clicked(self, button):
dlg = gtk.FileChooserDialog(parent=self.dlg, title=_("Import snippets"),
action=gtk.FILE_CHOOSER_ACTION_OPEN,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_OPEN, gtk.RESPONSE_OK))
dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar', '*.xml')))
dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
dlg.add_filter(self.file_filter(_('Bzip2 compressed archive'), ('*.tar.bz2',)))
dlg.add_filter(self.file_filter(_('Single snippets file'), ('*.xml',)))
dlg.add_filter(self.file_filter(_('All files'), '*'))
dlg.connect('response', self.on_import_response)
dlg.set_local_only(True)
dlg.show()
def export_snippets_real(self, filename, snippets, show_dialogs=True):
export = Exporter(filename, snippets)
error = export.run()
if error:
message = _('The following error occurred while exporting: %s') % error
msgtype = gtk.MESSAGE_ERROR
retval = False
else:
message = _('Export successfully completed')
msgtype = gtk.MESSAGE_INFO
retval = True
if show_dialogs:
message_dialog(self.dlg, msgtype, message)
return retval
def on_export_response(self, dialog, response):
filename = dialog.get_filename()
snippets = dialog._export_snippets
dialog.destroy()
if response != gtk.RESPONSE_OK:
return
self.export_snippets_real(filename, snippets);
def export_snippets(self, filename=None, show_dialogs=True):
snippets = self.selected_snippets()
if not snippets or len(snippets) == 0:
return False
usersnippets = []
systemsnippets = []
# Iterate through snippets and look for system snippets
for snippet in snippets:
if snippet.can_modify():
usersnippets.append(snippet)
else:
systemsnippets.append(snippet)
export_snippets = snippets
if len(systemsnippets) != 0 and show_dialogs:
# Ask if system snippets should also be exported
message = _('Do you want to include selected <b>system</b> snippets in your export?')
mes = gtk.MessageDialog(flags=gtk.DIALOG_MODAL,
type=gtk.MESSAGE_QUESTION,
buttons=gtk.BUTTONS_YES_NO,
message_format=message)
mes.set_property('use-markup', True)
resp = mes.run()
mes.destroy()
if resp == gtk.RESPONSE_NO:
export_snippets = usersnippets
elif resp != gtk.RESPONSE_YES:
return False
if len(export_snippets) == 0 and show_dialogs:
message = _('There are no snippets selected to be exported')
message_dialog(self.dlg, gtk.MESSAGE_INFORMATION, message)
return False
if not filename:
dlg = gtk.FileChooserDialog(parent=self.dlg, title=_('Export snippets'),
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
dlg._export_snippets = export_snippets
dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar')))
dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
dlg.add_filter(self.file_filter(_('Bzip2 compressed archive'), ('*.tar.bz2',)))
dlg.add_filter(self.file_filter(_('All files'), '*'))
dlg.set_do_overwrite_confirmation(True)
dlg.set_current_name(self.default_export_name)
dlg.connect('response', self.on_export_response)
dlg.set_local_only(True)
dlg.show()
return True
else:
return self.export_snippets_real(filename, export_snippets, show_dialogs)
def on_button_export_snippets_clicked(self, button):
snippets = self.selected_snippets()
if not snippets or len(snippets) == 0:
return
usersnippets = []
systemsnippets = []
# Iterate through snippets and look for system snippets
for snippet in snippets:
if snippet.can_modify():
usersnippets.append(snippet)
else:
systemsnippets.append(snippet)
dlg = gtk.FileChooserDialog(parent=self.dlg, title=_('Export snippets'),
action=gtk.FILE_CHOOSER_ACTION_SAVE,
buttons=(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,
gtk.STOCK_SAVE, gtk.RESPONSE_OK))
dlg._export_snippets = snippets
if len(systemsnippets) != 0:
# Ask if system snippets should also be exported
message = _('Do you want to include selected <b>system</b> snippets in your export?')
mes = gtk.MessageDialog(flags=gtk.DIALOG_MODAL,
type=gtk.MESSAGE_QUESTION,
buttons=gtk.BUTTONS_YES_NO,
message_format=message)
mes.set_property('use-markup', True)
resp = mes.run()
mes.destroy()
if resp == gtk.RESPONSE_NO:
dlg._export_snippets = usersnippets
elif resp != gtk.RESPONSE_YES:
dlg.destroy()
return
if len(dlg._export_snippets) == 0:
dlg.destroy()
message = _('There are no snippets selected to be exported')
message_dialog(self.dlg, gtk.MESSAGE_INFORMATION, message)
return
dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar')))
dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
dlg.add_filter(self.file_filter(_('Bzip2 compressed archive'), ('*.tar.bz2',)))
dlg.add_filter(self.file_filter(_('All files'), '*'))
dlg.set_do_overwrite_confirmation(True)
dlg.set_current_name(self.default_export_name)
dlg.connect('response', self.on_export_response)
dlg.set_local_only(True)
dlg.show()
def remove_snippet_revert(self, path, piter):
node = self.snippet_from_iter(self.model, piter)
Library().revert_snippet(node)
return piter
def remove_snippet_delete(self, path, piter):
node = self.snippet_from_iter(self.model, piter)
parent = self.model.iter_parent(piter)
Library().remove_snippet(node)
if self.model.remove(piter):
return piter
elif path[-1] != 0:
self.select_iter(self.model.get_iter((path[0], path[1] - 1)))
else:
dummy = self.add_new_snippet_node(parent)
self.tree_view.expand_row(self.model.get_path(parent), False)
return dummy
def on_button_remove_snippet_clicked(self, button):
override, remove, system = self.selected_snippets_state()
if not (override ^ remove) or system:
return
paths = self.selected_snippets(include_languages=False, as_path=True)
if override:
action = self.remove_snippet_revert
else:
action = self.remove_snippet_delete
# Remove selection
self.tree_view.get_selection().unselect_all()
# Create tree row references
references = []
for path in paths:
references.append(gtk.TreeRowReference(self.model, path))
# Remove/revert snippets
select = None
for reference in references:
path = reference.get_path()
piter = self.model.get_iter(path)
res = action(path, piter)
if res:
select = res
if select:
self.select_iter(select)
self.selection_changed()
def set_accelerator(self, keyval, mod):
accelerator = gtk.accelerator_name(keyval, mod)
self.snippet['accelerator'] = accelerator
return True
def on_entry_accelerator_key_press(self, entry, event):
source_view = self['source_view_snippet']
if event.keyval == gdk.keyval_from_name('Escape'):
# Reset
entry.set_text(self.snippet.accelerator_display())
self.tree_view.grab_focus()
return True
elif event.keyval == gdk.keyval_from_name('Delete') or \
event.keyval == gdk.keyval_from_name('BackSpace'):
# Remove the accelerator
entry.set_text('')
self.snippet['accelerator'] = ''
self.tree_view.grab_focus()
self.snippet_changed()
return True
elif Library().valid_accelerator(event.keyval, event.state):
# New accelerator
self.set_accelerator(event.keyval, \
event.state & gtk.accelerator_get_default_mod_mask())
entry.set_text(self.snippet.accelerator_display())
self.snippet_changed()
self.tree_view.grab_focus()
else:
return True
def on_entry_accelerator_focus_in(self, entry, event):
if self.snippet['accelerator']:
entry.set_text(_('Type a new shortcut, or press Backspace to clear'))
else:
entry.set_text(_('Type a new shortcut'))
def update_language_path(self):
model, paths = self.tree_view.get_selection().get_selected_rows()
# Check if all have the same language parent
current_parent = None
for path in paths:
piter = model.get_iter(path)
parent = model.iter_parent(piter)
if parent:
path = model.get_path(parent)
if current_parent != None and current_parent != path:
current_parent = None
break
else:
current_parent = path
self.language_path = current_parent
def on_tree_view_selection_changed(self, selection):
parent, piter, node = self.selected_snippet()
if self.snippet:
self.on_entry_tab_trigger_focus_out(self['entry_tab_trigger'],
None)
self.on_source_view_snippet_focus_out(self['source_view_snippet'],
None)
self.on_entry_drop_targets_focus_out(self['combo_drop_targets'].child,
None)
self.update_language_path()
if node:
self.snippet = Snippet(node)
else:
self.snippet = None
self.selection_changed()
def iter_after(self, target, after):
if not after:
return True
tp = self.model.get_path(target)
ap = self.model.get_path(after)
if tp[0] > ap[0] or (tp[0] == ap[0] and (len(ap) == 1 or tp[1] > ap[1])):
return True
return False
def on_tree_view_snippets_key_press(self, treeview, event):
if event.keyval == gdk.keyval_from_name('Delete'):
self.on_button_remove_snippet_clicked(None)
return True
def on_tree_view_snippets_row_expanded(self, treeview, piter, path):
# Check if it is already filled
self.fill_if_needed(piter)
self.select_iter(piter)
def on_entry_drop_targets_drag_data_received(self, entry, context, x, y, selection_data, info, timestamp):
if not gtk.targets_include_uri(context.targets):
return
uris = drop_get_uris(selection_data)
if not uris:
return
if entry.get_text():
mimes = [entry.get_text()]
else:
mimes = []
for uri in uris:
try:
mime = gio.content_type_guess(uri)
except:
mime = None
if mime:
mimes.append(mime)
entry.set_text(', '.join(mimes))
self.on_entry_drop_targets_focus_out(entry, None)
context.finish(True, False, timestamp)
entry.stop_emission('drag_data_received')
# ex:ts=8:et: