Commit ee6bddc9 authored by Kai Willadsen's avatar Kai Willadsen

preferences: Migrate filter settings to GSettings

parent 019341fd
......@@ -106,5 +106,34 @@
<summary>Version control status filters</summary>
<description>List of statuses used to filter visible files in version control comparison.</description>
</key>
<!-- Filters -->
<key name="filename-filters" type="a(sbs)">
<default>
[
("Backups", true, "#*# .#* ~* *~ *.{orig,bak,swp}"),
("OS-specific metadata", true, ".DS_Store ._* .Spotlight-V100 .Trashes Thumbs.db Desktop.ini"),
("Version Control", true, "_MTN .bzr .svn .svn .hg .fslckout _FOSSIL_ .fos CVS _darcs .git .svn"),
("Binaries", true, "*.{pyc,a,obj,o,so,la,lib,dll,exe}"),
("Media", false, "*.{jpg,gif,png,bmp,wav,mp3,ogg,flac,avi,mpg,xcf,xpm}")
]
</default>
<summary>Filename-based filters</summary>
<description>List of predefined filename-based filters that, if active, will remove matching files from a folder comparison.</description>
</key>
<key name="text-filters" type="a(sbs)">
<default>
[
("CVS keywords", false, "\$\\w+(:[^\\n$]+)?\$"),
("C++ comment", false, "//.*"),
("C comment", false, "/\\*.*?\\*/"),
("All whitespace", false, "[ \\t\\r\\f\\v]*"),
("Leading whitespace", false, "^[ \\t\\r\\f\\v]*"),
("Script comment", false, "#.*")
]
</default>
<summary>Text-based filters</summary>
<description>List of predefined text-based regex filters that, if active, will remove text from being used in a file comparison. The text will still be displayed, but won't contribute to the comparison itself.</description>
</key>
</schema>
</schemalist>
......@@ -47,7 +47,7 @@ from gettext import gettext as _
from gettext import ngettext
from .meldapp import app
from meld.settings import settings
from meld.settings import meldsettings, settings
################################################################################
......@@ -316,10 +316,12 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
self.text_filters = []
self.create_name_filters()
self.create_text_filters()
self.app_handlers = [app.connect("file-filters-changed",
self.on_file_filters_changed),
app.connect("text-filters-changed",
self.on_text_filters_changed)]
self.settings_handlers = [
meldsettings.connect("file-filters-changed",
self.on_file_filters_changed),
meldsettings.connect("text-filters-changed",
self.on_text_filters_changed)
]
self.map_widgets_into_lists(["treeview", "fileentry", "scrolledwindow",
"diffmap", "linkmap", "msgarea_mgr",
......@@ -543,11 +545,13 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
def create_name_filters(self):
# Ordering of name filters is irrelevant
old_active = set([f.filter_string for f in self.name_filters if f.active])
new_active = set([f.filter_string for f in app.file_filters if f.active])
old_active = set([f.filter_string for f in self.name_filters
if f.active])
new_active = set([f.filter_string for f in meldsettings.file_filters
if f.active])
active_filters_changed = old_active != new_active
self.name_filters = [copy.copy(f) for f in app.file_filters]
self.name_filters = [copy.copy(f) for f in meldsettings.file_filters]
actions = []
disabled_actions = []
self.filter_ui = []
......@@ -575,10 +579,11 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
def create_text_filters(self):
# In contrast to file filters, ordering of text filters can matter
old_active = [f.filter_string for f in self.text_filters if f.active]
new_active = [f.filter_string for f in app.text_filters if f.active]
new_active = [f.filter_string for f in meldsettings.text_filters
if f.active]
active_filters_changed = old_active != new_active
self.text_filters = [copy.copy(f) for f in app.text_filters]
self.text_filters = [copy.copy(f) for f in meldsettings.text_filters]
return active_filters_changed
......@@ -1508,8 +1513,8 @@ class DirDiff(melddoc.MeldDoc, gnomeglade.Component):
self.on_fileentry_file_set(None)
def on_delete_event(self, appquit=0):
for h in self.app_handlers:
app.disconnect(h)
for h in self.settings_handlers:
meldsettings.disconnect(h)
return Gtk.ResponseType.OK
......
......@@ -46,7 +46,7 @@ from . import undo
from .ui import findbar
from .ui import gnomeglade
from meld.settings import settings
from meld.settings import meldsettings, settings
from .meldapp import app
from .util.compat import text_type
from .util.sourceviewer import LanguageManager
......@@ -197,8 +197,10 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
self.undosequence = undo.UndoSequence()
self.text_filters = []
self.create_text_filters()
self.app_handlers = [app.connect("text-filters-changed",
self.on_text_filters_changed)]
self.settings_handlers = [
meldsettings.connect("text-filters-changed",
self.on_text_filters_changed)
]
self.buffer_filtered = [meldbuffer.BufferLines(b, self._filter_text)
for b in self.textbuffer]
for (i, w) in enumerate(self.scrolledwindow):
......@@ -425,10 +427,11 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
def create_text_filters(self):
# In contrast to file filters, ordering of text filters can matter
old_active = [f.filter_string for f in self.text_filters if f.active]
new_active = [f.filter_string for f in app.text_filters if f.active]
new_active = [f.filter_string for f in meldsettings.text_filters
if f.active]
active_filters_changed = old_active != new_active
self.text_filters = [copy.copy(f) for f in app.text_filters]
self.text_filters = [copy.copy(f) for f in meldsettings.text_filters]
return active_filters_changed
......@@ -892,8 +895,8 @@ class FileDiff(melddoc.MeldDoc, gnomeglade.Component):
def on_delete_event(self, appquit=0):
response = self.check_save_modified()
if response == Gtk.ResponseType.OK:
for h in self.app_handlers:
app.disconnect(h)
for h in self.settings_handlers:
meldsettings.disconnect(h)
return response
#
......
......@@ -70,6 +70,14 @@ class FilterEntry(object):
active = False
return FilterEntry(name, active, compiled, filter_string)
@classmethod
def new_from_gsetting(cls, elements, filter_type):
name, active, filter_string = elements
compiled = FilterEntry.compile_filter(filter_string, filter_type)
if compiled is None:
active = False
return FilterEntry(name, active, compiled, filter_string)
@classmethod
def compile_filter(cls, filter_string, filter_type):
if filter_type == FilterEntry.REGEX:
......
......@@ -37,13 +37,6 @@ import meld.recent
class MeldApp(Gtk.Application):
__gsignals__ = {
'file-filters-changed': (GObject.SignalFlags.RUN_FIRST,
None, ()),
'text-filters-changed': (GObject.SignalFlags.RUN_FIRST,
None, ()),
}
def __init__(self):
Gtk.Application.__init__(self)
self.set_flags(Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
......@@ -51,11 +44,6 @@ class MeldApp(Gtk.Application):
GObject.set_application_name("Meld")
Gtk.Window.set_default_icon_name("meld")
self.prefs = meld.preferences.MeldPreferences()
self.prefs.notify_add(self.on_preference_changed)
self.file_filters = self._parse_filters(self.prefs.filters,
meld.filters.FilterEntry.SHELL)
self.text_filters = self._parse_filters(self.prefs.regexes,
meld.filters.FilterEntry.REGEX)
self.recent_comparisons = meld.recent.RecentFiles(sys.argv[0])
self.window = None
......@@ -133,21 +121,6 @@ class MeldApp(Gtk.Application):
return self.window.open_paths(paths, **kwargs)
def on_preference_changed(self, key, val):
if key == "filters":
self.file_filters = self._parse_filters(
val, meld.filters.FilterEntry.SHELL)
self.emit('file-filters-changed')
elif key == "regexes":
self.text_filters = self._parse_filters(
val, meld.filters.FilterEntry.REGEX)
self.emit('text-filters-changed')
def _parse_filters(self, string, filt_type):
filt = [meld.filters.FilterEntry.parse(l, filt_type) for l
in string.split("\n")]
return [f for f in filt if f is not None]
def diff_files_callback(self, option, opt_str, value, parser):
"""Gather --diff arguments and append to a list"""
assert value is None
......
......@@ -19,12 +19,11 @@
from gettext import gettext as _
from gi.repository import Gio
from gi.repository import GLib
from gi.repository import GObject
from gi.repository import Gtk
from . import filters
from . import misc
from . import vc
from .ui import gnomeglade
from .ui import listwidget
from .util import prefs
......@@ -40,20 +39,19 @@ TIMESTAMP_RESOLUTION_PRESETS = [('1ns (ext4)', 1),
class FilterList(listwidget.ListWidget):
def __init__(self, prefs, key, filter_type):
def __init__(self, key, filter_type):
default_entry = [_("label"), False, _("pattern"), True]
listwidget.ListWidget.__init__(self, "EditableList.ui",
"list_alignment", ["EditableListStore"],
"EditableList", default_entry)
self.prefs = prefs
self.key = key
self.filter_type = filter_type
self.pattern_column.set_cell_data_func(self.validity_renderer,
self.valid_icon_celldata)
for filtstring in getattr(self.prefs, self.key).split("\n"):
filt = filters.FilterEntry.parse(filtstring, filter_type)
for filter_params in settings.get_value(self.key):
filt = filters.FilterEntry.new_from_gsetting(filter_params, filter_type)
if filt is None:
continue
valid = filt.filter is not None
......@@ -84,14 +82,8 @@ class FilterList(listwidget.ListWidget):
self.model[path][3] = valid
def _update_filter_string(self, *args):
pref = []
for row in self.model:
pattern = row[2]
if pattern:
pattern = pattern.replace('\r', '')
pattern = pattern.replace('\n', '')
pref.append("%s\t%s\t%s" % (row[0], 1 if row[1] else 0, pattern))
setattr(self.prefs, self.key, "\n".join(pref))
value = [(row[0], row[1], row[2]) for row in self.model]
settings.set_value(self.key, GLib.Variant('a(sbs)', value))
class ColumnList(listwidget.ListWidget):
......@@ -226,13 +218,11 @@ class PreferencesDialog(gnomeglade.Component):
self.checkbutton_wrap_text.set_active(True)
# file filters
self.filefilter = FilterList(self.prefs, "filters",
filters.FilterEntry.SHELL)
self.filefilter = FilterList("filename-filters", filters.FilterEntry.SHELL)
self.file_filters_tab.pack_start(self.filefilter.widget, True, True, 0)
# text filters
self.textfilter = FilterList(self.prefs, "regexes",
filters.FilterEntry.REGEX)
self.textfilter = FilterList("text-filters", filters.FilterEntry.REGEX)
self.text_filters_tab.pack_start(self.textfilter.widget, True, True, 0)
self.checkbutton_ignore_blank_lines.set_active( self.prefs.ignore_blank_lines )
# encoding
......@@ -304,29 +294,6 @@ class MeldPreferences(prefs.Preferences):
"edit_wrap_lines" : prefs.Value(prefs.INT, 0),
"text_codecs": prefs.Value(prefs.STRING, "utf8 latin1"),
"vc_console_visible": prefs.Value(prefs.BOOL, 0),
"filters" : prefs.Value(prefs.STRING,
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("Backups\t1\t#*# .#* ~* *~ *.{orig,bak,swp}\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("OS-specific metadata\t0\t.DS_Store ._* .Spotlight-V100 .Trashes Thumbs.db Desktop.ini\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("Version Control\t1\t%s\n") % misc.shell_escape(' '.join(vc.get_plugins_metadata())) + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("Binaries\t1\t*.{pyc,a,obj,o,so,la,lib,dll,exe}\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("Media\t0\t*.{jpg,gif,png,bmp,wav,mp3,ogg,flac,avi,mpg,xcf,xpm}")),
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
"regexes" : prefs.Value(prefs.STRING, _("CVS keywords\t0\t\$\\w+(:[^\\n$]+)?\$\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("C++ comment\t0\t//.*\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("C comment\t0\t/\*.*?\*/\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("All whitespace\t0\t[ \\t\\r\\f\\v]*\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("Leading whitespace\t0\t^[ \\t\\r\\f\\v]*\n") + \
#TRANSLATORS: translate this string ONLY to the first "\t", leave it and the following parts intact
_("Script comment\t0\t#.*")),
"ignore_blank_lines" : prefs.Value(prefs.BOOL, False),
"toolbar_visible" : prefs.Value(prefs.BOOL, True),
"statusbar_visible" : prefs.Value(prefs.BOOL, True),
......@@ -336,7 +303,6 @@ class MeldPreferences(prefs.Preferences):
"dirdiff_columns": prefs.Value(prefs.LIST,
["size 1", "modification time 1",
"permissions 0"]),
"vc_left_is_local": prefs.Value(prefs.BOOL, False),
}
......
......@@ -15,9 +15,10 @@
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
from gi.repository import Gio
from gi.repository import GObject
import meld.conf
import meld.filters
schema_source = Gio.SettingsSchemaSource.new_from_directory(
meld.conf.DATADIR,
......@@ -28,3 +29,40 @@ schema = schema_source.lookup('org.gnome.meld', False)
settings = Gio.Settings.new_full(schema, None, None)
interface_settings = Gio.Settings.new('org.gnome.desktop.interface')
class MeldSettings(GObject.GObject):
"""Handler for settings that can't easily be bound to object properties"""
__gsignals__ = {
'file-filters-changed': (GObject.SignalFlags.RUN_FIRST,
None, ()),
'text-filters-changed': (GObject.SignalFlags.RUN_FIRST,
None, ()),
}
def __init__(self):
GObject.GObject.__init__(self)
self.on_setting_changed(settings, 'filename-filters')
self.on_setting_changed(settings, 'text-filters')
settings.connect('changed', self.on_setting_changed)
def on_setting_changed(self, settings, key):
if key == 'filename-filters':
self.file_filters = self._filters_from_gsetting(
'filename-filters', meld.filters.FilterEntry.SHELL)
self.emit('file-filters-changed')
elif key == 'text-filters':
self.text_filters = self._filters_from_gsetting(
'text-filters', meld.filters.FilterEntry.REGEX)
self.emit('text-filters-changed')
def _filters_from_gsetting(self, key, filt_type):
filter_params = settings.get_value(key)
filters = [
meld.filters.FilterEntry.new_from_gsetting(params, filt_type)
for params in filter_params
]
return filters
meldsettings = MeldSettings()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment