summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/hig.py
diff options
context:
space:
mode:
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/hig.py')
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig.py1978
1 files changed, 0 insertions, 1978 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/hig.py b/bitbake/lib/bb/ui/crumbs/hig.py
deleted file mode 100644
index e56cf2a759..0000000000
--- a/bitbake/lib/bb/ui/crumbs/hig.py
+++ /dev/null
@@ -1,1978 +0,0 @@
1#
2# BitBake Graphical GTK User Interface
3#
4# Copyright (C) 2011-2012 Intel Corporation
5#
6# Authored by Joshua Lock <josh@linux.intel.com>
7# Authored by Dongxiao Xu <dongxiao.xu@intel.com>
8# Authored by Shane Wang <shane.wang@intel.com>
9#
10# This program is free software; you can redistribute it and/or modify
11# it under the terms of the GNU General Public License version 2 as
12# published by the Free Software Foundation.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License along
20# with this program; if not, write to the Free Software Foundation, Inc.,
21# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23import glob
24import glib
25import gtk
26import gobject
27import hashlib
28import os
29import re
30import shlex
31import subprocess
32import tempfile
33from bb.ui.crumbs.hobcolor import HobColors
34from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobInfoButton, HobButton, HobAltButton, HobIconChecker
35from bb.ui.crumbs.progressbar import HobProgressBar
36import bb.ui.crumbs.utils
37import bb.process
38
39"""
40The following are convenience classes for implementing GNOME HIG compliant
41BitBake GUI's
42In summary: spacing = 12px, border-width = 6px
43"""
44
45
46class SettingsUIHelper():
47
48 def gen_label_widget(self, content):
49 label = gtk.Label()
50 label.set_alignment(0, 0)
51 label.set_markup(content)
52 label.show()
53 return label
54
55 def gen_label_info_widget(self, content, tooltip):
56 table = gtk.Table(1, 10, False)
57 label = self.gen_label_widget(content)
58 info = HobInfoButton(tooltip, self)
59 table.attach(label, 0, 1, 0, 1, xoptions=gtk.FILL)
60 table.attach(info, 1, 2, 0, 1, xoptions=gtk.FILL, xpadding=10)
61 return table
62
63 def gen_spinner_widget(self, content, lower, upper, tooltip=""):
64 hbox = gtk.HBox(False, 12)
65 adjust = gtk.Adjustment(value=content, lower=lower, upper=upper, step_incr=1)
66 spinner = gtk.SpinButton(adjustment=adjust, climb_rate=1, digits=0)
67
68 spinner.set_value(content)
69 hbox.pack_start(spinner, expand=False, fill=False)
70
71 info = HobInfoButton(tooltip, self)
72 hbox.pack_start(info, expand=False, fill=False)
73
74 hbox.show_all()
75 return hbox, spinner
76
77 def gen_combo_widget(self, curr_item, all_item, tooltip=""):
78 hbox = gtk.HBox(False, 12)
79 combo = gtk.combo_box_new_text()
80 hbox.pack_start(combo, expand=False, fill=False)
81
82 index = 0
83 for item in all_item or []:
84 combo.append_text(item)
85 if item == curr_item:
86 combo.set_active(index)
87 index += 1
88
89 info = HobInfoButton(tooltip, self)
90 hbox.pack_start(info, expand=False, fill=False)
91
92 hbox.show_all()
93 return hbox, combo
94
95 def entry_widget_select_path_cb(self, action, parent, entry):
96 dialog = gtk.FileChooserDialog("", parent,
97 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
98 text = entry.get_text()
99 dialog.set_current_folder(text if len(text) > 0 else os.getcwd())
100 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
101 HobAltButton.style_button(button)
102 button = dialog.add_button("Open", gtk.RESPONSE_YES)
103 HobButton.style_button(button)
104 response = dialog.run()
105 if response == gtk.RESPONSE_YES:
106 path = dialog.get_filename()
107 entry.set_text(path)
108
109 dialog.destroy()
110
111 def gen_entry_widget(self, content, parent, tooltip="", need_button=True):
112 hbox = gtk.HBox(False, 12)
113 entry = gtk.Entry()
114 entry.set_text(content)
115 entry.set_size_request(350,30)
116
117 if need_button:
118 table = gtk.Table(1, 10, False)
119 hbox.pack_start(table, expand=True, fill=True)
120 table.attach(entry, 0, 9, 0, 1, xoptions=gtk.SHRINK)
121 image = gtk.Image()
122 image.set_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON)
123 open_button = gtk.Button()
124 open_button.set_image(image)
125 open_button.connect("clicked", self.entry_widget_select_path_cb, parent, entry)
126 table.attach(open_button, 9, 10, 0, 1, xoptions=gtk.SHRINK)
127 else:
128 hbox.pack_start(entry, expand=True, fill=True)
129
130 if tooltip != "":
131 info = HobInfoButton(tooltip, self)
132 hbox.pack_start(info, expand=False, fill=False)
133
134 hbox.show_all()
135 return hbox, entry
136
137 def gen_mirror_entry_widget(self, content, index, match_content=""):
138 hbox = gtk.HBox(False)
139 entry = gtk.Entry()
140 content = content[:-2]
141 entry.set_text(content)
142 entry.set_size_request(350,30)
143
144 entry_match = gtk.Entry()
145 entry_match.set_text(match_content)
146 entry_match.set_size_request(100,30)
147
148 table = gtk.Table(2, 5, False)
149 table.set_row_spacings(12)
150 table.set_col_spacings(6)
151 hbox.pack_start(table, expand=True, fill=True)
152
153 label_configuration = gtk.Label("Configuration")
154 label_configuration.set_alignment(0.0,0.5)
155 label_mirror_url = gtk.Label("Mirror URL")
156 label_mirror_url.set_alignment(0.0,0.5)
157 label_match = gtk.Label("Match")
158 label_match.set_alignment(0.0,0.5)
159 label_replace_with = gtk.Label("Replace with")
160 label_replace_with.set_alignment(0.0,0.5)
161
162 combo = gtk.combo_box_new_text()
163 combo.append_text("Standard")
164 combo.append_text("Custom")
165 if match_content == "":
166 combo.set_active(0)
167 else:
168 combo.set_active(1)
169 combo.connect("changed", self.on_combo_changed, index)
170 combo.set_size_request(100,30)
171
172 delete_button = HobAltButton("Delete")
173 delete_button.connect("clicked", self.delete_cb, index, entry)
174 if content == "" and index == 0 and len(self.sstatemirrors_list) == 1:
175 delete_button.set_sensitive(False)
176 delete_button.set_size_request(100, 30)
177
178 entry_match.connect("changed", self.insert_entry_match_cb, index)
179 entry.connect("changed", self.insert_entry_cb, index, delete_button)
180
181 if match_content == "":
182 table.attach(label_configuration, 1, 2, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
183 table.attach(label_mirror_url, 2, 3, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
184 table.attach(combo, 1, 2, 1, 2, xoptions=gtk.SHRINK)
185 table.attach(entry, 2, 3, 1, 2, xoptions=gtk.SHRINK)
186 table.attach(delete_button, 3, 4, 1, 2, xoptions=gtk.SHRINK)
187 else:
188 table.attach(label_configuration, 1, 2, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
189 table.attach(label_match, 2, 3, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
190 table.attach(label_replace_with, 3, 4, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
191 table.attach(combo, 1, 2, 1, 2, xoptions=gtk.SHRINK)
192 table.attach(entry_match, 2, 3, 1, 2, xoptions=gtk.SHRINK)
193 table.attach(entry, 3, 4, 1, 2, xoptions=gtk.SHRINK)
194 table.attach(delete_button, 4, 5, 1, 2, xoptions=gtk.SHRINK)
195
196 hbox.show_all()
197 return hbox
198
199 def insert_entry_match_cb(self, entry_match, index):
200 self.sstatemirrors_list[index][2] = entry_match.get_text()
201
202 def insert_entry_cb(self, entry, index, button):
203 self.sstatemirrors_list[index][1] = entry.get_text()
204 if entry.get_text() == "" and index == 0:
205 button.set_sensitive(False)
206 else:
207 button.set_sensitive(True)
208
209 def on_combo_changed(self, combo, index):
210 if combo.get_active_text() == "Standard":
211 self.sstatemirrors_list[index][0] = 0
212 self.sstatemirrors_list[index][2] = "file://(.*)"
213 else:
214 self.sstatemirrors_list[index][0] = 1
215 self.refresh_shared_state_page()
216
217 def delete_cb(self, button, index, entry):
218 if index == 0 and len(self.sstatemirrors_list)==1:
219 entry.set_text("")
220 else:
221 self.sstatemirrors_list.pop(index)
222 self.refresh_shared_state_page()
223
224 def add_mirror(self, button):
225 tooltip = "Select the pre-built mirror that will speed your build"
226 index = len(self.sstatemirrors_list)
227 sm_list = [0, "", "file://(.*)"]
228 self.sstatemirrors_list.append(sm_list)
229 self.refresh_shared_state_page()
230
231#
232# CrumbsDialog
233#
234class CrumbsDialog(gtk.Dialog):
235 """
236 A GNOME HIG compliant dialog widget.
237 Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons
238 """
239 def __init__(self, title="", parent=None, flags=0, buttons=None):
240 super(CrumbsDialog, self).__init__(title, parent, flags, buttons)
241
242 self.set_property("has-separator", False) # note: deprecated in 2.22
243
244 self.set_border_width(6)
245 self.vbox.set_property("spacing", 12)
246 self.action_area.set_property("spacing", 12)
247 self.action_area.set_property("border-width", 6)
248
249class CrumbsMessageDialog(CrumbsDialog):
250 """
251 A GNOME HIG compliant dialog widget.
252 Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons
253 """
254 def __init__(self, parent=None, label="", icon=gtk.STOCK_INFO, msg=""):
255 super(CrumbsMessageDialog, self).__init__("", parent, gtk.DIALOG_MODAL)
256
257 self.set_border_width(6)
258 self.vbox.set_property("spacing", 12)
259 self.action_area.set_property("spacing", 12)
260 self.action_area.set_property("border-width", 6)
261
262 first_column = gtk.HBox(spacing=12)
263 first_column.set_property("border-width", 6)
264 first_column.show()
265 self.vbox.add(first_column)
266
267 self.icon = gtk.Image()
268 # We have our own Info icon which should be used in preference of the stock icon
269 self.icon_chk = HobIconChecker()
270 self.icon.set_from_stock(self.icon_chk.check_stock_icon(icon), gtk.ICON_SIZE_DIALOG)
271 self.icon.set_property("yalign", 0.00)
272 self.icon.show()
273 first_column.pack_start(self.icon, expand=False, fill=True, padding=0)
274
275 if 0 <= len(msg) < 200:
276 lbl = label + "%s" % glib.markup_escape_text(msg)
277 self.label_short = gtk.Label()
278 self.label_short.set_use_markup(True)
279 self.label_short.set_line_wrap(True)
280 self.label_short.set_markup(lbl)
281 self.label_short.set_property("yalign", 0.00)
282 self.label_short.show()
283 first_column.add(self.label_short)
284 else:
285 second_row = gtk.VBox(spacing=12)
286 second_row.set_property("border-width", 6)
287 self.label_long = gtk.Label()
288 self.label_long.set_use_markup(True)
289 self.label_long.set_line_wrap(True)
290 self.label_long.set_markup(label)
291 self.label_long.set_alignment(0.0, 0.0)
292 second_row.pack_start(self.label_long, expand=False, fill=False, padding=0)
293 self.label_long.show()
294 self.textWindow = gtk.ScrolledWindow()
295 self.textWindow.set_shadow_type(gtk.SHADOW_IN)
296 self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
297 self.msgView = gtk.TextView()
298 self.msgView.set_editable(False)
299 self.msgView.set_wrap_mode(gtk.WRAP_WORD)
300 self.msgView.set_cursor_visible(False)
301 self.msgView.set_size_request(300, 300)
302 self.buf = gtk.TextBuffer()
303 self.buf.set_text(msg)
304 self.msgView.set_buffer(self.buf)
305 self.textWindow.add(self.msgView)
306 self.msgView.show()
307 second_row.add(self.textWindow)
308 self.textWindow.show()
309 first_column.add(second_row)
310 second_row.show()
311
312#
313# SimpleSettings Dialog
314#
315class SimpleSettingsDialog (CrumbsDialog, SettingsUIHelper):
316
317 (BUILD_ENV_PAGE_ID,
318 SHARED_STATE_PAGE_ID,
319 PROXIES_PAGE_ID,
320 OTHERS_PAGE_ID) = range(4)
321
322 (TEST_NETWORK_NONE,
323 TEST_NETWORK_INITIAL,
324 TEST_NETWORK_RUNNING,
325 TEST_NETWORK_PASSED,
326 TEST_NETWORK_FAILED,
327 TEST_NETWORK_CANCELED) = range(6)
328
329 def __init__(self, title, configuration, all_image_types,
330 all_package_formats, all_distros, all_sdk_machines,
331 max_threads, parent, flags, handler, buttons=None):
332 super(SimpleSettingsDialog, self).__init__(title, parent, flags, buttons)
333
334 # class members from other objects
335 # bitbake settings from Builder.Configuration
336 self.configuration = configuration
337 self.image_types = all_image_types
338 self.all_package_formats = all_package_formats
339 self.all_distros = all_distros
340 self.all_sdk_machines = all_sdk_machines
341 self.max_threads = max_threads
342
343 # class members for internal use
344 self.dldir_text = None
345 self.sstatedir_text = None
346 self.sstatemirrors_list = []
347 self.sstatemirrors_changed = 0
348 self.bb_spinner = None
349 self.pmake_spinner = None
350 self.rootfs_size_spinner = None
351 self.extra_size_spinner = None
352 self.gplv3_checkbox = None
353 self.toolchain_checkbox = None
354 self.setting_store = None
355 self.image_types_checkbuttons = {}
356
357 self.md5 = self.config_md5()
358 self.proxy_md5 = self.config_proxy_md5()
359 self.settings_changed = False
360 self.proxy_settings_changed = False
361 self.handler = handler
362 self.proxy_test_ran = False
363
364 # create visual elements on the dialog
365 self.create_visual_elements()
366 self.connect("response", self.response_cb)
367
368 def _get_sorted_value(self, var):
369 return " ".join(sorted(str(var).split())) + "\n"
370
371 def config_proxy_md5(self):
372 data = ("ENABLE_PROXY: " + self._get_sorted_value(self.configuration.enable_proxy))
373 if self.configuration.enable_proxy:
374 for protocol in self.configuration.proxies.keys():
375 data += (protocol + ": " + self._get_sorted_value(self.configuration.combine_proxy(protocol)))
376 return hashlib.md5(data).hexdigest()
377
378 def config_md5(self):
379 data = ""
380 for key in self.configuration.extra_setting.keys():
381 data += (key + ": " + self._get_sorted_value(self.configuration.extra_setting[key]))
382 return hashlib.md5(data).hexdigest()
383
384 def gen_proxy_entry_widget(self, protocol, parent, need_button=True, line=0):
385 label = gtk.Label(protocol.upper() + " proxy")
386 self.proxy_table.attach(label, 0, 1, line, line+1, xpadding=24)
387
388 proxy_entry = gtk.Entry()
389 proxy_entry.set_size_request(300, -1)
390 self.proxy_table.attach(proxy_entry, 1, 2, line, line+1, ypadding=4)
391
392 self.proxy_table.attach(gtk.Label(":"), 2, 3, line, line+1, xpadding=12, ypadding=4)
393
394 port_entry = gtk.Entry()
395 port_entry.set_size_request(60, -1)
396 self.proxy_table.attach(port_entry, 3, 4, line, line+1, ypadding=4)
397
398 details_button = HobAltButton("Details")
399 details_button.connect("clicked", self.details_cb, parent, protocol)
400 self.proxy_table.attach(details_button, 4, 5, line, line+1, xpadding=4, yoptions=gtk.EXPAND)
401
402 return proxy_entry, port_entry, details_button
403
404 def refresh_proxy_components(self):
405 self.same_checkbox.set_sensitive(self.configuration.enable_proxy)
406
407 self.http_proxy.set_text(self.configuration.combine_host_only("http"))
408 self.http_proxy.set_editable(self.configuration.enable_proxy)
409 self.http_proxy.set_sensitive(self.configuration.enable_proxy)
410 self.http_proxy_port.set_text(self.configuration.combine_port_only("http"))
411 self.http_proxy_port.set_editable(self.configuration.enable_proxy)
412 self.http_proxy_port.set_sensitive(self.configuration.enable_proxy)
413 self.http_proxy_details.set_sensitive(self.configuration.enable_proxy)
414
415 self.https_proxy.set_text(self.configuration.combine_host_only("https"))
416 self.https_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
417 self.https_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
418 self.https_proxy_port.set_text(self.configuration.combine_port_only("https"))
419 self.https_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
420 self.https_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
421 self.https_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
422
423 self.ftp_proxy.set_text(self.configuration.combine_host_only("ftp"))
424 self.ftp_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
425 self.ftp_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
426 self.ftp_proxy_port.set_text(self.configuration.combine_port_only("ftp"))
427 self.ftp_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
428 self.ftp_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
429 self.ftp_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
430
431 self.git_proxy.set_text(self.configuration.combine_host_only("git"))
432 self.git_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
433 self.git_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
434 self.git_proxy_port.set_text(self.configuration.combine_port_only("git"))
435 self.git_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
436 self.git_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
437 self.git_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
438
439 self.cvs_proxy.set_text(self.configuration.combine_host_only("cvs"))
440 self.cvs_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
441 self.cvs_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
442 self.cvs_proxy_port.set_text(self.configuration.combine_port_only("cvs"))
443 self.cvs_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
444 self.cvs_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
445 self.cvs_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
446
447 if self.configuration.same_proxy:
448 if self.http_proxy.get_text():
449 [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
450 if self.http_proxy_port.get_text():
451 [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
452
453 def proxy_checkbox_toggled_cb(self, button):
454 self.configuration.enable_proxy = self.proxy_checkbox.get_active()
455 if not self.configuration.enable_proxy:
456 self.configuration.same_proxy = False
457 self.same_checkbox.set_active(self.configuration.same_proxy)
458 self.save_proxy_data()
459 self.refresh_proxy_components()
460
461 def same_checkbox_toggled_cb(self, button):
462 self.configuration.same_proxy = self.same_checkbox.get_active()
463 self.save_proxy_data()
464 self.refresh_proxy_components()
465
466 def save_proxy_data(self):
467 self.configuration.split_proxy("http", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
468 if self.configuration.same_proxy:
469 self.configuration.split_proxy("https", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
470 self.configuration.split_proxy("ftp", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
471 self.configuration.split_proxy("git", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
472 self.configuration.split_proxy("cvs", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
473 else:
474 self.configuration.split_proxy("https", self.https_proxy.get_text() + ":" + self.https_proxy_port.get_text())
475 self.configuration.split_proxy("ftp", self.ftp_proxy.get_text() + ":" + self.ftp_proxy_port.get_text())
476 self.configuration.split_proxy("git", self.git_proxy.get_text() + ":" + self.git_proxy_port.get_text())
477 self.configuration.split_proxy("cvs", self.cvs_proxy.get_text() + ":" + self.cvs_proxy_port.get_text())
478
479 def response_cb(self, dialog, response_id):
480 if response_id == gtk.RESPONSE_YES:
481 # Check that all proxy entries have a corresponding port
482 for proxy, port in zip(self.all_proxy_addresses, self.all_proxy_ports):
483 if proxy.get_text() and not port.get_text():
484 lbl = "<b>Enter all port numbers</b>\n\n"
485 msg = "Proxy servers require a port number. Please make sure you have entered a port number for each proxy server."
486 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING, msg)
487 button = dialog.add_button("Close", gtk.RESPONSE_OK)
488 HobButton.style_button(button)
489 response = dialog.run()
490 dialog.destroy()
491 self.emit_stop_by_name("response")
492 return
493
494 self.configuration.dldir = self.dldir_text.get_text()
495 self.configuration.sstatedir = self.sstatedir_text.get_text()
496 self.configuration.sstatemirror = ""
497 for mirror in self.sstatemirrors_list:
498 if mirror[1] != "":
499 if mirror[1].endswith("\\1"):
500 smirror = mirror[2] + " " + mirror[1] + " \\n "
501 else:
502 smirror = mirror[2] + " " + mirror[1] + "\\1 \\n "
503 self.configuration.sstatemirror += smirror
504 self.configuration.bbthread = self.bb_spinner.get_value_as_int()
505 self.configuration.pmake = self.pmake_spinner.get_value_as_int()
506 self.save_proxy_data()
507 self.configuration.extra_setting = {}
508 it = self.setting_store.get_iter_first()
509 while it:
510 key = self.setting_store.get_value(it, 0)
511 value = self.setting_store.get_value(it, 1)
512 self.configuration.extra_setting[key] = value
513 it = self.setting_store.iter_next(it)
514
515 md5 = self.config_md5()
516 self.settings_changed = (self.md5 != md5)
517 self.proxy_settings_changed = (self.proxy_md5 != self.config_proxy_md5())
518
519 def create_build_environment_page(self):
520 advanced_vbox = gtk.VBox(False, 6)
521 advanced_vbox.set_border_width(6)
522
523 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Parallel threads</span>'), expand=False, fill=False)
524 sub_vbox = gtk.VBox(False, 6)
525 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
526 label = self.gen_label_widget("BitBake parallel threads")
527 tooltip = "Sets the number of threads that BitBake tasks can simultaneously run. See the <a href=\""
528 tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
529 tooltip += "poky-ref-manual.html#var-BB_NUMBER_THREADS\">Poky reference manual</a> for information"
530 bbthread_widget, self.bb_spinner = self.gen_spinner_widget(self.configuration.bbthread, 1, self.max_threads, tooltip)
531 sub_vbox.pack_start(label, expand=False, fill=False)
532 sub_vbox.pack_start(bbthread_widget, expand=False, fill=False)
533
534 sub_vbox = gtk.VBox(False, 6)
535 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
536 label = self.gen_label_widget("Make parallel threads")
537 tooltip = "Sets the maximum number of threads the host can use during the build. See the <a href=\""
538 tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
539 tooltip += "poky-ref-manual.html#var-PARALLEL_MAKE\">Poky reference manual</a> for information"
540 pmake_widget, self.pmake_spinner = self.gen_spinner_widget(self.configuration.pmake, 1, self.max_threads, tooltip)
541 sub_vbox.pack_start(label, expand=False, fill=False)
542 sub_vbox.pack_start(pmake_widget, expand=False, fill=False)
543
544 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Downloaded source code</span>'), expand=False, fill=False)
545 sub_vbox = gtk.VBox(False, 6)
546 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
547 label = self.gen_label_widget("Downloads directory")
548 tooltip = "Select a folder that caches the upstream project source code"
549 dldir_widget, self.dldir_text = self.gen_entry_widget(self.configuration.dldir, self, tooltip)
550 sub_vbox.pack_start(label, expand=False, fill=False)
551 sub_vbox.pack_start(dldir_widget, expand=False, fill=False)
552
553 return advanced_vbox
554
555 def create_shared_state_page(self):
556 advanced_vbox = gtk.VBox(False)
557 advanced_vbox.set_border_width(12)
558
559 sub_vbox = gtk.VBox(False)
560 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False, padding=24)
561 content = "<span>Shared state directory</span>"
562 tooltip = "Select a folder that caches your prebuilt results"
563 label = self.gen_label_info_widget(content, tooltip)
564 sstatedir_widget, self.sstatedir_text = self.gen_entry_widget(self.configuration.sstatedir, self)
565 sub_vbox.pack_start(label, expand=False, fill=False)
566 sub_vbox.pack_start(sstatedir_widget, expand=False, fill=False, padding=12)
567
568 content = "<span weight=\"bold\">Shared state mirrors</span>"
569 tooltip = "URLs pointing to pre-built mirrors that will speed your build. "
570 tooltip += "Select the \'Standard\' configuration if the structure of your "
571 tooltip += "mirror replicates the structure of your local shared state directory. "
572 tooltip += "For more information on shared state mirrors, check the <a href=\""
573 tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
574 tooltip += "poky-ref-manual.html#shared-state\">Yocto Project Reference Manual</a>."
575 table = self.gen_label_info_widget(content, tooltip)
576 advanced_vbox.pack_start(table, expand=False, fill=False)
577
578 sub_vbox = gtk.VBox(False)
579 scroll = gtk.ScrolledWindow()
580 scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
581 scroll.add_with_viewport(sub_vbox)
582 scroll.connect('size-allocate', self.scroll_changed)
583 advanced_vbox.pack_start(scroll, gtk.TRUE, gtk.TRUE, 0)
584 searched_string = "file://"
585
586 if self.sstatemirrors_changed == 0:
587 self.sstatemirrors_changed = 1
588 sstatemirrors = self.configuration.sstatemirror
589 if sstatemirrors == "":
590 sm_list = [ 0, "", "file://(.*)"]
591 self.sstatemirrors_list.append(sm_list)
592 else:
593 while sstatemirrors.find(searched_string) != -1:
594 if sstatemirrors.find(searched_string,1) != -1:
595 sstatemirror = sstatemirrors[:sstatemirrors.find(searched_string,1)]
596 sstatemirrors = sstatemirrors[sstatemirrors.find(searched_string,1):]
597 else:
598 sstatemirror = sstatemirrors
599 sstatemirrors = sstatemirrors[1:]
600
601 sstatemirror_fields = [x for x in sstatemirror.split(' ') if x.strip()]
602 if sstatemirror_fields[0] == "file://(.*)":
603 sm_list = [ 0, sstatemirror_fields[1], "file://(.*)"]
604 else:
605 sm_list = [ 1, sstatemirror_fields[1], sstatemirror_fields[0]]
606 self.sstatemirrors_list.append(sm_list)
607
608 index = 0
609 for mirror in self.sstatemirrors_list:
610 if mirror[0] == 0:
611 sstatemirror_widget = self.gen_mirror_entry_widget(mirror[1], index)
612 else:
613 sstatemirror_widget = self.gen_mirror_entry_widget(mirror[1], index, mirror[2])
614 sub_vbox.pack_start(sstatemirror_widget, expand=False, fill=False, padding=9)
615 index += 1
616
617 table = gtk.Table(1, 1, False)
618 table.set_col_spacings(6)
619 add_mirror_button = HobAltButton("Add another mirror")
620 add_mirror_button.connect("clicked", self.add_mirror)
621 add_mirror_button.set_size_request(150,30)
622 table.attach(add_mirror_button, 1, 2, 0, 1, xoptions=gtk.SHRINK)
623 advanced_vbox.pack_start(table, expand=False, fill=False, padding=9)
624
625 return advanced_vbox
626
627 def refresh_shared_state_page(self):
628 page_num = self.nb.get_current_page()
629 self.nb.remove_page(page_num);
630 self.nb.insert_page(self.create_shared_state_page(), gtk.Label("Shared state"),page_num)
631 self.show_all()
632 self.nb.set_current_page(page_num)
633
634 def test_proxy_ended(self, passed):
635 self.proxy_test_running = False
636 self.set_test_proxy_state(self.TEST_NETWORK_PASSED if passed else self.TEST_NETWORK_FAILED)
637 self.set_sensitive(True)
638 self.refresh_proxy_components()
639
640 def timer_func(self):
641 self.test_proxy_progress.pulse()
642 return self.proxy_test_running
643
644 def test_network_button_cb(self, b):
645 self.set_test_proxy_state(self.TEST_NETWORK_RUNNING)
646 self.set_sensitive(False)
647 self.save_proxy_data()
648 if self.configuration.enable_proxy == True:
649 self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
650 self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
651 self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
652 self.handler.set_git_proxy(self.configuration.combine_host_only("git"), self.configuration.combine_port_only("git"))
653 self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
654 elif self.configuration.enable_proxy == False:
655 self.handler.set_http_proxy("")
656 self.handler.set_https_proxy("")
657 self.handler.set_ftp_proxy("")
658 self.handler.set_git_proxy("", "")
659 self.handler.set_cvs_proxy("", "")
660 self.proxy_test_ran = True
661 self.proxy_test_running = True
662 gobject.timeout_add(100, self.timer_func)
663 self.handler.trigger_network_test()
664
665 def test_proxy_focus_event(self, w, direction):
666 if self.test_proxy_state in [self.TEST_NETWORK_PASSED, self.TEST_NETWORK_FAILED]:
667 self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
668 return False
669
670 def http_proxy_changed(self, e):
671 if not self.configuration.same_proxy:
672 return
673 if e == self.http_proxy:
674 [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
675 else:
676 [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
677
678 def proxy_address_focus_out_event(self, w, direction):
679 text = w.get_text()
680 if not text:
681 return False
682 if text.find("//") == -1:
683 w.set_text("http://" + text)
684 return False
685
686 def set_test_proxy_state(self, state):
687 if self.test_proxy_state == state:
688 return
689 [self.proxy_table.remove(w) for w in self.test_gui_elements]
690 if state == self.TEST_NETWORK_INITIAL:
691 self.proxy_table.attach(self.test_network_button, 1, 2, 5, 6)
692 self.test_network_button.show()
693 elif state == self.TEST_NETWORK_RUNNING:
694 self.test_proxy_progress.set_rcstyle("running")
695 self.test_proxy_progress.set_text("Testing network configuration")
696 self.proxy_table.attach(self.test_proxy_progress, 0, 5, 5, 6, xpadding=4)
697 self.test_proxy_progress.show()
698 else: # passed or failed
699 self.dummy_progress.update(1.0)
700 if state == self.TEST_NETWORK_PASSED:
701 self.dummy_progress.set_text("Your network is properly configured")
702 self.dummy_progress.set_rcstyle("running")
703 else:
704 self.dummy_progress.set_text("Network test failed")
705 self.dummy_progress.set_rcstyle("fail")
706 self.proxy_table.attach(self.dummy_progress, 0, 4, 5, 6)
707 self.proxy_table.attach(self.retest_network_button, 4, 5, 5, 6, xpadding=4)
708 self.dummy_progress.show()
709 self.retest_network_button.show()
710 self.test_proxy_state = state
711
712 def create_network_page(self):
713 advanced_vbox = gtk.VBox(False, 6)
714 advanced_vbox.set_border_width(6)
715 self.same_proxy_addresses = []
716 self.same_proxy_ports = []
717 self.all_proxy_ports = []
718 self.all_proxy_addresses = []
719
720 sub_vbox = gtk.VBox(False, 6)
721 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
722 label = self.gen_label_widget("<span weight=\"bold\">Set the proxies used when fetching source code</span>")
723 tooltip = "Set the proxies used when fetching source code. A blank field uses a direct internet connection."
724 info = HobInfoButton(tooltip, self)
725 hbox = gtk.HBox(False, 12)
726 hbox.pack_start(label, expand=True, fill=True)
727 hbox.pack_start(info, expand=False, fill=False)
728 sub_vbox.pack_start(hbox, expand=False, fill=False)
729
730 proxy_test_focus = []
731 self.direct_checkbox = gtk.RadioButton(None, "Direct network connection")
732 proxy_test_focus.append(self.direct_checkbox)
733 self.direct_checkbox.set_tooltip_text("Check this box to use a direct internet connection with no proxy")
734 self.direct_checkbox.set_active(not self.configuration.enable_proxy)
735 sub_vbox.pack_start(self.direct_checkbox, expand=False, fill=False)
736
737 self.proxy_checkbox = gtk.RadioButton(self.direct_checkbox, "Manual proxy configuration")
738 proxy_test_focus.append(self.proxy_checkbox)
739 self.proxy_checkbox.set_tooltip_text("Check this box to manually set up a specific proxy")
740 self.proxy_checkbox.set_active(self.configuration.enable_proxy)
741 sub_vbox.pack_start(self.proxy_checkbox, expand=False, fill=False)
742
743 self.same_checkbox = gtk.CheckButton("Use the HTTP proxy for all protocols")
744 proxy_test_focus.append(self.same_checkbox)
745 self.same_checkbox.set_tooltip_text("Check this box to use the HTTP proxy for all five proxies")
746 self.same_checkbox.set_active(self.configuration.same_proxy)
747 hbox = gtk.HBox(False, 12)
748 hbox.pack_start(self.same_checkbox, expand=False, fill=False, padding=24)
749 sub_vbox.pack_start(hbox, expand=False, fill=False)
750
751 self.proxy_table = gtk.Table(6, 5, False)
752 self.http_proxy, self.http_proxy_port, self.http_proxy_details = self.gen_proxy_entry_widget(
753 "http", self, True, 0)
754 proxy_test_focus +=[self.http_proxy, self.http_proxy_port]
755 self.http_proxy.connect("changed", self.http_proxy_changed)
756 self.http_proxy_port.connect("changed", self.http_proxy_changed)
757
758 self.https_proxy, self.https_proxy_port, self.https_proxy_details = self.gen_proxy_entry_widget(
759 "https", self, True, 1)
760 proxy_test_focus += [self.https_proxy, self.https_proxy_port]
761 self.same_proxy_addresses.append(self.https_proxy)
762 self.same_proxy_ports.append(self.https_proxy_port)
763
764 self.ftp_proxy, self.ftp_proxy_port, self.ftp_proxy_details = self.gen_proxy_entry_widget(
765 "ftp", self, True, 2)
766 proxy_test_focus += [self.ftp_proxy, self.ftp_proxy_port]
767 self.same_proxy_addresses.append(self.ftp_proxy)
768 self.same_proxy_ports.append(self.ftp_proxy_port)
769
770 self.git_proxy, self.git_proxy_port, self.git_proxy_details = self.gen_proxy_entry_widget(
771 "git", self, True, 3)
772 proxy_test_focus += [self.git_proxy, self.git_proxy_port]
773 self.same_proxy_addresses.append(self.git_proxy)
774 self.same_proxy_ports.append(self.git_proxy_port)
775
776 self.cvs_proxy, self.cvs_proxy_port, self.cvs_proxy_details = self.gen_proxy_entry_widget(
777 "cvs", self, True, 4)
778 proxy_test_focus += [self.cvs_proxy, self.cvs_proxy_port]
779 self.same_proxy_addresses.append(self.cvs_proxy)
780 self.same_proxy_ports.append(self.cvs_proxy_port)
781 self.all_proxy_ports = self.same_proxy_ports + [self.http_proxy_port]
782 self.all_proxy_addresses = self.same_proxy_addresses + [self.http_proxy]
783 sub_vbox.pack_start(self.proxy_table, expand=False, fill=False)
784 self.proxy_table.show_all()
785
786 # Create the graphical elements for the network test feature, but don't display them yet
787 self.test_network_button = HobAltButton("Test network configuration")
788 self.test_network_button.connect("clicked", self.test_network_button_cb)
789 self.test_proxy_progress = HobProgressBar()
790 self.dummy_progress = HobProgressBar()
791 self.retest_network_button = HobAltButton("Retest")
792 self.retest_network_button.connect("clicked", self.test_network_button_cb)
793 self.test_gui_elements = [self.test_network_button, self.test_proxy_progress, self.dummy_progress, self.retest_network_button]
794 # Initialize the network tester
795 self.test_proxy_state = self.TEST_NETWORK_NONE
796 self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
797 self.proxy_test_passed_id = self.handler.connect("network-passed", lambda h:self.test_proxy_ended(True))
798 self.proxy_test_failed_id = self.handler.connect("network-failed", lambda h:self.test_proxy_ended(False))
799 [w.connect("focus-in-event", self.test_proxy_focus_event) for w in proxy_test_focus]
800 [w.connect("focus-out-event", self.proxy_address_focus_out_event) for w in self.all_proxy_addresses]
801
802 self.direct_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
803 self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
804 self.same_checkbox.connect("toggled", self.same_checkbox_toggled_cb)
805
806 self.refresh_proxy_components()
807 return advanced_vbox
808
809 def switch_to_page(self, page_id):
810 self.nb.set_current_page(page_id)
811
812 def details_cb(self, button, parent, protocol):
813 self.save_proxy_data()
814 dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
815 user = self.configuration.proxies[protocol][1],
816 passwd = self.configuration.proxies[protocol][2],
817 parent = parent,
818 flags = gtk.DIALOG_MODAL
819 | gtk.DIALOG_DESTROY_WITH_PARENT
820 | gtk.DIALOG_NO_SEPARATOR)
821 dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
822 response = dialog.run()
823 if response == gtk.RESPONSE_OK:
824 self.configuration.proxies[protocol][1] = dialog.user
825 self.configuration.proxies[protocol][2] = dialog.passwd
826 self.refresh_proxy_components()
827 dialog.destroy()
828
829 def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
830 combo_item = self.rootfs_combo.get_active_text()
831 for child in check_hbox.get_children():
832 if isinstance(child, gtk.CheckButton):
833 check_hbox.remove(child)
834 for format in all_package_format:
835 if format != combo_item:
836 check_button = gtk.CheckButton(format)
837 check_hbox.pack_start(check_button, expand=False, fill=False)
838 check_hbox.show_all()
839
840 def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
841 pkgfmt_hbox = gtk.HBox(False, 24)
842
843 rootfs_vbox = gtk.VBox(False, 6)
844 pkgfmt_hbox.pack_start(rootfs_vbox, expand=False, fill=False)
845
846 label = self.gen_label_widget("Root file system package format")
847 rootfs_vbox.pack_start(label, expand=False, fill=False)
848
849 rootfs_format = ""
850 if curr_package_format:
851 rootfs_format = curr_package_format.split()[0]
852
853 rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
854 rootfs_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
855
856 extra_vbox = gtk.VBox(False, 6)
857 pkgfmt_hbox.pack_start(extra_vbox, expand=False, fill=False)
858
859 label = self.gen_label_widget("Additional package formats")
860 extra_vbox.pack_start(label, expand=False, fill=False)
861
862 check_hbox = gtk.HBox(False, 12)
863 extra_vbox.pack_start(check_hbox, expand=False, fill=False)
864 for format in all_package_format:
865 if format != rootfs_format:
866 check_button = gtk.CheckButton(format)
867 is_active = (format in curr_package_format.split())
868 check_button.set_active(is_active)
869 check_hbox.pack_start(check_button, expand=False, fill=False)
870
871 info = HobInfoButton(tooltip_extra, self)
872 check_hbox.pack_end(info, expand=False, fill=False)
873
874 rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
875
876 pkgfmt_hbox.show_all()
877
878 return pkgfmt_hbox, rootfs_combo, check_hbox
879
880 def editable_settings_cell_edited(self, cell, path_string, new_text, model):
881 it = model.get_iter_from_string(path_string)
882 column = cell.get_data("column")
883 model.set(it, column, new_text)
884
885 def editable_settings_add_item_clicked(self, button, model):
886 new_item = ["##KEY##", "##VALUE##"]
887
888 iter = model.append()
889 model.set (iter,
890 0, new_item[0],
891 1, new_item[1],
892 )
893
894 def editable_settings_remove_item_clicked(self, button, treeview):
895 selection = treeview.get_selection()
896 model, iter = selection.get_selected()
897
898 if iter:
899 path = model.get_path(iter)[0]
900 model.remove(iter)
901
902 def gen_editable_settings(self, setting, tooltip=""):
903 setting_hbox = gtk.HBox(False, 12)
904
905 vbox = gtk.VBox(False, 12)
906 setting_hbox.pack_start(vbox, expand=True, fill=True)
907
908 setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
909 for key in setting.keys():
910 setting_store.set(setting_store.append(), 0, key, 1, setting[key])
911
912 setting_tree = gtk.TreeView(setting_store)
913 setting_tree.set_headers_visible(True)
914 setting_tree.set_size_request(300, 100)
915
916 col = gtk.TreeViewColumn('Key')
917 col.set_min_width(100)
918 col.set_max_width(150)
919 col.set_resizable(True)
920 col1 = gtk.TreeViewColumn('Value')
921 col1.set_min_width(100)
922 col1.set_max_width(150)
923 col1.set_resizable(True)
924 setting_tree.append_column(col)
925 setting_tree.append_column(col1)
926 cell = gtk.CellRendererText()
927 cell.set_property('width-chars', 10)
928 cell.set_property('editable', True)
929 cell.set_data("column", 0)
930 cell.connect("edited", self.editable_settings_cell_edited, setting_store)
931 cell1 = gtk.CellRendererText()
932 cell1.set_property('width-chars', 10)
933 cell1.set_property('editable', True)
934 cell1.set_data("column", 1)
935 cell1.connect("edited", self.editable_settings_cell_edited, setting_store)
936 col.pack_start(cell, True)
937 col1.pack_end(cell1, True)
938 col.set_attributes(cell, text=0)
939 col1.set_attributes(cell1, text=1)
940
941 scroll = gtk.ScrolledWindow()
942 scroll.set_shadow_type(gtk.SHADOW_IN)
943 scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
944 scroll.add(setting_tree)
945 vbox.pack_start(scroll, expand=True, fill=True)
946
947 # some buttons
948 hbox = gtk.HBox(True, 6)
949 vbox.pack_start(hbox, False, False)
950
951 button = gtk.Button(stock=gtk.STOCK_ADD)
952 button.connect("clicked", self.editable_settings_add_item_clicked, setting_store)
953 hbox.pack_start(button)
954
955 button = gtk.Button(stock=gtk.STOCK_REMOVE)
956 button.connect("clicked", self.editable_settings_remove_item_clicked, setting_tree)
957 hbox.pack_start(button)
958
959 info = HobInfoButton(tooltip, self)
960 setting_hbox.pack_start(info, expand=False, fill=False)
961
962 return setting_hbox, setting_store
963
964 def create_others_page(self):
965 advanced_vbox = gtk.VBox(False, 6)
966 advanced_vbox.set_border_width(6)
967
968 sub_vbox = gtk.VBox(False, 6)
969 advanced_vbox.pack_start(sub_vbox, expand=True, fill=True)
970 label = self.gen_label_widget("<span weight=\"bold\">Add your own variables:</span>")
971 tooltip = "These are key/value pairs for your extra settings. Click \'Add\' and then directly edit the key and the value"
972 setting_widget, self.setting_store = self.gen_editable_settings(self.configuration.extra_setting, tooltip)
973 sub_vbox.pack_start(label, expand=False, fill=False)
974 sub_vbox.pack_start(setting_widget, expand=True, fill=True)
975
976 return advanced_vbox
977
978 def create_visual_elements(self):
979 self.nb = gtk.Notebook()
980 self.nb.set_show_tabs(True)
981 self.nb.append_page(self.create_build_environment_page(), gtk.Label("Build environment"))
982 self.nb.append_page(self.create_shared_state_page(), gtk.Label("Shared state"))
983 self.nb.append_page(self.create_network_page(), gtk.Label("Network"))
984 self.nb.append_page(self.create_others_page(), gtk.Label("Others"))
985 self.nb.set_current_page(0)
986 self.vbox.pack_start(self.nb, expand=True, fill=True)
987 self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
988
989 self.show_all()
990
991 def destroy(self):
992 self.handler.disconnect(self.proxy_test_passed_id)
993 self.handler.disconnect(self.proxy_test_failed_id)
994 super(SimpleSettingsDialog, self).destroy()
995
996 def scroll_changed(self, widget, event, data=None):
997 adj = widget.get_vadjustment()
998 adj.set_value(adj.upper - adj.page_size)
999
1000#
1001# AdvancedSettings Dialog
1002#
1003class AdvancedSettingDialog (CrumbsDialog, SettingsUIHelper):
1004
1005 def details_cb(self, button, parent, protocol):
1006 dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
1007 user = self.configuration.proxies[protocol][1],
1008 passwd = self.configuration.proxies[protocol][2],
1009 parent = parent,
1010 flags = gtk.DIALOG_MODAL
1011 | gtk.DIALOG_DESTROY_WITH_PARENT
1012 | gtk.DIALOG_NO_SEPARATOR)
1013 dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
1014 response = dialog.run()
1015 if response == gtk.RESPONSE_OK:
1016 self.configuration.proxies[protocol][1] = dialog.user
1017 self.configuration.proxies[protocol][2] = dialog.passwd
1018 self.refresh_proxy_components()
1019 dialog.destroy()
1020
1021 def set_save_button(self, button):
1022 self.save_button = button
1023
1024 def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
1025 combo_item = self.rootfs_combo.get_active_text()
1026 modified = False
1027 for child in check_hbox.get_children():
1028 if isinstance(child, gtk.CheckButton):
1029 check_hbox.remove(child)
1030 modified = True
1031 for format in all_package_format:
1032 if format != combo_item:
1033 check_button = gtk.CheckButton(format)
1034 check_hbox.pack_start(check_button, expand=False, fill=False)
1035 modified = True
1036 if modified:
1037 check_hbox.remove(self.pkgfmt_info)
1038 check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
1039 check_hbox.show_all()
1040
1041 def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
1042 pkgfmt_vbox = gtk.VBox(False, 6)
1043
1044 label = self.gen_label_widget("Root file system package format")
1045 pkgfmt_vbox.pack_start(label, expand=False, fill=False)
1046
1047 rootfs_format = ""
1048 if curr_package_format:
1049 rootfs_format = curr_package_format.split()[0]
1050
1051 rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
1052 pkgfmt_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
1053
1054 label = self.gen_label_widget("Additional package formats")
1055 pkgfmt_vbox.pack_start(label, expand=False, fill=False)
1056
1057 check_hbox = gtk.HBox(False, 12)
1058 pkgfmt_vbox.pack_start(check_hbox, expand=False, fill=False)
1059 for format in all_package_format:
1060 if format != rootfs_format:
1061 check_button = gtk.CheckButton(format)
1062 is_active = (format in curr_package_format.split())
1063 check_button.set_active(is_active)
1064 check_hbox.pack_start(check_button, expand=False, fill=False)
1065
1066 self.pkgfmt_info = HobInfoButton(tooltip_extra, self)
1067 check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
1068
1069 rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
1070
1071 pkgfmt_vbox.show_all()
1072
1073 return pkgfmt_vbox, rootfs_combo, check_hbox
1074
1075 def __init__(self, title, configuration, all_image_types,
1076 all_package_formats, all_distros, all_sdk_machines,
1077 max_threads, parent, flags, buttons=None):
1078 super(AdvancedSettingDialog, self).__init__(title, parent, flags, buttons)
1079
1080 # class members from other objects
1081 # bitbake settings from Builder.Configuration
1082 self.configuration = configuration
1083 self.image_types = all_image_types
1084 self.all_package_formats = all_package_formats
1085 self.all_distros = all_distros[:]
1086 self.all_sdk_machines = all_sdk_machines
1087 self.max_threads = max_threads
1088
1089 # class members for internal use
1090 self.distro_combo = None
1091 self.dldir_text = None
1092 self.sstatedir_text = None
1093 self.sstatemirror_text = None
1094 self.bb_spinner = None
1095 self.pmake_spinner = None
1096 self.rootfs_size_spinner = None
1097 self.extra_size_spinner = None
1098 self.gplv3_checkbox = None
1099 self.toolchain_checkbox = None
1100 self.image_types_checkbuttons = {}
1101
1102 self.md5 = self.config_md5()
1103 self.settings_changed = False
1104
1105 # create visual elements on the dialog
1106 self.save_button = None
1107 self.create_visual_elements()
1108 self.connect("response", self.response_cb)
1109
1110 def _get_sorted_value(self, var):
1111 return " ".join(sorted(str(var).split())) + "\n"
1112
1113 def config_md5(self):
1114 data = ""
1115 data += ("PACKAGE_CLASSES: " + self.configuration.curr_package_format + '\n')
1116 data += ("DISTRO: " + self._get_sorted_value(self.configuration.curr_distro))
1117 data += ("IMAGE_ROOTFS_SIZE: " + self._get_sorted_value(self.configuration.image_rootfs_size))
1118 data += ("IMAGE_EXTRA_SIZE: " + self._get_sorted_value(self.configuration.image_extra_size))
1119 data += ("INCOMPATIBLE_LICENSE: " + self._get_sorted_value(self.configuration.incompat_license))
1120 data += ("SDK_MACHINE: " + self._get_sorted_value(self.configuration.curr_sdk_machine))
1121 data += ("TOOLCHAIN_BUILD: " + self._get_sorted_value(self.configuration.toolchain_build))
1122 data += ("IMAGE_FSTYPES: " + self._get_sorted_value(self.configuration.image_fstypes))
1123 return hashlib.md5(data).hexdigest()
1124
1125 def create_visual_elements(self):
1126 self.nb = gtk.Notebook()
1127 self.nb.set_show_tabs(True)
1128 self.nb.append_page(self.create_image_types_page(), gtk.Label("Image types"))
1129 self.nb.append_page(self.create_output_page(), gtk.Label("Output"))
1130 self.nb.set_current_page(0)
1131 self.vbox.pack_start(self.nb, expand=True, fill=True)
1132 self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
1133
1134 self.show_all()
1135
1136 def get_num_checked_image_types(self):
1137 total = 0
1138 for b in self.image_types_checkbuttons.values():
1139 if b.get_active():
1140 total = total + 1
1141 return total
1142
1143 def set_save_button_state(self):
1144 if self.save_button:
1145 self.save_button.set_sensitive(self.get_num_checked_image_types() > 0)
1146
1147 def image_type_checkbutton_clicked_cb(self, button):
1148 self.set_save_button_state()
1149 if self.get_num_checked_image_types() == 0:
1150 # Show an error dialog
1151 lbl = "<b>Select an image type</b>\n\nYou need to select at least one image type."
1152 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
1153 button = dialog.add_button("OK", gtk.RESPONSE_OK)
1154 HobButton.style_button(button)
1155 response = dialog.run()
1156 dialog.destroy()
1157
1158 def create_image_types_page(self):
1159 main_vbox = gtk.VBox(False, 16)
1160 main_vbox.set_border_width(6)
1161
1162 advanced_vbox = gtk.VBox(False, 6)
1163 advanced_vbox.set_border_width(6)
1164
1165 distro_vbox = gtk.VBox(False, 6)
1166 label = self.gen_label_widget("Distro:")
1167 tooltip = "Selects the Yocto Project distribution you want"
1168 try:
1169 i = self.all_distros.index( "defaultsetup" )
1170 except ValueError:
1171 i = -1
1172 if i != -1:
1173 self.all_distros[ i ] = "Default"
1174 if self.configuration.curr_distro == "defaultsetup":
1175 self.configuration.curr_distro = "Default"
1176 distro_widget, self.distro_combo = self.gen_combo_widget(self.configuration.curr_distro, self.all_distros, tooltip)
1177 distro_vbox.pack_start(label, expand=False, fill=False)
1178 distro_vbox.pack_start(distro_widget, expand=False, fill=False)
1179 main_vbox.pack_start(distro_vbox, expand=False, fill=False)
1180
1181
1182 rows = (len(self.image_types)+1)/3
1183 table = gtk.Table(rows + 1, 10, True)
1184 advanced_vbox.pack_start(table, expand=False, fill=False)
1185
1186 tooltip = "Image file system types you want."
1187 info = HobInfoButton(tooltip, self)
1188 label = self.gen_label_widget("Image types:")
1189 align = gtk.Alignment(0, 0.5, 0, 0)
1190 table.attach(align, 0, 4, 0, 1)
1191 align.add(label)
1192 table.attach(info, 4, 5, 0, 1)
1193
1194 i = 1
1195 j = 1
1196 for image_type in sorted(self.image_types):
1197 self.image_types_checkbuttons[image_type] = gtk.CheckButton(image_type)
1198 self.image_types_checkbuttons[image_type].connect("toggled", self.image_type_checkbutton_clicked_cb)
1199 article = ""
1200 if image_type.startswith(("a", "e", "i", "o", "u")):
1201 article = "n"
1202 self.image_types_checkbuttons[image_type].set_tooltip_text("Build a%s %s image" % (article, image_type))
1203 table.attach(self.image_types_checkbuttons[image_type], j - 1, j + 3, i, i + 1)
1204 if image_type in self.configuration.image_fstypes.split():
1205 self.image_types_checkbuttons[image_type].set_active(True)
1206 i += 1
1207 if i > rows:
1208 i = 1
1209 j = j + 4
1210
1211 main_vbox.pack_start(advanced_vbox, expand=False, fill=False)
1212 self.set_save_button_state()
1213
1214 return main_vbox
1215
1216 def create_output_page(self):
1217 advanced_vbox = gtk.VBox(False, 6)
1218 advanced_vbox.set_border_width(6)
1219
1220 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Package format</span>'), expand=False, fill=False)
1221 sub_vbox = gtk.VBox(False, 6)
1222 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
1223 tooltip_combo = "Selects the package format used to generate rootfs."
1224 tooltip_extra = "Selects extra package formats to build"
1225 pkgfmt_widget, self.rootfs_combo, self.check_hbox = self.gen_pkgfmt_widget(self.configuration.curr_package_format, self.all_package_formats, tooltip_combo, tooltip_extra)
1226 sub_vbox.pack_start(pkgfmt_widget, expand=False, fill=False)
1227
1228 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Image size</span>'), expand=False, fill=False)
1229 sub_vbox = gtk.VBox(False, 6)
1230 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
1231 label = self.gen_label_widget("Image basic size (in MB)")
1232 tooltip = "Sets the basic size of your target image.\nThis is the basic size of your target image unless your selected package size exceeds this value or you select \'Image Extra Size\'."
1233 rootfs_size_widget, self.rootfs_size_spinner = self.gen_spinner_widget(int(self.configuration.image_rootfs_size*1.0/1024), 0, 65536, tooltip)
1234 sub_vbox.pack_start(label, expand=False, fill=False)
1235 sub_vbox.pack_start(rootfs_size_widget, expand=False, fill=False)
1236
1237 sub_vbox = gtk.VBox(False, 6)
1238 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
1239 label = self.gen_label_widget("Additional free space (in MB)")
1240 tooltip = "Sets the extra free space of your target image.\nBy default, the system reserves 30% of your image size as free space. If your image contains zypper, it brings in 50MB more space. The maximum free space is 64GB."
1241 extra_size_widget, self.extra_size_spinner = self.gen_spinner_widget(int(self.configuration.image_extra_size*1.0/1024), 0, 65536, tooltip)
1242 sub_vbox.pack_start(label, expand=False, fill=False)
1243 sub_vbox.pack_start(extra_size_widget, expand=False, fill=False)
1244
1245 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Licensing</span>'), expand=False, fill=False)
1246 self.gplv3_checkbox = gtk.CheckButton("Exclude GPLv3 packages")
1247 self.gplv3_checkbox.set_tooltip_text("Check this box to prevent GPLv3 packages from being included in your image")
1248 if "GPLv3" in self.configuration.incompat_license.split():
1249 self.gplv3_checkbox.set_active(True)
1250 else:
1251 self.gplv3_checkbox.set_active(False)
1252 advanced_vbox.pack_start(self.gplv3_checkbox, expand=False, fill=False)
1253
1254 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Toolchain</span>'), expand=False, fill=False)
1255 sub_hbox = gtk.HBox(False, 6)
1256 advanced_vbox.pack_start(sub_hbox, expand=False, fill=False)
1257 self.toolchain_checkbox = gtk.CheckButton("Build toolchain")
1258 self.toolchain_checkbox.set_tooltip_text("Check this box to build the related toolchain with your image")
1259 self.toolchain_checkbox.set_active(self.configuration.toolchain_build)
1260 sub_hbox.pack_start(self.toolchain_checkbox, expand=False, fill=False)
1261
1262 tooltip = "Selects the host platform for which you want to run the toolchain"
1263 sdk_machine_widget, self.sdk_machine_combo = self.gen_combo_widget(self.configuration.curr_sdk_machine, self.all_sdk_machines, tooltip)
1264 sub_hbox.pack_start(sdk_machine_widget, expand=False, fill=False)
1265
1266 return advanced_vbox
1267
1268 def response_cb(self, dialog, response_id):
1269 package_format = []
1270 package_format.append(self.rootfs_combo.get_active_text())
1271 for child in self.check_hbox:
1272 if isinstance(child, gtk.CheckButton) and child.get_active():
1273 package_format.append(child.get_label())
1274 self.configuration.curr_package_format = " ".join(package_format)
1275
1276 distro = self.distro_combo.get_active_text()
1277 if distro == "Default":
1278 distro = "defaultsetup"
1279 self.configuration.curr_distro = distro
1280 self.configuration.image_rootfs_size = self.rootfs_size_spinner.get_value_as_int() * 1024
1281 self.configuration.image_extra_size = self.extra_size_spinner.get_value_as_int() * 1024
1282
1283 self.configuration.image_fstypes = ""
1284 for image_type in self.image_types:
1285 if self.image_types_checkbuttons[image_type].get_active():
1286 self.configuration.image_fstypes += (" " + image_type)
1287 self.configuration.image_fstypes.strip()
1288
1289 if self.gplv3_checkbox.get_active():
1290 if "GPLv3" not in self.configuration.incompat_license.split():
1291 self.configuration.incompat_license += " GPLv3"
1292 else:
1293 if "GPLv3" in self.configuration.incompat_license.split():
1294 self.configuration.incompat_license = self.configuration.incompat_license.split().remove("GPLv3")
1295 self.configuration.incompat_license = " ".join(self.configuration.incompat_license or [])
1296 self.configuration.incompat_license = self.configuration.incompat_license.strip()
1297
1298 self.configuration.toolchain_build = self.toolchain_checkbox.get_active()
1299 self.configuration.curr_sdk_machine = self.sdk_machine_combo.get_active_text()
1300 md5 = self.config_md5()
1301 self.settings_changed = (self.md5 != md5)
1302
1303#
1304# DeployImageDialog
1305#
1306class DeployImageDialog (CrumbsDialog):
1307
1308 __dummy_usb__ = "--select a usb drive--"
1309
1310 def __init__(self, title, image_path, parent, flags, buttons=None, standalone=False):
1311 super(DeployImageDialog, self).__init__(title, parent, flags, buttons)
1312
1313 self.image_path = image_path
1314 self.standalone = standalone
1315
1316 self.create_visual_elements()
1317 self.connect("response", self.response_cb)
1318
1319 def create_visual_elements(self):
1320 self.set_size_request(600, 400)
1321 label = gtk.Label()
1322 label.set_alignment(0.0, 0.5)
1323 markup = "<span font_desc='12'>The image to be written into usb drive:</span>"
1324 label.set_markup(markup)
1325 self.vbox.pack_start(label, expand=False, fill=False, padding=2)
1326
1327 table = gtk.Table(2, 10, False)
1328 table.set_col_spacings(5)
1329 table.set_row_spacings(5)
1330 self.vbox.pack_start(table, expand=True, fill=True)
1331
1332 scroll = gtk.ScrolledWindow()
1333 scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
1334 scroll.set_shadow_type(gtk.SHADOW_IN)
1335 tv = gtk.TextView()
1336 tv.set_editable(False)
1337 tv.set_wrap_mode(gtk.WRAP_WORD)
1338 tv.set_cursor_visible(False)
1339 self.buf = gtk.TextBuffer()
1340 self.buf.set_text(self.image_path)
1341 tv.set_buffer(self.buf)
1342 scroll.add(tv)
1343 table.attach(scroll, 0, 10, 0, 1)
1344
1345 # There are 2 ways to use DeployImageDialog
1346 # One way is that called by HOB when the 'Deploy Image' button is clicked
1347 # The other way is that called by a standalone script.
1348 # Following block of codes handles the latter way. It adds a 'Select Image' button and
1349 # emit a signal when the button is clicked.
1350 if self.standalone:
1351 gobject.signal_new("select_image_clicked", self, gobject.SIGNAL_RUN_FIRST,
1352 gobject.TYPE_NONE, ())
1353 icon = gtk.Image()
1354 pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_IMAGES_DISPLAY_FILE)
1355 icon.set_from_pixbuf(pix_buffer)
1356 button = gtk.Button("Select Image")
1357 button.set_image(icon)
1358 #button.set_size_request(140, 50)
1359 table.attach(button, 9, 10, 1, 2, gtk.FILL, 0, 0, 0)
1360 button.connect("clicked", self.select_image_button_clicked_cb)
1361
1362 separator = gtk.HSeparator()
1363 self.vbox.pack_start(separator, expand=False, fill=False, padding=10)
1364
1365 self.usb_desc = gtk.Label()
1366 self.usb_desc.set_alignment(0.0, 0.5)
1367 markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>"
1368 self.usb_desc.set_markup(markup)
1369
1370 self.usb_combo = gtk.combo_box_new_text()
1371 self.usb_combo.connect("changed", self.usb_combo_changed_cb)
1372 model = self.usb_combo.get_model()
1373 model.clear()
1374 self.usb_combo.append_text(self.__dummy_usb__)
1375 for usb in self.find_all_usb_devices():
1376 self.usb_combo.append_text("/dev/" + usb)
1377 self.usb_combo.set_active(0)
1378 self.vbox.pack_start(self.usb_combo, expand=False, fill=False)
1379 self.vbox.pack_start(self.usb_desc, expand=False, fill=False, padding=2)
1380
1381 self.progress_bar = HobProgressBar()
1382 self.vbox.pack_start(self.progress_bar, expand=False, fill=False)
1383 separator = gtk.HSeparator()
1384 self.vbox.pack_start(separator, expand=False, fill=True, padding=10)
1385
1386 self.vbox.show_all()
1387 self.progress_bar.hide()
1388
1389 def set_image_text_buffer(self, image_path):
1390 self.buf.set_text(image_path)
1391
1392 def set_image_path(self, image_path):
1393 self.image_path = image_path
1394
1395 def popen_read(self, cmd):
1396 tmpout, errors = bb.process.run("%s" % cmd)
1397 return tmpout.strip()
1398
1399 def find_all_usb_devices(self):
1400 usb_devs = [ os.readlink(u)
1401 for u in glob.glob('/dev/disk/by-id/usb*')
1402 if not re.search(r'part\d+', u) ]
1403 return [ '%s' % u[u.rfind('/')+1:] for u in usb_devs ]
1404
1405 def get_usb_info(self, dev):
1406 return "%s %s" % \
1407 (self.popen_read('cat /sys/class/block/%s/device/vendor' % dev),
1408 self.popen_read('cat /sys/class/block/%s/device/model' % dev))
1409
1410 def select_image_button_clicked_cb(self, button):
1411 self.emit('select_image_clicked')
1412
1413 def usb_combo_changed_cb(self, usb_combo):
1414 combo_item = self.usb_combo.get_active_text()
1415 if not combo_item or combo_item == self.__dummy_usb__:
1416 markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>"
1417 self.usb_desc.set_markup(markup)
1418 else:
1419 markup = "<span font_desc='12'>" + self.get_usb_info(combo_item.lstrip("/dev/")) + "</span>"
1420 self.usb_desc.set_markup(markup)
1421
1422 def response_cb(self, dialog, response_id):
1423 if response_id == gtk.RESPONSE_YES:
1424 lbl = ''
1425 combo_item = self.usb_combo.get_active_text()
1426 if combo_item and combo_item != self.__dummy_usb__ and self.image_path:
1427 cmdline = bb.ui.crumbs.utils.which_terminal()
1428 if cmdline:
1429 tmpfile = tempfile.NamedTemporaryFile()
1430 cmdline += "\"sudo dd if=" + self.image_path + \
1431 " of=" + combo_item + "; echo $? > " + tmpfile.name + "\""
1432 subprocess.call(shlex.split(cmdline))
1433
1434 if int(tmpfile.readline().strip()) == 0:
1435 lbl = "<b>Deploy image successfully.</b>"
1436 else:
1437 lbl = "<b>Failed to deploy image.</b>\nPlease check image <b>%s</b> exists and USB device <b>%s</b> is writable." % (self.image_path, combo_item)
1438 tmpfile.close()
1439 else:
1440 if not self.image_path:
1441 lbl = "<b>No selection made.</b>\nYou have not selected an image to deploy."
1442 else:
1443 lbl = "<b>No selection made.</b>\nYou have not selected a USB device."
1444 if len(lbl):
1445 crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
1446 button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
1447 HobButton.style_button(button)
1448 crumbs_dialog.run()
1449 crumbs_dialog.destroy()
1450
1451 def update_progress_bar(self, title, fraction, status=None):
1452 self.progress_bar.update(fraction)
1453 self.progress_bar.set_title(title)
1454 self.progress_bar.set_rcstyle(status)
1455
1456 def write_file(self, ifile, ofile):
1457 self.progress_bar.reset()
1458 self.progress_bar.show()
1459
1460 f_from = os.open(ifile, os.O_RDONLY)
1461 f_to = os.open(ofile, os.O_WRONLY)
1462
1463 total_size = os.stat(ifile).st_size
1464 written_size = 0
1465
1466 while True:
1467 buf = os.read(f_from, 1024*1024)
1468 if not buf:
1469 break
1470 os.write(f_to, buf)
1471 written_size += 1024*1024
1472 self.update_progress_bar("Writing to usb:", written_size * 1.0/total_size)
1473
1474 self.update_progress_bar("Writing completed:", 1.0)
1475 os.close(f_from)
1476 os.close(f_to)
1477 self.progress_bar.hide()
1478
1479class CellRendererPixbufActivatable(gtk.CellRendererPixbuf):
1480 """
1481 A custom CellRenderer implementation which is activatable
1482 so that we can handle user clicks
1483 """
1484 __gsignals__ = { 'clicked' : (gobject.SIGNAL_RUN_LAST,
1485 gobject.TYPE_NONE,
1486 (gobject.TYPE_STRING,)), }
1487
1488 def __init__(self):
1489 gtk.CellRendererPixbuf.__init__(self)
1490 self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
1491 self.set_property('follow-state', True)
1492
1493 """
1494 Respond to a user click on a cell
1495 """
1496 def do_activate(self, even, widget, path, background_area, cell_area, flags):
1497 self.emit('clicked', path)
1498
1499#
1500# LayerSelectionDialog
1501#
1502class LayerSelectionDialog (CrumbsDialog):
1503
1504 TARGETS = [
1505 ("MY_TREE_MODEL_ROW", gtk.TARGET_SAME_WIDGET, 0),
1506 ("text/plain", 0, 1),
1507 ("TEXT", 0, 2),
1508 ("STRING", 0, 3),
1509 ]
1510
1511 def gen_label_widget(self, content):
1512 label = gtk.Label()
1513 label.set_alignment(0, 0)
1514 label.set_markup(content)
1515 label.show()
1516 return label
1517
1518 def layer_widget_toggled_cb(self, cell, path, layer_store):
1519 name = layer_store[path][0]
1520 toggle = not layer_store[path][1]
1521 layer_store[path][1] = toggle
1522
1523 def layer_widget_add_clicked_cb(self, action, layer_store, parent):
1524 dialog = gtk.FileChooserDialog("Add new layer", parent,
1525 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
1526 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1527 HobAltButton.style_button(button)
1528 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1529 HobButton.style_button(button)
1530 label = gtk.Label("Select the layer you wish to add")
1531 label.show()
1532 dialog.set_extra_widget(label)
1533 response = dialog.run()
1534 path = dialog.get_filename()
1535 dialog.destroy()
1536
1537 lbl = "<b>Error</b>\nUnable to load layer <i>%s</i> because " % path
1538 if response == gtk.RESPONSE_YES:
1539 import os
1540 import os.path
1541 layers = []
1542 it = layer_store.get_iter_first()
1543 while it:
1544 layers.append(layer_store.get_value(it, 0))
1545 it = layer_store.iter_next(it)
1546
1547 if not path:
1548 lbl += "it is an invalid path."
1549 elif not os.path.exists(path+"/conf/layer.conf"):
1550 lbl += "there is no layer.conf inside the directory."
1551 elif path in layers:
1552 lbl += "it is already in loaded layers."
1553 else:
1554 layer_store.append([path])
1555 return
1556 dialog = CrumbsMessageDialog(parent, lbl)
1557 dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
1558 response = dialog.run()
1559 dialog.destroy()
1560
1561 def layer_widget_del_clicked_cb(self, action, tree_selection, layer_store):
1562 model, iter = tree_selection.get_selected()
1563 if iter:
1564 layer_store.remove(iter)
1565
1566
1567 def gen_layer_widget(self, layers, layers_avail, window, tooltip=""):
1568 hbox = gtk.HBox(False, 6)
1569
1570 layer_tv = gtk.TreeView()
1571 layer_tv.set_rules_hint(True)
1572 layer_tv.set_headers_visible(False)
1573 tree_selection = layer_tv.get_selection()
1574 tree_selection.set_mode(gtk.SELECTION_SINGLE)
1575
1576 # Allow enable drag and drop of rows including row move
1577 layer_tv.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
1578 self.TARGETS,
1579 gtk.gdk.ACTION_DEFAULT|
1580 gtk.gdk.ACTION_MOVE)
1581 layer_tv.enable_model_drag_dest(self.TARGETS,
1582 gtk.gdk.ACTION_DEFAULT)
1583 layer_tv.connect("drag_data_get", self.drag_data_get_cb)
1584 layer_tv.connect("drag_data_received", self.drag_data_received_cb)
1585
1586 col0= gtk.TreeViewColumn('Path')
1587 cell0 = gtk.CellRendererText()
1588 cell0.set_padding(5,2)
1589 col0.pack_start(cell0, True)
1590 col0.set_cell_data_func(cell0, self.draw_layer_path_cb)
1591 layer_tv.append_column(col0)
1592
1593 scroll = gtk.ScrolledWindow()
1594 scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
1595 scroll.set_shadow_type(gtk.SHADOW_IN)
1596 scroll.add(layer_tv)
1597
1598 table_layer = gtk.Table(2, 10, False)
1599 hbox.pack_start(table_layer, expand=True, fill=True)
1600
1601 table_layer.attach(scroll, 0, 10, 0, 1)
1602
1603 layer_store = gtk.ListStore(gobject.TYPE_STRING)
1604 for layer in layers:
1605 layer_store.append([layer])
1606
1607 col1 = gtk.TreeViewColumn('Enabled')
1608 layer_tv.append_column(col1)
1609
1610 cell1 = CellRendererPixbufActivatable()
1611 cell1.set_fixed_size(-1,35)
1612 cell1.connect("clicked", self.del_cell_clicked_cb, layer_store)
1613 col1.pack_start(cell1, True)
1614 col1.set_cell_data_func(cell1, self.draw_delete_button_cb, layer_tv)
1615
1616 add_button = gtk.Button()
1617 add_button.set_relief(gtk.RELIEF_NONE)
1618 box = gtk.HBox(False, 6)
1619 box.show()
1620 add_button.add(box)
1621 add_button.connect("enter-notify-event", self.add_hover_cb)
1622 add_button.connect("leave-notify-event", self.add_leave_cb)
1623 self.im = gtk.Image()
1624 self.im.set_from_file(hic.ICON_INDI_ADD_FILE)
1625 self.im.show()
1626 box.pack_start(self.im, expand=False, fill=False, padding=6)
1627 lbl = gtk.Label("Add layer")
1628 lbl.set_alignment(0.0, 0.5)
1629 lbl.show()
1630 box.pack_start(lbl, expand=True, fill=True, padding=6)
1631 add_button.connect("clicked", self.layer_widget_add_clicked_cb, layer_store, window)
1632 table_layer.attach(add_button, 0, 10, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 6)
1633 layer_tv.set_model(layer_store)
1634
1635 hbox.show_all()
1636
1637 return hbox, layer_store
1638
1639 def drag_data_get_cb(self, treeview, context, selection, target_id, etime):
1640 treeselection = treeview.get_selection()
1641 model, iter = treeselection.get_selected()
1642 data = model.get_value(iter, 0)
1643 selection.set(selection.target, 8, data)
1644
1645 def drag_data_received_cb(self, treeview, context, x, y, selection, info, etime):
1646 model = treeview.get_model()
1647 data = selection.data
1648 drop_info = treeview.get_dest_row_at_pos(x, y)
1649 if drop_info:
1650 path, position = drop_info
1651 iter = model.get_iter(path)
1652 if (position == gtk.TREE_VIEW_DROP_BEFORE or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
1653 model.insert_before(iter, [data])
1654 else:
1655 model.insert_after(iter, [data])
1656 else:
1657 model.append([data])
1658 if context.action == gtk.gdk.ACTION_MOVE:
1659 context.finish(True, True, etime)
1660 return
1661
1662 def add_hover_cb(self, button, event):
1663 self.im.set_from_file(hic.ICON_INDI_ADD_HOVER_FILE)
1664
1665 def add_leave_cb(self, button, event):
1666 self.im.set_from_file(hic.ICON_INDI_ADD_FILE)
1667
1668 def __init__(self, title, layers, layers_non_removable, all_layers, parent, flags, buttons=None):
1669 super(LayerSelectionDialog, self).__init__(title, parent, flags, buttons)
1670
1671 # class members from other objects
1672 self.layers = layers
1673 self.layers_non_removable = layers_non_removable
1674 self.all_layers = all_layers
1675 self.layers_changed = False
1676
1677 # icon for remove button in TreeView
1678 im = gtk.Image()
1679 im.set_from_file(hic.ICON_INDI_REMOVE_FILE)
1680 self.rem_icon = im.get_pixbuf()
1681
1682 # class members for internal use
1683 self.layer_store = None
1684
1685 # create visual elements on the dialog
1686 self.create_visual_elements()
1687 self.connect("response", self.response_cb)
1688
1689 def create_visual_elements(self):
1690 layer_widget, self.layer_store = self.gen_layer_widget(self.layers, self.all_layers, self, None)
1691 layer_widget.set_size_request(450, 250)
1692 self.vbox.pack_start(layer_widget, expand=True, fill=True)
1693 self.show_all()
1694
1695 def response_cb(self, dialog, response_id):
1696 model = self.layer_store
1697 it = model.get_iter_first()
1698 layers = []
1699 while it:
1700 layers.append(model.get_value(it, 0))
1701 it = model.iter_next(it)
1702
1703 self.layers_changed = (self.layers != layers)
1704 self.layers = layers
1705
1706 """
1707 A custom cell_data_func to draw a delete 'button' in the TreeView for layers
1708 other than the meta layer. The deletion of which is prevented so that the
1709 user can't shoot themselves in the foot too badly.
1710 """
1711 def draw_delete_button_cb(self, col, cell, model, it, tv):
1712 path = model.get_value(it, 0)
1713 if path in self.layers_non_removable:
1714 cell.set_sensitive(False)
1715 cell.set_property('pixbuf', None)
1716 cell.set_property('mode', gtk.CELL_RENDERER_MODE_INERT)
1717 else:
1718 cell.set_property('pixbuf', self.rem_icon)
1719 cell.set_sensitive(True)
1720 cell.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
1721
1722 return True
1723
1724 """
1725 A custom cell_data_func to write an extra message into the layer path cell
1726 for the meta layer. We should inform the user that they can't remove it for
1727 their own safety.
1728 """
1729 def draw_layer_path_cb(self, col, cell, model, it):
1730 path = model.get_value(it, 0)
1731 if path in self.layers_non_removable:
1732 cell.set_property('markup', "<b>It cannot be removed</b>\n%s" % path)
1733 else:
1734 cell.set_property('text', path)
1735
1736 def del_cell_clicked_cb(self, cell, path, model):
1737 it = model.get_iter_from_string(path)
1738 model.remove(it)
1739
1740class ImageSelectionDialog (CrumbsDialog):
1741
1742 __columns__ = [{
1743 'col_name' : 'Image name',
1744 'col_id' : 0,
1745 'col_style': 'text',
1746 'col_min' : 400,
1747 'col_max' : 400
1748 }, {
1749 'col_name' : 'Select',
1750 'col_id' : 1,
1751 'col_style': 'radio toggle',
1752 'col_min' : 160,
1753 'col_max' : 160
1754 }]
1755
1756
1757 def __init__(self, image_folder, image_types, title, parent, flags, buttons=None, image_extension = {}):
1758 super(ImageSelectionDialog, self).__init__(title, parent, flags, buttons)
1759 self.connect("response", self.response_cb)
1760
1761 self.image_folder = image_folder
1762 self.image_types = image_types
1763 self.image_list = []
1764 self.image_names = []
1765 self.image_extension = image_extension
1766
1767 # create visual elements on the dialog
1768 self.create_visual_elements()
1769
1770 self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
1771 self.fill_image_store()
1772
1773 def create_visual_elements(self):
1774 hbox = gtk.HBox(False, 6)
1775
1776 self.vbox.pack_start(hbox, expand=False, fill=False)
1777
1778 entry = gtk.Entry()
1779 entry.set_text(self.image_folder)
1780 table = gtk.Table(1, 10, True)
1781 table.set_size_request(560, -1)
1782 hbox.pack_start(table, expand=False, fill=False)
1783 table.attach(entry, 0, 9, 0, 1)
1784 image = gtk.Image()
1785 image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
1786 open_button = gtk.Button()
1787 open_button.set_image(image)
1788 open_button.connect("clicked", self.select_path_cb, self, entry)
1789 table.attach(open_button, 9, 10, 0, 1)
1790
1791 self.image_table = HobViewTable(self.__columns__)
1792 self.image_table.set_size_request(-1, 300)
1793 self.image_table.connect("toggled", self.toggled_cb)
1794 self.image_table.connect_group_selection(self.table_selected_cb)
1795 self.image_table.connect("row-activated", self.row_actived_cb)
1796 self.vbox.pack_start(self.image_table, expand=True, fill=True)
1797
1798 self.show_all()
1799
1800 def change_image_cb(self, model, path, columnid):
1801 if not model:
1802 return
1803 iter = model.get_iter_first()
1804 while iter:
1805 rowpath = model.get_path(iter)
1806 model[rowpath][columnid] = False
1807 iter = model.iter_next(iter)
1808
1809 model[path][columnid] = True
1810
1811 def toggled_cb(self, table, cell, path, columnid, tree):
1812 model = tree.get_model()
1813 self.change_image_cb(model, path, columnid)
1814
1815 def table_selected_cb(self, selection):
1816 model, paths = selection.get_selected_rows()
1817 if paths:
1818 self.change_image_cb(model, paths[0], 1)
1819
1820 def row_actived_cb(self, tab, model, path):
1821 self.change_image_cb(model, path, 1)
1822 self.emit('response', gtk.RESPONSE_YES)
1823
1824 def select_path_cb(self, action, parent, entry):
1825 dialog = gtk.FileChooserDialog("", parent,
1826 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
1827 text = entry.get_text()
1828 dialog.set_current_folder(text if len(text) > 0 else os.getcwd())
1829 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
1830 HobAltButton.style_button(button)
1831 button = dialog.add_button("Open", gtk.RESPONSE_YES)
1832 HobButton.style_button(button)
1833 response = dialog.run()
1834 if response == gtk.RESPONSE_YES:
1835 path = dialog.get_filename()
1836 entry.set_text(path)
1837 self.image_folder = path
1838 self.fill_image_store()
1839
1840 dialog.destroy()
1841
1842 def fill_image_store(self):
1843 self.image_list = []
1844 self.image_store.clear()
1845 imageset = set()
1846 for root, dirs, files in os.walk(self.image_folder):
1847 # ignore the sub directories
1848 dirs[:] = []
1849 for f in files:
1850 for image_type in self.image_types:
1851 if image_type in self.image_extension:
1852 real_types = self.image_extension[image_type]
1853 else:
1854 real_types = [image_type]
1855 for real_image_type in real_types:
1856 if f.endswith('.' + real_image_type):
1857 imageset.add(f.rsplit('.' + real_image_type)[0].rsplit('.rootfs')[0])
1858 self.image_list.append(f)
1859
1860 for image in imageset:
1861 self.image_store.set(self.image_store.append(), 0, image, 1, False)
1862
1863 self.image_table.set_model(self.image_store)
1864
1865 def response_cb(self, dialog, response_id):
1866 self.image_names = []
1867 if response_id == gtk.RESPONSE_YES:
1868 iter = self.image_store.get_iter_first()
1869 while iter:
1870 path = self.image_store.get_path(iter)
1871 if self.image_store[path][1]:
1872 for f in self.image_list:
1873 if f.startswith(self.image_store[path][0] + '.'):
1874 self.image_names.append(f)
1875 break
1876 iter = self.image_store.iter_next(iter)
1877
1878#
1879# ProxyDetailsDialog
1880#
1881class ProxyDetailsDialog (CrumbsDialog):
1882
1883 def __init__(self, title, user, passwd, parent, flags, buttons=None):
1884 super(ProxyDetailsDialog, self).__init__(title, parent, flags, buttons)
1885 self.connect("response", self.response_cb)
1886
1887 self.auth = not (user == None or passwd == None or user == "")
1888 self.user = user or ""
1889 self.passwd = passwd or ""
1890
1891 # create visual elements on the dialog
1892 self.create_visual_elements()
1893
1894 def create_visual_elements(self):
1895 self.auth_checkbox = gtk.CheckButton("Use authentication")
1896 self.auth_checkbox.set_tooltip_text("Check this box to set the username and the password")
1897 self.auth_checkbox.set_active(self.auth)
1898 self.auth_checkbox.connect("toggled", self.auth_checkbox_toggled_cb)
1899 self.vbox.pack_start(self.auth_checkbox, expand=False, fill=False)
1900
1901 hbox = gtk.HBox(False, 6)
1902 self.user_label = gtk.Label("Username:")
1903 self.user_text = gtk.Entry()
1904 self.user_text.set_text(self.user)
1905 hbox.pack_start(self.user_label, expand=False, fill=False)
1906 hbox.pack_end(self.user_text, expand=False, fill=False)
1907 self.vbox.pack_start(hbox, expand=False, fill=False)
1908
1909 hbox = gtk.HBox(False, 6)
1910 self.passwd_label = gtk.Label("Password:")
1911 self.passwd_text = gtk.Entry()
1912 self.passwd_text.set_text(self.passwd)
1913 hbox.pack_start(self.passwd_label, expand=False, fill=False)
1914 hbox.pack_end(self.passwd_text, expand=False, fill=False)
1915 self.vbox.pack_start(hbox, expand=False, fill=False)
1916
1917 self.refresh_auth_components()
1918 self.show_all()
1919
1920 def refresh_auth_components(self):
1921 self.user_label.set_sensitive(self.auth)
1922 self.user_text.set_editable(self.auth)
1923 self.user_text.set_sensitive(self.auth)
1924 self.passwd_label.set_sensitive(self.auth)
1925 self.passwd_text.set_editable(self.auth)
1926 self.passwd_text.set_sensitive(self.auth)
1927
1928 def auth_checkbox_toggled_cb(self, button):
1929 self.auth = self.auth_checkbox.get_active()
1930 self.refresh_auth_components()
1931
1932 def response_cb(self, dialog, response_id):
1933 if response_id == gtk.RESPONSE_OK:
1934 if self.auth:
1935 self.user = self.user_text.get_text()
1936 self.passwd = self.passwd_text.get_text()
1937 else:
1938 self.user = None
1939 self.passwd = None
1940
1941
1942#
1943# OpeningLogDialog
1944#
1945class OpeningLogDialog (CrumbsDialog):
1946
1947 def __init__(self, title, parent, flags, buttons=None):
1948 super(OpeningLogDialog, self).__init__(title, parent, flags, buttons)
1949
1950 self.running = False
1951 # create visual elements on the dialog
1952 self.create_visual_elements()
1953
1954 def start(self):
1955 if not self.running:
1956 self.running = True
1957 gobject.timeout_add(100, self.pulse)
1958
1959 def pulse(self):
1960 self.progress_bar.pulse()
1961 return self.running
1962
1963 def create_visual_elements(self):
1964 hbox = gtk.HBox(False, 12)
1965 self.user_label = gtk.Label("The log will open in a text editor")
1966 hbox.pack_start(self.user_label, expand=False, fill=False)
1967 self.vbox.pack_start(hbox, expand=False, fill=False)
1968
1969 hbox = gtk.HBox(False, 12)
1970 # Progress bar
1971 self.progress_bar = HobProgressBar()
1972 hbox.pack_start(self.progress_bar)
1973 self.start()
1974 self.vbox.pack_start(hbox, expand=False, fill=False)
1975
1976 button = self.add_button("Cancel", gtk.RESPONSE_CANCEL)
1977 HobAltButton.style_button(button)
1978 self.show_all()