#
# package_gui.py: package group and individual package selection screens
#
# Brent Fox <bfox@redhat.com>
# Matt Wilson <msw@redhat.com>
# Jeremy Katz <katzj@redhat.com>
#
# Copyright 2000-2002 Red Hat, Inc.
#
# This software may be freely redistributed under the terms of the GNU
# library public license.
#
# You should have received a copy of the GNU Library Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#

import rpm
import string
import sys, os
import gtk
import gobject
from size_string import size_string

from string import *
from thread import *
from config import *
from rhpl.translate import _, N_, utf8
from rhpl.log import log
from constants import *
from GroupSet import orderPackageGroups
from GroupSet import Package, Group
import GroupDetails

class PackageSelectionWindow (gobject.GObject):
    windowTitle = N_("Package Group Selection")
    htmlTag = "sel-group"

    __gsignals__ = {
        'changed': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ())
    }

    def __init__ (self):
        self.__gobject_init__() # default constructor using our new GType

    def do_changed (self):
	self.setSize()

    def setSize(self):
        self.sizelabel.set_text (_("Total install size: %s") % 
					self.comps.sizeStr())

    def componentToggled(self, widget, data):
        # turn on all the comps we selected
	(comp, lbl, count, al, ebutton) = data
	if widget.get_active ():
            if ebutton:
                al.add(ebutton)
                al.show_all()
	    comp.select ()
	else:
            if ebutton in al.get_children():
                al.remove(ebutton)
	    comp.unselect ()

	if lbl:
	    self.setCompLabel(comp, lbl)
        if count:
            self.setCompCountLabel(comp, count)
        self.emit ('changed')

    def getStats(self, comp):
        allpkgs = comp.packageInfo()

        selected = 0
        for pkgnevra in allpkgs.keys():
            if self.comps.hdrlist[pkgnevra].isSelected():
                selected = selected + 1

        return (selected, len(allpkgs.keys()))

    def setDetailSizeLabel(self, comp, sizeLabel):
        text = _("Total install size: %s") % (self.comps.sizeStr(),)
	sizeLabel.set_text(text)

    def setCompLabel(self, comp, label):
	(selpkg, totpkg) = self.getStats(comp)
        if not comp.isSelected(justManual = 1):
            selpkg = 0

	label.set_markup("<b>%s</b>" % (_(comp.name),))

    def setCompCountLabel(self, comp, label):
	(selpkg, totpkg) = self.getStats(comp)
        if not comp.isSelected(justManual = 1):
            selpkg = 0

	if comp.name == u"Everything":
	    txt = ""
	else:
	    txt = "<b>[%d/%d]</b>" % (selpkg, totpkg)
	    
	label.set_markup(txt)

    def editDetails(self, button, data):

	# do all magic for packages and metapackages
	def getDescription(obj, comp):
            basedesc = obj.getDescription()

	    if basedesc is not None:
		desc = replace (basedesc, "\n\n", "\x00")
		desc = replace (desc, "\n", " ")
		desc = replace (desc, "\x00", "\n\n")
		desc = utf8(desc)
	    else:
		desc = ""
	    return "%s - %s" % (obj.name, desc)


	#
	# START OF editDetails
	#
	# backup state
	(comp, lbl, count) = data
        dialog = GroupDetails.GroupDetails (self.comps, comp, button.get_toplevel ())
        dialog.run ()
	if lbl:
	    self.setCompLabel(comp, lbl)
        if count:
            self.setCompCountLabel(comp, count)
        self.emit ('changed')
        return
    

    def getScreen(self, comps, im):
    # PackageSelectionWindow tag="sel-group"
        ICON_SIZE = 32
        
	self.comps = comps

#	self.origSelection = self.comps.getSelectionState()

        self.checkButtons = []
	(parlist, pardict) = orderPackageGroups(self.comps)

        row = 0

        topbox = gtk.VBox(gtk.FALSE, 3)
        topbox.set_border_width(3)
        
        checkGroup = gtk.SizeGroup(gtk.SIZE_GROUP_BOTH)
        countGroup = gtk.SizeGroup(gtk.SIZE_GROUP_BOTH)
        detailGroup = gtk.SizeGroup(gtk.SIZE_GROUP_BOTH)
        
	for par in parlist:
            # set the background to our selection color
	    eventBox = gtk.EventBox()
            eventBox.ensure_style ()
            style = eventBox.get_style ()
	    eventBox.modify_bg(gtk.STATE_NORMAL, style.base[gtk.STATE_SELECTED])
	    lbl = gtk.Label("")
	    lbl.set_markup("<span foreground='white'><big><b>"
                           "%s</b></big></span>" % (par,))
	    lbl.set_alignment(0.0, 0.0)
            pad = gtk.Alignment(0.0, 0.0)
            pad.add(lbl)
            pad.set_border_width(3)
            eventBox.add(pad)
            topbox.pack_start(eventBox)
            size_group = gtk.SizeGroup (gtk.SIZE_GROUP_HORIZONTAL)
	    for comp in pardict[par]:
		if comp.hidden:
		    continue
		
		pixname = string.lower(comp.id) + ".png"
                fn = None
                for dir in im.pixmapPath:
                    if os.access(dir + "/" + pixname, os.R_OK):
                        fn = dir + "/" + pixname
                        break
		if not fn:
		    # could not load pix
		    pix = None
		else:
                    try:
                        rawpix = gtk.gdk.pixbuf_new_from_file(fn)
                        sclpix = rawpix.scale_simple(ICON_SIZE, ICON_SIZE,
                                                     gtk.gdk.INTERP_BILINEAR)
                        pix = gtk.Image()
                        pix.set_from_pixbuf(sclpix)
                    except:
                        pix = None

                compbox = gtk.HBox(gtk.FALSE, 5)                

                spacer = gtk.Fixed()
                spacer.set_size_request(30, -1)
                compbox.pack_start(spacer, gtk.FALSE, gtk.FALSE)

		# create check button and edit button
		# make the comps title + edit button
		hdrlabel=gtk.Label("")
		hdrlabel.set_alignment (0.0, 0.5)
		self.setCompLabel(comp, hdrlabel)
		count=gtk.Label("")
                buttonal = gtk.Alignment(0.5, 0.5)
                editbutton = gtk.Button()

                
                # we check the black list to see if the component can be removed
                if comp.id in COMPS_BLACK_LIST and comp.installState == INSTALLED:
                    checkGroup.add_widget(hdrlabel)
                    compbox.pack_start(hdrlabel)
                else:
                    checkButton = gtk.CheckButton()
                    checkButton.add(hdrlabel)
                    checkButton.set_active (comp.isSelected(justManual = 1))
                    checkButton.connect('toggled', self.componentToggled,
                                        (comp, hdrlabel, count, buttonal,
                                         editbutton))
                    checkGroup.add_widget(checkButton)
                    compbox.pack_start(checkButton)

		count.set_alignment (1.0, 0.5)
		self.setCompCountLabel(comp, count)
                countGroup.add_widget(count)
                compbox.pack_start(count, gtk.FALSE, gtk.FALSE)

                spacer = gtk.Fixed()
                spacer.set_size_request(15, -1)
                compbox.pack_start(spacer, gtk.FALSE, gtk.FALSE)
                detailGroup.add_widget(buttonal)
                compbox.pack_start(buttonal, gtk.FALSE, gtk.FALSE)

		# now make the url looking button for details
		if comp.name != u"Everything":
		    nlbl = gtk.Label("")
                    selected = comp.isSelected(justManual = 1)
                    nlbl.set_markup('<span foreground="#3030c0"><u>'
                                    '%s</u></span>' % (_('Details'),))
		    editbutton.add(nlbl)
		    editbutton.set_relief(gtk.RELIEF_NONE)
		    editbutton.connect("clicked", self.editDetails,
				       (comp, hdrlabel, count))
                    if comp.isSelected(justManual = 1):
                        buttonal.add(editbutton)
		else:
		    editbutton = None

                topbox.pack_start(compbox)

                detailbox = gtk.HBox(gtk.FALSE)

                spacer = gtk.Fixed()
                spacer.set_size_request(45, -1)
                detailbox.pack_start(spacer, gtk.FALSE, gtk.FALSE)
                
		# icon
		if pix is not None:
		    al = gtk.Alignment(0.5, 0.5)
		    al.add(pix)
                    size_group.add_widget (al)
                    detailbox.pack_start(al, gtk.FALSE, gtk.FALSE, 10)
                    
		# add description if it exists
		descr = comp.getDescription()
		if descr is not None:
		    label=gtk.Label("")
		    label.set_alignment (0.0, 0.0)
		    label.set_line_wrap(gtk.TRUE)
		    label.set_size_request(350, -1)
		    label.set_markup("%s" % (_(descr),))
                    detailbox.pack_start(label, gtk.TRUE)
                topbox.pack_start(detailbox)

		self.checkButtons.append ((compbox, detailbox, comp))

            # add some extra space to the end of each group
            spacer = gtk.Fixed()
            spacer.set_size_request(-1, 3)
            topbox.pack_start(spacer, gtk.FALSE, gtk.FALSE)

        sw = gtk.ScrolledWindow()
        sw.set_policy (gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        viewport = gtk.Viewport(sw.get_hadjustment(), sw.get_vadjustment())
        sw.add(viewport)
        viewport.add(topbox)
        viewport.set_property('shadow-type', gtk.SHADOW_IN)
	viewport.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse("white"))
        topbox.set_focus_hadjustment(sw.get_hadjustment())
        topbox.set_focus_vadjustment(sw.get_vadjustment())

        hbox = gtk.HBox (gtk.FALSE, 5)

        self.sizelabel = gtk.Label ("")
        self.setSize()
        hbox.pack_start (self.sizelabel, gtk.TRUE)
        
        vbox = gtk.VBox (gtk.FALSE, 5)
        vbox.pack_start (sw, gtk.TRUE)
        vbox.pack_start (hbox, gtk.FALSE)
        vbox.set_border_width (5)

        return vbox


gobject.type_register(PackageSelectionWindow)
