diff options
Diffstat (limited to 'import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig')
8 files changed, 1362 insertions, 0 deletions
diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/__init__.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/__init__.py diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py new file mode 100644 index 000000000..c679f9a07 --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/crumbsdialog.py @@ -0,0 +1,44 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Joshua Lock <josh@linux.intel.com> +# Authored by Dongxiao Xu <dongxiao.xu@intel.com> +# Authored by Shane Wang <shane.wang@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import gtk + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class CrumbsDialog(gtk.Dialog): + """ + A GNOME HIG compliant dialog widget. + Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons + """ + def __init__(self, title="", parent=None, flags=0, buttons=None): + super(CrumbsDialog, self).__init__(title, parent, flags, buttons) + + self.set_property("has-separator", False) # note: deprecated in 2.22 + + self.set_border_width(6) + self.vbox.set_property("spacing", 12) + self.action_area.set_property("spacing", 12) + self.action_area.set_property("border-width", 6) diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py new file mode 100644 index 000000000..3b998e463 --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/crumbsmessagedialog.py @@ -0,0 +1,70 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Joshua Lock <josh@linux.intel.com> +# Authored by Dongxiao Xu <dongxiao.xu@intel.com> +# Authored by Shane Wang <shane.wang@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import glib +import gtk +from bb.ui.crumbs.hobwidget import HobIconChecker +from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class CrumbsMessageDialog(gtk.MessageDialog): + """ + A GNOME HIG compliant dialog widget. + Add buttons with gtk.Dialog.add_button or gtk.Dialog.add_buttons + """ + def __init__(self, parent = None, label="", dialog_type = gtk.MESSAGE_QUESTION, msg=""): + super(CrumbsMessageDialog, self).__init__(None, + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, + dialog_type, + gtk.BUTTONS_NONE, + None) + + self.set_skip_taskbar_hint(False) + + self.set_markup(label) + + if 0 <= len(msg) < 300: + self.format_secondary_markup(msg) + else: + vbox = self.get_message_area() + vbox.set_border_width(1) + vbox.set_property("spacing", 12) + self.textWindow = gtk.ScrolledWindow() + self.textWindow.set_shadow_type(gtk.SHADOW_IN) + self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.msgView = gtk.TextView() + self.msgView.set_editable(False) + self.msgView.set_wrap_mode(gtk.WRAP_WORD) + self.msgView.set_cursor_visible(False) + self.msgView.set_size_request(300, 300) + self.buf = gtk.TextBuffer() + self.buf.set_text(msg) + self.msgView.set_buffer(self.buf) + self.textWindow.add(self.msgView) + self.msgView.show() + vbox.add(self.textWindow) + self.textWindow.show() diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py new file mode 100644 index 000000000..a13fff906 --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/deployimagedialog.py @@ -0,0 +1,219 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Joshua Lock <josh@linux.intel.com> +# Authored by Dongxiao Xu <dongxiao.xu@intel.com> +# Authored by Shane Wang <shane.wang@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import glob +import gtk +import gobject +import os +import re +import shlex +import subprocess +import tempfile +from bb.ui.crumbs.hobwidget import hic, HobButton +from bb.ui.crumbs.progressbar import HobProgressBar +import bb.ui.crumbs.utils +import bb.process +from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog +from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class DeployImageDialog (CrumbsDialog): + + __dummy_usb__ = "--select a usb drive--" + + def __init__(self, title, image_path, parent, flags, buttons=None, standalone=False): + super(DeployImageDialog, self).__init__(title, parent, flags, buttons) + + self.image_path = image_path + self.standalone = standalone + + self.create_visual_elements() + self.connect("response", self.response_cb) + + def create_visual_elements(self): + self.set_size_request(600, 400) + label = gtk.Label() + label.set_alignment(0.0, 0.5) + markup = "<span font_desc='12'>The image to be written into usb drive:</span>" + label.set_markup(markup) + self.vbox.pack_start(label, expand=False, fill=False, padding=2) + + table = gtk.Table(2, 10, False) + table.set_col_spacings(5) + table.set_row_spacings(5) + self.vbox.pack_start(table, expand=True, fill=True) + + scroll = gtk.ScrolledWindow() + scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + scroll.set_shadow_type(gtk.SHADOW_IN) + tv = gtk.TextView() + tv.set_editable(False) + tv.set_wrap_mode(gtk.WRAP_WORD) + tv.set_cursor_visible(False) + self.buf = gtk.TextBuffer() + self.buf.set_text(self.image_path) + tv.set_buffer(self.buf) + scroll.add(tv) + table.attach(scroll, 0, 10, 0, 1) + + # There are 2 ways to use DeployImageDialog + # One way is that called by HOB when the 'Deploy Image' button is clicked + # The other way is that called by a standalone script. + # Following block of codes handles the latter way. It adds a 'Select Image' button and + # emit a signal when the button is clicked. + if self.standalone: + gobject.signal_new("select_image_clicked", self, gobject.SIGNAL_RUN_FIRST, + gobject.TYPE_NONE, ()) + icon = gtk.Image() + pix_buffer = gtk.gdk.pixbuf_new_from_file(hic.ICON_IMAGES_DISPLAY_FILE) + icon.set_from_pixbuf(pix_buffer) + button = gtk.Button("Select Image") + button.set_image(icon) + #button.set_size_request(140, 50) + table.attach(button, 9, 10, 1, 2, gtk.FILL, 0, 0, 0) + button.connect("clicked", self.select_image_button_clicked_cb) + + separator = gtk.HSeparator() + self.vbox.pack_start(separator, expand=False, fill=False, padding=10) + + self.usb_desc = gtk.Label() + self.usb_desc.set_alignment(0.0, 0.5) + markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>" + self.usb_desc.set_markup(markup) + + self.usb_combo = gtk.combo_box_new_text() + self.usb_combo.connect("changed", self.usb_combo_changed_cb) + model = self.usb_combo.get_model() + model.clear() + self.usb_combo.append_text(self.__dummy_usb__) + for usb in self.find_all_usb_devices(): + self.usb_combo.append_text("/dev/" + usb) + self.usb_combo.set_active(0) + self.vbox.pack_start(self.usb_combo, expand=False, fill=False) + self.vbox.pack_start(self.usb_desc, expand=False, fill=False, padding=2) + + self.progress_bar = HobProgressBar() + self.vbox.pack_start(self.progress_bar, expand=False, fill=False) + separator = gtk.HSeparator() + self.vbox.pack_start(separator, expand=False, fill=True, padding=10) + + self.vbox.show_all() + self.progress_bar.hide() + + def set_image_text_buffer(self, image_path): + self.buf.set_text(image_path) + + def set_image_path(self, image_path): + self.image_path = image_path + + def popen_read(self, cmd): + tmpout, errors = bb.process.run("%s" % cmd) + return tmpout.strip() + + def find_all_usb_devices(self): + usb_devs = [ os.readlink(u) + for u in glob.glob('/dev/disk/by-id/usb*') + if not re.search(r'part\d+', u) ] + return [ '%s' % u[u.rfind('/')+1:] for u in usb_devs ] + + def get_usb_info(self, dev): + return "%s %s" % \ + (self.popen_read('cat /sys/class/block/%s/device/vendor' % dev), + self.popen_read('cat /sys/class/block/%s/device/model' % dev)) + + def select_image_button_clicked_cb(self, button): + self.emit('select_image_clicked') + + def usb_combo_changed_cb(self, usb_combo): + combo_item = self.usb_combo.get_active_text() + if not combo_item or combo_item == self.__dummy_usb__: + markup = "<span font_desc='12'>You haven't chosen any USB drive.</span>" + self.usb_desc.set_markup(markup) + else: + markup = "<span font_desc='12'>" + self.get_usb_info(combo_item.lstrip("/dev/")) + "</span>" + self.usb_desc.set_markup(markup) + + def response_cb(self, dialog, response_id): + if response_id == gtk.RESPONSE_YES: + lbl = '' + msg = '' + combo_item = self.usb_combo.get_active_text() + if combo_item and combo_item != self.__dummy_usb__ and self.image_path: + cmdline = bb.ui.crumbs.utils.which_terminal() + if cmdline: + tmpfile = tempfile.NamedTemporaryFile() + cmdline += "\"sudo dd if=" + self.image_path + \ + " of=" + combo_item + " && sync; echo $? > " + tmpfile.name + "\"" + subprocess.call(shlex.split(cmdline)) + + if int(tmpfile.readline().strip()) == 0: + lbl = "<b>Deploy image successfully.</b>" + else: + lbl = "<b>Failed to deploy image.</b>" + msg = "Please check image <b>%s</b> exists and USB device <b>%s</b> is writable." % (self.image_path, combo_item) + tmpfile.close() + else: + if not self.image_path: + lbl = "<b>No selection made.</b>" + msg = "You have not selected an image to deploy." + else: + lbl = "<b>No selection made.</b>" + msg = "You have not selected a USB device." + if len(lbl): + crumbs_dialog = CrumbsMessageDialog(self, lbl, gtk.MESSAGE_INFO, msg) + button = crumbs_dialog.add_button("Close", gtk.RESPONSE_OK) + HobButton.style_button(button) + crumbs_dialog.run() + crumbs_dialog.destroy() + + def update_progress_bar(self, title, fraction, status=None): + self.progress_bar.update(fraction) + self.progress_bar.set_title(title) + self.progress_bar.set_rcstyle(status) + + def write_file(self, ifile, ofile): + self.progress_bar.reset() + self.progress_bar.show() + + f_from = os.open(ifile, os.O_RDONLY) + f_to = os.open(ofile, os.O_WRONLY) + + total_size = os.stat(ifile).st_size + written_size = 0 + + while True: + buf = os.read(f_from, 1024*1024) + if not buf: + break + os.write(f_to, buf) + written_size += 1024*1024 + self.update_progress_bar("Writing to usb:", written_size * 1.0/total_size) + + self.update_progress_bar("Writing completed:", 1.0) + os.close(f_from) + os.close(f_to) + self.progress_bar.hide() diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py new file mode 100644 index 000000000..21216adc9 --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/imageselectiondialog.py @@ -0,0 +1,172 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Joshua Lock <josh@linux.intel.com> +# Authored by Dongxiao Xu <dongxiao.xu@intel.com> +# Authored by Shane Wang <shane.wang@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import gtk +import gobject +import os +from bb.ui.crumbs.hobwidget import HobViewTable, HobInfoButton, HobButton, HobAltButton +from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog +from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class ImageSelectionDialog (CrumbsDialog): + + __columns__ = [{ + 'col_name' : 'Image name', + 'col_id' : 0, + 'col_style': 'text', + 'col_min' : 400, + 'col_max' : 400 + }, { + 'col_name' : 'Select', + 'col_id' : 1, + 'col_style': 'radio toggle', + 'col_min' : 160, + 'col_max' : 160 + }] + + + def __init__(self, image_folder, image_types, title, parent, flags, buttons=None, image_extension = {}): + super(ImageSelectionDialog, self).__init__(title, parent, flags, buttons) + self.connect("response", self.response_cb) + + self.image_folder = image_folder + self.image_types = image_types + self.image_list = [] + self.image_names = [] + self.image_extension = image_extension + + # create visual elements on the dialog + self.create_visual_elements() + + self.image_store = gtk.ListStore(gobject.TYPE_STRING, gobject.TYPE_BOOLEAN) + self.fill_image_store() + + def create_visual_elements(self): + hbox = gtk.HBox(False, 6) + + self.vbox.pack_start(hbox, expand=False, fill=False) + + entry = gtk.Entry() + entry.set_text(self.image_folder) + table = gtk.Table(1, 10, True) + table.set_size_request(560, -1) + hbox.pack_start(table, expand=False, fill=False) + table.attach(entry, 0, 9, 0, 1) + image = gtk.Image() + image.set_from_stock(gtk.STOCK_OPEN, gtk.ICON_SIZE_BUTTON) + open_button = gtk.Button() + open_button.set_image(image) + open_button.connect("clicked", self.select_path_cb, self, entry) + table.attach(open_button, 9, 10, 0, 1) + + self.image_table = HobViewTable(self.__columns__, "Images") + self.image_table.set_size_request(-1, 300) + self.image_table.connect("toggled", self.toggled_cb) + self.image_table.connect_group_selection(self.table_selected_cb) + self.image_table.connect("row-activated", self.row_actived_cb) + self.vbox.pack_start(self.image_table, expand=True, fill=True) + + self.show_all() + + def change_image_cb(self, model, path, columnid): + if not model: + return + iter = model.get_iter_first() + while iter: + rowpath = model.get_path(iter) + model[rowpath][columnid] = False + iter = model.iter_next(iter) + + model[path][columnid] = True + + def toggled_cb(self, table, cell, path, columnid, tree): + model = tree.get_model() + self.change_image_cb(model, path, columnid) + + def table_selected_cb(self, selection): + model, paths = selection.get_selected_rows() + if paths: + self.change_image_cb(model, paths[0], 1) + + def row_actived_cb(self, tab, model, path): + self.change_image_cb(model, path, 1) + self.emit('response', gtk.RESPONSE_YES) + + def select_path_cb(self, action, parent, entry): + dialog = gtk.FileChooserDialog("", parent, + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + text = entry.get_text() + dialog.set_current_folder(text if len(text) > 0 else os.getcwd()) + button = dialog.add_button("Cancel", gtk.RESPONSE_NO) + HobAltButton.style_button(button) + button = dialog.add_button("Open", gtk.RESPONSE_YES) + HobButton.style_button(button) + response = dialog.run() + if response == gtk.RESPONSE_YES: + path = dialog.get_filename() + entry.set_text(path) + self.image_folder = path + self.fill_image_store() + + dialog.destroy() + + def fill_image_store(self): + self.image_list = [] + self.image_store.clear() + imageset = set() + for root, dirs, files in os.walk(self.image_folder): + # ignore the sub directories + dirs[:] = [] + for f in files: + for image_type in self.image_types: + if image_type in self.image_extension: + real_types = self.image_extension[image_type] + else: + real_types = [image_type] + for real_image_type in real_types: + if f.endswith('.' + real_image_type): + imageset.add(f.rsplit('.' + real_image_type)[0].rsplit('.rootfs')[0]) + self.image_list.append(f) + + for image in imageset: + self.image_store.set(self.image_store.append(), 0, image, 1, False) + + self.image_table.set_model(self.image_store) + + def response_cb(self, dialog, response_id): + self.image_names = [] + if response_id == gtk.RESPONSE_YES: + iter = self.image_store.get_iter_first() + while iter: + path = self.image_store.get_path(iter) + if self.image_store[path][1]: + for f in self.image_list: + if f.startswith(self.image_store[path][0] + '.'): + self.image_names.append(f) + break + iter = self.image_store.iter_next(iter) diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py new file mode 100644 index 000000000..52d57b673 --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/layerselectiondialog.py @@ -0,0 +1,298 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Joshua Lock <josh@linux.intel.com> +# Authored by Dongxiao Xu <dongxiao.xu@intel.com> +# Authored by Shane Wang <shane.wang@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import gtk +import gobject +import os +import tempfile +from bb.ui.crumbs.hobwidget import hic, HobButton, HobAltButton +from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog +from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class CellRendererPixbufActivatable(gtk.CellRendererPixbuf): + """ + A custom CellRenderer implementation which is activatable + so that we can handle user clicks + """ + __gsignals__ = { 'clicked' : (gobject.SIGNAL_RUN_LAST, + gobject.TYPE_NONE, + (gobject.TYPE_STRING,)), } + + def __init__(self): + gtk.CellRendererPixbuf.__init__(self) + self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE) + self.set_property('follow-state', True) + + """ + Respond to a user click on a cell + """ + def do_activate(self, even, widget, path, background_area, cell_area, flags): + self.emit('clicked', path) + +# +# LayerSelectionDialog +# +class LayerSelectionDialog (CrumbsDialog): + + TARGETS = [ + ("MY_TREE_MODEL_ROW", gtk.TARGET_SAME_WIDGET, 0), + ("text/plain", 0, 1), + ("TEXT", 0, 2), + ("STRING", 0, 3), + ] + + def gen_label_widget(self, content): + label = gtk.Label() + label.set_alignment(0, 0) + label.set_markup(content) + label.show() + return label + + def layer_widget_toggled_cb(self, cell, path, layer_store): + name = layer_store[path][0] + toggle = not layer_store[path][1] + layer_store[path][1] = toggle + + def layer_widget_add_clicked_cb(self, action, layer_store, parent): + dialog = gtk.FileChooserDialog("Add new layer", parent, + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + button = dialog.add_button("Cancel", gtk.RESPONSE_NO) + HobAltButton.style_button(button) + button = dialog.add_button("Open", gtk.RESPONSE_YES) + HobButton.style_button(button) + label = gtk.Label("Select the layer you wish to add") + label.show() + dialog.set_extra_widget(label) + response = dialog.run() + path = dialog.get_filename() + dialog.destroy() + + lbl = "<b>Error</b>" + msg = "Unable to load layer <i>%s</i> because " % path + if response == gtk.RESPONSE_YES: + import os + import os.path + layers = [] + it = layer_store.get_iter_first() + while it: + layers.append(layer_store.get_value(it, 0)) + it = layer_store.iter_next(it) + + if not path: + msg += "it is an invalid path." + elif not os.path.exists(path+"/conf/layer.conf"): + msg += "there is no layer.conf inside the directory." + elif path in layers: + msg += "it is already in loaded layers." + else: + layer_store.append([path]) + return + dialog = CrumbsMessageDialog(parent, lbl, gtk.MESSAGE_ERROR, msg) + dialog.add_button(gtk.STOCK_CLOSE, gtk.RESPONSE_OK) + response = dialog.run() + dialog.destroy() + + def layer_widget_del_clicked_cb(self, action, tree_selection, layer_store): + model, iter = tree_selection.get_selected() + if iter: + layer_store.remove(iter) + + + def gen_layer_widget(self, layers, layers_avail, window, tooltip=""): + hbox = gtk.HBox(False, 6) + + layer_tv = gtk.TreeView() + layer_tv.set_rules_hint(True) + layer_tv.set_headers_visible(False) + tree_selection = layer_tv.get_selection() + tree_selection.set_mode(gtk.SELECTION_SINGLE) + + # Allow enable drag and drop of rows including row move + dnd_internal_target = '' + dnd_targets = [(dnd_internal_target, gtk.TARGET_SAME_WIDGET, 0)] + layer_tv.enable_model_drag_source( gtk.gdk.BUTTON1_MASK, + dnd_targets, + gtk.gdk.ACTION_MOVE) + layer_tv.enable_model_drag_dest(dnd_targets, + gtk.gdk.ACTION_MOVE) + layer_tv.connect("drag_data_get", self.drag_data_get_cb) + layer_tv.connect("drag_data_received", self.drag_data_received_cb) + + col0= gtk.TreeViewColumn('Path') + cell0 = gtk.CellRendererText() + cell0.set_padding(5,2) + col0.pack_start(cell0, True) + col0.set_cell_data_func(cell0, self.draw_layer_path_cb) + layer_tv.append_column(col0) + + scroll = gtk.ScrolledWindow() + scroll.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + scroll.set_shadow_type(gtk.SHADOW_IN) + scroll.add(layer_tv) + + table_layer = gtk.Table(2, 10, False) + hbox.pack_start(table_layer, expand=True, fill=True) + + table_layer.attach(scroll, 0, 10, 0, 1) + + layer_store = gtk.ListStore(gobject.TYPE_STRING) + for layer in layers: + layer_store.append([layer]) + + col1 = gtk.TreeViewColumn('Enabled') + layer_tv.append_column(col1) + + cell1 = CellRendererPixbufActivatable() + cell1.set_fixed_size(-1,35) + cell1.connect("clicked", self.del_cell_clicked_cb, layer_store) + col1.pack_start(cell1, True) + col1.set_cell_data_func(cell1, self.draw_delete_button_cb, layer_tv) + + add_button = gtk.Button() + add_button.set_relief(gtk.RELIEF_NONE) + box = gtk.HBox(False, 6) + box.show() + add_button.add(box) + add_button.connect("enter-notify-event", self.add_hover_cb) + add_button.connect("leave-notify-event", self.add_leave_cb) + self.im = gtk.Image() + self.im.set_from_file(hic.ICON_INDI_ADD_FILE) + self.im.show() + box.pack_start(self.im, expand=False, fill=False, padding=6) + lbl = gtk.Label("Add layer") + lbl.set_alignment(0.0, 0.5) + lbl.show() + box.pack_start(lbl, expand=True, fill=True, padding=6) + add_button.connect("clicked", self.layer_widget_add_clicked_cb, layer_store, window) + table_layer.attach(add_button, 0, 10, 1, 2, gtk.EXPAND | gtk.FILL, 0, 0, 6) + layer_tv.set_model(layer_store) + + hbox.show_all() + + return hbox, layer_store + + def drag_data_get_cb(self, treeview, context, selection, target_id, etime): + treeselection = treeview.get_selection() + model, iter = treeselection.get_selected() + data = model.get_value(iter, 0) + selection.set(selection.target, 8, data) + + def drag_data_received_cb(self, treeview, context, x, y, selection, info, etime): + model = treeview.get_model() + data = selection.data + drop_info = treeview.get_dest_row_at_pos(x, y) + if drop_info: + path, position = drop_info + iter = model.get_iter(path) + if (position == gtk.TREE_VIEW_DROP_BEFORE or position == gtk.TREE_VIEW_DROP_INTO_OR_BEFORE): + model.insert_before(iter, [data]) + else: + model.insert_after(iter, [data]) + else: + model.append([data]) + if context.action == gtk.gdk.ACTION_MOVE: + context.finish(True, True, etime) + return + + def add_hover_cb(self, button, event): + self.im.set_from_file(hic.ICON_INDI_ADD_HOVER_FILE) + + def add_leave_cb(self, button, event): + self.im.set_from_file(hic.ICON_INDI_ADD_FILE) + + def __init__(self, title, layers, layers_non_removable, all_layers, parent, flags, buttons=None): + super(LayerSelectionDialog, self).__init__(title, parent, flags, buttons) + + # class members from other objects + self.layers = layers + self.layers_non_removable = layers_non_removable + self.all_layers = all_layers + self.layers_changed = False + + # icon for remove button in TreeView + im = gtk.Image() + im.set_from_file(hic.ICON_INDI_REMOVE_FILE) + self.rem_icon = im.get_pixbuf() + + # class members for internal use + self.layer_store = None + + # create visual elements on the dialog + self.create_visual_elements() + self.connect("response", self.response_cb) + + def create_visual_elements(self): + layer_widget, self.layer_store = self.gen_layer_widget(self.layers, self.all_layers, self, None) + layer_widget.set_size_request(450, 250) + self.vbox.pack_start(layer_widget, expand=True, fill=True) + self.show_all() + + def response_cb(self, dialog, response_id): + model = self.layer_store + it = model.get_iter_first() + layers = [] + while it: + layers.append(model.get_value(it, 0)) + it = model.iter_next(it) + + self.layers_changed = (self.layers != layers) + self.layers = layers + + """ + A custom cell_data_func to draw a delete 'button' in the TreeView for layers + other than the meta layer. The deletion of which is prevented so that the + user can't shoot themselves in the foot too badly. + """ + def draw_delete_button_cb(self, col, cell, model, it, tv): + path = model.get_value(it, 0) + if path in self.layers_non_removable: + cell.set_sensitive(False) + cell.set_property('pixbuf', None) + cell.set_property('mode', gtk.CELL_RENDERER_MODE_INERT) + else: + cell.set_property('pixbuf', self.rem_icon) + cell.set_sensitive(True) + cell.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE) + + return True + + """ + A custom cell_data_func to write an extra message into the layer path cell + for the meta layer. We should inform the user that they can't remove it for + their own safety. + """ + def draw_layer_path_cb(self, col, cell, model, it): + path = model.get_value(it, 0) + if path in self.layers_non_removable: + cell.set_property('markup', "<b>It cannot be removed</b>\n%s" % path) + else: + cell.set_property('text', path) + + def del_cell_clicked_cb(self, cell, path, model): + it = model.get_iter_from_string(path) + model.remove(it) diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/propertydialog.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/propertydialog.py new file mode 100644 index 000000000..09b9ce6de --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/propertydialog.py @@ -0,0 +1,437 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2013 Intel Corporation +# +# Authored by Andrei Dinu <andrei.adrianx.dinu@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import string +import gtk +import gobject +import os +import tempfile +import glib +from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog +from bb.ui.crumbs.hig.settingsuihelper import SettingsUIHelper +from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog +from bb.ui.crumbs.hig.layerselectiondialog import LayerSelectionDialog + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class PropertyDialog(CrumbsDialog): + + def __init__(self, title, parent, information, flags, buttons=None): + + super(PropertyDialog, self).__init__(title, parent, flags, buttons) + + self.properties = information + + if len(self.properties) == 10: + self.create_recipe_visual_elements() + elif len(self.properties) == 5: + self.create_package_visual_elements() + else: + self.create_information_visual_elements() + + + def create_information_visual_elements(self): + + HOB_ICON_BASE_DIR = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), ("icons/")) + ICON_PACKAGES_DISPLAY_FILE = os.path.join(HOB_ICON_BASE_DIR, ('info/info_display.png')) + + self.set_resizable(False) + + self.table = gtk.Table(1,1,False) + self.table.set_row_spacings(0) + self.table.set_col_spacings(0) + + self.image = gtk.Image() + self.image.set_from_file(ICON_PACKAGES_DISPLAY_FILE) + self.image.set_property("xalign",0) + #self.vbox.add(self.image) + + image_info = self.properties.split("*")[0] + info = self.properties.split("*")[1] + + vbox = gtk.VBox(True, spacing=30) + + self.label_short = gtk.Label() + self.label_short.set_line_wrap(False) + self.label_short.set_markup(image_info) + self.label_short.set_property("xalign", 0) + + self.info_label = gtk.Label() + self.info_label.set_line_wrap(True) + self.info_label.set_markup(info) + self.info_label.set_property("yalign", 0.5) + + self.table.attach(self.image, 0,1,0,1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL,xpadding=5,ypadding=5) + self.table.attach(self.label_short, 0,1,0,1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL,xpadding=40,ypadding=5) + self.table.attach(self.info_label, 0,1,1,2, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL,xpadding=40,ypadding=10) + + self.vbox.add(self.table) + self.connect('delete-event', lambda w, e: self.destroy() or True) + + def treeViewTooltip( self, widget, e, tooltips, cell, emptyText="" ): + try: + (path,col,x,y) = widget.get_path_at_pos( int(e.x), int(e.y) ) + it = widget.get_model().get_iter(path) + value = widget.get_model().get_value(it,cell) + if value in self.tooltip_items: + tooltips.set_tip(widget, self.tooltip_items[value]) + tooltips.enable() + else: + tooltips.set_tip(widget, emptyText) + except: + tooltips.set_tip(widget, emptyText) + + + def create_package_visual_elements(self): + + import json + + name = self.properties['name'] + binb = self.properties['binb'] + size = self.properties['size'] + recipe = self.properties['recipe'] + file_list = json.loads(self.properties['files_list']) + + files_temp = '' + paths_temp = '' + files_binb = [] + paths_binb = [] + + self.tooltip_items = {} + + self.set_resizable(False) + + #cleaning out the recipe variable + recipe = recipe.split("+")[0] + + vbox = gtk.VBox(True,spacing = 0) + + ###################################### NAME ROW + COL ################################# + + self.label_short = gtk.Label() + self.label_short.set_size_request(300,-1) + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Name: </span>" + name) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ###################################### SIZE ROW + COL ###################################### + + self.label_short = gtk.Label() + self.label_short.set_size_request(300,-1) + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Size: </span>" + size) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ##################################### RECIPE ROW + COL ######################################### + + self.label_short = gtk.Label() + self.label_short.set_size_request(300,-1) + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Recipe: </span>" + recipe) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ##################################### BINB ROW + COL ####################################### + + if binb != '': + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Brought in by: </span>") + self.label_short.set_property("xalign", 0) + + self.label_info = gtk.Label() + self.label_info.set_size_request(300,-1) + self.label_info.set_selectable(True) + self.label_info.set_line_wrap(True) + self.label_info.set_markup(binb) + self.label_info.set_property("xalign", 0) + + self.vbox.add(self.label_short) + self.vbox.add(self.label_info) + + #################################### FILES BROUGHT BY PACKAGES ################################### + + if file_list: + + self.textWindow = gtk.ScrolledWindow() + self.textWindow.set_shadow_type(gtk.SHADOW_IN) + self.textWindow.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self.textWindow.set_size_request(100, 170) + + packagefiles_store = gtk.ListStore(str) + + self.packagefiles_tv = gtk.TreeView() + self.packagefiles_tv.set_rules_hint(True) + self.packagefiles_tv.set_headers_visible(True) + self.textWindow.add(self.packagefiles_tv) + + self.cell1 = gtk.CellRendererText() + col1 = gtk.TreeViewColumn('Package files', self.cell1) + col1.set_cell_data_func(self.cell1, self.regex_field) + self.packagefiles_tv.append_column(col1) + + items = file_list.keys() + items.sort() + for item in items: + fullpath = item + while len(item) > 35: + item = item[:len(item)/2] + "" + item[len(item)/2+1:] + if len(item) == 35: + item = item[:len(item)/2] + "..." + item[len(item)/2+3:] + self.tooltip_items[item] = fullpath + + packagefiles_store.append([str(item)]) + + self.packagefiles_tv.set_model(packagefiles_store) + + tips = gtk.Tooltips() + tips.set_tip(self.packagefiles_tv, "") + self.packagefiles_tv.connect("motion-notify-event", self.treeViewTooltip, tips, 0) + self.packagefiles_tv.set_events(gtk.gdk.POINTER_MOTION_MASK) + + self.vbox.add(self.textWindow) + + self.vbox.show_all() + + + def regex_field(self, column, cell, model, iter): + cell.set_property('text', model.get_value(iter, 0)) + return + + + def create_recipe_visual_elements(self): + + summary = self.properties['summary'] + name = self.properties['name'] + version = self.properties['version'] + revision = self.properties['revision'] + binb = self.properties['binb'] + group = self.properties['group'] + license = self.properties['license'] + homepage = self.properties['homepage'] + bugtracker = self.properties['bugtracker'] + description = self.properties['description'] + + self.set_resizable(False) + + #cleaning out the version variable and also the summary + version = version.split(":")[1] + if len(version) > 30: + version = version.split("+")[0] + else: + version = version.split("-")[0] + license = license.replace("&" , "and") + if (homepage == ''): + homepage = 'unknown' + if (bugtracker == ''): + bugtracker = 'unknown' + summary = summary.split("+")[0] + + #calculating the rows needed for the table + binb_items_count = len(binb.split(',')) + binb_items = binb.split(',') + + vbox = gtk.VBox(False,spacing = 0) + + ######################################## SUMMARY LABEL ######################################### + + if summary != '': + self.label_short = gtk.Label() + self.label_short.set_width_chars(37) + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<b>" + summary + "</b>") + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ########################################## NAME ROW + COL ####################################### + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Name: </span>" + name) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ####################################### VERSION ROW + COL #################################### + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Version: </span>" + version) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ##################################### REVISION ROW + COL ##################################### + + self.label_short = gtk.Label() + self.label_short.set_line_wrap(True) + self.label_short.set_selectable(True) + self.label_short.set_markup("<span weight=\"bold\">Revision: </span>" + revision) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ################################## GROUP ROW + COL ############################################ + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Group: </span>" + group) + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + + ################################# HOMEPAGE ROW + COL ############################################ + + if homepage != 'unknown': + self.label_info = gtk.Label() + self.label_info.set_selectable(True) + self.label_info.set_line_wrap(True) + if len(homepage) > 35: + self.label_info.set_markup("<a href=\"" + homepage + "\">" + homepage[0:35] + "..." + "</a>") + else: + self.label_info.set_markup("<a href=\"" + homepage + "\">" + homepage[0:60] + "</a>") + + self.label_info.set_property("xalign", 0) + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<b>Homepage: </b>") + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + self.vbox.add(self.label_info) + + ################################# BUGTRACKER ROW + COL ########################################### + + if bugtracker != 'unknown': + self.label_info = gtk.Label() + self.label_info.set_selectable(True) + self.label_info.set_line_wrap(True) + if len(bugtracker) > 35: + self.label_info.set_markup("<a href=\"" + bugtracker + "\">" + bugtracker[0:35] + "..." + "</a>") + else: + self.label_info.set_markup("<a href=\"" + bugtracker + "\">" + bugtracker[0:60] + "</a>") + self.label_info.set_property("xalign", 0) + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<b>Bugtracker: </b>") + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + self.vbox.add(self.label_info) + + ################################# LICENSE ROW + COL ############################################ + + self.label_info = gtk.Label() + self.label_info.set_selectable(True) + self.label_info.set_line_wrap(True) + self.label_info.set_markup(license) + self.label_info.set_property("xalign", 0) + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">License: </span>") + self.label_short.set_property("xalign", 0) + + self.vbox.add(self.label_short) + self.vbox.add(self.label_info) + + ################################### BINB ROW+COL ############################################# + + if binb != '': + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Brought in by: </span>") + self.label_short.set_property("xalign", 0) + self.vbox.add(self.label_short) + self.label_info = gtk.Label() + self.label_info.set_selectable(True) + self.label_info.set_width_chars(36) + if len(binb) > 200: + scrolled_window = gtk.ScrolledWindow() + scrolled_window.set_policy(gtk.POLICY_NEVER,gtk.POLICY_ALWAYS) + scrolled_window.set_size_request(100,100) + self.label_info.set_markup(binb) + self.label_info.set_padding(6,6) + self.label_info.set_alignment(0,0) + self.label_info.set_line_wrap(True) + scrolled_window.add_with_viewport(self.label_info) + self.vbox.add(scrolled_window) + else: + self.label_info.set_markup(binb) + self.label_info.set_property("xalign", 0) + self.label_info.set_line_wrap(True) + self.vbox.add(self.label_info) + + ################################ DESCRIPTION TAG ROW ################################################# + + self.label_short = gtk.Label() + self.label_short.set_line_wrap(True) + self.label_short.set_markup("<span weight=\"bold\">Description </span>") + self.label_short.set_property("xalign", 0) + self.vbox.add(self.label_short) + + ################################ DESCRIPTION INFORMATION ROW ########################################## + + hbox = gtk.HBox(True,spacing = 0) + + self.label_short = gtk.Label() + self.label_short.set_selectable(True) + self.label_short.set_width_chars(36) + if len(description) > 200: + scrolled_window = gtk.ScrolledWindow() + scrolled_window.set_policy(gtk.POLICY_NEVER,gtk.POLICY_ALWAYS) + scrolled_window.set_size_request(100,100) + self.label_short.set_markup(description) + self.label_short.set_padding(6,6) + self.label_short.set_alignment(0,0) + self.label_short.set_line_wrap(True) + scrolled_window.add_with_viewport(self.label_short) + self.vbox.add(scrolled_window) + else: + self.label_short.set_markup(description) + self.label_short.set_property("xalign", 0) + self.label_short.set_line_wrap(True) + self.vbox.add(self.label_short) + + self.vbox.show_all() diff --git a/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py new file mode 100644 index 000000000..e0285c93c --- /dev/null +++ b/import-layers/yocto-poky/bitbake/lib/bb/ui/crumbs/hig/settingsuihelper.py @@ -0,0 +1,122 @@ +# +# BitBake Graphical GTK User Interface +# +# Copyright (C) 2011-2012 Intel Corporation +# +# Authored by Joshua Lock <josh@linux.intel.com> +# Authored by Dongxiao Xu <dongxiao.xu@intel.com> +# Authored by Shane Wang <shane.wang@intel.com> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +import gtk +import os +from bb.ui.crumbs.hobwidget import HobInfoButton, HobButton, HobAltButton + +""" +The following are convenience classes for implementing GNOME HIG compliant +BitBake GUI's +In summary: spacing = 12px, border-width = 6px +""" + +class SettingsUIHelper(): + + def gen_label_widget(self, content): + label = gtk.Label() + label.set_alignment(0, 0) + label.set_markup(content) + label.show() + return label + + def gen_label_info_widget(self, content, tooltip): + table = gtk.Table(1, 10, False) + label = self.gen_label_widget(content) + info = HobInfoButton(tooltip, self) + table.attach(label, 0, 1, 0, 1, xoptions=gtk.FILL) + table.attach(info, 1, 2, 0, 1, xoptions=gtk.FILL, xpadding=10) + return table + + def gen_spinner_widget(self, content, lower, upper, tooltip=""): + hbox = gtk.HBox(False, 12) + adjust = gtk.Adjustment(value=content, lower=lower, upper=upper, step_incr=1) + spinner = gtk.SpinButton(adjustment=adjust, climb_rate=1, digits=0) + + spinner.set_value(content) + hbox.pack_start(spinner, expand=False, fill=False) + + info = HobInfoButton(tooltip, self) + hbox.pack_start(info, expand=False, fill=False) + + hbox.show_all() + return hbox, spinner + + def gen_combo_widget(self, curr_item, all_item, tooltip=""): + hbox = gtk.HBox(False, 12) + combo = gtk.combo_box_new_text() + hbox.pack_start(combo, expand=False, fill=False) + + index = 0 + for item in all_item or []: + combo.append_text(item) + if item == curr_item: + combo.set_active(index) + index += 1 + + info = HobInfoButton(tooltip, self) + hbox.pack_start(info, expand=False, fill=False) + + hbox.show_all() + return hbox, combo + + def entry_widget_select_path_cb(self, action, parent, entry): + dialog = gtk.FileChooserDialog("", parent, + gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER) + text = entry.get_text() + dialog.set_current_folder(text if len(text) > 0 else os.getcwd()) + button = dialog.add_button("Cancel", gtk.RESPONSE_NO) + HobAltButton.style_button(button) + button = dialog.add_button("Open", gtk.RESPONSE_YES) + HobButton.style_button(button) + response = dialog.run() + if response == gtk.RESPONSE_YES: + path = dialog.get_filename() + entry.set_text(path) + + dialog.destroy() + + def gen_entry_widget(self, content, parent, tooltip="", need_button=True): + hbox = gtk.HBox(False, 12) + entry = gtk.Entry() + entry.set_text(content) + entry.set_size_request(350,30) + + if need_button: + table = gtk.Table(1, 10, False) + hbox.pack_start(table, expand=True, fill=True) + table.attach(entry, 0, 9, 0, 1, xoptions=gtk.SHRINK) + image = gtk.Image() + image.set_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON) + open_button = gtk.Button() + open_button.set_image(image) + open_button.connect("clicked", self.entry_widget_select_path_cb, parent, entry) + table.attach(open_button, 9, 10, 0, 1, xoptions=gtk.SHRINK) + else: + hbox.pack_start(entry, expand=True, fill=True) + + if tooltip != "": + info = HobInfoButton(tooltip, self) + hbox.pack_start(info, expand=False, fill=False) + + hbox.show_all() + return hbox, entry |