#!/usr/bin/python
# -*- coding: UTF-8 -*-
###########################################################################
# grubconfig.py - description                                             #
# ------------------------------                                          #
# begin     : Sun Dec 10 2006                                             #
# copyright : (C) 2006-2007 by Martin Böhm                                #
# email     : martin.bohm@kubuntu.org                                     #
#                                                                         #
###########################################################################
#                                                                         #
#   This program is free software; you can redistribute it and/or modify  #
#   it under the terms of the GNU General Public License as published by  #
#   the Free Software Foundation; either version 2 of the License, or     #
#   (at your option) any later version.                                   #
#                                                                         #
###########################################################################

import sys
import os
import os.path
from PyTQt.tqt import *
from tdeui import *
from tdecore import *
from tdefile import *
import string, re
import shutil
import locale
import tempfile

programname = "Boot Loader Configuration"
version = "0.0.2"

standalone = __name__=='__main__'


if standalone:
  programbase = KDialogBase
else:
  programbase = TDECModule

parsable = ["default","menu","color","timeout","hiddenmenu","title","root","kernel","initrd"]
cat1 = ["default","menu","color","timeout","hiddenmenu","root","initrd"]
cat2 = ["savedefault","makeactive","chainloader"]
cat3 = ["kernel"]


class GreyListViewItem(TDEListViewItem):
  def paintCell(self, p, cg, column, width, align ):
    cgGrey = cg
    cgGrey.setColor(TQColorGroup.Text,TQColor("grey"))
    TDEListViewItem.paintCell(self, p, cgGrey, column, width, align)
    cg.restore()


class BoldListViewItem(TDEListViewItem):
  def paintCell(self, p, cg, column, width, align ):
    p.save()
    f = p.font()
    f.setBold(True)
    TDEListViewItem.paintCell(self, p, cg, column, width, align)
    p.restore()


class GrubConfigAppClass(programbase):
  def __init__(self,parent=None,name=None):
    if standalone:
      KDialogBase.__init__(self,KJanusWidget.Tabbed,i18n("Boot Loader Configuration"),
        KDialogBase.Help|KDialogBase.Ok|KDialogBase.Close, KDialogBase.Close)
      # no need to include About button yet
    self.menulstlocation = "/boot/grub/menu.lst"
    self.readfilename = self.menulstlocation
    self.globalvars = {}
    self.itemslist = []

    #--- Load menu.lst using the load_menulst() method
    self.load_menulst()
    print(self.globalvars)
    print(self.itemslist)

    # - GRUB Options Tab -
    if standalone:
      usershbox = self.addHBoxPage(i18n("Grub Options"))
      vbox = TQVBox(usershbox)
    else:
      vbox = TQVBox(tabcontrol)
      vbox.setMargin(KDialog.marginHint())

    # -- Operating Systems List & MakeDefault Button --
    horizontalbox = TQHBox(vbox)
    self.itemslistview = TDEListView(horizontalbox)
    self.itemslistview.addColumn("")
    self.itemslistview.setSorting(-1)
    self.itemslistview.header().hide()
    self.itemslistviewitems = []
    arrowsbox = TQVBox(horizontalbox)
    self.upbutton = KPushButton(i18n("Move Up"),arrowsbox)
    self.connect(self.upbutton,SIGNAL("clicked()"),self.slotUpButtonClicked)

    self.downbutton = KPushButton(i18n("Move Down"),arrowsbox)
    self.connect(self.downbutton,SIGNAL("clicked()"),self.slotDownButtonClicked)

    self.defaultbutton = KPushButton(i18n("Make Default"),vbox)
    self.connect(self.defaultbutton,SIGNAL("clicked()"),self.slotSetDefaultButtonClicked)


    # -- Boot Options Group Box --
    bootoptionsbasebox = TQVGroupBox(vbox,"Boot Options")
    bootoptionsbasebox.setTitle(i18n("Boot Options"));

    bootoptionsbasevbox = TQWidget(bootoptionsbasebox)

    infogrid = TQGridLayout(bootoptionsbasevbox,3,2)
    infogrid.setSpacing(KDialog.spacingHint())

    # --- Timeout ---
    label = TQLabel(i18n("Timeout:"),bootoptionsbasevbox)
    infogrid.addWidget(label,0,0)    

    timeoutbox = TQHBox(bootoptionsbasevbox)
    timeoutbox.setSpacing(KDialog.spacingHint())

    self.timeout = KIntSpinBox(timeoutbox,"Timeout")
    if "timeout" in self.globalvars:
      self.timeout.setValue(int(self.globalvars['timeout'][0]))
    label = TQLabel(i18n("seconds"),timeoutbox)
    infogrid.addWidget(timeoutbox,0,1)    
  

    infogrid.addWidget(self.timeout,0,1)

    # --- Hide Menu on Boot ---
    self.hidemenuonboot = TQCheckBox(i18n("Hide Menu on Boot"),bootoptionsbasevbox)
    if 'hiddenmenu' in self.globalvars:
      self.hidemenuonboot.setChecked(int(self.globalvars['hiddenmenu'][0]))
    infogrid.addWidget(self.hidemenuonboot,1,1)

    # --- Make Last OS Default ---
    self.lastdefault = TQCheckBox(i18n("Make Last Operating System Default"),bootoptionsbasevbox)
    infogrid.addWidget(self.lastdefault,2,1)


    # -- Security Group Box --
    securitybox = TQVGroupBox(vbox,"Security")
    securitybox.setTitle(i18n("Security"));
    securityvbox = TQWidget(securitybox)

    infogrid = TQGridLayout(securityvbox,2,2)
    infogrid.setSpacing(KDialog.spacingHint())

    # --- Password ---    
    label = TQLabel(i18n("Password:"),securityvbox)
    infogrid.addWidget(label,0,0)    
    self.userpassword = KPasswordEdit(securityvbox)
    infogrid.addWidget(self.userpassword,0,1)

    # --- Repeat Password ---
    label = TQLabel(i18n("Repeat Password:"),securityvbox)
    infogrid.addWidget(label,1,0)    
    self.userrepeatpassword = KPasswordEdit(securityvbox)
    infogrid.addWidget(self.userrepeatpassword,1,1)    

    # -- Splash Screen Group Box --
    splashbox = TQVGroupBox(vbox,"Splash screen")
    splashbox.setTitle(i18n("Splash screen"));

    # --- Background Color ---
    labelandeditbox = TQHBox(splashbox)
    label = TQLabel(i18n("Background Color:"),labelandeditbox)
    self.backgroundcolor = TQComboBox(labelandeditbox)

    # --- Highlight Color ---
    labelandeditbox = TQHBox(splashbox)
    label = TQLabel(i18n("Highlight Color:"),labelandeditbox)
    self.highlightcolor = TQComboBox(labelandeditbox)

    # - Operating Systems Tab -

    if standalone:
      groupsvbox = self.addVBoxPage(i18n("Operating Systems"))
      vb = TQVBox(groupsvbox)
    else:
      groupsvbox = TQVBox(tabcontrol)
      roupsvbox.setMargin(KDialog.marginHint())
      vb = TQVBox(groupsvbox)

    # -- Operating Systems List --
    
    horizontalbox = TQHBox(vb)
    self.oslistview = TDEListView(horizontalbox)
    self.oslistview.addColumn("")
    self.oslistview.addColumn("")
    self.oslistview.setSorting(-1)
    self.oslistview.header().hide()
    self.oslistviewitems = []
    self.connect(self.oslistview,SIGNAL("selectionChanged()"),self.oslistviewitemSelected)
    
    # -- Operating Systems Details Box --
    osdetailsbox = TQVGroupBox(vb,"Operating System Details")
    # label = TQLabel(i18n("Security"),securitybox)
    detailsvbox = TQWidget(osdetailsbox)

    infogrid = TQGridLayout(detailsvbox,7,2)
    infogrid.setSpacing(KDialog.spacingHint())

    osdetailsbox.setTitle(i18n("Operating System Details"));

    # --- List in GRUB Menu --- 
    self.listingrub = TQCheckBox(i18n("List in GRUB Menu"),detailsvbox)
    infogrid.addWidget(self.listingrub,0,1)

    # --- Display Name ---
    label = TQLabel(i18n("Display Name:"),detailsvbox)
    infogrid.addWidget(label,1,0)
    self.displaynamelabel = TQLineEdit("",detailsvbox)
    infogrid.addWidget(self.displaynamelabel,1,1)
    self.connect(self.displaynamelabel,SIGNAL("textChanged(const TQString &)"),self.slotDisplayNameLabelChanged)

    # --- Operating System ---
    label = TQLabel(i18n("Operating System:"),detailsvbox)
    infogrid.addWidget(label,2,0)
    self.operatingsystem = TQComboBox(detailsvbox)
    infogrid.addWidget(self.operatingsystem,2,1)

    # --- Kernel ---
    label = TQLabel(i18n("Kernel:"),detailsvbox)
    infogrid.addWidget(label,3,0)
    self.kernel = KURLRequester(detailsvbox)
    infogrid.addWidget(self.kernel,3,1)

    # --- Failsafe Kernel ---
    # not sure if that is possible - requested by seele
    label = TQLabel(i18n("Failsafe Kernel:"),detailsvbox)
    infogrid.addWidget(label,4,0)
    self.failsafekernel = TQComboBox(detailsvbox)
    infogrid.addWidget(self.failsafekernel,4,1)

    # --- Initial RAM Disk ---
    label = TQLabel(i18n("Initial RAM Disk:"),detailsvbox)
    infogrid.addWidget(label,5,0)
    self.initrd = KURLRequester(detailsvbox)
    infogrid.addWidget(self.initrd,5,1)

    # --- Root Filesystem ---
    label = TQLabel(i18n("Root Filesystem:"),detailsvbox)
    infogrid.addWidget(label,6,0)
    self.rootfilesystem = TQComboBox(detailsvbox)
    infogrid.addWidget(self.rootfilesystem,6,1)


    # -- Boot Options Box --
    bootoptionsbox = TQVGroupBox(vb,"Boot Options")
    # label = TQLabel(i18n("Security"),securitybox)
    bootoptionsbox.setTitle(i18n("Boot Options"));



    self.acpibox    = TQCheckBox(i18n("Power Management (ACPI) "),bootoptionsbox)
    self.debugbox   = TQCheckBox(i18n("Debugging Messages "),bootoptionsbox)
    self.selinuxbox = TQCheckBox(i18n("SELinux Support "),bootoptionsbox)
    self.splashbox  = TQCheckBox(i18n("Splash Screen"),bootoptionsbox)

    labelandeditbox = TQHBox(bootoptionsbox)
    label = TQLabel(i18n("Custom Options:"),labelandeditbox)
    self.customoptions = KLineEdit("",labelandeditbox)

    # -- (static) UI finished --
    self.reloadListViews("oslist")
    self.reloadListViews("itemslist")
    try:
      self.oslistview.setSelected(self.oslistviewitems[int(self.globalvars['default'][0])],True)
    except ValueError:
      self.oslistview.setSelected(self.oslistviewitems[0],True)
    
    ops_list = self.load_osprobe()
    print(ops_list) # mhb debug
    
  #######################################################################
  # reload listviews, because they have changed
  def reloadListViews(self,name):
    print("reloaded")
    # you should repaint the one that is not changed on screen
    if name == "oslist":
      self.oslistview.clear()
      
      for item in self.itemslist:
          try:
            if self.itemslist.index(item) == int(self.globalvars['default'][0]):
              self.oslistviewitems.append(BoldListViewItem(self.oslistview,self.oslistview.lastItem(),item['title'][0]))
            else:
              self.oslistviewitems.append(TDEListViewItem(self.oslistview,self.oslistview.lastItem(),item['title'][0]))
          except ValueError:
            self.oslistviewitems.append(TDEListViewItem(self.oslistview,self.oslistview.lastItem(),item['title'][0]))
      # if it has a root option (other than 1 which means only root by itself), it is an OS
    else:
      self.itemslistview.clear()
      #repaint main list
      for item in self.itemslist:
        try:
          if self.itemslist.index(item) == int(self.globalvars['default'][0]):
            print("bam!")
            self.itemslistviewitems.append(BoldListViewItem(self.itemslistview,self.itemslistview.lastItem(),item['title'][0]))
          else:
            self.itemslistviewitems.append(TDEListViewItem(self.itemslistview,self.itemslistview.lastItem(),item['title'][0]))
        except ValueError:
          self.itemslistviewitems.append(TDEListViewItem(self.itemslistview,self.itemslistview.lastItem(),item['title'][0]))
  
  #######################################################################
  def slotUser1(self):
    self.aboutus.show()


  #######################################################################
  # def slotClose(self):
  #   self.close()

  #######################################################################
  def slotOk(self):
    self.save_menulst()
    # mhb TODO: catching exceptions here would be useful
    self.close()

  #######################################################################
  def slotCheckOsClicked(self):
    self.OsProbedList = self.load_osprobe()

  #######################################################################
  def oslistviewitemSelected(self):
    # save current item changes & select another one
    i = self.oslistviewitems.index(self.oslistview.selectedItem())
    self.updatingGUI = True
    self.displaynamelabel.setText(self.itemslist[i]["title"][0])
    # visible in GRUB reload
    # kernel reload
    try:
      self.kernel.setURL(self.itemslist[i]["kernel"][0])
    except KeyError:
      self.initrd.setURL("unavailable") # mhb debug
    # initrd reload
    try:
      self.initrd.setURL(self.itemslist[i]["initrd"][0])
    except KeyError:
      self.initrd.setURL("unavailable") # mhb debug
    
    # custom options reload
    customoptions = ""
    for word in self.itemslist[i]["kernel"][1:-1]:
      customoptions += word + " "
    self.customoptions.setText(customoptions[:-1])
    
    self.updatingGUI = False
    print("oslistview item selected") #mhb debug
    pass
  #######################################################################
  def slotDisplayNameLabelChanged(self, string):
    if(self.updatingGUI == False):
      print("display name changed") #mhb debug
      i = self.oslistviewitems.index(self.oslistview.selectedItem())
      self.itemslist[i]["title"][0] = string
      self.oslistview.selectedItem().setText(0,string)
      self.reloadListViews("itemslist")
      pass
  #######################################################################
  def slotUpButtonClicked(self):
    print("UpButton clicked") #mhb debug
    i = self.itemslistviewitems.index(self.itemslistview.selectedItem())
    self.itemslistview.selectedItem().itemAbove().moveItem(self.itemslistview.selectedItem())
    # itemslist should have the same i for the same option
    if(i != 0):
      container = self.itemslist[i]
      self.itemslist[i] = self.itemslist[i-1]
      self.itemslist[i-1] = container
    self.reloadListViews("oslist")
    return "not working yet"

  #######################################################################
  def slotDownButtonClicked(self):
    print("DownButton clicked") #mhb debug
    i = self.itemslistviewitems.index(self.itemslistview.selectedItem())
    self.itemslistview.selectedItem().moveItem(self.itemslistview.selectedItem().itemBelow())
    if(i != len(self.itemslist)-1):
      container = self.itemslist[i]
    self.itemslist[i] = self.itemslist[i+1]
    self.itemslist[i+1] = container
    self.reloadListViews("oslist")
    return "not working yet"

    #######################################################################
  def slotSetDefaultButtonClicked(self):
    print("SetDefaultButton cliicked") #mhb debug
    try:
      defaultn = int(self.globalvars["default"][0])
    except ValueError:
      pass
    else:
      container = self.itemslistviewitems[defaultn]
      self.itemslistviewitems[defaultn] = TDEListViewItem(self.itemslistview,container,self.itemslist[defaultn]['title'][0])
    self.itemslistview.takeItem(container)

      
    indexn = self.itemslistviewitems.index(self.itemslistview.selectedItem())
    self.globalvars["default"] = str(indexn)
    self.itemslistviewitems[indexn] = BoldListViewItem(self.itemslistview,self.itemslistview.selectedItem(),self.itemslist[indexn]['title'][0])
    self.itemslistview.takeItem(self.itemslistview.selectedItem())
    
    self.reloadListViews("oslist")

    return "not working yet"



  #######################################################################
  # loop
  def exec_loop(self):
    global programbase
    # self.__loadOptions()
    self.updatingGUI = True
    #self.__updateUserList()
    #self.__updateGroupList()
    self.updatingGUI = False
    programbase.exec_loop(self)
    print("done")


  #######################################################################
  # loads menu.lst
  # NOT YET parsing:
  #   fallback
  # currently parsing:                  (type of the location number)
  #   default                           <int>
  #   timeout                           <int>
  #   hiddenmenu                        <int>
  #   color                             <int>
  #   password (consider an md5 sum?)   <int>
  #   AUTOMAGIC KERNELS LIST            <interval - two ints>
  #   GRUBCONFIG DISABLED ITEMS         <interval - two ints>
  # IMPORTANT note:
  #   any value that is not parsed MUST not be ommited at the end!
  #   any value that is commented (parsed or not) MUST not be omitted at the end!
  # not so important note:
  #   if a value we parse is not defined:
  #     apply defaults (how do find them out?)
  #     but specify it in the menu.lst when saving
  # mhb TODO: somehow handle automagic kernel list (target: feisty)
  # mhb TODO: adapt to more distributions, find menu.lst on different locations
  def load_menulst(self):
    self.modifiedlines = []
    menufd = open(self.menulstlocation,"r")
    linenum = 0
    lock = 0
    itemlock = 0
    currentitem = 0
    for line in menufd:
      # Checks if the first non-white char in a line is a #
      if re.search(r'^(/s)*#',line) or re.search(r'^(/s)*$',line):
        print("a commented line") # mhb debug
        if itemlock == 1:
          itemlock = 0
          currentitem += 1
          
        # if it is a start of an area we parse, use a lock
        if re.search(r'sumthin',line) and (lock == 0):
          lock = 1
        elif re.search(r'sumthin_other',line) and (lock == 0):
          lock = 2
        # else if it is an end of an area we parse, close the lock
        elif re.search(r'sumthin_other_end',line) and (lock == 2):
          lock = 0
        elif re.search(r'sumthin_end',line) and (lock == 1):
          lock = 0

        # errors
        # mhb TODO: exception catching
        elif re.search(r'sumthin',line) and (lock == 0):
          raise IdentationError
        elif re.search(r'sumthin_other',line) and (lock == 1):
          raise EndOfNotOpenedError

        # if it is in the lock, do the mumbo-jumbo
        # find out what kind of lock it is
        # AUTOCONFIG
        if lock == 1:
         
          
          # automagic kernels list?
          if re.search(r'sumthin',line):
            pass
          # or the other one (grubconfig disabled kernel's list )?
          else:
            self.modifiedlines.append(linenum)
        # else save it as a commented line (does not save the locks)
        # GRUBCONFiG commented item
        elif lock == 2:
          # remove leading spaces and one #
          # the parse as a normal menu item
          pass
        # it's a commented, no need to do anything
        else:
          pass
      # okay, it's not commented
      else:
        print("a not commented line") # mhb debug
        self.modifiedlines.append(linenum)
        # we presume the first character is already a name
        var_name = line.split()[0]
        #print "variable name is " + var_name # mhb debug
        # var_value's last item is always the line that has to be changed
        var_value = []
        if var_name in parsable:
          # cat 0 - a title - triggers itemlock, has a name and a value, which should be stored as text
          if var_name == "title":
            print(line.split(None,1))
            var_value.append(line.split(None,1)[1][:-1])
            itemlock = 1
            self.itemslist.append({})
          # cat 1 - has a name and 1 value
          elif var_name in cat1:
            try:
              var_value.append(line.split()[1])
            except IndexError:
              var_value.append(1)
          # cat 2 - has a name, but no value ( implicit 1 )
          elif var_name in cat2:
            var_value.append(1)
          # cat 3 - has a name, has multiple values, should be saved as list
          elif var_name in cat3:
              var_value = line.split()[1:]
          # now, append the number
          var_value.append(linenum)
          
          if itemlock == 1:
            self.itemslist[currentitem][var_name] = var_value
          else:
            self.globalvars[var_name] = var_value
        
        
        
        
        
        #if var_name in parsable:
          #print "variable name " + var_name + " is parsable " # mhb debug
          #if var_name == "title":
            #itemlock = 1
            #self.itemslist.append({})
          #if(len(line.split()) > 1):
            #var_value = line.split()[1]
            #if itemlock == 1:
              
            #else:
              
            #print "variable value is " + var_value # mhb debug
            
          #else:
            #if itemlock == 1:
              #self.itemslist[currentitem][var_name] = var_value
            #else:
              #self.globalvars[var_name] = 1
        #else:
          #print "variable name " + var_name + " is currently not parsable" # mhb debug

          #print "it has no value" # mhb debug
      # print "parsed another line" # mhb debug
      linenum += 1;
    print("load_menulst() called") # mhb debug
    return "not working yet"

  #######################################################################
  # writes menu.lst
  def save_menulst(self):
    delimeter = "      "
    # phase 1: preparing the values
    lines = []
    linecontent = []
    # this consists of:
    #   1. concatenating the list of lines that were modified
    #   2. writing the lines in another list (or something more efficient
    output = {}
    # the globals first
    for unit, value in list(self.globalvars.items()):
      lines.append(value[-1])
      temp_str=""
      temp_str+=(str(unit)+" ")
      for index in range(len(value)-1):
        temp_str+=(str(value[index])+" ")
      linecontent.append(temp_str)

    # itemslist next (abattoir)
    for item in self.itemslist:
      for unit, value in reversed(list(item.items())):
        lines.append(value[-1])
        temp_str=""
        temp_str+=(str(unit)+" ")
        for index in range(len(value)-1):
          temp_str+=(str(value[index])+" ")
        linecontent.append(temp_str)

    # phase 2: writing the file
    # by now we have a list of numbers (let's call it lines[])
    # and a list of mofified lines  (let's call it linecontent[] )
    # lines[i] corresponds with linecontent[]
    trfile = open(self.readfilename, "r" )
    twfilename = tempfile.mkstemp("menulst")[1]
    twfile = open(twfilename,"w")
    # the current solution is:
    # read the menu.lst again (or rather its copy, to prevent the file being changed)
    # line by line write it in the output file (to be exact, to a file in /tmp)
    linenum = 0
    print(linecontent)
    print(lines)
    # foreach file as line:
    for originalline in trfile:
      # if its number isn't in the location list, simply write it
      if linenum in lines:
        twfile.writelines(linecontent[linenum])
      else:
        twfile.writelines(originalline)

      linenum += 1;

    # if there are any more lines to be written (newly detected options)
    # write them at the end (now)
      
    # when that process works out fine do a quick rewrite to /boot/grub/menu.lst
    # mhb TODO: declare self.menulstlocation
    twfile.close()
    shutil.move(twfilename,self.menulstlocation)
    # mhb TODO: Exception handling
    os.remove(self.readfilename)

    print("save_menulst() called") # mhb debug
    return "not working yet"


  #######################################################################
  # loads output from os-probe
  def load_osprobe(self):
    detected = os.popen('os-prober').readlines()
    ops_list = []
    for ops in detected:
      ops = ops.replace("\n","")
      temp_list = ops.split(':')
      partition = temp_list[0]
      temp_list[0] = temp_list[0].replace("/dev/","")
      re_obj = re.search(r'([sh]d)([a-z])([0-9])*$',temp_list[0])
      disk = ord(re_obj.group(2))%97
      part = int(re_obj.group(3))-1
      if re_obj == None:
        re_obj = re.search(r'(fd[0-9]*)$',temp_list[0])
        if re_obj:
          disk = temp_list[0]
          part = ""
        else : re_obj = re.search(r'(part[0-9]*$', temp_list[0])
        if re_obj:
          disk = '/disc'
          part = temp_list[0]
      temp_list[0] = '('+re_obj.group(1)+str(disk)+','+str(part)+')'
      if temp_list[3].lower() == "linux":
        mounted = os.popen('mount | grep '+partition).readlines()
        if mounted:
          linux_os = os.popen('linux-boot-prober --mounted '+partition).readlines()
        else:
          linux_os = os.popen('linux-boot-prober '+partition).readlines()
        linux_list = []
        for lops in linux_os:
          lops = lops.replace("\n","")
          temp_linux_list = lops.split(':')
          linux_list.append(temp_linux_list)
        temp_list.append(linux_list)
      ops_list.append(temp_list)
      temp_list = []
    return ops_list


############################################################################
# Factory function for KControl
def create_grubconfig(parent,name):
    return GrubConfigAppClass(parent, name)


##########################################################################
def MakeAboutData():
    aboutdata = TDEAboutData("guidance", programname, version,
        str(i18n("Boot Loader Configuration Tool")).encode(locale.getpreferredencoding()),
        TDEAboutData.License_GPL, "Copyright (C) 2006-2007 Martin Böhm")
    aboutdata.addAuthor("Martin Böhm", "Developer", "martin.bohm@kubuntu.org", "http://mhb.ath.cx/")
    aboutdata.addAuthor("Simon Edwards", "Developer", "simon@simonzone.com", "http://www.simonzone.com/software/")
    aboutdata.addAuthor("Sebastian Kügler", "Developer", "sebas@kde.org", "http://vizZzion.org")
    return aboutdata

if standalone:
    aboutdata = MakeAboutData()

    TDECmdLineArgs.init(sys.argv,aboutdata)

    kapp = TDEApplication()
    grubconfigapp = GrubConfigAppClass()
    grubconfigapp.exec_loop()
