Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 | |
| 23 | import gtk |
| 24 | import gobject |
| 25 | import hashlib |
| 26 | from bb.ui.crumbs.hobwidget import hic, HobInfoButton, HobButton, HobAltButton |
| 27 | from bb.ui.crumbs.progressbar import HobProgressBar |
| 28 | from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper |
| 29 | from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog |
| 30 | from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog |
| 31 | from bb.ui.crumbs.hig.proxydetailsdialog import ProxyDetailsDialog |
| 32 | |
| 33 | """ |
| 34 | The following are convenience classes for implementing GNOME HIG compliant |
| 35 | BitBake GUI's |
| 36 | In summary: spacing = 12px, border-width = 6px |
| 37 | """ |
| 38 | |
| 39 | class 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 | TARGETS = [ |
| 54 | ("MY_TREE_MODEL_ROW", gtk.TARGET_SAME_WIDGET, 0), |
| 55 | ("text/plain", 0, 1), |
| 56 | ("TEXT", 0, 2), |
| 57 | ("STRING", 0, 3), |
| 58 | ] |
| 59 | |
| 60 | def __init__(self, title, configuration, all_image_types, |
| 61 | all_package_formats, all_distros, all_sdk_machines, |
| 62 | max_threads, parent, flags, handler, buttons=None): |
| 63 | super(SimpleSettingsDialog, self).__init__(title, parent, flags, buttons) |
| 64 | |
| 65 | # class members from other objects |
| 66 | # bitbake settings from Builder.Configuration |
| 67 | self.configuration = configuration |
| 68 | self.image_types = all_image_types |
| 69 | self.all_package_formats = all_package_formats |
| 70 | self.all_distros = all_distros |
| 71 | self.all_sdk_machines = all_sdk_machines |
| 72 | self.max_threads = max_threads |
| 73 | |
| 74 | # class members for internal use |
| 75 | self.dldir_text = None |
| 76 | self.sstatedir_text = None |
| 77 | self.sstatemirrors_list = [] |
| 78 | self.sstatemirrors_changed = 0 |
| 79 | self.bb_spinner = None |
| 80 | self.pmake_spinner = None |
| 81 | self.rootfs_size_spinner = None |
| 82 | self.extra_size_spinner = None |
| 83 | self.gplv3_checkbox = None |
| 84 | self.toolchain_checkbox = None |
| 85 | self.setting_store = None |
| 86 | self.image_types_checkbuttons = {} |
| 87 | |
| 88 | self.md5 = self.config_md5() |
| 89 | self.proxy_md5 = self.config_proxy_md5() |
| 90 | self.settings_changed = False |
| 91 | self.proxy_settings_changed = False |
| 92 | self.handler = handler |
| 93 | self.proxy_test_ran = False |
| 94 | self.selected_mirror_row = 0 |
| 95 | self.new_mirror = False |
| 96 | |
| 97 | # create visual elements on the dialog |
| 98 | self.create_visual_elements() |
| 99 | self.connect("response", self.response_cb) |
| 100 | |
| 101 | def _get_sorted_value(self, var): |
| 102 | return " ".join(sorted(str(var).split())) + "\n" |
| 103 | |
| 104 | def config_proxy_md5(self): |
| 105 | data = ("ENABLE_PROXY: " + self._get_sorted_value(self.configuration.enable_proxy)) |
| 106 | if self.configuration.enable_proxy: |
| 107 | for protocol in self.configuration.proxies.keys(): |
| 108 | data += (protocol + ": " + self._get_sorted_value(self.configuration.combine_proxy(protocol))) |
| 109 | return hashlib.md5(data).hexdigest() |
| 110 | |
| 111 | def config_md5(self): |
| 112 | data = "" |
| 113 | for key in self.configuration.extra_setting.keys(): |
| 114 | data += (key + ": " + self._get_sorted_value(self.configuration.extra_setting[key])) |
| 115 | return hashlib.md5(data).hexdigest() |
| 116 | |
| 117 | def gen_proxy_entry_widget(self, protocol, parent, need_button=True, line=0): |
| 118 | label = gtk.Label(protocol.upper() + " proxy") |
| 119 | self.proxy_table.attach(label, 0, 1, line, line+1, xpadding=24) |
| 120 | |
| 121 | proxy_entry = gtk.Entry() |
| 122 | proxy_entry.set_size_request(300, -1) |
| 123 | self.proxy_table.attach(proxy_entry, 1, 2, line, line+1, ypadding=4) |
| 124 | |
| 125 | self.proxy_table.attach(gtk.Label(":"), 2, 3, line, line+1, xpadding=12, ypadding=4) |
| 126 | |
| 127 | port_entry = gtk.Entry() |
| 128 | port_entry.set_size_request(60, -1) |
| 129 | self.proxy_table.attach(port_entry, 3, 4, line, line+1, ypadding=4) |
| 130 | |
| 131 | details_button = HobAltButton("Details") |
| 132 | details_button.connect("clicked", self.details_cb, parent, protocol) |
| 133 | self.proxy_table.attach(details_button, 4, 5, line, line+1, xpadding=4, yoptions=gtk.EXPAND) |
| 134 | |
| 135 | return proxy_entry, port_entry, details_button |
| 136 | |
| 137 | def refresh_proxy_components(self): |
| 138 | self.same_checkbox.set_sensitive(self.configuration.enable_proxy) |
| 139 | |
| 140 | self.http_proxy.set_text(self.configuration.combine_host_only("http")) |
| 141 | self.http_proxy.set_editable(self.configuration.enable_proxy) |
| 142 | self.http_proxy.set_sensitive(self.configuration.enable_proxy) |
| 143 | self.http_proxy_port.set_text(self.configuration.combine_port_only("http")) |
| 144 | self.http_proxy_port.set_editable(self.configuration.enable_proxy) |
| 145 | self.http_proxy_port.set_sensitive(self.configuration.enable_proxy) |
| 146 | self.http_proxy_details.set_sensitive(self.configuration.enable_proxy) |
| 147 | |
| 148 | self.https_proxy.set_text(self.configuration.combine_host_only("https")) |
| 149 | self.https_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 150 | self.https_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 151 | self.https_proxy_port.set_text(self.configuration.combine_port_only("https")) |
| 152 | self.https_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 153 | self.https_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 154 | self.https_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 155 | |
| 156 | self.ftp_proxy.set_text(self.configuration.combine_host_only("ftp")) |
| 157 | self.ftp_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 158 | self.ftp_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 159 | self.ftp_proxy_port.set_text(self.configuration.combine_port_only("ftp")) |
| 160 | self.ftp_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 161 | self.ftp_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 162 | self.ftp_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 163 | |
| 164 | self.socks_proxy.set_text(self.configuration.combine_host_only("socks")) |
| 165 | self.socks_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 166 | self.socks_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 167 | self.socks_proxy_port.set_text(self.configuration.combine_port_only("socks")) |
| 168 | self.socks_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 169 | self.socks_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 170 | self.socks_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 171 | |
| 172 | self.cvs_proxy.set_text(self.configuration.combine_host_only("cvs")) |
| 173 | self.cvs_proxy.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 174 | self.cvs_proxy.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 175 | self.cvs_proxy_port.set_text(self.configuration.combine_port_only("cvs")) |
| 176 | self.cvs_proxy_port.set_editable(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 177 | self.cvs_proxy_port.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 178 | self.cvs_proxy_details.set_sensitive(self.configuration.enable_proxy and (not self.configuration.same_proxy)) |
| 179 | |
| 180 | if self.configuration.same_proxy: |
| 181 | if self.http_proxy.get_text(): |
| 182 | [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses] |
| 183 | if self.http_proxy_port.get_text(): |
| 184 | [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports] |
| 185 | |
| 186 | def proxy_checkbox_toggled_cb(self, button): |
| 187 | self.configuration.enable_proxy = self.proxy_checkbox.get_active() |
| 188 | if not self.configuration.enable_proxy: |
| 189 | self.configuration.same_proxy = False |
| 190 | self.same_checkbox.set_active(self.configuration.same_proxy) |
| 191 | self.save_proxy_data() |
| 192 | self.refresh_proxy_components() |
| 193 | |
| 194 | def same_checkbox_toggled_cb(self, button): |
| 195 | self.configuration.same_proxy = self.same_checkbox.get_active() |
| 196 | self.save_proxy_data() |
| 197 | self.refresh_proxy_components() |
| 198 | |
| 199 | def save_proxy_data(self): |
| 200 | self.configuration.split_proxy("http", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text()) |
| 201 | if self.configuration.same_proxy: |
| 202 | self.configuration.split_proxy("https", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text()) |
| 203 | self.configuration.split_proxy("ftp", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text()) |
| 204 | self.configuration.split_proxy("socks", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text()) |
| 205 | self.configuration.split_proxy("cvs", self.http_proxy.get_text() + ":" + self.http_proxy_port.get_text()) |
| 206 | else: |
| 207 | self.configuration.split_proxy("https", self.https_proxy.get_text() + ":" + self.https_proxy_port.get_text()) |
| 208 | self.configuration.split_proxy("ftp", self.ftp_proxy.get_text() + ":" + self.ftp_proxy_port.get_text()) |
| 209 | self.configuration.split_proxy("socks", self.socks_proxy.get_text() + ":" + self.socks_proxy_port.get_text()) |
| 210 | self.configuration.split_proxy("cvs", self.cvs_proxy.get_text() + ":" + self.cvs_proxy_port.get_text()) |
| 211 | |
| 212 | def response_cb(self, dialog, response_id): |
| 213 | if response_id == gtk.RESPONSE_YES: |
| 214 | if self.proxy_checkbox.get_active(): |
| 215 | # Check that all proxy entries have a corresponding port |
| 216 | for proxy, port in zip(self.all_proxy_addresses, self.all_proxy_ports): |
| 217 | if proxy.get_text() and not port.get_text(): |
| 218 | lbl = "<b>Enter all port numbers</b>" |
| 219 | msg = "Proxy servers require a port number. Please make sure you have entered a port number for each proxy server." |
| 220 | dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_WARNING, msg) |
| 221 | button = dialog.add_button("Close", gtk.RESPONSE_OK) |
| 222 | HobButton.style_button(button) |
| 223 | response = dialog.run() |
| 224 | dialog.destroy() |
| 225 | self.emit_stop_by_name("response") |
| 226 | return |
| 227 | |
| 228 | self.configuration.dldir = self.dldir_text.get_text() |
| 229 | self.configuration.sstatedir = self.sstatedir_text.get_text() |
| 230 | self.configuration.sstatemirror = "" |
| 231 | for mirror in self.sstatemirrors_list: |
| 232 | if mirror[1] != "" and mirror[2].startswith("file://"): |
| 233 | smirror = mirror[2] + " " + mirror[1] + " \\n " |
| 234 | self.configuration.sstatemirror += smirror |
| 235 | self.configuration.bbthread = self.bb_spinner.get_value_as_int() |
| 236 | self.configuration.pmake = self.pmake_spinner.get_value_as_int() |
| 237 | self.save_proxy_data() |
| 238 | self.configuration.extra_setting = {} |
| 239 | it = self.setting_store.get_iter_first() |
| 240 | while it: |
| 241 | key = self.setting_store.get_value(it, 0) |
| 242 | value = self.setting_store.get_value(it, 1) |
| 243 | self.configuration.extra_setting[key] = value |
| 244 | it = self.setting_store.iter_next(it) |
| 245 | |
| 246 | md5 = self.config_md5() |
| 247 | self.settings_changed = (self.md5 != md5) |
| 248 | self.proxy_settings_changed = (self.proxy_md5 != self.config_proxy_md5()) |
| 249 | |
| 250 | def create_build_environment_page(self): |
| 251 | advanced_vbox = gtk.VBox(False, 6) |
| 252 | advanced_vbox.set_border_width(6) |
| 253 | |
| 254 | advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Parallel threads</span>'), expand=False, fill=False) |
| 255 | sub_vbox = gtk.VBox(False, 6) |
| 256 | advanced_vbox.pack_start(sub_vbox, expand=False, fill=False) |
| 257 | label = self.gen_label_widget("BitBake parallel threads") |
| 258 | tooltip = "Sets the number of threads that BitBake tasks can simultaneously run. See the <a href=\"" |
| 259 | tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/" |
| 260 | tooltip += "poky-ref-manual.html#var-BB_NUMBER_THREADS\">Poky reference manual</a> for information" |
| 261 | bbthread_widget, self.bb_spinner = self.gen_spinner_widget(self.configuration.bbthread, 1, self.max_threads,"<b>BitBake prallalel threads</b>" + "*" + tooltip) |
| 262 | sub_vbox.pack_start(label, expand=False, fill=False) |
| 263 | sub_vbox.pack_start(bbthread_widget, expand=False, fill=False) |
| 264 | |
| 265 | sub_vbox = gtk.VBox(False, 6) |
| 266 | advanced_vbox.pack_start(sub_vbox, expand=False, fill=False) |
| 267 | label = self.gen_label_widget("Make parallel threads") |
| 268 | tooltip = "Sets the maximum number of threads the host can use during the build. See the <a href=\"" |
| 269 | tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/" |
| 270 | tooltip += "poky-ref-manual.html#var-PARALLEL_MAKE\">Poky reference manual</a> for information" |
| 271 | pmake_widget, self.pmake_spinner = self.gen_spinner_widget(self.configuration.pmake, 1, self.max_threads,"<b>Make parallel threads</b>" + "*" + tooltip) |
| 272 | sub_vbox.pack_start(label, expand=False, fill=False) |
| 273 | sub_vbox.pack_start(pmake_widget, expand=False, fill=False) |
| 274 | |
| 275 | advanced_vbox.pack_start(self.gen_label_widget('<span weight="bold">Downloaded source code</span>'), expand=False, fill=False) |
| 276 | sub_vbox = gtk.VBox(False, 6) |
| 277 | advanced_vbox.pack_start(sub_vbox, expand=False, fill=False) |
| 278 | label = self.gen_label_widget("Downloads directory") |
| 279 | tooltip = "Select a folder that caches the upstream project source code" |
| 280 | dldir_widget, self.dldir_text = self.gen_entry_widget(self.configuration.dldir, self,"<b>Downloaded source code</b>" + "*" + tooltip) |
| 281 | sub_vbox.pack_start(label, expand=False, fill=False) |
| 282 | sub_vbox.pack_start(dldir_widget, expand=False, fill=False) |
| 283 | |
| 284 | return advanced_vbox |
| 285 | |
| 286 | def create_shared_state_page(self): |
| 287 | advanced_vbox = gtk.VBox(False) |
| 288 | advanced_vbox.set_border_width(12) |
| 289 | |
| 290 | sub_vbox = gtk.VBox(False) |
| 291 | advanced_vbox.pack_start(sub_vbox, expand=False, fill=False, padding=24) |
| 292 | content = "<span>Shared state directory</span>" |
| 293 | tooltip = "Select a folder that caches your prebuilt results" |
| 294 | label = self.gen_label_info_widget(content,"<b>Shared state directory</b>" + "*" + tooltip) |
| 295 | sstatedir_widget, self.sstatedir_text = self.gen_entry_widget(self.configuration.sstatedir, self) |
| 296 | sub_vbox.pack_start(label, expand=False, fill=False) |
| 297 | sub_vbox.pack_start(sstatedir_widget, expand=False, fill=False, padding=6) |
| 298 | |
| 299 | content = "<span weight=\"bold\">Shared state mirrors</span>" |
| 300 | tooltip = "URLs pointing to pre-built mirrors that will speed your build. " |
| 301 | tooltip += "Select the \'Standard\' configuration if the structure of your " |
| 302 | tooltip += "mirror replicates the structure of your local shared state directory. " |
| 303 | tooltip += "For more information on shared state mirrors, check the <a href=\"" |
| 304 | tooltip += "http://www.yoctoproject.org/docs/current/poky-ref-manual/" |
| 305 | tooltip += "poky-ref-manual.html#shared-state\">Yocto Project Reference Manual</a>." |
| 306 | table = self.gen_label_info_widget(content,"<b>Shared state mirrors</b>" + "*" + tooltip) |
| 307 | advanced_vbox.pack_start(table, expand=False, fill=False, padding=6) |
| 308 | |
| 309 | sub_vbox = gtk.VBox(False) |
| 310 | advanced_vbox.pack_start(sub_vbox, gtk.TRUE, gtk.TRUE, 0) |
| 311 | |
| 312 | if self.sstatemirrors_changed == 0: |
| 313 | self.sstatemirrors_changed = 1 |
| 314 | sstatemirrors = self.configuration.sstatemirror |
| 315 | if sstatemirrors == "": |
| 316 | sm_list = ["Standard", "", "file://(.*)"] |
| 317 | self.sstatemirrors_list.append(sm_list) |
| 318 | else: |
| 319 | sstatemirrors = [x for x in sstatemirrors.split('\\n')] |
| 320 | for sstatemirror in sstatemirrors: |
| 321 | sstatemirror_fields = [x for x in sstatemirror.split(' ') if x.strip()] |
| 322 | if len(sstatemirror_fields) == 2: |
| 323 | if sstatemirror_fields[0] == "file://(.*)" or sstatemirror_fields[0] == "file://.*": |
| 324 | sm_list = ["Standard", sstatemirror_fields[1], sstatemirror_fields[0]] |
| 325 | else: |
| 326 | sm_list = ["Custom", sstatemirror_fields[1], sstatemirror_fields[0]] |
| 327 | self.sstatemirrors_list.append(sm_list) |
| 328 | |
| 329 | sstatemirrors_widget, sstatemirrors_store = self.gen_shared_sstate_widget(self.sstatemirrors_list, self) |
| 330 | sub_vbox.pack_start(sstatemirrors_widget, expand=True, fill=True) |
| 331 | |
| 332 | table = gtk.Table(1, 10, False) |
| 333 | table.set_col_spacings(6) |
| 334 | add_mirror_button = HobAltButton("Add mirror") |
| 335 | add_mirror_button.connect("clicked", self.add_mirror) |
| 336 | add_mirror_button.set_size_request(120,30) |
| 337 | table.attach(add_mirror_button, 1, 2, 0, 1, xoptions=gtk.SHRINK) |
| 338 | |
| 339 | self.delete_button = HobAltButton("Delete mirror") |
| 340 | self.delete_button.connect("clicked", self.delete_cb) |
| 341 | self.delete_button.set_size_request(120, 30) |
| 342 | table.attach(self.delete_button, 3, 4, 0, 1, xoptions=gtk.SHRINK) |
| 343 | |
| 344 | advanced_vbox.pack_start(table, expand=False, fill=False, padding=6) |
| 345 | |
| 346 | return advanced_vbox |
| 347 | |
| 348 | def gen_shared_sstate_widget(self, sstatemirrors_list, window): |
| 349 | hbox = gtk.HBox(False) |
| 350 | |
| 351 | sstatemirrors_store = gtk.ListStore(str, str, str) |
| 352 | for sstatemirror in sstatemirrors_list: |
| 353 | sstatemirrors_store.append(sstatemirror) |
| 354 | |
| 355 | self.sstatemirrors_tv = gtk.TreeView() |
| 356 | self.sstatemirrors_tv.set_rules_hint(True) |
| 357 | self.sstatemirrors_tv.set_headers_visible(True) |
| 358 | tree_selection = self.sstatemirrors_tv.get_selection() |
| 359 | tree_selection.set_mode(gtk.SELECTION_SINGLE) |
| 360 | |
| 361 | # Allow enable drag and drop of rows including row move |
| 362 | self.sstatemirrors_tv.enable_model_drag_source( gtk.gdk.BUTTON1_MASK, |
| 363 | self.TARGETS, |
| 364 | gtk.gdk.ACTION_DEFAULT| |
| 365 | gtk.gdk.ACTION_MOVE) |
| 366 | self.sstatemirrors_tv.enable_model_drag_dest(self.TARGETS, |
| 367 | gtk.gdk.ACTION_DEFAULT) |
| 368 | self.sstatemirrors_tv.connect("drag_data_get", self.drag_data_get_cb) |
| 369 | self.sstatemirrors_tv.connect("drag_data_received", self.drag_data_received_cb) |
| 370 | |
| 371 | |
| 372 | self.scroll = gtk.ScrolledWindow() |
| 373 | self.scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) |
| 374 | self.scroll.set_shadow_type(gtk.SHADOW_IN) |
| 375 | self.scroll.connect('size-allocate', self.scroll_changed) |
| 376 | self.scroll.add(self.sstatemirrors_tv) |
| 377 | |
| 378 | #list store for cell renderer |
| 379 | m = gtk.ListStore(gobject.TYPE_STRING) |
| 380 | m.append(["Standard"]) |
| 381 | m.append(["Custom"]) |
| 382 | |
| 383 | cell0 = gtk.CellRendererCombo() |
| 384 | cell0.set_property("model",m) |
| 385 | cell0.set_property("text-column", 0) |
| 386 | cell0.set_property("editable", True) |
| 387 | cell0.set_property("has-entry", False) |
| 388 | col0 = gtk.TreeViewColumn("Configuration") |
| 389 | col0.pack_start(cell0, False) |
| 390 | col0.add_attribute(cell0, "text", 0) |
| 391 | col0.set_cell_data_func(cell0, self.configuration_field) |
| 392 | self.sstatemirrors_tv.append_column(col0) |
| 393 | |
| 394 | cell0.connect("edited", self.combo_changed, sstatemirrors_store) |
| 395 | |
| 396 | self.cell1 = gtk.CellRendererText() |
| 397 | self.cell1.set_padding(5,2) |
| 398 | col1 = gtk.TreeViewColumn('Regex', self.cell1) |
| 399 | col1.set_cell_data_func(self.cell1, self.regex_field) |
| 400 | self.sstatemirrors_tv.append_column(col1) |
| 401 | |
| 402 | self.cell1.connect("edited", self.regex_changed, sstatemirrors_store) |
| 403 | |
| 404 | cell2 = gtk.CellRendererText() |
| 405 | cell2.set_padding(5,2) |
| 406 | cell2.set_property("editable", True) |
| 407 | col2 = gtk.TreeViewColumn('URL', cell2) |
| 408 | col2.set_cell_data_func(cell2, self.url_field) |
| 409 | self.sstatemirrors_tv.append_column(col2) |
| 410 | |
| 411 | cell2.connect("edited", self.url_changed, sstatemirrors_store) |
| 412 | |
| 413 | self.sstatemirrors_tv.set_model(sstatemirrors_store) |
| 414 | self.sstatemirrors_tv.set_cursor(self.selected_mirror_row) |
| 415 | hbox.pack_start(self.scroll, expand=True, fill=True) |
| 416 | hbox.show_all() |
| 417 | |
| 418 | return hbox, sstatemirrors_store |
| 419 | |
| 420 | def drag_data_get_cb(self, treeview, context, selection, target_id, etime): |
| 421 | treeselection = treeview.get_selection() |
| 422 | model, iter = treeselection.get_selected() |
| 423 | data = model.get_string_from_iter(iter) |
| 424 | selection.set(selection.target, 8, data) |
| 425 | |
| 426 | def drag_data_received_cb(self, treeview, context, x, y, selection, info, etime): |
| 427 | model = treeview.get_model() |
| 428 | data = [] |
| 429 | tree_iter = model.get_iter_from_string(selection.data) |
| 430 | data.append(model.get_value(tree_iter, 0)) |
| 431 | data.append(model.get_value(tree_iter, 1)) |
| 432 | data.append(model.get_value(tree_iter, 2)) |
| 433 | |
| 434 | drop_info = treeview.get_dest_row_at_pos(x, y) |
| 435 | if drop_info: |
| 436 | path, position = drop_info |
| 437 | iter = model.get_iter(path) |
| 438 | if (position == gtk.TREE_VIEW_DROP_BEFORE or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE): |
| 439 | model.insert_before(iter, data) |
| 440 | else: |
| 441 | model.insert_after(iter, data) |
| 442 | else: |
| 443 | model.append(data) |
| 444 | if context.action == gtk.gdk.ACTION_MOVE: |
| 445 | context.finish(True, True, etime) |
| 446 | return |
| 447 | |
| 448 | def delete_cb(self, button): |
| 449 | selection = self.sstatemirrors_tv.get_selection() |
| 450 | tree_model, tree_iter = selection.get_selected() |
| 451 | index = int(tree_model.get_string_from_iter(tree_iter)) |
| 452 | if index == 0: |
| 453 | self.selected_mirror_row = index |
| 454 | else: |
| 455 | self.selected_mirror_row = index - 1 |
| 456 | self.sstatemirrors_list.pop(index) |
| 457 | self.refresh_shared_state_page() |
| 458 | if not self.sstatemirrors_list: |
| 459 | self.delete_button.set_sensitive(False) |
| 460 | |
| 461 | def add_mirror(self, button): |
| 462 | self.new_mirror = True |
| 463 | tooltip = "Select the pre-built mirror that will speed your build" |
| 464 | index = len(self.sstatemirrors_list) |
| 465 | self.selected_mirror_row = index |
| 466 | sm_list = ["Standard", "", "file://(.*)"] |
| 467 | self.sstatemirrors_list.append(sm_list) |
| 468 | self.refresh_shared_state_page() |
| 469 | |
| 470 | def scroll_changed(self, widget, event, data=None): |
| 471 | if self.new_mirror == True: |
| 472 | adj = widget.get_vadjustment() |
| 473 | adj.set_value(adj.upper - adj.page_size) |
| 474 | self.new_mirror = False |
| 475 | |
| 476 | def combo_changed(self, widget, path, text, model): |
| 477 | model[path][0] = text |
| 478 | selection = self.sstatemirrors_tv.get_selection() |
| 479 | tree_model, tree_iter = selection.get_selected() |
| 480 | index = int(tree_model.get_string_from_iter(tree_iter)) |
| 481 | self.sstatemirrors_list[index][0] = text |
| 482 | |
| 483 | def regex_changed(self, cell, path, new_text, user_data): |
| 484 | user_data[path][2] = new_text |
| 485 | selection = self.sstatemirrors_tv.get_selection() |
| 486 | tree_model, tree_iter = selection.get_selected() |
| 487 | index = int(tree_model.get_string_from_iter(tree_iter)) |
| 488 | self.sstatemirrors_list[index][2] = new_text |
| 489 | return |
| 490 | |
| 491 | def url_changed(self, cell, path, new_text, user_data): |
| 492 | if new_text!="Enter the mirror URL" and new_text!="Match regex and replace it with this URL": |
| 493 | user_data[path][1] = new_text |
| 494 | selection = self.sstatemirrors_tv.get_selection() |
| 495 | tree_model, tree_iter = selection.get_selected() |
| 496 | index = int(tree_model.get_string_from_iter(tree_iter)) |
| 497 | self.sstatemirrors_list[index][1] = new_text |
| 498 | return |
| 499 | |
| 500 | def configuration_field(self, column, cell, model, iter): |
| 501 | cell.set_property('text', model.get_value(iter, 0)) |
| 502 | if model.get_value(iter, 0) == "Standard": |
| 503 | self.cell1.set_property("sensitive", False) |
| 504 | self.cell1.set_property("editable", False) |
| 505 | else: |
| 506 | self.cell1.set_property("sensitive", True) |
| 507 | self.cell1.set_property("editable", True) |
| 508 | return |
| 509 | |
| 510 | def regex_field(self, column, cell, model, iter): |
| 511 | cell.set_property('text', model.get_value(iter, 2)) |
| 512 | return |
| 513 | |
| 514 | def url_field(self, column, cell, model, iter): |
| 515 | text = model.get_value(iter, 1) |
| 516 | if text == "": |
| 517 | if model.get_value(iter, 0) == "Standard": |
| 518 | text = "Enter the mirror URL" |
| 519 | else: |
| 520 | text = "Match regex and replace it with this URL" |
| 521 | cell.set_property('text', text) |
| 522 | return |
| 523 | |
| 524 | def refresh_shared_state_page(self): |
| 525 | page_num = self.nb.get_current_page() |
| 526 | self.nb.remove_page(page_num); |
| 527 | self.nb.insert_page(self.create_shared_state_page(), gtk.Label("Shared state"),page_num) |
| 528 | self.show_all() |
| 529 | self.nb.set_current_page(page_num) |
| 530 | |
| 531 | def test_proxy_ended(self, passed): |
| 532 | self.proxy_test_running = False |
| 533 | self.set_test_proxy_state(self.TEST_NETWORK_PASSED if passed else self.TEST_NETWORK_FAILED) |
| 534 | self.set_sensitive(True) |
| 535 | self.refresh_proxy_components() |
| 536 | |
| 537 | def timer_func(self): |
| 538 | self.test_proxy_progress.pulse() |
| 539 | return self.proxy_test_running |
| 540 | |
| 541 | def test_network_button_cb(self, b): |
| 542 | self.set_test_proxy_state(self.TEST_NETWORK_RUNNING) |
| 543 | self.set_sensitive(False) |
| 544 | self.save_proxy_data() |
| 545 | if self.configuration.enable_proxy == True: |
| 546 | self.handler.set_http_proxy(self.configuration.combine_proxy("http")) |
| 547 | self.handler.set_https_proxy(self.configuration.combine_proxy("https")) |
| 548 | self.handler.set_ftp_proxy(self.configuration.combine_proxy("ftp")) |
| 549 | self.handler.set_socks_proxy(self.configuration.combine_proxy("socks")) |
| 550 | self.handler.set_cvs_proxy(self.configuration.combine_host_only("cvs"), self.configuration.combine_port_only("cvs")) |
| 551 | elif self.configuration.enable_proxy == False: |
| 552 | self.handler.set_http_proxy("") |
| 553 | self.handler.set_https_proxy("") |
| 554 | self.handler.set_ftp_proxy("") |
| 555 | self.handler.set_socks_proxy("") |
| 556 | self.handler.set_cvs_proxy("", "") |
| 557 | self.proxy_test_ran = True |
| 558 | self.proxy_test_running = True |
| 559 | gobject.timeout_add(100, self.timer_func) |
| 560 | self.handler.trigger_network_test() |
| 561 | |
| 562 | def test_proxy_focus_event(self, w, direction): |
| 563 | if self.test_proxy_state in [self.TEST_NETWORK_PASSED, self.TEST_NETWORK_FAILED]: |
| 564 | self.set_test_proxy_state(self.TEST_NETWORK_INITIAL) |
| 565 | return False |
| 566 | |
| 567 | def http_proxy_changed(self, e): |
| 568 | if not self.configuration.same_proxy: |
| 569 | return |
| 570 | if e == self.http_proxy: |
| 571 | [w.set_text(self.http_proxy.get_text()) for w in self.same_proxy_addresses] |
| 572 | else: |
| 573 | [w.set_text(self.http_proxy_port.get_text()) for w in self.same_proxy_ports] |
| 574 | |
| 575 | def proxy_address_focus_out_event(self, w, direction): |
| 576 | text = w.get_text() |
| 577 | if not text: |
| 578 | return False |
| 579 | if text.find("//") == -1: |
| 580 | w.set_text("http://" + text) |
| 581 | return False |
| 582 | |
| 583 | def set_test_proxy_state(self, state): |
| 584 | if self.test_proxy_state == state: |
| 585 | return |
| 586 | [self.proxy_table.remove(w) for w in self.test_gui_elements] |
| 587 | if state == self.TEST_NETWORK_INITIAL: |
| 588 | self.proxy_table.attach(self.test_network_button, 1, 2, 5, 6) |
| 589 | self.test_network_button.show() |
| 590 | elif state == self.TEST_NETWORK_RUNNING: |
| 591 | self.test_proxy_progress.set_rcstyle("running") |
| 592 | self.test_proxy_progress.set_text("Testing network configuration") |
| 593 | self.proxy_table.attach(self.test_proxy_progress, 0, 5, 5, 6, xpadding=4) |
| 594 | self.test_proxy_progress.show() |
| 595 | else: # passed or failed |
| 596 | self.dummy_progress.update(1.0) |
| 597 | if state == self.TEST_NETWORK_PASSED: |
| 598 | self.dummy_progress.set_text("Your network is properly configured") |
| 599 | self.dummy_progress.set_rcstyle("running") |
| 600 | else: |
| 601 | self.dummy_progress.set_text("Network test failed") |
| 602 | self.dummy_progress.set_rcstyle("fail") |
| 603 | self.proxy_table.attach(self.dummy_progress, 0, 4, 5, 6) |
| 604 | self.proxy_table.attach(self.retest_network_button, 4, 5, 5, 6, xpadding=4) |
| 605 | self.dummy_progress.show() |
| 606 | self.retest_network_button.show() |
| 607 | self.test_proxy_state = state |
| 608 | |
| 609 | def create_network_page(self): |
| 610 | advanced_vbox = gtk.VBox(False, 6) |
| 611 | advanced_vbox.set_border_width(6) |
| 612 | self.same_proxy_addresses = [] |
| 613 | self.same_proxy_ports = [] |
| 614 | self.all_proxy_ports = [] |
| 615 | self.all_proxy_addresses = [] |
| 616 | |
| 617 | sub_vbox = gtk.VBox(False, 6) |
| 618 | advanced_vbox.pack_start(sub_vbox, expand=False, fill=False) |
| 619 | label = self.gen_label_widget("<span weight=\"bold\">Set the proxies used when fetching source code</span>") |
| 620 | tooltip = "Set the proxies used when fetching source code. A blank field uses a direct internet connection." |
| 621 | info = HobInfoButton("<span weight=\"bold\">Set the proxies used when fetching source code</span>" + "*" + tooltip, self) |
| 622 | hbox = gtk.HBox(False, 12) |
| 623 | hbox.pack_start(label, expand=True, fill=True) |
| 624 | hbox.pack_start(info, expand=False, fill=False) |
| 625 | sub_vbox.pack_start(hbox, expand=False, fill=False) |
| 626 | |
| 627 | proxy_test_focus = [] |
| 628 | self.direct_checkbox = gtk.RadioButton(None, "Direct network connection") |
| 629 | proxy_test_focus.append(self.direct_checkbox) |
| 630 | self.direct_checkbox.set_tooltip_text("Check this box to use a direct internet connection with no proxy") |
| 631 | self.direct_checkbox.set_active(not self.configuration.enable_proxy) |
| 632 | sub_vbox.pack_start(self.direct_checkbox, expand=False, fill=False) |
| 633 | |
| 634 | self.proxy_checkbox = gtk.RadioButton(self.direct_checkbox, "Manual proxy configuration") |
| 635 | proxy_test_focus.append(self.proxy_checkbox) |
| 636 | self.proxy_checkbox.set_tooltip_text("Check this box to manually set up a specific proxy") |
| 637 | self.proxy_checkbox.set_active(self.configuration.enable_proxy) |
| 638 | sub_vbox.pack_start(self.proxy_checkbox, expand=False, fill=False) |
| 639 | |
| 640 | self.same_checkbox = gtk.CheckButton("Use the HTTP proxy for all protocols") |
| 641 | proxy_test_focus.append(self.same_checkbox) |
| 642 | self.same_checkbox.set_tooltip_text("Check this box to use the HTTP proxy for all five proxies") |
| 643 | self.same_checkbox.set_active(self.configuration.same_proxy) |
| 644 | hbox = gtk.HBox(False, 12) |
| 645 | hbox.pack_start(self.same_checkbox, expand=False, fill=False, padding=24) |
| 646 | sub_vbox.pack_start(hbox, expand=False, fill=False) |
| 647 | |
| 648 | self.proxy_table = gtk.Table(6, 5, False) |
| 649 | self.http_proxy, self.http_proxy_port, self.http_proxy_details = self.gen_proxy_entry_widget( |
| 650 | "http", self, True, 0) |
| 651 | proxy_test_focus +=[self.http_proxy, self.http_proxy_port] |
| 652 | self.http_proxy.connect("changed", self.http_proxy_changed) |
| 653 | self.http_proxy_port.connect("changed", self.http_proxy_changed) |
| 654 | |
| 655 | self.https_proxy, self.https_proxy_port, self.https_proxy_details = self.gen_proxy_entry_widget( |
| 656 | "https", self, True, 1) |
| 657 | proxy_test_focus += [self.https_proxy, self.https_proxy_port] |
| 658 | self.same_proxy_addresses.append(self.https_proxy) |
| 659 | self.same_proxy_ports.append(self.https_proxy_port) |
| 660 | |
| 661 | self.ftp_proxy, self.ftp_proxy_port, self.ftp_proxy_details = self.gen_proxy_entry_widget( |
| 662 | "ftp", self, True, 2) |
| 663 | proxy_test_focus += [self.ftp_proxy, self.ftp_proxy_port] |
| 664 | self.same_proxy_addresses.append(self.ftp_proxy) |
| 665 | self.same_proxy_ports.append(self.ftp_proxy_port) |
| 666 | |
| 667 | self.socks_proxy, self.socks_proxy_port, self.socks_proxy_details = self.gen_proxy_entry_widget( |
| 668 | "socks", self, True, 3) |
| 669 | proxy_test_focus += [self.socks_proxy, self.socks_proxy_port] |
| 670 | self.same_proxy_addresses.append(self.socks_proxy) |
| 671 | self.same_proxy_ports.append(self.socks_proxy_port) |
| 672 | |
| 673 | self.cvs_proxy, self.cvs_proxy_port, self.cvs_proxy_details = self.gen_proxy_entry_widget( |
| 674 | "cvs", self, True, 4) |
| 675 | proxy_test_focus += [self.cvs_proxy, self.cvs_proxy_port] |
| 676 | self.same_proxy_addresses.append(self.cvs_proxy) |
| 677 | self.same_proxy_ports.append(self.cvs_proxy_port) |
| 678 | self.all_proxy_ports = self.same_proxy_ports + [self.http_proxy_port] |
| 679 | self.all_proxy_addresses = self.same_proxy_addresses + [self.http_proxy] |
| 680 | sub_vbox.pack_start(self.proxy_table, expand=False, fill=False) |
| 681 | self.proxy_table.show_all() |
| 682 | |
| 683 | # Create the graphical elements for the network test feature, but don't display them yet |
| 684 | self.test_network_button = HobAltButton("Test network configuration") |
| 685 | self.test_network_button.connect("clicked", self.test_network_button_cb) |
| 686 | self.test_proxy_progress = HobProgressBar() |
| 687 | self.dummy_progress = HobProgressBar() |
| 688 | self.retest_network_button = HobAltButton("Retest") |
| 689 | self.retest_network_button.connect("clicked", self.test_network_button_cb) |
| 690 | self.test_gui_elements = [self.test_network_button, self.test_proxy_progress, self.dummy_progress, self.retest_network_button] |
| 691 | # Initialize the network tester |
| 692 | self.test_proxy_state = self.TEST_NETWORK_NONE |
| 693 | self.set_test_proxy_state(self.TEST_NETWORK_INITIAL) |
| 694 | self.proxy_test_passed_id = self.handler.connect("network-passed", lambda h:self.test_proxy_ended(True)) |
| 695 | self.proxy_test_failed_id = self.handler.connect("network-failed", lambda h:self.test_proxy_ended(False)) |
| 696 | [w.connect("focus-in-event", self.test_proxy_focus_event) for w in proxy_test_focus] |
| 697 | [w.connect("focus-out-event", self.proxy_address_focus_out_event) for w in self.all_proxy_addresses] |
| 698 | |
| 699 | self.direct_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb) |
| 700 | self.proxy_checkbox.connect("toggled", self.proxy_checkbox_toggled_cb) |
| 701 | self.same_checkbox.connect("toggled", self.same_checkbox_toggled_cb) |
| 702 | |
| 703 | self.refresh_proxy_components() |
| 704 | return advanced_vbox |
| 705 | |
| 706 | def switch_to_page(self, page_id): |
| 707 | self.nb.set_current_page(page_id) |
| 708 | |
| 709 | def details_cb(self, button, parent, protocol): |
| 710 | self.save_proxy_data() |
| 711 | dialog = ProxyDetailsDialog(title = protocol.upper() + " Proxy Details", |
| 712 | user = self.configuration.proxies[protocol][1], |
| 713 | passwd = self.configuration.proxies[protocol][2], |
| 714 | parent = parent, |
| 715 | flags = gtk.DIALOG_MODAL |
| 716 | | gtk.DIALOG_DESTROY_WITH_PARENT |
| 717 | | gtk.DIALOG_NO_SEPARATOR) |
| 718 | dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK) |
| 719 | response = dialog.run() |
| 720 | if response == gtk.RESPONSE_OK: |
| 721 | self.configuration.proxies[protocol][1] = dialog.user |
| 722 | self.configuration.proxies[protocol][2] = dialog.passwd |
| 723 | self.refresh_proxy_components() |
| 724 | dialog.destroy() |
| 725 | |
| 726 | def rootfs_combo_changed_cb(self, rootfs_combo, all_package_format, check_hbox): |
| 727 | combo_item = self.rootfs_combo.get_active_text() |
| 728 | for child in check_hbox.get_children(): |
| 729 | if isinstance(child, gtk.CheckButton): |
| 730 | check_hbox.remove(child) |
| 731 | for format in all_package_format: |
| 732 | if format != combo_item: |
| 733 | check_button = gtk.CheckButton(format) |
| 734 | check_hbox.pack_start(check_button, expand=False, fill=False) |
| 735 | check_hbox.show_all() |
| 736 | |
| 737 | def gen_pkgfmt_widget(self, curr_package_format, all_package_format, tooltip_combo="", tooltip_extra=""): |
| 738 | pkgfmt_hbox = gtk.HBox(False, 24) |
| 739 | |
| 740 | rootfs_vbox = gtk.VBox(False, 6) |
| 741 | pkgfmt_hbox.pack_start(rootfs_vbox, expand=False, fill=False) |
| 742 | |
| 743 | label = self.gen_label_widget("Root file system package format") |
| 744 | rootfs_vbox.pack_start(label, expand=False, fill=False) |
| 745 | |
| 746 | rootfs_format = "" |
| 747 | if curr_package_format: |
| 748 | rootfs_format = curr_package_format.split()[0] |
| 749 | |
| 750 | rootfs_format_widget, rootfs_combo = self.gen_combo_widget(rootfs_format, all_package_format, tooltip_combo) |
| 751 | rootfs_vbox.pack_start(rootfs_format_widget, expand=False, fill=False) |
| 752 | |
| 753 | extra_vbox = gtk.VBox(False, 6) |
| 754 | pkgfmt_hbox.pack_start(extra_vbox, expand=False, fill=False) |
| 755 | |
| 756 | label = self.gen_label_widget("Additional package formats") |
| 757 | extra_vbox.pack_start(label, expand=False, fill=False) |
| 758 | |
| 759 | check_hbox = gtk.HBox(False, 12) |
| 760 | extra_vbox.pack_start(check_hbox, expand=False, fill=False) |
| 761 | for format in all_package_format: |
| 762 | if format != rootfs_format: |
| 763 | check_button = gtk.CheckButton(format) |
| 764 | is_active = (format in curr_package_format.split()) |
| 765 | check_button.set_active(is_active) |
| 766 | check_hbox.pack_start(check_button, expand=False, fill=False) |
| 767 | |
| 768 | info = HobInfoButton(tooltip_extra, self) |
| 769 | check_hbox.pack_end(info, expand=False, fill=False) |
| 770 | |
| 771 | rootfs_combo.connect("changed", self.rootfs_combo_changed_cb, all_package_format, check_hbox) |
| 772 | |
| 773 | pkgfmt_hbox.show_all() |
| 774 | |
| 775 | return pkgfmt_hbox, rootfs_combo, check_hbox |
| 776 | |
| 777 | def editable_settings_cell_edited(self, cell, path_string, new_text, model): |
| 778 | it = model.get_iter_from_string(path_string) |
| 779 | column = cell.get_data("column") |
| 780 | model.set(it, column, new_text) |
| 781 | |
| 782 | def editable_settings_add_item_clicked(self, button, model): |
| 783 | new_item = ["##KEY##", "##VALUE##"] |
| 784 | |
| 785 | iter = model.append() |
| 786 | model.set (iter, |
| 787 | 0, new_item[0], |
| 788 | 1, new_item[1], |
| 789 | ) |
| 790 | |
| 791 | def editable_settings_remove_item_clicked(self, button, treeview): |
| 792 | selection = treeview.get_selection() |
| 793 | model, iter = selection.get_selected() |
| 794 | |
| 795 | if iter: |
| 796 | path = model.get_path(iter)[0] |
| 797 | model.remove(iter) |
| 798 | |
| 799 | def gen_editable_settings(self, setting, tooltip=""): |
| 800 | setting_hbox = gtk.HBox(False, 12) |
| 801 | |
| 802 | vbox = gtk.VBox(False, 12) |
| 803 | setting_hbox.pack_start(vbox, expand=True, fill=True) |
| 804 | |
| 805 | setting_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_STRING) |
| 806 | for key in setting.keys(): |
| 807 | setting_store.set(setting_store.append(), 0, key, 1, setting[key]) |
| 808 | |
| 809 | setting_tree = gtk.TreeView(setting_store) |
| 810 | setting_tree.set_headers_visible(True) |
| 811 | setting_tree.set_size_request(300, 100) |
| 812 | |
| 813 | col = gtk.TreeViewColumn('Key') |
| 814 | col.set_min_width(100) |
| 815 | col.set_max_width(150) |
| 816 | col.set_resizable(True) |
| 817 | col1 = gtk.TreeViewColumn('Value') |
| 818 | col1.set_min_width(100) |
| 819 | col1.set_max_width(150) |
| 820 | col1.set_resizable(True) |
| 821 | setting_tree.append_column(col) |
| 822 | setting_tree.append_column(col1) |
| 823 | cell = gtk.CellRendererText() |
| 824 | cell.set_property('width-chars', 10) |
| 825 | cell.set_property('editable', True) |
| 826 | cell.set_data("column", 0) |
| 827 | cell.connect("edited", self.editable_settings_cell_edited, setting_store) |
| 828 | cell1 = gtk.CellRendererText() |
| 829 | cell1.set_property('width-chars', 10) |
| 830 | cell1.set_property('editable', True) |
| 831 | cell1.set_data("column", 1) |
| 832 | cell1.connect("edited", self.editable_settings_cell_edited, setting_store) |
| 833 | col.pack_start(cell, True) |
| 834 | col1.pack_end(cell1, True) |
| 835 | col.set_attributes(cell, text=0) |
| 836 | col1.set_attributes(cell1, text=1) |
| 837 | |
| 838 | scroll = gtk.ScrolledWindow() |
| 839 | scroll.set_shadow_type(gtk.SHADOW_IN) |
| 840 | scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) |
| 841 | scroll.add(setting_tree) |
| 842 | vbox.pack_start(scroll, expand=True, fill=True) |
| 843 | |
| 844 | # some buttons |
| 845 | hbox = gtk.HBox(True, 6) |
| 846 | vbox.pack_start(hbox, False, False) |
| 847 | |
| 848 | button = gtk.Button(stock=gtk.STOCK_ADD) |
| 849 | button.connect("clicked", self.editable_settings_add_item_clicked, setting_store) |
| 850 | hbox.pack_start(button) |
| 851 | |
| 852 | button = gtk.Button(stock=gtk.STOCK_REMOVE) |
| 853 | button.connect("clicked", self.editable_settings_remove_item_clicked, setting_tree) |
| 854 | hbox.pack_start(button) |
| 855 | |
| 856 | info = HobInfoButton(tooltip, self) |
| 857 | setting_hbox.pack_start(info, expand=False, fill=False) |
| 858 | |
| 859 | return setting_hbox, setting_store |
| 860 | |
| 861 | def create_others_page(self): |
| 862 | advanced_vbox = gtk.VBox(False, 6) |
| 863 | advanced_vbox.set_border_width(6) |
| 864 | |
| 865 | sub_vbox = gtk.VBox(False, 6) |
| 866 | advanced_vbox.pack_start(sub_vbox, expand=True, fill=True) |
| 867 | label = self.gen_label_widget("<span weight=\"bold\">Add your own variables:</span>") |
| 868 | tooltip = "These are key/value pairs for your extra settings. Click \'Add\' and then directly edit the key and the value" |
| 869 | setting_widget, self.setting_store = self.gen_editable_settings(self.configuration.extra_setting,"<b>Add your own variables</b>" + "*" + tooltip) |
| 870 | sub_vbox.pack_start(label, expand=False, fill=False) |
| 871 | sub_vbox.pack_start(setting_widget, expand=True, fill=True) |
| 872 | |
| 873 | return advanced_vbox |
| 874 | |
| 875 | def create_visual_elements(self): |
| 876 | self.nb = gtk.Notebook() |
| 877 | self.nb.set_show_tabs(True) |
| 878 | self.nb.append_page(self.create_build_environment_page(), gtk.Label("Build environment")) |
| 879 | self.nb.append_page(self.create_shared_state_page(), gtk.Label("Shared state")) |
| 880 | self.nb.append_page(self.create_network_page(), gtk.Label("Network")) |
| 881 | self.nb.append_page(self.create_others_page(), gtk.Label("Others")) |
| 882 | self.nb.set_current_page(0) |
| 883 | self.vbox.pack_start(self.nb, expand=True, fill=True) |
| 884 | self.vbox.pack_end(gtk.HSeparator(), expand=True, fill=True) |
| 885 | |
| 886 | self.show_all() |
| 887 | |
| 888 | def destroy(self): |
| 889 | self.handler.disconnect(self.proxy_test_passed_id) |
| 890 | self.handler.disconnect(self.proxy_test_failed_id) |
| 891 | super(SimpleSettingsDialog, self).destroy() |