diff options
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/hobwidget.py')
-rw-r--r-- | bitbake/lib/bb/ui/crumbs/hobwidget.py | 805 |
1 files changed, 805 insertions, 0 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/hobwidget.py b/bitbake/lib/bb/ui/crumbs/hobwidget.py new file mode 100644 index 0000000000..890151ddd4 --- /dev/null +++ b/bitbake/lib/bb/ui/crumbs/hobwidget.py | |||
@@ -0,0 +1,805 @@ | |||
1 | # BitBake Graphical GTK User Interface | ||
2 | # | ||
3 | # Copyright (C) 2011-2012 Intel Corporation | ||
4 | # | ||
5 | # Authored by Dongxiao Xu <dongxiao.xu@intel.com> | ||
6 | # Authored by Shane Wang <shane.wang@intel.com> | ||
7 | # | ||
8 | # This program is free software; you can redistribute it and/or modify | ||
9 | # it under the terms of the GNU General Public License version 2 as | ||
10 | # published by the Free Software Foundation. | ||
11 | # | ||
12 | # This program is distributed in the hope that it will be useful, | ||
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | # GNU General Public License for more details. | ||
16 | # | ||
17 | # You should have received a copy of the GNU General Public License along | ||
18 | # with this program; if not, write to the Free Software Foundation, Inc., | ||
19 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
20 | |||
21 | import gtk | ||
22 | import gobject | ||
23 | import os | ||
24 | import os.path | ||
25 | from bb.ui.crumbs.hobcolor import HobColors | ||
26 | |||
27 | class hwc: | ||
28 | |||
29 | MAIN_WIN_WIDTH = 1024 | ||
30 | MAIN_WIN_HEIGHT = 700 | ||
31 | |||
32 | class hic: | ||
33 | |||
34 | HOB_ICON_BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ("ui/icons/")) | ||
35 | |||
36 | ICON_RCIPE_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('recipe/recipe_display.png')) | ||
37 | ICON_RCIPE_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('recipe/recipe_hover.png')) | ||
38 | ICON_PACKAGES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('packages/packages_display.png')) | ||
39 | ICON_PACKAGES_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('packages/packages_hover.png')) | ||
40 | ICON_LAYERS_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('layers/layers_display.png')) | ||
41 | ICON_LAYERS_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('layers/layers_hover.png')) | ||
42 | ICON_TEMPLATES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('templates/templates_display.png')) | ||
43 | ICON_TEMPLATES_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('templates/templates_hover.png')) | ||
44 | ICON_IMAGES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('images/images_display.png')) | ||
45 | ICON_IMAGES_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('images/images_hover.png')) | ||
46 | ICON_SETTINGS_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('settings/settings_display.png')) | ||
47 | ICON_SETTINGS_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('settings/settings_hover.png')) | ||
48 | ICON_INFO_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('info/info_display.png')) | ||
49 | ICON_INFO_HOVER_FILE = os.path.join(HOB_ICON_BASE_DIR, ('info/info_hover.png')) | ||
50 | ICON_INDI_CONFIRM_FILE = os.path.join(HOB_ICON_BASE_DIR, ('indicators/confirmation.png')) | ||
51 | ICON_INDI_ERROR_FILE = os.path.join(HOB_ICON_BASE_DIR, ('indicators/error.png')) | ||
52 | |||
53 | class HobWidget: | ||
54 | @classmethod | ||
55 | def resize_widget(cls, screen, widget, widget_width, widget_height): | ||
56 | screen_width, screen_height = screen.get_size_request() | ||
57 | ratio_height = screen_width * hwc.MAIN_WIN_HEIGHT/hwc.MAIN_WIN_WIDTH | ||
58 | if ratio_height < screen_height: | ||
59 | screen_height = ratio_height | ||
60 | widget_width = widget_width * screen_width/hwc.MAIN_WIN_WIDTH | ||
61 | widget_height = widget_height * screen_height/hwc.MAIN_WIN_HEIGHT | ||
62 | widget.set_size_request(widget_width, widget_height) | ||
63 | |||
64 | @classmethod | ||
65 | def _toggle_cb(cls, cell, path, model, column): | ||
66 | it = model.get_iter(path) | ||
67 | val = model.get_value(it, column) | ||
68 | val = not val | ||
69 | model.set(it, column, val) | ||
70 | |||
71 | @classmethod | ||
72 | def _pkgfmt_up_clicked_cb(cls, button, tree_selection): | ||
73 | (model, it) = tree_selection.get_selected() | ||
74 | if not it: | ||
75 | return | ||
76 | path = model.get_path(it) | ||
77 | if path[0] <= 0: | ||
78 | return | ||
79 | |||
80 | pre_it = model.get_iter_first() | ||
81 | if not pre_it: | ||
82 | return | ||
83 | else: | ||
84 | while model.iter_next(pre_it) : | ||
85 | if model.get_value(model.iter_next(pre_it), 1) != model.get_value(it, 1): | ||
86 | pre_it = model.iter_next(pre_it) | ||
87 | else: | ||
88 | break | ||
89 | |||
90 | cur_index = model.get_value(it, 0) | ||
91 | pre_index = cur_index | ||
92 | if pre_it: | ||
93 | model.set(pre_it, 0, pre_index) | ||
94 | cur_index = cur_index - 1 | ||
95 | model.set(it, 0, cur_index) | ||
96 | |||
97 | @classmethod | ||
98 | def _pkgfmt_down_clicked_cb(cls, button, tree_selection): | ||
99 | (model, it) = tree_selection.get_selected() | ||
100 | if not it: | ||
101 | return | ||
102 | next_it = model.iter_next(it) | ||
103 | if not next_it: | ||
104 | return | ||
105 | cur_index = model.get_value(it, 0) | ||
106 | next_index = cur_index | ||
107 | model.set(next_it, 0, next_index) | ||
108 | cur_index = cur_index + 1 | ||
109 | model.set(it, 0, cur_index) | ||
110 | |||
111 | @classmethod | ||
112 | def _tree_selection_changed_cb(cls, tree_selection, button1, button2): | ||
113 | (model, it) = tree_selection.get_selected() | ||
114 | inc = model.get_value(it, 2) | ||
115 | if inc: | ||
116 | button1.set_sensitive(True) | ||
117 | button2.set_sensitive(True) | ||
118 | else: | ||
119 | button1.set_sensitive(False) | ||
120 | button2.set_sensitive(False) | ||
121 | |||
122 | @classmethod | ||
123 | def _sort_func(cls, model, iter1, iter2, data): | ||
124 | val1 = model.get_value(iter1, 0) | ||
125 | val2 = model.get_value(iter2, 0) | ||
126 | inc1 = model.get_value(iter1, 2) | ||
127 | inc2 = model.get_value(iter2, 2) | ||
128 | if inc1 != inc2: | ||
129 | return inc2 - inc1 | ||
130 | else: | ||
131 | return val1 - val2 | ||
132 | |||
133 | @classmethod | ||
134 | def gen_pkgfmt_widget(cls, curr_package_format, all_package_format, tooltip=""): | ||
135 | pkgfmt_hbox = gtk.HBox(False, 15) | ||
136 | |||
137 | pkgfmt_store = gtk.ListStore(int, str, gobject.TYPE_BOOLEAN) | ||
138 | for format in curr_package_format.split(): | ||
139 | pkgfmt_store.set(pkgfmt_store.append(), 1, format, 2, True) | ||
140 | for format in all_package_format: | ||
141 | if format not in curr_package_format: | ||
142 | pkgfmt_store.set(pkgfmt_store.append(), 1, format, 2, False) | ||
143 | pkgfmt_tree = gtk.TreeView(pkgfmt_store) | ||
144 | pkgfmt_tree.set_headers_clickable(True) | ||
145 | pkgfmt_tree.set_headers_visible(False) | ||
146 | tree_selection = pkgfmt_tree.get_selection() | ||
147 | tree_selection.set_mode(gtk.SELECTION_SINGLE) | ||
148 | |||
149 | col = gtk.TreeViewColumn('NO') | ||
150 | col.set_sort_column_id(0) | ||
151 | col.set_sort_order(gtk.SORT_ASCENDING) | ||
152 | col.set_clickable(False) | ||
153 | col1 = gtk.TreeViewColumn('TYPE') | ||
154 | col1.set_min_width(130) | ||
155 | col1.set_max_width(140) | ||
156 | col2 = gtk.TreeViewColumn('INCLUDED') | ||
157 | col2.set_min_width(60) | ||
158 | col2.set_max_width(70) | ||
159 | pkgfmt_tree.append_column(col1) | ||
160 | pkgfmt_tree.append_column(col2) | ||
161 | cell = gtk.CellRendererText() | ||
162 | cell1 = gtk.CellRendererText() | ||
163 | cell1.set_property('width-chars', 10) | ||
164 | cell2 = gtk.CellRendererToggle() | ||
165 | cell2.set_property('activatable', True) | ||
166 | cell2.connect("toggled", cls._toggle_cb, pkgfmt_store, 2) | ||
167 | col.pack_start(cell, True) | ||
168 | col1.pack_start(cell1, True) | ||
169 | col2.pack_end(cell2, True) | ||
170 | col.set_attributes(cell, text=0) | ||
171 | col1.set_attributes(cell1, text=1) | ||
172 | col2.set_attributes(cell2, active=2) | ||
173 | |||
174 | pkgfmt_store.set_sort_func(0, cls._sort_func, None) | ||
175 | pkgfmt_store.set_sort_column_id(0, gtk.SORT_ASCENDING) | ||
176 | |||
177 | scroll = gtk.ScrolledWindow() | ||
178 | scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) | ||
179 | scroll.set_shadow_type(gtk.SHADOW_IN) | ||
180 | scroll.add(pkgfmt_tree) | ||
181 | scroll.set_size_request(200,60) | ||
182 | pkgfmt_hbox.pack_start(scroll, False, False, 0) | ||
183 | |||
184 | vbox = gtk.VBox(False, 5) | ||
185 | pkgfmt_hbox.pack_start(vbox, False, False, 15) | ||
186 | |||
187 | up = gtk.Button() | ||
188 | image = gtk.Image() | ||
189 | image.set_from_stock(gtk.STOCK_GO_UP, gtk.ICON_SIZE_MENU) | ||
190 | up.set_image(image) | ||
191 | up.set_size_request(50,30) | ||
192 | up.connect("clicked", cls._pkgfmt_up_clicked_cb, tree_selection) | ||
193 | vbox.pack_start(up, False, False, 5) | ||
194 | |||
195 | down = gtk.Button() | ||
196 | image = gtk.Image() | ||
197 | image.set_from_stock(gtk.STOCK_GO_DOWN, gtk.ICON_SIZE_MENU) | ||
198 | down.set_image(image) | ||
199 | down.set_size_request(50,30) | ||
200 | down.connect("clicked", cls._pkgfmt_down_clicked_cb, tree_selection) | ||
201 | vbox.pack_start(down, False, False, 5) | ||
202 | tree_selection.connect("changed", cls._tree_selection_changed_cb, up, down) | ||
203 | |||
204 | image = gtk.Image() | ||
205 | image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON) | ||
206 | image.set_tooltip_text(tooltip) | ||
207 | pkgfmt_hbox.pack_start(image, expand=False, fill=False) | ||
208 | |||
209 | pkgfmt_hbox.show_all() | ||
210 | |||
211 | return pkgfmt_hbox, pkgfmt_store | ||
212 | |||
213 | @classmethod | ||
214 | def gen_combo_widget(cls, curr_item, all_item, tooltip=""): | ||
215 | hbox = gtk.HBox(False, 10) | ||
216 | combo = gtk.combo_box_new_text() | ||
217 | hbox.pack_start(combo, expand=False, fill=False) | ||
218 | |||
219 | index = 0 | ||
220 | for item in all_item or []: | ||
221 | combo.append_text(item) | ||
222 | if item == curr_item: | ||
223 | combo.set_active(index) | ||
224 | index += 1 | ||
225 | |||
226 | image = gtk.Image() | ||
227 | image.show() | ||
228 | image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON) | ||
229 | image.set_tooltip_text(tooltip) | ||
230 | |||
231 | hbox.pack_start(image, expand=False, fill=False) | ||
232 | |||
233 | hbox.show_all() | ||
234 | |||
235 | return hbox, combo | ||
236 | |||
237 | @classmethod | ||
238 | def gen_label_widget(cls, content): | ||
239 | label = gtk.Label() | ||
240 | label.set_alignment(0, 0) | ||
241 | label.set_markup(content) | ||
242 | label.show() | ||
243 | return label | ||
244 | |||
245 | @classmethod | ||
246 | def _select_path_cb(cls, action, parent, entry): | ||
247 | dialog = gtk.FileChooserDialog("", parent, | ||
248 | gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, | ||
249 | (gtk.STOCK_OK, gtk.RESPONSE_YES, | ||
250 | gtk.STOCK_CANCEL, gtk.RESPONSE_NO)) | ||
251 | response = dialog.run() | ||
252 | if response == gtk.RESPONSE_YES: | ||
253 | path = dialog.get_filename() | ||
254 | entry.set_text(path) | ||
255 | |||
256 | dialog.destroy() | ||
257 | |||
258 | @classmethod | ||
259 | def gen_entry_widget(cls, split_model, content, parent, tooltip=""): | ||
260 | hbox = gtk.HBox(False, 10) | ||
261 | entry = gtk.Entry() | ||
262 | entry.set_text(content) | ||
263 | |||
264 | if split_model: | ||
265 | hbox.pack_start(entry, expand=True, fill=True) | ||
266 | else: | ||
267 | table = gtk.Table(1, 10, True) | ||
268 | hbox.pack_start(table, expand=True, fill=True) | ||
269 | table.attach(entry, 0, 9, 0, 1) | ||
270 | image = gtk.Image() | ||
271 | image.set_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON) | ||
272 | open_button = gtk.Button() | ||
273 | open_button.set_image(image) | ||
274 | open_button.connect("clicked", cls._select_path_cb, parent, entry) | ||
275 | table.attach(open_button, 9, 10, 0, 1) | ||
276 | |||
277 | image = gtk.Image() | ||
278 | image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON) | ||
279 | image.set_tooltip_text(tooltip) | ||
280 | hbox.pack_start(image, expand=False, fill=False) | ||
281 | |||
282 | hbox.show_all() | ||
283 | |||
284 | return hbox, entry | ||
285 | |||
286 | @classmethod | ||
287 | def gen_spinner_widget(cls, content, lower, upper, tooltip=""): | ||
288 | hbox = gtk.HBox(False, 10) | ||
289 | adjust = gtk.Adjustment(value=content, lower=lower, upper=upper, step_incr=1) | ||
290 | spinner = gtk.SpinButton(adjustment=adjust, climb_rate=1, digits=0) | ||
291 | |||
292 | spinner.set_value(content) | ||
293 | hbox.pack_start(spinner, expand=False, fill=False) | ||
294 | |||
295 | image = gtk.Image() | ||
296 | image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON) | ||
297 | image.set_tooltip_text(tooltip) | ||
298 | hbox.pack_start(image, expand=False, fill=False) | ||
299 | |||
300 | hbox.show_all() | ||
301 | |||
302 | return hbox, spinner | ||
303 | |||
304 | @classmethod | ||
305 | def conf_error(cls, parent, lbl): | ||
306 | dialog = CrumbsDialog(parent, lbl) | ||
307 | dialog.add_button(gtk.STOCK_OK, gtk.RESPONSE_OK) | ||
308 | response = dialog.run() | ||
309 | dialog.destroy() | ||
310 | |||
311 | @classmethod | ||
312 | def _add_layer_cb(cls, action, layer_store, parent): | ||
313 | dialog = gtk.FileChooserDialog("Add new layer", parent, | ||
314 | gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, | ||
315 | (gtk.STOCK_OK, gtk.RESPONSE_YES, | ||
316 | gtk.STOCK_CANCEL, gtk.RESPONSE_NO)) | ||
317 | label = gtk.Label("Select the layer you wish to add") | ||
318 | label.show() | ||
319 | dialog.set_extra_widget(label) | ||
320 | response = dialog.run() | ||
321 | path = dialog.get_filename() | ||
322 | dialog.destroy() | ||
323 | |||
324 | lbl = "<b>Error</b>\nUnable to load layer <i>%s</i> because " % path | ||
325 | if response == gtk.RESPONSE_YES: | ||
326 | import os | ||
327 | import os.path | ||
328 | layers = [] | ||
329 | it = layer_store.get_iter_first() | ||
330 | while it: | ||
331 | layers.append(layer_store.get_value(it, 0)) | ||
332 | it = layer_store.iter_next(it) | ||
333 | |||
334 | if not path: | ||
335 | lbl += "it is an invalid path." | ||
336 | elif not os.path.exists(path+"/conf/layer.conf"): | ||
337 | lbl += "there is no layer.conf inside the directory." | ||
338 | elif path in layers: | ||
339 | lbl += "it is already in loaded layers." | ||
340 | else: | ||
341 | layer_store.append([path]) | ||
342 | return | ||
343 | cls.conf_error(parent, lbl) | ||
344 | |||
345 | @classmethod | ||
346 | def _del_layer_cb(cls, action, tree_selection, layer_store): | ||
347 | model, iter = tree_selection.get_selected() | ||
348 | if iter: | ||
349 | layer_store.remove(iter) | ||
350 | |||
351 | @classmethod | ||
352 | def _toggle_layer_cb(cls, cell, path, layer_store): | ||
353 | name = layer_store[path][0] | ||
354 | toggle = not layer_store[path][1] | ||
355 | layer_store[path][1] = toggle | ||
356 | |||
357 | @classmethod | ||
358 | def gen_layer_widget(cls, split_model, layers, layers_avail, window, tooltip=""): | ||
359 | hbox = gtk.HBox(False, 10) | ||
360 | |||
361 | layer_tv = gtk.TreeView() | ||
362 | layer_tv.set_rules_hint(True) | ||
363 | layer_tv.set_headers_visible(False) | ||
364 | tree_selection = layer_tv.get_selection() | ||
365 | tree_selection.set_mode(gtk.SELECTION_SINGLE) | ||
366 | |||
367 | col0= gtk.TreeViewColumn('Path') | ||
368 | cell0 = gtk.CellRendererText() | ||
369 | cell0.set_padding(5,2) | ||
370 | col0.pack_start(cell0, True) | ||
371 | col0.set_attributes(cell0, text=0) | ||
372 | layer_tv.append_column(col0) | ||
373 | |||
374 | scroll = gtk.ScrolledWindow() | ||
375 | scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) | ||
376 | scroll.set_shadow_type(gtk.SHADOW_IN) | ||
377 | scroll.add(layer_tv) | ||
378 | |||
379 | table_layer = gtk.Table(2, 10, False) | ||
380 | hbox.pack_start(table_layer, expand=True, fill=True) | ||
381 | |||
382 | if split_model: | ||
383 | table_layer.attach(scroll, 0, 10, 0, 2) | ||
384 | |||
385 | layer_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) | ||
386 | for layer in layers: | ||
387 | layer_store.set(layer_store.append(), 0, layer, 1, True) | ||
388 | for layer in layers_avail: | ||
389 | if layer not in layers: | ||
390 | layer_store.set(layer_store.append(), 0, layer, 1, False) | ||
391 | |||
392 | col1 = gtk.TreeViewColumn('Included') | ||
393 | layer_tv.append_column(col1) | ||
394 | |||
395 | cell1 = gtk.CellRendererToggle() | ||
396 | cell1.connect("toggled", cls._toggle_layer_cb, layer_store) | ||
397 | col1.pack_start(cell1, True) | ||
398 | col1.set_attributes(cell1, active=1) | ||
399 | |||
400 | else: | ||
401 | table_layer.attach(scroll, 0, 10, 0, 1) | ||
402 | |||
403 | layer_store = gtk.ListStore(gobject.TYPE_STRING) | ||
404 | for layer in layers: | ||
405 | layer_store.set(layer_store.append(), 0, layer) | ||
406 | |||
407 | image = gtk.Image() | ||
408 | image.set_from_stock(gtk.STOCK_ADD,gtk.ICON_SIZE_MENU) | ||
409 | add_button = gtk.Button() | ||
410 | add_button.set_image(image) | ||
411 | add_button.connect("clicked", cls._add_layer_cb, layer_store, window) | ||
412 | table_layer.attach(add_button, 0, 5, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 0) | ||
413 | image = gtk.Image() | ||
414 | image.set_from_stock(gtk.STOCK_REMOVE,gtk.ICON_SIZE_MENU) | ||
415 | del_button = gtk.Button() | ||
416 | del_button.set_image(image) | ||
417 | del_button.connect("clicked", cls._del_layer_cb, tree_selection, layer_store) | ||
418 | table_layer.attach(del_button, 5, 10, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 0) | ||
419 | layer_tv.set_model(layer_store) | ||
420 | |||
421 | hbox.show_all() | ||
422 | |||
423 | return hbox, layer_store | ||
424 | |||
425 | @classmethod | ||
426 | def _toggle_single_cb(cls, cell, select_path, treeview, toggle_column): | ||
427 | model = treeview.get_model() | ||
428 | if not model: | ||
429 | return | ||
430 | iter = model.get_iter_first() | ||
431 | while iter: | ||
432 | path = model.get_path(iter) | ||
433 | model[path][toggle_column] = False | ||
434 | iter = model.iter_next(iter) | ||
435 | |||
436 | model[select_path][toggle_column] = True | ||
437 | |||
438 | @classmethod | ||
439 | def gen_imgtv_widget(cls, col0_width, col1_width): | ||
440 | vbox = gtk.VBox(False, 10) | ||
441 | |||
442 | imgsel_tv = gtk.TreeView() | ||
443 | imgsel_tv.set_rules_hint(True) | ||
444 | imgsel_tv.set_headers_visible(False) | ||
445 | tree_selection = imgsel_tv.get_selection() | ||
446 | tree_selection.set_mode(gtk.SELECTION_SINGLE) | ||
447 | |||
448 | col0= gtk.TreeViewColumn('Image name') | ||
449 | cell0 = gtk.CellRendererText() | ||
450 | cell0.set_padding(5,2) | ||
451 | col0.pack_start(cell0, True) | ||
452 | col0.set_attributes(cell0, text=0) | ||
453 | col0.set_max_width(col0_width) | ||
454 | col0.set_min_width(col0_width) | ||
455 | imgsel_tv.append_column(col0) | ||
456 | |||
457 | col1= gtk.TreeViewColumn('Select') | ||
458 | cell1 = gtk.CellRendererToggle() | ||
459 | cell1.set_padding(5,2) | ||
460 | cell1.connect("toggled", cls._toggle_single_cb, imgsel_tv, 1) | ||
461 | col1.pack_start(cell1, True) | ||
462 | col1.set_attributes(cell1, active=1) | ||
463 | col1.set_max_width(col1_width) | ||
464 | col1.set_min_width(col1_width) | ||
465 | imgsel_tv.append_column(col1) | ||
466 | |||
467 | scroll = gtk.ScrolledWindow() | ||
468 | scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) | ||
469 | scroll.set_shadow_type(gtk.SHADOW_IN) | ||
470 | scroll.add(imgsel_tv) | ||
471 | |||
472 | vbox.pack_start(scroll, expand=True, fill=True) | ||
473 | |||
474 | return vbox, imgsel_tv | ||
475 | |||
476 | @classmethod | ||
477 | def gen_images_widget(cls, col0_width, col1_width, col2_width): | ||
478 | vbox = gtk.VBox(False, 10) | ||
479 | |||
480 | imgsel_tv = gtk.TreeView() | ||
481 | imgsel_tv.set_rules_hint(True) | ||
482 | imgsel_tv.set_headers_visible(False) | ||
483 | tree_selection = imgsel_tv.get_selection() | ||
484 | tree_selection.set_mode(gtk.SELECTION_SINGLE) | ||
485 | |||
486 | col0= gtk.TreeViewColumn('Image name') | ||
487 | cell0 = gtk.CellRendererText() | ||
488 | cell0.set_padding(5,2) | ||
489 | col0.pack_start(cell0, True) | ||
490 | col0.set_attributes(cell0, text=0) | ||
491 | col0.set_max_width(col0_width) | ||
492 | col0.set_min_width(col0_width) | ||
493 | imgsel_tv.append_column(col0) | ||
494 | |||
495 | col1= gtk.TreeViewColumn('Image size') | ||
496 | cell1 = gtk.CellRendererText() | ||
497 | cell1.set_padding(5,2) | ||
498 | col1.pack_start(cell1, True) | ||
499 | col1.set_attributes(cell1, text=1) | ||
500 | col1.set_max_width(col1_width) | ||
501 | col1.set_min_width(col1_width) | ||
502 | imgsel_tv.append_column(col1) | ||
503 | |||
504 | col2= gtk.TreeViewColumn('Select') | ||
505 | cell2 = gtk.CellRendererToggle() | ||
506 | cell2.set_padding(5,2) | ||
507 | cell2.connect("toggled", cls._toggle_single_cb, imgsel_tv, 2) | ||
508 | col2.pack_start(cell2, True) | ||
509 | col2.set_attributes(cell2, active=2) | ||
510 | col2.set_max_width(col2_width) | ||
511 | col2.set_min_width(col2_width) | ||
512 | imgsel_tv.append_column(col2) | ||
513 | |||
514 | scroll = gtk.ScrolledWindow() | ||
515 | scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) | ||
516 | scroll.set_shadow_type(gtk.SHADOW_IN) | ||
517 | scroll.add(imgsel_tv) | ||
518 | |||
519 | vbox.pack_start(scroll, expand=True, fill=True) | ||
520 | |||
521 | return vbox, imgsel_tv | ||
522 | |||
523 | @classmethod | ||
524 | def _on_add_item_clicked(cls, button, model): | ||
525 | new_item = ["##KEY##", "##VALUE##"] | ||
526 | |||
527 | iter = model.append() | ||
528 | model.set (iter, | ||
529 | 0, new_item[0], | ||
530 | 1, new_item[1], | ||
531 | ) | ||
532 | |||
533 | |||
534 | @classmethod | ||
535 | def _on_remove_item_clicked(cls, button, treeview): | ||
536 | |||
537 | selection = treeview.get_selection() | ||
538 | model, iter = selection.get_selected() | ||
539 | |||
540 | if iter: | ||
541 | path = model.get_path(iter)[0] | ||
542 | model.remove(iter) | ||
543 | |||
544 | @classmethod | ||
545 | def _on_cell_edited(cls, cell, path_string, new_text, model): | ||
546 | it = model.get_iter_from_string(path_string) | ||
547 | column = cell.get_data("column") | ||
548 | model.set(it, column, new_text) | ||
549 | |||
550 | |||
551 | @classmethod | ||
552 | def gen_editable_settings(cls, setting, tooltip=""): | ||
553 | setting_hbox = gtk.HBox(False, 10) | ||
554 | |||
555 | vbox = gtk.VBox(False, 10) | ||
556 | setting_hbox.pack_start(vbox, expand=True, fill=True) | ||
557 | |||
558 | setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) | ||
559 | for key in setting.keys(): | ||
560 | setting_store.set(setting_store.append(), 0, key, 1, setting[key]) | ||
561 | |||
562 | setting_tree = gtk.TreeView(setting_store) | ||
563 | setting_tree.set_headers_visible(True) | ||
564 | setting_tree.set_size_request(300, 100) | ||
565 | |||
566 | col = gtk.TreeViewColumn('Key') | ||
567 | col.set_min_width(100) | ||
568 | col.set_max_width(150) | ||
569 | col.set_resizable(True) | ||
570 | col1 = gtk.TreeViewColumn('Value') | ||
571 | col1.set_min_width(100) | ||
572 | col1.set_max_width(150) | ||
573 | col1.set_resizable(True) | ||
574 | setting_tree.append_column(col) | ||
575 | setting_tree.append_column(col1) | ||
576 | cell = gtk.CellRendererText() | ||
577 | cell.set_property('width-chars', 10) | ||
578 | cell.set_property('editable', True) | ||
579 | cell.set_data("column", 0) | ||
580 | cell.connect("edited", cls._on_cell_edited, setting_store) | ||
581 | cell1 = gtk.CellRendererText() | ||
582 | cell1.set_property('width-chars', 10) | ||
583 | cell1.set_property('editable', True) | ||
584 | cell1.set_data("column", 1) | ||
585 | cell1.connect("edited", cls._on_cell_edited, setting_store) | ||
586 | col.pack_start(cell, True) | ||
587 | col1.pack_end(cell1, True) | ||
588 | col.set_attributes(cell, text=0) | ||
589 | col1.set_attributes(cell1, text=1) | ||
590 | |||
591 | scroll = gtk.ScrolledWindow() | ||
592 | scroll.set_shadow_type(gtk.SHADOW_IN) | ||
593 | scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) | ||
594 | scroll.add(setting_tree) | ||
595 | vbox.pack_start(scroll, expand=True, fill=True) | ||
596 | |||
597 | # some buttons | ||
598 | hbox = gtk.HBox(True, 4) | ||
599 | vbox.pack_start(hbox, False, False) | ||
600 | |||
601 | button = gtk.Button(stock=gtk.STOCK_ADD) | ||
602 | button.connect("clicked", cls._on_add_item_clicked, setting_store) | ||
603 | hbox.pack_start(button) | ||
604 | |||
605 | button = gtk.Button(stock=gtk.STOCK_REMOVE) | ||
606 | button.connect("clicked", cls._on_remove_item_clicked, setting_tree) | ||
607 | hbox.pack_start(button) | ||
608 | |||
609 | image = gtk.Image() | ||
610 | image.set_from_stock(gtk.STOCK_INFO, gtk.ICON_SIZE_BUTTON) | ||
611 | image.set_tooltip_text(tooltip) | ||
612 | setting_hbox.pack_start(image, expand=False, fill=False) | ||
613 | |||
614 | return setting_hbox, setting_store | ||
615 | |||
616 | class HobViewTable (gtk.VBox): | ||
617 | """ | ||
618 | A VBox to contain the table for different recipe views and package view | ||
619 | """ | ||
620 | def __init__(self, columns, reset_clicked_cb=None, toggled_cb=None): | ||
621 | gtk.VBox.__init__(self, False, 6) | ||
622 | self.table_tree = gtk.TreeView() | ||
623 | self.table_tree.set_headers_visible(True) | ||
624 | self.table_tree.set_headers_clickable(True) | ||
625 | self.table_tree.set_enable_search(True) | ||
626 | self.table_tree.set_search_column(0) | ||
627 | self.table_tree.get_selection().set_mode(gtk.SELECTION_SINGLE) | ||
628 | |||
629 | for i in range(len(columns)): | ||
630 | col = gtk.TreeViewColumn(columns[i]['col_name']) | ||
631 | col.set_clickable(True) | ||
632 | col.set_resizable(True) | ||
633 | col.set_sort_column_id(columns[i]['col_id']) | ||
634 | col.set_min_width(columns[i]['col_min']) | ||
635 | col.set_max_width(columns[i]['col_max']) | ||
636 | self.table_tree.append_column(col) | ||
637 | |||
638 | if columns[i]['col_style'] == 'toggle': | ||
639 | cell = gtk.CellRendererToggle() | ||
640 | cell.set_property('activatable', True) | ||
641 | cell.connect("toggled", toggled_cb, self.table_tree) | ||
642 | col.pack_end(cell, True) | ||
643 | col.set_attributes(cell, active=columns[i]['col_id']) | ||
644 | elif columns[i]['col_style'] == 'text': | ||
645 | cell = gtk.CellRendererText() | ||
646 | col.pack_start(cell, True) | ||
647 | col.set_attributes(cell, text=columns[i]['col_id']) | ||
648 | |||
649 | scroll = gtk.ScrolledWindow() | ||
650 | scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_ALWAYS) | ||
651 | scroll.set_shadow_type(gtk.SHADOW_IN) | ||
652 | scroll.add(self.table_tree) | ||
653 | self.pack_start(scroll, True, True, 0) | ||
654 | |||
655 | hbox = gtk.HBox(False, 5) | ||
656 | button = gtk.Button("Reset") | ||
657 | button.connect('clicked', reset_clicked_cb) | ||
658 | hbox.pack_end(button, False, False, 0) | ||
659 | |||
660 | self.pack_start(hbox, False, False, 0) | ||
661 | |||
662 | class HobViewBar (gtk.EventBox): | ||
663 | """ | ||
664 | A EventBox with the specified gray background color is associated with a notebook. | ||
665 | And the toolbar to simulate the tabs. | ||
666 | """ | ||
667 | |||
668 | def __init__(self, notebook): | ||
669 | if not notebook: | ||
670 | return | ||
671 | self.notebook = notebook | ||
672 | |||
673 | # setup an event box | ||
674 | gtk.EventBox.__init__(self) | ||
675 | self.set_border_width(2) | ||
676 | style = self.get_style().copy() | ||
677 | style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color (HobColors.GRAY, False, False) | ||
678 | self.set_style(style) | ||
679 | |||
680 | hbox = gtk.HBox() | ||
681 | self.add(hbox) | ||
682 | |||
683 | # setup a tool bar in the event box | ||
684 | self.toolbar = gtk.Toolbar() | ||
685 | self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL) | ||
686 | self.toolbar.set_style(gtk.TOOLBAR_TEXT) | ||
687 | self.toolbar.set_border_width(5) | ||
688 | |||
689 | self.toolbuttons = [] | ||
690 | for index in range(self.notebook.get_n_pages()): | ||
691 | child = self.notebook.get_nth_page(index) | ||
692 | label = self.notebook.get_tab_label_text(child) | ||
693 | tip_text = 'switch to ' + label + ' page' | ||
694 | toolbutton = self.toolbar.append_element(gtk.TOOLBAR_CHILD_RADIOBUTTON, None, | ||
695 | label, tip_text, "Private text", None, | ||
696 | self.toolbutton_cb, index) | ||
697 | toolbutton.set_size_request(200, 100) | ||
698 | self.toolbuttons.append(toolbutton) | ||
699 | |||
700 | # set the default current page | ||
701 | self.modify_toolbuttons_bg(0) | ||
702 | self.notebook.set_current_page(0) | ||
703 | |||
704 | self.toolbar.append_space() | ||
705 | |||
706 | # add the tool bar into the event box | ||
707 | hbox.pack_start(self.toolbar, expand=False, fill=False) | ||
708 | |||
709 | self.search = gtk.Entry() | ||
710 | self.align = gtk.Alignment(xalign=0.5, yalign=0.5) | ||
711 | self.align.add(self.search) | ||
712 | hbox.pack_end(self.align, expand=False, fill=False) | ||
713 | |||
714 | self.label = gtk.Label(" Search: ") | ||
715 | self.label.set_alignment(0.5, 0.5) | ||
716 | hbox.pack_end(self.label, expand=False, fill=False) | ||
717 | |||
718 | def toolbutton_cb(self, widget, index): | ||
719 | if index >= self.notebook.get_n_pages(): | ||
720 | return | ||
721 | self.notebook.set_current_page(index) | ||
722 | self.modify_toolbuttons_bg(index) | ||
723 | |||
724 | def modify_toolbuttons_bg(self, index): | ||
725 | if index >= len(self.toolbuttons): | ||
726 | return | ||
727 | for i in range(0, len(self.toolbuttons)): | ||
728 | toolbutton = self.toolbuttons[i] | ||
729 | if i == index: | ||
730 | self.modify_toolbutton_bg(toolbutton, True) | ||
731 | else: | ||
732 | self.modify_toolbutton_bg(toolbutton) | ||
733 | |||
734 | def modify_toolbutton_bg(self, toolbutton, active=False): | ||
735 | if active: | ||
736 | toolbutton.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.WHITE)) | ||
737 | toolbutton.modify_bg(gtk.STATE_ACTIVE, gtk.gdk.Color(HobColors.WHITE)) | ||
738 | toolbutton.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.WHITE)) | ||
739 | toolbutton.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.WHITE)) | ||
740 | else: | ||
741 | toolbutton.modify_bg(gtk.STATE_NORMAL, gtk.gdk.Color(HobColors.GRAY)) | ||
742 | toolbutton.modify_bg(gtk.STATE_ACTIVE, gtk.gdk.Color(HobColors.GRAY)) | ||
743 | toolbutton.modify_bg(gtk.STATE_SELECTED, gtk.gdk.Color(HobColors.GRAY)) | ||
744 | toolbutton.modify_bg(gtk.STATE_PRELIGHT, gtk.gdk.Color(HobColors.GRAY)) | ||
745 | |||
746 | class HobXpmLabelButtonBox(gtk.EventBox): | ||
747 | """ label: name of buttonbox | ||
748 | description: the simple description | ||
749 | """ | ||
750 | |||
751 | def __init__(self, display_file="", hover_file="", label="", description=""): | ||
752 | gtk.EventBox.__init__(self) | ||
753 | self._base_state_flags = gtk.STATE_NORMAL | ||
754 | self.set_events(gtk.gdk.MOTION_NOTIFY | gtk.gdk.BUTTON_PRESS | gtk.gdk.EXPOSE) | ||
755 | |||
756 | self.connect("expose-event", self.cb) | ||
757 | self.connect("enter-notify-event", self.pointer_enter_cb) | ||
758 | self.connect("leave-notify-event", self.pointer_leave_cb) | ||
759 | |||
760 | self.icon_hover = gtk.Image() | ||
761 | self.icon_hover.set_name("icon_image") | ||
762 | if type(hover_file) == str: | ||
763 | pixbuf = gtk.gdk.pixbuf_new_from_file(hover_file) | ||
764 | self.icon_hover.set_from_pixbuf(pixbuf) | ||
765 | |||
766 | self.icon_display = gtk.Image() | ||
767 | self.icon_display.set_name("icon_image") | ||
768 | if type(display_file) == str: | ||
769 | pixbuf = gtk.gdk.pixbuf_new_from_file(display_file) | ||
770 | self.icon_display.set_from_pixbuf(pixbuf) | ||
771 | |||
772 | self.tb = gtk.Table(2, 10, True) | ||
773 | self.tb.set_row_spacing(1, False) | ||
774 | self.tb.set_col_spacing(1, False) | ||
775 | self.add(self.tb) | ||
776 | self.tb.attach(self.icon_display, 0, 2, 0, 2, 0, 0) | ||
777 | self.tb.attach(self.icon_hover, 0, 2, 0, 2, 0, 0) | ||
778 | |||
779 | lbl = gtk.Label() | ||
780 | lbl.set_alignment(0.0, 0.5) | ||
781 | lbl.set_markup("<span foreground=\'#1C1C1C\' font_desc=\'18px\'>%s</span>" % label) | ||
782 | self.tb.attach(lbl, 2, 10, 0, 1) | ||
783 | |||
784 | lbl = gtk.Label() | ||
785 | lbl.set_alignment(0.0, 0.5) | ||
786 | lbl.set_markup("<span foreground=\'#1C1C1C\' font_desc=\'14px\'>%s</span>" % description) | ||
787 | self.tb.attach(lbl, 2, 10, 1, 2) | ||
788 | |||
789 | def pointer_enter_cb(self, *args): | ||
790 | #if not self.is_focus(): | ||
791 | self.set_state(gtk.STATE_PRELIGHT) | ||
792 | self._base_state_flags = gtk.STATE_PRELIGHT | ||
793 | self.icon_hover.show() | ||
794 | self.icon_display.hide() | ||
795 | |||
796 | def pointer_leave_cb(self, *args): | ||
797 | self.set_state(gtk.STATE_NORMAL) | ||
798 | self._base_state_flags = gtk.STATE_NORMAL | ||
799 | self.icon_display.show() | ||
800 | self.icon_hover.hide() | ||
801 | |||
802 | def cb(self, w,e): | ||
803 | """ Hide items - first time """ | ||
804 | pass | ||
805 | |||