Skip to content

Commit e0d7014

Browse files
committed
preferences: Migrate list widgets to templates and resource loading
This is a big commit because the old separation between the ListWidget class and the actually-used subclasses was kind of wild. Now, EditableListWidget is much simpler and exists mostly to handle sensitivity setting and simple treemodel manipulation. Everything else lives on the actual list widgets themselves, which are now real widgets that do nice, normal GObject property things.
1 parent 1d7275e commit e0d7014

7 files changed

Lines changed: 499 additions & 410 deletions

File tree

data/meld.css

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010
padding: 3px 2px 2px 2px;
1111
}
1212

13+
.prefs-list-widget-toolbar {
14+
background-image: none;
15+
background-color: @theme_bg_color;
16+
border-width: 0 1px 1px 1px;
17+
border-style: solid;
18+
border-color: @borders;
19+
}
20+
1321
link-map {
1422
border-width: 0 0 1px 0;
1523
border-style: solid;

data/ui/EditableList.ui

Lines changed: 0 additions & 354 deletions
This file was deleted.

meld/preferences.py

Lines changed: 114 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -23,25 +23,54 @@
2323
from meld.conf import _
2424
from meld.filters import FilterEntry
2525
from meld.settings import settings
26+
from meld.ui._gtktemplate import Template
2627
from meld.ui.gnomeglade import Component
27-
from meld.ui.listwidget import ListWidget
28-
29-
30-
class FilterList(ListWidget):
31-
32-
def __init__(self, key, filter_type):
33-
default_entry = [_("label"), False, _("pattern"), True]
34-
super().__init__(
35-
"EditableList.ui", "list_vbox", ["EditableListStore"],
36-
"EditableList", default_entry)
37-
self.key = key
38-
self.filter_type = filter_type
28+
from meld.ui.listwidget import EditableListWidget
29+
30+
31+
@Template(resource_path='/org/gnome/meld/ui/filter-list.ui')
32+
class FilterList(Gtk.VBox, EditableListWidget):
33+
34+
__gtype_name__ = "FilterList"
35+
36+
treeview = Template.Child("treeview")
37+
remove = Template.Child("remove")
38+
move_up = Template.Child("move_up")
39+
move_down = Template.Child("move_down")
40+
pattern_column = Template.Child("pattern_column")
41+
validity_renderer = Template.Child("validity_renderer")
42+
43+
default_entry = [_("label"), False, _("pattern"), True]
44+
45+
filter_type = GObject.Property(
46+
type=int,
47+
flags=(
48+
GObject.ParamFlags.READABLE |
49+
GObject.ParamFlags.WRITABLE |
50+
GObject.ParamFlags.CONSTRUCT_ONLY
51+
),
52+
)
53+
54+
settings_key = GObject.Property(
55+
type=str,
56+
flags=(
57+
GObject.ParamFlags.READABLE |
58+
GObject.ParamFlags.WRITABLE |
59+
GObject.ParamFlags.CONSTRUCT_ONLY
60+
),
61+
)
62+
63+
def __init__(self, **kwargs):
64+
super().__init__(self, **kwargs)
65+
FilterList.init_template(self)
66+
self.model = self.treeview.get_model()
3967

4068
self.pattern_column.set_cell_data_func(
4169
self.validity_renderer, self.valid_icon_celldata)
4270

43-
for filter_params in settings.get_value(self.key):
44-
filt = FilterEntry.new_from_gsetting(filter_params, filter_type)
71+
for filter_params in settings.get_value(self.settings_key):
72+
filt = FilterEntry.new_from_gsetting(
73+
filter_params, self.filter_type)
4574
if filt is None:
4675
continue
4776
valid = filt.filter is not None
@@ -52,45 +81,84 @@ def __init__(self, key, filter_type):
5281
'rows-reordered'):
5382
self.model.connect(signal, self._update_filter_string)
5483

55-
self._update_sensitivity()
84+
self.setup_sensitivity_handling()
5685

5786
def valid_icon_celldata(self, col, cell, model, it, user_data=None):
5887
is_valid = model.get_value(it, 3)
5988
icon_name = "gtk-dialog-warning" if not is_valid else None
6089
cell.set_property("stock-id", icon_name)
6190

91+
@Template.Callback()
92+
def on_add_clicked(self, button):
93+
self.add_entry()
94+
95+
@Template.Callback()
96+
def on_remove_clicked(self, button):
97+
self.remove_selected_entry()
98+
99+
@Template.Callback()
100+
def on_move_up_clicked(self, button):
101+
self.move_up_selected_entry()
102+
103+
@Template.Callback()
104+
def on_move_down_clicked(self, button):
105+
self.move_down_selected_entry()
106+
107+
@Template.Callback()
62108
def on_name_edited(self, ren, path, text):
63109
self.model[path][0] = text
64110

111+
@Template.Callback()
65112
def on_cellrenderertoggle_toggled(self, ren, path):
66113
self.model[path][1] = not ren.get_active()
67114

115+
@Template.Callback()
68116
def on_pattern_edited(self, ren, path, text):
69117
valid = FilterEntry.check_filter(text, self.filter_type)
70118
self.model[path][2] = text
71119
self.model[path][3] = valid
72120

73121
def _update_filter_string(self, *args):
74122
value = [(row[0], row[1], row[2]) for row in self.model]
75-
settings.set_value(self.key, GLib.Variant('a(sbs)', value))
123+
settings.set_value(self.settings_key, GLib.Variant('a(sbs)', value))
76124

77125

78-
class ColumnList(ListWidget):
126+
@Template(resource_path='/org/gnome/meld/ui/column-list.ui')
127+
class ColumnList(Gtk.VBox, EditableListWidget):
128+
129+
__gtype_name__ = "ColumnList"
130+
131+
treeview = Template.Child("treeview")
132+
remove = Template.Child("remove")
133+
move_up = Template.Child("move_up")
134+
move_down = Template.Child("move_down")
135+
136+
default_entry = [_("label"), False, _("pattern"), True]
79137

80138
available_columns = {
81139
"size": _("Size"),
82140
"modification time": _("Modification time"),
83141
"permissions": _("Permissions"),
84142
}
85143

86-
def __init__(self, key):
87-
super().__init__(
88-
"EditableList.ui", "columns_ta", ["ColumnsListStore"],
89-
"columns_treeview")
90-
self.key = key
144+
settings_key = GObject.Property(
145+
type=str,
146+
flags=(
147+
GObject.ParamFlags.READABLE |
148+
GObject.ParamFlags.WRITABLE |
149+
GObject.ParamFlags.CONSTRUCT_ONLY
150+
),
151+
)
152+
153+
def __init__(self, **kwargs):
154+
super().__init__(self, **kwargs)
155+
ColumnList.init_template(self)
156+
self.model = self.treeview.get_model()
91157

92158
# Unwrap the variant
93-
prefs_columns = [(k, v) for k, v in settings.get_value(self.key)]
159+
prefs_columns = [
160+
(k, v) for k, v in settings.get_value(self.settings_key)
161+
]
94162
column_vis = {}
95163
column_order = {}
96164
for sort_key, (column_name, visibility) in enumerate(prefs_columns):
@@ -110,14 +178,23 @@ def __init__(self, key):
110178
'rows-reordered'):
111179
self.model.connect(signal, self._update_columns)
112180

113-
self._update_sensitivity()
181+
self.setup_sensitivity_handling()
182+
183+
@Template.Callback()
184+
def on_move_up_clicked(self, button):
185+
self.move_up_selected_entry()
186+
187+
@Template.Callback()
188+
def on_move_down_clicked(self, button):
189+
self.move_down_selected_entry()
114190

191+
@Template.Callback()
115192
def on_cellrenderertoggle_toggled(self, ren, path):
116193
self.model[path][0] = not ren.get_active()
117194

118195
def _update_columns(self, *args):
119196
value = [(c[1].lower(), c[0]) for c in self.model]
120-
settings.set_value(self.key, GLib.Variant('a(sb)', value))
197+
settings.set_value(self.settings_key, GLib.Variant('a(sb)', value))
121198

122199

123200
class GSettingsComboBox(Gtk.ComboBox):
@@ -237,14 +314,20 @@ def __init__(self, parent):
237314
self.checkbutton_wrap_text.set_active(wrap_mode != Gtk.WrapMode.NONE)
238315
self.checkbutton_wrap_word.set_active(wrap_mode == Gtk.WrapMode.WORD)
239316

240-
filefilter = FilterList("filename-filters", FilterEntry.SHELL)
241-
self.file_filters_vbox.pack_start(filefilter.widget, True, True, 0)
317+
filefilter = FilterList(
318+
filter_type=FilterEntry.SHELL,
319+
settings_key="filename-filters",
320+
)
321+
self.file_filters_vbox.pack_start(filefilter, True, True, 0)
242322

243-
textfilter = FilterList("text-filters", FilterEntry.REGEX)
244-
self.text_filters_vbox.pack_start(textfilter.widget, True, True, 0)
323+
textfilter = FilterList(
324+
filter_type=FilterEntry.REGEX,
325+
settings_key="text-filters",
326+
)
327+
self.text_filters_vbox.pack_start(textfilter, True, True, 0)
245328

246-
columnlist = ColumnList("folder-columns")
247-
self.column_list_vbox.pack_start(columnlist.widget, True, True, 0)
329+
columnlist = ColumnList(settings_key="folder-columns")
330+
self.column_list_vbox.pack_start(columnlist, True, True, 0)
248331

249332
self.combo_timestamp.bind_to('folder-time-resolution')
250333
self.combo_file_order.bind_to('vc-left-is-local')

meld/resources/meld.gresource.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@
99
<file>icons/16x16/actions/meld-change-delete.png</file>
1010
<file>ui/about-dialog.ui</file>
1111
<file>ui/appwindow.ui</file>
12+
<file>ui/column-list.ui</file>
1213
<file>ui/commit-dialog.ui</file>
1314
<file>ui/encoding-selector.ui</file>
15+
<file>ui/filter-list.ui</file>
1416
<file>ui/language-selector.ui</file>
1517
<file>ui/patch-dialog.ui</file>
1618
<file>ui/push-dialog.ui</file>

meld/resources/ui/column-list.ui

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<interface>
3+
<requires lib="gtk+" version="3.20"/>
4+
<object class="GtkListStore" id="column_list_store">
5+
<columns>
6+
<!-- column-name Active -->
7+
<column type="gboolean"/>
8+
<!-- column-name ID -->
9+
<column type="gchararray"/>
10+
<!-- column-name Label -->
11+
<column type="gchararray"/>
12+
</columns>
13+
</object>
14+
<template class="ColumnList" parent="GtkVBox">
15+
<property name="visible">True</property>
16+
<property name="can_focus">False</property>
17+
<property name="homogeneous">False</property>
18+
<child>
19+
<object class="GtkScrolledWindow" id="scrolledwindow2">
20+
<property name="visible">True</property>
21+
<property name="can_focus">True</property>
22+
<property name="hscrollbar_policy">automatic</property>
23+
<property name="vscrollbar_policy">automatic</property>
24+
<property name="shadow_type">in</property>
25+
<child>
26+
<object class="GtkTreeView" id="treeview">
27+
<property name="visible">True</property>
28+
<property name="can_focus">True</property>
29+
<property name="model">column_list_store</property>
30+
<property name="headers_clickable">False</property>
31+
<property name="reorderable">True</property>
32+
<property name="search_column">0</property>
33+
<property name="show_expanders">False</property>
34+
<property name="rubber_banding">True</property>
35+
<child>
36+
<object class="GtkTreeViewColumn" id="active_column">
37+
<property name="title" translatable="yes">Active</property>
38+
<child>
39+
<object class="GtkCellRendererToggle" id="cr_active">
40+
<signal name="toggled" handler="on_cellrenderertoggle_toggled" swapped="no"/>
41+
</object>
42+
<attributes>
43+
<attribute name="active">0</attribute>
44+
</attributes>
45+
</child>
46+
</object>
47+
</child>
48+
<child>
49+
<object class="GtkTreeViewColumn" id="name_column">
50+
<property name="title" translatable="yes">Column Name</property>
51+
<child>
52+
<object class="GtkCellRendererText" id="cr_name"/>
53+
<attributes>
54+
<attribute name="text">2</attribute>
55+
</attributes>
56+
</child>
57+
</object>
58+
</child>
59+
</object>
60+
</child>
61+
</object>
62+
<packing>
63+
<property name="expand">True</property>
64+
<property name="fill">True</property>
65+
<property name="position">0</property>
66+
</packing>
67+
</child>
68+
<child>
69+
<object class="GtkToolbar" id="list_toolbar">
70+
<property name="visible">True</property>
71+
<property name="can_focus">False</property>
72+
<property name="toolbar_style">icons</property>
73+
<property name="show_arrow">False</property>
74+
<property name="icon_size">1</property>
75+
<property name="icon_size_set">True</property>
76+
<style>
77+
<class name="prefs-list-widget-toolbar"/>
78+
</style>
79+
<child>
80+
<object class="GtkToolButton" id="add">
81+
<property name="can_focus">False</property>
82+
<property name="use_action_appearance">False</property>
83+
<property name="label" translatable="yes">_Add</property>
84+
<property name="use_underline">True</property>
85+
<property name="icon_name">list-add</property>
86+
<signal name="clicked" handler="on_add_clicked" swapped="no"/>
87+
</object>
88+
<packing>
89+
<property name="expand">False</property>
90+
<property name="homogeneous">True</property>
91+
</packing>
92+
</child>
93+
<child>
94+
<object class="GtkToolButton" id="remove">
95+
<property name="can_focus">False</property>
96+
<property name="use_action_appearance">False</property>
97+
<property name="label" translatable="yes">_Remove</property>
98+
<property name="use_underline">True</property>
99+
<property name="icon_name">list-remove</property>
100+
<signal name="clicked" handler="on_remove_clicked" swapped="no"/>
101+
</object>
102+
<packing>
103+
<property name="expand">False</property>
104+
<property name="homogeneous">True</property>
105+
</packing>
106+
</child>
107+
<child>
108+
<object class="GtkSeparatorToolItem" id="up_down_sep">
109+
<property name="can_focus">False</property>
110+
</object>
111+
<packing>
112+
<property name="expand">False</property>
113+
<property name="homogeneous">True</property>
114+
</packing>
115+
</child>
116+
<child>
117+
<object class="GtkToolButton" id="move_up">
118+
<property name="visible">True</property>
119+
<property name="can_focus">False</property>
120+
<property name="tooltip_text" translatable="yes">Move item up</property>
121+
<property name="use_action_appearance">False</property>
122+
<property name="label" translatable="yes">Move _Up</property>
123+
<property name="use_underline">True</property>
124+
<property name="icon_name">go-up</property>
125+
<signal name="clicked" handler="on_move_up_clicked" swapped="no"/>
126+
</object>
127+
<packing>
128+
<property name="expand">False</property>
129+
<property name="homogeneous">True</property>
130+
</packing>
131+
</child>
132+
<child>
133+
<object class="GtkToolButton" id="move_down">
134+
<property name="visible">True</property>
135+
<property name="can_focus">False</property>
136+
<property name="tooltip_text" translatable="yes">Move item down</property>
137+
<property name="use_action_appearance">False</property>
138+
<property name="label" translatable="yes">Move _Down</property>
139+
<property name="use_underline">True</property>
140+
<property name="icon_name">go-down</property>
141+
<signal name="clicked" handler="on_move_down_clicked" swapped="no"/>
142+
</object>
143+
<packing>
144+
<property name="expand">False</property>
145+
<property name="homogeneous">True</property>
146+
</packing>
147+
</child>
148+
</object>
149+
<packing>
150+
<property name="expand">False</property>
151+
<property name="fill">True</property>
152+
<property name="position">1</property>
153+
</packing>
154+
</child>
155+
</template>
156+
</interface>

0 commit comments

Comments
 (0)