#!/usr/bin/env python
######################################################################
#
# Filename: redist
#
# Content: Create a new Runtime Installer
#          Strip unwanted packages.
#
# Copyright (c) 2009 Matrox Electronic Systems Ltd.
# All Right Reserved
#
######################################################################
import sys, commands, os, re, commands, ConfigParser,shlex, subprocess
from optparse import OptionParser
usegtk = True
try:
    import pygtk
    pygtk.require("2.0")
    try:
        import gtk
    except:
        usegtk = False        
except:
    usegtk = False


class Installer:
    """
    Installer object used to extract and rebuild the installer
    """
    def __init__(self, options):
        """
        Initialize data 
        """
        self.options=options
        if not self.options.internal:
            self.destdir = self.options.destdir
            self.config = self.destdir + "/config.ini"
            self.installer = os.path.basename(self.options.installer)
            self.fullInstaller =  os.getcwd() + "/" + self.installer    
            if self.options.installer[0] == '/':
                self.fullInstaller =  self.options.installer
        else:
            self.destdir=os.getcwd()
            self.installer= ""
            self.fullInstaller=""
            self.config= os.getcwd() + "/config.ini"

        self.targetdir = self.options.targetdir
        self.type=""
        self.build=""
        self.branche=""
        self.arch=""
        self.earlyaccess=""
        self.configValid = False

        if self.options.verbose:
            print "Init"
            print "installer: " + self.installer
            print "full path installer: " + self.fullInstaller
            print "config :" + self.config

        if  self.options.internal:
            try:
                self.__configParser = ConfigParser.RawConfigParser()
                self.__configParser.read(self.config)
                sections =  self.__configParser.sections()
                if len(sections):
                    self.configValid = True
            except:
                print "Error parsing config file"
                self.configValid = False;
                pass
            
    def GetConfig(self):
        """
        return the config file
        """
        return self.config

    def GetDestDir(self):
        """
        return the destibnation directory whre the installer is extracted
        """
        return self.destdir

    def GetTargetDir(self):
        """
        return the directory where the final installer will be copied
        """
        return self.targetdir

    def GetConfigParser(self):
        """
        return the config parser object used to parse the config ini file
        """
        return self.__configParser

    def ConfigValid(self):
        """
        return true if the config is valid
        """
        return self.configValid

    def __getInfo(self):
        """
        get info about this installer (build, version,...) needed to rebuild the installer
        """
        if self.options.verbose:
            print "getInfo"

        if not os.path.exists(self.config):
            return False
        if not self.configValid:
            return False

        self.build = self.__configParser.get('global', 'milbuild')
        milversion = self.__configParser.get('global', 'milversion')

        if not milversion:
            return False

        milversion=milversion.lower()
        self.branche=self.__configParser.get('global', 'milversion_number')
        if self.branche:
            pass
        else:
            self.branche ="10.00"

        self.arch="32"
        self.type="FULL"

        if re.search("early access", milversion) != None:
            self.earlyaccess = "ea"
        elif re.search("engineering", milversion) != None:
            self.earlyaccess = "es"
            
        if re.search("64-bit", milversion) != None:
            self.arch="64"    

        if re.search("lite", milversion) != None:
            self.type="LITE"

        if self.options.verbose:
            print "installer build   :" + self.build
            print "installer arch    :" + self.arch
            print "installer branche :" + self.branche
            print "installer type    :" + self.type

        if self.type and self.build and self.branche:            
            return True

        print >>sys.stderr, "Error: Could not get Build informations."
        return False

    # Extract the installer to dest directory
    def Extract(self):
        """
        Extract the installer into destination directory
        Do nothing if we are inside the installer (internal == True)
        """
        if self.options.verbose:
            print "Extract"
            
        if self.options.internal  == True:
            return True

        if not os.path.exists(self.fullInstaller):
            print >>sys.stderr, "Error: Could not find the installer file."
            return False

        # run extract comand
        run_commands = ["rm -rf "+ self.options.destdir, "chmod +x " +self.fullInstaller, self.fullInstaller+" --noexec --target "+self.options.destdir]
        if self.options.verbose:
            print "extract command:  "
            print run_commands

        for cmd in run_commands :
            try:
                args = shlex.split(cmd)
                p = subprocess.Popen(args,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                run_result = p.wait()
                if not run_result == 0:
                    print >>sys.stderr, "Error: Could not extract the installer to a temporary directory."
                    return False
            except:
                return False
            
        try:
            self.__configParser = ConfigParser.RawConfigParser()
            self.__configParser.read(self.config)
            sections =  self.__configParser.sections()
            if len(sections):
                self.configValid = True
        except:
            print "Error parsing config file"
            self.configValid = False;
            print >>sys.stderr, "Error: Could not parse the installer config file."
            return False

        return True

    def GetInstallerName(self):
        """
        return the installer file name 
        """
        if not self.branche or not self.build or not self.arch or not self.type:
            return ""
        
        if self.installer:
            return self.installer

        if self.type == "FULL":
            installerName = "mil-" + self.branche + "_"
        else:
            installerName = "mil-lite-" + self.branche + "_"

        if self.earlyaccess:
            installerName+=self.earlyaccess + "_"

        if self.arch == "32":
            installerName+= self.build + "-installer.run"
        else:
            installerName+= self.build + "-installer64.run"
        return installerName
            

    def Rebuild(self):
        """
        Rebuild the installer using Makeself script
        and write the installer inot target directory
        """
        self.targetdir = self.options.targetdir
        if self.options.verbose:
            print "Rebuild"

        if not os.path.exists(self.config):
            print >>sys.stderr, "Error: Could not parse the installer config file."
            return False

        if self.options.internal and not os.path.exists("makeself"):
            print >>sys.stderr, "Error: No makeself found inside the installer."
            return False
        
        if not self.options.internal and not os.path.exists(self.destdir + "/makeself"):
            print >>sys.stderr, "Error: No makeself found inside the installer."
            return False
            
        if not self.__getInfo():
            return False

        
        # get  installer name
        installerName = self.GetInstallerName()
        if installerName == "":
            print >>sys.stderr, "Error: Could not get installer name."
            return False

        # make label
        milType = self.type
        if milType == "FULL":
            milType = ""

        Label = " \"MIL " + milType + " " + self.branche + " (" + self.earlyaccess.upper() + " " + self.build + " ) installer\" "   
            
        if self.options.internal == True:
            run_command = "./makeself --header  ./makeself-header --gzip . " + self.targetdir + "/" + installerName + Label + "./mil-installer"
        else:
            run_command = self.destdir + "/makeself --header  " + self.destdir + "/makeself-header --gzip " + self.destdir + " "+ self.targetdir + "/" + installerName + Label + "./mil-installer"

        if self.options.verbose:
            print "rebuild command:  " + run_command
        try:
            args = shlex.split(run_command)
            p = subprocess.Popen(args,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
            run_result = p.wait()
            if not run_result == 0:
                print >>sys.stderr, "Error: rebuilding the new installer."
                return False
        except:
            print >>sys.stderr, "Error: rebuilding the new installer."
            return False

        return True

##########################################
# Redist class text interface
###########################################    
class Redist:
    """
    Redist base class , use text/console to edit the configuration 
    """
    def __init__(self, options):
        self.options=options
        self.filesToRemove   = []
        self.configParser    = None
        self.installer       = None
        self.configFile      = None
        self.distro          = ['ubuntu12.04', 'sle11', 'rhel6.0']
        self.allExceptDistro = ['global', 'defaultdcf', 'defaultvcf', 'displaynames', 'docnames']
        self.distroLabels    = {'sle11':'Suse Enterprise 11',
                                'sle11_64':'Suse Enterprise 11 (64-bit)',
                                'rhel6.0': 'Red Hat Enterprise Linux 6',
                                'rhel6.0_64': 'Red Hat Enterprise Linux 6 (64-bit)',
                                'ubuntu12.04':'Ubuntu 12.04',
                                'ubuntu12.04_64':'Ubuntu 12.04 (64-bit)'}

    def StripPackages(self):
        """
        Remove unused packages 
        """
        for f  in self.filesToRemove:
            file = self.installer.GetDestDir() + "/" + f
            if self.options.verbose:
                print "removing packages..." + file
            if os.path.exists(file):
                try:
                    os.remove(file)
                except:
                    print >>sys.stderr, "Error removing file " + file
            
    def RewriteConfig(self):
        """
        write the new config file use by the installer
        """
        configfile = self.configFile
        if self.configParser == None : return False
        newconfigfile = configfile + ".new"
        try:
            f = open(newconfigfile, 'w')
            # ordered sections
            sections = self.configParser.sections()
            for section in self.allExceptDistro:
                sections.remove(section)
            sections = self.allExceptDistro + sections

            for section in sections:
                f.write("[%s]\n" % section)
                for (key,value) in sorted(self.configParser.items(section)):
                    if key != "__name__":
                        f.write("%s = %s\n" % (key, str(value).replace('\n', '\n\t')))
                f.write("\n")
            run_command = "mv " + newconfigfile + " " + configfile
            try:
                args = shlex.split(run_command)
                p = subprocess.Popen(args,stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
                run_result = p.wait()
                if not run_result == 0:
                    print >>sys.stderr, "Error generating new installer config file."
                    return False
            except:
                print >>sys.stderr, "Error generating new installer config file."
                return False
        except:
            print >>sys.stderr, "Error writing new installer config file."
            return False
        return True
        
    def __response(self, prompt, default="yes", retries=4):
        """
        get a response yes/no
        """
        default_response = True
        if default.lower() == "yes":
            prompt+=" ? (yes/no) [Yes] "
        else:
            default_response = False;
            prompt+=" ? (yes/no) [No] "
        while True:
            ok = raw_input(prompt)
            ok = ok.lower()
            if not ok:
                return default_response
            if ok in ('y', 'ye', 'yes'): return True
            if ok in ('n', 'no', 'nop', 'nope'): return False
            retries = retries - 1
            if retries < 0: raise IOError, 'refusd'


    def Run(self):
        """
        main function: extract installer, edit configuration and rebuild a new installer
        """
        self.installer = Installer(self.options)
        if self.options.internal == False:
            if not self.installer.Extract():
                print >>sys.stderr, "Error extracting the installer."
                return False

        self.configFile = self.installer.GetConfig()
        if not os.path.exists(self.configFile):
            print >>sys.stderr, "Error config file not found."
            return False

        if not self.installer.ConfigValid():
            print >>sys.stderr, "Error invalid config file."
            return false;
        self.configParser = self.installer.GetConfigParser()

        os.system("clear")
        print "Redist a Runtime MIL"
        displaynames = 'displaynames'

        milversion = self.configParser.get('global', 'milversion')
        print "MIL Version: ", milversion
        sections =  self.configParser.sections()
        try:
            if not displaynames in sections:
                self.allExceptDistro.remove(displaynames)
        except:
            pass

        oldsections =  self.configParser.sections()
        for s in oldsections:
            if s in self.allExceptDistro or self.configParser.get(s,'distro_enabled').lower() != "yes":
                sections.remove(s)

        for section in sections:
            print ""
            # remove examples package anyway
            if self.configParser.has_option(section,'package_examples'):
                toRemove = self.configParser.get(section,'package_examples')
                self.filesToRemove.append(toRemove)

            if self.__response("Enable " + self.distroLabels[section], "yes"):
                print "Please choose boards you would like to enable for [",self.distroLabels[section], "]"
                self.configParser.set(section,'distro_enabled','yes')
                Boards = self.configParser.get(section,'boards').split(',')
                AllBoards= []
                print ""
                for board in Boards:
                    if self.__response("Enable board " + board, "yes"):
                        AllBoards.append(board)

                s = ",".join(AllBoards)
                AllBoardsStr = s
                if s  and s[0] == ',': AllBoardsStr = s[1:]
                self.configParser.set(section,'boards',AllBoardsStr)
            else:
                self.configParser.set(section,'distro_enabled','no')
                package = self.configParser.get(section,'package')
                self.filesToRemove.append(package)
                package_display = self.configParser.get(section,'package_display')
                self.filesToRemove.append(package_display)


        # Distributed MIL
        print ""
        if self.configParser.has_option('global','components'):
            components = self.configParser.get('global','components').lower()
            if components.find("distributedmil") !=-1:
                if self.__response("Enable Distributed MIL ", "yes"):
                    self.configParser.set('global','components','distributedmil')
                else:
                    self.configParser.set('global','components','')
                
        # CmStick (Dongle)
        print ""
        if not self.__response("CmStick (Dongle) ", "yes"):
            # CmStick disabled remove all codemeters packages
            for section in sections:
                print ""
                toRemove = self.configParser.get(section,'package_license')
                self.filesToRemove.append(toRemove)

                
        # loop and remove unused package    
        self.StripPackages() 

        # rewrite new config
        if not self.RewriteConfig():
            return False
            
        # rebuild the installer
        if not self.installer.Rebuild():
            print >>sys.stderr, "Error rebuilding the installer."
            return False

        print "New installer " + self.installer.GetInstallerName() + " created in " + self.installer.GetTargetDir()

        return True

##########################################
# Redist class Gtk interface
###########################################    
class RedistGtk(Redist):
    """
    A Gtk interface to Redist 
    """
    def __init__(self, options):
        if hasattr(Redist, '__init__'):
            Redist.__init__(self, options)

        # Private  Gtk     
        self.__mainWindow                 = None
        self.__mainVBox                   = None
        self.__distroFrame                = None
        self.__distroVBox                 = None
        self.__otherMILFrame              = None
        self.__distributedMILCheckButton  = None
        self.__wibuDongleCheckButton      = None
        self.__dmaServiceCheckButton      = None
        self.__buttonSource               = None
        self.__buttonDestination          = None
        self.__buttonCancel               = None
        self.__buttonGenerate             = None
        self.__editSource                 = None
        self.__editDestination            = None
        self.__labelMilVersion            = None
        self.__distroCheckButtons         = {} # disto:checkbox
        self.__allCheckButtons            = {} # distro:[list of boards checkbox]
        self.__returnValue                = False 
        self.__initilized                 = False

    def __Message(self, message, message_type = gtk.MESSAGE_INFO):
        """
        A popup up message dialog
        """
        dialog = gtk.MessageDialog(None, gtk.DIALOG_MODAL, message_type, gtk.BUTTONS_CLOSE, message)

        ret = dialog.run()
        dialog.destroy()
    
    def __Show(self, w=None):
        """
        Callback called after main window is showed  
        """
        self.__FillData()

    def __Cancel(self, w=None, data=None):
        """
        Callback called when cancel button is clicked or window is detroyed
        """
        gtk.main_quit()
        if self.options.verbose:
            print "Redist canceled"
        self.__returnValue = False

    def __DoWait(self, flag=True, message=""):
        """
        Display a wait cursor when doing a long task
        or make widgets active when task finished
        """
        self.__labelMilVersion.set_text(message)
        if flag:
            self.__mainWindow.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.WATCH))
            self.__mainVBox.set_sensitive(False)
            self.__labelMilVersion.set_sensitive(True)
            while gtk.events_pending():
                gtk.main_iteration()
        else:
            self.__mainWindow.window.set_cursor(None)
            self.__mainVBox.set_sensitive(True)
            while gtk.events_pending():
                gtk.main_iteration()

    def __Generate(self, widget, data=None):
        """
        Callback called when generate button is clicked    
        """
        self.__returnValue = True
        if  self.installer == None or self.configParser == None:
            self.__returnValue = False
            return

        self.__DoWait(True,"Generating new installer, Please wait,...")
        
        self.StripPackages() 
        
        # rewrite new config
        if not self.RewriteConfig():
            return False

        # rebuild the installer
        Success = self.installer.Rebuild()

        self.__DoWait(False, "Done.")
        
        if Success == True:
            if self.options.verbose:
                print "New installer " + self.installer.GetInstallerName() + " created in " + self.installer.GetTargetDir()
            self.__Message("New installer " + self.installer.GetInstallerName() + " created in " + self.installer.GetTargetDir())
            self.__returnValue = True
        else:
            self.__Message("Error rebuilding the installer.",gtk.MESSAGE_ERROR)
            self.__returnValue = False

        gtk.main_quit()


    def __EnterSource(self, widget, entry):
        """
        Callback when user enter filename in edit Source
        """
        result = entry.get_text()
        if not os.path.isfile(result) or not os.path.exists(result):
            return
        if re.search("run", result) == None:
            return

        self.options.installer = result;
        self.__FillData()        
        
    def __EnterDestination(self, widget, entry):
        """
        Callback when user enter directory in edit Destination
        """
        result = entry.get_text()
        if not os.path.isdir(result) or not os.path.exists(result):
            return

        self.options.targetdir = result
    
    def __DeleteEvent(self, widget, event, data=None):
        """
        Callback called when the main window is close (x)
        """
        if self.options.verbose:
            print "Redist canceled"
        self.__returnValue = False
        return False

    def __BrowseDirectory(self, widget, data=None):
        """
        A Browse dialog to select a directory , called by browse destination button
        """
        dialog = gtk.FileChooserDialog("Select Destination directory",
        None, 
        gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER, 
        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
        if dialog.run() == gtk.RESPONSE_OK and  dialog.get_filename():
            if os.path.isdir(dialog.get_filename()):
                self.__editDestination.set_text(dialog.get_filename())
                self.options.targetdir = dialog.get_filename()
        dialog.destroy()

    def __BrowseFile(self,widget, data=None):
        """
        A Browse file dialog called by browse source button
        """
        dialog = gtk.FileChooserDialog("Select Installer", 
        None, 
        gtk.FILE_CHOOSER_ACTION_OPEN, 
        (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OPEN, gtk.RESPONSE_OK))
       
        filter = gtk.FileFilter()
        filter.set_name("Installer")
        filter.add_pattern("*.run")
        dialog.add_filter(filter)
        result =""
        if dialog.run() == gtk.RESPONSE_OK:
            result= dialog.get_filename()
        dialog.destroy()
        if result:
            self.options.installer = result;
            self.__FillData()
        return result

    def  __DistributedMILToggled(self, widget, data=None):
        """
        Callback called when a distributed MIL check button is toggled
        """
        if not self.installer or not self.configParser:
            return
        Active = widget.get_active()
        if Active:
            self.configParser.set('global','components','distributedmil')
        else:
            self.configParser.set('global','components','')

    def  __CmStickDongleToggled(self, widget, data=None):
        """
        Callback called when the CmStick Dongle is enabled toggled
        """
        section = data
        if not section or not self.installer or not self.configParser:
            return

        package_license  = self.configParser.get(section,'package_license')
        Active = widget.get_active()
        if Active:
            if package_license in self.filesToRemove:
                self.filesToRemove.remove(package_license)
        else:
            self.filesToRemove.append(package_license)

    def  __DMAServiceToggled(self, widget, data=None):
        """
        Callback called when the Memory/PCI Service is enabled toggled
        """
        if not self.installer or not self.configParser:
            return

        Active = widget.get_active()
        if Active:
            self.configParser.set('global','dmaservice','yes')
        else:
            self.configParser.set('global','dmaservice','no')

    def  __DistroToggled(self, widget, data=None):
        """
        Callback called when a distro check button is toggled
        """
        section = data
        if not section or not self.installer or not self.configParser:
            return

        # Update config
        package  = self.configParser.get(section,'package')
        package_display  = self.configParser.get(section,'package_display')
        Active = widget.get_active()
        if Active:
            if package in self.filesToRemove:
                self.filesToRemove.remove(package)
            if package_display in self.filesToRemove:
                self.filesToRemove.remove(package_display)

            self.configParser.set(data,'distro_enabled','yes')
        else:
            self.filesToRemove.append(package)
            self.filesToRemove.append(package_display)
            self.configParser.set(data,'distro_enabled','no')

        # toggle boards
        try:
            for b in self.__allCheckButtons[section]:
                b.set_active(Active)
                b.set_sensitive(Active)
        except:
            pass
        
        # check if DMA Service can be enabled
        DMAServiceEnabled = True
        try:
            for d in self.__allCheckButtons.keys():
                for b in self.__allCheckButtons[d]:
                    if b.get_active():
                        DMAServiceEnabled = False
                        break
        except:
            pass

        if DMAServiceEnabled:
            self.__dmaServiceCheckButton.set_sensitive(True)
        else:
            self.__dmaServiceCheckButton.set_sensitive(False)
            self.__dmaServiceCheckButton.set_active(True)
                
    def __BoardToggled(self, widget, data=None):
        """
        Callback called when a boards check button is toggled
        """
        if not isinstance(data,list) or  len(data) != 2:
            return

        if not self.installer or not self.configParser:
            return
        section = data[1]
        board   = data[0]
        BoardsStr = self.configParser.get(section,'boards')
        Active = widget.get_active()

        BoardsList = BoardsStr.split(',')
        if board in BoardsList: BoardsList.remove(board)

        s = ",".join(BoardsList)
        self.configParser.set(section,'boards',s)
        if s  and s[0] == ',': 
            self.configParser.set(section,'boards',s[1:])
            
        # check if DMA Service can be enabled
        DMAServiceEnabled = True
        for d in self.__allCheckButtons.keys():
            for b in self.__allCheckButtons[d]:
                if b.get_active():
                    DMAServiceEnabled = False
                    break

        if DMAServiceEnabled:
            self.__dmaServiceCheckButton.set_sensitive(True)
        else:
            self.__dmaServiceCheckButton.set_sensitive(False)
            self.__dmaServiceCheckButton.set_active(True)
        
    def __InitDialog(self):
        """
        display the main window dialog
        """
        self.__mainWindow = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.__mainWindow.set_title("Matrox Imaging Library Redistribution")
        self.__mainWindow.connect("destroy", self.__Cancel)
        self.__mainWindow.connect("delete_event", self.__DeleteEvent)
        self.__mainWindow.connect("map", self.__Show)

        vbox = gtk.VBox(False, 0)
        self.__mainWindow.add(vbox)

        self.__mainVBox = gtk.VBox(False, 5)
        vbox.pack_end(self.__mainVBox, True, True, 0)        
        
        self.__labelMilVersion = gtk.Label("")
        hbox = gtk.HBox(False, 10)
        hbox.pack_start(self.__labelMilVersion, False, False, 5)        
        vbox.pack_start(hbox, False, False, 10)        
        
        # Location Frame
        frame = gtk.Frame("Location")
        self.__mainVBox.pack_start(frame, False, False, 0)
        vbox = gtk.VBox(False, 10)
        frame.add(vbox)

        hbox = gtk.HBox(False, 0)
        vbox.pack_start(hbox, False, False, 0)

        table = gtk.Table(rows=2, columns=3, homogeneous=False)
        hbox.pack_start(table, True, True, 0)

        # Source
        label = gtk.Label(" Source : ")
        label.set_alignment(0,0)
        table.attach(label, 0, 1, 0, 1, gtk.FILL, gtk.FILL, 0, 0)
        self.__editSource = gtk.Entry()
        table.attach(self.__editSource, 1, 2, 0, 1)
        self.__buttonSource = gtk.Button("Browse")
        table.attach(self.__buttonSource, 2, 3, 0, 1, gtk.FILL, gtk.FILL, 0, 0)
        self.__buttonSource.connect("clicked", self.__BrowseFile, True)
        self.__editSource.connect("activate", self.__EnterSource, self.__editSource)
     
        # Destination
        label = gtk.Label(" Destination : ")
        label.set_alignment(0,0)
        table.attach(label, 0, 1, 1, 2, gtk.FILL, gtk.FILL, 0, 0)
        self.__editDestination = gtk.Entry()
        table.attach(self.__editDestination, 1, 2, 1, 2)
        self.__buttonDestination = gtk.Button("Browse")
        table.attach(self.__buttonDestination, 2, 3, 1, 2, gtk.FILL, gtk.FILL, 0, 0)
        self.__buttonDestination.connect("clicked", self.__BrowseDirectory, False)
        self.__editDestination.connect("activate", self.__EnterDestination, self.__editDestination)

        # Linux Distributions Frame
        self.__distroFrame = gtk.Frame("Linux Distributions")
        self.__mainVBox.pack_start(self.__distroFrame, False, False, 5)
        self.__distroVBox = gtk.VBox(False, 10)
        self.__distroFrame.add(self.__distroVBox)

        # Distributed MIL and CmStick
        self.__otherMILFrame = gtk.Frame("Other Services")
        self.__mainVBox.pack_start(self.__otherMILFrame, False, False, 5)
        vbox = gtk.VBox(False, 5)
        self.__otherMILFrame.add(vbox)
        hbox = gtk.HBox(False, 5)
        vbox.add(hbox)
        self.__distributedMILCheckButton = gtk.CheckButton("Distributed MIL")
        hbox.pack_start(self.__distributedMILCheckButton, False, False, 0)
        hbox = gtk.HBox(False, 5)
        vbox.add(hbox)
        self.__wibuDongleCheckButton = gtk.CheckButton("CmStick (Dongle)")
        hbox.pack_start(self.__wibuDongleCheckButton, False, False, 0)
        hbox = gtk.HBox(False, 5)
        vbox.add(hbox)
        self.__dmaServiceCheckButton = gtk.CheckButton("Memory and PCI Service")
        hbox.pack_start(self.__dmaServiceCheckButton, False, False, 0)



        hbox = gtk.HBox(False, 20)
        self.__mainVBox.pack_end(hbox, False, False, 0)
        self.__buttonCancel = gtk.Button(stock=gtk.STOCK_CANCEL)
        hbox.pack_start(self.__buttonCancel, False, False, 0)
        self.__buttonGenerate = gtk.Button("Generate")
        hbox.pack_end(self.__buttonGenerate, False, False, 0)
        self.__buttonCancel.connect("clicked", self.__Cancel, None)
        self.__buttonGenerate.connect("clicked", self.__Generate, None)
        self.__mainWindow.show_all()

    def __FillData(self):
        """
        Fill data from config file
        """
        text = ""
        self.__DoWait(True,"Reading configuration, Please wait,...")

        # clear old data
        if self.installer:
            del (self.installer)
            self.installer = None

        if (self.configParser):
            del (self.configParser)
            self.configParser = None

        self.__allCheckButtons.clear() 
        self.__distroCheckButtons.clear()

        if self.options.verbose:    
            print "installer provided ", self.options.installer     
            print "internal mode ", self.options.internal

        if self.options.installer or self.options.internal:
            self.installer = Installer(self.options)
            if self.options.internal == False:
                if not self.installer.Extract():
                    print >>sys.stderr, "Error extracting the installer."
                    return False

            self.configFile = self.installer.GetConfig()
            if not os.path.exists(self.configFile):
                print >>sys.stderr, "Error config file not found."
                return False

            if not self.installer.ConfigValid():
                print >>sys.stderr, "Error invalid config file."
                return false;
            self.configParser = self.installer.GetConfigParser()
            
        if self.installer and self.configParser:
            self.__distroFrame.show()
            self.__otherMILFrame.show()
            self.__editSource.set_sensitive(not self.options.internal)
            self.__buttonSource.set_sensitive(not self.options.internal)
            if self.options.internal:
                self.__mainWindow.set_title("Matrox Imaging Library Redistribution [Internal]")
            else:
                self.__mainWindow.set_title("Matrox Imaging Library Redistribution")

            milversion = self.configParser.get('global', 'milversion')        
            text = "MilVersion : " + milversion
            
            # Distro
            displaynames = 'displaynames'
            sections =  self.configParser.sections()
            try:
                if not displaynames in sections:
                    self.allExceptDistro.remove(displaynames)
            except:
                pass
            oldsections = self.configParser.sections();
            for s in oldsections:
                if s in self.allExceptDistro or self.configParser.get(s,'distro_enabled').lower() != "yes":
                    sections.remove(s)
            
            for s in sections:
                # remove examples package anyway
                if self.configParser.has_option(s,'package_examples'):
                    toRemove = self.configParser.get(s,'package_examples')
                    self.filesToRemove.append(toRemove)

                # remove development package anyway
                if self.configParser.has_option(s,'package_dev'):
                    toRemove = self.configParser.get(s,'package_dev')
                    self.filesToRemove.append(toRemove)

                checkbox = gtk.CheckButton(self.distroLabels[s])
                self.__distroCheckButtons[s] = checkbox
                distro_enabled = self.configParser.get(s,'distro_enabled').lower()
                if distro_enabled == "yes":
                    checkbox.set_active(True)
                checkbox.connect("toggled", self.__DistroToggled, s)
                self.__distroVBox.pack_start(checkbox, False, False, 5)
                hbox = gtk.HBox(False, 10)
                self.__distroVBox.pack_start(hbox, False, False, 0)

                # Boards
                BoardsStr = self.configParser.get(s,'boards')
                if not BoardsStr:
                    continue

                Boards = BoardsStr.split(',')
                l = []
                for board in Boards:
                    checkboxb = gtk.CheckButton(board)
                    l.append(checkboxb)
                    if distro_enabled == "yes":
                        checkboxb.set_active(True)
                    checkboxb.connect("toggled", self.__BoardToggled, [board,s])
                    hbox.pack_start(checkboxb, False, False, 10)
                self.__allCheckButtons[s]  = l

                # CmStick Dongle 
                self.__wibuDongleCheckButton.set_active(True)
                self.__wibuDongleCheckButton.connect("toggled", self.__CmStickDongleToggled, s)

            self.__buttonGenerate.set_sensitive(True)
            if self.options.installer: 
                self.__editSource.set_text(self.options.installer)
            if self.options.targetdir: 
                self.__editDestination.set_text(self.options.targetdir)

            # Distributed MIL
            if self.configParser.has_option('global','components'):
                components = self.configParser.get('global','components').lower()
                if components.find("distributedmil") !=-1:
                    self.configParser.set('global','components','distributedmil')
                    self.__distributedMILCheckButton.set_active(True)
                    self.__distributedMILCheckButton.connect("toggled", self.__DistributedMILToggled)
                else:
                    self.configParser.set('global','components','')
                    self.__distributedMILCheckButton.set_sensitive(False)


            # Memory/PCI Service
            self.__dmaServiceCheckButton.set_active(True)
            self.__dmaServiceCheckButton.set_sensitive(False)
            self.__dmaServiceCheckButton.connect("toggled", self.__DMAServiceToggled)
        else:
            self.__labelMilVersion.set_text("")
            self.__distroFrame.hide()
            self.__otherMILFrame.hide()
            self.__buttonGenerate.set_sensitive(False)

        self.__distroVBox.show_all()    

        # End fill data
        self.__DoWait(False, text)

    def Run(self):
        """
        Main function
        """
        self.__InitDialog()
        gtk.main()
        return self.__returnValue
    
def main():
    parser = OptionParser(usage="%prog [options] arg", version="%prog 1.0")
    parser.add_option("-f", "--file", dest="installer", help="where FILENAME is the installer filename(.run)")
    parser.add_option("-d", "--dest", metavar="DIR", dest="destdir", default="/tmp/installer", help="where to extract the installer (default /tmp/installer)")
    parser.add_option("-t", "--target", metavar="DIR", dest="targetdir", default="/tmp", help="where to put new installer (default /tmp)")
    parser.add_option("-v", "--verbose", action="store_true", dest="verbose")
    parser.add_option("-c", "--console", action="store_true", dest="console", help="force a text only interface ", default=False)
    parser.add_option("-i", "--internal", action="store_true", dest="internal", default=False)
    parser.add_option("-r", "--redist", action="store_true", dest="internal", default=False)
    (options, args) = parser.parse_args()

    # do some check
    if not options.internal and not usegtk:
        if not options.installer or not os.path.exists(options.installer):   
            print >>sys.stderr, "Please provides a valid installer filename (use --file option)."
            sys.exit(1)

    if options.internal:
        configFile   = os.getcwd() + "/config.ini"
        makeselfFile = os.getcwd() + "/makeself"
        if not os.path.exists(configFile) or not os.path.exists(makeselfFile):
            print >>sys.stderr, "No config file or makeself in the current directory."
            sys.exit(1)

    # check if we can use Gtk        
    if usegtk != True:
        options.console = True
        
    if options.console == True:
        redist = Redist(options)
    else:
        redist = RedistGtk(options)
        
    #try:
    redist.Run()
    #except:
    #    print >>sys.stderr, "Error occured during MIL redistribution."
    #    sys.exit(1)

if __name__ == "__main__":
    main()

    

