bitbake: hob: create save image dialog used to save a template

Implemented a new dialog used by Hob. This dialog was desinged
in order to permit to save only in a particular directory.
Also, it has a field where the user can type a description
for the image.
Implemented in the handler a method to retrieve the topdir variable,
because the changes will be saved in {topdir}/recipes/images directory.

[YOCTO #4193]
(Bitbake rev: 117d4809a62e28ffe7e9dcda5433993d76f7d934)

Signed-off-by: Cristiana Voicu <cristiana.voicu@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Cristiana Voicu 2013-07-25 07:25:38 +00:00 committed by Richard Purdie
parent 843ef10832
commit ee4fe5a229
5 changed files with 163 additions and 2 deletions

View File

@ -1451,3 +1451,6 @@ class Builder(gtk.Window):
self.consolelog.setFormatter(format) self.consolelog.setFormatter(format)
self.logger.addHandler(self.consolelog) self.logger.addHandler(self.consolelog)
def get_topdir(self):
return self.handler.get_topdir()

View File

@ -0,0 +1,136 @@
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2013 Intel Corporation
#
# Authored by Cristiana Voicu <cristiana.voicu@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 glib
from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
from bb.ui.crumbs.hig.crumbsmessagedialog import CrumbsMessageDialog
from bb.ui.crumbs.hobwidget import HobButton
class SaveImageDialog (CrumbsDialog):
"""
This class is used to create a dialog that permits to save
a custom image in a predefined directory.
"""
def __init__(self, directory, title, parent, flags, buttons=None):
super(SaveImageDialog, self).__init__(title, parent, flags, buttons)
self.directory = directory
self.builder = parent
# create visual elements on the dialog
self.create_visual_elements()
def create_visual_elements(self):
self.set_default_response(gtk.RESPONSE_OK)
self.vbox.set_border_width(6)
sub_vbox = gtk.VBox(False, 12)
self.vbox.pack_start(sub_vbox, expand=False, fill=False)
label = gtk.Label()
label.set_alignment(0, 0)
label.set_markup("<b>Name</b>")
sub_label = gtk.Label()
sub_label.set_alignment(0, 0)
content = "Image recipe names should be all lowercase and include only alphanumeric\n"
content += "characters. The only special character you can use is the ASCII hyphen (-)."
sub_label.set_markup(content)
self.name_entry = gtk.Entry()
self.name_entry.set_size_request(350,30)
self.name_entry.connect("changed", self.name_entry_changed)
sub_vbox.pack_start(label, expand=False, fill=False)
sub_vbox.pack_start(sub_label, expand=False, fill=False)
sub_vbox.pack_start(self.name_entry, expand=False, fill=False)
sub_vbox = gtk.VBox(False, 12)
self.vbox.pack_start(sub_vbox, expand=False, fill=False)
label = gtk.Label()
label.set_alignment(0, 0)
label.set_markup("<b>Description</b> (optional)")
sub_label = gtk.Label()
sub_label.set_alignment(0, 0)
sub_label.set_markup("The description should be less than 150 characters long.")
self.description_entry = gtk.TextView()
self.description_entry.set_wrap_mode(gtk.WRAP_WORD)
self.description_entry.set_size_request(350,150)
sub_vbox.pack_start(label, expand=False, fill=False)
sub_vbox.pack_start(sub_label, expand=False, fill=False)
sub_vbox.pack_start(self.description_entry, expand=False, fill=False)
sub_vbox = gtk.VBox(False, 12)
self.vbox.pack_start(sub_vbox, expand=False, fill=False)
label = gtk.Label()
label.set_alignment(0, 0)
label.set_markup("Your image recipe will be saved to:")
sub_label = gtk.Label()
sub_label.set_alignment(0, 0)
sub_label.set_markup(self.directory)
sub_vbox.pack_start(label, expand=False, fill=False)
sub_vbox.pack_start(sub_label, expand=False, fill=False)
table = gtk.Table(1, 4, True)
cancel_button = gtk.Button()
cancel_button.set_label("Cancel")
cancel_button.connect("clicked", self.cancel_button_cb)
cancel_button.set_size_request(110, 30)
self.save_button = gtk.Button()
self.save_button.set_label("Save")
self.save_button.connect("clicked", self.save_button_cb)
self.save_button.set_size_request(110, 30)
self.save_button.set_sensitive(False)
table.attach(cancel_button, 2, 3, 0, 1)
table.attach(self.save_button, 3, 4, 0, 1)
self.vbox.pack_end(table, expand=False, fill=False)
self.show_all()
def name_entry_changed(self, entry):
text = entry.get_text()
if text == '':
self.save_button.set_sensitive(False)
else:
self.save_button.set_sensitive(True)
def cancel_button_cb(self, button):
self.destroy()
def save_button_cb(self, button):
text = self.name_entry.get_text()
new_text = text.replace("-","")
if new_text.islower() and new_text.isalnum():
print(text)
self.destroy()
else:
self.show_invalid_input_error_dialog()
def show_invalid_input_error_dialog(self):
lbl = "<b>Invalid characters in image recipe name</b>\n"
msg = "Image recipe names should be all lowercase and\n"
msg += "include only alphanumeric characters. The only\n"
msg += "special character you can use is the ASCII hyphen (-)."
lbl = lbl + "\n%s\n" % glib.markup_escape_text(msg)
dialog = CrumbsMessageDialog(self, lbl, gtk.STOCK_DIALOG_ERROR)
button = dialog.add_button("Close", gtk.RESPONSE_OK)
HobButton.style_button(button)
res = dialog.run()
dialog.destroy()

View File

@ -452,6 +452,9 @@ class HobHandler(gobject.GObject):
def get_logfile(self): def get_logfile(self):
return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])[0] return self.server.runCommand(["getVariable", "BB_CONSOLELOG"])[0]
def get_topdir(self):
return self.runCommand(["getVariable", "TOPDIR"]) or ""
def _remove_redundant(self, string): def _remove_redundant(self, string):
ret = [] ret = []
for i in string.split(): for i in string.split():

View File

@ -882,3 +882,6 @@ class RecipeListModel(gtk.ListStore):
def get_custom_image_version(self): def get_custom_image_version(self):
return self.custom_image_version return self.custom_image_version
def is_custom_image(self):
return self.get_selected_image() == self.__custom_image__

View File

@ -27,6 +27,7 @@ from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobAltButton, HobButton
from bb.ui.crumbs.hobpages import HobPage from bb.ui.crumbs.hobpages import HobPage
import subprocess import subprocess
from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
from bb.ui.crumbs.hig.saveimagedialog import SaveImageDialog
# #
# ImageDetailsPage # ImageDetailsPage
@ -259,7 +260,7 @@ class ImageDetailsPage (HobPage):
self.build_result = self.BuildDetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color) self.build_result = self.BuildDetailBox(varlist=varlist, vallist=vallist, icon=icon, color=color)
self.box_group_area.pack_start(self.build_result, expand=False, fill=False) self.box_group_area.pack_start(self.build_result, expand=False, fill=False)
self.buttonlist = ["Build new image", "Run image", "Deploy image"] self.buttonlist = ["Build new image", "Save image recipe", "Run image", "Deploy image"]
# Name # Name
self.image_store = [] self.image_store = []
@ -340,7 +341,7 @@ class ImageDetailsPage (HobPage):
self.setting_detail = None self.setting_detail = None
if self.build_succeeded: if self.build_succeeded:
vallist.append(machine) vallist.append(machine)
if base_image == self.builder.recipe_model.__custom_image__: if self.builder.recipe_model.is_custom_image():
if self.builder.configuration.initial_selected_image == self.builder.recipe_model.__custom_image__: if self.builder.configuration.initial_selected_image == self.builder.recipe_model.__custom_image__:
base_image ="New image recipe" base_image ="New image recipe"
else: else:
@ -579,6 +580,13 @@ class ImageDetailsPage (HobPage):
created = True created = True
is_runnable = True is_runnable = True
name = "Save image recipe"
if name in buttonlist and self.builder.recipe_model.is_custom_image():
save_button = HobAltButton("Save image recipe")
button_id = save_button.connect("clicked", self.save_button_clicked_cb)
self.button_ids[button_id] = save_button
self.details_bottom_buttons.pack_end(save_button, expand=False, fill=False)
name = "Build new image" name = "Build new image"
if name in buttonlist: if name in buttonlist:
# create button "Build new image" # create button "Build new image"
@ -613,6 +621,14 @@ class ImageDetailsPage (HobPage):
else: else:
self.builder.runqemu_image(self.toggled_image, self.sel_kernel) self.builder.runqemu_image(self.toggled_image, self.sel_kernel)
def save_button_clicked_cb(self, button):
topdir = self.builder.get_topdir()
images_dir = topdir + "/recipes/images/"
dialog = SaveImageDialog(images_dir, "Save image recipe", self.builder,
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
response = dialog.run()
dialog.destroy()
def build_new_button_clicked_cb(self, button): def build_new_button_clicked_cb(self, button):
self.builder.initiate_new_build_async() self.builder.initiate_new_build_async()