#!/usr/bin/env python
#
# BitBake Graphical GTK User Interface
#
# Copyright (C) 2012        Intel Corporation
#
# 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 gobject
import gtk
from bb.ui.crumbs.hobcolor import HobColors
from bb.ui.crumbs.hobwidget import hic, HobViewTable, HobAltButton, HobButton
from bb.ui.crumbs.hobpages import HobPage
import subprocess
from bb.ui.crumbs.hig.crumbsdialog import CrumbsDialog
from bb.ui.crumbs.hig.saveimagedialog import SaveImageDialog

#
# ImageDetailsPage
#
class ImageDetailsPage (HobPage):

    class DetailBox (gtk.EventBox):
        def __init__(self, widget = None, varlist = None, vallist = None, icon = None, button = None, button2=None, color = HobColors.LIGHT_GRAY):
            gtk.EventBox.__init__(self)

            # set color
            style = self.get_style().copy()
            style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
            self.set_style(style)

            self.row = gtk.Table(1, 2, False)
            self.row.set_border_width(10)
            self.add(self.row)
        
            total_rows = 0
            if widget:
                total_rows = 10
            if varlist and vallist:
                # pack the icon and the text on the left
                total_rows += len(varlist)
            self.table = gtk.Table(total_rows, 20, True)
            self.table.set_row_spacings(6)
            self.table.set_size_request(100, -1)
            self.row.attach(self.table, 0, 1, 0, 1, xoptions=gtk.FILL|gtk.EXPAND, yoptions=gtk.FILL)
            
            colid = 0
            rowid = 0
            self.line_widgets = {}
            if icon:
                self.table.attach(icon, colid, colid + 2, 0, 1)
                colid = colid + 2
            if widget:
                self.table.attach(widget, colid, 20, 0, 10)
                rowid = 10
            if varlist and vallist:
                for row in range(rowid, total_rows):
                    index = row - rowid
                    self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
                    self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
            # pack the button on the right
            if button:
                self.bbox = gtk.VBox()
                self.bbox.pack_start(button, expand=True, fill=False)
                if button2:
                    self.bbox.pack_start(button2, expand=True, fill=False)
                self.bbox.set_size_request(150,-1)
                self.row.attach(self.bbox, 1, 2, 0, 1, xoptions=gtk.FILL, yoptions=gtk.EXPAND)
                
        def update_line_widgets(self, variable, value):
            if len(self.line_widgets) == 0:
                return
            if not isinstance(self.line_widgets[variable], gtk.Label):
                return
            self.line_widgets[variable].set_markup(self.format_line(variable, value))

        def wrap_line(self, inputs):
            # wrap the long text of inputs
            wrap_width_chars = 75
            outputs = ""
            tmps = inputs
            less_chars = len(inputs)
            while (less_chars - wrap_width_chars) > 0:
                less_chars -= wrap_width_chars
                outputs += tmps[:wrap_width_chars] + "\n               "
                tmps = inputs[less_chars:]
            outputs += tmps
            return outputs

        def format_line(self, variable, value):
            wraped_value = self.wrap_line(value)
            markup = "<span weight=\'bold\'>%s</span>" % variable
            markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
            return markup

        def text2label(self, variable, value):
            # append the name:value to the left box
            # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
            label = gtk.Label()
            label.set_alignment(0.0, 0.5)
            label.set_markup(self.format_line(variable, value))
            return label

    class BuildDetailBox (gtk.EventBox):
        def __init__(self, varlist = None, vallist = None, icon = None, color = HobColors.LIGHT_GRAY):
            gtk.EventBox.__init__(self)

            # set color
            style = self.get_style().copy()
            style.bg[gtk.STATE_NORMAL] = self.get_colormap().alloc_color(color, False, False)
            self.set_style(style)

            self.hbox = gtk.HBox()
            self.hbox.set_border_width(10)
            self.add(self.hbox)

            total_rows = 0
            if varlist and vallist:
                # pack the icon and the text on the left
                total_rows += len(varlist)
            self.table = gtk.Table(total_rows, 20, True)
            self.table.set_row_spacings(6)
            self.table.set_size_request(100, -1)
            self.hbox.pack_start(self.table, expand=True, fill=True, padding=15)

            colid = 0
            rowid = 0
            self.line_widgets = {}
            if icon:
                self.table.attach(icon, colid, colid + 2, 0, 1)
                colid = colid + 2
            if varlist and vallist:
                for row in range(rowid, total_rows):
                    index = row - rowid
                    self.line_widgets[varlist[index]] = self.text2label(varlist[index], vallist[index])
                    self.table.attach(self.line_widgets[varlist[index]], colid, 20, row, row + 1)
                
        def update_line_widgets(self, variable, value):
            if len(self.line_widgets) == 0:
                return
            if not isinstance(self.line_widgets[variable], gtk.Label):
                return
            self.line_widgets[variable].set_markup(self.format_line(variable, value))

        def wrap_line(self, inputs):
            # wrap the long text of inputs
            wrap_width_chars = 75
            outputs = ""
            tmps = inputs
            less_chars = len(inputs)
            while (less_chars - wrap_width_chars) > 0:
                less_chars -= wrap_width_chars
                outputs += tmps[:wrap_width_chars] + "\n               "
                tmps = inputs[less_chars:]
            outputs += tmps
            return outputs

        def format_line(self, variable, value):
            wraped_value = self.wrap_line(value)
            markup = "<span weight=\'bold\'>%s</span>" % variable
            markup += "<span weight=\'normal\' foreground=\'#1c1c1c\' font_desc=\'14px\'>%s</span>" % wraped_value
            return markup

        def text2label(self, variable, value):
            # append the name:value to the left box
            # such as "Name: hob-core-minimal-variant-2011-12-15-beagleboard"
            label = gtk.Label()
            label.set_alignment(0.0, 0.5)
            label.set_markup(self.format_line(variable, value))
            return label

    def __init__(self, builder):
        super(ImageDetailsPage, self).__init__(builder, "Image details")

        self.image_store = []
        self.button_ids = {}
        self.details_bottom_buttons = gtk.HBox(False, 6)
        self.image_saved = False
        self.create_visual_elements()
        self.name_field_template = ""
        self.description_field_template = ""

    def create_visual_elements(self):
        # create visual elements
        # create the toolbar
        self.toolbar = gtk.Toolbar()
        self.toolbar.set_orientation(gtk.ORIENTATION_HORIZONTAL)
        self.toolbar.set_style(gtk.TOOLBAR_BOTH)

        my_images_button = self.append_toolbar_button(self.toolbar,
            "Images",
            hic.ICON_IMAGES_DISPLAY_FILE,
            hic.ICON_IMAGES_HOVER_FILE,
            "Open previously built images",
            self.my_images_button_clicked_cb)
        settings_button = self.append_toolbar_button(self.toolbar,
            "Settings",
            hic.ICON_SETTINGS_DISPLAY_FILE,
            hic.ICON_SETTINGS_HOVER_FILE,
            "View additional build settings",
            self.settings_button_clicked_cb)

        self.details_top_buttons = self.add_onto_top_bar(self.toolbar)

    def _remove_all_widget(self):
        children = self.get_children() or []
        for child in children:
            self.remove(child)
        children = self.box_group_area.get_children() or []
        for child in children:
            self.box_group_area.remove(child)
        children = self.details_bottom_buttons.get_children() or []
        for child in children:
            self.details_bottom_buttons.remove(child)

    def show_page(self, step):
        self.build_succeeded = (step == self.builder.IMAGE_GENERATED)
        image_addr = self.builder.parameters.image_addr
        image_names = self.builder.parameters.image_names
        if self.build_succeeded:
            machine = self.builder.configuration.curr_mach
            base_image = self.builder.recipe_model.get_selected_image()
            layers = self.builder.configuration.layers
            pkg_num = "%s" % len(self.builder.package_model.get_selected_packages())
            log_file = self.builder.current_logfile
        else:
            pkg_num = "N/A"
            log_file = None

        # remove
        for button_id, button in self.button_ids.items():
            button.disconnect(button_id)
        self._remove_all_widget()

        # repack
        self.pack_start(self.details_top_buttons, expand=False, fill=False)
        self.pack_start(self.group_align, expand=True, fill=True)

        self.build_result = None
        if self.image_saved or (self.build_succeeded and self.builder.current_step == self.builder.IMAGE_GENERATING):
            # building is the previous step
            icon = gtk.Image()
            pixmap_path = hic.ICON_INDI_CONFIRM_FILE
            color = HobColors.RUNNING
            pix_buffer = gtk.gdk.pixbuf_new_from_file(pixmap_path)
            icon.set_from_pixbuf(pix_buffer)
            varlist = [""]
            if self.image_saved:
                vallist = ["Your image recipe has been saved"]
            else:
                vallist = ["Your image is ready"]
            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.buttonlist = ["Build new image", "Save image recipe", "Run image", "Deploy image"]

        # Name
        self.image_store = []
        self.toggled_image = ""
        default_image_size = 0
        self.num_toggled = 0
        i = 0
        for image_name in image_names:
            image_size = HobPage._size_to_string(os.stat(os.path.join(image_addr, image_name)).st_size)

            image_attr = ("run" if (self.test_type_runnable(image_name) and self.test_mach_runnable(image_name)) else \
                          ("deploy" if self.test_deployable(image_name) else ""))
            is_toggled = (image_attr != "")

            if not self.toggled_image:
                if i == (len(image_names) - 1):
                    is_toggled = True
                if is_toggled:
                    default_image_size = image_size
                    self.toggled_image = image_name

            split_stuff = image_name.split('.')
            if "rootfs" in split_stuff:
                image_type = image_name[(len(split_stuff[0]) + len(".rootfs") + 1):]
            else:
                image_type = image_name[(len(split_stuff[0]) + 1):]

            self.image_store.append({'name': image_name,
                                    'type': image_type,
                                    'size': image_size,
                                    'is_toggled': is_toggled,
                                    'action_attr': image_attr,})

            i = i + 1
            self.num_toggled += is_toggled

        is_runnable = self.create_bottom_buttons(self.buttonlist, self.toggled_image)

        # Generated image files info
        varlist = ["Name: ", "Files created: ", "Directory: "]
        vallist = []

        vallist.append(image_name.split('.')[0])
        vallist.append(',  '.join(fileitem['type'] for fileitem in self.image_store))
        vallist.append(image_addr)

        view_files_button = HobAltButton("View files")
        view_files_button.connect("clicked", self.view_files_clicked_cb, image_addr)
        view_files_button.set_tooltip_text("Open the directory containing the image files")
        open_log_button = None
        if log_file:
            open_log_button = HobAltButton("Open log")
            open_log_button.connect("clicked", self.open_log_clicked_cb, log_file)
            open_log_button.set_tooltip_text("Open the build's log file")
        self.image_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=view_files_button, button2=open_log_button)
        self.box_group_area.pack_start(self.image_detail, expand=False, fill=True)

        # The default kernel box for the qemu images
        self.sel_kernel = ""
        self.kernel_detail = None
        if 'qemu' in image_name:
            self.sel_kernel = self.get_kernel_file_name()

        #    varlist = ["Kernel: "]
        #    vallist = []
        #    vallist.append(self.sel_kernel)

        #    change_kernel_button = HobAltButton("Change")
        #    change_kernel_button.connect("clicked", self.change_kernel_cb)
        #    change_kernel_button.set_tooltip_text("Change qemu kernel file")
        #    self.kernel_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=change_kernel_button)
        #    self.box_group_area.pack_start(self.kernel_detail, expand=True, fill=True)

        # Machine, Image recipe and Layers
        layer_num_limit = 15
        varlist = ["Machine: ", "Image recipe: ", "Layers: "]
        vallist = []
        self.setting_detail = None
        if self.build_succeeded:
            vallist.append(machine)
            if self.builder.recipe_model.is_custom_image():
                if self.builder.configuration.initial_selected_image == self.builder.recipe_model.__custom_image__:
                    base_image ="New image recipe"
                else:
                    base_image = self.builder.configuration.initial_selected_image + " (edited)"
            vallist.append(base_image)
            i = 0
            for layer in layers:
                if i > layer_num_limit:
                    break
                varlist.append(" - ")
                i += 1
            vallist.append("")
            i = 0
            for layer in layers:
                if i > layer_num_limit:
                    break
                elif i == layer_num_limit:
                    vallist.append("and more...")
                else:
                    vallist.append(layer)
                i += 1

            edit_config_button = HobAltButton("Edit configuration")
            edit_config_button.set_tooltip_text("Edit machine and image recipe")
            edit_config_button.connect("clicked", self.edit_config_button_clicked_cb)
            self.setting_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_config_button)
            self.box_group_area.pack_start(self.setting_detail, expand=True, fill=True)

        # Packages included, and Total image size
        varlist = ["Packages included: ", "Total image size: "]
        vallist = []
        vallist.append(pkg_num)
        vallist.append(default_image_size)
        self.builder.configuration.image_size = default_image_size
        self.builder.configuration.image_packages = self.builder.configuration.selected_packages
        if self.build_succeeded:
            edit_packages_button = HobAltButton("Edit packages")
            edit_packages_button.set_tooltip_text("Edit the packages included in your image")
            edit_packages_button.connect("clicked", self.edit_packages_button_clicked_cb)
        else: # get to this page from "My images"
            edit_packages_button = None
        self.package_detail = self.DetailBox(varlist=varlist, vallist=vallist, button=edit_packages_button)
        self.box_group_area.pack_start(self.package_detail, expand=True, fill=True)

        # pack the buttons at the bottom, at this time they are already created.
        if self.build_succeeded:
            self.box_group_area.pack_end(self.details_bottom_buttons, expand=False, fill=False)
        else: # for "My images" page
            self.details_separator = gtk.HSeparator()
            self.box_group_area.pack_start(self.details_separator, expand=False, fill=False)
            self.box_group_area.pack_start(self.details_bottom_buttons, expand=False, fill=False)

        self.show_all()
        if self.kernel_detail and (not is_runnable):
            self.kernel_detail.hide()
        self.image_saved = False

    def view_files_clicked_cb(self, button, image_addr):
        subprocess.call("xdg-open /%s" % image_addr, shell=True)

    def open_log_clicked_cb(self, button, log_file):
        if log_file:
            log_file = "file:///" + log_file
            gtk.show_uri(screen=button.get_screen(), uri=log_file, timestamp=0)

    def refresh_package_detail_box(self, image_size):
        self.package_detail.update_line_widgets("Total image size: ", image_size)

    def test_type_runnable(self, image_name):
        type_runnable = False
        for t in self.builder.parameters.runnable_image_types:
            if image_name.endswith(t):
                type_runnable = True
                break
        return type_runnable

    def test_mach_runnable(self, image_name):
        mach_runnable = False
        for t in self.builder.parameters.runnable_machine_patterns:
            if t in image_name:
                mach_runnable = True
                break
        return mach_runnable

    def test_deployable(self, image_name):
        if self.builder.configuration.curr_mach.startswith("qemu"):
            return False
        deployable = False
        for t in self.builder.parameters.deployable_image_types:
            if image_name.endswith(t):
                deployable = True
                break
        return deployable

    def get_kernel_file_name(self, kernel_addr=""):
        kernel_name = ""

        if not kernel_addr:
            kernel_addr = self.builder.parameters.image_addr

        files = [f for f in os.listdir(kernel_addr) if f[0] <> '.']
        for check_file in files:
            if check_file.endswith(".bin"):
                name_splits = check_file.split(".")[0]
                if self.builder.parameters.kernel_image_type in name_splits.split("-"):
                    kernel_name = check_file
                    break

        return kernel_name

    def show_builded_images_dialog(self, widget, primary_action=""):
        title = primary_action if primary_action else "Your builded images"
        dialog = CrumbsDialog(title, self.builder,
                              gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT)
        dialog.set_border_width(12)

        label = gtk.Label()
        label.set_use_markup(True)
        label.set_alignment(0.0, 0.5)
        label.set_padding(12,0)
        if primary_action == "Run image":
            label.set_markup("<span font_desc='12'>Select the image file you want to run:</span>")
        elif primary_action == "Deploy image":
            label.set_markup("<span font_desc='12'>Select the image file you want to deploy:</span>")
        else:
            label.set_markup("<span font_desc='12'>Select the image file you want to %s</span>" % primary_action)
        dialog.vbox.pack_start(label, expand=False, fill=False)

        # filter created images as action attribution (deploy or run)
        action_attr = ""
        action_images = []
        for fileitem in self.image_store:
            action_attr = fileitem['action_attr']
            if  (action_attr == 'run' and primary_action == "Run image") \
             or (action_attr == 'deploy' and primary_action == "Deploy image"):
                action_images.append(fileitem)

        # pack the corresponding 'runnable' or 'deploy' radio_buttons, if there has no more than one file.
        # assume that there does not both have 'deploy' and 'runnable' files in the same building result
        # in possible as design.
        curr_row = 0
        rows = (len(action_images)) if len(action_images) < 10 else 10
        table = gtk.Table(rows, 10, True)
        table.set_row_spacings(6)
        table.set_col_spacing(0, 12)
        table.set_col_spacing(5, 12)

        sel_parent_btn = None
        for fileitem in action_images:
            sel_btn = gtk.RadioButton(sel_parent_btn, fileitem['type'])
            sel_parent_btn = sel_btn if not sel_parent_btn else sel_parent_btn
            sel_btn.set_active(fileitem['is_toggled'])
            sel_btn.connect('toggled', self.table_selected_cb, fileitem)
            if curr_row < 10:
                table.attach(sel_btn, 0, 4, curr_row, curr_row + 1, xpadding=24)
            else:
                table.attach(sel_btn, 5, 9, curr_row - 10, curr_row - 9, xpadding=24)
            curr_row += 1

        dialog.vbox.pack_start(table, expand=False, fill=False, padding=6)

        button = dialog.add_button("Cancel", gtk.RESPONSE_CANCEL)
        HobAltButton.style_button(button)

        if primary_action:
            button = dialog.add_button(primary_action, gtk.RESPONSE_YES)
            HobButton.style_button(button)

        dialog.show_all()

        response = dialog.run()
        dialog.destroy()

        if response != gtk.RESPONSE_YES:
            return

        for fileitem in self.image_store:
            if fileitem['is_toggled']:
                if fileitem['action_attr'] == 'run':
                    self.builder.runqemu_image(fileitem['name'], self.sel_kernel)
                elif fileitem['action_attr'] == 'deploy':
                    self.builder.deploy_image(fileitem['name'])

    def table_selected_cb(self, tbutton, image):
        image['is_toggled'] = tbutton.get_active()
        if image['is_toggled']:
            self.toggled_image = image['name']

    def change_kernel_cb(self, widget):
        kernel_path = self.builder.show_load_kernel_dialog()
        if kernel_path and self.kernel_detail:
            import os.path
            self.sel_kernel = os.path.basename(kernel_path)
            markup = self.kernel_detail.format_line("Kernel: ", self.sel_kernel)
            label = ((self.kernel_detail.get_children()[0]).get_children()[0]).get_children()[0]
            label.set_markup(markup)

    def create_bottom_buttons(self, buttonlist, image_name):
        # Create the buttons at the bottom
        created = False
        packed = False
        self.button_ids = {}
        is_runnable = False

        # create button "Deploy image"
        name = "Deploy image"
        if name in buttonlist and self.test_deployable(image_name):
            deploy_button = HobButton('Deploy image')
            #deploy_button.set_size_request(205, 49)
            deploy_button.set_tooltip_text("Burn a live image to a USB drive or flash memory")
            deploy_button.set_flags(gtk.CAN_DEFAULT)
            button_id = deploy_button.connect("clicked", self.deploy_button_clicked_cb)
            self.button_ids[button_id] = deploy_button
            self.details_bottom_buttons.pack_end(deploy_button, expand=False, fill=False)
            created = True
            packed = True

        name = "Run image"
        if name in buttonlist and self.test_type_runnable(image_name) and self.test_mach_runnable(image_name):
            if created == True:
                # separator
                #label = gtk.Label(" or ")
                #self.details_bottom_buttons.pack_end(label, expand=False, fill=False)

                # create button "Run image"
                run_button = HobAltButton("Run image")
            else:
                # create button "Run image" as the primary button
                run_button = HobButton("Run image")
                #run_button.set_size_request(205, 49)
                run_button.set_flags(gtk.CAN_DEFAULT)
                packed = True
            run_button.set_tooltip_text("Start up an image with qemu emulator")
            button_id = run_button.connect("clicked", self.run_button_clicked_cb)
            self.button_ids[button_id] = run_button
            self.details_bottom_buttons.pack_end(run_button, expand=False, fill=False)
            created = 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")
            save_button.set_tooltip_text("Keep your changes saving them as an image recipe")
            save_button.set_sensitive(not self.image_saved)
            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"
        if name in buttonlist:
            # create button "Build new image"
            if packed:
                build_new_button = HobAltButton("Build new image")
            else:
                build_new_button = HobButton("Build new image")
                build_new_button.set_flags(gtk.CAN_DEFAULT)
            #build_new_button.set_size_request(205, 49)
            self.details_bottom_buttons.pack_end(build_new_button, expand=False, fill=False)
            build_new_button.set_tooltip_text("Create a new image from scratch")
            button_id = build_new_button.connect("clicked", self.build_new_button_clicked_cb)
            self.button_ids[button_id] = build_new_button

        return is_runnable

    def deploy_button_clicked_cb(self, button):
        if self.toggled_image:
            if self.num_toggled > 1:
                self.set_sensitive(False)
                self.show_builded_images_dialog(None, "Deploy image")
                self.set_sensitive(True)
            else:
                self.builder.deploy_image(self.toggled_image)

    def run_button_clicked_cb(self, button):
        if self.toggled_image:
            if self.num_toggled > 1:
                self.set_sensitive(False)
                self.show_builded_images_dialog(None, "Run image")
                self.set_sensitive(True)
            else:
                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/"
        self.builder.ensure_dir(images_dir)

        self.name_field_template = self.builder.image_configuration_page.custom_image_selected
        if self.name_field_template:
            image_path = self.builder.recipe_model.pn_path[self.name_field_template]
            image_iter = self.builder.recipe_model.get_iter(image_path)
            self.description_field_template = self.builder.recipe_model.get_value(image_iter, self.builder.recipe_model.COL_DESC)
        else:
            self.name_field_template = ""

        dialog = SaveImageDialog(images_dir, self.name_field_template, self.description_field_template,
                 "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):
        self.builder.initiate_new_build_async()

    def edit_config_button_clicked_cb(self, button):
        self.builder.show_configuration()

    def edit_packages_button_clicked_cb(self, button):
        self.builder.show_packages(ask=False)

    def my_images_button_clicked_cb(self, button):
        self.builder.show_load_my_images_dialog()

    def settings_button_clicked_cb(self, button):
        # Create an advanced settings dialog
        response, settings_changed = self.builder.show_simple_settings_dialog()
        if not response:
            return
        if settings_changed:
            self.builder.reparse_post_adv_settings()
