Blob Blame Raw
From 2056b6f2fcc6f0fd5a190f68c4310129535a7bf5 Mon Sep 17 00:00:00 2001
From: Patrick Monnerat <patrick@monnerat.net>
Date: Mon, 27 May 2019 18:16:18 +0200
Subject: [PATCH] snippets plugin: change code for Python 2 & 3 compatibility

---
 plugins/snippets/snippets/Completion.py      |  23 +-
 plugins/snippets/snippets/Document.py        | 151 ++---
 plugins/snippets/snippets/Exporter.py        |   4 +-
 plugins/snippets/snippets/Helper.py          |  32 +-
 plugins/snippets/snippets/Importer.py        |   2 +-
 plugins/snippets/snippets/LanguageManager.py |   3 +-
 plugins/snippets/snippets/Library.py         |  43 +-
 plugins/snippets/snippets/Manager.py         |  76 ++-
 plugins/snippets/snippets/Parser.py          |   2 +-
 plugins/snippets/snippets/Placeholder.py     |  85 ++-
 plugins/snippets/snippets/Snippet.py         |  46 +-
 plugins/snippets/snippets/WindowHelper.py    |   4 +-
 plugins/snippets/snippets/__init__.py        |  19 +-
 plugins/snippets/snippets/snippets.ui        | 679 +++++++------------
 14 files changed, 528 insertions(+), 641 deletions(-)

diff --git a/plugins/snippets/snippets/Completion.py b/plugins/snippets/snippets/Completion.py
index a860d21..ad0ad75 100644
--- a/plugins/snippets/snippets/Completion.py
+++ b/plugins/snippets/snippets/Completion.py
@@ -1,14 +1,14 @@
 from gi.repository import GObject, Gtk, GtkSource, Pluma
 
-from Library import Library
-from LanguageManager import get_language_manager
-from Snippet import Snippet
+from .Library import Library
+from .LanguageManager import get_language_manager
+from .Snippet import Snippet
 
 class Proposal(GObject.Object, GtkSource.CompletionProposal):
     __gtype_name__ = "PlumaSnippetsProposal"
 
     def __init__(self, snippet):
-        GObject.Object.__init__(self)
+        super(Proposal, self).__init__()
         self._snippet = Snippet(snippet)
 
     def snippet(self):
@@ -25,7 +25,7 @@ class Provider(GObject.Object, GtkSource.CompletionProvider):
     __gtype_name__ = "PlumaSnippetsProvider"
 
     def __init__(self, name, language_id, handler):
-        GObject.Object.__init__(self)
+        super(Provider, self).__init__()
 
         self.name = name
         self.info_widget = None
@@ -38,7 +38,10 @@ class Provider(GObject.Object, GtkSource.CompletionProvider):
         theme = Gtk.IconTheme.get_default()
         f, w, h = Gtk.icon_size_lookup(Gtk.IconSize.MENU)
 
-        self.icon = theme.load_icon(Gtk.STOCK_JUSTIFY_LEFT, w, 0)
+        try:
+            self.icon = theme.load_icon("format-justify-left", w, 0)
+        except:
+            self.icon = None
 
     def __del__(self):
         if self.mark:
@@ -89,9 +92,9 @@ class Provider(GObject.Object, GtkSource.CompletionProvider):
 
         # Filter based on the current word
         if word:
-            proposals = filter(lambda x: x['tag'].startswith(word), proposals)
+            proposals = (x for x in proposals if x['tag'].startswith(word))
 
-        return map(lambda x: Proposal(x), proposals)
+        return [Proposal(x) for x in proposals]
 
     def do_populate(self, context):
         proposals = self.get_proposals(self.get_word(context))
@@ -113,6 +116,10 @@ class Provider(GObject.Object, GtkSource.CompletionProvider):
 
             sw = Gtk.ScrolledWindow()
             sw.add(view)
+            sw.show_all()
+
+            # Fixed size
+            sw.set_size_request(300, 200)
 
             self.info_view = view
             self.info_widget = sw
diff --git a/plugins/snippets/snippets/Document.py b/plugins/snippets/snippets/Document.py
index f1cc065..f40186b 100644
--- a/plugins/snippets/snippets/Document.py
+++ b/plugins/snippets/snippets/Document.py
@@ -18,12 +18,12 @@
 import os
 import re
 
-from gi.repository import GLib, Gio, Gdk, Gtk, GtkSource, Pluma
+from gi.repository import GLib, Gio, Gdk, Gtk, Pluma
 
-from Library import Library
-from Snippet import Snippet
-from Placeholder import *
-import Completion
+from .Library import Library
+from .Snippet import Snippet
+from .Placeholder import *
+from . import Completion
 
 class DynamicSnippet(dict):
     def __init__(self, text):
@@ -31,9 +31,7 @@ class DynamicSnippet(dict):
         self.valid = True
 
 class Document:
-    TAB_KEY_VAL = (Gdk.KEY_Tab, \
-            Gdk.KEY_ISO_Left_Tab)
-    SPACE_KEY_VAL = (Gdk.KEY_space,)
+    TAB_KEY_VAL = ('Tab', 'ISO_Left_Tab')
 
     def __init__(self, instance, view):
         self.view = None
@@ -109,7 +107,7 @@ class Document:
                 self.deactivate_snippet(snippet, True)
 
             completion = self.view.get_completion()
-            if completion:
+            if completion and self.provider in completion.get_providers():
                 completion.remove_provider(self.provider)
 
         self.view = view
@@ -182,8 +180,6 @@ class Document:
         snippets = Library().from_accelerator(accelerator, \
                 self.language_id)
 
-        snippets_debug('Accel!')
-
         if len(snippets) == 0:
             return False
         elif len(snippets) == 1:
@@ -193,6 +189,7 @@ class Document:
             provider = Completion.Provider(_('Snippets'), self.language_id, self.on_proposal_activated)
             provider.set_proposals(snippets)
 
+            cm = self.view.get_completion()
             cm.show([provider], cm.create_context(None))
 
         return True
@@ -266,7 +263,6 @@ class Document:
 
             # Find the nearest placeholder
             if nearest(piter, begin, end, found):
-                foundIndex = index
                 found = placeholder
 
             # Find the current placeholder
@@ -276,7 +272,7 @@ class Document:
                 currentIndex = index
                 current = placeholder
 
-        if current and current != found and \
+        if current and found and current != found and \
            (current.begin_iter().compare(found.begin_iter()) == 0 or \
             current.end_iter().compare(found.begin_iter()) == 0) and \
            self.active_placeholder and \
@@ -363,57 +359,60 @@ class Document:
 
     def env_get_current_word(self, buf):
         start, end = buffer_word_boundary(buf)
-
         return buf.get_text(start, end, False)
 
     def env_get_current_line(self, buf):
         start, end = buffer_line_boundary(buf)
-
         return buf.get_text(start, end, False)
 
     def env_get_current_line_number(self, buf):
         start, end = buffer_line_boundary(buf)
         return str(start.get_line() + 1)
 
-    def env_get_document_uri(self, buf):
-        location = buf.get_location()
-
+    def location_uri_for_env(self, location):
         if location:
             return location.get_uri()
-        else:
-            return ''
-
-    def env_get_document_name(self, buf):
-        location = buf.get_location()
+        return ''
 
+    def location_name_for_env(self, location):
         if location:
             return location.get_basename()
-        else:
-            return ''
-
-    def env_get_document_scheme(self, buf):
-        location = buf.get_location()
+        return ''
 
+    def location_scheme_for_env(self, location):
         if location:
             return location.get_uri_scheme()
-        else:
-            return ''
-
-    def env_get_document_path(self, buf):
-        location = buf.get_location()
+        return ''
 
+    def location_path_for_env(self, location):
         if location:
             return location.get_path()
-        else:
-            return ''
-
-    def env_get_document_dir(self, buf):
-        location = buf.get_location()
+        return ''
 
+    def location_dir_for_env(self, location):
         if location:
-            return location.get_parent().get_path() or ''
-        else:
-            return ''
+            parent = location.get_parent()
+
+            if parent and parent.has_uri_scheme('file'):
+                return parent.get_path() or ''
+
+        return ''
+
+    def env_add_for_location(self, environ, location, prefix):
+        parts = {
+            'URI': self.location_uri_for_env,
+            'NAME': self.location_name_for_env,
+            'SCHEME': self.location_scheme_for_env,
+            'PATH': self.location_path_for_env,
+            'DIR': self.location_dir_for_env,
+        }
+
+        for k in parts:
+            v = parts[k](location)
+            key = prefix + '_' + k
+            environ[key] = str(v)
+
+        return environ
 
     def env_get_document_type(self, buf):
         typ = buf.get_mime_type()
@@ -451,25 +450,30 @@ class Document:
 
         return ' '.join(documents_path)
 
-    def update_environment(self):
+    def get_environment(self):
         buf = self.view.get_buffer()
+        environ = {}
+
+        for k in os.environ:
+            # Get the original environment
+            v = os.environ[k]
+            environ[k] = v
 
-        variables = {'PLUMA_SELECTED_TEXT': self.env_get_selected_text,
+        variables = {
+                 'PLUMA_SELECTED_TEXT': self.env_get_selected_text,
                  'PLUMA_CURRENT_WORD': self.env_get_current_word,
                  'PLUMA_CURRENT_LINE': self.env_get_current_line,
                  'PLUMA_CURRENT_LINE_NUMBER': self.env_get_current_line_number,
-                 'PLUMA_CURRENT_DOCUMENT_URI': self.env_get_document_uri,
-                 'PLUMA_CURRENT_DOCUMENT_NAME': self.env_get_document_name,
-                 'PLUMA_CURRENT_DOCUMENT_SCHEME': self.env_get_document_scheme,
-                 'PLUMA_CURRENT_DOCUMENT_PATH': self.env_get_document_path,
-                 'PLUMA_CURRENT_DOCUMENT_DIR': self.env_get_document_dir,
                  'PLUMA_CURRENT_DOCUMENT_TYPE': self.env_get_document_type,
                  'PLUMA_DOCUMENTS_URI': self.env_get_documents_uri,
                  'PLUMA_DOCUMENTS_PATH': self.env_get_documents_path,
             }
 
         for var in variables:
-            os.environ[var] = variables[var](buf)
+            environ[var] = variables[var](buf)
+
+        self.env_add_for_location(environ, buf.get_location(), 'PLUMA_CURRENT_DOCUMENT')
+        return environ
 
     def uses_current_word(self, snippet):
         matches = re.findall('(\\\\*)\\$PLUMA_CURRENT_WORD', snippet['text'])
@@ -489,12 +493,19 @@ class Document:
 
         return False
 
-    def apply_snippet(self, snippet, start = None, end = None):
+    def apply_snippet(self, snippet, start = None, end = None, environ = {}):
         if not snippet.valid:
             return False
 
+        # Set environmental variables
+        env = self.get_environment()
+
+        if environ:
+            for k in environ:
+                env[k] = environ[k]
+
         buf = self.view.get_buffer()
-        s = Snippet(snippet)
+        s = Snippet(snippet, env)
 
         if not start:
             start = buf.get_iter_at_mark(buf.get_insert())
@@ -513,9 +524,6 @@ class Document:
             # it will be removed
             start, end = buffer_line_boundary(buf)
 
-        # Set environmental variables
-        self.update_environment()
-
         # You know, we could be in an end placeholder
         (current, next) = self.next_placeholder()
         if current and current.__class__ == PlaceholderEnd:
@@ -527,8 +535,6 @@ class Document:
         buf.delete(start, end)
 
         # Insert the snippet
-        holders = len(self.placeholders)
-
         if len(self.active_snippets) == 0:
             self.first_snippet_inserted()
 
@@ -536,7 +542,7 @@ class Document:
         self.active_snippets.append(sn)
 
         # Put cursor at first tab placeholder
-        keys = filter(lambda x: x > 0, sn.placeholders.keys())
+        keys = [x for x in sn.placeholders.keys() if x > 0]
 
         if len(keys) == 0:
             if 0 in sn.placeholders:
@@ -637,7 +643,6 @@ class Document:
             return True
 
     def deactivate_snippet(self, snippet, force = False):
-        buf = self.view.get_buffer()
         remove = []
         ordered_remove = []
 
@@ -792,10 +797,11 @@ class Document:
         library = Library()
 
         state = event.get_state()
+        keyname = Gdk.keyval_name(event.keyval)
 
         if not (state & Gdk.ModifierType.CONTROL_MASK) and \
                 not (state & Gdk.ModifierType.MOD1_MASK) and \
-                event.keyval in self.TAB_KEY_VAL:
+                keyname in self.TAB_KEY_VAL:
             if not state & Gdk.ModifierType.SHIFT_MASK:
                 return self.run_snippet()
             else:
@@ -868,20 +874,9 @@ class Document:
         pathname = ''
         dirname = ''
         ruri = ''
+        environ = {'PLUMA_DROP_DOCUMENT_TYPE': mime}
 
-        if Pluma.utils_uri_has_file_scheme(uri):
-            pathname = gfile.get_path()
-            dirname = gfile.get_parent().get_path()
-
-        name = os.path.basename(uri)
-        scheme = gfile.get_uri_scheme()
-
-        os.environ['PLUMA_DROP_DOCUMENT_URI'] = uri
-        os.environ['PLUMA_DROP_DOCUMENT_NAME'] = name
-        os.environ['PLUMA_DROP_DOCUMENT_SCHEME'] = scheme
-        os.environ['PLUMA_DROP_DOCUMENT_PATH'] = pathname
-        os.environ['PLUMA_DROP_DOCUMENT_DIR'] = dirname
-        os.environ['PLUMA_DROP_DOCUMENT_TYPE'] = mime
+        self.env_add_for_location(environ, gfile, 'PLUMA_DROP_DOCUMENT')
 
         buf = self.view.get_buffer()
         location = buf.get_location()
@@ -890,7 +885,7 @@ class Document:
 
         relpath = self.relative_path(ruri, uri, mime)
 
-        os.environ['PLUMA_DROP_DOCUMENT_RELATIVE_PATH'] = relpath
+        environ['PLUMA_DROP_DOCUMENT_RELATIVE_PATH'] = relpath
 
         mark = buf.get_mark('gtk_drag_target')
 
@@ -898,7 +893,7 @@ class Document:
             mark = buf.get_insert()
 
         piter = buf.get_iter_at_mark(mark)
-        self.apply_snippet(snippet, piter, piter)
+        self.apply_snippet(snippet, piter, piter, environ)
 
     def in_bounds(self, x, y):
         rect = self.view.get_visible_rect()
@@ -907,6 +902,9 @@ class Document:
         return not (x < rect.x or x > rect.x + rect.width or y < rect.y or y > rect.y + rect.height)
 
     def on_drag_data_received(self, view, context, x, y, data, info, timestamp):
+        if not self.view.get_editable():
+            return
+
         uris = drop_get_uris(data)
         if not uris:
             return
@@ -944,6 +942,9 @@ class Document:
         return self.view.drag_dest_find_target(context, lst)
 
     def on_proposal_activated(self, proposal, piter):
+        if not self.view.get_editable():
+            return False
+
         buf = self.view.get_buffer()
         bounds = buf.get_selection_bounds()
 
@@ -1048,8 +1049,6 @@ class Document:
         if isinstance(placeholder, PlaceholderEnd):
             return
 
-        buf = self.view.get_buffer()
-
         col = self.view.get_style_context().get_color(Gtk.StateFlags.INSENSITIVE)
         col.alpha = 0.5
         Gdk.cairo_set_source_rgba(ctx, col)
diff --git a/plugins/snippets/snippets/Exporter.py b/plugins/snippets/snippets/Exporter.py
index 850c3a4..713077f 100644
--- a/plugins/snippets/snippets/Exporter.py
+++ b/plugins/snippets/snippets/Exporter.py
@@ -3,9 +3,9 @@ import tempfile
 import sys
 import shutil
 
-from Library import *
+from .Library import *
 import xml.etree.ElementTree as et
-from Helper import *
+from .Helper import *
 
 class Exporter:
     def __init__(self, filename, snippets):
diff --git a/plugins/snippets/snippets/Helper.py b/plugins/snippets/snippets/Helper.py
index 6d440d0..c1f1c35 100644
--- a/plugins/snippets/snippets/Helper.py
+++ b/plugins/snippets/snippets/Helper.py
@@ -15,10 +15,10 @@
 #    along with this program; if not, write to the Free Software
 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-import string
 from xml.sax import saxutils
-from xml.etree.ElementTree import *
+import xml.etree.ElementTree as et
 import re
+import codecs
 
 from gi.repository import Gtk
 
@@ -93,7 +93,7 @@ def write_xml(node, f, cdata_nodes=()):
     assert node is not None
 
     if not hasattr(f, "write"):
-        f = open(f, "wb")
+        f = codecs.open(f, "wb", encoding="utf-8")
 
     # Encoding
     f.write("<?xml version='1.0' encoding='utf-8'?>\n")
@@ -107,27 +107,27 @@ def _write_node(node, file, cdata_nodes=(), indent=0):
     # write XML to file
     tag = node.tag
 
-    if node is Comment:
-        _write_indent(file, "<!-- %s -->\n" % saxutils.escape(node.text.encode('utf-8')), indent)
-    elif node is ProcessingInstruction:
-        _write_indent(file, "<?%s?>\n" % saxutils.escape(node.text.encode('utf-8')), indent)
+    if node is et.Comment:
+        _write_indent(file, "<!-- %s -->\n" % saxutils.escape(node.text), indent)
+    elif node is et.ProcessingInstruction:
+        _write_indent(file, "<?%s?>\n" % saxutils.escape(node.text), indent)
     else:
         items = node.items()
 
         if items or node.text or len(node):
-            _write_indent(file, "<" + tag.encode('utf-8'), indent)
+            _write_indent(file, "<" + tag, indent)
 
             if items:
                 items.sort() # lexical order
                 for k, v in items:
-                    file.write(" %s=%s" % (k.encode('utf-8'), saxutils.quoteattr(v.encode('utf-8'))))
+                    file.write(" %s=%s" % (k, saxutils.quoteattr(v)))
             if node.text or len(node):
                 file.write(">")
                 if node.text and node.text.strip() != "":
                     if tag in cdata_nodes:
                         file.write(_cdata(node.text))
                     else:
-                        file.write(saxutils.escape(node.text.encode('utf-8')))
+                        file.write(saxutils.escape(node.text))
                 else:
                     file.write("\n")
 
@@ -135,19 +135,17 @@ def _write_node(node, file, cdata_nodes=(), indent=0):
                     _write_node(n, file, cdata_nodes, indent + 1)
 
                 if not len(node):
-                    file.write("</" + tag.encode('utf-8') + ">\n")
+                    file.write("</" + tag + ">\n")
                 else:
-                    _write_indent(file, "</" + tag.encode('utf-8') + ">\n", \
-                            indent)
+                    _write_indent(file, "</" + tag + ">\n", indent)
             else:
                 file.write(" />\n")
 
         if node.tail and node.tail.strip() != "":
-            file.write(saxutils.escape(node.tail.encode('utf-8')))
+            file.write(saxutils.escape(node.tail))
 
-def _cdata(text, replace=string.replace):
-    text = text.encode('utf-8')
-    return '<![CDATA[' + replace(text, ']]>', ']]]]><![CDATA[>') + ']]>'
+def _cdata(text):
+    return '<![CDATA[' + text.replace(']]>', ']]]]><![CDATA[>') + ']]>'
 
 def buffer_word_boundary(buf):
     iter = buf.get_iter_at_mark(buf.get_insert())
diff --git a/plugins/snippets/snippets/Importer.py b/plugins/snippets/snippets/Importer.py
index c1d211e..83c520c 100644
--- a/plugins/snippets/snippets/Importer.py
+++ b/plugins/snippets/snippets/Importer.py
@@ -3,7 +3,7 @@ import tempfile
 import sys
 import shutil
 
-from Library import *
+from .Library import *
 
 class Importer:
     def __init__(self, filename):
diff --git a/plugins/snippets/snippets/LanguageManager.py b/plugins/snippets/snippets/LanguageManager.py
index e738333..d962dcf 100644
--- a/plugins/snippets/snippets/LanguageManager.py
+++ b/plugins/snippets/snippets/LanguageManager.py
@@ -1,7 +1,7 @@
 import os
 from gi.repository import GtkSource
 
-from Library import Library
+from .Library import Library
 
 global manager
 manager = None
@@ -19,4 +19,5 @@ def get_language_manager():
         manager.set_search_path(dirs + manager.get_search_path())
 
     return manager
+
 # ex:ts=4:et:
diff --git a/plugins/snippets/snippets/Library.py b/plugins/snippets/snippets/Library.py
index f152082..d8ae219 100644
--- a/plugins/snippets/snippets/Library.py
+++ b/plugins/snippets/snippets/Library.py
@@ -20,11 +20,12 @@ import weakref
 import sys
 import tempfile
 import re
+import codecs
 
 from gi.repository import Gdk, Gtk
 
 import xml.etree.ElementTree as et
-from Helper import *
+from .Helper import *
 
 class NamespacedId:
     def __init__(self, namespace, id):
@@ -453,28 +454,38 @@ class SnippetsSystemFile:
                 lambda node: elements.append((node, True)), \
                 lambda node: elements.append((node, False)))
 
-        parser = et.XMLTreeBuilder(target=builder)
+        self.ok = True
+        parser = et.XMLParser(target=builder)
         self.insnippet = False
 
         try:
-            f = open(self.path, "r")
+            f = codecs.open(self.path, "r", encoding='utf-8')
+        except IOError:
+            self.ok = False
+            return
 
-            while True:
+        while self.ok:
+            try:
                 data = f.read(readsize)
+            except IOError:
+                self.ok = False
+                break
 
-                if not data:
-                    break
+            if not data:
+                break
 
+            try:
                 parser.feed(data)
+            except Exception:
+                self.ok = False
+                break
 
-                for element in elements:
-                    yield element
+            for element in elements:
+                yield element
 
-                del elements[:]
+            del elements[:]
 
-            f.close()
-        except IOError:
-            self.ok = False
+        f.close()
 
     def load(self):
         if not self.ok:
@@ -531,6 +542,8 @@ class SnippetsUserFile(SnippetsSystemFile):
         SnippetsSystemFile.__init__(self, path)
         self.tainted = False
         self.need_id = False
+        self.modifier = False
+        self.root = None
 
     def _set_root(self, element):
         SnippetsSystemFile._set_root(self, element)
@@ -611,7 +624,7 @@ class SnippetsUserFile(SnippetsSystemFile):
 
         try:
             if not os.path.isdir(path):
-                os.makedirs(path, 0755)
+                os.makedirs(path, 0o755)
         except OSError:
             # TODO: this is bad...
             sys.stderr.write("Error in making dirs\n")
@@ -929,8 +942,8 @@ class Library(Singleton):
     def valid_accelerator(self, keyval, mod):
         mod &= Gtk.accelerator_get_default_mod_mask()
 
-        return (mod and (Gdk.keyval_to_unicode(keyval) or \
-                keyval in range(Gdk.KEY_F1, Gdk.KEY_F12 + 1)))
+        return mod and (Gdk.keyval_to_unicode(keyval) or \
+                re.match('^F(?:1[012]?|[2-9])$', Gdk.keyval_name(keyval)))
 
     def valid_tab_trigger(self, trigger):
         if not trigger:
diff --git a/plugins/snippets/snippets/Manager.py b/plugins/snippets/snippets/Manager.py
index 9760fa7..71ada38 100644
--- a/plugins/snippets/snippets/Manager.py
+++ b/plugins/snippets/snippets/Manager.py
@@ -21,13 +21,13 @@ import shutil
 
 from gi.repository import GObject, Gio, Gdk, Gtk, GtkSource, Pluma
 
-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
+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
@@ -42,7 +42,7 @@ class Manager:
     dragging = False
     dnd_target_list = [Gtk.TargetEntry.new('text/uri-list', 0, TARGET_URI)]
 
-    def __init__(self, datadir):
+    def __init__(self, datadir, window=None):
         self.datadir = datadir
         self.snippet = None
         self.dlg = None
@@ -52,7 +52,7 @@ class Manager:
         self.default_size = None
 
         self.key_press_id = 0
-        self.run()
+        self.run(window)
 
     def get_language_snippets(self, path, name = None):
         library = Library()
@@ -159,9 +159,9 @@ class Manager:
         snippet = model.get_value(iter, self.SNIPPET_COLUMN)
 
         if snippet and not snippet.valid:
-            cell.set_property('stock-id', Gtk.STOCK_DIALOG_ERROR)
+            cell.set_property('icon-name', 'dialog-error')
         else:
-            cell.set_property('stock-id', None)
+            cell.set_property('icon-name', None)
 
         cell.set_property('xalign', 1.0)
 
@@ -300,9 +300,6 @@ class Manager:
         self.build_tree_view()
         self.build_model()
 
-        image = self['image_remove']
-        image.set_from_stock(Gtk.STOCK_REMOVE, Gtk.IconSize.SMALL_TOOLBAR)
-
         source_view = self['source_view_snippet']
         manager = get_language_manager()
         lang = manager.get_language('snippets')
@@ -391,15 +388,15 @@ class Manager:
 
         if not (override ^ remove) or system:
             button_remove.set_sensitive(False)
-            image_remove.set_from_stock(Gtk.STOCK_DELETE, Gtk.IconSize.BUTTON)
+            image_remove.set_from_icon_name("edit-delete", Gtk.IconSize.BUTTON)
         else:
             button_remove.set_sensitive(True)
 
             if override:
-                image_remove.set_from_stock(Gtk.STOCK_UNDO, Gtk.IconSize.BUTTON)
+                image_remove.set_from_icon_name("edit-undo", Gtk.IconSize.BUTTON)
                 tooltip = _('Revert selected snippet')
             else:
-                image_remove.set_from_stock(Gtk.STOCK_DELETE, Gtk.IconSize.BUTTON)
+                image_remove.set_from_icon_name("edit-delete", Gtk.IconSize.BUTTON)
                 tooltip = _('Delete selected snippet')
 
             button_remove.set_tooltip_text(tooltip)
@@ -427,12 +424,14 @@ class Manager:
 
         return self.snippet_changed(piter)
 
-    def run(self):
+    def run(self, window=None):
         if not self.dlg:
             self.build()
+            self.dlg.set_transient_for(window)
             self.dlg.show()
         else:
             self.build_model()
+            self.dlg.set_transient_for(window)
             self.dlg.present()
 
     def snippet_from_iter(self, model, piter):
@@ -611,7 +610,7 @@ class Manager:
         self.default_size = [alloc.width, alloc.height]
 
         if resp == Gtk.ResponseType.HELP:
-            Pluma.help_display(self, 'pluma', 'pluma-snippets-plugin')
+            Pluma.help_display(self.dlg, 'pluma', 'pluma-snippets-plugin')
             return
 
         self.dlg.destroy()
@@ -668,7 +667,7 @@ class Manager:
 
         if text and not Library().valid_tab_trigger(text):
             img = self['image_tab_trigger']
-            img.set_from_stock(Gtk.STOCK_DIALOG_ERROR, Gtk.IconSize.BUTTON)
+            img.set_from_icon_name("dialog-error", Gtk.IconSize.BUTTON)
             img.show()
 
             #self['hbox_tab_trigger'].set_spacing(3)
@@ -790,10 +789,11 @@ class Manager:
         self.import_snippets(f)
 
     def on_button_import_snippets_clicked(self, button):
-        dlg = Gtk.FileChooserDialog(parent=self.dlg, title=_("Import snippets"),
-                action=Gtk.FileChooserAction.OPEN,
-                buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                     Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+        dlg = Gtk.FileChooserDialog(title=_("Import snippets"),
+                                    parent=self.dlg,
+                                    action=Gtk.FileChooserAction.OPEN)
+        self._add_button(dlg, _('_Cancel'), Gtk.ResponseType.CANCEL, "process-stop")
+        self._add_button(dlg, _("_Open"), Gtk.ResponseType.OK, "document-open")
 
         dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar', '*.xml')))
         dlg.add_filter(self.file_filter(_('Gzip compressed archive'), ('*.tar.gz',)))
@@ -875,10 +875,11 @@ class Manager:
             return False
 
         if not filename:
-            dlg = Gtk.FileChooserDialog(parent=self.dlg, title=_('Export snippets'),
-                    action=Gtk.FileChooserAction.SAVE,
-                    buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                         Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
+            dlg = Gtk.FileChooserDialog(title=_('Export snippets'),
+                                        parent=self.dlg,
+                                        action=Gtk.FileChooserAction.SAVE)
+            self._add_button(dlg, _('_Cancel'), Gtk.ResponseType.CANCEL, "process-stop")
+            self._add_button(dlg, _("_Save"), Gtk.ResponseType.OK, "document-save")
 
             dlg._export_snippets = export_snippets
             dlg.add_filter(self.file_filter(_('All supported archives'), ('*.gz','*.bz2','*.tar')))
@@ -913,10 +914,11 @@ class Manager:
             else:
                 systemsnippets.append(snippet)
 
-        dlg = Gtk.FileChooserDialog(parent=self.dlg, title=_('Export snippets'),
-                action=Gtk.FileChooserAction.SAVE,
-                buttons=(Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
-                     Gtk.STOCK_SAVE, Gtk.ResponseType.OK))
+        dlg = Gtk.FileChooserDialog(title=_('Export snippets'),
+                                    parent=self.dlg,
+                                    action=Gtk.FileChooserAction.SAVE)
+        self._add_button(dlg, _('_Cancel'), Gtk.ResponseType.CANCEL, "process-stop")
+        self._add_button(dlg, _("_Save"), Gtk.ResponseType.OK, "document-save")
 
         dlg._export_snippets = snippets
 
@@ -1145,4 +1147,14 @@ class Manager:
         context.finish(True, False, timestamp)
 
         entry.stop_emission('drag_data_received')
+
+    @staticmethod
+    def _add_button(dialog, label, response, icon=None):
+        button = dialog.add_button(label, response)
+        if icon:
+            image = Gtk.Image.new_from_icon_name(icon, Gtk.IconSize.BUTTON)
+            button.set_image(image)
+            button.set_property("always-show-image", True)
+        return button
+
 # ex:ts=4:et:
diff --git a/plugins/snippets/snippets/Parser.py b/plugins/snippets/snippets/Parser.py
index 280ce0c..f200043 100644
--- a/plugins/snippets/snippets/Parser.py
+++ b/plugins/snippets/snippets/Parser.py
@@ -18,7 +18,7 @@
 import os
 import re
 import sys
-from SubstitutionParser import SubstitutionParser
+from .SubstitutionParser import SubstitutionParser
 
 class Token:
     def __init__(self, klass, data):
diff --git a/plugins/snippets/snippets/Placeholder.py b/plugins/snippets/snippets/Placeholder.py
index 9edf099..050fda6 100644
--- a/plugins/snippets/snippets/Placeholder.py
+++ b/plugins/snippets/snippets/Placeholder.py
@@ -24,12 +24,12 @@ import locale
 import subprocess
 from gi.repository import GObject, GLib, Gtk
 
-from SubstitutionParser import SubstitutionParser
-from Helper import *
+from .SubstitutionParser import SubstitutionParser
+from .Helper import *
 
 # These are places in a view where the cursor can go and do things
 class Placeholder:
-    def __init__(self, view, tabstop, defaults, begin):
+    def __init__(self, view, tabstop, environ, defaults, begin):
         self.ok = True
         self.done = False
         self.buf = view.get_buffer()
@@ -38,6 +38,7 @@ class Placeholder:
         self.mirrors = []
         self.leave_mirrors = []
         self.tabstop = tabstop
+        self.environ = environ
         self.set_default(defaults)
         self.prev_contents = self.default
         self.set_mark_gravity()
@@ -49,6 +50,9 @@ class Placeholder:
 
         self.end = None
 
+    def get_environ(self):
+        return self.environ
+
     def __str__(self):
         return '%s (%s)' % (str(self.__class__), str(self.default))
 
@@ -81,10 +85,12 @@ class Placeholder:
         return s
 
     def re_environment(self, m):
-        if m.group(1) or not m.group(2) in os.environ:
+        env = self.get_environ()
+
+        if m.group(1) or not m.group(2) in env:
             return '$' + m.group(2)
         else:
-            return self.format_environment(os.environ[m.group(2)])
+            return self.format_environment(env[m.group(2)])
 
     def expand_environment(self, text):
         if not text:
@@ -214,8 +220,8 @@ class Placeholder:
 
 # This is an placeholder which inserts a mirror of another Placeholder
 class PlaceholderMirror(Placeholder):
-    def __init__(self, view, tabstop, begin):
-        Placeholder.__init__(self, view, -1, None, begin)
+    def __init__(self, view, tabstop, environ, begin):
+        Placeholder.__init__(self, view, -1, environ, None, begin)
         self.mirror_stop = tabstop
 
     def update(self, mirror):
@@ -237,8 +243,8 @@ class PlaceholderMirror(Placeholder):
 
 # This placeholder indicates the end of a snippet
 class PlaceholderEnd(Placeholder):
-    def __init__(self, view, begin, default):
-        Placeholder.__init__(self, view, 0, default, begin)
+    def __init__(self, view, environ, begin, default):
+        Placeholder.__init__(self, view, 0, environ, default, begin)
 
     def run_last(self, placeholders):
         Placeholder.run_last(self, placeholders)
@@ -264,8 +270,8 @@ class PlaceholderEnd(Placeholder):
 
 # This placeholder is used to expand a command with embedded mirrors
 class PlaceholderExpand(Placeholder):
-    def __init__(self, view, tabstop, begin, s):
-        Placeholder.__init__(self, view, tabstop, None, begin)
+    def __init__(self, view, tabstop, environ, begin, s):
+        Placeholder.__init__(self, view, tabstop, environ, None, begin)
 
         self.mirror_text = {0: ''}
         self.timeout_id = None
@@ -359,8 +365,6 @@ class PlaceholderExpand(Placeholder):
         return ret
 
     def update(self, mirror):
-        text = None
-
         if mirror:
             self.mirror_text[mirror.tabstop] = mirror.get_text()
 
@@ -379,8 +383,8 @@ class PlaceholderExpand(Placeholder):
 
 # The shell placeholder executes commands in a subshell
 class PlaceholderShell(PlaceholderExpand):
-    def __init__(self, view, tabstop, begin, s):
-        PlaceholderExpand.__init__(self, view, tabstop, begin, s)
+    def __init__(self, view, tabstop, environ, begin, s):
+        PlaceholderExpand.__init__(self, view, tabstop, environ, begin, s)
 
         self.shell = None
         self.remove_me = False
@@ -412,7 +416,7 @@ class PlaceholderShell(PlaceholderExpand):
         self.close_shell()
         self.remove_timeout()
 
-        self.set_text(str.join('', self.shell_output).rstrip('\n'))
+        self.set_text(''.join(self.shell_output).rstrip('\n'))
 
         if self.default == None:
             self.default = self.get_text()
@@ -423,19 +427,24 @@ class PlaceholderShell(PlaceholderExpand):
 
     def process_cb(self, source, condition):
         if condition & GObject.IO_IN:
-            line = source.readline()
+            while True:
+                line = source.readline()
 
-            if len(line) > 0:
-                try:
-                    line = unicode(line, 'utf-8')
-                except:
-                    line = unicode(line, locale.getdefaultlocale()[1],
-                            'replace')
+                if len(line) <= 0:
+                    break
 
-            self.shell_output += line
-            self.install_timeout()
+                if isinstance(line, bytes):
+                    try:
+                        line = line.decode('utf-8')
+                    except UnicodeDecodeError:
+                        line = line.decode(locale.getdefaultlocale()[1],
+                                           errors='replace')
 
-            return True
+                self.shell_output += line
+                self.install_timeout()
+
+                if not (condition & GObject.IO_HUP):
+                    return True
 
         self.process_close()
         return False
@@ -456,7 +465,7 @@ class PlaceholderShell(PlaceholderExpand):
         popen_args = {
             'cwd'  : None,
             'shell': True,
-            'env'  : os.environ,
+            'env': self.get_environ(),
             'stdout': subprocess.PIPE
         }
 
@@ -491,8 +500,8 @@ class TimeoutError(Exception):
 
 # The python placeholder evaluates commands in python
 class PlaceholderEval(PlaceholderExpand):
-    def __init__(self, view, tabstop, refs, begin, s, namespace):
-        PlaceholderExpand.__init__(self, view, tabstop, begin, s)
+    def __init__(self, view, tabstop, environ, refs, begin, s, namespace):
+        PlaceholderExpand.__init__(self, view, tabstop, environ, begin, s)
 
         self.fdread = 0
         self.remove_me = False
@@ -529,7 +538,7 @@ class PlaceholderEval(PlaceholderExpand):
         return hasattr(signal, 'SIGALRM')
 
     def timeout_cb(self, signum = 0, frame = 0):
-        raise TimeoutError, "Operation timed out (>2 seconds)"
+        raise TimeoutError("Operation timed out (>2 seconds)")
 
     def install_timeout(self):
         if not self.timeout_supported():
@@ -568,7 +577,7 @@ class PlaceholderEval(PlaceholderExpand):
             del self.namespace['process_snippet']
 
         try:
-            exec text in self.namespace
+            exec(text, self.namespace)
         except:
             traceback.print_exc()
 
@@ -593,7 +602,7 @@ class PlaceholderEval(PlaceholderExpand):
                 'time, execution aborted.') % self.command)
 
                 return False
-            except Exception, detail:
+            except Exception as detail:
                 self.remove_timeout()
 
                 message_dialog(None, Gtk.MessageType.ERROR,
@@ -612,8 +621,8 @@ class PlaceholderEval(PlaceholderExpand):
 
 # Regular expression placeholder
 class PlaceholderRegex(PlaceholderExpand):
-    def __init__(self, view, tabstop, begin, inp, pattern, substitution, modifiers):
-        PlaceholderExpand.__init__(self, view, tabstop, begin, '')
+    def __init__(self, view, tabstop, environ, begin, inp, pattern, substitution, modifiers):
+        PlaceholderExpand.__init__(self, view, tabstop, environ, begin, '')
 
         self.instant_update = True
         self.inp = inp
@@ -652,10 +661,12 @@ class PlaceholderRegex(PlaceholderExpand):
         return re.escape(s)
 
     def get_input(self):
+        env = self.get_environ()
+
         if isinstance(self.inp, int):
             return self.mirror_text[self.inp]
-        elif self.inp in os.environ:
-            return os.environ[self.inp]
+        elif self.inp in env:
+            return env[self.inp]
         else:
             return ''
 
@@ -672,7 +683,7 @@ class PlaceholderRegex(PlaceholderExpand):
         # Try to compile pattern
         try:
             regex = re.compile(pattern, self.modifiers)
-        except re.error, message:
+        except re.error as message:
             sys.stderr.write('Could not compile regular expression: %s\n%s\n' % (pattern, message))
             return False
 
diff --git a/plugins/snippets/snippets/Snippet.py b/plugins/snippets/snippets/Snippet.py
index 192b036..91e6380 100644
--- a/plugins/snippets/snippets/Snippet.py
+++ b/plugins/snippets/snippets/Snippet.py
@@ -16,11 +16,12 @@
 #    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
 import os
+import six
 from gi.repository import Gio, Gtk
 
-from Placeholder import *
-from Parser import Parser, Token
-from Helper import *
+from .Placeholder import *
+from .Parser import Parser, Token
+from .Helper import *
 
 class EvalUtilities:
     def __init__(self, view=None):
@@ -87,8 +88,8 @@ class EvalUtilities:
             for col in range(0, len(items[row]) - 1):
                 item = items[row][col]
 
-                result += item + ("\t" * ((maxlen[col] - \
-                        self._real_len(item, tablen)) / tablen))
+                result += item + ("\t" * int(((maxlen[col] - \
+                        self._real_len(item, tablen)) / tablen)))
 
             result += items[row][len(items[row]) - 1]
 
@@ -98,8 +99,9 @@ class EvalUtilities:
         return result
 
 class Snippet:
-    def __init__(self, data):
+    def __init__(self, data, environ = {}):
         self.data = data
+        self.environ = environ
 
     def __getitem__(self, prop):
         return self.data[prop]
@@ -132,7 +134,7 @@ class Snippet:
         if not detail:
             return nm
         else:
-            return nm + ' (<b>' + markup_escape(str.join(', ', detail)) + \
+            return nm + ' (<b>' + markup_escape(", ".join(detail)) + \
                     '</b>)'
 
     def _add_placeholder(self, placeholder):
@@ -149,14 +151,17 @@ class Snippet:
 
     def _insert_text(self, text):
         # Insert text keeping indentation in mind
-        indented = unicode.join('\n' + unicode(self._indent), spaces_instead_of_tabs(self._view, text).split('\n'))
+        indented = (six.u('\n') + self._indent).join(spaces_instead_of_tabs(self._view, text).split('\n'))
         self._view.get_buffer().insert(self._insert_iter(), indented)
 
     def _insert_iter(self):
         return self._view.get_buffer().get_iter_at_mark(self._insert_mark)
 
     def _create_environment(self, data):
-        val = ((data in os.environ) and os.environ[data]) or ''
+        if data in self.environ:
+            val = self.environ[data]
+        else:
+            val = ''
 
         # Get all the current indentation
         all_indent = compute_indentation(self._view, self._insert_iter())
@@ -165,7 +170,7 @@ class Snippet:
         indent = all_indent[len(self._indent):]
 
         # Keep indentation
-        return unicode.join('\n' + unicode(indent), val.split('\n'))
+        return (six.u('\n') + indent).join(val.split('\n'))
 
     def _create_placeholder(self, data):
         tabstop = data['tabstop']
@@ -173,25 +178,25 @@ class Snippet:
 
         if tabstop == 0:
             # End placeholder
-            return PlaceholderEnd(self._view, begin, data['default'])
+            return PlaceholderEnd(self._view, self.environ, begin, data['default'])
         elif tabstop in self.placeholders:
             # Mirror placeholder
-            return PlaceholderMirror(self._view, tabstop, begin)
+            return PlaceholderMirror(self._view, tabstop, self.environ, begin)
         else:
             # Default placeholder
-            return Placeholder(self._view, tabstop, data['default'], begin)
+            return Placeholder(self._view, tabstop, self.environ, data['default'], begin)
 
     def _create_shell(self, data):
         begin = self._insert_iter()
-        return PlaceholderShell(self._view, data['tabstop'], begin, data['contents'])
+        return PlaceholderShell(self._view, data['tabstop'], self.environ, begin, data['contents'])
 
     def _create_eval(self, data):
         begin = self._insert_iter()
-        return PlaceholderEval(self._view, data['tabstop'], data['dependencies'], begin, data['contents'], self._utils.namespace)
+        return PlaceholderEval(self._view, data['tabstop'], self.environ, data['dependencies'], begin, data['contents'], self._utils.namespace)
 
     def _create_regex(self, data):
         begin = self._insert_iter()
-        return PlaceholderRegex(self._view, data['tabstop'], begin, data['input'], data['pattern'], data['substitution'], data['modifiers'])
+        return PlaceholderRegex(self._view, data['tabstop'], self.environ, begin, data['input'], data['pattern'], data['substitution'], data['modifiers'])
 
     def _create_text(self, data):
         return data
@@ -239,11 +244,11 @@ class Snippet:
                     'eval': self._create_eval,
                     'regex': self._create_regex,
                     'text': self._create_text}[token.klass](token.data)
-            except:
+            except KeyError:
                 sys.stderr.write('Token class not supported: %s\n' % token.klass)
                 continue
 
-            if isinstance(val, basestring):
+            if isinstance(val, six.string_types):
                 # Insert text
                 self._insert_text(val)
             else:
@@ -252,7 +257,7 @@ class Snippet:
 
         # Create end placeholder if there isn't one yet
         if 0 not in self.placeholders:
-            self.placeholders[0] = PlaceholderEnd(self._view, self.end_iter(), None)
+            self.placeholders[0] = PlaceholderEnd(self._view, self.environ, self.end_iter(), None)
             self.plugin_data.ordered_placeholders.append(self.placeholders[0])
 
         # Make sure run_last is ran for all placeholders and remove any
@@ -317,8 +322,7 @@ class Snippet:
         # So now all of the snippet is in the buffer, we have all our
         # placeholders right here, what's next, put all marks in the
         # plugin_data.marks
-        k = self.placeholders.keys()
-        k.sort(reverse=True)
+        k = sorted(self.placeholders.keys(), reverse=True)
 
         plugin_data.placeholders.insert(last_index, self.placeholders[0])
         last_iter = self.placeholders[0].end_iter()
diff --git a/plugins/snippets/snippets/WindowHelper.py b/plugins/snippets/snippets/WindowHelper.py
index 296ff03..44ac558 100644
--- a/plugins/snippets/snippets/WindowHelper.py
+++ b/plugins/snippets/snippets/WindowHelper.py
@@ -21,8 +21,8 @@ import gettext
 
 from gi.repository import GObject, Gtk, Pluma
 
-from Document import Document
-from Library import Library
+from .Document import Document
+from .Library import Library
 
 class WindowHelper:
     def __init__(self, plugin):
diff --git a/plugins/snippets/snippets/__init__.py b/plugins/snippets/snippets/__init__.py
index 8642406..ada586c 100644
--- a/plugins/snippets/snippets/__init__.py
+++ b/plugins/snippets/snippets/__init__.py
@@ -18,9 +18,9 @@
 import os
 from gi.repository import GObject, GLib, Gtk, Peas, Pluma
 
-from WindowHelper import WindowHelper
-from Library import Library
-from Manager import Manager
+from .WindowHelper import WindowHelper
+from .Library import Library
+from .Manager import Manager
 
 class SnippetsPlugin(GObject.Object, Peas.Activatable):
     __gtype_name__ = "SnippetsPlugin"
@@ -53,7 +53,7 @@ class SnippetsPlugin(GObject.Object, Peas.Activatable):
         library = Library()
         library.add_accelerator_callback(self.accelerator_activated)
 
-        snippetsdir = os.path.join(GLib.get_user_config_dir(), '/pluma/snippets')
+        snippetsdir = os.path.join(GLib.get_user_config_dir(), 'pluma/snippets')
         library.set_dirs(snippetsdir, self.system_dirs())
 
         self._helper = WindowHelper(self)
@@ -72,15 +72,12 @@ class SnippetsPlugin(GObject.Object, Peas.Activatable):
         self._helper.update()
 
     def create_configure_dialog(self):
-        if not self.dlg:
-            self.dlg = Manager(self.plugin_info.get_data_dir())
-        else:
-            self.dlg.run()
-
         window = Pluma.App.get_default().get_active_window()
 
-        if window:
-            self.dlg.dlg.set_transient_for(window)
+        if not self.dlg:
+            self.dlg = Manager(self.plugin_info.get_data_dir(), window)
+        else:
+            self.dlg.run(window)
 
         return self.dlg.dlg
 
diff --git a/plugins/snippets/snippets/snippets.ui b/plugins/snippets/snippets/snippets.ui
index 6fcaf85..833aa02 100644
--- a/plugins/snippets/snippets/snippets.ui
+++ b/plugins/snippets/snippets/snippets.ui
@@ -1,8 +1,11 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.22.1 -->
 <!--*- mode: xml -*-->
 <interface>
+  <requires lib="gtk+" version="3.0"/>
   <object class="GtkListStore" id="model1">
     <columns>
+      <!-- column-name gchararray -->
       <column type="gchararray"/>
     </columns>
     <data>
@@ -32,303 +35,249 @@
       </row>
     </data>
   </object>
-  <object class="PlumaDocument" id="source_buffer">
-    <property name="highlight-matching-brackets">True</property>
-  </object>
   <object class="GtkDialog" id="dialog_snippets">
+    <property name="can_focus">False</property>
     <property name="title" translatable="yes">Snippets Manager</property>
-    <property name="type">GTK_WINDOW_TOPLEVEL</property>
-    <property name="window_position">GTK_WIN_POS_NONE</property>
-    <property name="modal">False</property>
     <property name="default_width">750</property>
     <property name="default_height">500</property>
-    <property name="resizable">True</property>
     <property name="destroy_with_parent">True</property>
-    <property name="decorated">True</property>
+    <property name="type_hint">dialog</property>
     <property name="skip_taskbar_hint">True</property>
-    <property name="skip_pager_hint">False</property>
-    <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
-    <property name="gravity">GDK_GRAVITY_NORTH_WEST</property>
-    <property name="focus_on_map">True</property>
-    <property name="urgency_hint">False</property>
-    <signal handler="on_dialog_snippets_response" last_modification_time="Mon, 19 Dec 2005 11:20:00 GMT" name="response"/>
-    <signal handler="on_dialog_snippets_destroy" last_modification_time="Sun, 22 Jun 2008 13:22:00 GMT" name="destroy"/>
+    <signal name="destroy" handler="on_dialog_snippets_destroy" swapped="no"/>
+    <signal name="response" handler="on_dialog_snippets_response" swapped="no"/>
+    <child>
+      <placeholder/>
+    </child>
     <child internal-child="vbox">
-      <object class="GtkVBox" id="dialog-vbox1">
+      <object class="GtkBox" id="dialog-vbox1">
         <property name="visible">True</property>
-        <property name="homogeneous">False</property>
-        <property name="spacing">0</property>
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
         <child internal-child="action_area">
-          <object class="GtkHButtonBox" id="dialog-action_area1">
+          <object class="GtkButtonBox" id="dialog-action_area1">
             <property name="visible">True</property>
-            <property name="layout_style">GTK_BUTTONBOX_END</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="layout_style">end</property>
             <child>
-              <object class="GtkButton" id="closebutton1">
+              <object class="GtkButton" id="button1">
+                <property name="label">gtk-help</property>
                 <property name="visible">True</property>
-                <property name="can_default">True</property>
                 <property name="can_focus">True</property>
-                <property name="label">gtk-close</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
                 <property name="use_stock">True</property>
-                <property name="relief">GTK_RELIEF_NORMAL</property>
-                <property name="focus_on_click">True</property>
               </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
             </child>
             <child>
-              <object class="GtkButton" id="button1">
+              <object class="GtkButton" id="closebutton1">
+                <property name="label">gtk-close</property>
                 <property name="visible">True</property>
-                <property name="can_default">True</property>
                 <property name="can_focus">True</property>
-                <property name="label">gtk-help</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
                 <property name="use_stock">True</property>
-                <property name="relief">GTK_RELIEF_NORMAL</property>
-                <property name="focus_on_click">True</property>
               </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="pack_type">end</property>
+                <property name="position">1</property>
+              </packing>
             </child>
           </object>
           <packing>
-            <property name="padding">0</property>
             <property name="expand">False</property>
             <property name="fill">True</property>
-            <property name="pack_type">GTK_PACK_END</property>
+            <property name="pack_type">end</property>
+            <property name="position">0</property>
           </packing>
         </child>
         <child>
-          <object class="GtkHPaned" id="hpaned_paned">
-            <property name="border_width">6</property>
+          <object class="GtkPaned">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
             <property name="position">275</property>
             <child>
-              <object class="GtkVBox" id="vbox_selection">
-                <property name="width_request">230</property>
+              <object class="GtkGrid" id="grid_selection">
                 <property name="visible">True</property>
-                <property name="homogeneous">False</property>
-                <property name="spacing">6</property>
-                <child>
-                  <object class="GtkLabel" id="label1">
-                    <property name="visible">True</property>
-                    <property name="label" translatable="yes">_Snippets:</property>
-                    <property name="use_underline">True</property>
-                    <property name="use_markup">False</property>
-                    <property name="justify">GTK_JUSTIFY_LEFT</property>
-                    <property name="wrap">False</property>
-                    <property name="selectable">False</property>
-                    <property name="xalign">0</property>
-                    <property name="yalign">0.5</property>
-                    <property name="xpad">0</property>
-                    <property name="ypad">0</property>
-                    <property name="mnemonic_widget">tree_view_snippets</property>
-                    <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                    <property name="width_chars">-1</property>
-                    <property name="single_line_mode">False</property>
-                    <property name="angle">0</property>
-                  </object>
-                  <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
-                  </packing>
-                </child>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="orientation">vertical</property>
+                <property name="row_spacing">6</property>
                 <child>
                   <object class="GtkScrolledWindow" id="scrolled_window_snippets">
                     <property name="visible">True</property>
                     <property name="can_focus">True</property>
-                    <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                    <property name="shadow_type">GTK_SHADOW_IN</property>
-                    <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="shadow_type">in</property>
                     <child>
                       <object class="GtkTreeView" id="tree_view_snippets">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
                         <property name="headers_visible">False</property>
-                        <property name="rules_hint">False</property>
-                        <property name="reorderable">False</property>
-                        <property name="enable_search">True</property>
-                        <property name="fixed_height_mode">False</property>
-                        <property name="hover_selection">False</property>
-                        <property name="hover_expand">False</property>
-                        <signal handler="on_tree_view_snippets_row_expanded" last_modification_time="Tue, 03 Jan 2006 22:06:02 GMT" name="row_expanded"/>
-                        <signal handler="on_tree_view_snippets_key_press" last_modification_time="Tue, 03 Jan 2006 22:07:00 GMT" name="key_press_event"/>
+                        <signal name="key-press-event" handler="on_tree_view_snippets_key_press" swapped="no"/>
+                        <signal name="row-expanded" handler="on_tree_view_snippets_row_expanded" swapped="no"/>
+                        <child internal-child="selection">
+                          <object class="GtkTreeSelection"/>
+                        </child>
                       </object>
                     </child>
                   </object>
                   <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkHBox" id="hbox_buttons">
+                  <object class="GtkLabel" id="label1">
                     <property name="visible">True</property>
-                    <property name="homogeneous">False</property>
-                    <property name="spacing">6</property>
+                    <property name="can_focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="label" translatable="yes">_Snippets:</property>
+                    <property name="use_underline">True</property>
+                    <property name="mnemonic_widget">tree_view_snippets</property>
+                  </object>
+                  <packing>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkGrid" id="grid_buttons">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="column_spacing">6</property>
                     <child>
                       <object class="GtkButton" id="button_new_snippet">
                         <property name="visible">True</property>
-                        <property name="tooltip-text" translatable="yes">Create new snippet</property>
-                        <property name="can_default">True</property>
                         <property name="can_focus">True</property>
-                        <property name="relief">GTK_RELIEF_NORMAL</property>
-                        <property name="focus_on_click">True</property>
-                        <signal handler="on_button_new_snippet_clicked" last_modification_time="Tue, 20 Dec 2005 19:50:58 GMT" name="clicked"/>
+                        <property name="can_default">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Create new snippet</property>
+                        <signal name="clicked" handler="on_button_new_snippet_clicked" swapped="no"/>
                         <child>
                           <object class="GtkImage" id="image1">
                             <property name="visible">True</property>
-                            <property name="stock">gtk-new</property>
-                            <property name="icon_size">4</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">document-new</property>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkButton" id="button_import_snippets">
                         <property name="visible">True</property>
-                        <property name="tooltip-text" translatable="yes">Import snippets</property>
-                        <property name="can_default">True</property>
                         <property name="can_focus">True</property>
-                        <property name="relief">GTK_RELIEF_NORMAL</property>
-                        <property name="focus_on_click">True</property>
-                        <signal handler="on_button_import_snippets_clicked" last_modification_time="Tue, 10 Jul 2007 18:37:11 GMT" name="clicked"/>
+                        <property name="can_default">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Import snippets</property>
+                        <signal name="clicked" handler="on_button_import_snippets_clicked" swapped="no"/>
                         <child>
                           <object class="GtkImage" id="image5">
                             <property name="visible">True</property>
-                            <property name="stock">gtk-open</property>
-                            <property name="icon_size">4</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">document-open</property>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
+                        <property name="left_attach">1</property>
+                        <property name="top_attach">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkButton" id="button_export_snippets">
                         <property name="visible">True</property>
-                        <property name="tooltip-text" translatable="yes">Export selected snippets</property>
-                        <property name="can_default">True</property>
                         <property name="can_focus">True</property>
-                        <property name="relief">GTK_RELIEF_NORMAL</property>
-                        <property name="focus_on_click">True</property>
-                        <signal handler="on_button_export_snippets_clicked" last_modification_time="Tue, 10 Jul 2007 18:37:25 GMT" name="clicked"/>
+                        <property name="can_default">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Export selected snippets</property>
+                        <signal name="clicked" handler="on_button_export_snippets_clicked" swapped="no"/>
                         <child>
                           <object class="GtkImage" id="image4">
                             <property name="visible">True</property>
-                            <property name="stock">gtk-save</property>
-                            <property name="icon_size">4</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">document-save</property>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
+                        <property name="left_attach">2</property>
+                        <property name="top_attach">0</property>
                       </packing>
                     </child>
                     <child>
                       <object class="GtkButton" id="button_remove_snippet">
                         <property name="visible">True</property>
                         <property name="sensitive">False</property>
-                        <property name="tooltip-text" translatable="yes">Delete selected snippet</property>
-                        <property name="can_default">True</property>
                         <property name="can_focus">True</property>
-                        <property name="relief">GTK_RELIEF_NORMAL</property>
-                        <property name="focus_on_click">True</property>
-                        <signal handler="on_button_remove_snippet_clicked" last_modification_time="Mon, 19 Dec 2005 13:15:14 GMT" name="clicked"/>
+                        <property name="can_default">True</property>
+                        <property name="receives_default">False</property>
+                        <property name="tooltip_text" translatable="yes">Delete selected snippet</property>
+                        <property name="halign">end</property>
+                        <property name="hexpand">True</property>
+                        <signal name="clicked" handler="on_button_remove_snippet_clicked" swapped="no"/>
                         <child>
                           <object class="GtkImage" id="image_remove">
                             <property name="visible">True</property>
-                            <property name="stock">gtk-delete</property>
-                            <property name="icon_size">4</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
+                            <property name="can_focus">False</property>
+                            <property name="icon_name">edit-delete</property>
                           </object>
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                        <property name="pack_type">GTK_PACK_END</property>
+                        <property name="left_attach">3</property>
+                        <property name="top_attach">0</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">2</property>
                   </packing>
                 </child>
               </object>
               <packing>
-                <property name="shrink">False</property>
                 <property name="resize">False</property>
+                <property name="shrink">True</property>
               </packing>
             </child>
             <child>
-              <object class="GtkVBox" id="vbox_snippet">
+              <object class="GtkGrid" id="grid_snippet">
                 <property name="visible">True</property>
-                <property name="homogeneous">False</property>
-                <property name="spacing">12</property>
+                <property name="can_focus">False</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="orientation">vertical</property>
+                <property name="row_spacing">12</property>
                 <child>
-                  <object class="GtkVBox" id="vbox2">
+                  <object class="GtkGrid">
                     <property name="visible">True</property>
-                    <property name="homogeneous">False</property>
-                    <property name="spacing">6</property>
-                    <child>
-                      <object class="GtkLabel" id="label4">
-                        <property name="visible">True</property>
-                        <property name="label" translatable="yes">_Edit:</property>
-                        <property name="use_underline">True</property>
-                        <property name="use_markup">False</property>
-                        <property name="justify">GTK_JUSTIFY_LEFT</property>
-                        <property name="wrap">False</property>
-                        <property name="selectable">False</property>
-                        <property name="xalign">0</property>
-                        <property name="yalign">0.5</property>
-                        <property name="xpad">0</property>
-                        <property name="ypad">0</property>
-                        <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                        <property name="width_chars">-1</property>
-                        <property name="single_line_mode">False</property>
-                        <property name="angle">0</property>
-                      </object>
-                      <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
-                      </packing>
-                    </child>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="vexpand">True</property>
+                    <property name="orientation">vertical</property>
+                    <property name="row_spacing">6</property>
                     <child>
                       <object class="GtkScrolledWindow" id="scrolled_window_snippet">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
-                        <property name="hscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                        <property name="vscrollbar_policy">GTK_POLICY_AUTOMATIC</property>
-                        <property name="shadow_type">GTK_SHADOW_IN</property>
-                        <property name="window_placement">GTK_CORNER_TOP_LEFT</property>
+                        <property name="hexpand">True</property>
+                        <property name="vexpand">True</property>
+                        <property name="shadow_type">in</property>
                         <child>
                           <object class="PlumaView" id="source_view_snippet">
                             <property name="buffer">source_buffer</property>
@@ -346,302 +295,198 @@
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
+                      </packing>
+                    </child>
+                    <child>
+                      <object class="GtkLabel" id="label4">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="hexpand">True</property>
+                        <property name="label" translatable="yes">_Edit:</property>
+                        <property name="use_underline">True</property>
+                      </object>
+                      <packing>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">True</property>
-                    <property name="fill">True</property>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">0</property>
                   </packing>
                 </child>
                 <child>
-                  <object class="GtkVBox" id="vbox1">
+                  <object class="GtkGrid">
                     <property name="visible">True</property>
-                    <property name="homogeneous">False</property>
-                    <property name="spacing">6</property>
+                    <property name="can_focus">False</property>
+                    <property name="hexpand">True</property>
+                    <property name="orientation">vertical</property>
+                    <property name="row_spacing">6</property>
                     <child>
                       <object class="GtkLabel" id="label3">
                         <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="halign">start</property>
+                        <property name="hexpand">True</property>
                         <property name="label" translatable="yes">Activation</property>
-                        <property name="use_underline">False</property>
                         <property name="use_markup">True</property>
-                        <property name="justify">GTK_JUSTIFY_LEFT</property>
-                        <property name="wrap">False</property>
-                        <property name="selectable">False</property>
-                        <property name="xalign">0</property>
-                        <property name="yalign">0.5</property>
-                        <property name="xpad">0</property>
-                        <property name="ypad">0</property>
-                        <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                        <property name="width_chars">-1</property>
-                        <property name="single_line_mode">False</property>
-                        <property name="angle">0</property>
                         <attributes>
-                          <attribute name="weight" value="PANGO_WEIGHT_BOLD"/>
+                          <attribute name="weight" value="bold"/>
                         </attributes>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">False</property>
-                        <property name="fill">False</property>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">0</property>
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkHBox" id="hbox1">
+                      <object class="GtkGrid">
                         <property name="visible">True</property>
-                        <property name="homogeneous">False</property>
-                        <property name="spacing">0</property>
+                        <property name="can_focus">False</property>
+                        <property name="margin_left">12</property>
+                        <property name="hexpand">True</property>
+                        <property name="row_spacing">6</property>
+                        <property name="column_spacing">6</property>
                         <child>
-                          <object class="GtkLabel" id="label2">
+                          <object class="GtkComboBox" id="combo_drop_targets">
                             <property name="visible">True</property>
-                            <property name="label" translatable="yes">    </property>
-                            <property name="use_underline">False</property>
-                            <property name="use_markup">False</property>
-                            <property name="justify">GTK_JUSTIFY_LEFT</property>
-                            <property name="wrap">False</property>
-                            <property name="selectable">False</property>
-                            <property name="xalign">0.5</property>
-                            <property name="yalign">0.5</property>
-                            <property name="xpad">0</property>
-                            <property name="ypad">0</property>
-                            <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                            <property name="width_chars">-1</property>
-                            <property name="single_line_mode">False</property>
-                            <property name="angle">0</property>
+                            <property name="can_focus">False</property>
+                            <property name="hexpand">True</property>
+                            <property name="model">model1</property>
+                            <property name="has_entry">True</property>
+                            <property name="entry_text_column">0</property>
+                            <child internal-child="entry">
+                              <object class="GtkEntry">
+                                <property name="can_focus">True</property>
+                              </object>
+                            </child>
                           </object>
                           <packing>
-                            <property name="padding">0</property>
-                            <property name="expand">False</property>
-                            <property name="fill">False</property>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">2</property>
+                            <property name="width">2</property>
                           </packing>
                         </child>
                         <child>
-                          <object class="GtkTable" id="table1">
+                          <object class="GtkLabel" id="label_drop_targets">
                             <property name="visible">True</property>
-                            <property name="n_rows">3</property>
-                            <property name="n_columns">2</property>
-                            <property name="homogeneous">False</property>
-                            <property name="row_spacing">6</property>
-                            <property name="column_spacing">6</property>
-                            <child>
-                              <object class="GtkLabel" id="label_tab_trigger">
-                                <property name="visible">True</property>
-                                <property comments="&quot;tab&quot; here means the tab key, not the notebook tab!" name="label" translatable="yes">_Tab trigger:</property>
-                                <property name="use_underline">True</property>
-                                <property name="use_markup">False</property>
-                                <property name="justify">GTK_JUSTIFY_LEFT</property>
-                                <property name="wrap">False</property>
-                                <property name="selectable">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0.5</property>
-                                <property name="xpad">0</property>
-                                <property name="ypad">0</property>
-                                <property name="mnemonic_widget">entry_tab_trigger</property>
-                                <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                                <property name="width_chars">-1</property>
-                                <property name="single_line_mode">False</property>
-                                <property name="angle">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">0</property>
-                                <property name="right_attach">1</property>
-                                <property name="top_attach">0</property>
-                                <property name="bottom_attach">1</property>
-                                <property name="x_options">fill</property>
-                                <property name="y_options"/>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkHBox" id="hbox_tab_trigger">
-                                <property name="visible">True</property>
-                                <child>
-                                  <object class="GtkEntry" id="entry_tab_trigger">
-                                    <property name="visible">True</property>
-                                    <property name="sensitive">False</property>
-                                    <property name="tooltip-text" translatable="yes">Single word the snippet is activated with after pressing Tab</property>
-                                    <property name="can_focus">True</property>
-                                    <property name="editable">True</property>
-                                    <property name="visibility">True</property>
-                                    <property name="max_length">0</property>
-                                    <property name="text" translatable="yes"/>
-                                    <property name="has_frame">True</property>
-                                    <property name="invisible_char">*</property>
-                                    <property name="activates_default">False</property>
-                                    <signal handler="on_entry_tab_trigger_focus_out" last_modification_time="Wed, 04 Jan 2006 14:07:29 GMT" name="focus_out_event"/>
-                                    <signal handler="on_entry_tab_trigger_changed" last_modification_time="Fri, 28 Apr 2006 16:50:34 GMT" name="changed"/>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">True</property>
-                                    <property name="position">0</property>
-                                  </packing>
-                                </child>
-                                <child>
-                                  <object class="GtkImage" id="image_tab_trigger">
-                                    <property name="visible">False</property>
-                                  </object>
-                                  <packing>
-                                    <property name="expand">False</property>
-                                    <property name="position">1</property>
-                                    <property name="padding">3</property>
-                                  </packing>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">0</property>
-                                <property name="bottom_attach">1</property>
-                                <property name="y_options"/>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkEntry" id="entry_accelerator">
-                                <property name="visible">True</property>
-                                <property name="sensitive">False</property>
-                                <property name="tooltip-text" translatable="yes">Shortcut key with which the snippet is activated</property>
-                                <property name="can_focus">True</property>
-                                <property name="editable">False</property>
-                                <property name="visibility">True</property>
-                                <property name="max_length">0</property>
-                                <property name="text" translatable="yes"/>
-                                <property name="has_frame">True</property>
-                                <property name="invisible_char">*</property>
-                                <property name="activates_default">False</property>
-                                <signal handler="on_entry_accelerator_focus_out" last_modification_time="Wed, 04 Jan 2006 14:07:20 GMT" name="focus_out_event"/>
-                                <signal handler="on_entry_accelerator_key_press" last_modification_time="Wed, 04 Jan 2006 14:07:23 GMT" name="key_press_event"/>
-                                <signal handler="on_entry_accelerator_focus_in" last_modification_time="Wed, 04 Jan 2006 14:09:06 GMT" name="focus_in_event"/>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="y_options"/>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label_accelerator">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">S_hortcut key:</property>
-                                <property name="use_underline">True</property>
-                                <property name="use_markup">False</property>
-                                <property name="justify">GTK_JUSTIFY_LEFT</property>
-                                <property name="wrap">False</property>
-                                <property name="selectable">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0.5</property>
-                                <property name="xpad">0</property>
-                                <property name="ypad">0</property>
-                                <property name="mnemonic_widget">entry_accelerator</property>
-                                <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                                <property name="width_chars">-1</property>
-                                <property name="single_line_mode">False</property>
-                                <property name="angle">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">0</property>
-                                <property name="right_attach">1</property>
-                                <property name="top_attach">1</property>
-                                <property name="bottom_attach">2</property>
-                                <property name="x_options">fill</property>
-                                <property name="y_options"/>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkLabel" id="label_drop_targets">
-                                <property name="visible">True</property>
-                                <property name="label" translatable="yes">_Drop targets:</property>
-                                <property name="use_underline">True</property>
-                                <property name="use_markup">False</property>
-                                <property name="justify">GTK_JUSTIFY_LEFT</property>
-                                <property name="wrap">False</property>
-                                <property name="selectable">False</property>
-                                <property name="xalign">0</property>
-                                <property name="yalign">0.5</property>
-                                <property name="xpad">0</property>
-                                <property name="ypad">0</property>
-                                <property name="mnemonic_widget">entry_accelerator</property>
-                                <property name="ellipsize">PANGO_ELLIPSIZE_NONE</property>
-                                <property name="width_chars">-1</property>
-                                <property name="single_line_mode">False</property>
-                                <property name="angle">0</property>
-                              </object>
-                              <packing>
-                                <property name="left_attach">0</property>
-                                <property name="right_attach">1</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="x_options">fill</property>
-                                <property name="y_options"/>
-                              </packing>
-                            </child>
-                            <child>
-                              <object class="GtkComboBox" id="combo_drop_targets">
-                                <property name="visible">True</property>
-                                <property name="add_tearoffs">False</property>
-                                <property name="has_frame">True</property>
-                                <property name="has_entry">True</property>
-                                <property name="focus_on_click">True</property>
-                                <property name="model">model1</property>
-                                <child>
-                                  <object class="GtkCellRendererText" id="renderer1"/>
-                                  <attributes>
-                                    <attribute name="text">0</attribute>
-                                  </attributes>
-                                </child>
-                              </object>
-                              <packing>
-                                <property name="left_attach">1</property>
-                                <property name="right_attach">2</property>
-                                <property name="top_attach">2</property>
-                                <property name="bottom_attach">3</property>
-                                <property name="x_options">fill</property>
-                                <property name="y_options">fill</property>
-                              </packing>
-                            </child>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes">_Drop targets:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="entry_accelerator">
+                            <property name="visible">True</property>
+                            <property name="sensitive">False</property>
+                            <property name="can_focus">True</property>
+                            <property name="tooltip_text" translatable="yes">Shortcut key with which the snippet is activated</property>
+                            <property name="hexpand">True</property>
+                            <property name="editable">False</property>
+                            <property name="invisible_char">*</property>
+                            <signal name="focus-in-event" handler="on_entry_accelerator_focus_in" swapped="no"/>
+                            <signal name="focus-out-event" handler="on_entry_accelerator_focus_out" swapped="no"/>
+                            <signal name="key-press-event" handler="on_entry_accelerator_key_press" swapped="no"/>
                           </object>
                           <packing>
-                            <property name="padding">0</property>
-                            <property name="expand">True</property>
-                            <property name="fill">True</property>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">1</property>
+                            <property name="width">2</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label_accelerator">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes">S_hortcut key:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">1</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkLabel" id="label_tab_trigger">
+                            <property name="visible">True</property>
+                            <property name="can_focus">False</property>
+                            <property name="halign">start</property>
+                            <property name="label" translatable="yes" comments="&quot;tab&quot; here means the tab key, not the notebook tab!">_Tab trigger:</property>
+                            <property name="use_underline">True</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">0</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkImage" id="image_tab_trigger">
+                            <property name="can_focus">False</property>
+                          </object>
+                          <packing>
+                            <property name="left_attach">2</property>
+                            <property name="top_attach">0</property>
+                          </packing>
+                        </child>
+                        <child>
+                          <object class="GtkEntry" id="entry_tab_trigger">
+                            <property name="visible">True</property>
+                            <property name="sensitive">False</property>
+                            <property name="can_focus">True</property>
+                            <property name="tooltip_text" translatable="yes">Single word the snippet is activated with after pressing Tab</property>
+                            <property name="hexpand">True</property>
+                            <property name="invisible_char">*</property>
+                            <signal name="changed" handler="on_entry_tab_trigger_changed" swapped="no"/>
+                            <signal name="focus-out-event" handler="on_entry_tab_trigger_focus_out" swapped="no"/>
+                          </object>
+                          <packing>
+                            <property name="left_attach">1</property>
+                            <property name="top_attach">0</property>
                           </packing>
                         </child>
                       </object>
                       <packing>
-                        <property name="padding">0</property>
-                        <property name="expand">True</property>
-                        <property name="fill">True</property>
+                        <property name="left_attach">0</property>
+                        <property name="top_attach">1</property>
                       </packing>
                     </child>
                   </object>
                   <packing>
-                    <property name="padding">0</property>
-                    <property name="expand">False</property>
-                    <property name="fill">False</property>
+                    <property name="left_attach">0</property>
+                    <property name="top_attach">1</property>
                   </packing>
                 </child>
               </object>
               <packing>
-                <property name="shrink">True</property>
                 <property name="resize">True</property>
+                <property name="shrink">True</property>
               </packing>
             </child>
           </object>
           <packing>
-            <property name="padding">0</property>
             <property name="expand">True</property>
             <property name="fill">True</property>
+            <property name="position">1</property>
           </packing>
         </child>
       </object>
     </child>
     <action-widgets>
-      <action-widget response="-7">closebutton1</action-widget>
       <action-widget response="-11">button1</action-widget>
+      <action-widget response="-7">closebutton1</action-widget>
     </action-widgets>
   </object>
+  <object class="PlumaDocument" id="source_buffer">
+    <property name="highlight-matching-brackets">True</property>
+  </object>
 </interface>
-- 
2.21.0