3
# This file is part of Diamond.
5
# Diamond is free software: you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation, either version 3 of the License, or
8
# (at your option) any later version.
10
# Diamond is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with Diamond. If not, see <http://www.gnu.org/licenses/>.
24
class AttributeWidget(gtk.Frame):
26
__gsignals__ = { "on-store" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ()),
27
"update-name" : (gobject.SIGNAL_RUN_LAST, gobject.TYPE_NONE, ())}
30
gtk.Frame.__init__(self)
32
scrolledWindow = gtk.ScrolledWindow()
33
scrolledWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
35
treeview = self.treeview = gtk.TreeView()
37
model = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING, gobject.TYPE_PYOBJECT)
38
treeview.set_model(model)
39
treeview.connect("motion-notify-event", self.treeview_mouse_over)
41
key_renderer = gtk.CellRendererText()
42
key_renderer.set_property("editable", False)
44
column1 = gtk.TreeViewColumn("Name", key_renderer, text = 0)
45
column1.set_cell_data_func(key_renderer, self.key_data_func)
46
column1.set_property("min-width", 75)
48
entry_renderer = gtk.CellRendererText()
49
entry_renderer.connect("edited", self.entry_edited)
50
entry_renderer.connect("editing-started", self.entry_edit_start)
52
combo_renderer = gtk.CellRendererCombo()
53
combo_renderer.set_property("text-column", 0)
54
combo_renderer.connect("edited", self.combo_selected)
55
combo_renderer.connect("editing-started", self.combo_edit_start)
57
column2 = gtk.TreeViewColumn("Value", entry_renderer, text = 1)
58
column2.pack_start(combo_renderer)
59
column2.set_attributes(combo_renderer, text = 1)
60
column2.set_cell_data_func(entry_renderer, self.entry_data_func)
61
column2.set_cell_data_func(combo_renderer, self.combo_data_func)
62
column2.set_property("expand", True)
63
column2.set_property("min-width", 75)
65
icon_renderer = gtk.CellRendererPixbuf()
67
column3 = gtk.TreeViewColumn("", icon_renderer)
68
column3.set_cell_data_func(icon_renderer, self.icon_data_func)
70
treeview.append_column(column1)
71
treeview.append_column(column2)
72
treeview.append_column(column3)
74
scrolledWindow.add(treeview)
77
label.set_markup("<b>Attributes</b>")
79
self.set_label_widget(label)
80
self.set_shadow_type(gtk.SHADOW_NONE)
81
self.add(scrolledWindow)
83
def update(self, node):
85
self.treeview.get_model().clear()
89
if node is None or not node.attrs.keys():
90
self.set_property("visible", False)
92
self.set_property("visible", True)
94
for key in node.attrs.keys():
95
model = self.treeview.get_model()
96
cell_model = gtk.ListStore(gobject.TYPE_STRING)
99
model.set_value(iter, 0, key)
100
model.set_value(iter, 2, cell_model)
102
if isinstance(node.attrs[key][0], tuple):
103
if node.attrs[key][1] is None:
104
if isinstance(node.attrs[key][0][0], tuple):
105
model.set_value(iter, 1, "Select " + datatype.print_type(node.attrs[key][0][1]) + "...")
107
model.set_value(iter, 1, "Select...")
109
model.set_value(iter, 1, node.attrs[key][1])
111
if isinstance(node.attrs[key][0][0], tuple):
112
opts = node.attrs[key][0][0]
114
opts = node.attrs[key][0]
117
cell_iter = cell_model.append()
118
cell_model.set_value(cell_iter, 0, opt)
120
self.treeview.get_column(2).set_property("visible", True)
121
elif node.attrs[key][0] is None:
122
model.set_value(iter, 1, "No data")
123
elif node.attrs[key][1] is None:
124
model.set_value(iter, 1, datatype.print_type(node.attrs[key][0]))
126
model.set_value(iter, 1, node.attrs[key][1])
128
self.treeview.queue_resize()
132
def treeview_mouse_over(self, widget, event):
134
Called when the mouse moves over the attributes widget. Sets the
135
appropriate attribute widget tooltip.
138
path_info = self.treeview.get_path_at_pos(int(event.x), int(event.y))
139
if path_info is None:
141
self.treeview.set_tooltip_text("")
142
self.treeview.set_property("has-tooltip", False)
149
if col is not self.treeview.get_column(1):
151
self.treeview.set_tooltip_text("")
152
self.treeview.set_property("has-tooltip", False)
157
iter = self.treeview.get_model().get_iter(path)
158
iter_key = self.treeview.get_model().get_value(iter, 0)
162
def key_data_func(self, col, cell_renderer, model, iter):
164
Attribute name data function. Sets the cell renderer text colours.
167
iter_key = model.get_value(iter, 0)
169
if not self.node.active or self.node.attrs[iter_key][0] is None or self.node.attrs[iter_key][0] == "fixed":
170
cell_renderer.set_property("foreground", "grey")
171
elif self.node.attrs[iter_key][1] is None:
172
cell_renderer.set_property("foreground", "blue")
174
cell_renderer.set_property("foreground", "black")
178
def entry_data_func(self, col, cell_renderer, model, iter):
180
Attribute text data function. Hides the renderer if a combo box is required,
181
and sets colours and editability otherwise.
184
iter_key = model.get_value(iter, 0)
186
if not self.node.active or self.node.attrs[iter_key][0] is None or self.node.attrs[iter_key][0] == "fixed":
187
cell_renderer.set_property("editable", False)
188
cell_renderer.set_property("foreground", "grey")
189
cell_renderer.set_property("visible", True)
190
elif not isinstance(self.node.attrs[iter_key][0], tuple):
191
cell_renderer.set_property("editable", True)
192
cell_renderer.set_property("visible", True)
193
if self.node.attrs[iter_key][1] is None:
194
cell_renderer.set_property("foreground", "blue")
196
cell_renderer.set_property("foreground", "black")
198
cell_renderer.set_property("editable", False)
199
cell_renderer.set_property("visible", False)
203
def combo_data_func(self, col, cell_renderer, model, iter):
205
Attribute combo box data function. Hides the renderer if a combo box is not
206
required, and sets the combo box options otherwise. Adds an entry if required.
209
iter_key = model.get_value(iter, 0)
211
if self.node.active and isinstance(self.node.attrs[iter_key][0], tuple):
212
cell_renderer.set_property("editable", True)
213
cell_renderer.set_property("visible", True)
214
if isinstance(self.node.attrs[iter_key][0][0], tuple):
215
cell_renderer.set_property("has-entry", True)
217
cell_renderer.set_property("has-entry", False)
218
if self.node.attrs[iter_key][1] is None:
219
cell_renderer.set_property("foreground", "blue")
221
cell_renderer.set_property("foreground", "black")
223
cell_renderer.set_property("visible", False)
224
cell_renderer.set_property("editable", False)
225
cell_renderer.set_property("model", model.get_value(iter, 2))
229
def icon_data_func(self, col, cell_renderer, model, iter):
231
Attribute icon data function. Used to add downward pointing arrows for combo
232
attributes, for consistency with the LHS.
235
iter_key = model.get_value(iter, 0)
237
if self.node.active and isinstance(self.node.attrs[iter_key][0], tuple):
238
cell_renderer.set_property("stock-id", gtk.STOCK_GO_DOWN)
240
cell_renderer.set_property("stock-id", None)
244
def entry_edit_start(self, cell_renderer, editable, path):
246
Called when editing is started on an attribute text cell. Used to delete the
247
printable_type placeholder.
250
iter = self.treeview.get_model().get_iter(path)
251
iter_key = self.treeview.get_model().get_value(iter, 0)
253
if self.node.attrs[iter_key][1] is None:
254
editable.set_text("")
258
def combo_edit_start(self, cell_renderer, editable, path):
260
Called when editing is started on an attribute combo cell. Used to delete the
261
select placeholder for mixed entry / combo attributes.
264
iter = self.treeview.get_model().get_iter(path)
265
iter_key = self.treeview.get_model().get_value(iter, 0)
267
if isinstance(self.node.attrs[iter_key][0][0], tuple) and self.node.attrs[iter_key][1] is None:
268
editable.child.set_text("")
272
def entry_edited(self, cell_renderer, path, new_text):
274
Called when editing is finished on an attribute text cell. Updates data in the
278
iter = self.treeview.get_model().get_iter(path)
279
iter_key = self.treeview.get_model().get_value(iter, 0)
281
if self.node.get_attr(iter_key) is None and new_text == "":
284
value_check = self.node.validity_check(self.node.attrs[iter_key][0], new_text)
286
if value_check is not None and value_check != self.node.attrs[iter_key][1]:
287
if iter_key == "name" and not self._name_check(value_check):
290
self.treeview.get_model().set_value(iter, 1, value_check)
291
self.node.set_attr(iter_key, value_check)
292
if iter_key == "name":
293
self.emit("update-name")
295
self.emit("on-store")
299
def combo_selected(self, cell_renderer, path, new_text):
301
Called when an attribute combo box element is selected, or combo box entry
302
element entry is edited. Updates data in the treestore.
305
iter = self.treeview.get_model().get_iter(path)
306
iter_key = self.treeview.get_model().get_value(iter, 0)
311
if isinstance(self.node.attrs[iter_key][0][0], tuple) and new_text not in self.node.attrs[iter_key][0][0]:
312
if self.node.get_attr(iter_key) is None and new_text == "":
315
new_text = self.node.validity_check(self.node.attrs[iter_key][0][1], new_text)
316
if iter_key == "name" and not self._name_check(new_text):
318
if new_text != self.node.attrs[iter_key][1]:
319
self.treeview.get_model().set_value(iter, 1, new_text)
320
self.node.set_attr(iter_key, new_text)
321
if iter_key == "name":
322
self.emit("update-name")
324
self.emit("on-store")
328
def _name_check(self, value):
330
Check to see if the supplied data is a valid tree name.
333
valid_chars = "_:[]1234567890qwertyuioplkjhgfdsazxcvbnmMNBVCXZASDFGHJKLPOIUYTREWQ"
335
if char not in valid_chars:
336
dialogs.error(None, "Invalid value entered")
341
gobject.type_register(AttributeWidget)