summaryrefslogtreecommitdiffstats
path: root/bitbake/lib/bb/ui/crumbs/hig
diff options
context:
space:
mode:
authorBogdan Marinescu <bogdan.a.marinescu@intel.com>2013-01-10 13:08:02 +0200
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-01-16 12:51:33 +0000
commit7bfb98568a1d7ba8dbd95332d65cd19faec6c725 (patch)
tree6a6d18d67a80e8ca862435d09c3ae63215659c7a /bitbake/lib/bb/ui/crumbs/hig
parenta746719a46e9277a118fd7d4a6342bb667034132 (diff)
downloadpoky-7bfb98568a1d7ba8dbd95332d65cd19faec6c725.tar.gz
bitbake: hig.py: refactor into individual components
Since hig.py was becoming too large (which impacted maintenance and operations like git merges) it was split into individual files for the classes that were implemented in hig.py. hig is now a Python package (lib/bb/ui/crumbs/hig/). The patch was tested by building core-image-basic/qemux86 in Hob and accessing the various UI elements implemented in hig. Note that the patch does not change the functionality of Hob in any way, it's just a code refactoring that should make life a bit easier for Hob developers. [YOCTO #3200] (Bitbake rev: a7a2b730f915cafe7aa30539622dd1ca64ae41f5) Signed-off-by: Bogdan Marinescu <bogdan.a.marinescu@intel.com> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'bitbake/lib/bb/ui/crumbs/hig')
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/__init__.py0
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py336
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py44
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py95
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py215
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py172
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py296
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/openinglogdialog.py68
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py90
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py216
-rw-r--r--bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py722
11 files changed, 2254 insertions, 0 deletions
diff --git a/bitbake/lib/bb/ui/crumbs/hig/__init__.py b/bitbake/lib/bb/ui/crumbs/hig/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/__init__.py
diff --git a/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py b/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py
new file mode 100644
index 0000000000..f5397c3ac0
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/advancedsettingsdialog.py
@@ -0,0 +1,336 @@
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 gtk
24import hashlib
25from bb.ui.crumbs.hobwidget import HobInfoButton, HobButton
26from bb.ui.crumbs.progressbar import HobProgressBar
27from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper
28from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
29from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
30from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog
31
32"""
33The following are convenience classes for implementing GNOME HIG compliant
34BitBake GUI's
35In summary: spacing = 12px, border-width = 6px
36"""
37
38class AdvancedSettingsDialog (CrumbsDialog, SettingsUIHelper):
39
40 def details_cb(self, button, parent, protocol):
41 dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
42 user = self.configuration.proxies[protocol][1],
43 passwd = self.configuration.proxies[protocol][2],
44 parent = parent,
45 flags = gtk.DIALOG_MODAL
46 | gtk.DIALOG_DESTROY_WITH_PARENT
47 | gtk.DIALOG_NO_SEPARATOR)
48 dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
49 response = dialog.run()
50 if response == gtk.RESPONSE_OK:
51 self.configuration.proxies[protocol][1] = dialog.user
52 self.configuration.proxies[protocol][2] = dialog.passwd
53 self.refresh_proxy_components()
54 dialog.destroy()
55
56 def set_save_button(self, button):
57 self.save_button = button
58
59 def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
60 combo_item = self.rootfs_combo.get_active_text()
61 modified = False
62 for child in check_hbox.get_children():
63 if isinstance(child, gtk.CheckButton):
64 check_hbox.remove(child)
65 modified = True
66 for format in all_package_format:
67 if format != combo_item:
68 check_button = gtk.CheckButton(format)
69 check_hbox.pack_start(check_button, expand=False, fill=False)
70 modified = True
71 if modified:
72 check_hbox.remove(self.pkgfmt_info)
73 check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
74 check_hbox.show_all()
75
76 def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
77 pkgfmt_vbox = gtk.VBox(False, 6)
78
79 label = self.gen_label_widget("Root file system package format")
80 pkgfmt_vbox.pack_start(label, expand=False, fill=False)
81
82 rootfs_format = ""
83 if curr_package_format:
84 rootfs_format = curr_package_format.split()[0]
85
86 rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
87 pkgfmt_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
88
89 label = self.gen_label_widget("Additional package formats")
90 pkgfmt_vbox.pack_start(label, expand=False, fill=False)
91
92 check_hbox = gtk.HBox(False, 12)
93 pkgfmt_vbox.pack_start(check_hbox, expand=False, fill=False)
94 for format in all_package_format:
95 if format != rootfs_format:
96 check_button = gtk.CheckButton(format)
97 is_active = (format in curr_package_format.split())
98 check_button.set_active(is_active)
99 check_hbox.pack_start(check_button, expand=False, fill=False)
100
101 self.pkgfmt_info = HobInfoButton(tooltip_extra, self)
102 check_hbox.pack_start(self.pkgfmt_info, expand=False, fill=False)
103
104 rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
105
106 pkgfmt_vbox.show_all()
107
108 return pkgfmt_vbox, rootfs_combo, check_hbox
109
110 def __init__(self, title, configuration, all_image_types,
111 all_package_formats, all_distros, all_sdk_machines,
112 max_threads, parent, flags, buttons=None):
113 super(AdvancedSettingsDialog, self).__init__(title, parent, flags, buttons)
114
115 # class members from other objects
116 # bitbake settings from Builder.Configuration
117 self.configuration = configuration
118 self.image_types = all_image_types
119 self.all_package_formats = all_package_formats
120 self.all_distros = all_distros[:]
121 self.all_sdk_machines = all_sdk_machines
122 self.max_threads = max_threads
123
124 # class members for internal use
125 self.distro_combo = None
126 self.dldir_text = None
127 self.sstatedir_text = None
128 self.sstatemirror_text = None
129 self.bb_spinner = None
130 self.pmake_spinner = None
131 self.rootfs_size_spinner = None
132 self.extra_size_spinner = None
133 self.gplv3_checkbox = None
134 self.toolchain_checkbox = None
135 self.image_types_checkbuttons = {}
136
137 self.md5 = self.config_md5()
138 self.settings_changed = False
139
140 # create visual elements on the dialog
141 self.save_button = None
142 self.create_visual_elements()
143 self.connect("response", self.response_cb)
144
145 def _get_sorted_value(self, var):
146 return " ".join(sorted(str(var).split())) + "\n"
147
148 def config_md5(self):
149 data = ""
150 data += ("PACKAGE_CLASSES: " + self.configuration.curr_package_format + '\n')
151 data += ("DISTRO: " + self._get_sorted_value(self.configuration.curr_distro))
152 data += ("IMAGE_ROOTFS_SIZE: " + self._get_sorted_value(self.configuration.image_rootfs_size))
153 data += ("IMAGE_EXTRA_SIZE: " + self._get_sorted_value(self.configuration.image_extra_size))
154 data += ("INCOMPATIBLE_LICENSE: " + self._get_sorted_value(self.configuration.incompat_license))
155 data += ("SDK_MACHINE: " + self._get_sorted_value(self.configuration.curr_sdk_machine))
156 data += ("TOOLCHAIN_BUILD: " + self._get_sorted_value(self.configuration.toolchain_build))
157 data += ("IMAGE_FSTYPES: " + self._get_sorted_value(self.configuration.image_fstypes))
158 return hashlib.md5(data).hexdigest()
159
160 def create_visual_elements(self):
161 self.nb = gtk.Notebook()
162 self.nb.set_show_tabs(True)
163 self.nb.append_page(self.create_image_types_page(), gtk.Label("Image types"))
164 self.nb.append_page(self.create_output_page(), gtk.Label("Output"))
165 self.nb.set_current_page(0)
166 self.vbox.pack_start(self.nb, expand=True, fill=True)
167 self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
168
169 self.show_all()
170
171 def get_num_checked_image_types(self):
172 total = 0
173 for b in self.image_types_checkbuttons.values():
174 if b.get_active():
175 total = total + 1
176 return total
177
178 def set_save_button_state(self):
179 if self.save_button:
180 self.save_button.set_sensitive(self.get_num_checked_image_types() > 0)
181
182 def image_type_checkbutton_clicked_cb(self, button):
183 self.set_save_button_state()
184 if self.get_num_checked_image_types() == 0:
185 # Show an error dialog
186 lbl = "<b>Select an image type</b>\n\nYou need to select at least one image type."
187 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING)
188 button = dialog.add_button("OK", gtk.RESPONSE_OK)
189 HobButton.style_button(button)
190 response = dialog.run()
191 dialog.destroy()
192
193 def create_image_types_page(self):
194 main_vbox = gtk.VBox(False, 16)
195 main_vbox.set_border_width(6)
196
197 advanced_vbox = gtk.VBox(False, 6)
198 advanced_vbox.set_border_width(6)
199
200 distro_vbox = gtk.VBox(False, 6)
201 label = self.gen_label_widget("Distro:")
202 tooltip = "Selects the Yocto Project distribution you want"
203 try:
204 i = self.all_distros.index( "defaultsetup" )
205 except ValueError:
206 i = -1
207 if i != -1:
208 self.all_distros[ i ] = "Default"
209 if self.configuration.curr_distro == "defaultsetup":
210 self.configuration.curr_distro = "Default"
211 distro_widget, self.distro_combo = self.gen_combo_widget(self.configuration.curr_distro, self.all_distros, tooltip)
212 distro_vbox.pack_start(label, expand=False, fill=False)
213 distro_vbox.pack_start(distro_widget, expand=False, fill=False)
214 main_vbox.pack_start(distro_vbox, expand=False, fill=False)
215
216
217 rows = (len(self.image_types)+1)/3
218 table = gtk.Table(rows + 1, 10, True)
219 advanced_vbox.pack_start(table, expand=False, fill=False)
220
221 tooltip = "Image file system types you want."
222 info = HobInfoButton(tooltip, self)
223 label = self.gen_label_widget("Image types:")
224 align = gtk.Alignment(0, 0.5, 0, 0)
225 table.attach(align, 0, 4, 0, 1)
226 align.add(label)
227 table.attach(info, 4, 5, 0, 1)
228
229 i = 1
230 j = 1
231 for image_type in sorted(self.image_types):
232 self.image_types_checkbuttons[image_type] = gtk.CheckButton(image_type)
233 self.image_types_checkbuttons[image_type].connect("toggled", self.image_type_checkbutton_clicked_cb)
234 article = ""
235 if image_type.startswith(("a", "e", "i", "o", "u")):
236 article = "n"
237 self.image_types_checkbuttons[image_type].set_tooltip_text("Build a%s %s image" % (article, image_type))
238 table.attach(self.image_types_checkbuttons[image_type], j - 1, j + 3, i, i + 1)
239 if image_type in self.configuration.image_fstypes.split():
240 self.image_types_checkbuttons[image_type].set_active(True)
241 i += 1
242 if i > rows:
243 i = 1
244 j = j + 4
245
246 main_vbox.pack_start(advanced_vbox, expand=False, fill=False)
247 self.set_save_button_state()
248
249 return main_vbox
250
251 def create_output_page(self):
252 advanced_vbox = gtk.VBox(False, 6)
253 advanced_vbox.set_border_width(6)
254
255 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Package format</span>'), expand=False, fill=False)
256 sub_vbox = gtk.VBox(False, 6)
257 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
258 tooltip_combo = "Selects the package format used to generate rootfs."
259 tooltip_extra = "Selects extra package formats to build"
260 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)
261 sub_vbox.pack_start(pkgfmt_widget, expand=False, fill=False)
262
263 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Image size</span>'), expand=False, fill=False)
264 sub_vbox = gtk.VBox(False, 6)
265 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
266 label = self.gen_label_widget("Image basic size (in MB)")
267 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\'."
268 rootfs_size_widget, self.rootfs_size_spinner = self.gen_spinner_widget(int(self.configuration.image_rootfs_size*1.0/1024), 0, 65536, tooltip)
269 sub_vbox.pack_start(label, expand=False, fill=False)
270 sub_vbox.pack_start(rootfs_size_widget, expand=False, fill=False)
271
272 sub_vbox = gtk.VBox(False, 6)
273 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
274 label = self.gen_label_widget("Additional free space (in MB)")
275 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."
276 extra_size_widget, self.extra_size_spinner = self.gen_spinner_widget(int(self.configuration.image_extra_size*1.0/1024), 0, 65536, tooltip)
277 sub_vbox.pack_start(label, expand=False, fill=False)
278 sub_vbox.pack_start(extra_size_widget, expand=False, fill=False)
279
280 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Licensing</span>'), expand=False, fill=False)
281 self.gplv3_checkbox = gtk.CheckButton("Exclude GPLv3 packages")
282 self.gplv3_checkbox.set_tooltip_text("Check this box to prevent GPLv3 packages from being included in your image")
283 if "GPLv3" in self.configuration.incompat_license.split():
284 self.gplv3_checkbox.set_active(True)
285 else:
286 self.gplv3_checkbox.set_active(False)
287 advanced_vbox.pack_start(self.gplv3_checkbox, expand=False, fill=False)
288
289 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Toolchain</span>'), expand=False, fill=False)
290 sub_hbox = gtk.HBox(False, 6)
291 advanced_vbox.pack_start(sub_hbox, expand=False, fill=False)
292 self.toolchain_checkbox = gtk.CheckButton("Build toolchain")
293 self.toolchain_checkbox.set_tooltip_text("Check this box to build the related toolchain with your image")
294 self.toolchain_checkbox.set_active(self.configuration.toolchain_build)
295 sub_hbox.pack_start(self.toolchain_checkbox, expand=False, fill=False)
296
297 tooltip = "Selects the host platform for which you want to run the toolchain"
298 sdk_machine_widget, self.sdk_machine_combo = self.gen_combo_widget(self.configuration.curr_sdk_machine, self.all_sdk_machines, tooltip)
299 sub_hbox.pack_start(sdk_machine_widget, expand=False, fill=False)
300
301 return advanced_vbox
302
303 def response_cb(self, dialog, response_id):
304 package_format = []
305 package_format.append(self.rootfs_combo.get_active_text())
306 for child in self.check_hbox:
307 if isinstance(child, gtk.CheckButton) and child.get_active():
308 package_format.append(child.get_label())
309 self.configuration.curr_package_format = " ".join(package_format)
310
311 distro = self.distro_combo.get_active_text()
312 if distro == "Default":
313 distro = "defaultsetup"
314 self.configuration.curr_distro = distro
315 self.configuration.image_rootfs_size = self.rootfs_size_spinner.get_value_as_int() * 1024
316 self.configuration.image_extra_size = self.extra_size_spinner.get_value_as_int() * 1024
317
318 self.configuration.image_fstypes = ""
319 for image_type in self.image_types:
320 if self.image_types_checkbuttons[image_type].get_active():
321 self.configuration.image_fstypes += (" " + image_type)
322 self.configuration.image_fstypes.strip()
323
324 if self.gplv3_checkbox.get_active():
325 if "GPLv3" not in self.configuration.incompat_license.split():
326 self.configuration.incompat_license += " GPLv3"
327 else:
328 if "GPLv3" in self.configuration.incompat_license.split():
329 self.configuration.incompat_license = self.configuration.incompat_license.split().remove("GPLv3")
330 self.configuration.incompat_license = " ".join(self.configuration.incompat_license or [])
331 self.configuration.incompat_license = self.configuration.incompat_license.strip()
332
333 self.configuration.toolchain_build = self.toolchain_checkbox.get_active()
334 self.configuration.curr_sdk_machine = self.sdk_machine_combo.get_active_text()
335 md5 = self.config_md5()
336 self.settings_changed = (self.md5 != md5)
diff --git a/bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py b/bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py
new file mode 100644
index 0000000000..c679f9a070
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py
@@ -0,0 +1,44 @@
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 gtk
24
25"""
26The following are convenience classes for implementing GNOME HIG compliant
27BitBake GUI's
28In summary: spacing = 12px, border-width = 6px
29"""
30
31class CrumbsDialog(gtk.Dialog):
32 """
33 A GNOME HIG compliant dialog widget.
34 Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons
35 """
36 def __init__(self, title="", parent=None, flags=0, buttons=None):
37 super(CrumbsDialog, self).__init__(title, parent, flags, buttons)
38
39 self.set_property("has-separator", False) # note: deprecated in 2.22
40
41 self.set_border_width(6)
42 self.vbox.set_property("spacing", 12)
43 self.action_area.set_property("spacing", 12)
44 self.action_area.set_property("border-width", 6)
diff --git a/bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py b/bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py
new file mode 100644
index 0000000000..097ce7b027
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py
@@ -0,0 +1,95 @@
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 glib
24import gtk
25from bb.ui.crumbs.hobwidget import HobIconChecker
26from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
27
28"""
29The following are convenience classes for implementing GNOME HIG compliant
30BitBake GUI's
31In summary: spacing = 12px, border-width = 6px
32"""
33
34class CrumbsMessageDialog(CrumbsDialog):
35 """
36 A GNOME HIG compliant dialog widget.
37 Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons
38 """
39 def __init__(self, parent=None, label="", icon=gtk.STOCK_INFO, msg=""):
40 super(CrumbsMessageDialog, self).__init__("", parent, gtk.DIALOG_MODAL)
41
42 self.set_border_width(6)
43 self.vbox.set_property("spacing", 12)
44 self.action_area.set_property("spacing", 12)
45 self.action_area.set_property("border-width", 6)
46
47 first_column = gtk.HBox(spacing=12)
48 first_column.set_property("border-width", 6)
49 first_column.show()
50 self.vbox.add(first_column)
51
52 self.icon = gtk.Image()
53 # We have our own Info icon which should be used in preference of the stock icon
54 self.icon_chk = HobIconChecker()
55 self.icon.set_from_stock(self.icon_chk.check_stock_icon(icon), gtk.ICON_SIZE_DIALOG)
56 self.icon.set_property("yalign", 0.00)
57 self.icon.show()
58 first_column.pack_start(self.icon, expand=False, fill=True, padding=0)
59
60 if 0 <= len(msg) < 200:
61 lbl = label + "%s" % glib.markup_escape_text(msg)
62 self.label_short = gtk.Label()
63 self.label_short.set_use_markup(True)
64 self.label_short.set_line_wrap(True)
65 self.label_short.set_markup(lbl)
66 self.label_short.set_property("yalign", 0.00)
67 self.label_short.show()
68 first_column.add(self.label_short)
69 else:
70 second_row = gtk.VBox(spacing=12)
71 second_row.set_property("border-width", 6)
72 self.label_long = gtk.Label()
73 self.label_long.set_use_markup(True)
74 self.label_long.set_line_wrap(True)
75 self.label_long.set_markup(label)
76 self.label_long.set_alignment(0.0, 0.0)
77 second_row.pack_start(self.label_long, expand=False, fill=False, padding=0)
78 self.label_long.show()
79 self.textWindow = gtk.ScrolledWindow()
80 self.textWindow.set_shadow_type(gtk.SHADOW_IN)
81 self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
82 self.msgView = gtk.TextView()
83 self.msgView.set_editable(False)
84 self.msgView.set_wrap_mode(gtk.WRAP_WORD)
85 self.msgView.set_cursor_visible(False)
86 self.msgView.set_size_request(300, 300)
87 self.buf = gtk.TextBuffer()
88 self.buf.set_text(msg)
89 self.msgView.set_buffer(self.buf)
90 self.textWindow.add(self.msgView)
91 self.msgView.show()
92 second_row.add(self.textWindow)
93 self.textWindow.show()
94 first_column.add(second_row)
95 second_row.show()
diff --git a/bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py b/bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py
new file mode 100644
index 0000000000..bc1efbbfaf
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py
@@ -0,0 +1,215 @@
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 gtk
25import gobject
26import os
27import re
28import shlex
29import subprocess
30import tempfile
31from bb.ui.crumbs.hobwidget import hic, HobButton
32from bb.ui.crumbs.progressbar import HobProgressBar
33import bb.ui.crumbs.utils
34import bb.process
35from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
36from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
37
38"""
39The following are convenience classes for implementing GNOME HIG compliant
40BitBake GUI's
41In summary: spacing = 12px, border-width = 6px
42"""
43
44class DeployImageDialog (CrumbsDialog):
45
46 __dummy_usb__ = "--select a usb drive--"
47
48 def __init__(self, title, image_path, parent, flags, buttons=None, standalone=False):
49 super(DeployImageDialog, self).__init__(title, parent, flags, buttons)
50
51 self.image_path = image_path
52 self.standalone = standalone
53
54 self.create_visual_elements()
55 self.connect("response", self.response_cb)
56
57 def create_visual_elements(self):
58 self.set_size_request(600, 400)
59 label = gtk.Label()
60 label.set_alignment(0.0, 0.5)
61 markup = "<span font_desc='12'>The image to be written into usb drive:</span>"
62 label.set_markup(markup)
63 self.vbox.pack_start(label, expand=False, fill=False, padding=2)
64
65 table = gtk.Table(2, 10, False)
66 table.set_col_spacings(5)
67 table.set_row_spacings(5)
68 self.vbox.pack_start(table, expand=True, fill=True)
69
70 scroll = gtk.ScrolledWindow()
71 scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
72 scroll.set_shadow_type(gtk.SHADOW_IN)
73 tv = gtk.TextView()
74 tv.set_editable(False)
75 tv.set_wrap_mode(gtk.WRAP_WORD)
76 tv.set_cursor_visible(False)
77 self.buf = gtk.TextBuffer()
78 self.buf.set_text(self.image_path)
79 tv.set_buffer(self.buf)
80 scroll.add(tv)
81 table.attach(scroll, 0, 10, 0, 1)
82
83 # There are 2 ways to use DeployImageDialog
84 # One way is that called by HOB when the 'Deploy Image' button is clicked
85 # The other way is that called by a standalone script.
86 # Following block of codes handles the latter way. It adds a 'Select Image' button and
87 # emit a signal when the button is clicked.
88 if self.standalone:
89 gobject.signal_new("select_image_clicked", self, gobject.SIGNAL_RUN_FIRST,
90 gobject.TYPE_NONE, ())
91 icon = gtk.Image()
92 pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_IMAGES_DISPLAY_FILE)
93 icon.set_from_pixbuf(pix_buffer)
94 button = gtk.Button("Select Image")
95 button.set_image(icon)
96 #button.set_size_request(140, 50)
97 table.attach(button, 9, 10, 1, 2, gtk.FILL, 0, 0, 0)
98 button.connect("clicked", self.select_image_button_clicked_cb)
99
100 separator = gtk.HSeparator()
101 self.vbox.pack_start(separator, expand=False, fill=False, padding=10)
102
103 self.usb_desc = gtk.Label()
104 self.usb_desc.set_alignment(0.0, 0.5)
105 markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>"
106 self.usb_desc.set_markup(markup)
107
108 self.usb_combo = gtk.combo_box_new_text()
109 self.usb_combo.connect("changed", self.usb_combo_changed_cb)
110 model = self.usb_combo.get_model()
111 model.clear()
112 self.usb_combo.append_text(self.__dummy_usb__)
113 for usb in self.find_all_usb_devices():
114 self.usb_combo.append_text("/dev/" + usb)
115 self.usb_combo.set_active(0)
116 self.vbox.pack_start(self.usb_combo, expand=False, fill=False)
117 self.vbox.pack_start(self.usb_desc, expand=False, fill=False, padding=2)
118
119 self.progress_bar = HobProgressBar()
120 self.vbox.pack_start(self.progress_bar, expand=False, fill=False)
121 separator = gtk.HSeparator()
122 self.vbox.pack_start(separator, expand=False, fill=True, padding=10)
123
124 self.vbox.show_all()
125 self.progress_bar.hide()
126
127 def set_image_text_buffer(self, image_path):
128 self.buf.set_text(image_path)
129
130 def set_image_path(self, image_path):
131 self.image_path = image_path
132
133 def popen_read(self, cmd):
134 tmpout, errors = bb.process.run("%s" % cmd)
135 return tmpout.strip()
136
137 def find_all_usb_devices(self):
138 usb_devs = [ os.readlink(u)
139 for u in glob.glob('/dev/disk/by-id/usb*')
140 if not re.search(r'part\d+', u) ]
141 return [ '%s' % u[u.rfind('/')+1:] for u in usb_devs ]
142
143 def get_usb_info(self, dev):
144 return "%s %s" % \
145 (self.popen_read('cat /sys/class/block/%s/device/vendor' % dev),
146 self.popen_read('cat /sys/class/block/%s/device/model' % dev))
147
148 def select_image_button_clicked_cb(self, button):
149 self.emit('select_image_clicked')
150
151 def usb_combo_changed_cb(self, usb_combo):
152 combo_item = self.usb_combo.get_active_text()
153 if not combo_item or combo_item == self.__dummy_usb__:
154 markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>"
155 self.usb_desc.set_markup(markup)
156 else:
157 markup = "<span font_desc='12'>" + self.get_usb_info(combo_item.lstrip("/dev/")) + "</span>"
158 self.usb_desc.set_markup(markup)
159
160 def response_cb(self, dialog, response_id):
161 if response_id == gtk.RESPONSE_YES:
162 lbl = ''
163 combo_item = self.usb_combo.get_active_text()
164 if combo_item and combo_item != self.__dummy_usb__ and self.image_path:
165 cmdline = bb.ui.crumbs.utils.which_terminal()
166 if cmdline:
167 tmpfile = tempfile.NamedTemporaryFile()
168 cmdline += "\"sudo dd if=" + self.image_path + \
169 " of=" + combo_item + "; echo $? > " + tmpfile.name + "\""
170 subprocess.call(shlex.split(cmdline))
171
172 if int(tmpfile.readline().strip()) == 0:
173 lbl = "<b>Deploy image successfully.</b>"
174 else:
175 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)
176 tmpfile.close()
177 else:
178 if not self.image_path:
179 lbl = "<b>No selection made.</b>\nYou have not selected an image to deploy."
180 else:
181 lbl = "<b>No selection made.</b>\nYou have not selected a USB device."
182 if len(lbl):
183 crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_INFO)
184 button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK)
185 HobButton.style_button(button)
186 crumbs_dialog.run()
187 crumbs_dialog.destroy()
188
189 def update_progress_bar(self, title, fraction, status=None):
190 self.progress_bar.update(fraction)
191 self.progress_bar.set_title(title)
192 self.progress_bar.set_rcstyle(status)
193
194 def write_file(self, ifile, ofile):
195 self.progress_bar.reset()
196 self.progress_bar.show()
197
198 f_from = os.open(ifile, os.O_RDONLY)
199 f_to = os.open(ofile, os.O_WRONLY)
200
201 total_size = os.stat(ifile).st_size
202 written_size = 0
203
204 while True:
205 buf = os.read(f_from, 1024*1024)
206 if not buf:
207 break
208 os.write(f_to, buf)
209 written_size += 1024*1024
210 self.update_progress_bar("Writing to usb:", written_size * 1.0/total_size)
211
212 self.update_progress_bar("Writing completed:", 1.0)
213 os.close(f_from)
214 os.close(f_to)
215 self.progress_bar.hide()
diff --git a/bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py b/bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py
new file mode 100644
index 0000000000..17f6bffe00
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py
@@ -0,0 +1,172 @@
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 gtk
24import gobject
25import os
26from bb.ui.crumbs.hobwidget import HobViewTable, HobInfoButton, HobButton, HobAltButton
27from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
28from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog
29
30"""
31The following are convenience classes for implementing GNOME HIG compliant
32BitBake GUI's
33In summary: spacing = 12px, border-width = 6px
34"""
35
36class ImageSelectionDialog (CrumbsDialog):
37
38 __columns__ = [{
39 'col_name' : 'Image name',
40 'col_id' : 0,
41 'col_style': 'text',
42 'col_min' : 400,
43 'col_max' : 400
44 }, {
45 'col_name' : 'Select',
46 'col_id' : 1,
47 'col_style': 'radio toggle',
48 'col_min' : 160,
49 'col_max' : 160
50 }]
51
52
53 def __init__(self, image_folder, image_types, title, parent, flags, buttons=None, image_extension = {}):
54 super(ImageSelectionDialog, self).__init__(title, parent, flags, buttons)
55 self.connect("response", self.response_cb)
56
57 self.image_folder = image_folder
58 self.image_types = image_types
59 self.image_list = []
60 self.image_names = []
61 self.image_extension = image_extension
62
63 # create visual elements on the dialog
64 self.create_visual_elements()
65
66 self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN)
67 self.fill_image_store()
68
69 def create_visual_elements(self):
70 hbox = gtk.HBox(False, 6)
71
72 self.vbox.pack_start(hbox, expand=False, fill=False)
73
74 entry = gtk.Entry()
75 entry.set_text(self.image_folder)
76 table = gtk.Table(1, 10, True)
77 table.set_size_request(560, -1)
78 hbox.pack_start(table, expand=False, fill=False)
79 table.attach(entry, 0, 9, 0, 1)
80 image = gtk.Image()
81 image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON)
82 open_button = gtk.Button()
83 open_button.set_image(image)
84 open_button.connect("clicked", self.select_path_cb, self, entry)
85 table.attach(open_button, 9, 10, 0, 1)
86
87 self.image_table = HobViewTable(self.__columns__)
88 self.image_table.set_size_request(-1, 300)
89 self.image_table.connect("toggled", self.toggled_cb)
90 self.image_table.connect_group_selection(self.table_selected_cb)
91 self.image_table.connect("row-activated", self.row_actived_cb)
92 self.vbox.pack_start(self.image_table, expand=True, fill=True)
93
94 self.show_all()
95
96 def change_image_cb(self, model, path, columnid):
97 if not model:
98 return
99 iter = model.get_iter_first()
100 while iter:
101 rowpath = model.get_path(iter)
102 model[rowpath][columnid] = False
103 iter = model.iter_next(iter)
104
105 model[path][columnid] = True
106
107 def toggled_cb(self, table, cell, path, columnid, tree):
108 model = tree.get_model()
109 self.change_image_cb(model, path, columnid)
110
111 def table_selected_cb(self, selection):
112 model, paths = selection.get_selected_rows()
113 if paths:
114 self.change_image_cb(model, paths[0], 1)
115
116 def row_actived_cb(self, tab, model, path):
117 self.change_image_cb(model, path, 1)
118 self.emit('response', gtk.RESPONSE_YES)
119
120 def select_path_cb(self, action, parent, entry):
121 dialog = gtk.FileChooserDialog("", parent,
122 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
123 text = entry.get_text()
124 dialog.set_current_folder(text if len(text) > 0 else os.getcwd())
125 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
126 HobAltButton.style_button(button)
127 button = dialog.add_button("Open", gtk.RESPONSE_YES)
128 HobButton.style_button(button)
129 response = dialog.run()
130 if response == gtk.RESPONSE_YES:
131 path = dialog.get_filename()
132 entry.set_text(path)
133 self.image_folder = path
134 self.fill_image_store()
135
136 dialog.destroy()
137
138 def fill_image_store(self):
139 self.image_list = []
140 self.image_store.clear()
141 imageset = set()
142 for root, dirs, files in os.walk(self.image_folder):
143 # ignore the sub directories
144 dirs[:] = []
145 for f in files:
146 for image_type in self.image_types:
147 if image_type in self.image_extension:
148 real_types = self.image_extension[image_type]
149 else:
150 real_types = [image_type]
151 for real_image_type in real_types:
152 if f.endswith('.' + real_image_type):
153 imageset.add(f.rsplit('.' + real_image_type)[0].rsplit('.rootfs')[0])
154 self.image_list.append(f)
155
156 for image in imageset:
157 self.image_store.set(self.image_store.append(), 0, image, 1, False)
158
159 self.image_table.set_model(self.image_store)
160
161 def response_cb(self, dialog, response_id):
162 self.image_names = []
163 if response_id == gtk.RESPONSE_YES:
164 iter = self.image_store.get_iter_first()
165 while iter:
166 path = self.image_store.get_path(iter)
167 if self.image_store[path][1]:
168 for f in self.image_list:
169 if f.startswith(self.image_store[path][0] + '.'):
170 self.image_names.append(f)
171 break
172 iter = self.image_store.iter_next(iter)
diff --git a/bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py b/bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py
new file mode 100644
index 0000000000..783ee73c7a
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py
@@ -0,0 +1,296 @@
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 gtk
24import gobject
25import os
26import tempfile
27from bb.ui.crumbs.hobwidget import hic, HobButton, HobAltButton
28from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
29from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
30
31"""
32The following are convenience classes for implementing GNOME HIG compliant
33BitBake GUI's
34In summary: spacing = 12px, border-width = 6px
35"""
36
37class CellRendererPixbufActivatable(gtk.CellRendererPixbuf):
38 """
39 A custom CellRenderer implementation which is activatable
40 so that we can handle user clicks
41 """
42 __gsignals__ = { 'clicked' : (gobject.SIGNAL_RUN_LAST,
43 gobject.TYPE_NONE,
44 (gobject.TYPE_STRING,)), }
45
46 def __init__(self):
47 gtk.CellRendererPixbuf.__init__(self)
48 self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
49 self.set_property('follow-state', True)
50
51 """
52 Respond to a user click on a cell
53 """
54 def do_activate(self, even, widget, path, background_area, cell_area, flags):
55 self.emit('clicked', path)
56
57#
58# LayerSelectionDialog
59#
60class LayerSelectionDialog (CrumbsDialog):
61
62 TARGETS = [
63 ("MY_TREE_MODEL_ROW", gtk.TARGET_SAME_WIDGET, 0),
64 ("text/plain", 0, 1),
65 ("TEXT", 0, 2),
66 ("STRING", 0, 3),
67 ]
68
69 def gen_label_widget(self, content):
70 label = gtk.Label()
71 label.set_alignment(0, 0)
72 label.set_markup(content)
73 label.show()
74 return label
75
76 def layer_widget_toggled_cb(self, cell, path, layer_store):
77 name = layer_store[path][0]
78 toggle = not layer_store[path][1]
79 layer_store[path][1] = toggle
80
81 def layer_widget_add_clicked_cb(self, action, layer_store, parent):
82 dialog = gtk.FileChooserDialog("Add new layer", parent,
83 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
84 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
85 HobAltButton.style_button(button)
86 button = dialog.add_button("Open", gtk.RESPONSE_YES)
87 HobButton.style_button(button)
88 label = gtk.Label("Select the layer you wish to add")
89 label.show()
90 dialog.set_extra_widget(label)
91 response = dialog.run()
92 path = dialog.get_filename()
93 dialog.destroy()
94
95 lbl = "<b>Error</b>\nUnable to load layer <i>%s</i> because " % path
96 if response == gtk.RESPONSE_YES:
97 import os
98 import os.path
99 layers = []
100 it = layer_store.get_iter_first()
101 while it:
102 layers.append(layer_store.get_value(it, 0))
103 it = layer_store.iter_next(it)
104
105 if not path:
106 lbl += "it is an invalid path."
107 elif not os.path.exists(path+"/conf/layer.conf"):
108 lbl += "there is no layer.conf inside the directory."
109 elif path in layers:
110 lbl += "it is already in loaded layers."
111 else:
112 layer_store.append([path])
113 return
114 dialog = CrumbsMessageDialog(parent, lbl)
115 dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
116 response = dialog.run()
117 dialog.destroy()
118
119 def layer_widget_del_clicked_cb(self, action, tree_selection, layer_store):
120 model, iter = tree_selection.get_selected()
121 if iter:
122 layer_store.remove(iter)
123
124
125 def gen_layer_widget(self, layers, layers_avail, window, tooltip=""):
126 hbox = gtk.HBox(False, 6)
127
128 layer_tv = gtk.TreeView()
129 layer_tv.set_rules_hint(True)
130 layer_tv.set_headers_visible(False)
131 tree_selection = layer_tv.get_selection()
132 tree_selection.set_mode(gtk.SELECTION_SINGLE)
133
134 # Allow enable drag and drop of rows including row move
135 layer_tv.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
136 self.TARGETS,
137 gtk.gdk.ACTION_DEFAULT|
138 gtk.gdk.ACTION_MOVE)
139 layer_tv.enable_model_drag_dest(self.TARGETS,
140 gtk.gdk.ACTION_DEFAULT)
141 layer_tv.connect("drag_data_get", self.drag_data_get_cb)
142 layer_tv.connect("drag_data_received", self.drag_data_received_cb)
143
144 col0= gtk.TreeViewColumn('Path')
145 cell0 = gtk.CellRendererText()
146 cell0.set_padding(5,2)
147 col0.pack_start(cell0, True)
148 col0.set_cell_data_func(cell0, self.draw_layer_path_cb)
149 layer_tv.append_column(col0)
150
151 scroll = gtk.ScrolledWindow()
152 scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
153 scroll.set_shadow_type(gtk.SHADOW_IN)
154 scroll.add(layer_tv)
155
156 table_layer = gtk.Table(2, 10, False)
157 hbox.pack_start(table_layer, expand=True, fill=True)
158
159 table_layer.attach(scroll, 0, 10, 0, 1)
160
161 layer_store = gtk.ListStore(gobject.TYPE_STRING)
162 for layer in layers:
163 layer_store.append([layer])
164
165 col1 = gtk.TreeViewColumn('Enabled')
166 layer_tv.append_column(col1)
167
168 cell1 = CellRendererPixbufActivatable()
169 cell1.set_fixed_size(-1,35)
170 cell1.connect("clicked", self.del_cell_clicked_cb, layer_store)
171 col1.pack_start(cell1, True)
172 col1.set_cell_data_func(cell1, self.draw_delete_button_cb, layer_tv)
173
174 add_button = gtk.Button()
175 add_button.set_relief(gtk.RELIEF_NONE)
176 box = gtk.HBox(False, 6)
177 box.show()
178 add_button.add(box)
179 add_button.connect("enter-notify-event", self.add_hover_cb)
180 add_button.connect("leave-notify-event", self.add_leave_cb)
181 self.im = gtk.Image()
182 self.im.set_from_file(hic.ICON_INDI_ADD_FILE)
183 self.im.show()
184 box.pack_start(self.im, expand=False, fill=False, padding=6)
185 lbl = gtk.Label("Add layer")
186 lbl.set_alignment(0.0, 0.5)
187 lbl.show()
188 box.pack_start(lbl, expand=True, fill=True, padding=6)
189 add_button.connect("clicked", self.layer_widget_add_clicked_cb, layer_store, window)
190 table_layer.attach(add_button, 0, 10, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 6)
191 layer_tv.set_model(layer_store)
192
193 hbox.show_all()
194
195 return hbox, layer_store
196
197 def drag_data_get_cb(self, treeview, context, selection, target_id, etime):
198 treeselection = treeview.get_selection()
199 model, iter = treeselection.get_selected()
200 data = model.get_value(iter, 0)
201 selection.set(selection.target, 8, data)
202
203 def drag_data_received_cb(self, treeview, context, x, y, selection, info, etime):
204 model = treeview.get_model()
205 data = selection.data
206 drop_info = treeview.get_dest_row_at_pos(x, y)
207 if drop_info:
208 path, position = drop_info
209 iter = model.get_iter(path)
210 if (position == gtk.TREE_VIEW_DROP_BEFORE or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE):
211 model.insert_before(iter, [data])
212 else:
213 model.insert_after(iter, [data])
214 else:
215 model.append([data])
216 if context.action == gtk.gdk.ACTION_MOVE:
217 context.finish(True, True, etime)
218 return
219
220 def add_hover_cb(self, button, event):
221 self.im.set_from_file(hic.ICON_INDI_ADD_HOVER_FILE)
222
223 def add_leave_cb(self, button, event):
224 self.im.set_from_file(hic.ICON_INDI_ADD_FILE)
225
226 def __init__(self, title, layers, layers_non_removable, all_layers, parent, flags, buttons=None):
227 super(LayerSelectionDialog, self).__init__(title, parent, flags, buttons)
228
229 # class members from other objects
230 self.layers = layers
231 self.layers_non_removable = layers_non_removable
232 self.all_layers = all_layers
233 self.layers_changed = False
234
235 # icon for remove button in TreeView
236 im = gtk.Image()
237 im.set_from_file(hic.ICON_INDI_REMOVE_FILE)
238 self.rem_icon = im.get_pixbuf()
239
240 # class members for internal use
241 self.layer_store = None
242
243 # create visual elements on the dialog
244 self.create_visual_elements()
245 self.connect("response", self.response_cb)
246
247 def create_visual_elements(self):
248 layer_widget, self.layer_store = self.gen_layer_widget(self.layers, self.all_layers, self, None)
249 layer_widget.set_size_request(450, 250)
250 self.vbox.pack_start(layer_widget, expand=True, fill=True)
251 self.show_all()
252
253 def response_cb(self, dialog, response_id):
254 model = self.layer_store
255 it = model.get_iter_first()
256 layers = []
257 while it:
258 layers.append(model.get_value(it, 0))
259 it = model.iter_next(it)
260
261 self.layers_changed = (self.layers != layers)
262 self.layers = layers
263
264 """
265 A custom cell_data_func to draw a delete 'button' in the TreeView for layers
266 other than the meta layer. The deletion of which is prevented so that the
267 user can't shoot themselves in the foot too badly.
268 """
269 def draw_delete_button_cb(self, col, cell, model, it, tv):
270 path = model.get_value(it, 0)
271 if path in self.layers_non_removable:
272 cell.set_sensitive(False)
273 cell.set_property('pixbuf', None)
274 cell.set_property('mode', gtk.CELL_RENDERER_MODE_INERT)
275 else:
276 cell.set_property('pixbuf', self.rem_icon)
277 cell.set_sensitive(True)
278 cell.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
279
280 return True
281
282 """
283 A custom cell_data_func to write an extra message into the layer path cell
284 for the meta layer. We should inform the user that they can't remove it for
285 their own safety.
286 """
287 def draw_layer_path_cb(self, col, cell, model, it):
288 path = model.get_value(it, 0)
289 if path in self.layers_non_removable:
290 cell.set_property('markup', "<b>It cannot be removed</b>\n%s" % path)
291 else:
292 cell.set_property('text', path)
293
294 def del_cell_clicked_cb(self, cell, path, model):
295 it = model.get_iter_from_string(path)
296 model.remove(it)
diff --git a/bitbake/lib/bb/ui/crumbs/hig/openinglogdialog.py b/bitbake/lib/bb/ui/crumbs/hig/openinglogdialog.py
new file mode 100644
index 0000000000..f1733156a7
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/openinglogdialog.py
@@ -0,0 +1,68 @@
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 gtk
24import gobject
25from bb.ui.crumbs.hobwidget import HobAltButton
26from bb.ui.crumbs.progressbar import HobProgressBar
27from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
28
29"""
30The following are convenience classes for implementing GNOME HIG compliant
31BitBake GUI's
32In summary: spacing = 12px, border-width = 6px
33"""
34
35class OpeningLogDialog (CrumbsDialog):
36
37 def __init__(self, title, parent, flags, buttons=None):
38 super(OpeningLogDialog, self).__init__(title, parent, flags, buttons)
39
40 self.running = False
41 # create visual elements on the dialog
42 self.create_visual_elements()
43
44 def start(self):
45 if not self.running:
46 self.running = True
47 gobject.timeout_add(100, self.pulse)
48
49 def pulse(self):
50 self.progress_bar.pulse()
51 return self.running
52
53 def create_visual_elements(self):
54 hbox = gtk.HBox(False, 12)
55 self.user_label = gtk.Label("The log will open in a text editor")
56 hbox.pack_start(self.user_label, expand=False, fill=False)
57 self.vbox.pack_start(hbox, expand=False, fill=False)
58
59 hbox = gtk.HBox(False, 12)
60 # Progress bar
61 self.progress_bar = HobProgressBar()
62 hbox.pack_start(self.progress_bar)
63 self.start()
64 self.vbox.pack_start(hbox, expand=False, fill=False)
65
66 button = self.add_button("Cancel", gtk.RESPONSE_CANCEL)
67 HobAltButton.style_button(button)
68 self.show_all()
diff --git a/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py b/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py
new file mode 100644
index 0000000000..69e7dffb6d
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/proxydetailsdialog.py
@@ -0,0 +1,90 @@
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 gtk
24from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
25
26"""
27The following are convenience classes for implementing GNOME HIG compliant
28BitBake GUI's
29In summary: spacing = 12px, border-width = 6px
30"""
31
32class ProxyDetailsDialog (CrumbsDialog):
33
34 def __init__(self, title, user, passwd, parent, flags, buttons=None):
35 super(ProxyDetailsDialog, self).__init__(title, parent, flags, buttons)
36 self.connect("response", self.response_cb)
37
38 self.auth = not (user == None or passwd == None or user == "")
39 self.user = user or ""
40 self.passwd = passwd or ""
41
42 # create visual elements on the dialog
43 self.create_visual_elements()
44
45 def create_visual_elements(self):
46 self.auth_checkbox = gtk.CheckButton("Use authentication")
47 self.auth_checkbox.set_tooltip_text("Check this box to set the username and the password")
48 self.auth_checkbox.set_active(self.auth)
49 self.auth_checkbox.connect("toggled", self.auth_checkbox_toggled_cb)
50 self.vbox.pack_start(self.auth_checkbox, expand=False, fill=False)
51
52 hbox = gtk.HBox(False, 6)
53 self.user_label = gtk.Label("Username:")
54 self.user_text = gtk.Entry()
55 self.user_text.set_text(self.user)
56 hbox.pack_start(self.user_label, expand=False, fill=False)
57 hbox.pack_end(self.user_text, expand=False, fill=False)
58 self.vbox.pack_start(hbox, expand=False, fill=False)
59
60 hbox = gtk.HBox(False, 6)
61 self.passwd_label = gtk.Label("Password:")
62 self.passwd_text = gtk.Entry()
63 self.passwd_text.set_text(self.passwd)
64 hbox.pack_start(self.passwd_label, expand=False, fill=False)
65 hbox.pack_end(self.passwd_text, expand=False, fill=False)
66 self.vbox.pack_start(hbox, expand=False, fill=False)
67
68 self.refresh_auth_components()
69 self.show_all()
70
71 def refresh_auth_components(self):
72 self.user_label.set_sensitive(self.auth)
73 self.user_text.set_editable(self.auth)
74 self.user_text.set_sensitive(self.auth)
75 self.passwd_label.set_sensitive(self.auth)
76 self.passwd_text.set_editable(self.auth)
77 self.passwd_text.set_sensitive(self.auth)
78
79 def auth_checkbox_toggled_cb(self, button):
80 self.auth = self.auth_checkbox.get_active()
81 self.refresh_auth_components()
82
83 def response_cb(self, dialog, response_id):
84 if response_id == gtk.RESPONSE_OK:
85 if self.auth:
86 self.user = self.user_text.get_text()
87 self.passwd = self.passwd_text.get_text()
88 else:
89 self.user = None
90 self.passwd = None
diff --git a/bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py b/bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py
new file mode 100644
index 0000000000..e10dd064ab
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py
@@ -0,0 +1,216 @@
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 gtk
24import os
25from bb.ui.crumbs.hobwidget import HobInfoButton, HobButton, HobAltButton
26
27"""
28The following are convenience classes for implementing GNOME HIG compliant
29BitBake GUI's
30In summary: spacing = 12px, border-width = 6px
31"""
32
33class SettingsUIHelper():
34
35 def gen_label_widget(self, content):
36 label = gtk.Label()
37 label.set_alignment(0, 0)
38 label.set_markup(content)
39 label.show()
40 return label
41
42 def gen_label_info_widget(self, content, tooltip):
43 table = gtk.Table(1, 10, False)
44 label = self.gen_label_widget(content)
45 info = HobInfoButton(tooltip, self)
46 table.attach(label, 0, 1, 0, 1, xoptions=gtk.FILL)
47 table.attach(info, 1, 2, 0, 1, xoptions=gtk.FILL, xpadding=10)
48 return table
49
50 def gen_spinner_widget(self, content, lower, upper, tooltip=""):
51 hbox = gtk.HBox(False, 12)
52 adjust = gtk.Adjustment(value=content, lower=lower, upper=upper, step_incr=1)
53 spinner = gtk.SpinButton(adjustment=adjust, climb_rate=1, digits=0)
54
55 spinner.set_value(content)
56 hbox.pack_start(spinner, expand=False, fill=False)
57
58 info = HobInfoButton(tooltip, self)
59 hbox.pack_start(info, expand=False, fill=False)
60
61 hbox.show_all()
62 return hbox, spinner
63
64 def gen_combo_widget(self, curr_item, all_item, tooltip=""):
65 hbox = gtk.HBox(False, 12)
66 combo = gtk.combo_box_new_text()
67 hbox.pack_start(combo, expand=False, fill=False)
68
69 index = 0
70 for item in all_item or []:
71 combo.append_text(item)
72 if item == curr_item:
73 combo.set_active(index)
74 index += 1
75
76 info = HobInfoButton(tooltip, self)
77 hbox.pack_start(info, expand=False, fill=False)
78
79 hbox.show_all()
80 return hbox, combo
81
82 def entry_widget_select_path_cb(self, action, parent, entry):
83 dialog = gtk.FileChooserDialog("", parent,
84 gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
85 text = entry.get_text()
86 dialog.set_current_folder(text if len(text) > 0 else os.getcwd())
87 button = dialog.add_button("Cancel", gtk.RESPONSE_NO)
88 HobAltButton.style_button(button)
89 button = dialog.add_button("Open", gtk.RESPONSE_YES)
90 HobButton.style_button(button)
91 response = dialog.run()
92 if response == gtk.RESPONSE_YES:
93 path = dialog.get_filename()
94 entry.set_text(path)
95
96 dialog.destroy()
97
98 def gen_entry_widget(self, content, parent, tooltip="", need_button=True):
99 hbox = gtk.HBox(False, 12)
100 entry = gtk.Entry()
101 entry.set_text(content)
102 entry.set_size_request(350,30)
103
104 if need_button:
105 table = gtk.Table(1, 10, False)
106 hbox.pack_start(table, expand=True, fill=True)
107 table.attach(entry, 0, 9, 0, 1, xoptions=gtk.SHRINK)
108 image = gtk.Image()
109 image.set_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON)
110 open_button = gtk.Button()
111 open_button.set_image(image)
112 open_button.connect("clicked", self.entry_widget_select_path_cb, parent, entry)
113 table.attach(open_button, 9, 10, 0, 1, xoptions=gtk.SHRINK)
114 else:
115 hbox.pack_start(entry, expand=True, fill=True)
116
117 if tooltip != "":
118 info = HobInfoButton(tooltip, self)
119 hbox.pack_start(info, expand=False, fill=False)
120
121 hbox.show_all()
122 return hbox, entry
123
124 def gen_mirror_entry_widget(self, content, index, match_content=""):
125 hbox = gtk.HBox(False)
126 entry = gtk.Entry()
127 content = content[:-2]
128 entry.set_text(content)
129 entry.set_size_request(350,30)
130
131 entry_match = gtk.Entry()
132 entry_match.set_text(match_content)
133 entry_match.set_size_request(100,30)
134
135 table = gtk.Table(2, 5, False)
136 table.set_row_spacings(12)
137 table.set_col_spacings(6)
138 hbox.pack_start(table, expand=True, fill=True)
139
140 label_configuration = gtk.Label("Configuration")
141 label_configuration.set_alignment(0.0,0.5)
142 label_mirror_url = gtk.Label("Mirror URL")
143 label_mirror_url.set_alignment(0.0,0.5)
144 label_match = gtk.Label("Match")
145 label_match.set_alignment(0.0,0.5)
146 label_replace_with = gtk.Label("Replace with")
147 label_replace_with.set_alignment(0.0,0.5)
148
149 combo = gtk.combo_box_new_text()
150 combo.append_text("Standard")
151 combo.append_text("Custom")
152 if match_content == "":
153 combo.set_active(0)
154 else:
155 combo.set_active(1)
156 combo.connect("changed", self.on_combo_changed, index)
157 combo.set_size_request(100,30)
158
159 delete_button = HobAltButton("Delete")
160 delete_button.connect("clicked", self.delete_cb, index, entry)
161 if content == "" and index == 0 and len(self.sstatemirrors_list) == 1:
162 delete_button.set_sensitive(False)
163 delete_button.set_size_request(100, 30)
164
165 entry_match.connect("changed", self.insert_entry_match_cb, index)
166 entry.connect("changed", self.insert_entry_cb, index, delete_button)
167
168 if match_content == "":
169 table.attach(label_configuration, 1, 2, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
170 table.attach(label_mirror_url, 2, 3, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
171 table.attach(combo, 1, 2, 1, 2, xoptions=gtk.SHRINK)
172 table.attach(entry, 2, 3, 1, 2, xoptions=gtk.SHRINK)
173 table.attach(delete_button, 3, 4, 1, 2, xoptions=gtk.SHRINK)
174 else:
175 table.attach(label_configuration, 1, 2, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
176 table.attach(label_match, 2, 3, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
177 table.attach(label_replace_with, 3, 4, 0, 1, xoptions=gtk.SHRINK|gtk.FILL)
178 table.attach(combo, 1, 2, 1, 2, xoptions=gtk.SHRINK)
179 table.attach(entry_match, 2, 3, 1, 2, xoptions=gtk.SHRINK)
180 table.attach(entry, 3, 4, 1, 2, xoptions=gtk.SHRINK)
181 table.attach(delete_button, 4, 5, 1, 2, xoptions=gtk.SHRINK)
182
183 hbox.show_all()
184 return hbox
185
186 def insert_entry_match_cb(self, entry_match, index):
187 self.sstatemirrors_list[index][2] = entry_match.get_text()
188
189 def insert_entry_cb(self, entry, index, button):
190 self.sstatemirrors_list[index][1] = entry.get_text()
191 if entry.get_text() == "" and index == 0:
192 button.set_sensitive(False)
193 else:
194 button.set_sensitive(True)
195
196 def on_combo_changed(self, combo, index):
197 if combo.get_active_text() == "Standard":
198 self.sstatemirrors_list[index][0] = 0
199 self.sstatemirrors_list[index][2] = "file://(.*)"
200 else:
201 self.sstatemirrors_list[index][0] = 1
202 self.refresh_shared_state_page()
203
204 def delete_cb(self, button, index, entry):
205 if index == 0 and len(self.sstatemirrors_list)==1:
206 entry.set_text("")
207 else:
208 self.sstatemirrors_list.pop(index)
209 self.refresh_shared_state_page()
210
211 def add_mirror(self, button):
212 tooltip = "Select the pre-built mirror that will speed your build"
213 index = len(self.sstatemirrors_list)
214 sm_list = [0, "", "file://(.*)"]
215 self.sstatemirrors_list.append(sm_list)
216 self.refresh_shared_state_page()
diff --git a/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py b/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py
new file mode 100644
index 0000000000..3642e9bc5c
--- /dev/null
+++ b/bitbake/lib/bb/ui/crumbs/hig/simplesettingsdialog.py
@@ -0,0 +1,722 @@
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 gtk
24import gobject
25import hashlib
26from bb.ui.crumbs.hobwidget import hic, HobInfoButton, HobButton, HobAltButton
27from bb.ui.crumbs.progressbar import HobProgressBar
28from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper
29from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
30from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
31from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog
32
33"""
34The following are convenience classes for implementing GNOME HIG compliant
35BitBake GUI's
36In summary: spacing = 12px, border-width = 6px
37"""
38
39class SimpleSettingsDialog (CrumbsDialog, SettingsUIHelper):
40
41 (BUILD_ENV_PAGE_ID,
42 SHARED_STATE_PAGE_ID,
43 PROXIES_PAGE_ID,
44 OTHERS_PAGE_ID) = range(4)
45
46 (TEST_NETWORK_NONE,
47 TEST_NETWORK_INITIAL,
48 TEST_NETWORK_RUNNING,
49 TEST_NETWORK_PASSED,
50 TEST_NETWORK_FAILED,
51 TEST_NETWORK_CANCELED) = range(6)
52
53 def __init__(self, title, configuration, all_image_types,
54 all_package_formats, all_distros, all_sdk_machines,
55 max_threads, parent, flags, handler, buttons=None):
56 super(SimpleSettingsDialog, self).__init__(title, parent, flags, buttons)
57
58 # class members from other objects
59 # bitbake settings from Builder.Configuration
60 self.configuration = configuration
61 self.image_types = all_image_types
62 self.all_package_formats = all_package_formats
63 self.all_distros = all_distros
64 self.all_sdk_machines = all_sdk_machines
65 self.max_threads = max_threads
66
67 # class members for internal use
68 self.dldir_text = None
69 self.sstatedir_text = None
70 self.sstatemirrors_list = []
71 self.sstatemirrors_changed = 0
72 self.bb_spinner = None
73 self.pmake_spinner = None
74 self.rootfs_size_spinner = None
75 self.extra_size_spinner = None
76 self.gplv3_checkbox = None
77 self.toolchain_checkbox = None
78 self.setting_store = None
79 self.image_types_checkbuttons = {}
80
81 self.md5 = self.config_md5()
82 self.proxy_md5 = self.config_proxy_md5()
83 self.settings_changed = False
84 self.proxy_settings_changed = False
85 self.handler = handler
86 self.proxy_test_ran = False
87
88 # create visual elements on the dialog
89 self.create_visual_elements()
90 self.connect("response", self.response_cb)
91
92 def _get_sorted_value(self, var):
93 return " ".join(sorted(str(var).split())) + "\n"
94
95 def config_proxy_md5(self):
96 data = ("ENABLE_PROXY: " + self._get_sorted_value(self.configuration.enable_proxy))
97 if self.configuration.enable_proxy:
98 for protocol in self.configuration.proxies.keys():
99 data += (protocol + ": " + self._get_sorted_value(self.configuration.combine_proxy(protocol)))
100 return hashlib.md5(data).hexdigest()
101
102 def config_md5(self):
103 data = ""
104 for key in self.configuration.extra_setting.keys():
105 data += (key + ": " + self._get_sorted_value(self.configuration.extra_setting[key]))
106 return hashlib.md5(data).hexdigest()
107
108 def gen_proxy_entry_widget(self, protocol, parent, need_button=True, line=0):
109 label = gtk.Label(protocol.upper() + " proxy")
110 self.proxy_table.attach(label, 0, 1, line, line+1, xpadding=24)
111
112 proxy_entry = gtk.Entry()
113 proxy_entry.set_size_request(300, -1)
114 self.proxy_table.attach(proxy_entry, 1, 2, line, line+1, ypadding=4)
115
116 self.proxy_table.attach(gtk.Label(":"), 2, 3, line, line+1, xpadding=12, ypadding=4)
117
118 port_entry = gtk.Entry()
119 port_entry.set_size_request(60, -1)
120 self.proxy_table.attach(port_entry, 3, 4, line, line+1, ypadding=4)
121
122 details_button = HobAltButton("Details")
123 details_button.connect("clicked", self.details_cb, parent, protocol)
124 self.proxy_table.attach(details_button, 4, 5, line, line+1, xpadding=4, yoptions=gtk.EXPAND)
125
126 return proxy_entry, port_entry, details_button
127
128 def refresh_proxy_components(self):
129 self.same_checkbox.set_sensitive(self.configuration.enable_proxy)
130
131 self.http_proxy.set_text(self.configuration.combine_host_only("http"))
132 self.http_proxy.set_editable(self.configuration.enable_proxy)
133 self.http_proxy.set_sensitive(self.configuration.enable_proxy)
134 self.http_proxy_port.set_text(self.configuration.combine_port_only("http"))
135 self.http_proxy_port.set_editable(self.configuration.enable_proxy)
136 self.http_proxy_port.set_sensitive(self.configuration.enable_proxy)
137 self.http_proxy_details.set_sensitive(self.configuration.enable_proxy)
138
139 self.https_proxy.set_text(self.configuration.combine_host_only("https"))
140 self.https_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
141 self.https_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
142 self.https_proxy_port.set_text(self.configuration.combine_port_only("https"))
143 self.https_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
144 self.https_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
145 self.https_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
146
147 self.ftp_proxy.set_text(self.configuration.combine_host_only("ftp"))
148 self.ftp_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
149 self.ftp_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
150 self.ftp_proxy_port.set_text(self.configuration.combine_port_only("ftp"))
151 self.ftp_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
152 self.ftp_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
153 self.ftp_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
154
155 self.git_proxy.set_text(self.configuration.combine_host_only("git"))
156 self.git_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
157 self.git_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
158 self.git_proxy_port.set_text(self.configuration.combine_port_only("git"))
159 self.git_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
160 self.git_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
161 self.git_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
162
163 self.cvs_proxy.set_text(self.configuration.combine_host_only("cvs"))
164 self.cvs_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
165 self.cvs_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
166 self.cvs_proxy_port.set_text(self.configuration.combine_port_only("cvs"))
167 self.cvs_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy))
168 self.cvs_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
169 self.cvs_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy))
170
171 if self.configuration.same_proxy:
172 if self.http_proxy.get_text():
173 [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
174 if self.http_proxy_port.get_text():
175 [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
176
177 def proxy_checkbox_toggled_cb(self, button):
178 self.configuration.enable_proxy = self.proxy_checkbox.get_active()
179 if not self.configuration.enable_proxy:
180 self.configuration.same_proxy = False
181 self.same_checkbox.set_active(self.configuration.same_proxy)
182 self.save_proxy_data()
183 self.refresh_proxy_components()
184
185 def same_checkbox_toggled_cb(self, button):
186 self.configuration.same_proxy = self.same_checkbox.get_active()
187 self.save_proxy_data()
188 self.refresh_proxy_components()
189
190 def save_proxy_data(self):
191 self.configuration.split_proxy("http", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
192 if self.configuration.same_proxy:
193 self.configuration.split_proxy("https", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
194 self.configuration.split_proxy("ftp", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
195 self.configuration.split_proxy("git", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
196 self.configuration.split_proxy("cvs", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text())
197 else:
198 self.configuration.split_proxy("https", self.https_proxy.get_text() + ":" + self.https_proxy_port.get_text())
199 self.configuration.split_proxy("ftp", self.ftp_proxy.get_text() + ":" + self.ftp_proxy_port.get_text())
200 self.configuration.split_proxy("git", self.git_proxy.get_text() + ":" + self.git_proxy_port.get_text())
201 self.configuration.split_proxy("cvs", self.cvs_proxy.get_text() + ":" + self.cvs_proxy_port.get_text())
202
203 def response_cb(self, dialog, response_id):
204 if response_id == gtk.RESPONSE_YES:
205 # Check that all proxy entries have a corresponding port
206 for proxy, port in zip(self.all_proxy_addresses, self.all_proxy_ports):
207 if proxy.get_text() and not port.get_text():
208 lbl = "<b>Enter all port numbers</b>\n\n"
209 msg = "Proxy servers require a port number. Please make sure you have entered a port number for each proxy server."
210 dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_WARNING, msg)
211 button = dialog.add_button("Close", gtk.RESPONSE_OK)
212 HobButton.style_button(button)
213 response = dialog.run()
214 dialog.destroy()
215 self.emit_stop_by_name("response")
216 return
217
218 self.configuration.dldir = self.dldir_text.get_text()
219 self.configuration.sstatedir = self.sstatedir_text.get_text()
220 self.configuration.sstatemirror = ""
221 for mirror in self.sstatemirrors_list:
222 if mirror[1] != "":
223 if mirror[1].endswith("\\1"):
224 smirror = mirror[2] + " " + mirror[1] + " \\n "
225 else:
226 smirror = mirror[2] + " " + mirror[1] + "\\1 \\n "
227 self.configuration.sstatemirror += smirror
228 self.configuration.bbthread = self.bb_spinner.get_value_as_int()
229 self.configuration.pmake = self.pmake_spinner.get_value_as_int()
230 self.save_proxy_data()
231 self.configuration.extra_setting = {}
232 it = self.setting_store.get_iter_first()
233 while it:
234 key = self.setting_store.get_value(it, 0)
235 value = self.setting_store.get_value(it, 1)
236 self.configuration.extra_setting[key] = value
237 it = self.setting_store.iter_next(it)
238
239 md5 = self.config_md5()
240 self.settings_changed = (self.md5 != md5)
241 self.proxy_settings_changed = (self.proxy_md5 != self.config_proxy_md5())
242
243 def create_build_environment_page(self):
244 advanced_vbox = gtk.VBox(False, 6)
245 advanced_vbox.set_border_width(6)
246
247 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Parallel threads</span>'), expand=False, fill=False)
248 sub_vbox = gtk.VBox(False, 6)
249 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
250 label = self.gen_label_widget("BitBake parallel threads")
251 tooltip = "Sets the number of threads that BitBake tasks can simultaneously run. See the <a href=\""
252 tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
253 tooltip += "poky-ref-manual.html#var-BB_NUMBER_THREADS\">Poky reference manual</a> for information"
254 bbthread_widget, self.bb_spinner = self.gen_spinner_widget(self.configuration.bbthread, 1, self.max_threads, tooltip)
255 sub_vbox.pack_start(label, expand=False, fill=False)
256 sub_vbox.pack_start(bbthread_widget, expand=False, fill=False)
257
258 sub_vbox = gtk.VBox(False, 6)
259 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
260 label = self.gen_label_widget("Make parallel threads")
261 tooltip = "Sets the maximum number of threads the host can use during the build. See the <a href=\""
262 tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
263 tooltip += "poky-ref-manual.html#var-PARALLEL_MAKE\">Poky reference manual</a> for information"
264 pmake_widget, self.pmake_spinner = self.gen_spinner_widget(self.configuration.pmake, 1, self.max_threads, tooltip)
265 sub_vbox.pack_start(label, expand=False, fill=False)
266 sub_vbox.pack_start(pmake_widget, expand=False, fill=False)
267
268 advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Downloaded source code</span>'), expand=False, fill=False)
269 sub_vbox = gtk.VBox(False, 6)
270 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
271 label = self.gen_label_widget("Downloads directory")
272 tooltip = "Select a folder that caches the upstream project source code"
273 dldir_widget, self.dldir_text = self.gen_entry_widget(self.configuration.dldir, self, tooltip)
274 sub_vbox.pack_start(label, expand=False, fill=False)
275 sub_vbox.pack_start(dldir_widget, expand=False, fill=False)
276
277 return advanced_vbox
278
279 def create_shared_state_page(self):
280 advanced_vbox = gtk.VBox(False)
281 advanced_vbox.set_border_width(12)
282
283 sub_vbox = gtk.VBox(False)
284 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False, padding=24)
285 content = "<span>Shared state directory</span>"
286 tooltip = "Select a folder that caches your prebuilt results"
287 label = self.gen_label_info_widget(content, tooltip)
288 sstatedir_widget, self.sstatedir_text = self.gen_entry_widget(self.configuration.sstatedir, self)
289 sub_vbox.pack_start(label, expand=False, fill=False)
290 sub_vbox.pack_start(sstatedir_widget, expand=False, fill=False, padding=12)
291
292 content = "<span weight=\"bold\">Shared state mirrors</span>"
293 tooltip = "URLs pointing to pre-built mirrors that will speed your build. "
294 tooltip += "Select the \'Standard\' configuration if the structure of your "
295 tooltip += "mirror replicates the structure of your local shared state directory. "
296 tooltip += "For more information on shared state mirrors, check the <a href=\""
297 tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/"
298 tooltip += "poky-ref-manual.html#shared-state\">Yocto Project Reference Manual</a>."
299 table = self.gen_label_info_widget(content, tooltip)
300 advanced_vbox.pack_start(table, expand=False, fill=False)
301
302 sub_vbox = gtk.VBox(False)
303 scroll = gtk.ScrolledWindow()
304 scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
305 scroll.add_with_viewport(sub_vbox)
306 scroll.connect('size-allocate', self.scroll_changed)
307 advanced_vbox.pack_start(scroll, gtk.TRUE, gtk.TRUE, 0)
308 searched_string = "file://"
309
310 if self.sstatemirrors_changed == 0:
311 self.sstatemirrors_changed = 1
312 sstatemirrors = self.configuration.sstatemirror
313 if sstatemirrors == "":
314 sm_list = [ 0, "", "file://(.*)"]
315 self.sstatemirrors_list.append(sm_list)
316 else:
317 while sstatemirrors.find(searched_string) != -1:
318 if sstatemirrors.find(searched_string,1) != -1:
319 sstatemirror = sstatemirrors[:sstatemirrors.find(searched_string,1)]
320 sstatemirrors = sstatemirrors[sstatemirrors.find(searched_string,1):]
321 else:
322 sstatemirror = sstatemirrors
323 sstatemirrors = sstatemirrors[1:]
324
325 sstatemirror_fields = [x for x in sstatemirror.split(' ') if x.strip()]
326 if sstatemirror_fields[0] == "file://(.*)":
327 sm_list = [ 0, sstatemirror_fields[1], "file://(.*)"]
328 else:
329 sm_list = [ 1, sstatemirror_fields[1], sstatemirror_fields[0]]
330 self.sstatemirrors_list.append(sm_list)
331
332 index = 0
333 for mirror in self.sstatemirrors_list:
334 if mirror[0] == 0:
335 sstatemirror_widget = self.gen_mirror_entry_widget(mirror[1], index)
336 else:
337 sstatemirror_widget = self.gen_mirror_entry_widget(mirror[1], index, mirror[2])
338 sub_vbox.pack_start(sstatemirror_widget, expand=False, fill=False, padding=9)
339 index += 1
340
341 table = gtk.Table(1, 1, False)
342 table.set_col_spacings(6)
343 add_mirror_button = HobAltButton("Add another mirror")
344 add_mirror_button.connect("clicked", self.add_mirror)
345 add_mirror_button.set_size_request(150,30)
346 table.attach(add_mirror_button, 1, 2, 0, 1, xoptions=gtk.SHRINK)
347 advanced_vbox.pack_start(table, expand=False, fill=False, padding=9)
348
349 return advanced_vbox
350
351 def refresh_shared_state_page(self):
352 page_num = self.nb.get_current_page()
353 self.nb.remove_page(page_num);
354 self.nb.insert_page(self.create_shared_state_page(), gtk.Label("Shared state"),page_num)
355 self.show_all()
356 self.nb.set_current_page(page_num)
357
358 def test_proxy_ended(self, passed):
359 self.proxy_test_running = False
360 self.set_test_proxy_state(self.TEST_NETWORK_PASSED if passed else self.TEST_NETWORK_FAILED)
361 self.set_sensitive(True)
362 self.refresh_proxy_components()
363
364 def timer_func(self):
365 self.test_proxy_progress.pulse()
366 return self.proxy_test_running
367
368 def test_network_button_cb(self, b):
369 self.set_test_proxy_state(self.TEST_NETWORK_RUNNING)
370 self.set_sensitive(False)
371 self.save_proxy_data()
372 if self.configuration.enable_proxy == True:
373 self.handler.set_http_proxy(self.configuration.combine_proxy("http"))
374 self.handler.set_https_proxy(self.configuration.combine_proxy("https"))
375 self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp"))
376 self.handler.set_git_proxy(self.configuration.combine_host_only("git"), self.configuration.combine_port_only("git"))
377 self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs"))
378 elif self.configuration.enable_proxy == False:
379 self.handler.set_http_proxy("")
380 self.handler.set_https_proxy("")
381 self.handler.set_ftp_proxy("")
382 self.handler.set_git_proxy("", "")
383 self.handler.set_cvs_proxy("", "")
384 self.proxy_test_ran = True
385 self.proxy_test_running = True
386 gobject.timeout_add(100, self.timer_func)
387 self.handler.trigger_network_test()
388
389 def test_proxy_focus_event(self, w, direction):
390 if self.test_proxy_state in [self.TEST_NETWORK_PASSED, self.TEST_NETWORK_FAILED]:
391 self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
392 return False
393
394 def http_proxy_changed(self, e):
395 if not self.configuration.same_proxy:
396 return
397 if e == self.http_proxy:
398 [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses]
399 else:
400 [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports]
401
402 def proxy_address_focus_out_event(self, w, direction):
403 text = w.get_text()
404 if not text:
405 return False
406 if text.find("//") == -1:
407 w.set_text("http://" + text)
408 return False
409
410 def set_test_proxy_state(self, state):
411 if self.test_proxy_state == state:
412 return
413 [self.proxy_table.remove(w) for w in self.test_gui_elements]
414 if state == self.TEST_NETWORK_INITIAL:
415 self.proxy_table.attach(self.test_network_button, 1, 2, 5, 6)
416 self.test_network_button.show()
417 elif state == self.TEST_NETWORK_RUNNING:
418 self.test_proxy_progress.set_rcstyle("running")
419 self.test_proxy_progress.set_text("Testing network configuration")
420 self.proxy_table.attach(self.test_proxy_progress, 0, 5, 5, 6, xpadding=4)
421 self.test_proxy_progress.show()
422 else: # passed or failed
423 self.dummy_progress.update(1.0)
424 if state == self.TEST_NETWORK_PASSED:
425 self.dummy_progress.set_text("Your network is properly configured")
426 self.dummy_progress.set_rcstyle("running")
427 else:
428 self.dummy_progress.set_text("Network test failed")
429 self.dummy_progress.set_rcstyle("fail")
430 self.proxy_table.attach(self.dummy_progress, 0, 4, 5, 6)
431 self.proxy_table.attach(self.retest_network_button, 4, 5, 5, 6, xpadding=4)
432 self.dummy_progress.show()
433 self.retest_network_button.show()
434 self.test_proxy_state = state
435
436 def create_network_page(self):
437 advanced_vbox = gtk.VBox(False, 6)
438 advanced_vbox.set_border_width(6)
439 self.same_proxy_addresses = []
440 self.same_proxy_ports = []
441 self.all_proxy_ports = []
442 self.all_proxy_addresses = []
443
444 sub_vbox = gtk.VBox(False, 6)
445 advanced_vbox.pack_start(sub_vbox, expand=False, fill=False)
446 label = self.gen_label_widget("<span weight=\"bold\">Set the proxies used when fetching source code</span>")
447 tooltip = "Set the proxies used when fetching source code. A blank field uses a direct internet connection."
448 info = HobInfoButton(tooltip, self)
449 hbox = gtk.HBox(False, 12)
450 hbox.pack_start(label, expand=True, fill=True)
451 hbox.pack_start(info, expand=False, fill=False)
452 sub_vbox.pack_start(hbox, expand=False, fill=False)
453
454 proxy_test_focus = []
455 self.direct_checkbox = gtk.RadioButton(None, "Direct network connection")
456 proxy_test_focus.append(self.direct_checkbox)
457 self.direct_checkbox.set_tooltip_text("Check this box to use a direct internet connection with no proxy")
458 self.direct_checkbox.set_active(not self.configuration.enable_proxy)
459 sub_vbox.pack_start(self.direct_checkbox, expand=False, fill=False)
460
461 self.proxy_checkbox = gtk.RadioButton(self.direct_checkbox, "Manual proxy configuration")
462 proxy_test_focus.append(self.proxy_checkbox)
463 self.proxy_checkbox.set_tooltip_text("Check this box to manually set up a specific proxy")
464 self.proxy_checkbox.set_active(self.configuration.enable_proxy)
465 sub_vbox.pack_start(self.proxy_checkbox, expand=False, fill=False)
466
467 self.same_checkbox = gtk.CheckButton("Use the HTTP proxy for all protocols")
468 proxy_test_focus.append(self.same_checkbox)
469 self.same_checkbox.set_tooltip_text("Check this box to use the HTTP proxy for all five proxies")
470 self.same_checkbox.set_active(self.configuration.same_proxy)
471 hbox = gtk.HBox(False, 12)
472 hbox.pack_start(self.same_checkbox, expand=False, fill=False, padding=24)
473 sub_vbox.pack_start(hbox, expand=False, fill=False)
474
475 self.proxy_table = gtk.Table(6, 5, False)
476 self.http_proxy, self.http_proxy_port, self.http_proxy_details = self.gen_proxy_entry_widget(
477 "http", self, True, 0)
478 proxy_test_focus +=[self.http_proxy, self.http_proxy_port]
479 self.http_proxy.connect("changed", self.http_proxy_changed)
480 self.http_proxy_port.connect("changed", self.http_proxy_changed)
481
482 self.https_proxy, self.https_proxy_port, self.https_proxy_details = self.gen_proxy_entry_widget(
483 "https", self, True, 1)
484 proxy_test_focus += [self.https_proxy, self.https_proxy_port]
485 self.same_proxy_addresses.append(self.https_proxy)
486 self.same_proxy_ports.append(self.https_proxy_port)
487
488 self.ftp_proxy, self.ftp_proxy_port, self.ftp_proxy_details = self.gen_proxy_entry_widget(
489 "ftp", self, True, 2)
490 proxy_test_focus += [self.ftp_proxy, self.ftp_proxy_port]
491 self.same_proxy_addresses.append(self.ftp_proxy)
492 self.same_proxy_ports.append(self.ftp_proxy_port)
493
494 self.git_proxy, self.git_proxy_port, self.git_proxy_details = self.gen_proxy_entry_widget(
495 "git", self, True, 3)
496 proxy_test_focus += [self.git_proxy, self.git_proxy_port]
497 self.same_proxy_addresses.append(self.git_proxy)
498 self.same_proxy_ports.append(self.git_proxy_port)
499
500 self.cvs_proxy, self.cvs_proxy_port, self.cvs_proxy_details = self.gen_proxy_entry_widget(
501 "cvs", self, True, 4)
502 proxy_test_focus += [self.cvs_proxy, self.cvs_proxy_port]
503 self.same_proxy_addresses.append(self.cvs_proxy)
504 self.same_proxy_ports.append(self.cvs_proxy_port)
505 self.all_proxy_ports = self.same_proxy_ports + [self.http_proxy_port]
506 self.all_proxy_addresses = self.same_proxy_addresses + [self.http_proxy]
507 sub_vbox.pack_start(self.proxy_table, expand=False, fill=False)
508 self.proxy_table.show_all()
509
510 # Create the graphical elements for the network test feature, but don't display them yet
511 self.test_network_button = HobAltButton("Test network configuration")
512 self.test_network_button.connect("clicked", self.test_network_button_cb)
513 self.test_proxy_progress = HobProgressBar()
514 self.dummy_progress = HobProgressBar()
515 self.retest_network_button = HobAltButton("Retest")
516 self.retest_network_button.connect("clicked", self.test_network_button_cb)
517 self.test_gui_elements = [self.test_network_button, self.test_proxy_progress, self.dummy_progress, self.retest_network_button]
518 # Initialize the network tester
519 self.test_proxy_state = self.TEST_NETWORK_NONE
520 self.set_test_proxy_state(self.TEST_NETWORK_INITIAL)
521 self.proxy_test_passed_id = self.handler.connect("network-passed", lambda h:self.test_proxy_ended(True))
522 self.proxy_test_failed_id = self.handler.connect("network-failed", lambda h:self.test_proxy_ended(False))
523 [w.connect("focus-in-event", self.test_proxy_focus_event) for w in proxy_test_focus]
524 [w.connect("focus-out-event", self.proxy_address_focus_out_event) for w in self.all_proxy_addresses]
525
526 self.direct_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
527 self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb)
528 self.same_checkbox.connect("toggled", self.same_checkbox_toggled_cb)
529
530 self.refresh_proxy_components()
531 return advanced_vbox
532
533 def switch_to_page(self, page_id):
534 self.nb.set_current_page(page_id)
535
536 def details_cb(self, button, parent, protocol):
537 self.save_proxy_data()
538 dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details",
539 user = self.configuration.proxies[protocol][1],
540 passwd = self.configuration.proxies[protocol][2],
541 parent = parent,
542 flags = gtk.DIALOG_MODAL
543 | gtk.DIALOG_DESTROY_WITH_PARENT
544 | gtk.DIALOG_NO_SEPARATOR)
545 dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK)
546 response = dialog.run()
547 if response == gtk.RESPONSE_OK:
548 self.configuration.proxies[protocol][1] = dialog.user
549 self.configuration.proxies[protocol][2] = dialog.passwd
550 self.refresh_proxy_components()
551 dialog.destroy()
552
553 def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox):
554 combo_item = self.rootfs_combo.get_active_text()
555 for child in check_hbox.get_children():
556 if isinstance(child, gtk.CheckButton):
557 check_hbox.remove(child)
558 for format in all_package_format:
559 if format != combo_item:
560 check_button = gtk.CheckButton(format)
561 check_hbox.pack_start(check_button, expand=False, fill=False)
562 check_hbox.show_all()
563
564 def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""):
565 pkgfmt_hbox = gtk.HBox(False, 24)
566
567 rootfs_vbox = gtk.VBox(False, 6)
568 pkgfmt_hbox.pack_start(rootfs_vbox, expand=False, fill=False)
569
570 label = self.gen_label_widget("Root file system package format")
571 rootfs_vbox.pack_start(label, expand=False, fill=False)
572
573 rootfs_format = ""
574 if curr_package_format:
575 rootfs_format = curr_package_format.split()[0]
576
577 rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo)
578 rootfs_vbox.pack_start(rootfs_format_widget, expand=False, fill=False)
579
580 extra_vbox = gtk.VBox(False, 6)
581 pkgfmt_hbox.pack_start(extra_vbox, expand=False, fill=False)
582
583 label = self.gen_label_widget("Additional package formats")
584 extra_vbox.pack_start(label, expand=False, fill=False)
585
586 check_hbox = gtk.HBox(False, 12)
587 extra_vbox.pack_start(check_hbox, expand=False, fill=False)
588 for format in all_package_format:
589 if format != rootfs_format:
590 check_button = gtk.CheckButton(format)
591 is_active = (format in curr_package_format.split())
592 check_button.set_active(is_active)
593 check_hbox.pack_start(check_button, expand=False, fill=False)
594
595 info = HobInfoButton(tooltip_extra, self)
596 check_hbox.pack_end(info, expand=False, fill=False)
597
598 rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox)
599
600 pkgfmt_hbox.show_all()
601
602 return pkgfmt_hbox, rootfs_combo, check_hbox
603
604 def editable_settings_cell_edited(self, cell, path_string, new_text, model):
605 it = model.get_iter_from_string(path_string)
606 column = cell.get_data("column")
607 model.set(it, column, new_text)
608
609 def editable_settings_add_item_clicked(self, button, model):
610 new_item = ["##KEY##", "##VALUE##"]
611
612 iter = model.append()
613 model.set (iter,
614 0, new_item[0],
615 1, new_item[1],
616 )
617
618 def editable_settings_remove_item_clicked(self, button, treeview):
619 selection = treeview.get_selection()
620 model, iter = selection.get_selected()
621
622 if iter:
623 path = model.get_path(iter)[0]
624 model.remove(iter)
625
626 def gen_editable_settings(self, setting, tooltip=""):
627 setting_hbox = gtk.HBox(False, 12)
628
629 vbox = gtk.VBox(False, 12)
630 setting_hbox.pack_start(vbox, expand=True, fill=True)
631
632 setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING)
633 for key in setting.keys():
634 setting_store.set(setting_store.append(), 0, key, 1, setting[key])
635
636 setting_tree = gtk.TreeView(setting_store)
637 setting_tree.set_headers_visible(True)
638 setting_tree.set_size_request(300, 100)
639
640 col = gtk.TreeViewColumn('Key')
641 col.set_min_width(100)
642 col.set_max_width(150)
643 col.set_resizable(True)
644 col1 = gtk.TreeViewColumn('Value')
645 col1.set_min_width(100)
646 col1.set_max_width(150)
647 col1.set_resizable(True)
648 setting_tree.append_column(col)
649 setting_tree.append_column(col1)
650 cell = gtk.CellRendererText()
651 cell.set_property('width-chars', 10)
652 cell.set_property('editable', True)
653 cell.set_data("column", 0)
654 cell.connect("edited", self.editable_settings_cell_edited, setting_store)
655 cell1 = gtk.CellRendererText()
656 cell1.set_property('width-chars', 10)
657 cell1.set_property('editable', True)
658 cell1.set_data("column", 1)
659 cell1.connect("edited", self.editable_settings_cell_edited, setting_store)
660 col.pack_start(cell, True)
661 col1.pack_end(cell1, True)
662 col.set_attributes(cell, text=0)
663 col1.set_attributes(cell1, text=1)
664
665 scroll = gtk.ScrolledWindow()
666 scroll.set_shadow_type(gtk.SHADOW_IN)
667 scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
668 scroll.add(setting_tree)
669 vbox.pack_start(scroll, expand=True, fill=True)
670
671 # some buttons
672 hbox = gtk.HBox(True, 6)
673 vbox.pack_start(hbox, False, False)
674
675 button = gtk.Button(stock=gtk.STOCK_ADD)
676 button.connect("clicked", self.editable_settings_add_item_clicked, setting_store)
677 hbox.pack_start(button)
678
679 button = gtk.Button(stock=gtk.STOCK_REMOVE)
680 button.connect("clicked", self.editable_settings_remove_item_clicked, setting_tree)
681 hbox.pack_start(button)
682
683 info = HobInfoButton(tooltip, self)
684 setting_hbox.pack_start(info, expand=False, fill=False)
685
686 return setting_hbox, setting_store
687
688 def create_others_page(self):
689 advanced_vbox = gtk.VBox(False, 6)
690 advanced_vbox.set_border_width(6)
691
692 sub_vbox = gtk.VBox(False, 6)
693 advanced_vbox.pack_start(sub_vbox, expand=True, fill=True)
694 label = self.gen_label_widget("<span weight=\"bold\">Add your own variables:</span>")
695 tooltip = "These are key/value pairs for your extra settings. Click \'Add\' and then directly edit the key and the value"
696 setting_widget, self.setting_store = self.gen_editable_settings(self.configuration.extra_setting, tooltip)
697 sub_vbox.pack_start(label, expand=False, fill=False)
698 sub_vbox.pack_start(setting_widget, expand=True, fill=True)
699
700 return advanced_vbox
701
702 def create_visual_elements(self):
703 self.nb = gtk.Notebook()
704 self.nb.set_show_tabs(True)
705 self.nb.append_page(self.create_build_environment_page(), gtk.Label("Build environment"))
706 self.nb.append_page(self.create_shared_state_page(), gtk.Label("Shared state"))
707 self.nb.append_page(self.create_network_page(), gtk.Label("Network"))
708 self.nb.append_page(self.create_others_page(), gtk.Label("Others"))
709 self.nb.set_current_page(0)
710 self.vbox.pack_start(self.nb, expand=True, fill=True)
711 self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True)
712
713 self.show_all()
714
715 def destroy(self):
716 self.handler.disconnect(self.proxy_test_passed_id)
717 self.handler.disconnect(self.proxy_test_failed_id)
718 super(SimpleSettingsDialog, self).destroy()
719
720 def scroll_changed(self, widget, event, data=None):
721 adj = widget.get_vadjustment()
722 adj.set_value(adj.upper - adj.page_size)